summaryrefslogtreecommitdiff
path: root/src/lj_func.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_func.c')
-rw-r--r--src/lj_func.c37
1 files changed, 32 insertions, 5 deletions
diff --git a/src/lj_func.c b/src/lj_func.c
index d7d37802..334ba4c8 100644
--- a/src/lj_func.c
+++ b/src/lj_func.c
@@ -65,6 +65,17 @@ static GCupval *func_finduv(lua_State *L, TValue *slot)
65 return uv; 65 return uv;
66} 66}
67 67
68/* Create an empty and closed upvalue. */
69static 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
68/* Close all open upvalues pointing to some stack level or above. */ 79/* Close all open upvalues pointing to some stack level or above. */
69void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level) 80void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level)
70{ 81{
@@ -105,30 +116,45 @@ GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env)
105 return fn; 116 return fn;
106} 117}
107 118
108GCfunc *lj_func_newL(lua_State *L, GCproto *pt, GCtab *env) 119static GCfunc *func_newL(lua_State *L, GCproto *pt, GCtab *env)
109{ 120{
110 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv)); 121 GCfunc *fn = (GCfunc *)lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv));
111 fn->l.gct = ~LJ_TFUNC; 122 fn->l.gct = ~LJ_TFUNC;
112 fn->l.ffid = FF_LUA; 123 fn->l.ffid = FF_LUA;
113 fn->l.nupvalues = (uint8_t)pt->sizeuv; 124 fn->l.nupvalues = 0; /* Set to zero until upvalues are initialized. */
114 /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */ 125 /* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */
115 setmref(fn->l.pc, proto_bc(pt)); 126 setmref(fn->l.pc, proto_bc(pt));
116 setgcref(fn->l.env, obj2gco(env)); 127 setgcref(fn->l.env, obj2gco(env));
117 return fn; 128 return fn;
118} 129}
119 130
131/* Create a new Lua function with empty upvalues. */
132GCfunc *lj_func_newL_empty(lua_State *L, GCproto *pt, GCtab *env)
133{
134 GCfunc *fn = func_newL(L, pt, env);
135 MSize i, nuv = pt->sizeuv;
136 /* NOBARRIER: The GCfunc is new (marked white). */
137 for (i = 0; i < nuv; i++) {
138 GCupval *uv = func_emptyuv(L);
139 uv->dhash = (uint32_t)(uintptr_t)pt ^ ((uint32_t)proto_uv(pt)[i] << 24);
140 setgcref(fn->l.uvptr[i], obj2gco(uv));
141 }
142 fn->l.nupvalues = (uint8_t)nuv;
143 return fn;
144}
145
120/* Do a GC check and create a new Lua function with inherited upvalues. */ 146/* Do a GC check and create a new Lua function with inherited upvalues. */
121GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent) 147GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent)
122{ 148{
123 GCfunc *fn; 149 GCfunc *fn;
124 GCRef *puv; 150 GCRef *puv;
125 uint32_t i, nuv; 151 MSize i, nuv;
126 TValue *base; 152 TValue *base;
127 lj_gc_check_fixtop(L); 153 lj_gc_check_fixtop(L);
128 fn = lj_func_newL(L, pt, tabref(parent->env)); 154 fn = func_newL(L, pt, tabref(parent->env));
129 /* NOBARRIER: The GCfunc is new (marked white). */ 155 /* NOBARRIER: The GCfunc is new (marked white). */
130 puv = parent->uvptr; 156 puv = parent->uvptr;
131 nuv = fn->l.nupvalues; 157 nuv = pt->sizeuv;
132 base = L->base; 158 base = L->base;
133 for (i = 0; i < nuv; i++) { 159 for (i = 0; i < nuv; i++) {
134 uint32_t v = proto_uv(pt)[i]; 160 uint32_t v = proto_uv(pt)[i];
@@ -141,6 +167,7 @@ GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent)
141 } 167 }
142 setgcref(fn->l.uvptr[i], obj2gco(uv)); 168 setgcref(fn->l.uvptr[i], obj2gco(uv));
143 } 169 }
170 fn->l.nupvalues = (uint8_t)nuv;
144 return fn; 171 return fn;
145} 172}
146 173