summaryrefslogtreecommitdiff
path: root/lib/v.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lib/v.lua')
-rw-r--r--lib/v.lua156
1 files changed, 156 insertions, 0 deletions
diff --git a/lib/v.lua b/lib/v.lua
new file mode 100644
index 00000000..39fb8ed5
--- /dev/null
+++ b/lib/v.lua
@@ -0,0 +1,156 @@
1----------------------------------------------------------------------------
2-- Verbose mode of the LuaJIT compiler.
3--
4-- Copyright (C) 2005-2009 Mike Pall. All rights reserved.
5-- Released under the MIT/X license. See Copyright Notice in luajit.h
6----------------------------------------------------------------------------
7--
8-- This module shows verbose information about the progress of the
9-- JIT compiler. It prints one line for each generated trace. This module
10-- is useful to see which code has been compiled or where the compiler
11-- punts and falls back to the interpreter.
12--
13-- Example usage:
14--
15-- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end"
16-- luajit -jv=myapp.out myapp.lua
17--
18-- Default output is to stderr. To redirect the output to a file, pass a
19-- filename as an argument (use '-' for stdout) or set the environment
20-- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the
21-- module is started.
22--
23-- The output from the first example should look like this:
24--
25-- [TRACE 1 (command line):1]
26-- [TRACE 2 (1/3) (command line):1 -> 1]
27--
28-- The first number in each line is the internal trace number. Next are
29-- the file name ('(command line)') and the line number (':1') where the
30-- trace has started. Side traces also show the parent trace number and
31-- the exit number where they are attached to in parentheses ('(1/3)').
32-- An arrow at the end shows where the trace links to ('-> 1'), unless
33-- it loops to itself.
34--
35-- In this case the inner loop gets hot and is traced first, generating
36-- a root trace. Then the last exit from the 1st trace gets hot, too,
37-- and triggers generation of the 2nd trace. The side trace follows the
38-- path along the outer loop and *around* the inner loop, back to its
39-- start, and then links to the 1st trace. Yes, this may seem unusual,
40-- if you know how traditional compilers work. Trace compilers are full
41-- of surprises like this -- have fun! :-)
42--
43-- Aborted traces are shown like this:
44--
45-- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50]
46--
47-- Don't worry -- trace aborts are quite common, even in programs which
48-- can be fully compiled. The compiler may retry several times until it
49-- finds a suitable trace.
50--
51-- Of course this doesn't work with features that are not-yet-implemented
52-- (NYI error messages). The VM simply falls back to the interpreter. This
53-- may not matter at all if the particular trace is not very high up in
54-- the CPU usage profile. Oh, and the interpreter is quite fast, too.
55--
56-- Also check out the -jdump module, which prints all the gory details.
57--
58------------------------------------------------------------------------------
59
60-- Cache some library functions and objects.
61local jit = require("jit")
62assert(jit.version_num == 20000, "LuaJIT core/library version mismatch")
63local jutil = require("jit.util")
64local vmdef = require("jit.vmdef")
65local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
66local type, format = type, string.format
67local stdout, stderr = io.stdout, io.stderr
68
69-- Active flag and output file handle.
70local active, out
71
72------------------------------------------------------------------------------
73
74local startloc, startex
75
76-- Format trace error message.
77local function fmterr(err, info)
78 if type(err) == "number" then
79 if type(info) == "function" then
80 local fi = funcinfo(info)
81 if fi.ffid then
82 info = vmdef.ffnames[fi.ffid]
83 else
84 info = fi.loc
85 end
86 end
87 err = format(vmdef.traceerr[err], info)
88 end
89 return err
90end
91
92-- Dump trace states.
93local function dump_trace(what, tr, func, pc, otr, oex)
94 if what == "start" then
95 startloc = funcinfo(func, pc).loc
96 startex = otr and "("..otr.."/"..oex..") " or ""
97 else
98 if what == "abort" then
99 local loc = funcinfo(func, pc).loc
100 if loc ~= startloc then
101 out:write(format("[TRACE --- %s%s -- %s at %s]\n",
102 startex, startloc, fmterr(otr, oex), loc))
103 else
104 out:write(format("[TRACE --- %s%s -- %s]\n",
105 startex, startloc, fmterr(otr, oex)))
106 end
107 elseif what == "stop" then
108 local link = traceinfo(tr).link
109 if link == 0 then
110 out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n",
111 tr, startex, startloc))
112 elseif link == tr then
113 out:write(format("[TRACE %3s %s%s]\n", tr, startex, startloc))
114 else
115 out:write(format("[TRACE %3s %s%s -> %d]\n",
116 tr, startex, startloc, link))
117 end
118 else
119 out:write(format("[TRACE %s]\n", what))
120 end
121 out:flush()
122 end
123end
124
125------------------------------------------------------------------------------
126
127-- Detach dump handlers.
128local function dumpoff()
129 if active then
130 active = false
131 jit.attach(dump_trace)
132 if out and out ~= stdout and out ~= stderr then out:close() end
133 out = nil
134 end
135end
136
137-- Open the output file and attach dump handlers.
138local function dumpon(outfile)
139 if active then dumpoff() end
140 if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end
141 if outfile then
142 out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
143 else
144 out = stderr
145 end
146 jit.attach(dump_trace, "trace")
147 active = true
148end
149
150-- Public module functions.
151module(...)
152
153on = dumpon
154off = dumpoff
155start = dumpon -- For -j command line option.
156