#ifndef jit_StructuredSpewer_h
#define jit_StructuredSpewer_h
#ifdef JS_STRUCTURED_SPEW
# include "mozilla/Atomics.h"
# include "mozilla/Attributes.h"
# include "mozilla/EnumeratedArray.h"
# include "mozilla/EnumSet.h"
# include "mozilla/Maybe.h"
# include "mozilla/Sprintf.h"
# include "vm/JSONPrinter.h"
# include "vm/Printer.h"
# ifdef XP_WIN
# include <process.h>
# define getpid _getpid
# else
# include <unistd.h>
# endif
class JSScript;
namespace js {
# define STRUCTURED_CHANNEL_LIST(_) _(BaselineICStats)
enum class SpewChannel {
# define STRUCTURED_CHANNEL(name) name,
STRUCTURED_CHANNEL_LIST(STRUCTURED_CHANNEL)
# undef STRUCTURED_CHANNEL
Count
};
class StructuredSpewFilter {
mozilla::EnumSet<SpewChannel> bits_;
public:
StructuredSpewFilter() : bits_() {}
bool enabled(SpewChannel x) const { return bits_.contains(x); }
void enableChannel(SpewChannel x) { bits_ += x; }
void disableAll() { bits_.clear(); }
};
class StructuredSpewer {
public:
StructuredSpewer()
: outputInitializationAttempted_(false),
json_(mozilla::Nothing()),
selectedChannels_() {
if (mozilla::recordreplay::IsRecordingOrReplaying()) {
return;
}
if (getenv("SPEW")) {
parseSpewFlags(getenv("SPEW"));
}
}
~StructuredSpewer() {
if (json_.isSome()) {
json_->endList();
output_.flush();
output_.finish();
}
}
static bool enabled(JSScript* script);
static void spew(JSContext* cx, SpewChannel channel, const char* fmt, ...)
MOZ_FORMAT_PRINTF(3, 4);
private:
bool outputInitializationAttempted_;
Fprinter output_;
mozilla::Maybe<JSONPrinter> json_;
StructuredSpewFilter selectedChannels_;
using NameArray =
mozilla::EnumeratedArray<SpewChannel, SpewChannel::Count, const char*>;
static NameArray const names_;
StructuredSpewFilter& filter() { return selectedChannels_; }
static const char* getName(SpewChannel channel) { return names_[channel]; }
bool ensureInitializationAttempted();
void tryToInitializeOutput(const char* path);
void parseSpewFlags(const char* flags);
bool enabled(JSContext* cx, const JSScript* script,
SpewChannel channel) const;
void startObject(JSContext* cx, const JSScript* script, SpewChannel channel);
friend class AutoStructuredSpewer;
};
class MOZ_RAII AutoStructuredSpewer {
mozilla::Maybe<JSONPrinter*> printer_;
AutoStructuredSpewer(const AutoStructuredSpewer&) = delete;
void operator=(AutoStructuredSpewer&) = delete;
public:
explicit AutoStructuredSpewer(JSContext* cx, SpewChannel channel,
JSScript* script);
~AutoStructuredSpewer() {
if (printer_.isSome()) {
printer_.ref()->endObject();
}
}
explicit operator bool() const { return printer_.isSome(); }
JSONPrinter* operator->() {
MOZ_ASSERT(printer_.isSome());
return printer_.ref();
}
JSONPrinter& operator*() {
MOZ_ASSERT(printer_.isSome());
return *printer_.ref();
}
};
}
#endif
#endif