lj_func.c (7860B)
1 /* 2 ** Function handling (prototypes, functions and upvalues). 3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h 4 ** 5 ** Upvalue handling rewrite and closure lifting. 6 ** Copyright (C) 2014 Karel Tuma. See Copyright Notice in luajit.h 7 ** 8 ** Portions taken verbatim or adapted from the Lua interpreter. 9 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h 10 */ 11 12 #define lj_func_c 13 #define LUA_CORE 14 15 #include "lj_obj.h" 16 #include "lj_gc.h" 17 #include "lj_func.h" 18 #include "lj_trace.h" 19 #include "lj_vm.h" 20 21 /* -- Prototypes ---------------------------------------------------------- */ 22 23 void LJ_FASTCALL lj_func_freeproto(global_State *g, GCproto *pt) 24 { 25 lj_mem_free(g, pt, pt->sizept); 26 } 27 28 /* -- Upvalues ------------------------------------------------------------ */ 29 30 static void unlinkuv(GCupval *uv) 31 { 32 lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv); 33 setgcrefr(uvnext(uv)->prev, uv->prev); 34 setgcrefr(uvprev(uv)->next, uv->next); 35 } 36 37 /* Find existing open upvalue for a stack slot or create a new one. */ 38 static GCupval *func_finduv(lua_State *L, TValue *slot) 39 { 40 global_State *g = G(L); 41 GCRef *pp = &L->openupval; 42 GCupval *p; 43 GCupval *uv; 44 /* Search the sorted list of open upvalues. */ 45 while (gcref(*pp) != NULL && uvval((p = gco2uv(gcref(*pp)))) >= slot) { 46 lua_assert(!p->closed && uvval(p) != &p->tv); 47 if (uvval(p) == slot) { /* Found open upvalue pointing to same slot? */ 48 if (isdead(g, obj2gco(p))) /* Resurrect it, if it's dead. */ 49 flipwhite(obj2gco(p)); 50 return p; 51 } 52 pp = &p->nextgc; 53 } 54 /* No matching upvalue found. Create a new one. */ 55 uv = lj_mem_newt(L, sizeof(GCupval), GCupval); 56 newwhite(g, uv); 57 uv->gct = ~LJ_TUPVAL; 58 uv->closed = 0; /* Still open. */ 59 setmref(uv->v, slot); /* Pointing to the stack slot. */ 60 /* NOBARRIER: The GCupval is new (marked white) and open. */ 61 setgcrefr(uv->nextgc, *pp); /* Insert into sorted list of open upvalues. */ 62 setgcref(*pp, obj2gco(uv)); 63 setgcref(uv->prev, obj2gco(&g->uvhead)); /* Insert into GC list, too. */ 64 setgcrefr(uv->next, g->uvhead.next); 65 setgcref(uvnext(uv)->prev, obj2gco(uv)); 66 setgcref(g->uvhead.next, obj2gco(uv)); 67 lua_assert(uvprev(uvnext(uv)) == uv && uvnext(uvprev(uv)) == uv); 68 return uv; 69 } 70 71 /* Create an empty and closed upvalue. */ 72 static GCupval *func_emptyuv(lua_State *L) 73 { 74 GCupval *uv = (GCupval *)lj_mem_newgco(L, sizeof(GCupval)); 75 uv->gct = ~LJ_TUPVAL; 76 uv->closed = 1; 77 setnilV(&uv->tv); 78 setmref(uv->v, &uv->tv); 79 return uv; 80 } 81 82 /* Close all open upvalues pointing to some stack level or above. */ 83 void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level) 84 { 85 GCupval *uv; 86 global_State *g = G(L); 87 while (gcref(L->openupval) != NULL && 88 uvval((uv = gco2uv(gcref(L->openupval)))) >= level) { 89 GCobj *o = obj2gco(uv); 90 lua_assert(!isblack(o) && !uv->closed && uvval(uv) != &uv->tv); 91 setgcrefr(L->openupval, uv->nextgc); /* No longer in open list. */ 92 if (isdead(g, o)) { 93 lj_func_freeuv(g, uv); 94 } else { 95 unlinkuv(uv); 96 lj_gc_closeuv(g, uv); 97 } 98 } 99 } 100 101 void LJ_FASTCALL lj_func_freeuv(global_State *g, GCupval *uv) 102 { 103 if (!uv->closed) 104 unlinkuv(uv); 105 lj_mem_freet(g, uv); 106 } 107 108 /* -- Functions (closures) ------------------------------------------------ */ 109 110 GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env) 111 { 112 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeCfunc(nelems)); 113 fn->c.gct = ~LJ_TFUNC; 114 fn->c.ffid = FF_C; 115 fn->c.nupvalues = (uint8_t)nelems; 116 /* NOBARRIER: The GCfunc is new (marked white). */ 117 setmref(fn->c.pc, &G(L)->bc_cfunc_ext); 118 setgcref(fn->c.env, obj2gco(env)); 119 return fn; 120 } 121 122 static GCfunc *func_newL(lua_State *L, GCproto *pt, GCtab *env) 123 { 124 uint32_t count; 125 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv)); 126 /* Initially points to itself */ 127 setgcref(fn->l.prev_ENV, obj2gco(fn)); 128 setgcref(fn->l.next_ENV, obj2gco(fn)); 129 fn->l.gct = ~LJ_TFUNC; 130 fn->l.ffid = FF_LUA; 131 fn->l.nupvalues = 0; /* Set to zero until upvalues are initialized. */ 132 /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */ 133 setmref(fn->l.pc, proto_bc(pt)); 134 setgcref(fn->l.env, obj2gco(env)); 135 /* Saturating 3 bit counter (0..7) for created closures. */ 136 count = (uint32_t)pt->flags + PROTO_CLCOUNT; 137 pt->flags = (uint8_t)(count - ((count >> PROTO_CLC_BITS) & PROTO_CLCOUNT)); 138 return fn; 139 } 140 141 static GCfunc *lj_func_newL(lua_State *L, GCproto *pt, GCfuncL *parent); 142 /* Recursively instantiate closures */ 143 static inline 144 void lj_func_init_closure(lua_State *L, uintptr_t i, GCproto *pttab, GCfuncL *parent, GCupval *uv) 145 { 146 setfuncV(L, &uv->tv, lj_func_newL(L, &proto_kgc(pttab, (~i))->pt, parent)); 147 } 148 149 /* Create a new Lua function with empty upvalues. */ 150 GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env) 151 { 152 GCfunc *fn = func_newL(L, pt, env); 153 MSize i, nuv = pt->sizeuv; 154 for (i = 0; i < nuv; i++) { 155 GCupval *uv = func_emptyuv(L); 156 uint32_t v = proto_uv(pt)[i]; 157 uint8_t flags = (v >> PROTO_UV_SHIFT); 158 if (flags == UV_HOLE) { 159 setgcrefnull(fn->l.uvptr[i]); 160 continue; 161 } 162 uv->flags = flags; 163 uv->dhash = (uint32_t)(uintptr_t)pt ^ ((uint32_t)proto_uv(pt)[i] << 24); 164 /* NOBARRIER: The GCfunc is new (marked white). */ 165 setgcref(fn->l.uvptr[i], obj2gco(uv)); 166 /* TBD: sub-closures and env barriers? */ 167 if (flags == UV_ENV) { 168 settabV(L, &uv->tv, env); 169 } else if (flags == UV_CLOSURE) 170 lj_func_init_closure(L, v & PROTO_UV_MASK, pt, &fn->l, uv); 171 } 172 fn->l.nupvalues = (uint8_t)nuv; 173 return fn; 174 } 175 176 /* Do a GC check and create a new Lua function with inherited upvalues. */ 177 static GCfunc *lj_func_newL(lua_State *L, GCproto *pt, GCfuncL *parent) 178 { 179 GCfunc *fn; 180 GCRef *puv; 181 MSize i, nuv; 182 TValue *base; 183 184 fn = func_newL(L, pt, tabref(parent->env)); 185 /* NOBARRIER: The GCfunc is new (marked white). */ 186 puv = parent->uvptr; 187 nuv = pt->sizeuv; 188 base = L->base; 189 190 fn->l.nupvalues = 0; 191 /* TBD: sub-closures and env barriers? */ 192 for (i = 0; i < nuv; i++) { 193 uint32_t v = proto_uv(pt)[i]; 194 GCupval *uv; 195 switch (v >> PROTO_UV_SHIFT) { 196 case UV_CLOSURE: 197 uv = func_emptyuv(L); 198 uv->flags = v >> PROTO_UV_SHIFT; 199 setgcref(fn->l.uvptr[i], obj2gco(uv)); 200 lj_func_init_closure(L, v & PROTO_UV_MASK, pt, &fn->l, uv); 201 break; 202 case UV_ENV: 203 //lua_assert(0); 204 case UV_CHAINED: 205 uv = &gcref(puv[v & PROTO_UV_MASK])->uv; 206 lua_assert(uv); 207 if (uv->flags & UV_ENV) { 208 setgcref(fn->l.next_ENV, obj2gco(parent)); 209 fn->l.prev_ENV = parent->prev_ENV; 210 setgcref(gcref(fn->l.prev_ENV)->fn.l.next_ENV, obj2gco(fn)); 211 setgcref(parent->prev_ENV, obj2gco(fn)); 212 } 213 setgcref(fn->l.uvptr[i], obj2gco(uv)); 214 break; 215 case UV_IMMUTABLE: 216 case UV_LOCAL: 217 uv = func_finduv(L, base + (v & 0xff)); 218 uv->flags = v >> PROTO_UV_SHIFT; 219 uv->dhash = (uint32_t)(uintptr_t)mref(parent->pc, char) ^ (v << 24); 220 setgcref(fn->l.uvptr[i], obj2gco(uv)); 221 break; 222 case UV_HOLE: 223 setgcrefnull(fn->l.uvptr[i]); 224 continue; 225 default: 226 lua_assert(0); 227 } 228 } 229 fn->l.nupvalues = (uint8_t)nuv; 230 return fn; 231 } 232 233 GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent) 234 { 235 lj_gc_check_fixtop(L); 236 return lj_func_newL(L, pt, parent); 237 } 238 239 void LJ_FASTCALL lj_func_free(global_State *g, GCfunc *fn) 240 { 241 MSize size = isluafunc(fn) ? sizeLfunc((MSize)fn->l.nupvalues) : 242 sizeCfunc((MSize)fn->c.nupvalues); 243 /* NOBARRIER: Should be handled in ESETV/lua_setupvalue. */ 244 if (isluafunc(fn)) { 245 setgcrefr(gcref(fn->l.next_ENV)->fn.l.prev_ENV, fn->l.prev_ENV); 246 setgcrefr(gcref(fn->l.prev_ENV)->fn.l.next_ENV, fn->l.next_ENV); 247 } 248 lj_mem_free(g, fn, size); 249 } 250