diff options
Diffstat (limited to 'js/src/jit/CacheIRSpewer.h')
-rw-r--r-- | js/src/jit/CacheIRSpewer.h | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/js/src/jit/CacheIRSpewer.h b/js/src/jit/CacheIRSpewer.h new file mode 100644 index 0000000000..fba33ba990 --- /dev/null +++ b/js/src/jit/CacheIRSpewer.h @@ -0,0 +1,116 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * 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_CacheIRSpewer_h +#define jit_CacheIRSpewer_h + +#ifdef JS_CACHEIR_SPEW + +# include "mozilla/Maybe.h" + +# include "jit/CacheIR.h" +# include "jit/CacheIRGenerator.h" +# include "jit/CacheIRReader.h" +# include "jit/CacheIRWriter.h" +# include "js/TypeDecls.h" +# include "threading/LockGuard.h" +# include "vm/JSONPrinter.h" +# include "vm/MutexIDs.h" + +namespace js { +namespace jit { + +class CacheIRSpewer { + Mutex outputLock_ MOZ_UNANNOTATED; + Fprinter output_; + mozilla::Maybe<JSONPrinter> json_; + static CacheIRSpewer cacheIRspewer; + + // Counter to record how many times Guard class is called. This is used to + // determine when to flush outputs based on the given interval value. + // For example, if |spewInterval_ = 2|, outputs will be flushed on + // guardCount_ values 0,2,4,6,... + uint32_t guardCount_; + + // Interval at which to flush output files. This value can be set with the + // environment variable |CACHEIR_LOG_FLUSH|. + uint32_t spewInterval_; + + CacheIRSpewer(); + ~CacheIRSpewer(); + + bool enabled() { return json_.isSome(); } + + // These methods can only be called when enabled() is true. + Mutex& lock() { + MOZ_ASSERT(enabled()); + return outputLock_; + } + + void beginCache(const IRGenerator& generator); + void valueProperty(const char* name, const Value& v); + void opcodeProperty(const char* name, const JSOp op); + void cacheIRSequence(CacheIRReader& reader); + void attached(const char* name); + void endCache(); + + public: + static CacheIRSpewer& singleton() { return cacheIRspewer; } + bool init(const char* name); + + class MOZ_RAII Guard { + CacheIRSpewer& sp_; + const IRGenerator& gen_; + const char* name_; + + public: + Guard(const IRGenerator& gen, const char* name) + : sp_(CacheIRSpewer::singleton()), gen_(gen), name_(name) { + if (sp_.enabled()) { + sp_.lock().lock(); + sp_.beginCache(gen_); + } + } + + ~Guard() { + if (sp_.enabled()) { + const CacheIRWriter& writer = gen_.writerRef(); + if (!writer.failed() && writer.codeLength() > 0) { + CacheIRReader reader(writer); + sp_.cacheIRSequence(reader); + } + if (name_ != nullptr) { + sp_.attached(name_); + } + sp_.endCache(); + if (sp_.guardCount_++ % sp_.spewInterval_ == 0) { + sp_.output_.flush(); + } + sp_.lock().unlock(); + } + } + + void valueProperty(const char* name, const Value& v) const { + sp_.valueProperty(name, v); + } + + void opcodeProperty(const char* name, const JSOp op) const { + sp_.opcodeProperty(name, op); + } + + explicit operator bool() const { return sp_.enabled(); } + }; +}; + +extern void SpewCacheIROps(GenericPrinter& out, const char* prefix, + const CacheIRStubInfo* info); + +} // namespace jit +} // namespace js + +#endif /* JS_CACHEIR_SPEW */ + +#endif /* jit_CacheIRSpewer_h */ |