aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-09-02 01:55:20 +0200
committerMike Pall <mike>2013-09-02 01:55:20 +0200
commitb186fb835efb82757b973db224ec3be39d0ad501 (patch)
treece594240025d4b4a2301413ccb530a55002856a4
parent8a9519a5f442726bafa954f5beecf67b0df3cf45 (diff)
downloadluajit-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.lua41
-rw-r--r--src/lib_jit.c101
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
27local remove = table.remove
28
29return 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
535static const char KEY_PROFILE_THREAD = 't';
536static const char KEY_PROFILE_FUNC = 'f';
537
538static 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) */
561LJLIB_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() */
580LJLIB_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) */
595LJLIB_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
616static 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