Line data Source code
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 JS_JITSPEW
8 :
9 : #include "jit/JitSpewer.h"
10 :
11 : #include "mozilla/Atomics.h"
12 :
13 : #ifdef XP_WIN
14 : #include <process.h>
15 : #define getpid _getpid
16 : #else
17 : #include <unistd.h>
18 : #endif
19 :
20 : #include "jsprf.h"
21 :
22 : #include "jit/Ion.h"
23 : #include "jit/MIR.h"
24 : #include "jit/MIRGenerator.h"
25 : #include "jit/MIRGraph.h"
26 :
27 : #include "threading/LockGuard.h"
28 :
29 : #include "vm/HelperThreads.h"
30 : #include "vm/MutexIDs.h"
31 :
32 : #include "jscompartmentinlines.h"
33 :
34 : #ifndef JIT_SPEW_DIR
35 : # if defined(_WIN32)
36 : # define JIT_SPEW_DIR "."
37 : # elif defined(__ANDROID__)
38 : # define JIT_SPEW_DIR "/data/local/tmp"
39 : # else
40 : # define JIT_SPEW_DIR "/tmp"
41 : # endif
42 : #endif
43 :
44 : using namespace js;
45 : using namespace js::jit;
46 :
47 : class IonSpewer
48 : {
49 : private:
50 : Mutex outputLock_;
51 : Fprinter c1Output_;
52 : Fprinter jsonOutput_;
53 : bool firstFunction_;
54 : bool asyncLogging_;
55 : bool inited_;
56 :
57 : void release();
58 :
59 : public:
60 3 : IonSpewer()
61 3 : : outputLock_(mutexid::IonSpewer),
62 : firstFunction_(false),
63 : asyncLogging_(false),
64 3 : inited_(false)
65 3 : { }
66 :
67 : // File output is terminated safely upon destruction.
68 : ~IonSpewer();
69 :
70 : bool init();
71 20 : bool isEnabled() {
72 20 : return inited_;
73 : }
74 0 : void setAsyncLogging(bool incremental) {
75 0 : asyncLogging_ = incremental;
76 0 : }
77 0 : bool getAsyncLogging() {
78 0 : return asyncLogging_;
79 : }
80 :
81 : void beginFunction();
82 : void spewPass(GraphSpewer* gs);
83 : void endFunction(GraphSpewer* gs);
84 : };
85 :
86 : // IonSpewer singleton.
87 3 : static IonSpewer ionspewer;
88 :
89 : static bool LoggingChecked = false;
90 : static_assert(JitSpew_Terminator <= 64, "Increase the size of the LoggingBits global.");
91 : static uint64_t LoggingBits = 0;
92 : static mozilla::Atomic<uint32_t, mozilla::Relaxed> filteredOutCompilations(0);
93 :
94 : static const char * const ChannelNames[] =
95 : {
96 : #define JITSPEW_CHANNEL(name) #name,
97 : JITSPEW_CHANNEL_LIST(JITSPEW_CHANNEL)
98 : #undef JITSPEW_CHANNEL
99 : };
100 :
101 : static size_t ChannelIndentLevel[] =
102 : {
103 : #define JITSPEW_CHANNEL(name) 0,
104 : JITSPEW_CHANNEL_LIST(JITSPEW_CHANNEL)
105 : #undef JITSPEW_CHANNEL
106 : };
107 :
108 : static bool
109 0 : FilterContainsLocation(JSScript* function)
110 : {
111 0 : static const char* filter = getenv("IONFILTER");
112 :
113 : // If there is no filter we accept all outputs.
114 0 : if (!filter || !filter[0])
115 0 : return true;
116 :
117 : // Disable wasm output when filter is set.
118 0 : if (!function)
119 0 : return false;
120 :
121 0 : const char* filename = function->filename();
122 0 : const size_t line = function->lineno();
123 0 : const size_t filelen = strlen(filename);
124 0 : const char* index = strstr(filter, filename);
125 0 : while (index) {
126 0 : if (index == filter || index[-1] == ',') {
127 0 : if (index[filelen] == 0 || index[filelen] == ',')
128 0 : return true;
129 0 : if (index[filelen] == ':' && line != size_t(-1)) {
130 0 : size_t read_line = strtoul(&index[filelen + 1], nullptr, 10);
131 0 : if (read_line == line)
132 0 : return true;
133 : }
134 : }
135 0 : index = strstr(index + filelen, filename);
136 : }
137 0 : return false;
138 : }
139 :
140 : void
141 0 : jit::EnableIonDebugSyncLogging()
142 : {
143 0 : ionspewer.init();
144 0 : ionspewer.setAsyncLogging(false);
145 0 : EnableChannel(JitSpew_IonSyncLogs);
146 0 : }
147 :
148 : void
149 0 : jit::EnableIonDebugAsyncLogging()
150 : {
151 0 : ionspewer.init();
152 0 : ionspewer.setAsyncLogging(true);
153 0 : }
154 :
155 : void
156 0 : IonSpewer::release()
157 : {
158 0 : if (c1Output_.isInitialized())
159 0 : c1Output_.finish();
160 0 : if (jsonOutput_.isInitialized())
161 0 : jsonOutput_.finish();
162 0 : inited_ = false;
163 0 : }
164 :
165 : bool
166 0 : IonSpewer::init()
167 : {
168 0 : if (inited_)
169 0 : return true;
170 :
171 0 : const size_t bufferLength = 256;
172 : char c1Buffer[bufferLength];
173 : char jsonBuffer[bufferLength];
174 0 : const char *c1Filename = JIT_SPEW_DIR "/ion.cfg";
175 0 : const char *jsonFilename = JIT_SPEW_DIR "/ion.json";
176 :
177 0 : const char* usePid = getenv("ION_SPEW_BY_PID");
178 0 : if (usePid && *usePid != 0) {
179 0 : uint32_t pid = getpid();
180 : size_t len;
181 0 : len = snprintf(jsonBuffer, bufferLength, JIT_SPEW_DIR "/ion%" PRIu32 ".json", pid);
182 0 : if (bufferLength <= len) {
183 0 : fprintf(stderr, "Warning: IonSpewer::init: Cannot serialize file name.");
184 0 : return false;
185 : }
186 0 : jsonFilename = jsonBuffer;
187 :
188 0 : len = snprintf(c1Buffer, bufferLength, JIT_SPEW_DIR "/ion%" PRIu32 ".cfg", pid);
189 0 : if (bufferLength <= len) {
190 0 : fprintf(stderr, "Warning: IonSpewer::init: Cannot serialize file name.");
191 0 : return false;
192 : }
193 0 : c1Filename = c1Buffer;
194 : }
195 :
196 0 : if (!c1Output_.init(c1Filename) ||
197 0 : !jsonOutput_.init(jsonFilename))
198 : {
199 0 : release();
200 0 : return false;
201 : }
202 :
203 0 : jsonOutput_.printf("{\n \"functions\": [\n");
204 0 : firstFunction_ = true;
205 :
206 0 : inited_ = true;
207 0 : return true;
208 : }
209 :
210 : void
211 0 : IonSpewer::beginFunction()
212 : {
213 : // If we are doing a synchronous logging then we spew everything as we go,
214 : // as this is useful in case of failure during the compilation. On the other
215 : // hand, it is recommended to disable off thread compilation.
216 0 : if (!getAsyncLogging() && !firstFunction_) {
217 0 : LockGuard<Mutex> guard(outputLock_);
218 0 : jsonOutput_.put(","); // separate functions
219 : }
220 0 : }
221 :
222 : void
223 0 : IonSpewer::spewPass(GraphSpewer* gs)
224 : {
225 0 : if (!getAsyncLogging()) {
226 0 : LockGuard<Mutex> guard(outputLock_);
227 0 : gs->dump(c1Output_, jsonOutput_);
228 : }
229 0 : }
230 :
231 : void
232 0 : IonSpewer::endFunction(GraphSpewer* gs)
233 : {
234 0 : LockGuard<Mutex> guard(outputLock_);
235 0 : if (getAsyncLogging() && !firstFunction_)
236 0 : jsonOutput_.put(","); // separate functions
237 :
238 0 : gs->dump(c1Output_, jsonOutput_);
239 0 : firstFunction_ = false;
240 0 : }
241 :
242 0 : IonSpewer::~IonSpewer()
243 : {
244 0 : if (!inited_)
245 0 : return;
246 :
247 0 : jsonOutput_.printf("\n]}\n");
248 0 : release();
249 0 : }
250 :
251 179 : GraphSpewer::GraphSpewer(TempAllocator *alloc)
252 : : graph_(nullptr),
253 : c1Printer_(alloc->lifoAlloc()),
254 : jsonPrinter_(alloc->lifoAlloc()),
255 : c1Spewer_(c1Printer_),
256 179 : jsonSpewer_(jsonPrinter_)
257 : {
258 179 : }
259 :
260 : void
261 10 : GraphSpewer::init(MIRGraph* graph, JSScript* function)
262 : {
263 10 : MOZ_ASSERT(!isSpewing());
264 10 : if (!ionspewer.isEnabled())
265 10 : return;
266 :
267 0 : if (!FilterContainsLocation(function)) {
268 : // filter out logs during the compilation.
269 0 : filteredOutCompilations++;
270 0 : MOZ_ASSERT(!isSpewing());
271 0 : return;
272 : }
273 :
274 0 : graph_ = graph;
275 0 : MOZ_ASSERT(isSpewing());
276 : }
277 :
278 : void
279 10 : GraphSpewer::beginFunction(JSScript* function)
280 : {
281 10 : if (!isSpewing())
282 10 : return;
283 :
284 0 : c1Spewer_.beginFunction(graph_, function);
285 0 : jsonSpewer_.beginFunction(function);
286 :
287 0 : ionspewer.beginFunction();
288 : }
289 :
290 : void
291 240 : GraphSpewer::spewPass(const char* pass)
292 : {
293 240 : if (!isSpewing())
294 240 : return;
295 :
296 0 : c1Spewer_.spewPass(pass);
297 :
298 0 : jsonSpewer_.beginPass(pass);
299 0 : jsonSpewer_.spewMIR(graph_);
300 0 : jsonSpewer_.spewLIR(graph_);
301 0 : jsonSpewer_.endPass();
302 :
303 0 : ionspewer.spewPass(this);
304 :
305 : // As this function is used for debugging, we ignore any of the previous
306 : // failures and ensure there is enough ballast space, such that we do not
307 : // exhaust the ballast space before running the next phase.
308 0 : AutoEnterOOMUnsafeRegion oomUnsafe;
309 0 : if (!graph_->alloc().ensureBallast())
310 0 : oomUnsafe.crash("Could not ensure enough ballast space after spewing graph information.");
311 : }
312 :
313 : void
314 0 : GraphSpewer::spewPass(const char* pass, BacktrackingAllocator* ra)
315 : {
316 0 : if (!isSpewing())
317 0 : return;
318 :
319 0 : c1Spewer_.spewPass(pass);
320 0 : c1Spewer_.spewRanges(pass, ra);
321 :
322 0 : jsonSpewer_.beginPass(pass);
323 0 : jsonSpewer_.spewMIR(graph_);
324 0 : jsonSpewer_.spewLIR(graph_);
325 0 : jsonSpewer_.spewRanges(ra);
326 0 : jsonSpewer_.endPass();
327 :
328 0 : ionspewer.spewPass(this);
329 : }
330 :
331 : void
332 10 : GraphSpewer::endFunction()
333 : {
334 10 : if (!ionspewer.isEnabled())
335 10 : return;
336 :
337 0 : if (!isSpewing()) {
338 0 : MOZ_ASSERT(filteredOutCompilations != 0);
339 0 : filteredOutCompilations--;
340 0 : return;
341 : }
342 :
343 0 : c1Spewer_.endFunction();
344 0 : jsonSpewer_.endFunction();
345 :
346 0 : ionspewer.endFunction(this);
347 0 : graph_ = nullptr;
348 : }
349 :
350 : void
351 0 : GraphSpewer::dump(Fprinter& c1Out, Fprinter& jsonOut)
352 : {
353 0 : if (!c1Printer_.hadOutOfMemory()) {
354 0 : c1Printer_.exportInto(c1Out);
355 0 : c1Out.flush();
356 : }
357 0 : c1Printer_.clear();
358 :
359 0 : if (!jsonPrinter_.hadOutOfMemory())
360 0 : jsonPrinter_.exportInto(jsonOut);
361 : else
362 0 : jsonOut.put("{}");
363 0 : jsonOut.flush();
364 0 : jsonPrinter_.clear();
365 0 : }
366 :
367 : void
368 10 : jit::SpewBeginFunction(MIRGenerator* mir, JSScript* function)
369 : {
370 10 : MIRGraph* graph = &mir->graph();
371 10 : mir->graphSpewer().init(graph, function);
372 10 : mir->graphSpewer().beginFunction(function);
373 10 : }
374 :
375 16 : AutoSpewEndFunction::~AutoSpewEndFunction()
376 : {
377 8 : mir_->graphSpewer().endFunction();
378 8 : }
379 :
380 : Fprinter&
381 0 : jit::JitSpewPrinter()
382 : {
383 0 : static Fprinter out;
384 0 : return out;
385 : }
386 :
387 :
388 : static bool
389 0 : ContainsFlag(const char* str, const char* flag)
390 : {
391 0 : size_t flaglen = strlen(flag);
392 0 : const char* index = strstr(str, flag);
393 0 : while (index) {
394 0 : if ((index == str || index[-1] == ',') && (index[flaglen] == 0 || index[flaglen] == ','))
395 0 : return true;
396 0 : index = strstr(index + flaglen, flag);
397 : }
398 0 : return false;
399 : }
400 :
401 : void
402 3 : jit::CheckLogging()
403 : {
404 3 : if (LoggingChecked)
405 0 : return;
406 3 : LoggingChecked = true;
407 3 : const char* env = getenv("IONFLAGS");
408 3 : if (!env)
409 3 : return;
410 0 : if (strstr(env, "help")) {
411 0 : fflush(nullptr);
412 : printf(
413 : "\n"
414 : "usage: IONFLAGS=option,option,option,... where options can be:\n"
415 : "\n"
416 : " aborts Compilation abort messages\n"
417 : " scripts Compiled scripts\n"
418 : " mir MIR information\n"
419 : " prune Prune unused branches\n"
420 : " escape Escape analysis\n"
421 : " alias Alias analysis\n"
422 : " alias-sum Alias analysis: shows summaries for every block\n"
423 : " gvn Global Value Numbering\n"
424 : " licm Loop invariant code motion\n"
425 : " flac Fold linear arithmetic constants\n"
426 : " eaa Effective address analysis\n"
427 : " sincos Replace sin/cos by sincos\n"
428 : " sink Sink transformation\n"
429 : " regalloc Register allocation\n"
430 : " inline Inlining\n"
431 : " snapshots Snapshot information\n"
432 : " codegen Native code generation\n"
433 : " bailouts Bailouts\n"
434 : " caches Inline caches\n"
435 : " osi Invalidation\n"
436 : " safepoints Safepoints\n"
437 : " pools Literal Pools (ARM only for now)\n"
438 : " cacheflush Instruction Cache flushes (ARM only for now)\n"
439 : " range Range Analysis\n"
440 : " unroll Loop unrolling\n"
441 : " logs C1 and JSON visualization logging\n"
442 : " logs-sync Same as logs, but flushes between each pass (sync. compiled functions only).\n"
443 : " profiling Profiling-related information\n"
444 : " trackopts Optimization tracking information gathered by the Gecko profiler. "
445 : "(Note: call enableGeckoProfiling() in your script to enable it).\n"
446 : " trackopts-ext Encoding information about optimization tracking\n"
447 : " dump-mir-expr Dump the MIR expressions\n"
448 : " cfg Control flow graph generation\n"
449 : " all Everything\n"
450 : "\n"
451 : " bl-aborts Baseline compiler abort messages\n"
452 : " bl-scripts Baseline script-compilation\n"
453 : " bl-op Baseline compiler detailed op-specific messages\n"
454 : " bl-ic Baseline inline-cache messages\n"
455 : " bl-ic-fb Baseline IC fallback stub messages\n"
456 : " bl-osr Baseline IC OSR messages\n"
457 : " bl-bails Baseline bailouts\n"
458 : " bl-dbg-osr Baseline debug mode on stack recompile messages\n"
459 : " bl-all All baseline spew\n"
460 : "\n"
461 0 : );
462 0 : exit(0);
463 : /*NOTREACHED*/
464 : }
465 0 : if (ContainsFlag(env, "aborts"))
466 0 : EnableChannel(JitSpew_IonAbort);
467 0 : if (ContainsFlag(env, "prune"))
468 0 : EnableChannel(JitSpew_Prune);
469 0 : if (ContainsFlag(env, "escape"))
470 0 : EnableChannel(JitSpew_Escape);
471 0 : if (ContainsFlag(env, "alias"))
472 0 : EnableChannel(JitSpew_Alias);
473 0 : if (ContainsFlag(env, "alias-sum"))
474 0 : EnableChannel(JitSpew_AliasSummaries);
475 0 : if (ContainsFlag(env, "scripts"))
476 0 : EnableChannel(JitSpew_IonScripts);
477 0 : if (ContainsFlag(env, "mir"))
478 0 : EnableChannel(JitSpew_IonMIR);
479 0 : if (ContainsFlag(env, "gvn"))
480 0 : EnableChannel(JitSpew_GVN);
481 0 : if (ContainsFlag(env, "range"))
482 0 : EnableChannel(JitSpew_Range);
483 0 : if (ContainsFlag(env, "unroll"))
484 0 : EnableChannel(JitSpew_Unrolling);
485 0 : if (ContainsFlag(env, "licm"))
486 0 : EnableChannel(JitSpew_LICM);
487 0 : if (ContainsFlag(env, "flac"))
488 0 : EnableChannel(JitSpew_FLAC);
489 0 : if (ContainsFlag(env, "eaa"))
490 0 : EnableChannel(JitSpew_EAA);
491 0 : if (ContainsFlag(env, "sincos"))
492 0 : EnableChannel(JitSpew_Sincos);
493 0 : if (ContainsFlag(env, "sink"))
494 0 : EnableChannel(JitSpew_Sink);
495 0 : if (ContainsFlag(env, "regalloc"))
496 0 : EnableChannel(JitSpew_RegAlloc);
497 0 : if (ContainsFlag(env, "inline"))
498 0 : EnableChannel(JitSpew_Inlining);
499 0 : if (ContainsFlag(env, "snapshots"))
500 0 : EnableChannel(JitSpew_IonSnapshots);
501 0 : if (ContainsFlag(env, "codegen"))
502 0 : EnableChannel(JitSpew_Codegen);
503 0 : if (ContainsFlag(env, "bailouts"))
504 0 : EnableChannel(JitSpew_IonBailouts);
505 0 : if (ContainsFlag(env, "osi"))
506 0 : EnableChannel(JitSpew_IonInvalidate);
507 0 : if (ContainsFlag(env, "caches"))
508 0 : EnableChannel(JitSpew_IonIC);
509 0 : if (ContainsFlag(env, "safepoints"))
510 0 : EnableChannel(JitSpew_Safepoints);
511 0 : if (ContainsFlag(env, "pools"))
512 0 : EnableChannel(JitSpew_Pools);
513 0 : if (ContainsFlag(env, "cacheflush"))
514 0 : EnableChannel(JitSpew_CacheFlush);
515 0 : if (ContainsFlag(env, "logs"))
516 0 : EnableIonDebugAsyncLogging();
517 0 : if (ContainsFlag(env, "logs-sync"))
518 0 : EnableIonDebugSyncLogging();
519 0 : if (ContainsFlag(env, "profiling"))
520 0 : EnableChannel(JitSpew_Profiling);
521 0 : if (ContainsFlag(env, "trackopts")) {
522 0 : JitOptions.disableOptimizationTracking = false;
523 0 : EnableChannel(JitSpew_OptimizationTracking);
524 : }
525 0 : if (ContainsFlag(env, "trackopts-ext"))
526 0 : EnableChannel(JitSpew_OptimizationTrackingExtended);
527 0 : if (ContainsFlag(env, "dump-mir-expr"))
528 0 : EnableChannel(JitSpew_MIRExpressions);
529 0 : if (ContainsFlag(env, "cfg"))
530 0 : EnableChannel(JitSpew_CFG);
531 0 : if (ContainsFlag(env, "all"))
532 0 : LoggingBits = uint64_t(-1);
533 :
534 0 : if (ContainsFlag(env, "bl-aborts"))
535 0 : EnableChannel(JitSpew_BaselineAbort);
536 0 : if (ContainsFlag(env, "bl-scripts"))
537 0 : EnableChannel(JitSpew_BaselineScripts);
538 0 : if (ContainsFlag(env, "bl-op"))
539 0 : EnableChannel(JitSpew_BaselineOp);
540 0 : if (ContainsFlag(env, "bl-ic"))
541 0 : EnableChannel(JitSpew_BaselineIC);
542 0 : if (ContainsFlag(env, "bl-ic-fb"))
543 0 : EnableChannel(JitSpew_BaselineICFallback);
544 0 : if (ContainsFlag(env, "bl-osr"))
545 0 : EnableChannel(JitSpew_BaselineOSR);
546 0 : if (ContainsFlag(env, "bl-bails"))
547 0 : EnableChannel(JitSpew_BaselineBailouts);
548 0 : if (ContainsFlag(env, "bl-dbg-osr"))
549 0 : EnableChannel(JitSpew_BaselineDebugModeOSR);
550 0 : if (ContainsFlag(env, "bl-all")) {
551 0 : EnableChannel(JitSpew_BaselineAbort);
552 0 : EnableChannel(JitSpew_BaselineScripts);
553 0 : EnableChannel(JitSpew_BaselineOp);
554 0 : EnableChannel(JitSpew_BaselineIC);
555 0 : EnableChannel(JitSpew_BaselineICFallback);
556 0 : EnableChannel(JitSpew_BaselineOSR);
557 0 : EnableChannel(JitSpew_BaselineBailouts);
558 0 : EnableChannel(JitSpew_BaselineDebugModeOSR);
559 : }
560 :
561 0 : JitSpewPrinter().init(stderr);
562 : }
563 :
564 836 : JitSpewIndent::JitSpewIndent(JitSpewChannel channel)
565 836 : : channel_(channel)
566 : {
567 836 : ChannelIndentLevel[channel]++;
568 836 : }
569 :
570 1672 : JitSpewIndent::~JitSpewIndent()
571 : {
572 836 : ChannelIndentLevel[channel_]--;
573 836 : }
574 :
575 : void
576 257176 : jit::JitSpewStartVA(JitSpewChannel channel, const char* fmt, va_list ap)
577 : {
578 257176 : if (!JitSpewEnabled(channel))
579 257176 : return;
580 :
581 0 : JitSpewHeader(channel);
582 0 : Fprinter& out = JitSpewPrinter();
583 0 : out.vprintf(fmt, ap);
584 : }
585 :
586 : void
587 535 : jit::JitSpewContVA(JitSpewChannel channel, const char* fmt, va_list ap)
588 : {
589 535 : if (!JitSpewEnabled(channel))
590 535 : return;
591 :
592 0 : Fprinter& out = JitSpewPrinter();
593 0 : out.vprintf(fmt, ap);
594 : }
595 :
596 : void
597 257169 : jit::JitSpewFin(JitSpewChannel channel)
598 : {
599 257169 : if (!JitSpewEnabled(channel))
600 257169 : return;
601 :
602 0 : Fprinter& out = JitSpewPrinter();
603 0 : out.put("\n");
604 : }
605 :
606 : void
607 255379 : jit::JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap)
608 : {
609 255379 : JitSpewStartVA(channel, fmt, ap);
610 255379 : JitSpewFin(channel);
611 255379 : }
612 :
613 : void
614 255375 : jit::JitSpew(JitSpewChannel channel, const char* fmt, ...)
615 : {
616 : va_list ap;
617 255375 : va_start(ap, fmt);
618 255375 : JitSpewVA(channel, fmt, ap);
619 255376 : va_end(ap);
620 255376 : }
621 :
622 : void
623 26 : jit::JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def)
624 : {
625 26 : if (!JitSpewEnabled(channel))
626 26 : return;
627 :
628 0 : JitSpewHeader(channel);
629 0 : Fprinter& out = JitSpewPrinter();
630 0 : out.put(str);
631 0 : def->dump(out);
632 0 : def->dumpLocation(out);
633 : }
634 :
635 : void
636 1800 : jit::JitSpewStart(JitSpewChannel channel, const char* fmt, ...)
637 : {
638 : va_list ap;
639 1800 : va_start(ap, fmt);
640 1800 : JitSpewStartVA(channel, fmt, ap);
641 1800 : va_end(ap);
642 1800 : }
643 : void
644 535 : jit::JitSpewCont(JitSpewChannel channel, const char* fmt, ...)
645 : {
646 : va_list ap;
647 535 : va_start(ap, fmt);
648 535 : JitSpewContVA(channel, fmt, ap);
649 535 : va_end(ap);
650 535 : }
651 :
652 : void
653 0 : jit::JitSpewHeader(JitSpewChannel channel)
654 : {
655 0 : if (!JitSpewEnabled(channel))
656 0 : return;
657 :
658 0 : Fprinter& out = JitSpewPrinter();
659 0 : out.printf("[%s] ", ChannelNames[channel]);
660 0 : for (size_t i = ChannelIndentLevel[channel]; i != 0; i--)
661 0 : out.put(" ");
662 : }
663 :
664 : bool
665 1921579 : jit::JitSpewEnabled(JitSpewChannel channel)
666 : {
667 1921579 : MOZ_ASSERT(LoggingChecked);
668 1921579 : return (LoggingBits & (uint64_t(1) << uint32_t(channel))) && !filteredOutCompilations;
669 : }
670 :
671 : void
672 0 : jit::EnableChannel(JitSpewChannel channel)
673 : {
674 0 : MOZ_ASSERT(LoggingChecked);
675 0 : LoggingBits |= uint64_t(1) << uint32_t(channel);
676 0 : }
677 :
678 : void
679 0 : jit::DisableChannel(JitSpewChannel channel)
680 : {
681 0 : MOZ_ASSERT(LoggingChecked);
682 0 : LoggingBits &= ~(uint64_t(1) << uint32_t(channel));
683 0 : }
684 :
685 : #endif /* JS_JITSPEW */
686 :
|