2009-12-08 18:46:35 +00:00
|
|
|
/*
|
|
|
|
** State and stack handling.
|
2023-08-20 19:25:30 +00:00
|
|
|
** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
|
2009-12-08 18:46:35 +00:00
|
|
|
**
|
|
|
|
** Portions taken verbatim or adapted from the Lua interpreter.
|
|
|
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define lj_state_c
|
|
|
|
#define LUA_CORE
|
|
|
|
|
|
|
|
#include "lj_obj.h"
|
|
|
|
#include "lj_gc.h"
|
|
|
|
#include "lj_err.h"
|
2013-02-27 16:11:31 +00:00
|
|
|
#include "lj_buf.h"
|
2009-12-08 18:46:35 +00:00
|
|
|
#include "lj_str.h"
|
|
|
|
#include "lj_tab.h"
|
|
|
|
#include "lj_func.h"
|
|
|
|
#include "lj_meta.h"
|
|
|
|
#include "lj_state.h"
|
|
|
|
#include "lj_frame.h"
|
2010-12-04 23:11:35 +00:00
|
|
|
#if LJ_HASFFI
|
|
|
|
#include "lj_ctype.h"
|
2010-02-28 20:58:40 +00:00
|
|
|
#endif
|
2009-12-08 18:46:35 +00:00
|
|
|
#include "lj_trace.h"
|
|
|
|
#include "lj_dispatch.h"
|
|
|
|
#include "lj_vm.h"
|
2020-06-15 10:21:05 +00:00
|
|
|
#include "lj_prng.h"
|
2009-12-08 18:46:35 +00:00
|
|
|
#include "lj_lex.h"
|
|
|
|
#include "lj_alloc.h"
|
2013-09-01 23:49:19 +00:00
|
|
|
#include "luajit.h"
|
2009-12-08 18:46:35 +00:00
|
|
|
|
|
|
|
/* -- Stack handling ------------------------------------------------------ */
|
|
|
|
|
|
|
|
/* Stack sizes. */
|
|
|
|
#define LJ_STACK_MIN LUA_MINSTACK /* Min. stack size. */
|
|
|
|
#define LJ_STACK_MAX LUAI_MAXSTACK /* Max. stack size. */
|
|
|
|
#define LJ_STACK_START (2*LJ_STACK_MIN) /* Starting stack size. */
|
|
|
|
#define LJ_STACK_MAXEX (LJ_STACK_MAX + 1 + LJ_STACK_EXTRA)
|
|
|
|
|
|
|
|
/* Explanation of LJ_STACK_EXTRA:
|
|
|
|
**
|
|
|
|
** Calls to metamethods store their arguments beyond the current top
|
|
|
|
** without checking for the stack limit. This avoids stack resizes which
|
|
|
|
** would invalidate passed TValue pointers. The stack check is performed
|
2010-02-13 03:51:56 +00:00
|
|
|
** later by the function header. This can safely resize the stack or raise
|
|
|
|
** an error. Thus we need some extra slots beyond the current stack limit.
|
2009-12-08 18:46:35 +00:00
|
|
|
**
|
|
|
|
** Most metamethods need 4 slots above top (cont, mobj, arg1, arg2) plus
|
|
|
|
** one extra slot if mobj is not a function. Only lj_meta_tset needs 5
|
|
|
|
** slots above top, but then mobj is always a function. So we can get by
|
|
|
|
** with 5 extra slots.
|
2015-01-03 14:04:38 +00:00
|
|
|
** LJ_FR2: We need 2 more slots for the frame PC and the continuation PC.
|
2009-12-08 18:46:35 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Resize stack slots and adjust pointers in state. */
|
|
|
|
static void resizestack(lua_State *L, MSize n)
|
|
|
|
{
|
2010-09-09 10:28:17 +00:00
|
|
|
TValue *st, *oldst = tvref(L->stack);
|
2009-12-08 18:46:35 +00:00
|
|
|
ptrdiff_t delta;
|
2010-02-11 00:21:40 +00:00
|
|
|
MSize oldsize = L->stacksize;
|
2009-12-08 18:46:35 +00:00
|
|
|
MSize realsize = n + 1 + LJ_STACK_EXTRA;
|
|
|
|
GCobj *up;
|
2020-06-12 22:52:54 +00:00
|
|
|
lj_assertL((MSize)(tvref(L->maxstack)-oldst) == L->stacksize-LJ_STACK_EXTRA-1,
|
|
|
|
"inconsistent stack size");
|
2010-09-09 10:28:17 +00:00
|
|
|
st = (TValue *)lj_mem_realloc(L, tvref(L->stack),
|
2013-08-26 16:28:58 +00:00
|
|
|
(MSize)(oldsize*sizeof(TValue)),
|
2010-09-09 10:28:17 +00:00
|
|
|
(MSize)(realsize*sizeof(TValue)));
|
|
|
|
setmref(L->stack, st);
|
2010-02-11 00:21:40 +00:00
|
|
|
delta = (char *)st - (char *)oldst;
|
2010-09-09 10:28:17 +00:00
|
|
|
setmref(L->maxstack, st + n);
|
2010-02-11 00:21:40 +00:00
|
|
|
while (oldsize < realsize) /* Clear new slots. */
|
|
|
|
setnilV(st + oldsize++);
|
2009-12-08 18:46:35 +00:00
|
|
|
L->stacksize = realsize;
|
2013-08-26 16:28:58 +00:00
|
|
|
if ((size_t)(mref(G(L)->jit_base, char) - (char *)oldst) < oldsize)
|
|
|
|
setmref(G(L)->jit_base, mref(G(L)->jit_base, char) + delta);
|
2009-12-08 18:46:35 +00:00
|
|
|
L->base = (TValue *)((char *)L->base + delta);
|
|
|
|
L->top = (TValue *)((char *)L->top + delta);
|
|
|
|
for (up = gcref(L->openupval); up != NULL; up = gcnext(up))
|
2010-01-09 20:11:35 +00:00
|
|
|
setmref(gco2uv(up)->v, (TValue *)((char *)uvval(gco2uv(up)) + delta));
|
2009-12-08 18:46:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Relimit stack after error, in case the limit was overdrawn. */
|
|
|
|
void lj_state_relimitstack(lua_State *L)
|
|
|
|
{
|
2010-09-09 10:28:17 +00:00
|
|
|
if (L->stacksize > LJ_STACK_MAXEX && L->top-tvref(L->stack) < LJ_STACK_MAX-1)
|
2009-12-08 18:46:35 +00:00
|
|
|
resizestack(L, LJ_STACK_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to shrink the stack (called from GC). */
|
|
|
|
void lj_state_shrinkstack(lua_State *L, MSize used)
|
|
|
|
{
|
|
|
|
if (L->stacksize > LJ_STACK_MAXEX)
|
|
|
|
return; /* Avoid stack shrinking while handling stack overflow. */
|
|
|
|
if (4*used < L->stacksize &&
|
|
|
|
2*(LJ_STACK_START+LJ_STACK_EXTRA) < L->stacksize &&
|
2013-08-26 16:28:58 +00:00
|
|
|
/* Don't shrink stack of live trace. */
|
2013-08-28 11:06:19 +00:00
|
|
|
(tvref(G(L)->jit_base) == NULL || obj2gco(L) != gcref(G(L)->cur_L)))
|
2009-12-08 18:46:35 +00:00
|
|
|
resizestack(L, L->stacksize >> 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to grow stack. */
|
2009-12-27 16:42:41 +00:00
|
|
|
void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
|
2009-12-08 18:46:35 +00:00
|
|
|
{
|
2024-02-04 15:34:30 +00:00
|
|
|
MSize n = L->stacksize + need;
|
|
|
|
if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */
|
|
|
|
if (n < 2 * L->stacksize) { /* Try to double the size. */
|
|
|
|
n = 2 * L->stacksize;
|
|
|
|
if (n > LJ_STACK_MAX)
|
|
|
|
n = LJ_STACK_MAX;
|
|
|
|
}
|
|
|
|
resizestack(L, n);
|
|
|
|
} else { /* Request would overflow. Raise a stack overflow error. */
|
2024-02-04 15:47:14 +00:00
|
|
|
if (LJ_HASJIT) {
|
|
|
|
TValue *base = tvref(G(L)->jit_base);
|
|
|
|
if (base) L->base = base;
|
|
|
|
}
|
2024-02-04 15:34:30 +00:00
|
|
|
if (curr_funcisL(L)) {
|
|
|
|
L->top = curr_topL(L);
|
|
|
|
if (L->top > tvref(L->maxstack)) {
|
|
|
|
/* The current Lua frame violates the stack, so replace it with a
|
|
|
|
** dummy. This can happen when BC_IFUNCF is trying to grow the stack.
|
|
|
|
*/
|
|
|
|
L->top = L->base;
|
2024-02-04 15:47:14 +00:00
|
|
|
setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD);
|
2024-02-04 15:34:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (L->stacksize <= LJ_STACK_MAXEX) {
|
|
|
|
/* An error handler might want to inspect the stack overflow error, but
|
|
|
|
** will need some stack space to run in. We give it a stack size beyond
|
|
|
|
** the normal limit in order to do so, then rely on lj_state_relimitstack
|
|
|
|
** calls during unwinding to bring us back to a convential stack size.
|
|
|
|
** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for
|
|
|
|
** the lj_state_checkstack() call in lj_err_run().
|
|
|
|
*/
|
|
|
|
resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK);
|
|
|
|
lj_err_stkov(L); /* May invoke an error handler. */
|
|
|
|
} else {
|
|
|
|
/* If we're here, then the stack overflow error handler is requesting
|
|
|
|
** to grow the stack even further. We have no choice but to abort the
|
|
|
|
** error handler.
|
|
|
|
*/
|
|
|
|
GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */
|
|
|
|
setstrV(L, L->top++, em); /* There is always space to push an error. */
|
2023-09-20 23:58:43 +00:00
|
|
|
lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */
|
|
|
|
}
|
2010-03-01 04:51:04 +00:00
|
|
|
}
|
2009-12-08 18:46:35 +00:00
|
|
|
}
|
|
|
|
|
2009-12-27 16:42:41 +00:00
|
|
|
void LJ_FASTCALL lj_state_growstack1(lua_State *L)
|
2009-12-08 18:46:35 +00:00
|
|
|
{
|
|
|
|
lj_state_growstack(L, 1);
|
|
|
|
}
|
|
|
|
|
2023-09-21 02:40:48 +00:00
|
|
|
static TValue *cpgrowstack(lua_State *co, lua_CFunction dummy, void *ud)
|
|
|
|
{
|
|
|
|
UNUSED(dummy);
|
|
|
|
lj_state_growstack(co, *(MSize *)ud);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LJ_FASTCALL lj_state_cpgrowstack(lua_State *L, MSize need)
|
|
|
|
{
|
|
|
|
return lj_vm_cpcall(L, NULL, &need, cpgrowstack);
|
|
|
|
}
|
|
|
|
|
2009-12-08 18:46:35 +00:00
|
|
|
/* Allocate basic stack for new state. */
|
|
|
|
static void stack_init(lua_State *L1, lua_State *L)
|
|
|
|
{
|
2010-09-09 10:28:17 +00:00
|
|
|
TValue *stend, *st = lj_mem_newvec(L, LJ_STACK_START+LJ_STACK_EXTRA, TValue);
|
|
|
|
setmref(L1->stack, st);
|
2009-12-08 18:46:35 +00:00
|
|
|
L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA;
|
2010-02-11 00:21:40 +00:00
|
|
|
stend = st + L1->stacksize;
|
2010-09-09 10:28:17 +00:00
|
|
|
setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1);
|
2015-01-03 14:04:38 +00:00
|
|
|
setthreadV(L1, st++, L1); /* Needed for curr_funcisL() on empty stack. */
|
|
|
|
if (LJ_FR2) setnilV(st++);
|
|
|
|
L1->base = L1->top = st;
|
2010-02-11 00:21:40 +00:00
|
|
|
while (st < stend) /* Clear new slots. */
|
|
|
|
setnilV(st++);
|
2009-12-08 18:46:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* -- State handling ------------------------------------------------------ */
|
|
|
|
|
|
|
|
/* Open parts that may cause memory-allocation errors. */
|
|
|
|
static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud)
|
|
|
|
{
|
|
|
|
global_State *g = G(L);
|
|
|
|
UNUSED(dummy);
|
|
|
|
UNUSED(ud);
|
|
|
|
stack_init(L, L);
|
|
|
|
/* NOBARRIER: State initialization, all objects are white. */
|
|
|
|
setgcref(L->env, obj2gco(lj_tab_new(L, 0, LJ_MIN_GLOBAL)));
|
|
|
|
settabV(L, registry(L), lj_tab_new(L, 0, LJ_MIN_REGISTRY));
|
2020-06-23 01:06:45 +00:00
|
|
|
lj_str_init(L);
|
2009-12-08 18:46:35 +00:00
|
|
|
lj_meta_init(L);
|
|
|
|
lj_lex_init(L);
|
|
|
|
fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */
|
|
|
|
g->gc.threshold = 4*g->gc.total;
|
2024-04-18 23:33:19 +00:00
|
|
|
#if LJ_HASFFI
|
|
|
|
lj_ctype_initfin(L);
|
|
|
|
#endif
|
2010-02-24 22:17:17 +00:00
|
|
|
lj_trace_initstate(g);
|
2021-03-22 23:35:46 +00:00
|
|
|
lj_err_verify();
|
2009-12-08 18:46:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void close_state(lua_State *L)
|
|
|
|
{
|
|
|
|
global_State *g = G(L);
|
2010-09-13 17:48:31 +00:00
|
|
|
lj_func_closeuv(L, tvref(L->stack));
|
|
|
|
lj_gc_freeall(g);
|
2020-06-12 22:52:54 +00:00
|
|
|
lj_assertG(gcref(g->gc.root) == obj2gco(L),
|
|
|
|
"main thread is not first GC object");
|
2020-06-23 01:06:45 +00:00
|
|
|
lj_assertG(g->str.num == 0, "leaked %d strings", g->str.num);
|
2010-09-13 17:48:31 +00:00
|
|
|
lj_trace_freestate(g);
|
2010-12-04 23:11:35 +00:00
|
|
|
#if LJ_HASFFI
|
|
|
|
lj_ctype_freestate(g);
|
|
|
|
#endif
|
2020-06-23 01:06:45 +00:00
|
|
|
lj_str_freetab(g);
|
2013-02-27 16:11:31 +00:00
|
|
|
lj_buf_free(g, &g->tmpbuf);
|
2010-09-13 17:48:31 +00:00
|
|
|
lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue);
|
2020-09-29 23:31:27 +00:00
|
|
|
#if LJ_64
|
|
|
|
if (mref(g->gc.lightudseg, uint32_t)) {
|
|
|
|
MSize segnum = g->gc.lightudnum ? (2 << lj_fls(g->gc.lightudnum)) : 2;
|
|
|
|
lj_mem_freevec(g, mref(g->gc.lightudseg, uint32_t), segnum, uint32_t);
|
|
|
|
}
|
|
|
|
#endif
|
2020-06-12 22:52:54 +00:00
|
|
|
lj_assertG(g->gc.total == sizeof(GG_State),
|
|
|
|
"memory leak of %lld bytes",
|
|
|
|
(long long)(g->gc.total - sizeof(GG_State)));
|
2009-12-08 18:46:35 +00:00
|
|
|
#ifndef LUAJIT_USE_SYSMALLOC
|
2010-09-13 17:48:31 +00:00
|
|
|
if (g->allocf == lj_alloc_f)
|
2009-12-08 18:46:35 +00:00
|
|
|
lj_alloc_destroy(g->allocd);
|
2010-09-13 17:48:31 +00:00
|
|
|
else
|
2009-12-08 18:46:35 +00:00
|
|
|
#endif
|
2010-02-13 03:51:56 +00:00
|
|
|
g->allocf(g->allocd, G2GG(g), sizeof(GG_State), 0);
|
2009-12-08 18:46:35 +00:00
|
|
|
}
|
|
|
|
|
2016-06-03 04:42:35 +00:00
|
|
|
#if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC))
|
2020-06-15 10:21:05 +00:00
|
|
|
lua_State *lj_state_newstate(lua_Alloc allocf, void *allocd)
|
2010-01-24 14:50:59 +00:00
|
|
|
#else
|
2020-06-15 10:21:05 +00:00
|
|
|
LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd)
|
2010-01-24 14:50:59 +00:00
|
|
|
#endif
|
2009-12-08 18:46:35 +00:00
|
|
|
{
|
2020-06-15 10:21:05 +00:00
|
|
|
PRNGState prng;
|
|
|
|
GG_State *GG;
|
|
|
|
lua_State *L;
|
|
|
|
global_State *g;
|
|
|
|
/* We need the PRNG for the memory allocator, so initialize this first. */
|
|
|
|
if (!lj_prng_seed_secure(&prng)) {
|
|
|
|
lj_assertX(0, "secure PRNG seeding failed");
|
|
|
|
/* Can only return NULL here, so this errors with "not enough memory". */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
#ifndef LUAJIT_USE_SYSMALLOC
|
|
|
|
if (allocf == LJ_ALLOCF_INTERNAL) {
|
|
|
|
allocd = lj_alloc_create(&prng);
|
|
|
|
if (!allocd) return NULL;
|
|
|
|
allocf = lj_alloc_f;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
GG = (GG_State *)allocf(allocd, NULL, 0, sizeof(GG_State));
|
2014-12-19 23:17:50 +00:00
|
|
|
if (GG == NULL || !checkptrGC(GG)) return NULL;
|
2009-12-08 18:46:35 +00:00
|
|
|
memset(GG, 0, sizeof(GG_State));
|
2020-06-15 10:21:05 +00:00
|
|
|
L = &GG->L;
|
|
|
|
g = &GG->g;
|
2009-12-08 18:46:35 +00:00
|
|
|
L->gct = ~LJ_TTHREAD;
|
|
|
|
L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */
|
|
|
|
L->dummy_ffid = FF_C;
|
|
|
|
setmref(L->glref, g);
|
|
|
|
g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED;
|
2010-07-21 20:53:27 +00:00
|
|
|
g->strempty.marked = LJ_GC_WHITE0;
|
|
|
|
g->strempty.gct = ~LJ_TSTR;
|
2020-06-15 10:21:05 +00:00
|
|
|
g->allocf = allocf;
|
|
|
|
g->allocd = allocd;
|
|
|
|
g->prng = prng;
|
|
|
|
#ifndef LUAJIT_USE_SYSMALLOC
|
|
|
|
if (allocf == lj_alloc_f) {
|
|
|
|
lj_alloc_setprng(allocd, &g->prng);
|
|
|
|
}
|
|
|
|
#endif
|
2009-12-08 18:46:35 +00:00
|
|
|
setgcref(g->mainthref, obj2gco(L));
|
|
|
|
setgcref(g->uvhead.prev, obj2gco(&g->uvhead));
|
|
|
|
setgcref(g->uvhead.next, obj2gco(&g->uvhead));
|
2020-06-23 01:06:45 +00:00
|
|
|
g->str.mask = ~(MSize)0;
|
2009-12-08 18:46:35 +00:00
|
|
|
setnilV(registry(L));
|
|
|
|
setnilV(&g->nilnode.val);
|
|
|
|
setnilV(&g->nilnode.key);
|
2015-01-03 14:23:58 +00:00
|
|
|
#if !LJ_GC64
|
2010-03-22 14:05:37 +00:00
|
|
|
setmref(g->nilnode.freetop, &g->nilnode);
|
2015-01-03 14:23:58 +00:00
|
|
|
#endif
|
2013-02-28 12:37:56 +00:00
|
|
|
lj_buf_init(NULL, &g->tmpbuf);
|
2009-12-08 18:46:35 +00:00
|
|
|
g->gc.state = GCSpause;
|
|
|
|
setgcref(g->gc.root, obj2gco(L));
|
2010-03-15 22:29:10 +00:00
|
|
|
setmref(g->gc.sweep, &g->gc.root);
|
2010-02-13 03:51:56 +00:00
|
|
|
g->gc.total = sizeof(GG_State);
|
2009-12-08 18:46:35 +00:00
|
|
|
g->gc.pause = LUAI_GCPAUSE;
|
|
|
|
g->gc.stepmul = LUAI_GCMUL;
|
|
|
|
lj_dispatch_init((GG_State *)L);
|
|
|
|
L->status = LUA_ERRERR+1; /* Avoid touching the stack upon memory error. */
|
2009-12-17 21:08:20 +00:00
|
|
|
if (lj_vm_cpcall(L, NULL, NULL, cpluaopen) != 0) {
|
2009-12-08 18:46:35 +00:00
|
|
|
/* Memory allocation error: free partial state. */
|
|
|
|
close_state(L);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-04-07 10:12:03 +00:00
|
|
|
L->status = LUA_OK;
|
2009-12-08 18:46:35 +00:00
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|
|
|
|
static TValue *cpfinalize(lua_State *L, lua_CFunction dummy, void *ud)
|
|
|
|
{
|
|
|
|
UNUSED(dummy);
|
|
|
|
UNUSED(ud);
|
2011-02-28 15:48:13 +00:00
|
|
|
lj_gc_finalize_cdata(L);
|
2012-03-05 14:05:28 +00:00
|
|
|
lj_gc_finalize_udata(L);
|
2009-12-08 18:46:35 +00:00
|
|
|
/* Frame pop omitted. */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LUA_API void lua_close(lua_State *L)
|
|
|
|
{
|
|
|
|
global_State *g = G(L);
|
2012-04-11 13:15:50 +00:00
|
|
|
int i;
|
2009-12-08 18:46:35 +00:00
|
|
|
L = mainthread(g); /* Only the main thread can be closed. */
|
2013-09-01 23:49:19 +00:00
|
|
|
#if LJ_HASPROFILE
|
|
|
|
luaJIT_profile_stop(L);
|
|
|
|
#endif
|
|
|
|
setgcrefnull(g->cur_L);
|
2010-09-09 10:28:17 +00:00
|
|
|
lj_func_closeuv(L, tvref(L->stack));
|
2009-12-08 18:46:35 +00:00
|
|
|
lj_gc_separateudata(g, 1); /* Separate udata which have GC metamethods. */
|
|
|
|
#if LJ_HASJIT
|
|
|
|
G2J(g)->flags &= ~JIT_F_ON;
|
|
|
|
G2J(g)->state = LJ_TRACE_IDLE;
|
|
|
|
lj_dispatch_update(g);
|
|
|
|
#endif
|
2012-06-10 21:40:53 +00:00
|
|
|
for (i = 0;;) {
|
2009-12-08 18:46:35 +00:00
|
|
|
hook_enter(g);
|
2017-04-07 10:12:03 +00:00
|
|
|
L->status = LUA_OK;
|
2015-01-03 14:04:38 +00:00
|
|
|
L->base = L->top = tvref(L->stack) + 1 + LJ_FR2;
|
2013-08-28 11:06:19 +00:00
|
|
|
L->cframe = NULL;
|
2017-04-07 10:12:03 +00:00
|
|
|
if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == LUA_OK) {
|
2012-06-10 21:40:53 +00:00
|
|
|
if (++i >= 10) break;
|
2012-04-11 10:08:09 +00:00
|
|
|
lj_gc_separateudata(g, 1); /* Separate udata again. */
|
|
|
|
if (gcref(g->gc.mmudata) == NULL) /* Until nothing is left to do. */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-12-08 18:46:35 +00:00
|
|
|
close_state(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_State *lj_state_new(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_State *L1 = lj_mem_newobj(L, lua_State);
|
|
|
|
L1->gct = ~LJ_TTHREAD;
|
|
|
|
L1->dummy_ffid = FF_C;
|
2017-04-07 10:12:03 +00:00
|
|
|
L1->status = LUA_OK;
|
2009-12-08 18:46:35 +00:00
|
|
|
L1->stacksize = 0;
|
2010-09-09 10:28:17 +00:00
|
|
|
setmref(L1->stack, NULL);
|
2009-12-08 18:46:35 +00:00
|
|
|
L1->cframe = NULL;
|
|
|
|
/* NOBARRIER: The lua_State is new (marked white). */
|
|
|
|
setgcrefnull(L1->openupval);
|
|
|
|
setmrefr(L1->glref, L->glref);
|
|
|
|
setgcrefr(L1->env, L->env);
|
|
|
|
stack_init(L1, L); /* init stack */
|
2020-06-12 22:52:54 +00:00
|
|
|
lj_assertL(iswhite(obj2gco(L1)), "new thread object is not white");
|
2009-12-08 18:46:35 +00:00
|
|
|
return L1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L)
|
|
|
|
{
|
2020-06-12 22:52:54 +00:00
|
|
|
lj_assertG(L != mainthread(g), "free of main thread");
|
2013-08-28 11:06:19 +00:00
|
|
|
if (obj2gco(L) == gcref(g->cur_L))
|
|
|
|
setgcrefnull(g->cur_L);
|
2023-11-05 15:34:46 +00:00
|
|
|
if (gcref(L->openupval) != NULL) {
|
|
|
|
lj_func_closeuv(L, tvref(L->stack));
|
|
|
|
lj_trace_abort(g); /* For aa_uref soundness. */
|
|
|
|
lj_assertG(gcref(L->openupval) == NULL, "stale open upvalues");
|
|
|
|
}
|
2010-09-09 10:28:17 +00:00
|
|
|
lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue);
|
2009-12-08 18:46:35 +00:00
|
|
|
lj_mem_freet(g, L);
|
|
|
|
}
|
|
|
|
|