| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #ifndef jit_JitSpewer_h |
| #define jit_JitSpewer_h |
| |
| #include "mozilla/DebugOnly.h" |
| #include "mozilla/IntegerPrintfMacros.h" |
| |
| #include <stdarg.h> |
| |
| #include "jit/C1Spewer.h" |
| #include "jit/JSONSpewer.h" |
| #include "js/RootingAPI.h" |
| |
| namespace js { |
| namespace jit { |
| |
| // New channels may be added below. |
| #define JITSPEW_CHANNEL_LIST(_) \ |
| /* Information during sinking */ \ |
| _(Prune) \ |
| /* Information during escape analysis */\ |
| _(Escape) \ |
| /* Information during alias analysis */ \ |
| _(Alias) \ |
| /* Information during GVN */ \ |
| _(GVN) \ |
| /* Information during sincos */ \ |
| _(Sincos) \ |
| /* Information during sinking */ \ |
| _(Sink) \ |
| /* Information during Range analysis */ \ |
| _(Range) \ |
| /* Information during loop unrolling */ \ |
| _(Unrolling) \ |
| /* Information during LICM */ \ |
| _(LICM) \ |
| /* Information during regalloc */ \ |
| _(RegAlloc) \ |
| /* Information during inlining */ \ |
| _(Inlining) \ |
| /* Information during codegen */ \ |
| _(Codegen) \ |
| /* Debug info about safepoints */ \ |
| _(Safepoints) \ |
| /* Debug info about Pools*/ \ |
| _(Pools) \ |
| /* Profiling-related information */ \ |
| _(Profiling) \ |
| /* Information of tracked opt strats */ \ |
| _(OptimizationTracking) \ |
| /* Debug info about the I$ */ \ |
| _(CacheFlush) \ |
| \ |
| /* BASELINE COMPILER SPEW */ \ |
| \ |
| /* Aborting Script Compilation. */ \ |
| _(BaselineAbort) \ |
| /* Script Compilation. */ \ |
| _(BaselineScripts) \ |
| /* Detailed op-specific spew. */ \ |
| _(BaselineOp) \ |
| /* Inline caches. */ \ |
| _(BaselineIC) \ |
| /* Inline cache fallbacks. */ \ |
| _(BaselineICFallback) \ |
| /* OSR from Baseline => Ion. */ \ |
| _(BaselineOSR) \ |
| /* Bailouts. */ \ |
| _(BaselineBailouts) \ |
| /* Debug Mode On Stack Recompile . */ \ |
| _(BaselineDebugModeOSR) \ |
| \ |
| /* ION COMPILER SPEW */ \ |
| \ |
| /* Used to abort SSA construction */ \ |
| _(IonAbort) \ |
| /* Information about compiled scripts */\ |
| _(IonScripts) \ |
| /* Info about failing to log script */ \ |
| _(IonSyncLogs) \ |
| /* Information during MIR building */ \ |
| _(IonMIR) \ |
| /* Information during bailouts */ \ |
| _(IonBailouts) \ |
| /* Information during OSI */ \ |
| _(IonInvalidate) \ |
| /* Debug info about snapshots */ \ |
| _(IonSnapshots) \ |
| /* Generated inline cache stubs */ \ |
| _(IonIC) |
| |
| enum JitSpewChannel { |
| #define JITSPEW_CHANNEL(name) JitSpew_##name, |
| JITSPEW_CHANNEL_LIST(JITSPEW_CHANNEL) |
| #undef JITSPEW_CHANNEL |
| JitSpew_Terminator |
| }; |
| |
| class MIRGenerator; |
| class TempAllocator; |
| |
| // The JitSpewer is only available on debug builds. |
| // None of the global functions have effect on non-debug builds. |
| static const int NULL_ID = -1; |
| |
| #ifdef JS_JITSPEW |
| |
| // Class made to hold the MIR and LIR graphs of an AsmJS / Ion compilation. |
| class GraphSpewer |
| { |
| private: |
| MIRGraph* graph_; |
| LSprinter c1Printer_; |
| LSprinter jsonPrinter_; |
| C1Spewer c1Spewer_; |
| JSONSpewer jsonSpewer_; |
| |
| public: |
| explicit GraphSpewer(TempAllocator *alloc); |
| |
| bool isSpewing() const { |
| return graph_; |
| } |
| void init(MIRGraph* graph, JSScript* function); |
| void beginFunction(JSScript* function); |
| void spewPass(const char* pass); |
| void spewPass(const char* pass, BacktrackingAllocator* ra); |
| void endFunction(); |
| |
| void dump(Fprinter& c1, Fprinter& json); |
| }; |
| |
| void SpewBeginFunction(MIRGenerator* mir, JSScript* function); |
| class AutoSpewEndFunction |
| { |
| private: |
| MIRGenerator* mir_; |
| |
| public: |
| explicit AutoSpewEndFunction(MIRGenerator* mir) |
| : mir_(mir) |
| { } |
| ~AutoSpewEndFunction(); |
| }; |
| |
| void CheckLogging(); |
| Fprinter& JitSpewPrinter(); |
| |
| class JitSpewIndent |
| { |
| JitSpewChannel channel_; |
| |
| public: |
| explicit JitSpewIndent(JitSpewChannel channel); |
| ~JitSpewIndent(); |
| }; |
| |
| void JitSpew(JitSpewChannel channel, const char* fmt, ...); |
| void JitSpewStart(JitSpewChannel channel, const char* fmt, ...); |
| void JitSpewCont(JitSpewChannel channel, const char* fmt, ...); |
| void JitSpewFin(JitSpewChannel channel); |
| void JitSpewHeader(JitSpewChannel channel); |
| bool JitSpewEnabled(JitSpewChannel channel); |
| void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap); |
| void JitSpewStartVA(JitSpewChannel channel, const char* fmt, va_list ap); |
| void JitSpewContVA(JitSpewChannel channel, const char* fmt, va_list ap); |
| void JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def); |
| |
| void EnableChannel(JitSpewChannel channel); |
| void DisableChannel(JitSpewChannel channel); |
| void EnableIonDebugSyncLogging(); |
| void EnableIonDebugAsyncLogging(); |
| |
| #else |
| |
| class GraphSpewer |
| { |
| public: |
| explicit GraphSpewer(TempAllocator *alloc) { } |
| |
| bool isSpewing() { return false; } |
| void init(MIRGraph* graph, JSScript* function) { } |
| void beginFunction(JSScript* function) { } |
| void spewPass(const char* pass) { } |
| void spewPass(const char* pass, BacktrackingAllocator* ra) { } |
| void endFunction() { } |
| |
| void dump(Fprinter& c1, Fprinter& json) { } |
| }; |
| |
| static inline void SpewBeginFunction(MIRGenerator* mir, JSScript* function) |
| { } |
| |
| class AutoSpewEndFunction |
| { |
| public: |
| explicit AutoSpewEndFunction(MIRGenerator* mir) { } |
| ~AutoSpewEndFunction() { } |
| }; |
| |
| static inline void CheckLogging() |
| { } |
| static inline Fprinter& JitSpewPrinter() |
| { |
| MOZ_CRASH("No empty backend for JitSpewPrinter"); |
| } |
| |
| class JitSpewIndent |
| { |
| public: |
| explicit JitSpewIndent(JitSpewChannel channel) {} |
| ~JitSpewIndent() {} |
| }; |
| |
| // The computation of some of the argument of the spewing functions might be |
| // costly, thus we use variaidic macros to ignore any argument of these |
| // functions. |
| static inline void JitSpewCheckArguments(JitSpewChannel channel, const char* fmt) |
| { } |
| |
| #define JitSpewCheckExpandedArgs(channel, fmt, ...) JitSpewCheckArguments(channel, fmt) |
| #define JitSpewCheckExpandedArgs_(ArgList) JitSpewCheckExpandedArgs ArgList /* Fix MSVC issue */ |
| #define JitSpew(...) JitSpewCheckExpandedArgs_((__VA_ARGS__)) |
| #define JitSpewStart(...) JitSpewCheckExpandedArgs_((__VA_ARGS__)) |
| #define JitSpewCont(...) JitSpewCheckExpandedArgs_((__VA_ARGS__)) |
| |
| static inline void JitSpewFin(JitSpewChannel channel) |
| { } |
| |
| static inline void JitSpewHeader(JitSpewChannel channel) |
| { } |
| static inline bool JitSpewEnabled(JitSpewChannel channel) |
| { return false; } |
| static inline void JitSpewVA(JitSpewChannel channel, const char* fmt, va_list ap) |
| { } |
| static inline void JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def) |
| { } |
| |
| static inline void EnableChannel(JitSpewChannel) |
| { } |
| static inline void DisableChannel(JitSpewChannel) |
| { } |
| static inline void EnableIonDebugSyncLogging() |
| { } |
| static inline void EnableIonDebugAsyncLogging() |
| { } |
| |
| #endif /* JS_JITSPEW */ |
| |
| template <JitSpewChannel Channel> |
| class AutoDisableSpew |
| { |
| mozilla::DebugOnly<bool> enabled_; |
| |
| public: |
| AutoDisableSpew() |
| : enabled_(JitSpewEnabled(Channel)) |
| { |
| DisableChannel(Channel); |
| } |
| |
| ~AutoDisableSpew() |
| { |
| #ifdef JS_JITSPEW |
| if (enabled_) |
| EnableChannel(Channel); |
| #endif |
| } |
| }; |
| |
| } // namespace jit |
| } // namespace js |
| |
| #endif /* jit_JitSpewer_h */ |