aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-31 13:51:38 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-31 13:51:38 -0300
commitfa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd (patch)
tree5c5f4f75e46a0ce1e82eca4395457627895c665c
parentd1e677c52be3b107a7a29fdc482158f6d9251e79 (diff)
downloadlua-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.c2
-rw-r--r--ldo.c9
-rw-r--r--lgc.c8
-rw-r--r--lstate.c39
-rw-r--r--lstate.h78
-rw-r--r--ltests.c4
6 files changed, 65 insertions, 75 deletions
diff --git a/lapi.c b/lapi.c
index b3062072..a5e94507 100644
--- a/lapi.c
+++ b/lapi.c
@@ -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
diff --git a/ldo.c b/ldo.c
index 3f9c8b7d..65252e07 100644
--- a/ldo.c
+++ b/ldo.c
@@ -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");
diff --git a/lgc.c b/lgc.c
index 8a82b6d9..e8533052 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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) {
441static void restartcollection (global_State *g) { 441static 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 */
diff --git a/lstate.c b/lstate.c
index 18ab4900..69ddef40 100644
--- a/lstate.c
+++ b/lstate.c
@@ -29,25 +29,6 @@
29 29
30 30
31 31
32/*
33** thread state + extra space
34*/
35typedef 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*/
44typedef 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) {
352LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { 333LUA_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
409LUA_API void lua_close (lua_State *L) { 388LUA_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
diff --git a/lstate.h b/lstate.h
index b47a4e9b..050fc35f 100644
--- a/lstate.h
+++ b/lstate.h
@@ -284,6 +284,48 @@ struct CallInfo {
284 284
285 285
286/* 286/*
287** 'per thread' state
288*/
289struct 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*/
322typedef 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*/
289typedef struct global_State { 331typedef 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*/
340struct 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
diff --git a/ltests.c b/ltests.c
index 6b5dc276..f4855fea 100644
--- a/ltests.c
+++ b/ltests.c
@@ -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)));