From 92fa45f9eb5d9aa732c6b972a85c26120d7612b4 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sun, 8 Dec 2019 19:56:56 +0100 Subject: [PATCH] Fix interaction between profiler hooks and finalizers. Thanks to Julien Desgats. --- src/lj_gc.c | 2 ++ src/lj_obj.h | 3 ++- src/lj_profile.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/lj_gc.c b/src/lj_gc.c index 2aaf5b2c..012d0879 100644 --- a/src/lj_gc.c +++ b/src/lj_gc.c @@ -466,6 +466,7 @@ static void gc_call_finalizer(global_State *g, lua_State *L, 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); @@ -474,6 +475,7 @@ static void gc_call_finalizer(global_State *g, lua_State *L, L->top = top+1; errcode = lj_vm_pcall(L, top, 1+0, -1); /* Stack: |mo|o| -> | */ hook_restore(g, oldh); + if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g); g->gc.threshold = oldt; /* Restore GC threshold. */ if (errcode) lj_err_throw(L, errcode); /* Propagate errors. */ diff --git a/src/lj_obj.h b/src/lj_obj.h index 72b7ace8..5d5cc49b 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -638,7 +638,8 @@ typedef struct global_State { #define HOOK_PROFILE 0x80 #define hook_active(g) ((g)->hookmask & HOOK_ACTIVE) #define hook_enter(g) ((g)->hookmask |= HOOK_ACTIVE) -#define hook_entergc(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_GC)) +#define hook_entergc(g) \ + ((g)->hookmask = ((g)->hookmask | (HOOK_ACTIVE|HOOK_GC)) & ~HOOK_PROFILE) #define hook_vmevent(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_VMEVENT)) #define hook_leave(g) ((g)->hookmask &= ~HOOK_ACTIVE) #define hook_save(g) ((g)->hookmask & ~HOOK_EVENTMASK) diff --git a/src/lj_profile.c b/src/lj_profile.c index 3223697f..e2966e0c 100644 --- a/src/lj_profile.c +++ b/src/lj_profile.c @@ -153,7 +153,7 @@ static void profile_trigger(ProfileState *ps) profile_lock(ps); ps->samples++; /* Always increment number of samples. */ mask = g->hookmask; - if (!(mask & (HOOK_PROFILE|HOOK_VMEVENT))) { /* Set profile hook. */ + if (!(mask & (HOOK_PROFILE|HOOK_VMEVENT|HOOK_GC))) { /* Set profile hook. */ int st = g->vmstate; ps->vmstate = st >= 0 ? 'N' : st == ~LJ_VMST_INTERP ? 'I' :