src/lj_func.c - luajit-2.0-src

Functions defined

Macros defined

Source code

  1. /*
  2. ** Function handling (prototypes, functions and upvalues).
  3. ** Copyright (C) 2005-2015 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. #define lj_func_c
  9. #define LUA_CORE

  10. #include "lj_obj.h"
  11. #include "lj_gc.h"
  12. #include "lj_func.h"
  13. #include "lj_trace.h"
  14. #include "lj_vm.h"

  15. /* -- Prototypes ---------------------------------------------------------- */

  16. void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt)
  17. {
  18.   lj_mem_free(g, pt, pt->sizept);
  19. }

  20. /* -- Upvalues ------------------------------------------------------------ */

  21. static void unlinkuv(GCupval *uv)
  22. {
  23.   lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv);
  24.   setgcrefr(uvnext(uv)->prev, uv->prev);
  25.   setgcrefr(uvprev(uv)->next, uv->next);
  26. }

  27. /* Find existing open upvalue for a stack slot or create a new one. */
  28. static GCupval *func_finduv(lua_State *L, TValue *slot)
  29. {
  30.   global_State *g = G(L);
  31.   GCRef *pp = &L->openupval;
  32.   GCupval *p;
  33.   GCupval *uv;
  34.   /* Search the sorted list of open upvalues. */
  35.   while (gcref(*pp) != NULL && uvval((p = gco2uv(gcref(*pp)))) >= slot) {
  36.     lua_assert(!p->closed && uvval(p) != &p->tv);
  37.     if (uvval(p) == slot) {  /* Found open upvalue pointing to same slot? */
  38.       if (isdead(g, obj2gco(p)))  /* Resurrect it, if it's dead. */
  39.         flipwhite(obj2gco(p));
  40.       return p;
  41.     }
  42.     pp = &p->nextgc;
  43.   }
  44.   /* No matching upvalue found. Create a new one. */
  45.   uv = lj_mem_newt(L, sizeof(GCupval), GCupval);
  46.   newwhite(g, uv);
  47.   uv->gct = ~LJ_TUPVAL;
  48.   uv->closed = 0/* Still open. */
  49.   setmref(uv->v, slot);  /* Pointing to the stack slot. */
  50.   /* NOBARRIER: The GCupval is new (marked white) and open. */
  51.   setgcrefr(uv->nextgc, *pp);  /* Insert into sorted list of open upvalues. */
  52.   setgcref(*pp, obj2gco(uv));
  53.   setgcref(uv->prev, obj2gco(&g->uvhead));  /* Insert into GC list, too. */
  54.   setgcrefr(uv->next, g->uvhead.next);
  55.   setgcref(uvnext(uv)->prev, obj2gco(uv));
  56.   setgcref(g->uvhead.next, obj2gco(uv));
  57.   lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv);
  58.   return uv;
  59. }

  60. /* Create an empty and closed upvalue. */
  61. static GCupval *func_emptyuv(lua_State *L)
  62. {
  63.   GCupval *uv = (GCupval *)lj_mem_newgco(L, sizeof(GCupval));
  64.   uv->gct = ~LJ_TUPVAL;
  65.   uv->closed = 1;
  66.   setnilV(&uv->tv);
  67.   setmref(uv->v, &uv->tv);
  68.   return uv;
  69. }

  70. /* Close all open upvalues pointing to some stack level or above. */
  71. void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level)
  72. {
  73.   GCupval *uv;
  74.   global_State *g = G(L);
  75.   while (gcref(L->openupval) != NULL &&
  76.          uvval((uv = gco2uv(gcref(L->openupval)))) >= level) {
  77.     GCobj *o = obj2gco(uv);
  78.     lua_assert(!isblack(o) && !uv->closed && uvval(uv) != &uv->tv);
  79.     setgcrefr(L->openupval, uv->nextgc);  /* No longer in open list. */
  80.     if (isdead(g, o)) {
  81.       lj_func_freeuv(g, uv);
  82.     } else {
  83.       unlinkuv(uv);
  84.       lj_gc_closeuv(g, uv);
  85.     }
  86.   }
  87. }

  88. void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv)
  89. {
  90.   if (!uv->closed)
  91.     unlinkuv(uv);
  92.   lj_mem_freet(g, uv);
  93. }

  94. /* -- Functions (closures) ------------------------------------------------ */

  95. GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env)
  96. {
  97.   GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeCfunc(nelems));
  98.   fn->c.gct = ~LJ_TFUNC;
  99.   fn->c.ffid = FF_C;
  100.   fn->c.nupvalues = (uint8_t)nelems;
  101.   /* NOBARRIER: The GCfunc is new (marked white). */
  102.   setmref(fn->c.pc, &G(L)->bc_cfunc_ext);
  103.   setgcref(fn->c.env, obj2gco(env));
  104.   return fn;
  105. }

  106. static GCfunc *func_newL(lua_State *L, GCproto *pt, GCtab *env)
  107. {
  108.   uint32_t count;
  109.   GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv));
  110.   fn->l.gct = ~LJ_TFUNC;
  111.   fn->l.ffid = FF_LUA;
  112.   fn->l.nupvalues = 0/* Set to zero until upvalues are initialized. */
  113.   /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */
  114.   setmref(fn->l.pc, proto_bc(pt));
  115.   setgcref(fn->l.env, obj2gco(env));
  116.   /* Saturating 3 bit counter (0..7) for created closures. */
  117.   count = (uint32_t)pt->flags + PROTO_CLCOUNT;
  118.   pt->flags = (uint8_t)(count - ((count >> PROTO_CLC_BITS) & PROTO_CLCOUNT));
  119.   return fn;
  120. }

  121. /* Create a new Lua function with empty upvalues. */
  122. GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env)
  123. {
  124.   GCfunc *fn = func_newL(L, pt, env);
  125.   MSize i, nuv = pt->sizeuv;
  126.   /* NOBARRIER: The GCfunc is new (marked white). */
  127.   for (i = 0; i < nuv; i++) {
  128.     GCupval *uv = func_emptyuv(L);
  129.     uv->dhash = (uint32_t)(uintptr_t)pt ^ ((uint32_t)proto_uv(pt)[i] << 24);
  130.     setgcref(fn->l.uvptr[i], obj2gco(uv));
  131.   }
  132.   fn->l.nupvalues = (uint8_t)nuv;
  133.   return fn;
  134. }

  135. /* Do a GC check and create a new Lua function with inherited upvalues. */
  136. GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent)
  137. {
  138.   GCfunc *fn;
  139.   GCRef *puv;
  140.   MSize i, nuv;
  141.   TValue *base;
  142.   lj_gc_check_fixtop(L);
  143.   fn = func_newL(L, pt, tabref(parent->env));
  144.   /* NOBARRIER: The GCfunc is new (marked white). */
  145.   puv = parent->uvptr;
  146.   nuv = pt->sizeuv;
  147.   base = L->base;
  148.   for (i = 0; i < nuv; i++) {
  149.     uint32_t v = proto_uv(pt)[i];
  150.     GCupval *uv;
  151.     if ((v & PROTO_UV_LOCAL)) {
  152.       uv = func_finduv(L, base + (v & 0xff));
  153.       uv->immutable = ((v / PROTO_UV_IMMUTABLE) & 1);
  154.       uv->dhash = (uint32_t)(uintptr_t)mref(parent->pc, char) ^ (v << 24);
  155.     } else {
  156.       uv = &gcref(puv[v])->uv;
  157.     }
  158.     setgcref(fn->l.uvptr[i], obj2gco(uv));
  159.   }
  160.   fn->l.nupvalues = (uint8_t)nuv;
  161.   return fn;
  162. }

  163. void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *fn)
  164. {
  165.   MSize size = isluafunc(fn) ? sizeLfunc((MSize)fn->l.nupvalues) :
  166.                                sizeCfunc((MSize)fn->c.nupvalues);
  167.   lj_mem_free(g, fn, size);
  168. }