#ifndef jit_CacheIRSpewer_h
#define jit_CacheIRSpewer_h
#ifdef JS_CACHEIR_SPEW
# include "mozilla/Maybe.h"
# include "jit/CacheIR.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_;
Fprinter output_;
mozilla::Maybe<JSONPrinter> json_;
static CacheIRSpewer cacheIRspewer;
uint32_t guardCount_;
uint32_t spewInterval_;
CacheIRSpewer();
~CacheIRSpewer();
bool enabled() { return json_.isSome(); }
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 CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
CacheIROpFormat::ArgType arg);
template <typename... Args>
void CacheIRArgs(JSONPrinter& j, CacheIRReader& r,
CacheIROpFormat::ArgType arg, Args... args);
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()) {
if (gen_.writerRef().codeLength() > 0) {
CacheIRReader reader(gen_.writerRef());
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(); }
};
};
} }
#endif
#endif