#if LJ_TARGET_UNALIGNED
G(L)->tmptv.u64 = U64x(0000504d,4d500000);
#endif
- lj_dispatch_update(G(L));
+ lj_dispatch_update(G(L), 0);
#if LJ_TARGET_UNALIGNED
/* If you get a crash below then your toolchain indicates unaligned
** accesses are OK, but your kernel disagrees. I.e. fix your toolchain.
#define DISPMODE_PROF 0x40 /* Profiling active. */
/* Update dispatch table depending on various flags. */
-void lj_dispatch_update(global_State *g)
+void LJ_FASTCALL lj_dispatch_update(global_State *g, int nolock)
{
+#if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF
+ int profile_locked = nolock ? 0 : lj_profile_lock();
+#endif
uint8_t oldmode = g->dispatchmode;
uint8_t mode = 0;
#if LJ_HASJIT
lj_dispatch_init_hotcount(g);
#endif
}
+#if LJ_HASPROFILE && !LJ_PROFILE_SIGPROF
+ if (profile_locked) lj_profile_unlock();
+#else
+ UNUSED(nolock);
+#endif
}
/* -- JIT mode setting ---------------------------------------------------- */
G2J(g)->flags &= ~(uint32_t)JIT_F_ON;
else
G2J(g)->flags |= (uint32_t)JIT_F_ON;
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 0);
}
break;
case LUAJIT_MODE_FUNC:
g->hookcount = g->hookcstart = (int32_t)count;
g->hookmask = (uint8_t)((g->hookmask & ~HOOK_EVENTMASK) | mask);
lj_trace_abort(g); /* Abort recording on any hook change. */
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 0);
return 1;
}
#if LJ_HASJIT
LJ_FUNC void lj_dispatch_init_hotcount(global_State *g);
#endif
-LJ_FUNC void lj_dispatch_update(global_State *g);
+LJ_FUNC void LJ_FASTCALL lj_dispatch_update(global_State *g, int nolock);
/* Instruction dispatch callback for hooks or when recording. */
LJ_FUNCA void LJ_FASTCALL lj_dispatch_ins(lua_State *L, const BCIns *pc);
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);
+ if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g, 0);
g->gc.threshold = LJ_MAX_MEM; /* Prevent GC steps. */
top = VL->top;
copyTV(VL, top++, mo);
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);
+ if (LJ_HASPROFILE && (oldh & HOOK_PROFILE)) lj_dispatch_update(g, 0);
g->gc.threshold = oldt; /* Restore GC threshold. */
if (errcode) {
TValue tmp;
hook_leave(g);
}
}
+
+int lj_profile_lock(void)
+{
+ ProfileState *ps = &profile_state;
+ if (ps->g) {
+ profile_lock(ps);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void lj_profile_unlock(void)
+{
+ ProfileState *ps = &profile_state;
+ profile_unlock(ps);
+}
#endif
/* -- Profile callbacks --------------------------------------------------- */
int samples = ps->samples;
ps->samples = 0;
g->hookmask = HOOK_VMEVENT;
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 1);
profile_unlock(ps);
ps->cb(ps->data, L, samples, ps->vmstate); /* Invoke user callback. */
profile_lock(ps);
mask |= (g->hookmask & HOOK_PROFILE);
}
g->hookmask = mask;
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 1);
profile_unlock(ps);
}
st == ~LJ_VMST_C ? 'C' :
st == ~LJ_VMST_GC ? 'G' : 'J';
g->hookmask = (mask | HOOK_PROFILE);
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 1);
}
profile_unlock(ps);
}
if (G(L) == g) { /* Only stop profiler if started by this VM. */
profile_timer_stop(ps);
g->hookmask &= ~HOOK_PROFILE;
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 0);
#if LJ_HASJIT
G2J(g)->prof_mode = 0;
lj_trace_flushall(L);
#if !LJ_PROFILE_SIGPROF
LJ_FUNC void LJ_FASTCALL lj_profile_hook_enter(global_State *g);
LJ_FUNC void LJ_FASTCALL lj_profile_hook_leave(global_State *g);
+LJ_FUNC int lj_profile_lock(void);
+LJ_FUNC void lj_profile_unlock(void);
#endif
#endif
#if LJ_HASJIT
G2J(g)->flags &= ~JIT_F_ON;
G2J(g)->state = LJ_TRACE_IDLE;
- lj_dispatch_update(g);
+ lj_dispatch_update(g, 0);
#endif
for (i = 0;;) {
hook_enter(g);
} else if (e == LJ_TRERR_MCODEAL) {
if (!J->mcarea) { /* Disable JIT compiler if first mcode alloc fails. */
J->flags &= ~JIT_F_ON;
- lj_dispatch_update(J2G(J));
+ lj_dispatch_update(J2G(J), 0);
}
lj_trace_flushall(L);
}
case LJ_TRACE_START:
J->state = LJ_TRACE_RECORD; /* trace_start() may change state. */
trace_start(J);
- lj_dispatch_update(J2G(J));
+ lj_dispatch_update(J2G(J), 0);
if (J->state != LJ_TRACE_RECORD_1ST)
break;
/* fallthrough */
trace_stop(J);
setvmstate(J2G(J), INTERP);
J->state = LJ_TRACE_IDLE;
- lj_dispatch_update(J2G(J));
+ lj_dispatch_update(J2G(J), 0);
return NULL;
default: /* Trace aborted asynchronously. */
goto retry;
setvmstate(J2G(J), INTERP);
J->state = LJ_TRACE_IDLE;
- lj_dispatch_update(J2G(J));
+ lj_dispatch_update(J2G(J), 0);
return NULL;
}
} while (J->state > LJ_TRACE_RECORD);