root/lj_func.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lj_func_freeproto
  2. unlinkuv
  3. func_finduv
  4. func_emptyuv
  5. lj_func_closeuv
  6. lj_func_freeuv
  7. lj_func_newC
  8. func_newL
  9. lj_func_newL_empty
  10. lj_func_newL_gc
  11. lj_func_free

   1 /*
   2 ** Function handling (prototypes, functions and upvalues).
   3 ** Copyright (C) 2005-2017 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_func_c
  10 #define LUA_CORE
  11 
  12 #include "lj_obj.h"
  13 #include "lj_gc.h"
  14 #include "lj_func.h"
  15 #include "lj_trace.h"
  16 #include "lj_vm.h"
  17 
  18 /* -- Prototypes ---------------------------------------------------------- */
  19 
  20 void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt)
  21 {
  22   lj_mem_free(g, pt, pt->sizept);
  23 }
  24 
  25 /* -- Upvalues ------------------------------------------------------------ */
  26 
  27 static void unlinkuv(GCupval *uv)
  28 {
  29   lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv);
  30   setgcrefr(uvnext(uv)->prev, uv->prev);
  31   setgcrefr(uvprev(uv)->next, uv->next);
  32 }
  33 
  34 /* Find existing open upvalue for a stack slot or create a new one. */
  35 static GCupval *func_finduv(lua_State *L, TValue *slot)
  36 {
  37   global_State *g = G(L);
  38   GCRef *pp = &L->openupval;
  39   GCupval *p;
  40   GCupval *uv;
  41   /* Search the sorted list of open upvalues. */
  42   while (gcref(*pp) != NULL && uvval((p = gco2uv(gcref(*pp)))) >= slot) {
  43     lua_assert(!p->closed && uvval(p) != &p->tv);
  44     if (uvval(p) == slot) {  /* Found open upvalue pointing to same slot? */
  45       if (isdead(g, obj2gco(p)))  /* Resurrect it, if it's dead. */
  46         flipwhite(obj2gco(p));
  47       return p;
  48     }
  49     pp = &p->nextgc;
  50   }
  51   /* No matching upvalue found. Create a new one. */
  52   uv = lj_mem_newt(L, sizeof(GCupval), GCupval);
  53   newwhite(g, uv);
  54   uv->gct = ~LJ_TUPVAL;
  55   uv->closed = 0;  /* Still open. */
  56   setmref(uv->v, slot);  /* Pointing to the stack slot. */
  57   /* NOBARRIER: The GCupval is new (marked white) and open. */
  58   setgcrefr(uv->nextgc, *pp);  /* Insert into sorted list of open upvalues. */
  59   setgcref(*pp, obj2gco(uv));
  60   setgcref(uv->prev, obj2gco(&g->uvhead));  /* Insert into GC list, too. */
  61   setgcrefr(uv->next, g->uvhead.next);
  62   setgcref(uvnext(uv)->prev, obj2gco(uv));
  63   setgcref(g->uvhead.next, obj2gco(uv));
  64   lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv);
  65   return uv;
  66 }
  67 
  68 /* Create an empty and closed upvalue. */
  69 static GCupval *func_emptyuv(lua_State *L)
  70 {
  71   GCupval *uv = (GCupval *)lj_mem_newgco(L, sizeof(GCupval));
  72   uv->gct = ~LJ_TUPVAL;
  73   uv->closed = 1;
  74   setnilV(&uv->tv);
  75   setmref(uv->v, &uv->tv);
  76   return uv;
  77 }
  78 
  79 /* Close all open upvalues pointing to some stack level or above. */
  80 void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level)
  81 {
  82   GCupval *uv;
  83   global_State *g = G(L);
  84   while (gcref(L->openupval) != NULL &&
  85          uvval((uv = gco2uv(gcref(L->openupval)))) >= level) {
  86     GCobj *o = obj2gco(uv);
  87     lua_assert(!isblack(o) && !uv->closed && uvval(uv) != &uv->tv);
  88     setgcrefr(L->openupval, uv->nextgc);  /* No longer in open list. */
  89     if (isdead(g, o)) {
  90       lj_func_freeuv(g, uv);
  91     } else {
  92       unlinkuv(uv);
  93       lj_gc_closeuv(g, uv);
  94     }
  95   }
  96 }
  97 
  98 void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv)
  99 {
 100   if (!uv->closed)
 101     unlinkuv(uv);
 102   lj_mem_freet(g, uv);
 103 }
 104 
 105 /* -- Functions (closures) ------------------------------------------------ */
 106 
 107 GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env)
 108 {
 109   GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeCfunc(nelems));
 110   fn->c.gct = ~LJ_TFUNC;
 111   fn->c.ffid = FF_C;
 112   fn->c.nupvalues = (uint8_t)nelems;
 113   /* NOBARRIER: The GCfunc is new (marked white). */
 114   setmref(fn->c.pc, &G(L)->bc_cfunc_ext);
 115   setgcref(fn->c.env, obj2gco(env));
 116   return fn;
 117 }
 118 
 119 static GCfunc *func_newL(lua_State *L, GCproto *pt, GCtab *env)
 120 {
 121   uint32_t count;
 122   GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv));
 123   fn->l.gct = ~LJ_TFUNC;
 124   fn->l.ffid = FF_LUA;
 125   fn->l.nupvalues = 0;  /* Set to zero until upvalues are initialized. */
 126   /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */
 127   setmref(fn->l.pc, proto_bc(pt));
 128   setgcref(fn->l.env, obj2gco(env));
 129   /* Saturating 3 bit counter (0..7) for created closures. */
 130   count = (uint32_t)pt->flags + PROTO_CLCOUNT;
 131   pt->flags = (uint8_t)(count - ((count >> PROTO_CLC_BITS) & PROTO_CLCOUNT));
 132   return fn;
 133 }
 134 
 135 /* Create a new Lua function with empty upvalues. */
 136 GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env)
 137 {
 138   GCfunc *fn = func_newL(L, pt, env);
 139   MSize i, nuv = pt->sizeuv;
 140   /* NOBARRIER: The GCfunc is new (marked white). */
 141   for (i = 0; i < nuv; i++) {
 142     GCupval *uv = func_emptyuv(L);
 143     int32_t v = proto_uv(pt)[i];
 144     uv->immutable = ((v / PROTO_UV_IMMUTABLE) & 1);
 145     uv->dhash = (uint32_t)(uintptr_t)pt ^ (v << 24);
 146     setgcref(fn->l.uvptr[i], obj2gco(uv));
 147   }
 148   fn->l.nupvalues = (uint8_t)nuv;
 149   return fn;
 150 }
 151 
 152 /* Do a GC check and create a new Lua function with inherited upvalues. */
 153 GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent)
 154 {
 155   GCfunc *fn;
 156   GCRef *puv;
 157   MSize i, nuv;
 158   TValue *base;
 159   lj_gc_check_fixtop(L);
 160   fn = func_newL(L, pt, tabref(parent->env));
 161   /* NOBARRIER: The GCfunc is new (marked white). */
 162   puv = parent->uvptr;
 163   nuv = pt->sizeuv;
 164   base = L->base;
 165   for (i = 0; i < nuv; i++) {
 166     uint32_t v = proto_uv(pt)[i];
 167     GCupval *uv;
 168     if ((v & PROTO_UV_LOCAL)) {
 169       uv = func_finduv(L, base + (v & 0xff));
 170       uv->immutable = ((v / PROTO_UV_IMMUTABLE) & 1);
 171       uv->dhash = (uint32_t)(uintptr_t)mref(parent->pc, char) ^ (v << 24);
 172     } else {
 173       uv = &gcref(puv[v])->uv;
 174     }
 175     setgcref(fn->l.uvptr[i], obj2gco(uv));
 176   }
 177   fn->l.nupvalues = (uint8_t)nuv;
 178   return fn;
 179 }
 180 
 181 void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *fn)
 182 {
 183   MSize size = isluafunc(fn) ? sizeLfunc((MSize)fn->l.nupvalues) :
 184                                sizeCfunc((MSize)fn->c.nupvalues);
 185   lj_mem_free(g, fn, size);
 186 }
 187 

/* [<][>][^][v][top][bottom][index][help] */