diff options
author | Mike Pall <mike> | 2013-09-02 01:55:20 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-09-02 01:55:20 +0200 |
commit | b186fb835efb82757b973db224ec3be39d0ad501 (patch) | |
tree | ce594240025d4b4a2301413ccb530a55002856a4 | |
parent | 8a9519a5f442726bafa954f5beecf67b0df3cf45 (diff) | |
download | luajit-b186fb835efb82757b973db224ec3be39d0ad501.tar.gz luajit-b186fb835efb82757b973db224ec3be39d0ad501.tar.bz2 luajit-b186fb835efb82757b973db224ec3be39d0ad501.zip |
Add low-overhead profiler. Part 2: low-level Lua API.
-rw-r--r-- | src/jit/zone.lua | 41 | ||||
-rw-r--r-- | src/lib_jit.c | 101 |
2 files changed, 142 insertions, 0 deletions
diff --git a/src/jit/zone.lua b/src/jit/zone.lua new file mode 100644 index 00000000..da2eccb0 --- /dev/null +++ b/src/jit/zone.lua | |||
@@ -0,0 +1,41 @@ | |||
1 | ---------------------------------------------------------------------------- | ||
2 | -- LuaJIT profiler zones. | ||
3 | -- | ||
4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. | ||
5 | -- Released under the MIT license. See Copyright Notice in luajit.h | ||
6 | ---------------------------------------------------------------------------- | ||
7 | -- | ||
8 | -- This module implements a simple hierarchical zone model. | ||
9 | -- | ||
10 | -- Example usage: | ||
11 | -- | ||
12 | -- local zone = require("jit.zone") | ||
13 | -- zone("AI") | ||
14 | -- ... | ||
15 | -- zone("A*") | ||
16 | -- ... | ||
17 | -- print(zone:get()) --> "A*" | ||
18 | -- ... | ||
19 | -- zone() | ||
20 | -- ... | ||
21 | -- print(zone:get()) --> "AI" | ||
22 | -- ... | ||
23 | -- zone() | ||
24 | -- | ||
25 | ---------------------------------------------------------------------------- | ||
26 | |||
27 | local remove = table.remove | ||
28 | |||
29 | return setmetatable({ | ||
30 | flush = function(t) | ||
31 | for i=#t,1,-1 do t[i] = nil end | ||
32 | end, | ||
33 | get = function(t) | ||
34 | return t[#t] | ||
35 | end | ||
36 | }, { | ||
37 | __call = function(t, zone) | ||
38 | if zone then t[#t+1] = zone else return assert(remove(t)) end | ||
39 | end | ||
40 | }) | ||
41 | |||
diff --git a/src/lib_jit.c b/src/lib_jit.c index 47663b72..ee2ff056 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c | |||
@@ -524,6 +524,103 @@ LJLIB_CF(jit_opt_start) | |||
524 | 524 | ||
525 | #endif | 525 | #endif |
526 | 526 | ||
527 | /* -- jit.profile module -------------------------------------------------- */ | ||
528 | |||
529 | #if LJ_HASPROFILE | ||
530 | |||
531 | #define LJLIB_MODULE_jit_profile | ||
532 | |||
533 | /* Not loaded by default, use: local profile = require("jit.profile") */ | ||
534 | |||
535 | static const char KEY_PROFILE_THREAD = 't'; | ||
536 | static const char KEY_PROFILE_FUNC = 'f'; | ||
537 | |||
538 | static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | ||
539 | int vmstate) | ||
540 | { | ||
541 | TValue key; | ||
542 | cTValue *tv; | ||
543 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
544 | tv = lj_tab_get(L, tabV(registry(L)), &key); | ||
545 | if (tvisfunc(tv)) { | ||
546 | char vmst = (char)vmstate; | ||
547 | int status; | ||
548 | setfuncV(L2, L2->top++, funcV(tv)); | ||
549 | setthreadV(L2, L2->top++, L); | ||
550 | setintV(L2->top++, samples); | ||
551 | setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1)); | ||
552 | status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */ | ||
553 | if (status) { | ||
554 | if (G(L2)->panic) G(L2)->panic(L2); | ||
555 | exit(EXIT_FAILURE); | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | /* profile.start(mode, func) */ | ||
561 | LJLIB_CF(jit_profile_start) | ||
562 | { | ||
563 | GCtab *registry = tabV(registry(L)); | ||
564 | GCstr *mode = lj_lib_optstr(L, 1); | ||
565 | GCfunc *func = lj_lib_checkfunc(L, 2); | ||
566 | lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ | ||
567 | TValue key; | ||
568 | /* Anchor thread and function in registry. */ | ||
569 | setlightudV(&key, (void *)&KEY_PROFILE_THREAD); | ||
570 | setthreadV(L, lj_tab_set(L, registry, &key), L2); | ||
571 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
572 | setfuncV(L, lj_tab_set(L, registry, &key), func); | ||
573 | lj_gc_anybarriert(L, registry); | ||
574 | luaJIT_profile_start(L, mode ? strdata(mode) : "", | ||
575 | (luaJIT_profile_callback)jit_profile_callback, L2); | ||
576 | return 0; | ||
577 | } | ||
578 | |||
579 | /* profile.stop() */ | ||
580 | LJLIB_CF(jit_profile_stop) | ||
581 | { | ||
582 | GCtab *registry; | ||
583 | TValue key; | ||
584 | luaJIT_profile_stop(L); | ||
585 | registry = tabV(registry(L)); | ||
586 | setlightudV(&key, (void *)&KEY_PROFILE_THREAD); | ||
587 | setnilV(lj_tab_set(L, registry, &key)); | ||
588 | setlightudV(&key, (void *)&KEY_PROFILE_FUNC); | ||
589 | setnilV(lj_tab_set(L, registry, &key)); | ||
590 | lj_gc_anybarriert(L, registry); | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | /* profile.dumpstack([thread,] fmt, depth) */ | ||
595 | LJLIB_CF(jit_profile_dumpstack) | ||
596 | { | ||
597 | lua_State *L2 = L; | ||
598 | int arg = 0; | ||
599 | size_t len; | ||
600 | int depth; | ||
601 | GCstr *fmt; | ||
602 | const char *p; | ||
603 | if (L->top > L->base && tvisthread(L->base)) { | ||
604 | L2 = threadV(L->base); | ||
605 | arg = 1; | ||
606 | } | ||
607 | fmt = lj_lib_checkstr(L, arg+1); | ||
608 | depth = lj_lib_checkint(L, arg+2); | ||
609 | p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len); | ||
610 | lua_pushlstring(L, p, len); | ||
611 | return 1; | ||
612 | } | ||
613 | |||
614 | #include "lj_libdef.h" | ||
615 | |||
616 | static int luaopen_jit_profile(lua_State *L) | ||
617 | { | ||
618 | LJ_LIB_REG(L, NULL, jit_profile); | ||
619 | return 1; | ||
620 | } | ||
621 | |||
622 | #endif | ||
623 | |||
527 | /* -- JIT compiler initialization ----------------------------------------- */ | 624 | /* -- JIT compiler initialization ----------------------------------------- */ |
528 | 625 | ||
529 | #if LJ_HASJIT | 626 | #if LJ_HASJIT |
@@ -646,6 +743,10 @@ LUALIB_API int luaopen_jit(lua_State *L) | |||
646 | lua_pushinteger(L, LUAJIT_VERSION_NUM); | 743 | lua_pushinteger(L, LUAJIT_VERSION_NUM); |
647 | lua_pushliteral(L, LUAJIT_VERSION); | 744 | lua_pushliteral(L, LUAJIT_VERSION); |
648 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); | 745 | LJ_LIB_REG(L, LUA_JITLIBNAME, jit); |
746 | #if LJ_HASPROFILE | ||
747 | lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile, | ||
748 | tabref(L->env)); | ||
749 | #endif | ||
649 | #ifndef LUAJIT_DISABLE_JITUTIL | 750 | #ifndef LUAJIT_DISABLE_JITUTIL |
650 | LJ_LIB_REG(L, "jit.util", jit_util); | 751 | LJ_LIB_REG(L, "jit.util", jit_util); |
651 | #endif | 752 | #endif |