diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-31 13:51:38 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-31 13:51:38 -0300 |
commit | fa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd (patch) | |
tree | 5c5f4f75e46a0ce1e82eca4395457627895c665c | |
parent | d1e677c52be3b107a7a29fdc482158f6d9251e79 (diff) | |
download | lua-fa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd.tar.gz lua-fa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd.tar.bz2 lua-fa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd.zip |
Main thread is a regular field of global_State
They were already allocated as a single block, so there is no need
for the global_State to point to its main thread.
-rw-r--r-- | lapi.c | 2 | ||||
-rw-r--r-- | ldo.c | 9 | ||||
-rw-r--r-- | lgc.c | 8 | ||||
-rw-r--r-- | lstate.c | 39 | ||||
-rw-r--r-- | lstate.h | 78 | ||||
-rw-r--r-- | ltests.c | 4 |
6 files changed, 65 insertions, 75 deletions
@@ -655,7 +655,7 @@ LUA_API int lua_pushthread (lua_State *L) { | |||
655 | setthvalue(L, s2v(L->top.p), L); | 655 | setthvalue(L, s2v(L->top.p), L); |
656 | api_incr_top(L); | 656 | api_incr_top(L); |
657 | lua_unlock(L); | 657 | lua_unlock(L); |
658 | return (G(L)->mainthread == L); | 658 | return (mainthread(G(L)) == L); |
659 | } | 659 | } |
660 | 660 | ||
661 | 661 | ||
@@ -132,11 +132,12 @@ l_noret luaD_throw (lua_State *L, TStatus errcode) { | |||
132 | } | 132 | } |
133 | else { /* thread has no error handler */ | 133 | else { /* thread has no error handler */ |
134 | global_State *g = G(L); | 134 | global_State *g = G(L); |
135 | lua_State *mainth = mainthread(g); | ||
135 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ | 136 | errcode = luaE_resetthread(L, errcode); /* close all upvalues */ |
136 | L->status = errcode; | 137 | L->status = errcode; |
137 | if (g->mainthread->errorJmp) { /* main thread has a handler? */ | 138 | if (mainth->errorJmp) { /* main thread has a handler? */ |
138 | setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ | 139 | setobjs2s(L, mainth->top.p++, L->top.p - 1); /* copy error obj. */ |
139 | luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ | 140 | luaD_throw(mainth, errcode); /* re-throw in main thread */ |
140 | } | 141 | } |
141 | else { /* no handler at all; abort */ | 142 | else { /* no handler at all; abort */ |
142 | if (g->panic) { /* panic function? */ | 143 | if (g->panic) { /* panic function? */ |
@@ -961,7 +962,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
961 | ci = L->ci; | 962 | ci = L->ci; |
962 | api_checkpop(L, nresults); | 963 | api_checkpop(L, nresults); |
963 | if (l_unlikely(!yieldable(L))) { | 964 | if (l_unlikely(!yieldable(L))) { |
964 | if (L != G(L)->mainthread) | 965 | if (L != mainthread(G(L))) |
965 | luaG_runerror(L, "attempt to yield across a C-call boundary"); | 966 | luaG_runerror(L, "attempt to yield across a C-call boundary"); |
966 | else | 967 | else |
967 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 968 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
@@ -78,7 +78,7 @@ | |||
78 | ((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL) | 78 | ((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL) |
79 | 79 | ||
80 | 80 | ||
81 | #define markvalue(g,o) { checkliveness(g->mainthread,o); \ | 81 | #define markvalue(g,o) { checkliveness(mainthread(g),o); \ |
82 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } | 82 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
83 | 83 | ||
84 | #define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } | 84 | #define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } |
@@ -441,7 +441,7 @@ static void cleargraylists (global_State *g) { | |||
441 | static void restartcollection (global_State *g) { | 441 | static void restartcollection (global_State *g) { |
442 | cleargraylists(g); | 442 | cleargraylists(g); |
443 | g->GCmarked = 0; | 443 | g->GCmarked = 0; |
444 | markobject(g, g->mainthread); | 444 | markobject(g, mainthread(g)); |
445 | markvalue(g, &g->l_registry); | 445 | markvalue(g, &g->l_registry); |
446 | markmt(g); | 446 | markmt(g); |
447 | markbeingfnz(g); /* mark any finalizing object left from previous cycle */ | 447 | markbeingfnz(g); /* mark any finalizing object left from previous cycle */ |
@@ -1513,7 +1513,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
1513 | separatetobefnz(g, 1); /* separate all objects with finalizers */ | 1513 | separatetobefnz(g, 1); /* separate all objects with finalizers */ |
1514 | lua_assert(g->finobj == NULL); | 1514 | lua_assert(g->finobj == NULL); |
1515 | callallpendingfinalizers(L); | 1515 | callallpendingfinalizers(L); |
1516 | deletelist(L, g->allgc, obj2gco(g->mainthread)); | 1516 | deletelist(L, g->allgc, obj2gco(mainthread(g))); |
1517 | lua_assert(g->finobj == NULL); /* no new finalizers */ | 1517 | lua_assert(g->finobj == NULL); /* no new finalizers */ |
1518 | deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ | 1518 | deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ |
1519 | lua_assert(g->strt.nuse == 0); | 1519 | lua_assert(g->strt.nuse == 0); |
@@ -1526,7 +1526,7 @@ static void atomic (lua_State *L) { | |||
1526 | GCObject *grayagain = g->grayagain; /* save original list */ | 1526 | GCObject *grayagain = g->grayagain; /* save original list */ |
1527 | g->grayagain = NULL; | 1527 | g->grayagain = NULL; |
1528 | lua_assert(g->ephemeron == NULL && g->weak == NULL); | 1528 | lua_assert(g->ephemeron == NULL && g->weak == NULL); |
1529 | lua_assert(!iswhite(g->mainthread)); | 1529 | lua_assert(!iswhite(mainthread(g))); |
1530 | g->gcstate = GCSatomic; | 1530 | g->gcstate = GCSatomic; |
1531 | markobject(g, L); /* mark running thread */ | 1531 | markobject(g, L); /* mark running thread */ |
1532 | /* registry and global metatables may be changed by API */ | 1532 | /* registry and global metatables may be changed by API */ |
@@ -29,25 +29,6 @@ | |||
29 | 29 | ||
30 | 30 | ||
31 | 31 | ||
32 | /* | ||
33 | ** thread state + extra space | ||
34 | */ | ||
35 | typedef struct LX { | ||
36 | lu_byte extra_[LUA_EXTRASPACE]; | ||
37 | lua_State l; | ||
38 | } LX; | ||
39 | |||
40 | |||
41 | /* | ||
42 | ** Main thread combines a thread state and the global state | ||
43 | */ | ||
44 | typedef struct LG { | ||
45 | LX l; | ||
46 | global_State g; | ||
47 | } LG; | ||
48 | |||
49 | |||
50 | |||
51 | #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) | 32 | #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) |
52 | 33 | ||
53 | 34 | ||
@@ -278,8 +259,8 @@ static void close_state (lua_State *L) { | |||
278 | } | 259 | } |
279 | luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size)); | 260 | luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size)); |
280 | freestack(L); | 261 | freestack(L); |
281 | lua_assert(gettotalbytes(g) == sizeof(LG)); | 262 | lua_assert(gettotalbytes(g) == sizeof(global_State)); |
282 | (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ | 263 | (*g->frealloc)(g->ud, g, sizeof(global_State), 0); /* free main block */ |
283 | } | 264 | } |
284 | 265 | ||
285 | 266 | ||
@@ -301,7 +282,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
301 | L1->hook = L->hook; | 282 | L1->hook = L->hook; |
302 | resethookcount(L1); | 283 | resethookcount(L1); |
303 | /* initialize L1 extra space */ | 284 | /* initialize L1 extra space */ |
304 | memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), | 285 | memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)), |
305 | LUA_EXTRASPACE); | 286 | LUA_EXTRASPACE); |
306 | luai_userstatethread(L, L1); | 287 | luai_userstatethread(L, L1); |
307 | stack_init(L1, L); /* init stack */ | 288 | stack_init(L1, L); /* init stack */ |
@@ -352,11 +333,10 @@ LUA_API int lua_closethread (lua_State *L, lua_State *from) { | |||
352 | LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { | 333 | LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { |
353 | int i; | 334 | int i; |
354 | lua_State *L; | 335 | lua_State *L; |
355 | global_State *g; | 336 | global_State *g = cast(global_State*, |
356 | LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); | 337 | (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State))); |
357 | if (l == NULL) return NULL; | 338 | if (g == NULL) return NULL; |
358 | L = &l->l.l; | 339 | L = &g->mainth.l; |
359 | g = &l->g; | ||
360 | L->tt = LUA_VTHREAD; | 340 | L->tt = LUA_VTHREAD; |
361 | g->currentwhite = bitmask(WHITE0BIT); | 341 | g->currentwhite = bitmask(WHITE0BIT); |
362 | L->marked = luaC_white(g); | 342 | L->marked = luaC_white(g); |
@@ -368,7 +348,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { | |||
368 | g->ud = ud; | 348 | g->ud = ud; |
369 | g->warnf = NULL; | 349 | g->warnf = NULL; |
370 | g->ud_warn = NULL; | 350 | g->ud_warn = NULL; |
371 | g->mainthread = L; | ||
372 | g->seed = seed; | 351 | g->seed = seed; |
373 | g->gcstp = GCSTPGC; /* no GC while building state */ | 352 | g->gcstp = GCSTPGC; /* no GC while building state */ |
374 | g->strt.size = g->strt.nuse = 0; | 353 | g->strt.size = g->strt.nuse = 0; |
@@ -386,7 +365,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { | |||
386 | g->gray = g->grayagain = NULL; | 365 | g->gray = g->grayagain = NULL; |
387 | g->weak = g->ephemeron = g->allweak = NULL; | 366 | g->weak = g->ephemeron = g->allweak = NULL; |
388 | g->twups = NULL; | 367 | g->twups = NULL; |
389 | g->GCtotalbytes = sizeof(LG); | 368 | g->GCtotalbytes = sizeof(global_State); |
390 | g->GCmarked = 0; | 369 | g->GCmarked = 0; |
391 | g->GCdebt = 0; | 370 | g->GCdebt = 0; |
392 | setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ | 371 | setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ |
@@ -408,7 +387,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { | |||
408 | 387 | ||
409 | LUA_API void lua_close (lua_State *L) { | 388 | LUA_API void lua_close (lua_State *L) { |
410 | lua_lock(L); | 389 | lua_lock(L); |
411 | L = G(L)->mainthread; /* only the main thread can be closed */ | 390 | L = mainthread(G(L)); /* only the main thread can be closed */ |
412 | close_state(L); | 391 | close_state(L); |
413 | } | 392 | } |
414 | 393 | ||
@@ -284,6 +284,48 @@ struct CallInfo { | |||
284 | 284 | ||
285 | 285 | ||
286 | /* | 286 | /* |
287 | ** 'per thread' state | ||
288 | */ | ||
289 | struct lua_State { | ||
290 | CommonHeader; | ||
291 | lu_byte allowhook; | ||
292 | TStatus status; | ||
293 | unsigned short nci; /* number of items in 'ci' list */ | ||
294 | StkIdRel top; /* first free slot in the stack */ | ||
295 | struct global_State *l_G; | ||
296 | CallInfo *ci; /* call info for current function */ | ||
297 | StkIdRel stack_last; /* end of stack (last element + 1) */ | ||
298 | StkIdRel stack; /* stack base */ | ||
299 | UpVal *openupval; /* list of open upvalues in this stack */ | ||
300 | StkIdRel tbclist; /* list of to-be-closed variables */ | ||
301 | GCObject *gclist; | ||
302 | struct lua_State *twups; /* list of threads with open upvalues */ | ||
303 | struct lua_longjmp *errorJmp; /* current error recover point */ | ||
304 | CallInfo base_ci; /* CallInfo for first level (C host) */ | ||
305 | volatile lua_Hook hook; | ||
306 | ptrdiff_t errfunc; /* current error handling function (stack index) */ | ||
307 | l_uint32 nCcalls; /* number of nested non-yieldable or C calls */ | ||
308 | int oldpc; /* last pc traced */ | ||
309 | int basehookcount; | ||
310 | int hookcount; | ||
311 | volatile l_signalT hookmask; | ||
312 | struct { /* info about transferred values (for call/return hooks) */ | ||
313 | int ftransfer; /* offset of first value transferred */ | ||
314 | int ntransfer; /* number of values transferred */ | ||
315 | } transferinfo; | ||
316 | }; | ||
317 | |||
318 | |||
319 | /* | ||
320 | ** thread state + extra space | ||
321 | */ | ||
322 | typedef struct LX { | ||
323 | lu_byte extra_[LUA_EXTRASPACE]; | ||
324 | lua_State l; | ||
325 | } LX; | ||
326 | |||
327 | |||
328 | /* | ||
287 | ** 'global state', shared by all threads of this state | 329 | ** 'global state', shared by all threads of this state |
288 | */ | 330 | */ |
289 | typedef struct global_State { | 331 | typedef struct global_State { |
@@ -324,50 +366,18 @@ typedef struct global_State { | |||
324 | GCObject *finobjrold; /* list of really old objects with finalizers */ | 366 | GCObject *finobjrold; /* list of really old objects with finalizers */ |
325 | struct lua_State *twups; /* list of threads with open upvalues */ | 367 | struct lua_State *twups; /* list of threads with open upvalues */ |
326 | lua_CFunction panic; /* to be called in unprotected errors */ | 368 | lua_CFunction panic; /* to be called in unprotected errors */ |
327 | struct lua_State *mainthread; | ||
328 | TString *memerrmsg; /* message for memory-allocation errors */ | 369 | TString *memerrmsg; /* message for memory-allocation errors */ |
329 | TString *tmname[TM_N]; /* array with tag-method names */ | 370 | TString *tmname[TM_N]; /* array with tag-method names */ |
330 | struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ | 371 | struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ |
331 | TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ | 372 | TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ |
332 | lua_WarnFunction warnf; /* warning function */ | 373 | lua_WarnFunction warnf; /* warning function */ |
333 | void *ud_warn; /* auxiliary data to 'warnf' */ | 374 | void *ud_warn; /* auxiliary data to 'warnf' */ |
375 | LX mainth; /* main thread of this state */ | ||
334 | } global_State; | 376 | } global_State; |
335 | 377 | ||
336 | 378 | ||
337 | /* | ||
338 | ** 'per thread' state | ||
339 | */ | ||
340 | struct lua_State { | ||
341 | CommonHeader; | ||
342 | lu_byte allowhook; | ||
343 | TStatus status; | ||
344 | unsigned short nci; /* number of items in 'ci' list */ | ||
345 | StkIdRel top; /* first free slot in the stack */ | ||
346 | global_State *l_G; | ||
347 | CallInfo *ci; /* call info for current function */ | ||
348 | StkIdRel stack_last; /* end of stack (last element + 1) */ | ||
349 | StkIdRel stack; /* stack base */ | ||
350 | UpVal *openupval; /* list of open upvalues in this stack */ | ||
351 | StkIdRel tbclist; /* list of to-be-closed variables */ | ||
352 | GCObject *gclist; | ||
353 | struct lua_State *twups; /* list of threads with open upvalues */ | ||
354 | struct lua_longjmp *errorJmp; /* current error recover point */ | ||
355 | CallInfo base_ci; /* CallInfo for first level (C host) */ | ||
356 | volatile lua_Hook hook; | ||
357 | ptrdiff_t errfunc; /* current error handling function (stack index) */ | ||
358 | l_uint32 nCcalls; /* number of nested non-yieldable or C calls */ | ||
359 | int oldpc; /* last pc traced */ | ||
360 | int basehookcount; | ||
361 | int hookcount; | ||
362 | volatile l_signalT hookmask; | ||
363 | struct { /* info about transferred values (for call/return hooks) */ | ||
364 | int ftransfer; /* offset of first value transferred */ | ||
365 | int ntransfer; /* number of values transferred */ | ||
366 | } transferinfo; | ||
367 | }; | ||
368 | |||
369 | |||
370 | #define G(L) (L->l_G) | 379 | #define G(L) (L->l_G) |
380 | #define mainthread(G) (&(G)->mainth.l) | ||
371 | 381 | ||
372 | /* | 382 | /* |
373 | ** 'g->nilvalue' being a nil value flags that the state was completely | 383 | ** 'g->nilvalue' being a nil value flags that the state was completely |
@@ -408,7 +408,7 @@ static void checktable (global_State *g, Table *h) { | |||
408 | for (n = gnode(h, 0); n < limit; n++) { | 408 | for (n = gnode(h, 0); n < limit; n++) { |
409 | if (!isempty(gval(n))) { | 409 | if (!isempty(gval(n))) { |
410 | TValue k; | 410 | TValue k; |
411 | getnodekey(g->mainthread, &k, n); | 411 | getnodekey(mainthread(g), &k, n); |
412 | assert(!keyisnil(n)); | 412 | assert(!keyisnil(n)); |
413 | checkvalref(g, hgc, &k); | 413 | checkvalref(g, hgc, &k); |
414 | checkvalref(g, hgc, gval(n)); | 414 | checkvalref(g, hgc, gval(n)); |
@@ -672,7 +672,7 @@ int lua_checkmemory (lua_State *L) { | |||
672 | l_mem totalin; /* total of objects that are in gray lists */ | 672 | l_mem totalin; /* total of objects that are in gray lists */ |
673 | l_mem totalshould; /* total of objects that should be in gray lists */ | 673 | l_mem totalshould; /* total of objects that should be in gray lists */ |
674 | if (keepinvariant(g)) { | 674 | if (keepinvariant(g)) { |
675 | assert(!iswhite(g->mainthread)); | 675 | assert(!iswhite(mainthread(g))); |
676 | assert(!iswhite(gcvalue(&g->l_registry))); | 676 | assert(!iswhite(gcvalue(&g->l_registry))); |
677 | } | 677 | } |
678 | assert(!isdead(g, gcvalue(&g->l_registry))); | 678 | assert(!isdead(g, gcvalue(&g->l_registry))); |