CacheIRSpewer.h (3656B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 #ifndef jit_CacheIRSpewer_h 8 #define jit_CacheIRSpewer_h 9 10 #include "mozilla/Maybe.h" 11 12 #include "jit/CacheIR.h" 13 #include "jit/CacheIRGenerator.h" 14 #include "jit/CacheIRReader.h" 15 #include "jit/CacheIRWriter.h" 16 #include "js/TypeDecls.h" 17 #include "threading/LockGuard.h" 18 #include "vm/JSONPrinter.h" 19 #include "vm/MutexIDs.h" 20 21 namespace js { 22 namespace jit { 23 24 #ifdef JS_CACHEIR_SPEW 25 26 class CacheIRSpewer { 27 Mutex outputLock_ MOZ_UNANNOTATED; 28 Fprinter output_; 29 mozilla::Maybe<JSONPrinter> json_; 30 static CacheIRSpewer cacheIRspewer; 31 32 // Counter to record how many times Guard class is called. This is used to 33 // determine when to flush outputs based on the given interval value. 34 // For example, if |spewInterval_ = 2|, outputs will be flushed on 35 // guardCount_ values 0,2,4,6,... 36 uint32_t guardCount_; 37 38 // Interval at which to flush output files. This value can be set with the 39 // environment variable |CACHEIR_LOG_FLUSH|. 40 uint32_t spewInterval_; 41 42 CacheIRSpewer(); 43 ~CacheIRSpewer(); 44 45 bool enabled() { return json_.isSome(); } 46 47 // These methods can only be called when enabled() is true. 48 Mutex& lock() { 49 MOZ_ASSERT(enabled()); 50 return outputLock_; 51 } 52 53 void beginCache(const IRGenerator& generator); 54 void valueProperty(const char* name, const Value& v); 55 void opcodeProperty(const char* name, const JSOp op); 56 void jstypeProperty(const char* name, const JSType type); 57 void cacheIRSequence(CacheIRReader& reader); 58 void attached(const char* name); 59 void endCache(); 60 61 public: 62 static CacheIRSpewer& singleton() { return cacheIRspewer; } 63 bool init(const char* name); 64 65 class MOZ_RAII Guard { 66 CacheIRSpewer& sp_; 67 const IRGenerator& gen_; 68 const char* name_; 69 70 public: 71 Guard(const IRGenerator& gen, const char* name) 72 : sp_(CacheIRSpewer::singleton()), gen_(gen), name_(name) { 73 if (sp_.enabled()) { 74 sp_.lock().lock(); 75 sp_.beginCache(gen_); 76 } 77 } 78 79 ~Guard() { 80 if (sp_.enabled()) { 81 const CacheIRWriter& writer = gen_.writerRef(); 82 if (!writer.failed() && writer.codeLength() > 0) { 83 CacheIRReader reader(writer); 84 sp_.cacheIRSequence(reader); 85 } 86 if (name_ != nullptr) { 87 sp_.attached(name_); 88 } 89 sp_.endCache(); 90 if (sp_.guardCount_++ % sp_.spewInterval_ == 0) { 91 sp_.output_.flush(); 92 } 93 sp_.lock().unlock(); 94 } 95 } 96 97 void valueProperty(const char* name, const Value& v) const { 98 sp_.valueProperty(name, v); 99 } 100 101 void opcodeProperty(const char* name, const JSOp op) const { 102 sp_.opcodeProperty(name, op); 103 } 104 105 void jstypeProperty(const char* name, const JSType type) const { 106 sp_.jstypeProperty(name, type); 107 } 108 109 explicit operator bool() const { return sp_.enabled(); } 110 }; 111 }; 112 113 extern void SpewCacheIROps(GenericPrinter& out, const char* prefix, 114 CacheIRReader& reader); 115 extern void SpewCacheIROps(GenericPrinter& out, const char* prefix, 116 const CacheIRStubInfo* info); 117 118 #endif /* JS_CACHEIR_SPEW */ 119 120 #ifdef ENABLE_JS_AOT_ICS 121 extern void SpewCacheIROpsAsAOT(GenericPrinter& out, CacheKind kind, 122 const CacheIRWriter& writer); 123 #endif 124 125 } // namespace jit 126 } // namespace js 127 128 #endif /* jit_CacheIRSpewer_h */