/* -*- 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" #include "vm/Printer.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 alias analysis */ \ _(AliasSummaries) \ /* 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) \ /* Info about fold linear constants */ \ _(FLAC) \ /* Effective address analysis info */ \ _(EAA) \ /* 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) \ /* Output a list of MIR expressions */ \ _(MIRExpressions) \ \ /* 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 BacktrackingAllocator; class MDefinition; class MIRGenerator; class MIRGraph; 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 Wasm / 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, ...) MOZ_FORMAT_PRINTF(2, 3); void JitSpewStart(JitSpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3); void JitSpewCont(JitSpewChannel channel, const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3); 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 */