diff -Nr lua-5.4.0/Makefile lua-5.4.1/Makefile 49c49 < R= $V.0 --- > R= $V.1 diff -Nr lua-5.4.0/README lua-5.4.1/README 2c2 < This is Lua 5.4.0, released on 18 Jun 2020. --- > This is Lua 5.4.1, released on 30 Sep 2020. diff -Nr lua-5.4.0/doc/contents.html lua-5.4.1/doc/contents.html 97a98 >
  • 4.1.3 – Pointers to strings 667c668 < Sat May 30 08:22:18 -03 2020 --- > Wed Sep 30 06:45:10 -03 2020 670c671 < Last change: revised for Lua 5.4.0 (final) --- > Last change: revised for Lua 5.4.1 diff -Nr lua-5.4.0/doc/manual.html lua-5.4.1/doc/manual.html 2976c2976,2977 < at least LUA_MINSTACK extra slots. --- > at least LUA_MINSTACK extra elements; > that is, you can safely push up to LUA_MINSTACK values into it. 2987c2988 < So, before pushing anything in the stack after such a call --- > So, before pushing anything on the stack after such a call 3046a3048,3089 >

    4.1.3 – Pointers to strings

    > >

    > Several functions in the API return pointers (const char*) > to Lua strings in the stack. > (See lua_pushfstring, lua_pushlstring, > lua_pushstring, and lua_tolstring. > See also luaL_checklstring, luaL_checkstring, > and luaL_tolstring in the auxiliary library.) > > >

    > In general, > Lua's garbage collection can free or move internal memory > and then invalidate pointers to internal strings. > To allow a safe use of these pointers, > The API guarantees that any pointer to a string in a stack index > is valid while the value at that index is neither modified nor popped. > When the index is a pseudo-index (referring to an upvalue), > the pointer is valid while the corresponding call is active and > the corresponding upvalue is not modified. > > >

    > Some functions in the debug interface > also return pointers to strings, > namely lua_getlocal, lua_getupvalue, > lua_setlocal, and lua_setupvalue. > For these functions, the pointer is guaranteed to > be valid while the caller function is active and > the given closure (if one was given) is in the stack. > > >

    > Except for these guarantees, > the garbage collector is free to invalidate > any pointer to internal strings. > > > > > 3392c3435 < (For instance, they may depend on what is on the stack.) --- > (For instance, they may depend on what is in the stack.) 3681c3724 < Ensures that the stack has space for at least n extra slots, --- > Ensures that the stack has space for at least n extra elements, 3689c3732 < if the stack already has space for the extra slots, --- > if the stack already has space for the extra elements, 4445a4489,4492 > Lua ensures that this address is valid as long as > the corresponding userdata is alive (see §2.5). > Moreover, if the userdata is marked for finalization (see §2.5.3), > its address is valid at least until the call to its finalizer. 4691c4738 < and returns a pointer to this string. --- > and returns a pointer to this string (see §4.1.3). 4791c4838 < Returns a pointer to the internal copy of the string. --- > Returns a pointer to the internal copy of the string (see §4.1.3). 4832c4879 < Returns a pointer to the internal copy of the string. --- > Returns a pointer to the internal copy of the string (see §4.1.3). 5402c5449 < [-0, +0, v] --- > [-0, +0, m] 5426,5427c5473,5474 < This function can raise an out-of-memory error. < In that case, the value in the given index is immediately closed, --- > In the case of an out-of-memory error, > the value in the given index is immediately closed, 5430a5478,5485 >

    > Note that, both in case of errors and of a regular return, > by the time the __close metamethod runs, > the C stack was already unwound, > so that any automatic C variable declared in the calling function > will be out of scope. > > 5485c5540 < to a string inside the Lua state. --- > to a string inside the Lua state (see §4.1.3). 5491,5496d5545 <

    < Because Lua has garbage collection, < there is no guarantee that the pointer returned by lua_tolstring < will be valid after the corresponding Lua value is removed from the stack. < < 5947c5996 < the index on the stack of the first value being "transferred", --- > the index in the stack of the first value being "transferred", 6144c6193 < (except for tail calls, which do not count on the stack). --- > (except for tail calls, which do not count in the stack). 6262,6263c6311 < The hook is called just after Lua enters the new function, < before the function gets its arguments. --- > The hook is called just after Lua enters the new function. 7576c7624 < returned by the function. --- > returned by the function (see §4.1.3). 8004,8006c8052,8056 < Lua does not check the consistency of binary chunks. < Maliciously crafted binary chunks can crash < the interpreter. --- > It is safe to load malformed binary chunks; > load signals an appropriate error. > However, > Lua does not check the consistency of the code inside binary chunks; > running maliciously crafted bytecode can crash the interpreter. 8667a8718,8729 >

    > This function is inherently insecure, > as it allows Lua to call any function in any readable dynamic > library in the system. > (Lua calls any function assuming the function > has a proper prototype and respects a proper protocol > (see lua_CFunction). > Therefore, > calling an arbitrary function in an arbitrary dynamic library > more often than not results in an access violation.) > > 11087c11149 < (except for tail calls, which do not count on the stack); --- > (except for tail calls, which do not count in the stack); 11889c11951 < Thu Jun 18 16:10:16 UTC 2020 --- > Wed Sep 30 09:46:30 UTC 2020 11892c11954 < Last change: revised for Lua 5.4.0 (final) --- > Last change: revised for Lua 5.4.1 diff -Nr lua-5.4.0/doc/readme.html lua-5.4.1/doc/readme.html 113c113 < the top-level directory, which is named lua-5.4.0. --- > the top-level directory, which is named lua-5.4.1. 333c333 < Fri May 1 19:33:31 UTC 2020 --- > Wed Sep 30 09:55:45 UTC 2020 336c336 < Last change: revised for Lua 5.4.0 (final) --- > Last change: revised for Lua 5.4.1 diff -Nr lua-5.4.0/src/lapi.c lua-5.4.1/src/lapi.c 100c100 < CallInfo *ci = L->ci; --- > CallInfo *ci; 101a102 > ci = L->ci; 173,174c174,175 < CallInfo *ci = L->ci; < StkId func = ci->func; --- > CallInfo *ci; > StkId func; 176a178,179 > ci = L->ci; > func = ci->func; 379c382,384 < TValue *o = index2value(L, idx); --- > TValue *o; > lua_lock(L); > o = index2value(L, idx); 382a388 > lua_unlock(L); 385d390 < lua_lock(L); /* 'luaO_tostring' may create a new string */ 389d393 < lua_unlock(L); 392a397 > lua_unlock(L); 565a571 > lua_assert(iswhite(cl)); 627c633 < Table *reg = hvalue(&G(L)->l_registry); --- > Table *reg; 628a635 > reg = hvalue(&G(L)->l_registry); 807c814 < Table *reg = hvalue(&G(L)->l_registry); --- > Table *reg; 808a816 > reg = hvalue(&G(L)->l_registry); 1096c1104 < global_State *g = G(L); --- > global_State *g; 1097a1106 > g = G(L); 1196a1206 > TValue *errobj; 1197a1208 > errobj = s2v(L->top - 1); 1199c1210,1214 < luaG_errormsg(L); --- > /* error object is the memory error message? */ > if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) > luaM_error(L); /* raise a memory error */ > else > luaG_errormsg(L); /* raise a regular error */ 1241c1256 < if (n >= 2) { --- > if (n > 0) 1243,1245c1258,1259 < } < else if (n == 0) { /* push empty string */ < setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); --- > else { /* nothing to concatenate */ > setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ 1248d1261 < /* else n == 1; nothing to do */ diff -Nr lua-5.4.0/src/lauxlib.c lua-5.4.1/src/lauxlib.c 478,479c478,481 < if (temp == NULL && newsize > 0) /* allocation error? */ < luaL_error(L, "not enough memory"); --- > if (temp == NULL && newsize > 0) { /* allocation error? */ > lua_pushliteral(L, "not enough memory"); > lua_error(L); /* raise a memory error */ > } diff -Nr lua-5.4.0/src/lcorolib.c lua-5.4.1/src/lcorolib.c 76c76 < if (r < 0) { --- > if (r < 0) { /* error? */ 78,80c78,81 < if (stat != LUA_OK && stat != LUA_YIELD) < lua_resetthread(co); /* close variables in case of errors */ < if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ --- > if (stat != LUA_OK && stat != LUA_YIELD) /* error in the coroutine? */ > lua_resetthread(co); /* close its tbc variables */ > if (stat != LUA_ERRMEM && /* not a memory error and ... */ > lua_type(L, -1) == LUA_TSTRING) { /* ... error object is a string? */ diff -Nr lua-5.4.0/src/lctype.h lua-5.4.1/src/lctype.h 16c16 < ** optimized for the specific needs of Lua --- > ** optimized for the specific needs of Lua. 63a64 > 65c66,69 < ** this 'ltolower' only works for alphabetic characters --- > ** In ASCII, this 'ltolower' is correct for alphabetic characters and > ** for '.'. That is enough for Lua needs. ('check_exp' ensures that > ** the character either is an upper-case letter or is unchanged by > ** the transformation, which holds for lower-case letters and '.'.) 67c71,73 < #define ltolower(c) ((c) | ('A' ^ 'a')) --- > #define ltolower(c) \ > check_exp(('A' <= (c) && (c) <= 'Z') || (c) == ((c) | ('A' ^ 'a')), \ > (c) | ('A' ^ 'a')) 70c76 < /* two more entries for 0 and -1 (EOZ) */ --- > /* one entry for each character and for -1 (EOZ) */ diff -Nr lua-5.4.0/src/ldebug.c lua-5.4.1/src/ldebug.c 36,39c36,37 < < /* Active Lua function (given call info) */ < #define ci_func(ci) (clLvalue(s2v((ci)->func))) < --- > /* inverse of 'pcRel' */ > #define invpcRel(pc, p) ((p)->code + (pc) + 1) 130,135c128,133 < ** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by < ** 'resethookcount') are for debug only, and it is no problem if they < ** get arbitrary values (causes at most one wrong hook call). 'hookmask' < ** is an atomic value. We assume that pointers are atomic too (e.g., gcc < ** ensures that for all platforms where it runs). Moreover, 'hook' is < ** always checked before being called (see 'luaD_hook'). --- > ** Fields 'basehookcount' and 'hookcount' (set by 'resethookcount') > ** are for debug only, and it is no problem if they get arbitrary > ** values (causes at most one wrong hook call). 'hookmask' is an atomic > ** value. We assume that pointers are atomic too (e.g., gcc ensures that > ** for all platforms where it runs). Moreover, 'hook' is always checked > ** before being called (see 'luaD_hook'). 142,143d139 < if (isLua(L->ci)) < L->oldpc = L->ci->u.l.savedpc; 195,196c191,192 < if (n <= nextra) { < *pos = ci->func - nextra + (n - 1); --- > if (n >= -nextra) { /* 'n' is negative */ > *pos = ci->func - nextra - (n + 1); 209c205 < return findvararg(ci, -n, pos); --- > return findvararg(ci, n, pos); 789a786,787 > if (p->lineinfo == NULL) /* no debug information? */ > return 0; 794c792 < return 0; /* no line changes in the way */ --- > return 0; /* no line changes between positions */ 797a796,806 > /* > ** Traces the execution of a Lua function. Called before the execution > ** of each opcode, when debug is on. 'L->oldpc' stores the last > ** instruction traced, to detect line changes. When entering a new > ** function, 'npci' will be zero and will test as a new line without > ** the need for 'oldpc'; so, 'oldpc' does not need to be initialized > ** before. Some exceptional conditions may return to a function without > ** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is > ** reset to zero. (A wrong but valid 'oldpc' at most causes an extra > ** call to a line hook.) > */ 800a810 > const Proto *p = ci_func(ci)->p; 801a812,813 > /* 'L->oldpc' may be invalid; reset it in this case */ > int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0; 822d833 < const Proto *p = ci_func(ci)->p; 825,826c836,837 < pc <= L->oldpc || /* when jump back (loop), or when */ < changedline(p, pcRel(L->oldpc, p), npci)) { /* enter new line */ --- > pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */ > changedline(p, oldpc, npci)) { /* enter new line */ 830c841 < L->oldpc = pc; /* 'pc' of last call to line hook */ --- > L->oldpc = npci; /* 'pc' of last call to line hook */ diff -Nr lua-5.4.0/src/ldebug.h lua-5.4.1/src/ldebug.h 15a16,20 > > /* Active Lua function (given call info) */ > #define ci_func(ci) (clLvalue(s2v((ci)->func))) > > diff -Nr lua-5.4.0/src/ldo.c lua-5.4.1/src/ldo.c 248c248 < int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; --- > int goodsize = inuse + BASIC_STACK_SIZE; 253,254c253 < if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && < goodsize < L->stacksize) --- > if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && goodsize < L->stacksize) 331c330 < Proto *p = clLvalue(s2v(ci->func))->p; --- > Proto *p = ci_func(ci)->p; 344,345c343,344 < if (isLua(ci->previous)) < L->oldpc = ci->previous->u.l.savedpc; /* update 'oldpc' */ --- > if (isLua(ci = ci->previous)) > L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */ 469,470c468,470 < CallInfo *ci = next_ci(L); < checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ --- > CallInfo *ci; > checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ > L->ci = ci = next_ci(L); 475d474 < L->ci = ci; 489c488 < CallInfo *ci = next_ci(L); --- > CallInfo *ci; 494c493,494 < checkstackp(L, fsize, func); --- > checkstackGCp(L, fsize, func); > L->ci = ci = next_ci(L); 508c508 < checkstackp(L, 1, func); /* space for metamethod */ --- > checkstackGCp(L, 1, func); /* space for metamethod */ 518,520d517 < ** If there is a stack overflow, freeing all CI structures will < ** force the subsequent call to invoke 'luaE_extendCI', which then < ** will raise any errors. 524,525c521,524 < if (getCcalls(L) <= CSTACKERR) /* possible stack overflow? */ < luaE_freeCI(L); --- > if (getCcalls(L) <= CSTACKERR) { /* possible C stack overflow? */ > luaE_exitCcall(L); /* to compensate decrement in next call */ > luaE_enterCcall(L); /* check properly */ > } 677c676 < L->nCcalls = getCcalls(from) + from->nci - L->nci - CSTACKCF; --- > L->nCcalls = getCcalls(from) - L->nci - CSTACKCF; 709c708 < CallInfo *ci = L->ci; --- > CallInfo *ci; 711a711 > ci = L->ci; diff -Nr lua-5.4.0/src/ldo.h lua-5.4.1/src/ldo.h 19a20,21 > ** It also allows the running of one GC step when the stack is > ** reallocated. 38c40 < #define checkstackp(L,n,p) \ --- > #define checkstackGCp(L,n,p) \ 47c49 < luaD_checkstackaux(L, (fsize), (void)0, luaC_checkGC(L)) --- > luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0) diff -Nr lua-5.4.0/src/lfunc.c lua-5.4.1/src/lfunc.c 237,239c237,240 < if (!iswhite(uv)) < gray2black(uv); /* closed upvalues cannot be gray */ < luaC_barrier(L, uv, slot); --- > if (!iswhite(uv)) { /* neither white nor dead? */ > nw2black(uv); /* closed upvalues cannot be gray */ > luaC_barrier(L, uv, slot); > } diff -Nr lua-5.4.0/src/lgc.c lua-5.4.1/src/lgc.c 63,64c63,64 < /* mask to erase all color bits (plus gen. related stuff) */ < #define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS | AGEBITS)) --- > /* mask with all color bits */ > #define maskcolors (bitmask(BLACKBIT) | WHITEBITS) 65a66,67 > /* mask with all GC bits */ > #define maskgcbits (maskcolors | AGEBITS) 67c69,70 < /* macro to erase all color bits then sets only the current white bit */ --- > > /* macro to erase all color bits then set only the current white bit */ 69c72,75 < (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) --- > (x->marked = cast_byte((x->marked & ~maskcolors) | luaC_white(g))) > > /* make an object gray (neither white nor black) */ > #define set2gray(x) resetbits(x->marked, maskcolors) 71,72c77,80 < #define white2gray(x) resetbits(x->marked, WHITEBITS) < #define black2gray(x) resetbit(x->marked, BLACKBIT) --- > > /* make an object black (coming from any color) */ > #define set2black(x) \ > (x->marked = cast_byte((x->marked & ~WHITEBITS) | bitmask(BLACKBIT))) 80,82d87 < #define checkconsistency(obj) \ < lua_longassert(!iscollectable(obj) || righttt(obj)) < 89c94 < #define markvalue(g,o) { checkconsistency(o); \ --- > #define markvalue(g,o) { checkliveness(g->mainthread,o); \ 138c143,144 < ** Link a collectable object 'o' with a known type into list pointed by 'p'. --- > ** Link a collectable object 'o' with a known type into the list 'p'. > ** (Must be a macro to access the 'gclist' field in different types.) 140c146,153 < #define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) --- > #define linkgclist(o,p) linkgclist_(obj2gco(o), &(o)->gclist, &(p)) > > static void linkgclist_ (GCObject *o, GCObject **pnext, GCObject **list) { > lua_assert(!isgray(o)); /* cannot be in a gray list */ > *pnext = *list; > *list = o; > set2gray(o); /* now it is */ > } 144c157 < ** Link a generic collectable object 'o' into list pointed by 'p'. --- > ** Link a generic collectable object 'o' into the list 'p'. 146c159 < #define linkobjgclist(o,p) (*getgclist(o) = (p), (p) = obj2gco(o)) --- > #define linkobjgclist(o,p) linkgclist_(obj2gco(o), getgclist(o), &(p)) 184,191c197,207 < ** barrier that moves collector forward, that is, mark the white object < ** 'v' being pointed by the black object 'o'. (If in sweep phase, clear < ** the black object to white [sweep it] to avoid other barrier calls for < ** this same object.) In the generational mode, 'v' must also become < ** old, if 'o' is old; however, it cannot be changed directly to OLD, < ** because it may still point to non-old objects. So, it is marked as < ** OLD0. In the next cycle it will become OLD1, and in the next it < ** will finally become OLD (regular old). --- > ** Barrier that moves collector forward, that is, marks the white object > ** 'v' being pointed by the black object 'o'. In the generational > ** mode, 'v' must also become old, if 'o' is old; however, it cannot > ** be changed directly to OLD, because it may still point to non-old > ** objects. So, it is marked as OLD0. In the next cycle it will become > ** OLD1, and in the next it will finally become OLD (regular old). By > ** then, any object it points to will also be old. If called in the > ** incremental sweep phase, it clears the black object to white (sweep > ** it) to avoid other barrier calls for this same object. (That cannot > ** be done is generational mode, as its sweep does not distinguish > ** whites from deads.) 205c221,222 < makewhite(g, o); /* mark main obj. as white to avoid other barriers */ --- > if (g->gckind == KGC_INC) /* incremental mode? */ > makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 217,221c234,240 < lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1)); < if (getage(o) != G_TOUCHED2) /* not already in gray list? */ < linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */ < black2gray(o); /* make object gray (again) */ < setage(o, G_TOUCHED1); /* touched in current cycle */ --- > lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); > if (getage(o) == G_TOUCHED2) /* already in gray list? */ > set2gray(o); /* make it gray to become touched1 */ > else /* link it in 'grayagain' and paint it gray */ > linkobjgclist(o, g->grayagain); > if (isold(o)) /* generational mode? */ > setage(o, G_TOUCHED1); /* touched in current cycle */ 228c247 < white2gray(o); /* they will be gray forever */ --- > set2gray(o); /* they will be gray forever */ 262,266c281,290 < ** Mark an object. Userdata, strings, and closed upvalues are visited < ** and turned black here. Other objects are marked gray and added < ** to appropriate list to be visited (and turned black) later. (Open < ** upvalues are already linked in 'headuv' list. They are kept gray < ** to avoid barriers, as their values will be revisited by the thread.) --- > ** Mark an object. Userdata with no user values, strings, and closed > ** upvalues are visited and turned black here. Open upvalues are > ** already indirectly linked through their respective threads in the > ** 'twups' list, so they don't go to the gray list; nevertheless, they > ** are kept gray to avoid barriers, as their values will be revisited > ** by the thread or by 'remarkupvals'. Other objects are added to the > ** gray list to be visited (and turned black) later. Both userdata and > ** upvalues can call this function recursively, but this recursion goes > ** for at most two levels: An upvalue cannot refer to another upvalue > ** (only closures can), and a userdata's metatable must be a table. 269d292 < white2gray(o); 273c296 < gray2black(o); --- > set2black(o); /* nothing to visit */ 278,279c301,304 < if (!upisopen(uv)) /* open upvalues are kept gray */ < gray2black(o); --- > if (upisopen(uv)) > set2gray(uv); /* open upvalues are kept gray */ > else > set2black(o); /* closed upvalues are visited here */ 287c312 < gray2black(o); /* nothing else to mark */ --- > set2black(o); /* nothing else to mark */ 294c319 < linkobjgclist(o, g->gray); --- > linkobjgclist(o, g->gray); /* to be visited later */ 327,330c352,360 < ** Mark all values stored in marked open upvalues from non-marked threads. < ** (Values from marked threads were already marked when traversing the < ** thread.) Remove from the list threads that no longer have upvalues and < ** not-marked threads. --- > ** For each non-marked thread, simulates a barrier between each open > ** upvalue and its value. (If the thread is collected, the value will be > ** assigned to the upvalue, but then it can be too late for the barrier > ** to act. The "barrier" does not need to check colors: A non-marked > ** thread must be young; upvalues cannot be older than their threads; so > ** any visited upvalue must be young too.) Also removes the thread from > ** the list, as it was already visited. Removes also threads with no > ** upvalues, as they have nothing to be checked. (If the thread gets an > ** upvalue later, it will be linked in the list again.) 335c365 < int work = 0; --- > int work = 0; /* estimate of how much work was done here */ 338,339c368 < lua_assert(!isblack(thread)); /* threads are never black */ < if (isgray(thread) && thread->openupval != NULL) --- > if (!iswhite(thread) && thread->openupval != NULL) 342a372 > lua_assert(!isold(thread) || thread->openupval == NULL); 345a376 > lua_assert(getage(uv) <= getage(thread)); 347c378,379 < if (!iswhite(uv)) /* upvalue already visited? */ --- > if (!iswhite(uv)) { /* upvalue already visited? */ > lua_assert(upisopen(uv) && isgray(uv)); 348a381 > } 355a389,394 > static void cleargraylists (global_State *g) { > g->gray = g->grayagain = NULL; > g->weak = g->allweak = g->ephemeron = NULL; > } > > 360,361c399 < g->gray = g->grayagain = NULL; < g->weak = g->allweak = g->ephemeron = NULL; --- > cleargraylists(g); 376a415,434 > > /* > ** Check whether object 'o' should be kept in the 'grayagain' list for > ** post-processing by 'correctgraylist'. (It could put all old objects > ** in the list and leave all the work to 'correctgraylist', but it is > ** more efficient to avoid adding elements that will be removed.) Only > ** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go > ** back to a gray list, but then it must become OLD. (That is what > ** 'correctgraylist' does when it finds a TOUCHED2 object.) > */ > static void genlink (global_State *g, GCObject *o) { > lua_assert(isblack(o)); > if (getage(o) == G_TOUCHED1) { /* touched in this cycle? */ > linkobjgclist(o, g->grayagain); /* link it back in 'grayagain' */ > } /* everything else do not need to be linked back */ > else if (getage(o) == G_TOUCHED2) > changeage(o, G_TOUCHED2, G_OLD); /* advance age */ > } > > 413,414c471,473 < ** (in the atomic phase). In generational mode, it (like all visited < ** tables) must be kept in some gray list for post-processing. --- > ** (in the atomic phase). In generational mode, some tables > ** must be kept in some gray list for post-processing; this is done > ** by 'genlink'. 453,454d511 < else if (g->gckind == KGC_GEN) < linkgclist(h, g->grayagain); /* keep it in some list */ 456c513 < gray2black(h); --- > genlink(g, obj2gco(h)); /* check whether collector still needs to see it */ 476,479c533 < if (g->gckind == KGC_GEN) { < linkgclist(h, g->grayagain); /* keep it in some gray list */ < black2gray(h); < } --- > genlink(g, obj2gco(h)); 491d544 < black2gray(h); /* keep table gray */ 510,513c563 < if (g->gckind == KGC_GEN) { < linkgclist(u, g->grayagain); /* keep it in some gray list */ < black2gray(u); < } --- > genlink(g, obj2gco(u)); 562,563c612,620 < ** and cleaning the rest of the stack in the final traversal. < ** That ensures that the entire stack have valid (non-dead) objects. --- > ** and cleaning the rest of the stack in the final traversal. That > ** ensures that the entire stack have valid (non-dead) objects. > ** Threads have no barriers. In gen. mode, old threads must be visited > ** at every cycle, because they might point to young objects. In inc. > ** mode, the thread can still be modified before the end of the cycle, > ** and therefore it must be visited again in the atomic phase. To ensure > ** these visits, threads must return to a gray list if they are not new > ** (which can only happen in generational mode) or if the traverse is in > ** the propagate phase (which can only happen in incremental mode). 567a625,626 > if (isold(th) || g->gcstate == GCSpropagate) > linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 593,594c652 < ** traverse one gray object, turning it to black (except for threads, < ** which are always gray). --- > ** traverse one gray object, turning it to black. 598c656 < gray2black(o); --- > nw2black(o); 606,611c664 < case LUA_VTHREAD: { < lua_State *th = gco2th(o); < linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ < black2gray(o); < return traversethread(g, th); < } --- > case LUA_VTHREAD: return traversethread(g, gco2th(o)); 641,642c694,697 < next = gco2t(w)->gclist; /* list is rebuilt during loop */ < if (traverseephemeron(g, gco2t(w), dir)) { /* marked some value? */ --- > Table *h = gco2t(w); > next = h->gclist; /* list is rebuilt during loop */ > nw2black(h); /* out of the list (for now) */ > if (traverseephemeron(g, h, dir)) { /* marked some value? */ 769c824 < curr->marked = cast_byte((marked & maskcolors) | white); --- > curr->marked = cast_byte((marked & ~maskgcbits) | white); 825a881,882 > else if (getage(o) == G_OLD1) > g->firstold1 = o; /* it is the first OLD1 object in the list */ 899,900c956,957 < ** (Note that objects after 'finobjold' cannot be white, so they < ** don't need to be traversed. In incremental mode, 'finobjold' is NULL, --- > ** (Note that objects after 'finobjold1' cannot be white, so they > ** don't need to be traversed. In incremental mode, 'finobjold1' is NULL, 907c964 < while ((curr = *p) != g->finobjold) { /* traverse all finalizable objects */ --- > while ((curr = *p) != g->finobjold1) { /* traverse all finalizable objects */ 923a981,1001 > ** If pointer 'p' points to 'o', move it to the next element. > */ > static void checkpointer (GCObject **p, GCObject *o) { > if (o == *p) > *p = o->next; > } > > > /* > ** Correct pointers to objects inside 'allgc' list when > ** object 'o' is being removed from the list. > */ > static void correctpointers (global_State *g, GCObject *o) { > checkpointer(&g->survival, o); > checkpointer(&g->old1, o); > checkpointer(&g->reallyold, o); > checkpointer(&g->firstold1, o); > } > > > /* 939,946c1017,1018 < else { /* correct pointers into 'allgc' list, if needed */ < if (o == g->survival) < g->survival = o->next; < if (o == g->old) < g->old = o->next; < if (o == g->reallyold) < g->reallyold = o->next; < } --- > else > correctpointers(g, o); 968,971d1039 < /* mask to erase all color bits, not changing gen-related stuff */ < #define maskgencolors (~(bitmask(BLACKBIT) | WHITEBITS)) < < 973,974c1041,1044 < ** Sweep a list of objects, deleting dead ones and turning < ** the non dead to old (without changing their colors). --- > ** Sweep a list of objects to enter generational mode. Deletes dead > ** objects and turns the non dead to old. All non-dead threads---which > ** are now old---must be in a gray list. Everything else is not in a > ** gray list. Open upvalues are also kept gray. 977a1048 > global_State *g = G(L); 980c1051 < lua_assert(isdead(G(L), curr)); --- > lua_assert(isdead(g, curr)); 985a1057,1064 > if (curr->tt == LUA_VTHREAD) { /* threads must be watched */ > lua_State *th = gco2th(curr); > linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ > } > else if (curr->tt == LUA_VUPVAL && upisopen(gco2upv(curr))) > set2gray(curr); /* open upvalues are always gray */ > else /* everything else is black */ > nw2black(curr); 997a1077,1080 > ** The ages of G_TOUCHED1 and G_TOUCHED2 objects cannot be advanced > ** here, because these old-generation objects are usually not swept > ** here. They will all be advanced in 'correctgraylist'. That function > ** will also remove objects turned white here from any gray list. 1000c1083 < GCObject *limit) { --- > GCObject *limit, GCObject **pfirstold1) { 1019,1021c1102,1110 < if (getage(curr) == G_NEW) < curr->marked = cast_byte((curr->marked & maskgencolors) | white); < setage(curr, nextage[getage(curr)]); --- > if (getage(curr) == G_NEW) { /* new objects go back to white */ > int marked = curr->marked & ~maskgcbits; /* erase GC bits */ > curr->marked = cast_byte(marked | G_SURVIVAL | white); > } > else { /* all other objects will be old, and so keep their color */ > setage(curr, nextage[getage(curr)]); > if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) > *pfirstold1 = curr; /* first OLD1 object in the list */ > } 1031c1120,1121 < ** age. --- > ** age. In incremental mode, all objects are 'new' all the time, > ** except for fixed strings (which are always old). 1036c1126 < p->marked = cast_byte((p->marked & maskcolors) | white); --- > p->marked = cast_byte((p->marked & ~maskgcbits) | white); 1041c1131,1132 < ** Correct a list of gray objects. --- > ** Correct a list of gray objects. Return pointer to where rest of the > ** list should be linked. 1044,1046c1135,1137 < ** For tables and userdata, advance 'touched1' to 'touched2'; 'touched2' < ** objects become regular old and are removed from the list. < ** For threads, just remove white ones from the list. --- > ** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; > ** Non-white threads also remain on the list; 'TOUCHED2' objects become > ** regular old; they and anything else are removed from the list. 1051,1081c1142,1160 < switch (curr->tt) { < case LUA_VTABLE: case LUA_VUSERDATA: { < GCObject **next = getgclist(curr); < if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ < lua_assert(isgray(curr)); < gray2black(curr); /* make it black, for next barrier */ < changeage(curr, G_TOUCHED1, G_TOUCHED2); < p = next; /* go to next element */ < } < else { /* not touched in this cycle */ < if (!iswhite(curr)) { /* not white? */ < lua_assert(isold(curr)); < if (getage(curr) == G_TOUCHED2) /* advance from G_TOUCHED2... */ < changeage(curr, G_TOUCHED2, G_OLD); /* ... to G_OLD */ < gray2black(curr); /* make it black */ < } < /* else, object is white: just remove it from this list */ < *p = *next; /* remove 'curr' from gray list */ < } < break; < } < case LUA_VTHREAD: { < lua_State *th = gco2th(curr); < lua_assert(!isblack(th)); < if (iswhite(th)) /* new object? */ < *p = th->gclist; /* remove from gray list */ < else /* old threads remain gray */ < p = &th->gclist; /* go to next element */ < break; < } < default: lua_assert(0); /* nothing more could be gray here */ --- > GCObject **next = getgclist(curr); > if (iswhite(curr)) > goto remove; /* remove all white objects */ > else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ > lua_assert(isgray(curr)); > nw2black(curr); /* make it black, for next barrier */ > changeage(curr, G_TOUCHED1, G_TOUCHED2); > goto remain; /* keep it in the list and go to next element */ > } > else if (curr->tt == LUA_VTHREAD) { > lua_assert(isgray(curr)); > goto remain; /* keep non-white threads on the list */ > } > else { /* everything else is removed */ > lua_assert(isold(curr)); /* young objects should be white here */ > if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ > changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ > nw2black(curr); /* make object black (to be removed) */ > goto remove; 1082a1162,1163 > remove: *p = *next; continue; > remain: p = next; continue; 1103c1184 < ** Mark 'OLD1' objects when starting a new young collection. --- > ** Mark black 'OLD1' objects when starting a new young collection. 1112,1113c1193,1194 < if (isblack(p)) { < black2gray(p); /* should be '2white', but gray works too */ --- > changeage(p, G_OLD1, G_OLD); /* now they are old */ > if (isblack(p)) 1115d1195 < } 1134,1138c1214,1216 < ** Does a young collection. First, mark 'OLD1' objects. (Only survival < ** and "recent old" lists can contain 'OLD1' objects. New lists cannot < ** contain 'OLD1' objects, at most 'OLD0' objects that were already < ** visited when marked old.) Then does the atomic step. Then, < ** sweep all lists and advance pointers. Finally, finish the collection. --- > ** Does a young collection. First, mark 'OLD1' objects. Then does the > ** atomic step. Then, sweep all lists and advance pointers. Finally, > ** finish the collection. 1141a1220 > GCObject *dummy; /* dummy out parameter to 'sweepgen' */ 1143c1222,1225 < markold(g, g->survival, g->reallyold); --- > if (g->firstold1) { /* are there regular OLD1 objects? */ > markold(g, g->firstold1, g->reallyold); /* mark them */ > g->firstold1 = NULL; /* no more OLD1 objects (for now) */ > } 1144a1227 > markold(g, g->tobefnz, NULL); 1148,1152c1231,1236 < psurvival = sweepgen(L, g, &g->allgc, g->survival); < /* sweep 'survival' and 'old' */ < sweepgen(L, g, psurvival, g->reallyold); < g->reallyold = g->old; < g->old = *psurvival; /* 'survival' survivals are old now */ --- > g->gcstate = GCSswpallgc; > psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); > /* sweep 'survival' */ > sweepgen(L, g, psurvival, g->old1, &g->firstold1); > g->reallyold = g->old1; > g->old1 = *psurvival; /* 'survival' survivals are old now */ 1156,1160c1240,1245 < psurvival = sweepgen(L, g, &g->finobj, g->finobjsur); < /* sweep 'survival' and 'old' */ < sweepgen(L, g, psurvival, g->finobjrold); < g->finobjrold = g->finobjold; < g->finobjold = *psurvival; /* 'survival' survivals are old now */ --- > dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */ > psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy); > /* sweep 'survival' */ > sweepgen(L, g, psurvival, g->finobjold1, &dummy); > g->finobjrold = g->finobjold1; > g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ 1163,1164c1248 < sweepgen(L, g, &g->tobefnz, NULL); < --- > sweepgen(L, g, &g->tobefnz, NULL, &dummy); 1168a1253,1258 > /* > ** Clears all gray lists, sweeps objects, and prepare sublists to enter > ** generational mode. The sweeps remove dead objects and turn all > ** surviving objects to old. Threads go back to 'grayagain'; everything > ** else is turned black (not in any gray list). > */ 1169a1260 > cleargraylists(g); 1170a1262 > g->gcstate = GCSswpallgc; 1173c1265,1266 < g->reallyold = g->old = g->survival = g->allgc; --- > g->reallyold = g->old1 = g->survival = g->allgc; > g->firstold1 = NULL; /* there are no OLD1 objects anywhere */ 1177c1270 < g->finobjrold = g->finobjold = g->finobjsur = g->finobj; --- > g->finobjrold = g->finobjold1 = g->finobjsur = g->finobj; 1190,1191c1283,1285 < ** to ensure that all threads and weak tables are in the gray lists. < ** Then, turn all objects into old and finishes the collection. --- > ** to ensure that all objects are correctly marked and weak tables > ** are cleared. Then, turn all objects into old and finishes the > ** collection. 1210c1304 < g->reallyold = g->old = g->survival = NULL; --- > g->reallyold = g->old1 = g->survival = NULL; 1213c1307 < g->finobjrold = g->finobjold = g->finobjsur = NULL; --- > g->finobjrold = g->finobjold1 = g->finobjsur = NULL; diff -Nr lua-5.4.0/src/lgc.h lua-5.4.1/src/lgc.h 15,24c15,24 < ** Collectable objects may have one of three colors: white, which < ** means the object is not marked; gray, which means the < ** object is marked, but its references may be not marked; and < ** black, which means that the object and all its references are marked. < ** The main invariant of the garbage collector, while marking objects, < ** is that a black object can never point to a white one. Moreover, < ** any gray object must be in a "gray list" (gray, grayagain, weak, < ** allweak, ephemeron) so that it can be visited again before finishing < ** the collection cycle. These lists have no meaning when the invariant < ** is not being enforced (e.g., sweep phase). --- > ** Collectable objects may have one of three colors: white, which means > ** the object is not marked; gray, which means the object is marked, but > ** its references may be not marked; and black, which means that the > ** object and all its references are marked. The main invariant of the > ** garbage collector, while marking objects, is that a black object can > ** never point to a white one. Moreover, any gray object must be in a > ** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it > ** can be visited again before finishing the collection cycle. (Open > ** upvalues are an exception to this rule.) These lists have no meaning > ** when the invariant is not being enforced (e.g., sweep phase). 72,73c72,73 < ** used for object "age" in generational mode. Last bit is free < ** to be used by respective objects. --- > ** used for object "age" in generational mode. Last bit is used > ** by tests. 79a80,81 > #define TESTBIT 7 > 97c99,100 < #define gray2black(x) l_setbit((x)->marked, BLACKBIT) --- > #define nw2black(x) \ > check_exp(!iswhite(x), l_setbit((x)->marked, BLACKBIT)) diff -Nr lua-5.4.0/src/liolib.c lua-5.4.1/src/liolib.c 54a55,60 > #if !defined(l_checkmodep) > /* By default, Lua accepts only "r" or "w" as mode */ > #define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') > #endif > > 281a288 > luaL_argcheck(L, l_checkmodep(mode), 2, "invalid mode"); diff -Nr lua-5.4.0/src/llex.c lua-5.4.1/src/llex.c 84d83 < lua_assert(token == cast_uchar(token)); diff -Nr lua-5.4.0/src/llex.h lua-5.4.1/src/llex.h 9a10,11 > #include > 14c16,20 < #define FIRST_RESERVED 257 --- > /* > ** Single-char tokens (terminal symbols) are represented by their own > ** numeric code. Other tokens start at the following value. > */ > #define FIRST_RESERVED (UCHAR_MAX + 1) diff -Nr lua-5.4.0/src/llimits.h lua-5.4.1/src/llimits.h 87c87,95 < /* internal assertions for in-house debugging */ --- > /* > ** Internal assertions for in-house debugging > */ > #if defined LUAI_ASSERT > #undef NDEBUG > #include > #define lua_assert(c) assert(c) > #endif > diff -Nr lua-5.4.0/src/lmem.c lua-5.4.1/src/lmem.c 25c25 < #if defined(HARDMEMTESTS) --- > #if defined(EMERGENCYGCTESTS) diff -Nr lua-5.4.0/src/lobject.c lua-5.4.1/src/lobject.c 218c218 < /* maximum length of a numeral */ --- > /* maximum length of a numeral to be converted to a number */ 222a223,227 > /* > ** Convert string 's' to a Lua number (put in 'result'). Return NULL on > ** fail or the address of the ending '\0' on success. ('mode' == 'x') > ** means a hexadecimal numeral. > */ 229c234 < return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ --- > return (*endptr == '\0') ? endptr : NULL; /* OK iff no trailing chars */ 234,239c239,240 < ** Convert string 's' to a Lua number (put in 'result'). Return NULL < ** on fail or the address of the ending '\0' on success. < ** 'pmode' points to (and 'mode' contains) special things in the string: < ** - 'x'/'X' means a hexadecimal numeral < ** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) < ** - '.' just optimizes the search for the common case (nothing special) --- > ** Convert string 's' to a Lua number (put in 'result') handling the > ** current locale. 244a246,249 > ** The variable 'mode' checks for special characters in the string: > ** - 'n' means 'inf' or 'nan' (which should be rejected) > ** - 'x' means a hexadecimal numeral > ** - '.' just optimizes the search for the common case (no special chars) 248c253 < const char *pmode = strpbrk(s, ".xXnN"); --- > const char *pmode = strpbrk(s, ".xXnN"); /* look for special chars */ 336,337c341,349 < /* maximum length of the conversion of a number to a string */ < #define MAXNUMBER2STR 50 --- > /* > ** Maximum length of the conversion of a number to a string. Must be > ** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. > ** (For a long long int, this is 19 digits plus a sign and a final '\0', > ** adding to 21. For a long double, it can go to a sign, 33 digits, > ** the dot, an exponent letter, an exponent sign, 5 exponent digits, > ** and a final '\0', adding to 43.) > */ > #define MAXNUMBER2STR 44 378c390 < #define BUFVFS 400 --- > #define BUFVFS 200 390,391c402,403 < ** Push given string to the stack, as part of the buffer. If the stack < ** is almost full, join all partial strings in the stack into one. --- > ** Push given string to the stack, as part of the buffer, and > ** join the partial strings in the stack into one. 398,401c410,411 < if (buff->pushed > 1 && L->top + 1 >= L->stack_last) { < luaV_concat(L, buff->pushed); /* join all partial results into one */ < buff->pushed = 1; < } --- > luaV_concat(L, buff->pushed); /* join partial results into one */ > buff->pushed = 1; 524,525c534 < if (buff.pushed > 1) < luaV_concat(L, buff.pushed); /* join all partial results */ --- > lua_assert(buff.pushed == 1); diff -Nr lua-5.4.0/src/lobject.h lua-5.4.1/src/lobject.h 99c99,100 < ** and it is not dead. --- > ** and it is not dead. The option 'L == NULL' allows other > ** macros using this one to be used where L is not available. 706,708c707,709 < #define isrealasize(t) (!((t)->marked & BITRAS)) < #define setrealasize(t) ((t)->marked &= cast_byte(~BITRAS)) < #define setnorealasize(t) ((t)->marked |= BITRAS) --- > #define isrealasize(t) (!((t)->flags & BITRAS)) > #define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS)) > #define setnorealasize(t) ((t)->flags |= BITRAS) diff -Nr lua-5.4.0/src/lstate.c lua-5.4.1/src/lstate.c 303a304 > L->oldpc = 0; 321c322 < global_State *g = G(L); --- > global_State *g; 323a325 > g = G(L); 397a400 > incnny(L); /* main thread is always non yieldable */ 413,414c416,417 < g->survival = g->old = g->reallyold = NULL; < g->finobjsur = g->finobjold = g->finobjrold = NULL; --- > g->firstold1 = g->survival = g->old1 = g->reallyold = NULL; > g->finobjsur = g->finobjold1 = g->finobjrold = NULL; 439d441 < L = G(L)->mainthread; /* only the main thread can be closed */ 440a443 > L = G(L)->mainthread; /* only the main thread can be closed */ diff -Nr lua-5.4.0/src/lstate.h lua-5.4.1/src/lstate.h 35c35 < ** 'old' -> 'reallyold': objects that became old in last collection; --- > ** 'old1' -> 'reallyold': objects that became old in last collection; 39,40c39,40 < ** 'finobjsur' -> 'finobjold': survived """"; < ** 'finobjold' -> 'finobjrold': just old """"; --- > ** 'finobjsur' -> 'finobjold1': survived """"; > ** 'finobjold1' -> 'finobjrold': just old """"; 41a42,57 > ** > ** All lists can contain elements older than their main ages, due > ** to 'luaC_checkfinalizer' and 'udata2finalize', which move > ** objects between the normal lists and the "marked for finalization" > ** lists. Moreover, barriers can age young objects in young lists as > ** OLD0, which then become OLD1. However, a list never contains > ** elements younger than their main ages. > ** > ** The generational collector also uses a pointer 'firstold1', which > ** points to the first OLD1 object in the list. It is used to optimize > ** 'markold'. (Potentially OLD1 objects can be anywhere between 'allgc' > ** and 'reallyold', but often the list has no OLD1 objects or they are > ** after 'old1'.) Note the difference between it and 'old1': > ** 'firstold1': no OLD1 objects before this point; there can be all > ** ages after it. > ** 'old1': no objects younger than OLD1 after this point. 50c66 < ** must be gray: --- > ** must be gray (with two exceptions explained below): 60a77,84 > ** > ** The exceptions to that "gray rule" are: > ** - TOUCHED2 objects in generational mode stay in a gray list (because > ** they must be visited again at the end of the cycle), but they are > ** marked black because assignments to them must activate barriers (to > ** move them back to TOUCHED1). > ** - Open upvales are kept gray to avoid barriers, but they stay out > ** of gray lists. (They don't even have a 'gclist' field.) 260,261c284,286 < GCObject *old; /* start of old objects */ < GCObject *reallyold; /* old objects with more than one cycle */ --- > GCObject *old1; /* start of old1 objects */ > GCObject *reallyold; /* objects more than one cycle old ("really old") */ > GCObject *firstold1; /* first OLD1 object in the list (if any) */ 263c288 < GCObject *finobjold; /* list of old objects with finalizers */ --- > GCObject *finobjold1; /* list of old1 objects with finalizers */ 289d313 < const Instruction *oldpc; /* last pc traced */ 299a324 > int oldpc; /* last pc traced */ 311a337,342 > ** ISO C99, 6.5.2.3 p.5: > ** "if a union contains several structures that share a common initial > ** sequence [...], and if the union object currently contains one > ** of these structures, it is permitted to inspect the common initial > ** part of any of them anywhere that a declaration of the complete type > ** of the union is visible." 324a356,360 > /* > ** ISO C99, 6.7.2.1 p.14: > ** "A pointer to a union object, suitably converted, points to each of > ** its members [...], and vice versa." > */ diff -Nr lua-5.4.0/src/ltable.c lua-5.4.1/src/ltable.c 586c586 < t->flags = cast_byte(~0); --- > t->flags = cast_byte(maskflags); /* table has no metamethod fields */ diff -Nr lua-5.4.0/src/ltable.h lua-5.4.1/src/ltable.h 18c18,23 < #define invalidateTMcache(t) ((t)->flags = 0) --- > /* > ** Clear all bits of fast-access metamethods, which means that the table > ** may have any of these metamethods. (First access that fails after the > ** clearing will set the bit again.) > */ > #define invalidateTMcache(t) ((t)->flags &= ~maskflags) diff -Nr lua-5.4.0/src/ltm.c lua-5.4.1/src/ltm.c 243c243 < checkstackGC(L, p->maxstacksize + 1); --- > luaD_checkstack(L, p->maxstacksize + 1); 262c262 < checkstackp(L, nextra, where); /* ensure stack space */ --- > checkstackGCp(L, nextra, where); /* ensure stack space */ diff -Nr lua-5.4.0/src/ltm.h lua-5.4.1/src/ltm.h 48a49,57 > ** Mask with 1 in all fast-access methods. A 1 in any of these bits > ** in the flag of a (meta)table means the metatable does not have the > ** corresponding metamethod field. (Bit 7 of the flag is used for > ** 'isrealasize'.) > */ > #define maskflags (~(~0u << (TM_EQ + 1))) > > > /* diff -Nr lua-5.4.0/src/lua.h lua-5.4.1/src/lua.h 21c21 < #define LUA_VERSION_RELEASE "0" --- > #define LUA_VERSION_RELEASE "1" diff -Nr lua-5.4.0/src/lundump.c lua-5.4.1/src/lundump.c 122a123,124 > setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ > luaD_inctop(L); 123a126 > L->top--; /* pop string */ 202a206,211 > /* > ** Load the upvalues for a function. The names must be filled first, > ** because the filling of the other fields can raise read errors and > ** the creation of the error message can call an emergency collection; > ** in that case all prototypes must be consistent for the GC. > */ 208c217 < for (i = 0; i < n; i++) { --- > for (i = 0; i < n; i++) /* make array valid for GC */ 209a219 > for (i = 0; i < n; i++) { /* following calls can raise errors */ diff -Nr lua-5.4.0/src/lvm.c lua-5.4.1/src/lvm.c 637c637,638 < lua_assert(total >= 2); --- > if (total == 1) > return; /* "all" values already concatenated */ 843,846c844,845 < if (total > 1) { /* are there elements to concat? */ < L->top = top - 1; /* top is one after last element (at top-2) */ < luaV_concat(L, total); /* concat them (may yield again) */ < } --- > L->top = top - 1; /* top is one after last element (at top-2) */ > luaV_concat(L, total); /* concat them (may yield again) */ 1105c1104 < --- > /* 'c' is the limit of live values in the stack */ 1107c1106 < { luaC_condGC(L, L->top = (c), /* limit of live values */ \ --- > { luaC_condGC(L, (savepc(L), L->top = (c)), \ 1638c1637 < checkstackp(L, 1, ra); --- > checkstackGCp(L, 1, ra); 1795,1796c1794 < luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p); < updatetrap(ci); --- > ProtectNT(luaT_adjustvarargs(L, GETARG_A(i), ci, cl->p)); 1799c1797 < L->oldpc = pc + 1; /* next opcode will be seen as a "new" line */ --- > L->oldpc = 1; /* next opcode will be seen as a "new" line */