diff options
Diffstat (limited to 'src/lj_func.c')
-rw-r--r-- | src/lj_func.c | 37 |
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. */ | ||
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 | |||
68 | /* Close all open upvalues pointing to some stack level or above. */ | 79 | /* Close all open upvalues pointing to some stack level or above. */ |
69 | void LJ_FASTCALL lj_func_closeuv(lua_State *L, TValue *level) | 80 | void 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 | ||
108 | GCfunc *lj_func_newL(lua_State *L, GCproto *pt, GCtab *env) | 119 | static 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. */ | ||
132 | GCfunc *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. */ |
121 | GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent) | 147 | GCfunc *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 | ||