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 |
