ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lj_state.c (10031B)


      1 /*
      2 ** State and stack handling.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 **
      5 ** Portions taken verbatim or adapted from the Lua interpreter.
      6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
      7 */
      8 
      9 #define lj_state_c
     10 #define LUA_CORE
     11 
     12 #include "lj_obj.h"
     13 #include "lj_gc.h"
     14 #include "lj_err.h"
     15 #include "lj_buf.h"
     16 #include "lj_str.h"
     17 #include "lj_tab.h"
     18 #include "lj_func.h"
     19 #include "lj_meta.h"
     20 #include "lj_state.h"
     21 #include "lj_frame.h"
     22 #if LJ_HASFFI
     23 #include "lj_ctype.h"
     24 #endif
     25 #include "lj_trace.h"
     26 #include "lj_dispatch.h"
     27 #include "lj_vm.h"
     28 #include "lj_lex.h"
     29 #include "lj_alloc.h"
     30 #include "luajit.h"
     31 
     32 /* -- Stack handling ------------------------------------------------------ */
     33 
     34 /* Stack sizes. */
     35 #define LJ_STACK_MIN	LUA_MINSTACK	/* Min. stack size. */
     36 #define LJ_STACK_MAX	LUAI_MAXSTACK	/* Max. stack size. */
     37 #define LJ_STACK_START	(2*LJ_STACK_MIN)	/* Starting stack size. */
     38 #define LJ_STACK_MAXEX	(LJ_STACK_MAX + 1 + LJ_STACK_EXTRA)
     39 
     40 /* Explanation of LJ_STACK_EXTRA:
     41 **
     42 ** Calls to metamethods store their arguments beyond the current top
     43 ** without checking for the stack limit. This avoids stack resizes which
     44 ** would invalidate passed TValue pointers. The stack check is performed
     45 ** later by the function header. This can safely resize the stack or raise
     46 ** an error. Thus we need some extra slots beyond the current stack limit.
     47 **
     48 ** Most metamethods need 4 slots above top (cont, mobj, arg1, arg2) plus
     49 ** one extra slot if mobj is not a function. Only lj_meta_tset needs 5
     50 ** slots above top, but then mobj is always a function. So we can get by
     51 ** with 5 extra slots.
     52 ** LJ_FR2: We need 2 more slots for the frame PC and the continuation PC.
     53 */
     54 
     55 /* Resize stack slots and adjust pointers in state. */
     56 static void resizestack(lua_State *L, MSize n)
     57 {
     58   TValue *st, *oldst = tvref(L->stack);
     59   ptrdiff_t delta;
     60   MSize oldsize = L->stacksize;
     61   MSize realsize = n + 1 + LJ_STACK_EXTRA;
     62   GCobj *up;
     63   lua_assert((MSize)(tvref(L->maxstack)-oldst)==L->stacksize-LJ_STACK_EXTRA-1);
     64   st = (TValue *)lj_mem_realloc(L, tvref(L->stack),
     65 				(MSize)(oldsize*sizeof(TValue)),
     66 				(MSize)(realsize*sizeof(TValue)));
     67   setmref(L->stack, st);
     68   delta = (char *)st - (char *)oldst;
     69   setmref(L->maxstack, st + n);
     70   while (oldsize < realsize)  /* Clear new slots. */
     71     setnilV(st + oldsize++);
     72   L->stacksize = realsize;
     73   if ((size_t)(mref(G(L)->jit_base, char) - (char *)oldst) < oldsize)
     74     setmref(G(L)->jit_base, mref(G(L)->jit_base, char) + delta);
     75   L->base = (TValue *)((char *)L->base + delta);
     76   L->top = (TValue *)((char *)L->top + delta);
     77   for (up = gcref(L->openupval); up != NULL; up = gcnext(up))
     78     setmref(gco2uv(up)->v, (TValue *)((char *)uvval(gco2uv(up)) + delta));
     79 }
     80 
     81 /* Relimit stack after error, in case the limit was overdrawn. */
     82 void lj_state_relimitstack(lua_State *L)
     83 {
     84   if (L->stacksize > LJ_STACK_MAXEX && L->top-tvref(L->stack) < LJ_STACK_MAX-1)
     85     resizestack(L, LJ_STACK_MAX);
     86 }
     87 
     88 /* Try to shrink the stack (called from GC). */
     89 void lj_state_shrinkstack(lua_State *L, MSize used)
     90 {
     91   if (L->stacksize > LJ_STACK_MAXEX)
     92     return;  /* Avoid stack shrinking while handling stack overflow. */
     93   if (4*used < L->stacksize &&
     94       2*(LJ_STACK_START+LJ_STACK_EXTRA) < L->stacksize &&
     95       /* Don't shrink stack of live trace. */
     96       (tvref(G(L)->jit_base) == NULL || obj2gco(L) != gcref(G(L)->cur_L)))
     97     resizestack(L, L->stacksize >> 1);
     98 }
     99 
    100 /* Try to grow stack. */
    101 void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need)
    102 {
    103   MSize n;
    104   if (L->stacksize > LJ_STACK_MAXEX)  /* Overflow while handling overflow? */
    105     lj_err_throw(L, LUA_ERRERR);
    106   n = L->stacksize + need;
    107   if (n > LJ_STACK_MAX) {
    108     n += 2*LUA_MINSTACK;
    109   } else if (n < 2*L->stacksize) {
    110     n = 2*L->stacksize;
    111     if (n >= LJ_STACK_MAX)
    112       n = LJ_STACK_MAX;
    113   }
    114   resizestack(L, n);
    115   if (L->stacksize > LJ_STACK_MAXEX)
    116     lj_err_msg(L, LJ_ERR_STKOV);
    117 }
    118 
    119 void LJ_FASTCALL lj_state_growstack1(lua_State *L)
    120 {
    121   lj_state_growstack(L, 1);
    122 }
    123 
    124 /* Allocate basic stack for new state. */
    125 static void stack_init(lua_State *L1, lua_State *L)
    126 {
    127   TValue *stend, *st = lj_mem_newvec(L, LJ_STACK_START+LJ_STACK_EXTRA, TValue);
    128   setmref(L1->stack, st);
    129   L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA;
    130   stend = st + L1->stacksize;
    131   setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1);
    132   setthreadV(L1, st++, L1);  /* Needed for curr_funcisL() on empty stack. */
    133   if (LJ_FR2) setnilV(st++);
    134   L1->base = L1->top = st;
    135   while (st < stend)  /* Clear new slots. */
    136     setnilV(st++);
    137 }
    138 
    139 /* -- State handling ------------------------------------------------------ */
    140 
    141 /* Open parts that may cause memory-allocation errors. */
    142 static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud)
    143 {
    144   GCtab *weak, *t, *reg;
    145   global_State *g = G(L);
    146   UNUSED(dummy);
    147   UNUSED(ud);
    148   stack_init(L, L);
    149   lua_assert(L->cframe);
    150   g->cframe_limit = L->cframe - LUAI_MAXCFRAME;
    151   /* NOBARRIER: State initialization, all objects are white. */
    152   lj_str_resize(L, LJ_MIN_STRTAB-1);
    153   lj_meta_init(L);
    154   lj_lex_init(L);
    155   fixstring(lj_err_str(L, LJ_ERR_ERRMEM));  /* Preallocate memory error msg. */
    156 
    157   /* Create weak key metatable. */
    158   weak = lj_tab_new(L, 0, 1);
    159   setgcref(weak->metatable, obj2gco(weak));
    160   setstrV(L, lj_tab_setstr(L, weak, lj_str_newlit(L, "__mode")), lj_str_newlit(L, "k"));
    161   weak->nomm = (uint8_t)(~(1u<<MM_mode));
    162  
    163   /* Registry table. */
    164   reg = lj_tab_new(L, 0, LJ_MIN_REGISTRY);
    165   settabV(L, registry(L), reg);
    166 
    167   /* Globals table. */ 
    168   t = lj_tab_new(L, 0, LJ_MIN_GLOBAL);
    169   setgcref(L->env, obj2gco(t));
    170   settabV(L, lj_tab_setint(L, reg, LUA_RIDX_GLOBALS), t);
    171 
    172   /* Userval table. */
    173   t = lj_tab_new(L, 0, 0);
    174   setgcref(t->metatable, obj2gco(weak));
    175   settabV(L, lj_tab_setint(L, reg, LUA_RIDX_USERVAL), t);
    176 
    177   /* Register main thread. */  
    178   setthreadV(L, lj_tab_setint(L, reg, LUA_RIDX_MAINTHREAD), L);
    179 
    180   g->version = lua_version(NULL);
    181   g->gc.threshold = 4*g->gc.total;
    182   lj_trace_initstate(g);
    183   return NULL;
    184 }
    185 
    186 static void close_state(lua_State *L)
    187 {
    188   global_State *g = G(L);
    189   lj_func_closeuv(L, tvref(L->stack));
    190   lj_gc_freeall(g);
    191   lua_assert(gcref(g->gc.root) == obj2gco(L));
    192   lua_assert(g->strnum == 0);
    193   lj_trace_freestate(g);
    194 #if LJ_HASFFI
    195   lj_ctype_freestate(g);
    196 #endif
    197   lj_mem_freevec(g, g->strhash, g->strmask+1, GCRef);
    198   lj_buf_free(g, &g->tmpbuf);
    199   lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue);
    200   lua_assert(g->gc.total == sizeof(GG_State));
    201 #ifndef LUAJIT_USE_SYSMALLOC
    202   if (g->allocf == lj_alloc_f)
    203     lj_alloc_destroy(g->allocd);
    204   else
    205 #endif
    206     g->allocf(g->allocd, G2GG(g), sizeof(GG_State), 0);
    207 }
    208 
    209 #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC))
    210 lua_State *lj_state_newstate(lua_Alloc f, void *ud)
    211 #else
    212 LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
    213 #endif
    214 {
    215   GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State));
    216   lua_State *L = &GG->L;
    217   global_State *g = &GG->g;
    218   if (GG == NULL || !checkptrGC(GG)) return NULL;
    219   memset(GG, 0, sizeof(GG_State));
    220   L->gct = ~LJ_TTHREAD;
    221   L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED;  /* Prevent free. */
    222   L->dummy_ffid = FF_C;
    223   setmref(L->glref, g);
    224   g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED;
    225   g->strempty.marked = LJ_GC_WHITE0;
    226   g->strempty.gct = ~LJ_TSTR;
    227   g->allocf = f;
    228   g->allocd = ud;
    229   setgcref(g->mainthref, obj2gco(L));
    230   setgcref(g->uvhead.prev, obj2gco(&g->uvhead));
    231   setgcref(g->uvhead.next, obj2gco(&g->uvhead));
    232   g->strmask = ~(MSize)0;
    233   setnilV(registry(L));
    234   setnilV(&g->nilnode.val);
    235   setnilV(&g->nilnode.key);
    236 #if !LJ_GC64
    237   setmref(g->nilnode.freetop, &g->nilnode);
    238 #endif
    239   lj_buf_init(NULL, &g->tmpbuf);
    240   g->gc.state = GCSpause;
    241   setgcref(g->gc.root, obj2gco(L));
    242   setmref(g->gc.sweep, &g->gc.root);
    243   g->gc.total = sizeof(GG_State);
    244   g->gc.pause = LUAI_GCPAUSE;
    245   g->gc.stepmul = LUAI_GCMUL;
    246   lj_dispatch_init((GG_State *)L);
    247   L->status = LUA_ERRERR+1;  /* Avoid touching the stack upon memory error. */
    248   if (lj_vm_cpcall(L, NULL, NULL, cpluaopen) != 0) {
    249     /* Memory allocation error: free partial state. */
    250     close_state(L);
    251     return NULL;
    252   }
    253   L->status = 0;
    254   return L;
    255 }
    256 
    257 static TValue *cpfinalize(lua_State *L, lua_CFunction dummy, void *ud)
    258 {
    259   UNUSED(dummy);
    260   UNUSED(ud);
    261   lj_gc_finalize_cdata(L);
    262   lj_gc_finalize_udata(L);
    263   /* Frame pop omitted. */
    264   return NULL;
    265 }
    266 
    267 LUA_API void lua_close(lua_State *L)
    268 {
    269   global_State *g = G(L);
    270   int i;
    271   L = mainthread(g);  /* Only the main thread can be closed. */
    272 #if LJ_HASPROFILE
    273   luaJIT_profile_stop(L);
    274 #endif
    275   setgcrefnull(g->cur_L);
    276   lj_func_closeuv(L, tvref(L->stack));
    277   lj_gc_separateudata(g, 1);  /* Separate udata which have GC metamethods. */
    278 #if LJ_HASJIT
    279   G2J(g)->flags &= ~JIT_F_ON;
    280   G2J(g)->state = LJ_TRACE_IDLE;
    281   lj_dispatch_update(g);
    282 #endif
    283   for (i = 0;;) {
    284     hook_enter(g);
    285     L->status = 0;
    286     L->base = L->top = tvref(L->stack) + 1 + LJ_FR2;
    287     L->cframe = NULL;
    288     if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == 0) {
    289       if (++i >= 10) break;
    290       lj_gc_separateudata(g, 1);  /* Separate udata again. */
    291       if (gcref(g->gc.mmudata) == NULL)  /* Until nothing is left to do. */
    292 	break;
    293     }
    294   }
    295   close_state(L);
    296 }
    297 
    298 lua_State *lj_state_new(lua_State *L)
    299 {
    300   lua_State *L1 = lj_mem_newobj(L, lua_State);
    301   L1->gct = ~LJ_TTHREAD;
    302   L1->dummy_ffid = FF_C;
    303   L1->status = 0;
    304   L1->stacksize = 0;
    305   setmref(L1->stack, NULL);
    306   L1->cframe = NULL;
    307   /* NOBARRIER: The lua_State is new (marked white). */
    308   setgcrefnull(L1->openupval);
    309   setmrefr(L1->glref, L->glref);
    310   setgcrefr(L1->env, L->env);
    311   stack_init(L1, L);  /* init stack */
    312   lua_assert(iswhite(obj2gco(L1)));
    313   return L1;
    314 }
    315 
    316 void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L)
    317 {
    318   lua_assert(L != mainthread(g));
    319   if (obj2gco(L) == gcref(g->cur_L))
    320     setgcrefnull(g->cur_L);
    321   lj_func_closeuv(L, tvref(L->stack));
    322   lua_assert(gcref(L->openupval) == NULL);
    323   lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue);
    324   lj_mem_freet(g, L);
    325 }
    326