diff options
Diffstat (limited to 'src/lj_state.c')
-rw-r--r-- | src/lj_state.c | 112 |
1 files changed, 80 insertions, 32 deletions
diff --git a/src/lj_state.c b/src/lj_state.c index 1e2cfde9..0b9c46ba 100644 --- a/src/lj_state.c +++ b/src/lj_state.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include "lj_obj.h" | 12 | #include "lj_obj.h" |
13 | #include "lj_gc.h" | 13 | #include "lj_gc.h" |
14 | #include "lj_err.h" | 14 | #include "lj_err.h" |
15 | #include "lj_buf.h" | ||
15 | #include "lj_str.h" | 16 | #include "lj_str.h" |
16 | #include "lj_tab.h" | 17 | #include "lj_tab.h" |
17 | #include "lj_func.h" | 18 | #include "lj_func.h" |
@@ -24,8 +25,10 @@ | |||
24 | #include "lj_trace.h" | 25 | #include "lj_trace.h" |
25 | #include "lj_dispatch.h" | 26 | #include "lj_dispatch.h" |
26 | #include "lj_vm.h" | 27 | #include "lj_vm.h" |
28 | #include "lj_prng.h" | ||
27 | #include "lj_lex.h" | 29 | #include "lj_lex.h" |
28 | #include "lj_alloc.h" | 30 | #include "lj_alloc.h" |
31 | #include "luajit.h" | ||
29 | 32 | ||
30 | /* -- Stack handling ------------------------------------------------------ */ | 33 | /* -- Stack handling ------------------------------------------------------ */ |
31 | 34 | ||
@@ -47,6 +50,7 @@ | |||
47 | ** one extra slot if mobj is not a function. Only lj_meta_tset needs 5 | 50 | ** one extra slot if mobj is not a function. Only lj_meta_tset needs 5 |
48 | ** slots above top, but then mobj is always a function. So we can get by | 51 | ** slots above top, but then mobj is always a function. So we can get by |
49 | ** with 5 extra slots. | 52 | ** with 5 extra slots. |
53 | ** LJ_FR2: We need 2 more slots for the frame PC and the continuation PC. | ||
50 | */ | 54 | */ |
51 | 55 | ||
52 | /* Resize stack slots and adjust pointers in state. */ | 56 | /* Resize stack slots and adjust pointers in state. */ |
@@ -57,9 +61,10 @@ static void resizestack(lua_State *L, MSize n) | |||
57 | MSize oldsize = L->stacksize; | 61 | MSize oldsize = L->stacksize; |
58 | MSize realsize = n + 1 + LJ_STACK_EXTRA; | 62 | MSize realsize = n + 1 + LJ_STACK_EXTRA; |
59 | GCobj *up; | 63 | GCobj *up; |
60 | lua_assert((MSize)(tvref(L->maxstack)-oldst)==L->stacksize-LJ_STACK_EXTRA-1); | 64 | lj_assertL((MSize)(tvref(L->maxstack)-oldst) == L->stacksize-LJ_STACK_EXTRA-1, |
65 | "inconsistent stack size"); | ||
61 | st = (TValue *)lj_mem_realloc(L, tvref(L->stack), | 66 | st = (TValue *)lj_mem_realloc(L, tvref(L->stack), |
62 | (MSize)(L->stacksize*sizeof(TValue)), | 67 | (MSize)(oldsize*sizeof(TValue)), |
63 | (MSize)(realsize*sizeof(TValue))); | 68 | (MSize)(realsize*sizeof(TValue))); |
64 | setmref(L->stack, st); | 69 | setmref(L->stack, st); |
65 | delta = (char *)st - (char *)oldst; | 70 | delta = (char *)st - (char *)oldst; |
@@ -67,12 +72,12 @@ static void resizestack(lua_State *L, MSize n) | |||
67 | while (oldsize < realsize) /* Clear new slots. */ | 72 | while (oldsize < realsize) /* Clear new slots. */ |
68 | setnilV(st + oldsize++); | 73 | setnilV(st + oldsize++); |
69 | L->stacksize = realsize; | 74 | L->stacksize = realsize; |
75 | if ((size_t)(mref(G(L)->jit_base, char) - (char *)oldst) < oldsize) | ||
76 | setmref(G(L)->jit_base, mref(G(L)->jit_base, char) + delta); | ||
70 | L->base = (TValue *)((char *)L->base + delta); | 77 | L->base = (TValue *)((char *)L->base + delta); |
71 | L->top = (TValue *)((char *)L->top + delta); | 78 | L->top = (TValue *)((char *)L->top + delta); |
72 | for (up = gcref(L->openupval); up != NULL; up = gcnext(up)) | 79 | for (up = gcref(L->openupval); up != NULL; up = gcnext(up)) |
73 | setmref(gco2uv(up)->v, (TValue *)((char *)uvval(gco2uv(up)) + delta)); | 80 | setmref(gco2uv(up)->v, (TValue *)((char *)uvval(gco2uv(up)) + delta)); |
74 | if (obj2gco(L) == gcref(G(L)->jit_L)) | ||
75 | setmref(G(L)->jit_base, mref(G(L)->jit_base, char) + delta); | ||
76 | } | 81 | } |
77 | 82 | ||
78 | /* Relimit stack after error, in case the limit was overdrawn. */ | 83 | /* Relimit stack after error, in case the limit was overdrawn. */ |
@@ -89,7 +94,8 @@ void lj_state_shrinkstack(lua_State *L, MSize used) | |||
89 | return; /* Avoid stack shrinking while handling stack overflow. */ | 94 | return; /* Avoid stack shrinking while handling stack overflow. */ |
90 | if (4*used < L->stacksize && | 95 | if (4*used < L->stacksize && |
91 | 2*(LJ_STACK_START+LJ_STACK_EXTRA) < L->stacksize && | 96 | 2*(LJ_STACK_START+LJ_STACK_EXTRA) < L->stacksize && |
92 | obj2gco(L) != gcref(G(L)->jit_L)) /* Don't shrink stack of live trace. */ | 97 | /* Don't shrink stack of live trace. */ |
98 | (tvref(G(L)->jit_base) == NULL || obj2gco(L) != gcref(G(L)->cur_L))) | ||
93 | resizestack(L, L->stacksize >> 1); | 99 | resizestack(L, L->stacksize >> 1); |
94 | } | 100 | } |
95 | 101 | ||
@@ -125,8 +131,9 @@ static void stack_init(lua_State *L1, lua_State *L) | |||
125 | L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA; | 131 | L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA; |
126 | stend = st + L1->stacksize; | 132 | stend = st + L1->stacksize; |
127 | setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1); | 133 | setmref(L1->maxstack, stend - LJ_STACK_EXTRA - 1); |
128 | L1->base = L1->top = st+1; | 134 | setthreadV(L1, st++, L1); /* Needed for curr_funcisL() on empty stack. */ |
129 | setthreadV(L1, st, L1); /* Needed for curr_funcisL() on empty stack. */ | 135 | if (LJ_FR2) setnilV(st++); |
136 | L1->base = L1->top = st; | ||
130 | while (st < stend) /* Clear new slots. */ | 137 | while (st < stend) /* Clear new slots. */ |
131 | setnilV(st++); | 138 | setnilV(st++); |
132 | } | 139 | } |
@@ -143,12 +150,13 @@ static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud) | |||
143 | /* NOBARRIER: State initialization, all objects are white. */ | 150 | /* NOBARRIER: State initialization, all objects are white. */ |
144 | setgcref(L->env, obj2gco(lj_tab_new(L, 0, LJ_MIN_GLOBAL))); | 151 | setgcref(L->env, obj2gco(lj_tab_new(L, 0, LJ_MIN_GLOBAL))); |
145 | settabV(L, registry(L), lj_tab_new(L, 0, LJ_MIN_REGISTRY)); | 152 | settabV(L, registry(L), lj_tab_new(L, 0, LJ_MIN_REGISTRY)); |
146 | lj_str_resize(L, LJ_MIN_STRTAB-1); | 153 | lj_str_init(L); |
147 | lj_meta_init(L); | 154 | lj_meta_init(L); |
148 | lj_lex_init(L); | 155 | lj_lex_init(L); |
149 | fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */ | 156 | fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */ |
150 | g->gc.threshold = 4*g->gc.total; | 157 | g->gc.threshold = 4*g->gc.total; |
151 | lj_trace_initstate(g); | 158 | lj_trace_initstate(g); |
159 | lj_err_verify(); | ||
152 | return NULL; | 160 | return NULL; |
153 | } | 161 | } |
154 | 162 | ||
@@ -157,16 +165,25 @@ static void close_state(lua_State *L) | |||
157 | global_State *g = G(L); | 165 | global_State *g = G(L); |
158 | lj_func_closeuv(L, tvref(L->stack)); | 166 | lj_func_closeuv(L, tvref(L->stack)); |
159 | lj_gc_freeall(g); | 167 | lj_gc_freeall(g); |
160 | lua_assert(gcref(g->gc.root) == obj2gco(L)); | 168 | lj_assertG(gcref(g->gc.root) == obj2gco(L), |
161 | lua_assert(g->strnum == 0); | 169 | "main thread is not first GC object"); |
170 | lj_assertG(g->str.num == 0, "leaked %d strings", g->str.num); | ||
162 | lj_trace_freestate(g); | 171 | lj_trace_freestate(g); |
163 | #if LJ_HASFFI | 172 | #if LJ_HASFFI |
164 | lj_ctype_freestate(g); | 173 | lj_ctype_freestate(g); |
165 | #endif | 174 | #endif |
166 | lj_mem_freevec(g, g->strhash, g->strmask+1, GCRef); | 175 | lj_str_freetab(g); |
167 | lj_str_freebuf(g, &g->tmpbuf); | 176 | lj_buf_free(g, &g->tmpbuf); |
168 | lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); | 177 | lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); |
169 | lua_assert(g->gc.total == sizeof(GG_State)); | 178 | #if LJ_64 |
179 | if (mref(g->gc.lightudseg, uint32_t)) { | ||
180 | MSize segnum = g->gc.lightudnum ? (2 << lj_fls(g->gc.lightudnum)) : 2; | ||
181 | lj_mem_freevec(g, mref(g->gc.lightudseg, uint32_t), segnum, uint32_t); | ||
182 | } | ||
183 | #endif | ||
184 | lj_assertG(g->gc.total == sizeof(GG_State), | ||
185 | "memory leak of %lld bytes", | ||
186 | (long long)(g->gc.total - sizeof(GG_State))); | ||
170 | #ifndef LUAJIT_USE_SYSMALLOC | 187 | #ifndef LUAJIT_USE_SYSMALLOC |
171 | if (g->allocf == lj_alloc_f) | 188 | if (g->allocf == lj_alloc_f) |
172 | lj_alloc_destroy(g->allocd); | 189 | lj_alloc_destroy(g->allocd); |
@@ -175,17 +192,34 @@ static void close_state(lua_State *L) | |||
175 | g->allocf(g->allocd, G2GG(g), sizeof(GG_State), 0); | 192 | g->allocf(g->allocd, G2GG(g), sizeof(GG_State), 0); |
176 | } | 193 | } |
177 | 194 | ||
178 | #if LJ_64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) | 195 | #if LJ_64 && !LJ_GC64 && !(defined(LUAJIT_USE_VALGRIND) && defined(LUAJIT_USE_SYSMALLOC)) |
179 | lua_State *lj_state_newstate(lua_Alloc f, void *ud) | 196 | lua_State *lj_state_newstate(lua_Alloc allocf, void *allocd) |
180 | #else | 197 | #else |
181 | LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | 198 | LUA_API lua_State *lua_newstate(lua_Alloc allocf, void *allocd) |
182 | #endif | 199 | #endif |
183 | { | 200 | { |
184 | GG_State *GG = (GG_State *)f(ud, NULL, 0, sizeof(GG_State)); | 201 | PRNGState prng; |
185 | lua_State *L = &GG->L; | 202 | GG_State *GG; |
186 | global_State *g = &GG->g; | 203 | lua_State *L; |
187 | if (GG == NULL || !checkptr32(GG)) return NULL; | 204 | global_State *g; |
205 | /* We need the PRNG for the memory allocator, so initialize this first. */ | ||
206 | if (!lj_prng_seed_secure(&prng)) { | ||
207 | lj_assertX(0, "secure PRNG seeding failed"); | ||
208 | /* Can only return NULL here, so this errors with "not enough memory". */ | ||
209 | return NULL; | ||
210 | } | ||
211 | #ifndef LUAJIT_USE_SYSMALLOC | ||
212 | if (allocf == LJ_ALLOCF_INTERNAL) { | ||
213 | allocd = lj_alloc_create(&prng); | ||
214 | if (!allocd) return NULL; | ||
215 | allocf = lj_alloc_f; | ||
216 | } | ||
217 | #endif | ||
218 | GG = (GG_State *)allocf(allocd, NULL, 0, sizeof(GG_State)); | ||
219 | if (GG == NULL || !checkptrGC(GG)) return NULL; | ||
188 | memset(GG, 0, sizeof(GG_State)); | 220 | memset(GG, 0, sizeof(GG_State)); |
221 | L = &GG->L; | ||
222 | g = &GG->g; | ||
189 | L->gct = ~LJ_TTHREAD; | 223 | L->gct = ~LJ_TTHREAD; |
190 | L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ | 224 | L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */ |
191 | L->dummy_ffid = FF_C; | 225 | L->dummy_ffid = FF_C; |
@@ -193,17 +227,25 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | |||
193 | g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; | 227 | g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED; |
194 | g->strempty.marked = LJ_GC_WHITE0; | 228 | g->strempty.marked = LJ_GC_WHITE0; |
195 | g->strempty.gct = ~LJ_TSTR; | 229 | g->strempty.gct = ~LJ_TSTR; |
196 | g->allocf = f; | 230 | g->allocf = allocf; |
197 | g->allocd = ud; | 231 | g->allocd = allocd; |
232 | g->prng = prng; | ||
233 | #ifndef LUAJIT_USE_SYSMALLOC | ||
234 | if (allocf == lj_alloc_f) { | ||
235 | lj_alloc_setprng(allocd, &g->prng); | ||
236 | } | ||
237 | #endif | ||
198 | setgcref(g->mainthref, obj2gco(L)); | 238 | setgcref(g->mainthref, obj2gco(L)); |
199 | setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); | 239 | setgcref(g->uvhead.prev, obj2gco(&g->uvhead)); |
200 | setgcref(g->uvhead.next, obj2gco(&g->uvhead)); | 240 | setgcref(g->uvhead.next, obj2gco(&g->uvhead)); |
201 | g->strmask = ~(MSize)0; | 241 | g->str.mask = ~(MSize)0; |
202 | setnilV(registry(L)); | 242 | setnilV(registry(L)); |
203 | setnilV(&g->nilnode.val); | 243 | setnilV(&g->nilnode.val); |
204 | setnilV(&g->nilnode.key); | 244 | setnilV(&g->nilnode.key); |
245 | #if !LJ_GC64 | ||
205 | setmref(g->nilnode.freetop, &g->nilnode); | 246 | setmref(g->nilnode.freetop, &g->nilnode); |
206 | lj_str_initbuf(&g->tmpbuf); | 247 | #endif |
248 | lj_buf_init(NULL, &g->tmpbuf); | ||
207 | g->gc.state = GCSpause; | 249 | g->gc.state = GCSpause; |
208 | setgcref(g->gc.root, obj2gco(L)); | 250 | setgcref(g->gc.root, obj2gco(L)); |
209 | setmref(g->gc.sweep, &g->gc.root); | 251 | setmref(g->gc.sweep, &g->gc.root); |
@@ -217,7 +259,7 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud) | |||
217 | close_state(L); | 259 | close_state(L); |
218 | return NULL; | 260 | return NULL; |
219 | } | 261 | } |
220 | L->status = 0; | 262 | L->status = LUA_OK; |
221 | return L; | 263 | return L; |
222 | } | 264 | } |
223 | 265 | ||
@@ -236,6 +278,10 @@ LUA_API void lua_close(lua_State *L) | |||
236 | global_State *g = G(L); | 278 | global_State *g = G(L); |
237 | int i; | 279 | int i; |
238 | L = mainthread(g); /* Only the main thread can be closed. */ | 280 | L = mainthread(g); /* Only the main thread can be closed. */ |
281 | #if LJ_HASPROFILE | ||
282 | luaJIT_profile_stop(L); | ||
283 | #endif | ||
284 | setgcrefnull(g->cur_L); | ||
239 | lj_func_closeuv(L, tvref(L->stack)); | 285 | lj_func_closeuv(L, tvref(L->stack)); |
240 | lj_gc_separateudata(g, 1); /* Separate udata which have GC metamethods. */ | 286 | lj_gc_separateudata(g, 1); /* Separate udata which have GC metamethods. */ |
241 | #if LJ_HASJIT | 287 | #if LJ_HASJIT |
@@ -245,10 +291,10 @@ LUA_API void lua_close(lua_State *L) | |||
245 | #endif | 291 | #endif |
246 | for (i = 0;;) { | 292 | for (i = 0;;) { |
247 | hook_enter(g); | 293 | hook_enter(g); |
248 | L->status = 0; | 294 | L->status = LUA_OK; |
295 | L->base = L->top = tvref(L->stack) + 1 + LJ_FR2; | ||
249 | L->cframe = NULL; | 296 | L->cframe = NULL; |
250 | L->base = L->top = tvref(L->stack) + 1; | 297 | if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == LUA_OK) { |
251 | if (lj_vm_cpcall(L, NULL, NULL, cpfinalize) == 0) { | ||
252 | if (++i >= 10) break; | 298 | if (++i >= 10) break; |
253 | lj_gc_separateudata(g, 1); /* Separate udata again. */ | 299 | lj_gc_separateudata(g, 1); /* Separate udata again. */ |
254 | if (gcref(g->gc.mmudata) == NULL) /* Until nothing is left to do. */ | 300 | if (gcref(g->gc.mmudata) == NULL) /* Until nothing is left to do. */ |
@@ -263,7 +309,7 @@ lua_State *lj_state_new(lua_State *L) | |||
263 | lua_State *L1 = lj_mem_newobj(L, lua_State); | 309 | lua_State *L1 = lj_mem_newobj(L, lua_State); |
264 | L1->gct = ~LJ_TTHREAD; | 310 | L1->gct = ~LJ_TTHREAD; |
265 | L1->dummy_ffid = FF_C; | 311 | L1->dummy_ffid = FF_C; |
266 | L1->status = 0; | 312 | L1->status = LUA_OK; |
267 | L1->stacksize = 0; | 313 | L1->stacksize = 0; |
268 | setmref(L1->stack, NULL); | 314 | setmref(L1->stack, NULL); |
269 | L1->cframe = NULL; | 315 | L1->cframe = NULL; |
@@ -272,15 +318,17 @@ lua_State *lj_state_new(lua_State *L) | |||
272 | setmrefr(L1->glref, L->glref); | 318 | setmrefr(L1->glref, L->glref); |
273 | setgcrefr(L1->env, L->env); | 319 | setgcrefr(L1->env, L->env); |
274 | stack_init(L1, L); /* init stack */ | 320 | stack_init(L1, L); /* init stack */ |
275 | lua_assert(iswhite(obj2gco(L1))); | 321 | lj_assertL(iswhite(obj2gco(L1)), "new thread object is not white"); |
276 | return L1; | 322 | return L1; |
277 | } | 323 | } |
278 | 324 | ||
279 | void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L) | 325 | void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L) |
280 | { | 326 | { |
281 | lua_assert(L != mainthread(g)); | 327 | lj_assertG(L != mainthread(g), "free of main thread"); |
328 | if (obj2gco(L) == gcref(g->cur_L)) | ||
329 | setgcrefnull(g->cur_L); | ||
282 | lj_func_closeuv(L, tvref(L->stack)); | 330 | lj_func_closeuv(L, tvref(L->stack)); |
283 | lua_assert(gcref(L->openupval) == NULL); | 331 | lj_assertG(gcref(L->openupval) == NULL, "stale open upvalues"); |
284 | lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); | 332 | lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); |
285 | lj_mem_freet(g, L); | 333 | lj_mem_freet(g, L); |
286 | } | 334 | } |