js/src/jit/IonSpewer.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:00b7f6d2bda2
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifdef DEBUG
8
9 #include "jit/IonSpewer.h"
10
11 #include "jsworkers.h"
12
13 #include "jit/Ion.h"
14
15 #ifndef ION_SPEW_DIR
16 # if defined(_WIN32)
17 # define ION_SPEW_DIR ""
18 # elif defined(__ANDROID__)
19 # define ION_SPEW_DIR "/data/local/tmp/"
20 # else
21 # define ION_SPEW_DIR "/tmp/"
22 # endif
23 #endif
24
25 using namespace js;
26 using namespace js::jit;
27
28 // IonSpewer singleton.
29 static IonSpewer ionspewer;
30
31 static bool LoggingChecked = false;
32 static uint32_t LoggingBits = 0;
33 static uint32_t filteredOutCompilations = 0;
34
35 static const char * const ChannelNames[] =
36 {
37 #define IONSPEW_CHANNEL(name) #name,
38 IONSPEW_CHANNEL_LIST(IONSPEW_CHANNEL)
39 #undef IONSPEW_CHANNEL
40 };
41
42 static bool
43 FilterContainsLocation(HandleScript function)
44 {
45 static const char *filter = getenv("IONFILTER");
46
47 // If there is no filter we accept all outputs.
48 if (!filter || !filter[0])
49 return true;
50
51 // Disable asm.js output when filter is set.
52 if (!function)
53 return false;
54
55 const char *filename = function->filename();
56 const size_t line = function->lineno();
57 const size_t filelen = strlen(filename);
58 const char *index = strstr(filter, filename);
59 while (index) {
60 if (index == filter || index[-1] == ',') {
61 if (index[filelen] == 0 || index[filelen] == ',')
62 return true;
63 if (index[filelen] == ':' && line != size_t(-1)) {
64 size_t read_line = strtoul(&index[filelen + 1], nullptr, 10);
65 if (read_line == line)
66 return true;
67 }
68 }
69 index = strstr(index + filelen, filename);
70 }
71 return false;
72 }
73
74 void
75 jit::EnableIonDebugLogging()
76 {
77 EnableChannel(IonSpew_Logs);
78 ionspewer.init();
79 }
80
81 void
82 jit::IonSpewNewFunction(MIRGraph *graph, HandleScript func)
83 {
84 if (GetIonContext()->runtime->onMainThread())
85 ionspewer.beginFunction(graph, func);
86 }
87
88 void
89 jit::IonSpewPass(const char *pass)
90 {
91 if (GetIonContext()->runtime->onMainThread())
92 ionspewer.spewPass(pass);
93 }
94
95 void
96 jit::IonSpewPass(const char *pass, LinearScanAllocator *ra)
97 {
98 if (GetIonContext()->runtime->onMainThread())
99 ionspewer.spewPass(pass, ra);
100 }
101
102 void
103 jit::IonSpewEndFunction()
104 {
105 if (GetIonContext()->runtime->onMainThread())
106 ionspewer.endFunction();
107 }
108
109
110 IonSpewer::~IonSpewer()
111 {
112 if (!inited_)
113 return;
114
115 c1Spewer.finish();
116 jsonSpewer.finish();
117 }
118
119 bool
120 IonSpewer::init()
121 {
122 if (inited_)
123 return true;
124
125 if (!c1Spewer.init(ION_SPEW_DIR "ion.cfg"))
126 return false;
127 if (!jsonSpewer.init(ION_SPEW_DIR "ion.json"))
128 return false;
129
130 inited_ = true;
131 return true;
132 }
133
134 bool
135 IonSpewer::isSpewingFunction() const
136 {
137 return inited_ && graph;
138 }
139
140 void
141 IonSpewer::beginFunction(MIRGraph *graph, HandleScript function)
142 {
143 if (!inited_)
144 return;
145
146 if (!FilterContainsLocation(function)) {
147 JS_ASSERT(!this->graph);
148 // filter out logs during the compilation.
149 filteredOutCompilations++;
150 return;
151 }
152
153 this->graph = graph;
154 this->function.repoint(function);
155
156 c1Spewer.beginFunction(graph, function);
157 jsonSpewer.beginFunction(function);
158 }
159
160 void
161 IonSpewer::spewPass(const char *pass)
162 {
163 if (!isSpewingFunction())
164 return;
165
166 c1Spewer.spewPass(pass);
167 jsonSpewer.beginPass(pass);
168 jsonSpewer.spewMIR(graph);
169 jsonSpewer.spewLIR(graph);
170 jsonSpewer.endPass();
171 }
172
173 void
174 IonSpewer::spewPass(const char *pass, LinearScanAllocator *ra)
175 {
176 if (!isSpewingFunction())
177 return;
178
179 c1Spewer.spewPass(pass);
180 c1Spewer.spewIntervals(pass, ra);
181 jsonSpewer.beginPass(pass);
182 jsonSpewer.spewMIR(graph);
183 jsonSpewer.spewLIR(graph);
184 jsonSpewer.spewIntervals(ra);
185 jsonSpewer.endPass();
186 }
187
188 void
189 IonSpewer::endFunction()
190 {
191 if (!isSpewingFunction()) {
192 if (inited_) {
193 JS_ASSERT(filteredOutCompilations != 0);
194 filteredOutCompilations--;
195 }
196 return;
197 }
198
199 c1Spewer.endFunction();
200 jsonSpewer.endFunction();
201
202 this->graph = nullptr;
203 }
204
205
206 FILE *jit::IonSpewFile = nullptr;
207
208 static bool
209 ContainsFlag(const char *str, const char *flag)
210 {
211 size_t flaglen = strlen(flag);
212 const char *index = strstr(str, flag);
213 while (index) {
214 if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ','))
215 return true;
216 index = strstr(index + flaglen, flag);
217 }
218 return false;
219 }
220
221 void
222 jit::CheckLogging()
223 {
224 if (LoggingChecked)
225 return;
226 LoggingChecked = true;
227 const char *env = getenv("IONFLAGS");
228 if (!env)
229 return;
230 if (strstr(env, "help")) {
231 fflush(nullptr);
232 printf(
233 "\n"
234 "usage: IONFLAGS=option,option,option,... where options can be:\n"
235 "\n"
236 " aborts Compilation abort messages\n"
237 " scripts Compiled scripts\n"
238 " mir MIR information\n"
239 " alias Alias analysis\n"
240 " gvn Global Value Numbering\n"
241 " licm Loop invariant code motion\n"
242 " regalloc Register allocation\n"
243 " inline Inlining\n"
244 " snapshots Snapshot information\n"
245 " codegen Native code generation\n"
246 " bailouts Bailouts\n"
247 " caches Inline caches\n"
248 " osi Invalidation\n"
249 " safepoints Safepoints\n"
250 " pools Literal Pools (ARM only for now)\n"
251 " cacheflush Instruction Cache flushes (ARM only for now)\n"
252 " range Range Analysis\n"
253 " logs C1 and JSON visualization logging\n"
254 " trace Generate calls to js::jit::Trace() for effectful instructions\n"
255 " all Everything\n"
256 "\n"
257 " bl-aborts Baseline compiler abort messages\n"
258 " bl-scripts Baseline script-compilation\n"
259 " bl-op Baseline compiler detailed op-specific messages\n"
260 " bl-ic Baseline inline-cache messages\n"
261 " bl-ic-fb Baseline IC fallback stub messages\n"
262 " bl-osr Baseline IC OSR messages\n"
263 " bl-bails Baseline bailouts\n"
264 " bl-dbg-osr Baseline debug mode on stack recompile messages\n"
265 " bl-all All baseline spew\n"
266 "\n"
267 );
268 exit(0);
269 /*NOTREACHED*/
270 }
271 if (ContainsFlag(env, "aborts"))
272 EnableChannel(IonSpew_Abort);
273 if (ContainsFlag(env, "alias"))
274 EnableChannel(IonSpew_Alias);
275 if (ContainsFlag(env, "scripts"))
276 EnableChannel(IonSpew_Scripts);
277 if (ContainsFlag(env, "mir"))
278 EnableChannel(IonSpew_MIR);
279 if (ContainsFlag(env, "gvn"))
280 EnableChannel(IonSpew_GVN);
281 if (ContainsFlag(env, "range"))
282 EnableChannel(IonSpew_Range);
283 if (ContainsFlag(env, "licm"))
284 EnableChannel(IonSpew_LICM);
285 if (ContainsFlag(env, "regalloc"))
286 EnableChannel(IonSpew_RegAlloc);
287 if (ContainsFlag(env, "inline"))
288 EnableChannel(IonSpew_Inlining);
289 if (ContainsFlag(env, "snapshots"))
290 EnableChannel(IonSpew_Snapshots);
291 if (ContainsFlag(env, "codegen"))
292 EnableChannel(IonSpew_Codegen);
293 if (ContainsFlag(env, "bailouts"))
294 EnableChannel(IonSpew_Bailouts);
295 if (ContainsFlag(env, "osi"))
296 EnableChannel(IonSpew_Invalidate);
297 if (ContainsFlag(env, "caches"))
298 EnableChannel(IonSpew_InlineCaches);
299 if (ContainsFlag(env, "safepoints"))
300 EnableChannel(IonSpew_Safepoints);
301 if (ContainsFlag(env, "pools"))
302 EnableChannel(IonSpew_Pools);
303 if (ContainsFlag(env, "cacheflush"))
304 EnableChannel(IonSpew_CacheFlush);
305 if (ContainsFlag(env, "logs"))
306 EnableIonDebugLogging();
307 if (ContainsFlag(env, "trace"))
308 EnableChannel(IonSpew_Trace);
309 if (ContainsFlag(env, "all"))
310 LoggingBits = uint32_t(-1);
311
312 if (ContainsFlag(env, "bl-aborts"))
313 EnableChannel(IonSpew_BaselineAbort);
314 if (ContainsFlag(env, "bl-scripts"))
315 EnableChannel(IonSpew_BaselineScripts);
316 if (ContainsFlag(env, "bl-op"))
317 EnableChannel(IonSpew_BaselineOp);
318 if (ContainsFlag(env, "bl-ic"))
319 EnableChannel(IonSpew_BaselineIC);
320 if (ContainsFlag(env, "bl-ic-fb"))
321 EnableChannel(IonSpew_BaselineICFallback);
322 if (ContainsFlag(env, "bl-osr"))
323 EnableChannel(IonSpew_BaselineOSR);
324 if (ContainsFlag(env, "bl-bails"))
325 EnableChannel(IonSpew_BaselineBailouts);
326 if (ContainsFlag(env, "bl-dbg-osr"))
327 EnableChannel(IonSpew_BaselineDebugModeOSR);
328 if (ContainsFlag(env, "bl-all")) {
329 EnableChannel(IonSpew_BaselineAbort);
330 EnableChannel(IonSpew_BaselineScripts);
331 EnableChannel(IonSpew_BaselineOp);
332 EnableChannel(IonSpew_BaselineIC);
333 EnableChannel(IonSpew_BaselineICFallback);
334 EnableChannel(IonSpew_BaselineOSR);
335 EnableChannel(IonSpew_BaselineBailouts);
336 EnableChannel(IonSpew_BaselineDebugModeOSR);
337 }
338
339 IonSpewFile = stderr;
340 }
341
342 void
343 jit::IonSpewStartVA(IonSpewChannel channel, const char *fmt, va_list ap)
344 {
345 if (!IonSpewEnabled(channel))
346 return;
347
348 IonSpewHeader(channel);
349 vfprintf(stderr, fmt, ap);
350 }
351
352 void
353 jit::IonSpewContVA(IonSpewChannel channel, const char *fmt, va_list ap)
354 {
355 if (!IonSpewEnabled(channel))
356 return;
357
358 vfprintf(stderr, fmt, ap);
359 }
360
361 void
362 jit::IonSpewFin(IonSpewChannel channel)
363 {
364 if (!IonSpewEnabled(channel))
365 return;
366
367 fprintf(stderr, "\n");
368 }
369
370 void
371 jit::IonSpewVA(IonSpewChannel channel, const char *fmt, va_list ap)
372 {
373 IonSpewStartVA(channel, fmt, ap);
374 IonSpewFin(channel);
375 }
376
377 void
378 jit::IonSpew(IonSpewChannel channel, const char *fmt, ...)
379 {
380 va_list ap;
381 va_start(ap, fmt);
382 IonSpewVA(channel, fmt, ap);
383 va_end(ap);
384 }
385
386 void
387 jit::IonSpewStart(IonSpewChannel channel, const char *fmt, ...)
388 {
389 va_list ap;
390 va_start(ap, fmt);
391 IonSpewStartVA(channel, fmt, ap);
392 va_end(ap);
393 }
394 void
395 jit::IonSpewCont(IonSpewChannel channel, const char *fmt, ...)
396 {
397 va_list ap;
398 va_start(ap, fmt);
399 IonSpewContVA(channel, fmt, ap);
400 va_end(ap);
401 }
402
403 void
404 jit::IonSpewHeader(IonSpewChannel channel)
405 {
406 if (!IonSpewEnabled(channel))
407 return;
408
409 fprintf(stderr, "[%s] ", ChannelNames[channel]);
410 }
411
412 bool
413 jit::IonSpewEnabled(IonSpewChannel channel)
414 {
415 JS_ASSERT(LoggingChecked);
416 return (LoggingBits & (1 << uint32_t(channel))) && !filteredOutCompilations;
417 }
418
419 void
420 jit::EnableChannel(IonSpewChannel channel)
421 {
422 JS_ASSERT(LoggingChecked);
423 LoggingBits |= (1 << uint32_t(channel));
424 }
425
426 void
427 jit::DisableChannel(IonSpewChannel channel)
428 {
429 JS_ASSERT(LoggingChecked);
430 LoggingBits &= ~(1 << uint32_t(channel));
431 }
432
433 #endif /* DEBUG */
434

mercurial