aboutsummaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/bc.lua19
-rw-r--r--src/jit/bcsave.lua14
-rw-r--r--src/jit/dis_arm.lua18
-rw-r--r--src/jit/dis_mips.lua30
-rw-r--r--src/jit/dis_mipsel.lua15
-rw-r--r--src/jit/dis_ppc.lua18
-rw-r--r--src/jit/dis_x64.lua15
-rw-r--r--src/jit/dis_x86.lua38
-rw-r--r--src/jit/dump.lua29
-rw-r--r--src/jit/p.lua310
-rw-r--r--src/jit/v.lua15
-rw-r--r--src/jit/zone.lua45
12 files changed, 463 insertions, 103 deletions
diff --git a/src/jit/bc.lua b/src/jit/bc.lua
index a179d50e..320039ff 100644
--- a/src/jit/bc.lua
+++ b/src/jit/bc.lua
@@ -41,7 +41,7 @@
41 41
42-- Cache some library functions and objects. 42-- Cache some library functions and objects.
43local jit = require("jit") 43local jit = require("jit")
44assert(jit.version_num == 20003, "LuaJIT core/library version mismatch") 44assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
45local jutil = require("jit.util") 45local jutil = require("jit.util")
46local vmdef = require("jit.vmdef") 46local vmdef = require("jit.vmdef")
47local bit = require("bit") 47local bit = require("bit")
@@ -179,13 +179,12 @@ local function bcliston(outfile)
179end 179end
180 180
181-- Public module functions. 181-- Public module functions.
182module(...) 182return {
183 183 line = bcline,
184line = bcline 184 dump = bcdump,
185dump = bcdump 185 targets = bctargets,
186targets = bctargets 186 on = bcliston,
187 187 off = bclistoff,
188on = bcliston 188 start = bcliston -- For -j command line option.
189off = bclistoff 189}
190start = bcliston -- For -j command line option.
191 190
diff --git a/src/jit/bcsave.lua b/src/jit/bcsave.lua
index 2ba234d0..ef5a1aa9 100644
--- a/src/jit/bcsave.lua
+++ b/src/jit/bcsave.lua
@@ -11,7 +11,7 @@
11------------------------------------------------------------------------------ 11------------------------------------------------------------------------------
12 12
13local jit = require("jit") 13local jit = require("jit")
14assert(jit.version_num == 20003, "LuaJIT core/library version mismatch") 14assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
15local bit = require("bit") 15local bit = require("bit")
16 16
17-- Symbol name prefix for LuaJIT bytecode. 17-- Symbol name prefix for LuaJIT bytecode.
@@ -63,7 +63,7 @@ local map_type = {
63} 63}
64 64
65local map_arch = { 65local map_arch = {
66 x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true, 66 x86 = true, x64 = true, arm = true, ppc = true,
67 mips = true, mipsel = true, 67 mips = true, mipsel = true,
68} 68}
69 69
@@ -202,7 +202,7 @@ typedef struct {
202 local is64, isbe = false, false 202 local is64, isbe = false, false
203 if ctx.arch == "x64" then 203 if ctx.arch == "x64" then
204 is64 = true 204 is64 = true
205 elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" or ctx.arch == "mips" then 205 elseif ctx.arch == "ppc" or ctx.arch == "mips" then
206 isbe = true 206 isbe = true
207 end 207 end
208 208
@@ -237,7 +237,7 @@ typedef struct {
237 hdr.eendian = isbe and 2 or 1 237 hdr.eendian = isbe and 2 or 1
238 hdr.eversion = 1 238 hdr.eversion = 1
239 hdr.type = f16(1) 239 hdr.type = f16(1)
240 hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20, mips=8, mipsel=8 })[ctx.arch]) 240 hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, mips=8, mipsel=8 })[ctx.arch])
241 if ctx.arch == "mips" or ctx.arch == "mipsel" then 241 if ctx.arch == "mips" or ctx.arch == "mipsel" then
242 hdr.flags = 0x50001006 242 hdr.flags = 0x50001006
243 end 243 end
@@ -653,7 +653,7 @@ end
653------------------------------------------------------------------------------ 653------------------------------------------------------------------------------
654 654
655-- Public module functions. 655-- Public module functions.
656module(...) 656return {
657 657 start = docmd -- Process -b command line option.
658start = docmd -- Process -b command line option. 658}
659 659
diff --git a/src/jit/dis_arm.lua b/src/jit/dis_arm.lua
index 59be715a..dfcbeeec 100644
--- a/src/jit/dis_arm.lua
+++ b/src/jit/dis_arm.lua
@@ -658,7 +658,7 @@ local function disass_block(ctx, ofs, len)
658end 658end
659 659
660-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 660-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
661local function create_(code, addr, out) 661local function create(code, addr, out)
662 local ctx = {} 662 local ctx = {}
663 ctx.code = code 663 ctx.code = code
664 ctx.addr = addr or 0 664 ctx.addr = addr or 0
@@ -670,20 +670,20 @@ local function create_(code, addr, out)
670end 670end
671 671
672-- Simple API: disassemble code (a string) at address and output via out. 672-- Simple API: disassemble code (a string) at address and output via out.
673local function disass_(code, addr, out) 673local function disass(code, addr, out)
674 create_(code, addr, out):disass() 674 create(code, addr, out):disass()
675end 675end
676 676
677-- Return register name for RID. 677-- Return register name for RID.
678local function regname_(r) 678local function regname(r)
679 if r < 16 then return map_gpr[r] end 679 if r < 16 then return map_gpr[r] end
680 return "d"..(r-16) 680 return "d"..(r-16)
681end 681end
682 682
683-- Public module functions. 683-- Public module functions.
684module(...) 684return {
685 685 create = create,
686create = create_ 686 disass = disass,
687disass = disass_ 687 regname = regname
688regname = regname_ 688}
689 689
diff --git a/src/jit/dis_mips.lua b/src/jit/dis_mips.lua
index acdd2be1..9466f45c 100644
--- a/src/jit/dis_mips.lua
+++ b/src/jit/dis_mips.lua
@@ -384,7 +384,7 @@ local function disass_block(ctx, ofs, len)
384end 384end
385 385
386-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 386-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
387local function create_(code, addr, out) 387local function create(code, addr, out)
388 local ctx = {} 388 local ctx = {}
389 ctx.code = code 389 ctx.code = code
390 ctx.addr = addr or 0 390 ctx.addr = addr or 0
@@ -396,33 +396,33 @@ local function create_(code, addr, out)
396 return ctx 396 return ctx
397end 397end
398 398
399local function create_el_(code, addr, out) 399local function create_el(code, addr, out)
400 local ctx = create_(code, addr, out) 400 local ctx = create(code, addr, out)
401 ctx.get = get_le 401 ctx.get = get_le
402 return ctx 402 return ctx
403end 403end
404 404
405-- Simple API: disassemble code (a string) at address and output via out. 405-- Simple API: disassemble code (a string) at address and output via out.
406local function disass_(code, addr, out) 406local function disass(code, addr, out)
407 create_(code, addr, out):disass() 407 create(code, addr, out):disass()
408end 408end
409 409
410local function disass_el_(code, addr, out) 410local function disass_el(code, addr, out)
411 create_el_(code, addr, out):disass() 411 create_el(code, addr, out):disass()
412end 412end
413 413
414-- Return register name for RID. 414-- Return register name for RID.
415local function regname_(r) 415local function regname(r)
416 if r < 32 then return map_gpr[r] end 416 if r < 32 then return map_gpr[r] end
417 return "f"..(r-32) 417 return "f"..(r-32)
418end 418end
419 419
420-- Public module functions. 420-- Public module functions.
421module(...) 421return {
422 422 create = create,
423create = create_ 423 create_el = create_el,
424create_el = create_el_ 424 disass = disass,
425disass = disass_ 425 disass_el = disass_el,
426disass_el = disass_el_ 426 regname = regname
427regname = regname_ 427}
428 428
diff --git a/src/jit/dis_mipsel.lua b/src/jit/dis_mipsel.lua
index dd9d26ae..f06ffe85 100644
--- a/src/jit/dis_mipsel.lua
+++ b/src/jit/dis_mipsel.lua
@@ -8,13 +8,10 @@
8-- MIPS disassembler module. All the interesting stuff is there. 8-- MIPS disassembler module. All the interesting stuff is there.
9------------------------------------------------------------------------------ 9------------------------------------------------------------------------------
10 10
11local require = require 11local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
12 12return {
13module(...) 13 create = dis_mips.create_el,
14 14 disass = dis_mips.disass_el,
15local dis_mips = require(_PACKAGE.."dis_mips") 15 regname = dis_mips.regname
16 16}
17create = dis_mips.create_el
18disass = dis_mips.disass_el
19regname = dis_mips.regname
20 17
diff --git a/src/jit/dis_ppc.lua b/src/jit/dis_ppc.lua
index d05c4311..e077d7ac 100644
--- a/src/jit/dis_ppc.lua
+++ b/src/jit/dis_ppc.lua
@@ -560,7 +560,7 @@ local function disass_block(ctx, ofs, len)
560end 560end
561 561
562-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 562-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
563local function create_(code, addr, out) 563local function create(code, addr, out)
564 local ctx = {} 564 local ctx = {}
565 ctx.code = code 565 ctx.code = code
566 ctx.addr = addr or 0 566 ctx.addr = addr or 0
@@ -572,20 +572,20 @@ local function create_(code, addr, out)
572end 572end
573 573
574-- Simple API: disassemble code (a string) at address and output via out. 574-- Simple API: disassemble code (a string) at address and output via out.
575local function disass_(code, addr, out) 575local function disass(code, addr, out)
576 create_(code, addr, out):disass() 576 create(code, addr, out):disass()
577end 577end
578 578
579-- Return register name for RID. 579-- Return register name for RID.
580local function regname_(r) 580local function regname(r)
581 if r < 32 then return map_gpr[r] end 581 if r < 32 then return map_gpr[r] end
582 return "f"..(r-32) 582 return "f"..(r-32)
583end 583end
584 584
585-- Public module functions. 585-- Public module functions.
586module(...) 586return {
587 587 create = create,
588create = create_ 588 disass = disass,
589disass = disass_ 589 regname = regname
590regname = regname_ 590}
591 591
diff --git a/src/jit/dis_x64.lua b/src/jit/dis_x64.lua
index a80981bd..15d55243 100644
--- a/src/jit/dis_x64.lua
+++ b/src/jit/dis_x64.lua
@@ -8,13 +8,10 @@
8-- x86/x64 disassembler module. All the interesting stuff is there. 8-- x86/x64 disassembler module. All the interesting stuff is there.
9------------------------------------------------------------------------------ 9------------------------------------------------------------------------------
10 10
11local require = require 11local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86")
12 12return {
13module(...) 13 create = dis_x86.create64,
14 14 disass = dis_x86.disass64,
15local dis_x86 = require(_PACKAGE.."dis_x86") 15 regname = dis_x86.regname64
16 16}
17create = dis_x86.create64
18disass = dis_x86.disass64
19regname = dis_x86.regname64
20 17
diff --git a/src/jit/dis_x86.lua b/src/jit/dis_x86.lua
index 078d6094..6bc38066 100644
--- a/src/jit/dis_x86.lua
+++ b/src/jit/dis_x86.lua
@@ -28,6 +28,8 @@ local type = type
28local sub, byte, format = string.sub, string.byte, string.format 28local sub, byte, format = string.sub, string.byte, string.format
29local match, gmatch, gsub = string.match, string.gmatch, string.gsub 29local match, gmatch, gsub = string.match, string.gmatch, string.gsub
30local lower, rep = string.lower, string.rep 30local lower, rep = string.lower, string.rep
31local bit = require("bit")
32local tohex = bit.tohex
31 33
32-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. 34-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on.
33local map_opc1_32 = { 35local map_opc1_32 = {
@@ -532,7 +534,7 @@ local function putpat(ctx, name, pat)
532 local lo = imm % 0x1000000 534 local lo = imm % 0x1000000
533 x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) 535 x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo)
534 else 536 else
535 x = format("0x%08x", imm) 537 x = "0x"..tohex(imm)
536 end 538 end
537 elseif p == "R" then 539 elseif p == "R" then
538 local r = byte(code, pos-1, pos-1)%8 540 local r = byte(code, pos-1, pos-1)%8
@@ -782,7 +784,7 @@ local function disass_block(ctx, ofs, len)
782end 784end
783 785
784-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 786-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
785local function create_(code, addr, out) 787local function create(code, addr, out)
786 local ctx = {} 788 local ctx = {}
787 ctx.code = code 789 ctx.code = code
788 ctx.addr = (addr or 0) - 1 790 ctx.addr = (addr or 0) - 1
@@ -796,8 +798,8 @@ local function create_(code, addr, out)
796 return ctx 798 return ctx
797end 799end
798 800
799local function create64_(code, addr, out) 801local function create64(code, addr, out)
800 local ctx = create_(code, addr, out) 802 local ctx = create(code, addr, out)
801 ctx.x64 = true 803 ctx.x64 = true
802 ctx.map1 = map_opc1_64 804 ctx.map1 = map_opc1_64
803 ctx.aregs = map_regs.Q 805 ctx.aregs = map_regs.Q
@@ -805,32 +807,32 @@ local function create64_(code, addr, out)
805end 807end
806 808
807-- Simple API: disassemble code (a string) at address and output via out. 809-- Simple API: disassemble code (a string) at address and output via out.
808local function disass_(code, addr, out) 810local function disass(code, addr, out)
809 create_(code, addr, out):disass() 811 create(code, addr, out):disass()
810end 812end
811 813
812local function disass64_(code, addr, out) 814local function disass64(code, addr, out)
813 create64_(code, addr, out):disass() 815 create64(code, addr, out):disass()
814end 816end
815 817
816-- Return register name for RID. 818-- Return register name for RID.
817local function regname_(r) 819local function regname(r)
818 if r < 8 then return map_regs.D[r+1] end 820 if r < 8 then return map_regs.D[r+1] end
819 return map_regs.X[r-7] 821 return map_regs.X[r-7]
820end 822end
821 823
822local function regname64_(r) 824local function regname64(r)
823 if r < 16 then return map_regs.Q[r+1] end 825 if r < 16 then return map_regs.Q[r+1] end
824 return map_regs.X[r-15] 826 return map_regs.X[r-15]
825end 827end
826 828
827-- Public module functions. 829-- Public module functions.
828module(...) 830return {
829 831 create = create,
830create = create_ 832 create64 = create64,
831create64 = create64_ 833 disass = disass,
832disass = disass_ 834 disass64 = disass64,
833disass64 = disass64_ 835 regname = regname,
834regname = regname_ 836 regname64 = regname64
835regname64 = regname64_ 837}
836 838
diff --git a/src/jit/dump.lua b/src/jit/dump.lua
index 589543f1..5f858492 100644
--- a/src/jit/dump.lua
+++ b/src/jit/dump.lua
@@ -55,7 +55,7 @@
55 55
56-- Cache some library functions and objects. 56-- Cache some library functions and objects.
57local jit = require("jit") 57local jit = require("jit")
58assert(jit.version_num == 20003, "LuaJIT core/library version mismatch") 58assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
59local jutil = require("jit.util") 59local jutil = require("jit.util")
60local vmdef = require("jit.vmdef") 60local vmdef = require("jit.vmdef")
61local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc 61local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
@@ -63,7 +63,7 @@ local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek
63local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap 63local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap
64local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr 64local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr
65local bit = require("bit") 65local bit = require("bit")
66local band, shl, shr = bit.band, bit.lshift, bit.rshift 66local band, shl, shr, tohex = bit.band, bit.lshift, bit.rshift, bit.tohex
67local sub, gsub, format = string.sub, string.gsub, string.format 67local sub, gsub, format = string.sub, string.gsub, string.format
68local byte, char, rep = string.byte, string.char, string.rep 68local byte, char, rep = string.byte, string.char, string.rep
69local type, tostring = type, tostring 69local type, tostring = type, tostring
@@ -91,6 +91,7 @@ local function fillsymtab_tr(tr, nexit)
91 end 91 end
92 for i=0,nexit-1 do 92 for i=0,nexit-1 do
93 local addr = traceexitstub(tr, i) 93 local addr = traceexitstub(tr, i)
94 if addr < 0 then addr = addr + 2^32 end
94 t[addr] = tostring(i) 95 t[addr] = tostring(i)
95 end 96 end
96 local addr = traceexitstub(tr, nexit) 97 local addr = traceexitstub(tr, nexit)
@@ -104,7 +105,10 @@ local function fillsymtab(tr, nexit)
104 local ircall = vmdef.ircall 105 local ircall = vmdef.ircall
105 for i=0,#ircall do 106 for i=0,#ircall do
106 local addr = ircalladdr(i) 107 local addr = ircalladdr(i)
107 if addr ~= 0 then t[addr] = ircall[i] end 108 if addr ~= 0 then
109 if addr < 0 then addr = addr + 2^32 end
110 t[addr] = ircall[i]
111 end
108 end 112 end
109 end 113 end
110 if nexitsym == 1000000 then -- Per-trace exit stubs. 114 if nexitsym == 1000000 then -- Per-trace exit stubs.
@@ -118,6 +122,7 @@ local function fillsymtab(tr, nexit)
118 nexit = 1000000 122 nexit = 1000000
119 break 123 break
120 end 124 end
125 if addr < 0 then addr = addr + 2^32 end
121 t[addr] = tostring(i) 126 t[addr] = tostring(i)
122 end 127 end
123 nexitsym = nexit 128 nexitsym = nexit
@@ -136,6 +141,7 @@ local function dump_mcode(tr)
136 local mcode, addr, loop = tracemc(tr) 141 local mcode, addr, loop = tracemc(tr)
137 if not mcode then return end 142 if not mcode then return end
138 if not disass then disass = require("jit.dis_"..jit.arch) end 143 if not disass then disass = require("jit.dis_"..jit.arch) end
144 if addr < 0 then addr = addr + 2^32 end
139 out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") 145 out:write("---- TRACE ", tr, " mcode ", #mcode, "\n")
140 local ctx = disass.create(mcode, addr, dumpwrite) 146 local ctx = disass.create(mcode, addr, dumpwrite)
141 ctx.hexdump = 0 147 ctx.hexdump = 0
@@ -270,8 +276,7 @@ local litname = {
270 ["CONV "] = setmetatable({}, { __index = function(t, mode) 276 ["CONV "] = setmetatable({}, { __index = function(t, mode)
271 local s = irtype[band(mode, 31)] 277 local s = irtype[band(mode, 31)]
272 s = irtype[band(shr(mode, 5), 31)].."."..s 278 s = irtype[band(shr(mode, 5), 31)].."."..s
273 if band(mode, 0x400) ~= 0 then s = s.." trunc" 279 if band(mode, 0x800) ~= 0 then s = s.." sext" end
274 elseif band(mode, 0x800) ~= 0 then s = s.." sext" end
275 local c = shr(mode, 14) 280 local c = shr(mode, 14)
276 if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end 281 if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
277 t[mode] = s 282 t[mode] = s
@@ -280,6 +285,8 @@ local litname = {
280 ["FLOAD "] = vmdef.irfield, 285 ["FLOAD "] = vmdef.irfield,
281 ["FREF "] = vmdef.irfield, 286 ["FREF "] = vmdef.irfield,
282 ["FPMATH"] = vmdef.irfpm, 287 ["FPMATH"] = vmdef.irfpm,
288 ["BUFHDR"] = { [0] = "RESET", "APPEND" },
289 ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
283} 290}
284 291
285local function ctlsub(c) 292local function ctlsub(c)
@@ -607,7 +614,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
607 end 614 end
608 else 615 else
609 for i=1,ngpr do 616 for i=1,ngpr do
610 out:write(format(" %08x", regs[i])) 617 out:write(" ", tohex(regs[i]))
611 if i % 8 == 0 then out:write("\n") end 618 if i % 8 == 0 then out:write("\n") end
612 end 619 end
613 end 620 end
@@ -691,9 +698,9 @@ local function dumpon(opt, outfile)
691end 698end
692 699
693-- Public module functions. 700-- Public module functions.
694module(...) 701return {
695 702 on = dumpon,
696on = dumpon 703 off = dumpoff,
697off = dumpoff 704 start = dumpon -- For -j command line option.
698start = dumpon -- For -j command line option. 705}
699 706
diff --git a/src/jit/p.lua b/src/jit/p.lua
new file mode 100644
index 00000000..97d4ccdf
--- /dev/null
+++ b/src/jit/p.lua
@@ -0,0 +1,310 @@
1----------------------------------------------------------------------------
2-- LuaJIT profiler.
3--
4-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
5-- Released under the MIT license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module is a simple command line interface to the built-in
9-- low-overhead profiler of LuaJIT.
10--
11-- The lower-level API of the profiler is accessible via the "jit.profile"
12-- module or the luaJIT_profile_* C API.
13--
14-- Example usage:
15--
16-- luajit -jp myapp.lua
17-- luajit -jp=s myapp.lua
18-- luajit -jp=-s myapp.lua
19-- luajit -jp=vl myapp.lua
20-- luajit -jp=G,profile.txt myapp.lua
21--
22-- The following dump features are available:
23--
24-- f Stack dump: function name, otherwise module:line. Default mode.
25-- F Stack dump: ditto, but always prepend module.
26-- l Stack dump: module:line.
27-- <number> stack dump depth (callee < caller). Default: 1.
28-- -<number> Inverse stack dump depth (caller > callee).
29-- s Split stack dump after first stack level. Implies abs(depth) >= 2.
30-- p Show full path for module names.
31-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv.
32-- z Show zones. Can be combined with stack dumps, e.g. zf or fz.
33-- r Show raw sample counts. Default: show percentages.
34-- a Annotate excerpts from source code files.
35-- A Annotate complete source code files.
36-- G Produce raw output suitable for graphical tools (e.g. flame graphs).
37-- m<number> Minimum sample percentage to be shown. Default: 3.
38-- i<number> Sampling interval in milliseconds. Default: 10.
39--
40----------------------------------------------------------------------------
41
42-- Cache some library functions and objects.
43local jit = require("jit")
44assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
45local profile = require("jit.profile")
46local vmdef = require("jit.vmdef")
47local math = math
48local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor
49local sort, format = table.sort, string.format
50local stdout = io.stdout
51local zone -- Load jit.zone module on demand.
52
53-- Output file handle.
54local out
55
56------------------------------------------------------------------------------
57
58local prof_ud
59local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth
60local prof_ann, prof_count1, prof_count2, prof_samples
61
62local map_vmmode = {
63 N = "Compiled",
64 I = "Interpreted",
65 C = "C code",
66 G = "Garbage Collector",
67 J = "JIT Compiler",
68}
69
70-- Profiler callback.
71local function prof_cb(th, samples, vmmode)
72 prof_samples = prof_samples + samples
73 local key_stack, key_stack2, key_state
74 -- Collect keys for sample.
75 if prof_states then
76 if prof_states == "v" then
77 key_state = map_vmmode[vmmode] or vmmode
78 else
79 key_state = zone:get() or "(none)"
80 end
81 end
82 if prof_fmt then
83 key_stack = profile.dumpstack(th, prof_fmt, prof_depth)
84 key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x)
85 return vmdef.ffnames[tonumber(x)]
86 end)
87 if prof_split == 2 then
88 local k1, k2 = key_stack:match("(.-) [<>] (.*)")
89 if k2 then key_stack, key_stack2 = k1, k2 end
90 elseif prof_split == 3 then
91 key_stack2 = profile.dumpstack(th, "l", 1)
92 end
93 end
94 -- Order keys.
95 local k1, k2
96 if prof_split == 1 then
97 if key_state then
98 k1 = key_state
99 if key_stack then k2 = key_stack end
100 end
101 elseif key_stack then
102 k1 = key_stack
103 if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end
104 end
105 -- Coalesce samples in one or two levels.
106 if k1 then
107 local t1 = prof_count1
108 t1[k1] = (t1[k1] or 0) + samples
109 if k2 then
110 local t2 = prof_count2
111 local t3 = t2[k1]
112 if not t3 then t3 = {}; t2[k1] = t3 end
113 t3[k2] = (t3[k2] or 0) + samples
114 end
115 end
116end
117
118------------------------------------------------------------------------------
119
120-- Show top N list.
121local function prof_top(count1, count2, samples, indent)
122 local t, n = {}, 0
123 for k, v in pairs(count1) do
124 n = n + 1
125 t[n] = k
126 end
127 sort(t, function(a, b) return count1[a] > count1[b] end)
128 for i=1,n do
129 local k = t[i]
130 local v = count1[k]
131 local pct = floor(v*100/samples + 0.5)
132 if pct < prof_min then break end
133 if not prof_raw then
134 out:write(format("%s%2d%% %s\n", indent, pct, k))
135 elseif prof_raw == "r" then
136 out:write(format("%s%5d %s\n", indent, v, k))
137 else
138 out:write(format("%s %d\n", k, v))
139 end
140 if count2 then
141 local r = count2[k]
142 if r then
143 prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or
144 (prof_depth < 0 and " -> " or " <- "))
145 end
146 end
147 end
148end
149
150-- Annotate source code
151local function prof_annotate(count1, samples)
152 local files = {}
153 local ms = 0
154 for k, v in pairs(count1) do
155 local pct = floor(v*100/samples + 0.5)
156 ms = math.max(ms, v)
157 if pct >= prof_min then
158 local file, line = k:match("^(.*):(%d+)$")
159 local fl = files[file]
160 if not fl then fl = {}; files[file] = fl; files[#files+1] = file end
161 line = tonumber(line)
162 fl[line] = prof_raw and v or pct
163 end
164 end
165 sort(files)
166 local fmtv, fmtn = " %3d%% | %s\n", " | %s\n"
167 if prof_raw then
168 local n = math.max(5, math.ceil(math.log10(ms)))
169 fmtv = "%"..n.."d | %s\n"
170 fmtn = (" "):rep(n).." | %s\n"
171 end
172 local ann = prof_ann
173 for _, file in ipairs(files) do
174 local f0 = file:byte()
175 if f0 == 40 or f0 == 91 then
176 out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file))
177 break
178 end
179 local fp, err = io.open(file)
180 if not fp then
181 out:write(format("====== ERROR: %s: %s\n", file, err))
182 break
183 end
184 out:write(format("\n====== %s ======\n", file))
185 local fl = files[file]
186 local n, show = 1, false
187 if ann ~= 0 then
188 for i=1,ann do
189 if fl[i] then show = true; out:write("@@ 1 @@\n"); break end
190 end
191 end
192 for line in fp:lines() do
193 if line:byte() == 27 then
194 out:write("[Cannot annotate bytecode file]\n")
195 break
196 end
197 local v = fl[n]
198 if ann ~= 0 then
199 local v2 = fl[n+ann]
200 if show then
201 if v2 then show = n+ann elseif v then show = n
202 elseif show+ann < n then show = false end
203 elseif v2 then
204 show = n+ann
205 out:write(format("@@ %d @@\n", n))
206 end
207 if not show then goto next end
208 end
209 if v then
210 out:write(format(fmtv, v, line))
211 else
212 out:write(format(fmtn, line))
213 end
214 ::next::
215 n = n + 1
216 end
217 fp:close()
218 end
219end
220
221------------------------------------------------------------------------------
222
223-- Finish profiling and dump result.
224local function prof_finish()
225 if prof_ud then
226 profile.stop()
227 local samples = prof_samples
228 if samples == 0 then
229 if prof_raw ~= true then out:write("[No samples collected]\n") end
230 return
231 end
232 if prof_ann then
233 prof_annotate(prof_count1, samples)
234 else
235 prof_top(prof_count1, prof_count2, samples, "")
236 end
237 prof_count1 = nil
238 prof_count2 = nil
239 prof_ud = nil
240 end
241end
242
243-- Start profiling.
244local function prof_start(mode)
245 local interval = ""
246 mode = mode:gsub("i%d*", function(s) interval = s; return "" end)
247 prof_min = 3
248 mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end)
249 prof_depth = 1
250 mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end)
251 local m = {}
252 for c in mode:gmatch(".") do m[c] = c end
253 prof_states = m.z or m.v
254 if prof_states == "z" then zone = require("jit.zone") end
255 local scope = m.l or m.f or m.F or (prof_states and "" or "f")
256 local flags = (m.p or "")
257 prof_raw = m.r
258 if m.s then
259 prof_split = 2
260 if prof_depth == -1 or m["-"] then prof_depth = -2
261 elseif prof_depth == 1 then prof_depth = 2 end
262 elseif mode:find("[fF].*l") then
263 scope = "l"
264 prof_split = 3
265 else
266 prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0
267 end
268 prof_ann = m.A and 0 or (m.a and 3)
269 if prof_ann then
270 scope = "l"
271 prof_fmt = "pl"
272 prof_split = 0
273 prof_depth = 1
274 elseif m.G and scope ~= "" then
275 prof_fmt = flags..scope.."Z;"
276 prof_depth = -100
277 prof_raw = true
278 prof_min = 0
279 elseif scope == "" then
280 prof_fmt = false
281 else
282 local sc = prof_split == 3 and m.f or m.F or scope
283 prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ")
284 end
285 prof_count1 = {}
286 prof_count2 = {}
287 prof_samples = 0
288 profile.start(scope:lower()..interval, prof_cb)
289 prof_ud = newproxy(true)
290 getmetatable(prof_ud).__gc = prof_finish
291end
292
293------------------------------------------------------------------------------
294
295local function start(mode, outfile)
296 if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end
297 if outfile then
298 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
299 else
300 out = stdout
301 end
302 prof_start(mode or "f")
303end
304
305-- Public module functions.
306return {
307 start = start, -- For -j command line option.
308 stop = prof_finish
309}
310
diff --git a/src/jit/v.lua b/src/jit/v.lua
index c622443d..157c34bc 100644
--- a/src/jit/v.lua
+++ b/src/jit/v.lua
@@ -59,7 +59,7 @@
59 59
60-- Cache some library functions and objects. 60-- Cache some library functions and objects.
61local jit = require("jit") 61local jit = require("jit")
62assert(jit.version_num == 20003, "LuaJIT core/library version mismatch") 62assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
63local jutil = require("jit.util") 63local jutil = require("jit.util")
64local vmdef = require("jit.vmdef") 64local vmdef = require("jit.vmdef")
65local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo 65local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
@@ -116,6 +116,9 @@ local function dump_trace(what, tr, func, pc, otr, oex)
116 if ltype == "interpreter" then 116 if ltype == "interpreter" then
117 out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", 117 out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n",
118 tr, startex, startloc)) 118 tr, startex, startloc))
119 elseif ltype == "stitch" then
120 out:write(format("[TRACE %3s %s%s %s %s]\n",
121 tr, startex, startloc, ltype, fmtfunc(func, pc)))
119 elseif link == tr or link == 0 then 122 elseif link == tr or link == 0 then
120 out:write(format("[TRACE %3s %s%s %s]\n", 123 out:write(format("[TRACE %3s %s%s %s]\n",
121 tr, startex, startloc, ltype)) 124 tr, startex, startloc, ltype))
@@ -159,9 +162,9 @@ local function dumpon(outfile)
159end 162end
160 163
161-- Public module functions. 164-- Public module functions.
162module(...) 165return {
163 166 on = dumpon,
164on = dumpon 167 off = dumpoff,
165off = dumpoff 168 start = dumpon -- For -j command line option.
166start = dumpon -- For -j command line option. 169}
167 170
diff --git a/src/jit/zone.lua b/src/jit/zone.lua
new file mode 100644
index 00000000..69f0f169
--- /dev/null
+++ b/src/jit/zone.lua
@@ -0,0 +1,45 @@
1----------------------------------------------------------------------------
2-- LuaJIT profiler zones.
3--
4-- Copyright (C) 2005-2015 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
39 t[#t+1] = zone
40 else
41 return (assert(remove(t), "empty zone stack"))
42 end
43 end
44})
45