aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c9
-rw-r--r--lbaselib.c6
-rw-r--r--lfunc.c3
-rw-r--r--lgc.c184
-rw-r--r--lgc.h31
-rw-r--r--lstate.c18
-rw-r--r--lstate.h8
-rw-r--r--ltests.c67
-rw-r--r--lua.h3
-rw-r--r--lundump.c3
10 files changed, 69 insertions, 263 deletions
diff --git a/lapi.c b/lapi.c
index 05640ef9..0fcb6eaa 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.192 2013/12/30 20:47:58 roberto Exp roberto $ 2** $Id: lapi.c,v 2.193 2014/01/27 13:34:32 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -589,7 +589,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
589 while (n--) { 589 while (n--) {
590 setobj2n(L, &cl->c.upvalue[n], L->top + n); 590 setobj2n(L, &cl->c.upvalue[n], L->top + n);
591 /* does not need barrier because closure is white */ 591 /* does not need barrier because closure is white */
592 valnolocal(L->top + n); /* but needs 'local barrier' */
593 } 592 }
594 setclCvalue(L, L->top, cl); 593 setclCvalue(L, L->top, cl);
595 } 594 }
@@ -864,7 +863,6 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
864 } 863 }
865 default: { 864 default: {
866 G(L)->mt[ttnov(obj)] = mt; 865 G(L)->mt[ttnov(obj)] = mt;
867 if (mt) nolocal(obj2gco(mt));
868 break; 866 break;
869 } 867 }
870 } 868 }
@@ -1086,11 +1084,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
1086 g->gcpause = data; 1084 g->gcpause = data;
1087 break; 1085 break;
1088 } 1086 }
1089 case LUA_GCSETLOCALPAUSE: {
1090 res = g->gclocalpause;
1091 g->gclocalpause = data;
1092 break;
1093 }
1094 case LUA_GCSETSTEPMUL: { 1087 case LUA_GCSETSTEPMUL: {
1095 res = g->gcstepmul; 1088 res = g->gcstepmul;
1096 g->gcstepmul = data; 1089 g->gcstepmul = data;
diff --git a/lbaselib.c b/lbaselib.c
index 9e3c5c87..0b51b743 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.281 2013/08/05 16:58:28 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.282 2013/09/13 16:21:52 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -175,10 +175,10 @@ static int luaB_rawset (lua_State *L) {
175static int luaB_collectgarbage (lua_State *L) { 175static int luaB_collectgarbage (lua_State *L) {
176 static const char *const opts[] = {"stop", "restart", "collect", 176 static const char *const opts[] = {"stop", "restart", "collect",
177 "count", "step", "setpause", "setstepmul", 177 "count", "step", "setpause", "setstepmul",
178 "setlocalpause", "isrunning", NULL}; 178 "isrunning", NULL};
179 static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, 179 static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
180 LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, 180 LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
181 LUA_GCSETLOCALPAUSE, LUA_GCISRUNNING}; 181 LUA_GCISRUNNING};
182 int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; 182 int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
183 int ex = luaL_optint(L, 2, 0); 183 int ex = luaL_optint(L, 2, 0);
184 int res = lua_gc(L, o, ex); 184 int res = lua_gc(L, o, ex);
diff --git a/lfunc.c b/lfunc.c
index 3727b6cf..3381e437 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lfunc.c,v 2.37 2013/08/27 20:04:00 roberto Exp roberto $ 2** $Id: lfunc.c,v 2.38 2013/09/11 12:26:14 roberto Exp roberto $
3** Auxiliary functions to manipulate prototypes and closures 3** Auxiliary functions to manipulate prototypes and closures
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -86,7 +86,6 @@ void luaF_close (lua_State *L, StkId level) {
86 86
87Proto *luaF_newproto (lua_State *L) { 87Proto *luaF_newproto (lua_State *L) {
88 Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p; 88 Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto))->p;
89 nolocal(obj2gco(f)); /* prototypes are never local */
90 f->k = NULL; 89 f->k = NULL;
91 f->sizek = 0; 90 f->sizek = 0;
92 f->p = NULL; 91 f->p = NULL;
diff --git a/lgc.c b/lgc.c
index 4fb65ef3..61162d42 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.169 2014/02/11 12:18:12 roberto Exp roberto $ 2** $Id: lgc.c,v 2.170 2014/02/11 12:28:47 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -72,18 +72,11 @@
72 lua_longassert(!iscollectable(obj) || righttt(obj)) 72 lua_longassert(!iscollectable(obj) || righttt(obj))
73 73
74 74
75#define marklocalvalue(g,o) { checkconsistency(o); \ 75#define markvalue(g,o) { checkconsistency(o); \
76 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } 76 if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
77 77
78#define markvalue(g,o) { \
79 lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \
80 marklocalvalue(g,o); }
81
82#define marklocalobject(g,t) \
83 { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
84
85#define markobject(g,t) \ 78#define markobject(g,t) \
86 { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } 79 { if ((t) && iswhite(obj2gco(t))) reallymarkobject(g, obj2gco(t)); }
87 80
88static void reallymarkobject (global_State *g, GCObject *o); 81static void reallymarkobject (global_State *g, GCObject *o);
89 82
@@ -178,7 +171,6 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
178 global_State *g = G(L); 171 global_State *g = G(L);
179 GCObject *o = gcvalue(uv->v); 172 GCObject *o = gcvalue(uv->v);
180 lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ 173 lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */
181 nolocal(o);
182 if (keepinvariant(g)) 174 if (keepinvariant(g))
183 markobject(g, o); 175 markobject(g, o);
184} 176}
@@ -186,9 +178,9 @@ LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) {
186 178
187void luaC_fix (lua_State *L, GCObject *o) { 179void luaC_fix (lua_State *L, GCObject *o) {
188 global_State *g = G(L); 180 global_State *g = G(L);
189 lua_assert(g->localgc == o); 181 lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
190 white2gray(o); 182 white2gray(o); /* they will be gray forever */
191 g->localgc = o->gch.next; /* remove object from 'localgc' list */ 183 g->allgc = o->gch.next; /* remove object from 'allgc' list */
192 o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */ 184 o->gch.next = g->fixedgc; /* link it to 'fixedgc' list */
193 g->fixedgc = o; 185 g->fixedgc = o;
194} 186}
@@ -196,15 +188,15 @@ void luaC_fix (lua_State *L, GCObject *o) {
196 188
197/* 189/*
198** create a new collectable object (with given type and size) and link 190** create a new collectable object (with given type and size) and link
199** it to 'localgc' list. 191** it to 'allgc' list.
200*/ 192*/
201GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 193GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
202 global_State *g = G(L); 194 global_State *g = G(L);
203 GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); 195 GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz));
204 gch(o)->marked = luaC_white(g); 196 gch(o)->marked = luaC_white(g);
205 gch(o)->tt = tt; 197 gch(o)->tt = tt;
206 gch(o)->next = g->localgc; 198 gch(o)->next = g->allgc;
207 g->localgc = o; 199 g->allgc = o;
208 return o; 200 return o;
209} 201}
210 202
@@ -289,7 +281,7 @@ static void markmt (global_State *g) {
289static void markbeingfnz (global_State *g) { 281static void markbeingfnz (global_State *g) {
290 GCObject *o; 282 GCObject *o;
291 for (o = g->tobefnz; o != NULL; o = gch(o)->next) 283 for (o = g->tobefnz; o != NULL; o = gch(o)->next)
292 marklocalobject(g, o); 284 markobject(g, o);
293} 285}
294 286
295 287
@@ -306,7 +298,7 @@ static void remarkupvals (global_State *g) {
306 UpVal *uv = gco2th(thread)->openupval; 298 UpVal *uv = gco2th(thread)->openupval;
307 for (; uv != NULL; uv = uv->u.op.next) { 299 for (; uv != NULL; uv = uv->u.op.next) {
308 if (uv->u.op.touched) { 300 if (uv->u.op.touched) {
309 marklocalvalue(g, uv->v); /* remark upvalue's value */ 301 markvalue(g, uv->v); /* remark upvalue's value */
310 uv->u.op.touched = 0; 302 uv->u.op.touched = 0;
311 } 303 }
312 } 304 }
@@ -463,7 +455,7 @@ static int traverseproto (global_State *g, Proto *f) {
463static lu_mem traverseCclosure (global_State *g, CClosure *cl) { 455static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
464 int i; 456 int i;
465 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 457 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
466 marklocalvalue(g, &cl->upvalue[i]); 458 markvalue(g, &cl->upvalue[i]);
467 return sizeCclosure(cl->nupvalues); 459 return sizeCclosure(cl->nupvalues);
468} 460}
469 461
@@ -489,7 +481,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) {
489 if (o == NULL) 481 if (o == NULL)
490 return 1; /* stack not completely built yet */ 482 return 1; /* stack not completely built yet */
491 for (; o < th->top; o++) /* mark live elements in the stack */ 483 for (; o < th->top; o++) /* mark live elements in the stack */
492 marklocalvalue(g, o); 484 markvalue(g, o);
493 if (g->gcstate == GCSatomic) { /* final traversal? */ 485 if (g->gcstate == GCSatomic) { /* final traversal? */
494 StkId lim = th->stack + th->stacksize; /* real end of stack */ 486 StkId lim = th->stack + th->stacksize; /* real end of stack */
495 for (; o < lim; o++) /* clear not-marked stack slice */ 487 for (; o < lim; o++) /* clear not-marked stack slice */
@@ -769,16 +761,8 @@ static GCObject *udata2finalize (global_State *g) {
769 GCObject *o = g->tobefnz; /* get first element */ 761 GCObject *o = g->tobefnz; /* get first element */
770 lua_assert(tofinalize(o)); 762 lua_assert(tofinalize(o));
771 g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ 763 g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */
772 if (islocal(o)) { 764 gch(o)->next = g->allgc; /* return it to 'allgc' list */
773 gch(o)->next = g->localgc; /* return it to 'localgc' list */ 765 g->allgc = o;
774 g->localgc = o;
775 resetbit(gch(o)->marked, LOCALMARK);
776 }
777 else { /* return it to 'allgc' list */
778 gch(o)->next = g->allgc;
779 g->allgc = o;
780 l_setbit(gch(o)->marked, LOCALMARK);
781 }
782 resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */ 766 resetbit(gch(o)->marked, FINALIZEDBIT); /* object is "normal" again */
783 if (issweepphase(g)) 767 if (issweepphase(g))
784 makewhite(g, o); /* "sweep" object */ 768 makewhite(g, o); /* "sweep" object */
@@ -882,8 +866,7 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
882 g->sweepgc = sweeptolive(L, g->sweepgc, NULL); 866 g->sweepgc = sweeptolive(L, g->sweepgc, NULL);
883 } 867 }
884 /* search for pointer pointing to 'o' */ 868 /* search for pointer pointing to 'o' */
885 p = (testbit(o->gch.marked, LOCALMARK)) ? &g->allgc : &g->localgc; 869 for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
886 for (; *p != o; p = &gch(*p)->next) { /* empty */ }
887 *p = o->gch.next; /* remove 'o' from its list */ 870 *p = o->gch.next; /* remove 'o' from its list */
888 o->gch.next = g->finobj; /* link it in "fin" list */ 871 o->gch.next = g->finobj; /* link it in "fin" list */
889 g->finobj = o; 872 g->finobj = o;
@@ -896,105 +879,6 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
896/* }====================================================== */ 879/* }====================================================== */
897 880
898 881
899/*
900** {======================================================
901** Local Collection
902** =======================================================
903*/
904
905
906/*
907** Traverse a thread, local marking all its collectable objects
908*/
909static void localmarkthread (lua_State *l) {
910 StkId o = l->stack;
911 StkId lim = l->stack + l->stacksize; /* real end of stack */
912 if (o == NULL)
913 return; /* stack not completely built yet */
914 for (; o < l->top; o++) { /* mark live elements in the stack */
915 if (iscollectable(o))
916 l_setbit(gcvalue(o)->gch.marked, LOCALMARK);
917 }
918 for (; o < lim; o++) /* clear not-marked stack slice */
919 setnilvalue(o);
920}
921
922
923/*
924** Mark all that is locally accessible (accessible directly from
925** a thread)
926*/
927static void localmark (global_State *g) {
928 GCObject *thread = obj2gco(g->mainthread);
929 for (; thread != NULL; thread = gch(thread)->next) /* traverse all threads */
930 localmarkthread(gco2th(thread));
931}
932
933
934static void localsweep (lua_State *L, global_State *g) {
935 GCObject **p = &g->localgc;
936 while (*p != NULL) {
937 GCObject *curr = *p;
938 if (!islocal(curr)) { /* is 'curr' no more local? */
939 *p = curr->gch.next; /* remove 'curr' from list */
940 curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */
941 g->allgc = curr;
942 /* mark it as out of local list */
943 l_setbit(curr->gch.marked, LOCALMARK);
944 }
945 else { /* still local */
946 if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */
947 resetbit(curr->gch.marked, LOCALMARK);
948 p = &curr->gch.next; /* go to next element */
949 }
950 else { /* object is dead */
951 if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */
952 if (gco2lcl(curr)->p->cache == gco2cl(curr))
953 gco2lcl(curr)->p->cache = NULL; /* clear cache */
954 }
955 *p = curr->gch.next; /* remove 'curr' from list */
956 freeobj(L, curr); /* erase 'curr' */
957 }
958 }
959 }
960}
961
962
963static void separatelocal (global_State *g) {
964 GCObject **p = &g->finobj;
965 GCObject **lastnext = findlast(&g->tobefnz);
966 while (*p != NULL) {
967 GCObject *curr = *p;
968 if (!islocal(curr)) /* is 'curr' no more local? */
969 p = &curr->gch.next; /* go to next element */
970 else { /* still local */
971 if (testbit(curr->gch.marked, LOCALMARK)) { /* locally alive? */
972 resetbit(curr->gch.marked, LOCALMARK);
973 p = &curr->gch.next; /* go to next element */
974 }
975 else { /* object is "dead" */
976 *p = curr->gch.next; /* remove 'curr' from list */
977 curr->gch.next = *lastnext; /* link at the end of 'tobefnz' list */
978 *lastnext = curr;
979 lastnext = &curr->gch.next;
980 }
981 }
982 }
983}
984
985
986static void luaC_localcollection (lua_State *L) {
987 global_State *g = G(L);
988 lua_assert(g->gcstate == GCSpause);
989 localmark(g);
990 localsweep(L, g);
991 separatelocal(g);
992 callallpendingfinalizers(L, 1);
993}
994
995/* }====================================================== */
996
997
998 882
999/* 883/*
1000** {====================================================== 884** {======================================================
@@ -1008,13 +892,13 @@ static void luaC_localcollection (lua_State *L) {
1008** cycle will start when memory use hits threshold 892** cycle will start when memory use hits threshold
1009*/ 893*/
1010static void setpause (global_State *g, l_mem estimate) { 894static void setpause (global_State *g, l_mem estimate) {
1011 l_mem threshold; 895 l_mem threshold, debt;
1012 estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ 896 estimate = estimate / PAUSEADJ; /* adjust 'estimate' */
1013 threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ 897 threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */
1014 ? estimate * g->gcpause /* no overflow */ 898 ? estimate * g->gcpause /* no overflow */
1015 : MAX_LMEM; /* overflow; truncate to maximum */ 899 : MAX_LMEM; /* overflow; truncate to maximum */
1016 g->GCthreshold = threshold; 900 debt = gettotalbytes(g) - threshold;
1017 luaE_setdebt(g, -g->gclocalpause); 901 luaE_setdebt(g, debt);
1018} 902}
1019 903
1020 904
@@ -1029,9 +913,9 @@ static void setpause (global_State *g, l_mem estimate) {
1029static int entersweep (lua_State *L) { 913static int entersweep (lua_State *L) {
1030 global_State *g = G(L); 914 global_State *g = G(L);
1031 int n = 0; 915 int n = 0;
1032 g->gcstate = GCSswplocalgc; 916 g->gcstate = GCSswpallgc;
1033 lua_assert(g->sweepgc == NULL); 917 lua_assert(g->sweepgc == NULL);
1034 g->sweepgc = sweeptolive(L, &g->localgc, &n); 918 g->sweepgc = sweeptolive(L, &g->allgc, &n);
1035 return n; 919 return n;
1036} 920}
1037 921
@@ -1044,7 +928,6 @@ void luaC_freeallobjects (lua_State *L) {
1044 lua_assert(g->tobefnz == NULL); 928 lua_assert(g->tobefnz == NULL);
1045 g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ 929 g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */
1046 g->gckind = KGC_NORMAL; 930 g->gckind = KGC_NORMAL;
1047 sweepwholelist(L, &g->localgc);
1048 sweepwholelist(L, &g->finobj); 931 sweepwholelist(L, &g->finobj);
1049 sweepwholelist(L, &g->allgc); 932 sweepwholelist(L, &g->allgc);
1050 sweepwholelist(L, &g->mainthread->next); 933 sweepwholelist(L, &g->mainthread->next);
@@ -1136,10 +1019,7 @@ static lu_mem singlestep (lua_State *L) {
1136 sw = entersweep(L); 1019 sw = entersweep(L);
1137 return work + sw * GCSWEEPCOST; 1020 return work + sw * GCSWEEPCOST;
1138 } 1021 }
1139 case GCSswplocalgc: { /* sweep local objects */ 1022 case GCSswpallgc: { /* sweep "regular" objects */
1140 return sweepstep(L, g, GCSswpallgc, &g->allgc);
1141 }
1142 case GCSswpallgc: { /* sweep non-local objects */
1143 return sweepstep(L, g, GCSswpthreads, &g->mainthread->next); 1023 return sweepstep(L, g, GCSswpthreads, &g->mainthread->next);
1144 } 1024 }
1145 case GCSswpthreads: { /* sweep threads */ 1025 case GCSswpthreads: { /* sweep threads */
@@ -1208,23 +1088,13 @@ void luaC_forcestep (lua_State *L) {
1208 1088
1209 1089
1210/* 1090/*
1211** performs a basic GC step or a local collection when collector is running 1091** performs a basic GC step when collector is running
1212*/ 1092*/
1213void luaC_step (lua_State *L) { 1093void luaC_step (lua_State *L) {
1214 global_State *g = G(L); 1094 if (!G(L)->gcrunning)
1215 if (!g->gcrunning) 1095 luaE_setdebt(G(L), -GCSTEPSIZE); /* avoid being called too often */
1216 luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ 1096 else
1217 else { 1097 luaC_forcestep(L);
1218 if (g->gcstate != GCSpause) /* in the middle of a cycle? */
1219 luaC_forcestep(L); /* continue it */
1220 else {
1221 luaC_localcollection(L); /* try a local collection */
1222 if (gettotalbytes(g) <= g->GCthreshold) /* enough? */
1223 luaE_setdebt(g, -g->gclocalpause);
1224 else /* local collection did not collect enough memory */
1225 luaC_forcestep(L); /* start a full collection */
1226 }
1227 }
1228} 1098}
1229 1099
1230 1100
diff --git a/lgc.h b/lgc.h
index 43cfb851..c4e1f3b0 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.76 2013/09/11 20:15:31 roberto Exp roberto $ 2** $Id: lgc.h,v 2.77 2014/02/11 12:18:12 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -38,17 +38,16 @@
38*/ 38*/
39#define GCSpropagate 0 39#define GCSpropagate 0
40#define GCSatomic 1 40#define GCSatomic 1
41#define GCSswplocalgc 2 41#define GCSswpallgc 2
42#define GCSswpallgc 3 42#define GCSswpthreads 3
43#define GCSswpthreads 4 43#define GCSswpfinobj 4
44#define GCSswpfinobj 5 44#define GCSswptobefnz 5
45#define GCSswptobefnz 6 45#define GCSswpend 6
46#define GCSswpend 7 46#define GCSpause 7
47#define GCSpause 8
48 47
49 48
50#define issweepphase(g) \ 49#define issweepphase(g) \
51 (GCSswplocalgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) 50 (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend)
52 51
53 52
54/* 53/*
@@ -80,8 +79,6 @@
80#define WHITE1BIT 1 /* object is white (type 1) */ 79#define WHITE1BIT 1 /* object is white (type 1) */
81#define BLACKBIT 2 /* object is black */ 80#define BLACKBIT 2 /* object is black */
82#define FINALIZEDBIT 3 /* object has been marked for finalization */ 81#define FINALIZEDBIT 3 /* object has been marked for finalization */
83#define NOLOCALBIT 4 /* object is not local */
84#define LOCALMARK 5 /* object is 'locally marked' or out of local list */
85/* bit 7 is currently used by tests (luaL_checkmemory) */ 82/* bit 7 is currently used by tests (luaL_checkmemory) */
86 83
87#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) 84#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT)
@@ -91,7 +88,6 @@
91#define isblack(x) testbit((x)->gch.marked, BLACKBIT) 88#define isblack(x) testbit((x)->gch.marked, BLACKBIT)
92#define isgray(x) /* neither white nor black */ \ 89#define isgray(x) /* neither white nor black */ \
93 (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) 90 (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT)))
94#define islocal(x) (!testbit((x)->gch.marked, NOLOCALBIT))
95 91
96#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT) 92#define tofinalize(x) testbit((x)->gch.marked, FINALIZEDBIT)
97 93
@@ -102,9 +98,6 @@
102#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) 98#define changewhite(x) ((x)->gch.marked ^= WHITEBITS)
103#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) 99#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT)
104 100
105#define nolocal(x) l_setbit((x)->gch.marked, NOLOCALBIT)
106#define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); }
107
108#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) 101#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS)
109 102
110 103
@@ -114,17 +107,15 @@
114 107
115 108
116#define luaC_barrier(L,p,v) { \ 109#define luaC_barrier(L,p,v) { \
117 if (iscollectable(v) && \ 110 if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
118 (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
119 luaC_barrier_(L,obj2gco(p),gcvalue(v)); } 111 luaC_barrier_(L,obj2gco(p),gcvalue(v)); }
120 112
121#define luaC_barrierback(L,p,v) { \ 113#define luaC_barrierback(L,p,v) { \
122 if (iscollectable(v) && \ 114 if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \
123 (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \
124 luaC_barrierback_(L,obj2gco(p)); } 115 luaC_barrierback_(L,obj2gco(p)); }
125 116
126#define luaC_objbarrier(L,p,o) { \ 117#define luaC_objbarrier(L,p,o) { \
127 if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ 118 if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \
128 luaC_barrier_(L,obj2gco(p),obj2gco(o)); } 119 luaC_barrier_(L,obj2gco(p),obj2gco(o)); }
129 120
130#define luaC_upvalbarrier(L,uv) \ 121#define luaC_upvalbarrier(L,uv) \
diff --git a/lstate.c b/lstate.c
index 2f21f98e..3a33390d 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.116 2013/11/08 17:34:22 roberto Exp roberto $ 2** $Id: lstate.c,v 2.117 2014/02/11 12:18:12 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -30,10 +30,6 @@
30#define LUAI_GCPAUSE 200 /* 200% */ 30#define LUAI_GCPAUSE 200 /* 200% */
31#endif 31#endif
32 32
33#if !defined(LUAI_GCLOCALPAUSE)
34#define LUAI_GCLOCALPAUSE (1000 * sizeof(TString))
35#endif
36
37#if !defined(LUAI_GCMUL) 33#if !defined(LUAI_GCMUL)
38#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ 34#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */
39#endif 35#endif
@@ -187,14 +183,12 @@ static void init_registry (lua_State *L, global_State *g) {
187 Table *registry = luaH_new(L); 183 Table *registry = luaH_new(L);
188 sethvalue(L, &g->l_registry, registry); 184 sethvalue(L, &g->l_registry, registry);
189 luaH_resize(L, registry, LUA_RIDX_LAST, 0); 185 luaH_resize(L, registry, LUA_RIDX_LAST, 0);
190 nolocal(obj2gco(registry));
191 /* registry[LUA_RIDX_MAINTHREAD] = L */ 186 /* registry[LUA_RIDX_MAINTHREAD] = L */
192 setthvalue(L, &temp, L); /* temp = L */ 187 setthvalue(L, &temp, L); /* temp = L */
193 luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); 188 luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp);
194 /* registry[LUA_RIDX_GLOBALS] = table of globals */ 189 /* registry[LUA_RIDX_GLOBALS] = table of globals */
195 sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ 190 sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */
196 luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); 191 luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp);
197 valnolocal(&temp); /* keep local invariant */
198} 192}
199 193
200 194
@@ -263,7 +257,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
263 luaC_checkGC(L); 257 luaC_checkGC(L);
264 /* create new thread */ 258 /* create new thread */
265 L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; 259 L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l;
266 L1->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); 260 L1->marked = luaC_white(g);
267 L1->tt = LUA_TTHREAD; 261 L1->tt = LUA_TTHREAD;
268 /* link it on list of threads */ 262 /* link it on list of threads */
269 L1->next = g->mainthread->next; 263 L1->next = g->mainthread->next;
@@ -303,7 +297,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
303 L->next = NULL; 297 L->next = NULL;
304 L->tt = LUA_TTHREAD; 298 L->tt = LUA_TTHREAD;
305 g->currentwhite = bitmask(WHITE0BIT); 299 g->currentwhite = bitmask(WHITE0BIT);
306 L->marked = luaC_white(g) | bit2mask(NOLOCALBIT, LOCALMARK); 300 L->marked = luaC_white(g);
307 g->gckind = KGC_NORMAL; 301 g->gckind = KGC_NORMAL;
308 preinit_state(L, g); 302 preinit_state(L, g);
309 g->frealloc = f; 303 g->frealloc = f;
@@ -312,7 +306,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
312 g->seed = makeseed(L); 306 g->seed = makeseed(L);
313 g->gcrunning = 0; /* no GC while building state */ 307 g->gcrunning = 0; /* no GC while building state */
314 g->GCestimate = 0; 308 g->GCestimate = 0;
315 g->GCthreshold = 10000;
316 g->strt.size = g->strt.nuse = 0; 309 g->strt.size = g->strt.nuse = 0;
317 g->strt.hash = NULL; 310 g->strt.hash = NULL;
318 setnilvalue(&g->l_registry); 311 setnilvalue(&g->l_registry);
@@ -320,16 +313,13 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
320 g->panic = NULL; 313 g->panic = NULL;
321 g->version = NULL; 314 g->version = NULL;
322 g->gcstate = GCSpause; 315 g->gcstate = GCSpause;
323 g->localgc = g->allgc = g->finobj = NULL; 316 g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL;
324 g->tobefnz = NULL;
325 g->fixedgc = NULL;
326 g->sweepgc = NULL; 317 g->sweepgc = NULL;
327 g->gray = g->grayagain = NULL; 318 g->gray = g->grayagain = NULL;
328 g->weak = g->ephemeron = g->allweak = NULL; 319 g->weak = g->ephemeron = g->allweak = NULL;
329 g->totalbytes = sizeof(LG); 320 g->totalbytes = sizeof(LG);
330 g->GCdebt = 0; 321 g->GCdebt = 0;
331 g->gcpause = LUAI_GCPAUSE; 322 g->gcpause = LUAI_GCPAUSE;
332 g->gclocalpause = LUAI_GCLOCALPAUSE;
333 g->gcstepmul = LUAI_GCMUL; 323 g->gcstepmul = LUAI_GCMUL;
334 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; 324 for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL;
335 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { 325 if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
diff --git a/lstate.h b/lstate.h
index 49b5d24e..13b2108c 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.97 2013/09/17 15:40:06 roberto Exp roberto $ 2** $Id: lstate.h,v 2.98 2014/02/11 12:18:12 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -22,8 +22,7 @@
22** the 'CommonHeader' for the link: 22** the 'CommonHeader' for the link:
23** 23**
24** mainthread->next: all threads; 24** mainthread->next: all threads;
25** localgc: all local objects not marked for finalization; 25** allgc: all objects not marked for finalization;
26** allgc: all non local objects not marked for finalization;
27** finobj: all objects marked for finalization; 26** finobj: all objects marked for finalization;
28** tobefnz: all objects ready to be finalized; 27** tobefnz: all objects ready to be finalized;
29** fixedgc: all objects that are not to be collected (currently 28** fixedgc: all objects that are not to be collected (currently
@@ -108,7 +107,6 @@ typedef struct global_State {
108 l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ 107 l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
109 lu_mem GCmemtrav; /* memory traversed by the GC */ 108 lu_mem GCmemtrav; /* memory traversed by the GC */
110 lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ 109 lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
111 lu_mem GCthreshold; /* threshold to start a new GC cycle */
112 stringtable strt; /* hash table for strings */ 110 stringtable strt; /* hash table for strings */
113 TValue l_registry; 111 TValue l_registry;
114 unsigned int seed; /* randomized seed for hashes */ 112 unsigned int seed; /* randomized seed for hashes */
@@ -117,7 +115,6 @@ typedef struct global_State {
117 lu_byte gckind; /* kind of GC running */ 115 lu_byte gckind; /* kind of GC running */
118 lu_byte gcrunning; /* true if GC is running */ 116 lu_byte gcrunning; /* true if GC is running */
119 GCObject *allgc; /* list of all collectable objects */ 117 GCObject *allgc; /* list of all collectable objects */
120 GCObject *localgc; /* list of local objects */
121 GCObject **sweepgc; /* current position of sweep in list */ 118 GCObject **sweepgc; /* current position of sweep in list */
122 GCObject *finobj; /* list of collectable objects with finalizers */ 119 GCObject *finobj; /* list of collectable objects with finalizers */
123 GCObject *gray; /* list of gray objects */ 120 GCObject *gray; /* list of gray objects */
@@ -129,7 +126,6 @@ typedef struct global_State {
129 GCObject *fixedgc; /* list of objects not to be collected */ 126 GCObject *fixedgc; /* list of objects not to be collected */
130 Mbuffer buff; /* temporary buffer for string concatenation */ 127 Mbuffer buff; /* temporary buffer for string concatenation */
131 int gcpause; /* size of pause between successive GCs */ 128 int gcpause; /* size of pause between successive GCs */
132 int gclocalpause; /* size of pause between local collections */
133 int gcstepmul; /* GC `granularity' */ 129 int gcstepmul; /* GC `granularity' */
134 lua_CFunction panic; /* to be called in unprotected errors */ 130 lua_CFunction panic; /* to be called in unprotected errors */
135 struct lua_State *mainthread; 131 struct lua_State *mainthread;
diff --git a/ltests.c b/ltests.c
index 6923cef5..7ec2aac2 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 2.162 2013/12/30 20:47:58 roberto Exp roberto $ 2** $Id: ltests.c,v 2.163 2014/02/11 12:18:12 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -188,41 +188,23 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) {
188} 188}
189 189
190 190
191/*
192** Check locality
193*/
194static int testobjref2 (GCObject *f, GCObject *t) {
195 /* not a local or pointed by a thread? */
196 if (!islocal(t) || gch(f)->tt == LUA_TTHREAD)
197 return 1; /* ok */
198 if (gch(f)->tt == LUA_TPROTO && gch(t)->tt == LUA_TLCL)
199 return 1; /* cache from a prototype */
200 return 0;
201}
202
203
204static void printobj (global_State *g, GCObject *o) { 191static void printobj (global_State *g, GCObject *o) {
205 printf("||%s(%p)-%s-%c(%02X)||", 192 printf("||%s(%p)-%c(%02X)||",
206 ttypename(novariant(gch(o)->tt)), (void *)o, 193 ttypename(novariant(gch(o)->tt)), (void *)o,
207 islocal(o)?"L":"NL",
208 isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); 194 isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked);
209} 195}
210 196
211 197
212static int testobjref (global_State *g, GCObject *f, GCObject *t) { 198static int testobjref (global_State *g, GCObject *f, GCObject *t) {
213 int r1 = testobjref1(g,f,t); 199 int r1 = testobjref1(g, f, t);
214 int r2 = testobjref2(f,t); 200 if (!r1) {
215 if (!r1 || !r2) { 201 printf("%d(%02X) - ", g->gcstate, g->currentwhite);
216 if (!r1)
217 printf("%d(%02X) - ", g->gcstate, g->currentwhite);
218 else
219 printf("local violation - ");
220 printobj(g, f); 202 printobj(g, f);
221 printf(" -> "); 203 printf(" -> ");
222 printobj(g, t); 204 printobj(g, t);
223 printf("\n"); 205 printf("\n");
224 } 206 }
225 return r1 && r2; 207 return r1;
226} 208}
227 209
228#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) 210#define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t)))
@@ -349,7 +331,6 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
349 break; 331 break;
350 } 332 }
351 case LUA_TTHREAD: { 333 case LUA_TTHREAD: {
352 lua_assert(!islocal(o));
353 checkstack(g, gco2th(o)); 334 checkstack(g, gco2th(o));
354 break; 335 break;
355 } 336 }
@@ -366,7 +347,10 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
366 break; 347 break;
367 } 348 }
368 case LUA_TSHRSTR: 349 case LUA_TSHRSTR:
369 case LUA_TLNGSTR: break; 350 case LUA_TLNGSTR: {
351 lua_assert(!isgray(o)); /* strings are never gray */
352 break;
353 }
370 default: lua_assert(0); 354 default: lua_assert(0);
371 } 355 }
372 } 356 }
@@ -431,28 +415,23 @@ int lua_checkmemory (lua_State *L) {
431 resetbit(g->mainthread->marked, TESTGRAYBIT); 415 resetbit(g->mainthread->marked, TESTGRAYBIT);
432 lua_assert(g->sweepgc == NULL || issweepphase(g)); 416 lua_assert(g->sweepgc == NULL || issweepphase(g));
433 markgrays(g); 417 markgrays(g);
434 /* check 'localgc' list */ 418 /* check 'fixedgc' list */
435 checkgray(g, g->localgc); 419 for (o = g->fixedgc; o != NULL; o = gch(o)->next) {
436 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswplocalgc); 420 lua_assert(gch(o)->tt == LUA_TSHRSTR && isgray(o));
437 for (o = g->localgc; o != NULL; o = gch(o)->next) {
438 checkobject(g, o, maybedead);
439 lua_assert(!tofinalize(o) && !testbit(o->gch.marked, LOCALMARK));
440 } 421 }
441 /* check 'allgc' list */ 422 /* check 'allgc' list */
442 checkgray(g, g->allgc); 423 checkgray(g, g->allgc);
443 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc); 424 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc);
444 for (o = g->allgc; o != NULL; o = gch(o)->next) { 425 for (o = g->allgc; o != NULL; o = gch(o)->next) {
445 checkobject(g, o, maybedead); 426 checkobject(g, o, maybedead);
446 lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); 427 lua_assert(!tofinalize(o));
447 lua_assert(testbit(o->gch.marked, NOLOCALBIT));
448 } 428 }
449 /* check thread list */ 429 /* check thread list */
450 checkgray(g, obj2gco(g->mainthread)); 430 checkgray(g, obj2gco(g->mainthread));
451 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads); 431 maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpthreads);
452 for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) { 432 for (o = obj2gco(g->mainthread); o != NULL; o = gch(o)->next) {
453 checkobject(g, o, maybedead); 433 checkobject(g, o, maybedead);
454 lua_assert(!tofinalize(o) && testbit(o->gch.marked, LOCALMARK)); 434 lua_assert(!tofinalize(o));
455 lua_assert(testbit(o->gch.marked, NOLOCALBIT));
456 lua_assert(gch(o)->tt == LUA_TTHREAD); 435 lua_assert(gch(o)->tt == LUA_TTHREAD);
457 } 436 }
458 /* check 'finobj' list */ 437 /* check 'finobj' list */
@@ -460,7 +439,6 @@ int lua_checkmemory (lua_State *L) {
460 for (o = g->finobj; o != NULL; o = gch(o)->next) { 439 for (o = g->finobj; o != NULL; o = gch(o)->next) {
461 checkobject(g, o, 0); 440 checkobject(g, o, 0);
462 lua_assert(tofinalize(o)); 441 lua_assert(tofinalize(o));
463 lua_assert(!islocal(o) || !testbit(gch(o)->marked, LOCALMARK));
464 lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE); 442 lua_assert(gch(o)->tt == LUA_TUSERDATA || gch(o)->tt == LUA_TTABLE);
465 } 443 }
466 /* check 'tobefnz' list */ 444 /* check 'tobefnz' list */
@@ -636,21 +614,12 @@ static int gc_color (lua_State *L) {
636} 614}
637 615
638 616
639static int gc_local (lua_State *L) {
640 TValue *o;
641 luaL_checkany(L, 1);
642 o = obj_at(L, 1);
643 lua_pushboolean(L, !iscollectable(o) || islocal(gcvalue(o)));
644 return 1;
645}
646
647
648static int gc_state (lua_State *L) { 617static int gc_state (lua_State *L) {
649 static const char *statenames[] = {"propagate", "atomic", 618 static const char *statenames[] = {"propagate", "atomic",
650 "sweeplocalgc", "sweepallgc", "sweepthreads", "sweepfinobj", 619 "sweepallgc", "sweepthreads", "sweepfinobj",
651 "sweeptobefnz", "sweepend", "pause", ""}; 620 "sweeptobefnz", "sweepend", "pause", ""};
652 static const int states[] = {GCSpropagate, GCSatomic, 621 static const int states[] = {GCSpropagate, GCSatomic,
653 GCSswplocalgc, GCSswpallgc, GCSswpthreads, GCSswpfinobj, 622 GCSswpallgc, GCSswpthreads, GCSswpfinobj,
654 GCSswptobefnz, GCSswpend, GCSpause, -1}; 623 GCSswptobefnz, GCSswpend, GCSpause, -1};
655 int option = states[luaL_checkoption(L, 1, "", statenames)]; 624 int option = states[luaL_checkoption(L, 1, "", statenames)];
656 if (option == -1) { 625 if (option == -1) {
@@ -1459,7 +1428,6 @@ static const struct luaL_Reg tests_funcs[] = {
1459 {"doonnewstack", doonnewstack}, 1428 {"doonnewstack", doonnewstack},
1460 {"doremote", doremote}, 1429 {"doremote", doremote},
1461 {"gccolor", gc_color}, 1430 {"gccolor", gc_color},
1462 {"isgclocal", gc_local},
1463 {"gcstate", gc_state}, 1431 {"gcstate", gc_state},
1464 {"getref", getref}, 1432 {"getref", getref},
1465 {"hash", hash_query}, 1433 {"hash", hash_query},
@@ -1509,3 +1477,4 @@ int luaB_opentests (lua_State *L) {
1509} 1477}
1510 1478
1511#endif 1479#endif
1480
diff --git a/lua.h b/lua.h
index d40d1956..95fb3f9c 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.297 2013/12/18 14:12:03 roberto Exp roberto $ 2** $Id: lua.h,v 1.298 2013/12/30 20:47:58 roberto Exp roberto $
3** Lua - A Scripting Language 3** Lua - A Scripting Language
4** Lua.org, PUC-Rio, Brazil (http://www.lua.org) 4** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
5** See Copyright Notice at the end of this file 5** See Copyright Notice at the end of this file
@@ -294,7 +294,6 @@ LUA_API int (lua_status) (lua_State *L);
294#define LUA_GCSTEP 5 294#define LUA_GCSTEP 5
295#define LUA_GCSETPAUSE 6 295#define LUA_GCSETPAUSE 6
296#define LUA_GCSETSTEPMUL 7 296#define LUA_GCSETSTEPMUL 7
297#define LUA_GCSETLOCALPAUSE 8
298#define LUA_GCISRUNNING 9 297#define LUA_GCISRUNNING 9
299 298
300LUA_API int (lua_gc) (lua_State *L, int what, int data); 299LUA_API int (lua_gc) (lua_State *L, int what, int data);
diff --git a/lundump.c b/lundump.c
index be77d98e..7194d82a 100644
--- a/lundump.c
+++ b/lundump.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $ 2** $Id: lundump.c,v 2.24 2013/08/16 18:55:49 roberto Exp roberto $
3** load precompiled Lua chunks 3** load precompiled Lua chunks
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -88,7 +88,6 @@ static TString* LoadString(LoadState* S)
88 char* s=luaZ_openspace(S->L,S->b,size); 88 char* s=luaZ_openspace(S->L,S->b,size);
89 LoadBlock(S,s,size*sizeof(char)); 89 LoadBlock(S,s,size*sizeof(char));
90 ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ 90 ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */
91 nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */
92 return ts; 91 return ts;
93 } 92 }
94} 93}