diff options
| -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))); |
