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