commit fa1382b5cd504bdfc5fc3f5c447ed09a4c9804fd
parent d1e677c52be3b107a7a29fdc482158f6d9251e79
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Fri, 31 Jan 2025 13:51:11 -0300
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.
Diffstat:
M | lapi.c | | | 2 | +- |
M | ldo.c | | | 9 | +++++---- |
M | lgc.c | | | 8 | ++++---- |
M | lstate.c | | | 39 | +++++++++------------------------------ |
M | lstate.h | | | 78 | ++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
M | ltests.c | | | 4 | ++-- |
6 files changed, 65 insertions(+), 75 deletions(-)
diff --git a/lapi.c b/lapi.c
@@ -655,7 +655,7 @@ LUA_API int lua_pushthread (lua_State *L) {
setthvalue(L, s2v(L->top.p), L);
api_incr_top(L);
lua_unlock(L);
- return (G(L)->mainthread == L);
+ return (mainthread(G(L)) == L);
}
diff --git a/ldo.c b/ldo.c
@@ -132,11 +132,12 @@ l_noret luaD_throw (lua_State *L, TStatus errcode) {
}
else { /* thread has no error handler */
global_State *g = G(L);
+ lua_State *mainth = mainthread(g);
errcode = luaE_resetthread(L, errcode); /* close all upvalues */
L->status = errcode;
- if (g->mainthread->errorJmp) { /* main thread has a handler? */
- setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */
- luaD_throw(g->mainthread, errcode); /* re-throw in main thread */
+ if (mainth->errorJmp) { /* main thread has a handler? */
+ setobjs2s(L, mainth->top.p++, L->top.p - 1); /* copy error obj. */
+ luaD_throw(mainth, errcode); /* re-throw in main thread */
}
else { /* no handler at all; abort */
if (g->panic) { /* panic function? */
@@ -961,7 +962,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx,
ci = L->ci;
api_checkpop(L, nresults);
if (l_unlikely(!yieldable(L))) {
- if (L != G(L)->mainthread)
+ if (L != mainthread(G(L)))
luaG_runerror(L, "attempt to yield across a C-call boundary");
else
luaG_runerror(L, "attempt to yield from outside a coroutine");
diff --git a/lgc.c b/lgc.c
@@ -78,7 +78,7 @@
((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL)
-#define markvalue(g,o) { checkliveness(g->mainthread,o); \
+#define markvalue(g,o) { checkliveness(mainthread(g),o); \
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
#define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); }
@@ -441,7 +441,7 @@ static void cleargraylists (global_State *g) {
static void restartcollection (global_State *g) {
cleargraylists(g);
g->GCmarked = 0;
- markobject(g, g->mainthread);
+ markobject(g, mainthread(g));
markvalue(g, &g->l_registry);
markmt(g);
markbeingfnz(g); /* mark any finalizing object left from previous cycle */
@@ -1513,7 +1513,7 @@ void luaC_freeallobjects (lua_State *L) {
separatetobefnz(g, 1); /* separate all objects with finalizers */
lua_assert(g->finobj == NULL);
callallpendingfinalizers(L);
- deletelist(L, g->allgc, obj2gco(g->mainthread));
+ deletelist(L, g->allgc, obj2gco(mainthread(g)));
lua_assert(g->finobj == NULL); /* no new finalizers */
deletelist(L, g->fixedgc, NULL); /* collect fixed objects */
lua_assert(g->strt.nuse == 0);
@@ -1526,7 +1526,7 @@ static void atomic (lua_State *L) {
GCObject *grayagain = g->grayagain; /* save original list */
g->grayagain = NULL;
lua_assert(g->ephemeron == NULL && g->weak == NULL);
- lua_assert(!iswhite(g->mainthread));
+ lua_assert(!iswhite(mainthread(g)));
g->gcstate = GCSatomic;
markobject(g, L); /* mark running thread */
/* registry and global metatables may be changed by API */
diff --git a/lstate.c b/lstate.c
@@ -29,25 +29,6 @@
-/*
-** thread state + extra space
-*/
-typedef struct LX {
- lu_byte extra_[LUA_EXTRASPACE];
- lua_State l;
-} LX;
-
-
-/*
-** Main thread combines a thread state and the global state
-*/
-typedef struct LG {
- LX l;
- global_State g;
-} LG;
-
-
-
#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
@@ -278,8 +259,8 @@ static void close_state (lua_State *L) {
}
luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size));
freestack(L);
- lua_assert(gettotalbytes(g) == sizeof(LG));
- (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */
+ lua_assert(gettotalbytes(g) == sizeof(global_State));
+ (*g->frealloc)(g->ud, g, sizeof(global_State), 0); /* free main block */
}
@@ -301,7 +282,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) {
L1->hook = L->hook;
resethookcount(L1);
/* initialize L1 extra space */
- memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread),
+ memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)),
LUA_EXTRASPACE);
luai_userstatethread(L, L1);
stack_init(L1, L); /* init stack */
@@ -352,11 +333,10 @@ LUA_API int lua_closethread (lua_State *L, lua_State *from) {
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
int i;
lua_State *L;
- global_State *g;
- LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG)));
- if (l == NULL) return NULL;
- L = &l->l.l;
- g = &l->g;
+ global_State *g = cast(global_State*,
+ (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State)));
+ if (g == NULL) return NULL;
+ L = &g->mainth.l;
L->tt = LUA_VTHREAD;
g->currentwhite = bitmask(WHITE0BIT);
L->marked = luaC_white(g);
@@ -368,7 +348,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
g->ud = ud;
g->warnf = NULL;
g->ud_warn = NULL;
- g->mainthread = L;
g->seed = seed;
g->gcstp = GCSTPGC; /* no GC while building state */
g->strt.size = g->strt.nuse = 0;
@@ -386,7 +365,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
g->gray = g->grayagain = NULL;
g->weak = g->ephemeron = g->allweak = NULL;
g->twups = NULL;
- g->GCtotalbytes = sizeof(LG);
+ g->GCtotalbytes = sizeof(global_State);
g->GCmarked = 0;
g->GCdebt = 0;
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) {
LUA_API void lua_close (lua_State *L) {
lua_lock(L);
- L = G(L)->mainthread; /* only the main thread can be closed */
+ L = mainthread(G(L)); /* only the main thread can be closed */
close_state(L);
}
diff --git a/lstate.h b/lstate.h
@@ -284,6 +284,48 @@ struct CallInfo {
/*
+** 'per thread' state
+*/
+struct lua_State {
+ CommonHeader;
+ lu_byte allowhook;
+ TStatus status;
+ unsigned short nci; /* number of items in 'ci' list */
+ StkIdRel top; /* first free slot in the stack */
+ struct global_State *l_G;
+ CallInfo *ci; /* call info for current function */
+ StkIdRel stack_last; /* end of stack (last element + 1) */
+ StkIdRel stack; /* stack base */
+ UpVal *openupval; /* list of open upvalues in this stack */
+ StkIdRel tbclist; /* list of to-be-closed variables */
+ GCObject *gclist;
+ struct lua_State *twups; /* list of threads with open upvalues */
+ struct lua_longjmp *errorJmp; /* current error recover point */
+ CallInfo base_ci; /* CallInfo for first level (C host) */
+ volatile lua_Hook hook;
+ ptrdiff_t errfunc; /* current error handling function (stack index) */
+ l_uint32 nCcalls; /* number of nested non-yieldable or C calls */
+ int oldpc; /* last pc traced */
+ int basehookcount;
+ int hookcount;
+ volatile l_signalT hookmask;
+ struct { /* info about transferred values (for call/return hooks) */
+ int ftransfer; /* offset of first value transferred */
+ int ntransfer; /* number of values transferred */
+ } transferinfo;
+};
+
+
+/*
+** thread state + extra space
+*/
+typedef struct LX {
+ lu_byte extra_[LUA_EXTRASPACE];
+ lua_State l;
+} LX;
+
+
+/*
** 'global state', shared by all threads of this state
*/
typedef struct global_State {
@@ -324,50 +366,18 @@ typedef struct global_State {
GCObject *finobjrold; /* list of really old objects with finalizers */
struct lua_State *twups; /* list of threads with open upvalues */
lua_CFunction panic; /* to be called in unprotected errors */
- struct lua_State *mainthread;
TString *memerrmsg; /* message for memory-allocation errors */
TString *tmname[TM_N]; /* array with tag-method names */
struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */
TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */
lua_WarnFunction warnf; /* warning function */
void *ud_warn; /* auxiliary data to 'warnf' */
+ LX mainth; /* main thread of this state */
} global_State;
-/*
-** 'per thread' state
-*/
-struct lua_State {
- CommonHeader;
- lu_byte allowhook;
- TStatus status;
- unsigned short nci; /* number of items in 'ci' list */
- StkIdRel top; /* first free slot in the stack */
- global_State *l_G;
- CallInfo *ci; /* call info for current function */
- StkIdRel stack_last; /* end of stack (last element + 1) */
- StkIdRel stack; /* stack base */
- UpVal *openupval; /* list of open upvalues in this stack */
- StkIdRel tbclist; /* list of to-be-closed variables */
- GCObject *gclist;
- struct lua_State *twups; /* list of threads with open upvalues */
- struct lua_longjmp *errorJmp; /* current error recover point */
- CallInfo base_ci; /* CallInfo for first level (C host) */
- volatile lua_Hook hook;
- ptrdiff_t errfunc; /* current error handling function (stack index) */
- l_uint32 nCcalls; /* number of nested non-yieldable or C calls */
- int oldpc; /* last pc traced */
- int basehookcount;
- int hookcount;
- volatile l_signalT hookmask;
- struct { /* info about transferred values (for call/return hooks) */
- int ftransfer; /* offset of first value transferred */
- int ntransfer; /* number of values transferred */
- } transferinfo;
-};
-
-
#define G(L) (L->l_G)
+#define mainthread(G) (&(G)->mainth.l)
/*
** 'g->nilvalue' being a nil value flags that the state was completely
diff --git a/ltests.c b/ltests.c
@@ -408,7 +408,7 @@ static void checktable (global_State *g, Table *h) {
for (n = gnode(h, 0); n < limit; n++) {
if (!isempty(gval(n))) {
TValue k;
- getnodekey(g->mainthread, &k, n);
+ getnodekey(mainthread(g), &k, n);
assert(!keyisnil(n));
checkvalref(g, hgc, &k);
checkvalref(g, hgc, gval(n));
@@ -672,7 +672,7 @@ int lua_checkmemory (lua_State *L) {
l_mem totalin; /* total of objects that are in gray lists */
l_mem totalshould; /* total of objects that should be in gray lists */
if (keepinvariant(g)) {
- assert(!iswhite(g->mainthread));
+ assert(!iswhite(mainthread(g)));
assert(!iswhite(gcvalue(&g->l_registry)));
}
assert(!isdead(g, gcvalue(&g->l_registry)));