One Level Up
Top Level
src/lj_profile.c - luajit-2.0-src
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #define lj_profile_c
- #define LUA_CORE
- #include "lj_obj.h"
- #if LJ_HASPROFILE
- #include "lj_buf.h"
- #include "lj_frame.h"
- #include "lj_debug.h"
- #include "lj_dispatch.h"
- #if LJ_HASJIT
- #include "lj_jit.h"
- #include "lj_trace.h"
- #endif
- #include "lj_profile.h"
- #include "luajit.h"
- #if LJ_PROFILE_SIGPROF
- #include <sys/time.h>
- #include <signal.h>
- #define profile_lock(ps) UNUSED(ps)
- #define profile_unlock(ps) UNUSED(ps)
- #elif LJ_PROFILE_PTHREAD
- #include <pthread.h>
- #include <time.h>
- #if LJ_TARGET_PS3
- #include <sys/timer.h>
- #endif
- #define profile_lock(ps) pthread_mutex_lock(&ps->lock)
- #define profile_unlock(ps) pthread_mutex_unlock(&ps->lock)
- #elif LJ_PROFILE_WTHREAD
- #define WIN32_LEAN_AND_MEAN
- #if LJ_TARGET_XBOX360
- #include <xtl.h>
- #include <xbox.h>
- #else
- #include <windows.h>
- #endif
- typedef unsigned int (WINAPI *WMM_TPFUNC)(unsigned int);
- #define profile_lock(ps) EnterCriticalSection(&ps->lock)
- #define profile_unlock(ps) LeaveCriticalSection(&ps->lock)
- #endif
- typedef struct ProfileState {
- global_State *g;
- luaJIT_profile_callback cb;
- void *data;
- SBuf sb;
- int interval;
- int samples;
- int vmstate;
- #if LJ_PROFILE_SIGPROF
- struct sigaction oldsa;
- #elif LJ_PROFILE_PTHREAD
- pthread_mutex_t lock;
- pthread_t thread;
- int abort;
- #elif LJ_PROFILE_WTHREAD
- #if LJ_TARGET_WINDOWS
- HINSTANCE wmm;
- WMM_TPFUNC wmm_tbp;
- WMM_TPFUNC wmm_tep;
- #endif
- CRITICAL_SECTION lock;
- HANDLE thread;
- int abort;
- #endif
- } ProfileState;
- static ProfileState profile_state;
- #define LJ_PROFILE_INTERVAL_DEFAULT 10
- #if !LJ_PROFILE_SIGPROF
- void LJ_FASTCALL lj_profile_hook_enter(global_State *g)
- {
- ProfileState *ps = &profile_state;
- if (ps->g) {
- profile_lock(ps);
- hook_enter(g);
- profile_unlock(ps);
- } else {
- hook_enter(g);
- }
- }
- void LJ_FASTCALL lj_profile_hook_leave(global_State *g)
- {
- ProfileState *ps = &profile_state;
- if (ps->g) {
- profile_lock(ps);
- hook_leave(g);
- profile_unlock(ps);
- } else {
- hook_leave(g);
- }
- }
- #endif
- void LJ_FASTCALL lj_profile_interpreter(lua_State *L)
- {
- ProfileState *ps = &profile_state;
- global_State *g = G(L);
- uint8_t mask;
- profile_lock(ps);
- mask = (g->hookmask & ~HOOK_PROFILE);
- if (!(mask & HOOK_VMEVENT)) {
- int samples = ps->samples;
- ps->samples = 0;
- g->hookmask = HOOK_VMEVENT;
- lj_dispatch_update(g);
- profile_unlock(ps);
- ps->cb(ps->data, L, samples, ps->vmstate);
- profile_lock(ps);
- mask |= (g->hookmask & HOOK_PROFILE);
- }
- g->hookmask = mask;
- lj_dispatch_update(g);
- profile_unlock(ps);
- }
- static void profile_trigger(ProfileState *ps)
- {
- global_State *g = ps->g;
- uint8_t mask;
- profile_lock(ps);
- ps->samples++;
- mask = g->hookmask;
- if (!(mask & (HOOK_PROFILE|HOOK_VMEVENT))) {
- int st = g->vmstate;
- ps->vmstate = st >= 0 ? 'N' :
- st == ~LJ_VMST_INTERP ? 'I' :
- st == ~LJ_VMST_C ? 'C' :
- st == ~LJ_VMST_GC ? 'G' : 'J';
- g->hookmask = (mask | HOOK_PROFILE);
- lj_dispatch_update(g);
- }
- profile_unlock(ps);
- }
- #if LJ_PROFILE_SIGPROF
- static void profile_signal(int sig)
- {
- UNUSED(sig);
- profile_trigger(&profile_state);
- }
- static void profile_timer_start(ProfileState *ps)
- {
- int interval = ps->interval;
- struct itimerval tm;
- struct sigaction sa;
- tm.it_value.tv_sec = tm.it_interval.tv_sec = interval / 1000;
- tm.it_value.tv_usec = tm.it_interval.tv_usec = (interval % 1000) * 1000;
- setitimer(ITIMER_PROF, &tm, NULL);
- sa.sa_flags = SA_RESTART;
- sa.sa_handler = profile_signal;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGPROF, &sa, &ps->oldsa);
- }
- static void profile_timer_stop(ProfileState *ps)
- {
- struct itimerval tm;
- tm.it_value.tv_sec = tm.it_interval.tv_sec = 0;
- tm.it_value.tv_usec = tm.it_interval.tv_usec = 0;
- setitimer(ITIMER_PROF, &tm, NULL);
- sigaction(SIGPROF, &ps->oldsa, NULL);
- }
- #elif LJ_PROFILE_PTHREAD
- static void *profile_thread(ProfileState *ps)
- {
- int interval = ps->interval;
- #if !LJ_TARGET_PS3
- struct timespec ts;
- ts.tv_sec = interval / 1000;
- ts.tv_nsec = (interval % 1000) * 1000000;
- #endif
- while (1) {
- #if LJ_TARGET_PS3
- sys_timer_usleep(interval * 1000);
- #else
- nanosleep(&ts, NULL);
- #endif
- if (ps->abort) break;
- profile_trigger(ps);
- }
- return NULL;
- }
- static void profile_timer_start(ProfileState *ps)
- {
- pthread_mutex_init(&ps->lock, 0);
- ps->abort = 0;
- pthread_create(&ps->thread, NULL, (void *(*)(void *))profile_thread, ps);
- }
- static void profile_timer_stop(ProfileState *ps)
- {
- ps->abort = 1;
- pthread_join(ps->thread, NULL);
- pthread_mutex_destroy(&ps->lock);
- }
- #elif LJ_PROFILE_WTHREAD
- static DWORD WINAPI profile_thread(void *psx)
- {
- ProfileState *ps = (ProfileState *)psx;
- int interval = ps->interval;
- #if LJ_TARGET_WINDOWS
- ps->wmm_tbp(interval);
- #endif
- while (1) {
- Sleep(interval);
- if (ps->abort) break;
- profile_trigger(ps);
- }
- #if LJ_TARGET_WINDOWS
- ps->wmm_tep(interval);
- #endif
- return 0;
- }
- static void profile_timer_start(ProfileState *ps)
- {
- #if LJ_TARGET_WINDOWS
- if (!ps->wmm) {
- ps->wmm = LoadLibraryA("winmm.dll");
- if (ps->wmm) {
- ps->wmm_tbp = (WMM_TPFUNC)GetProcAddress(ps->wmm, "timeBeginPeriod");
- ps->wmm_tep = (WMM_TPFUNC)GetProcAddress(ps->wmm, "timeEndPeriod");
- if (!ps->wmm_tbp || !ps->wmm_tep) {
- ps->wmm = NULL;
- return;
- }
- }
- }
- #endif
- InitializeCriticalSection(&ps->lock);
- ps->abort = 0;
- ps->thread = CreateThread(NULL, 0, profile_thread, ps, 0, NULL);
- }
- static void profile_timer_stop(ProfileState *ps)
- {
- ps->abort = 1;
- WaitForSingleObject(ps->thread, INFINITE);
- DeleteCriticalSection(&ps->lock);
- }
- #endif
- LUA_API void luaJIT_profile_start(lua_State *L, const char *mode,
- luaJIT_profile_callback cb, void *data)
- {
- ProfileState *ps = &profile_state;
- int interval = LJ_PROFILE_INTERVAL_DEFAULT;
- while (*mode) {
- int m = *mode++;
- switch (m) {
- case 'i':
- interval = 0;
- while (*mode >= '0' && *mode <= '9')
- interval = interval * 10 + (*mode++ - '0');
- if (interval <= 0) interval = 1;
- break;
- #if LJ_HASJIT
- case 'l': case 'f':
- L2J(L)->prof_mode = m;
- lj_trace_flushall(L);
- break;
- #endif
- default:
- break;
- }
- }
- if (ps->g) {
- luaJIT_profile_stop(L);
- if (ps->g) return;
- }
- ps->g = G(L);
- ps->interval = interval;
- ps->cb = cb;
- ps->data = data;
- ps->samples = 0;
- lj_buf_init(L, &ps->sb);
- profile_timer_start(ps);
- }
- LUA_API void luaJIT_profile_stop(lua_State *L)
- {
- ProfileState *ps = &profile_state;
- global_State *g = ps->g;
- if (G(L) == g) {
- profile_timer_stop(ps);
- g->hookmask &= ~HOOK_PROFILE;
- lj_dispatch_update(g);
- #if LJ_HASJIT
- G2J(g)->prof_mode = 0;
- lj_trace_flushall(L);
- #endif
- lj_buf_free(g, &ps->sb);
- setmref(ps->sb.b, NULL);
- setmref(ps->sb.e, NULL);
- ps->g = NULL;
- }
- }
- LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
- int depth, size_t *len)
- {
- ProfileState *ps = &profile_state;
- SBuf *sb = &ps->sb;
- setsbufL(sb, L);
- lj_buf_reset(sb);
- lj_debug_dumpstack(L, sb, fmt, depth);
- *len = (size_t)sbuflen(sb);
- return sbufB(sb);
- }
- #endif
One Level Up
Top Level