Run VM events and finalizers in separate state.
Reported by Sergey Kaplun. #1403
This commit is contained in:
18
src/lj_gc.c
18
src/lj_gc.c
@@ -106,6 +106,7 @@ static void gc_mark_start(global_State *g)
|
||||
setgcrefnull(g->gc.weak);
|
||||
gc_markobj(g, mainthread(g));
|
||||
gc_markobj(g, tabref(mainthread(g)->env));
|
||||
gc_markobj(g, vmthread(g));
|
||||
gc_marktv(g, &g->registrytv);
|
||||
gc_mark_gcroot(g);
|
||||
g->gc.state = GCSpropagate;
|
||||
@@ -507,24 +508,25 @@ static void gc_call_finalizer(global_State *g, lua_State *L,
|
||||
uint8_t oldh = hook_save(g);
|
||||
GCSize oldt = g->gc.threshold;
|
||||
int errcode;
|
||||
lua_State *VL = vmthread(g);
|
||||
TValue *top;
|
||||
lj_trace_abort(g);
|
||||
hook_entergc(g); /* Disable hooks and new traces during __gc. */
|
||||
if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g);
|
||||
g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */
|
||||
top = L->top;
|
||||
copyTV(L, top++, mo);
|
||||
top = VL->top;
|
||||
copyTV(VL, top++, mo);
|
||||
if (LJ_FR2) setnilV(top++);
|
||||
setgcV(L, top, o, ~o->gch.gct);
|
||||
L->top = top+1;
|
||||
errcode = lj_vm_pcall(L, top, 1+0, -1); /* Stack: |mo|o| -> | */
|
||||
setgcV(VL, top, o, ~o->gch.gct);
|
||||
VL->top = top+1;
|
||||
errcode = lj_vm_pcall(VL, top, 1+0, -1); /* Stack: |mo|o| -> | */
|
||||
setgcref(g->cur_L, obj2gco(L));
|
||||
hook_restore(g, oldh);
|
||||
if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g);
|
||||
g->gc.threshold = oldt; /* Restore GC threshold. */
|
||||
if (errcode) {
|
||||
ptrdiff_t errobj = savestack(L, L->top-1); /* Stack may be resized. */
|
||||
lj_vmevent_send(L, ERRFIN,
|
||||
copyTV(L, L->top++, restorestack(L, errobj));
|
||||
lj_vmevent_send(g, ERRFIN,
|
||||
copyTV(V, V->top++, L->top-1);
|
||||
);
|
||||
L->top--;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user