mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 20:35:50 +00:00
Bug 1045063 - TraceLogging: Don't keep track of stack while disabled, r=bbouvier
This commit is contained in:
parent
3c8c24351c
commit
d86704b06c
@ -1616,7 +1616,7 @@ EnableTraceLogger(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
||||
args.rval().setBoolean(TraceLoggerEnable(logger));
|
||||
args.rval().setBoolean(TraceLoggerEnable(logger, cx));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1005,17 +1005,23 @@ CodeGeneratorShared::computeDivisionConstants(int d) {
|
||||
bool
|
||||
CodeGeneratorShared::emitTracelogScript(bool isStart)
|
||||
{
|
||||
Label done;
|
||||
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
Register logger = regs.takeGeneral();
|
||||
Register script = regs.takeGeneral();
|
||||
|
||||
masm.Push(logger);
|
||||
masm.Push(script);
|
||||
|
||||
CodeOffsetLabel patchLogger = masm.movWithPatch(ImmPtr(nullptr), logger);
|
||||
if (!patchableTraceLoggers_.append(patchLogger))
|
||||
return false;
|
||||
|
||||
Address enabledAddress(logger, TraceLogger::offsetOfEnabled());
|
||||
masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
|
||||
|
||||
masm.Push(script);
|
||||
|
||||
CodeOffsetLabel patchScript = masm.movWithPatch(ImmWord(0), script);
|
||||
if (!patchableTLScripts_.append(patchScript))
|
||||
return false;
|
||||
@ -1026,6 +1032,9 @@ CodeGeneratorShared::emitTracelogScript(bool isStart)
|
||||
masm.tracelogStop(logger, script);
|
||||
|
||||
masm.Pop(script);
|
||||
|
||||
masm.bind(&done);
|
||||
|
||||
masm.Pop(logger);
|
||||
return true;
|
||||
}
|
||||
@ -1036,6 +1045,7 @@ CodeGeneratorShared::emitTracelogTree(bool isStart, uint32_t textId)
|
||||
if (!TraceLogTextIdEnabled(textId))
|
||||
return true;
|
||||
|
||||
Label done;
|
||||
RegisterSet regs = RegisterSet::Volatile();
|
||||
Register logger = regs.takeGeneral();
|
||||
|
||||
@ -1045,6 +1055,9 @@ CodeGeneratorShared::emitTracelogTree(bool isStart, uint32_t textId)
|
||||
if (!patchableTraceLoggers_.append(patchLocation))
|
||||
return false;
|
||||
|
||||
Address enabledAddress(logger, TraceLogger::offsetOfEnabled());
|
||||
masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
|
||||
|
||||
if (isStart) {
|
||||
masm.tracelogStart(logger, textId);
|
||||
} else {
|
||||
@ -1055,6 +1068,8 @@ CodeGeneratorShared::emitTracelogTree(bool isStart, uint32_t textId)
|
||||
#endif
|
||||
}
|
||||
|
||||
masm.bind(&done);
|
||||
|
||||
masm.Pop(logger);
|
||||
return true;
|
||||
}
|
||||
|
@ -17,7 +17,10 @@
|
||||
#include "jit/CompileWrappers.h"
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
#include "jit/IonFrames-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
using mozilla::NativeEndian;
|
||||
|
||||
#ifndef TRACE_LOG_DIR
|
||||
@ -85,8 +88,7 @@ static const char* const text[] =
|
||||
};
|
||||
|
||||
TraceLogger::TraceLogger()
|
||||
: enabled(false),
|
||||
enabledTimes(0),
|
||||
: enabled(0),
|
||||
failed(false),
|
||||
nextTextId(0),
|
||||
treeOffset(0),
|
||||
@ -157,82 +159,89 @@ TraceLogger::init(uint32_t loggerId)
|
||||
MOZ_ASSERT(textId == i);
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
enabledTimes = 1;
|
||||
enabled = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceLogger::enable()
|
||||
{
|
||||
if (enabled) {
|
||||
enabledTimes++;
|
||||
if (enabled > 0) {
|
||||
enabled++;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
return false;
|
||||
|
||||
if (!tree.ensureSpaceBeforeAdd(stack.size())) {
|
||||
if (!flush()) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
|
||||
enabled = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TraceLogger::enable(JSContext *cx)
|
||||
{
|
||||
if (!enable())
|
||||
return false;
|
||||
|
||||
if (enabled == 1) {
|
||||
// Get the top Activation to log the top script/pc (No inlined frames).
|
||||
Activation *act = cx->mainThread().activation();
|
||||
while (act && (act->cx() != cx || (act->isJit() && !act->asJit()->isActive())))
|
||||
act = act->prev();
|
||||
|
||||
if (!act) {
|
||||
failed = true;
|
||||
enabled = 0;
|
||||
return false;
|
||||
}
|
||||
if (!tree.ensureSpaceBeforeAdd(stack.size())) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't reserve enough space.\n");
|
||||
failed = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t start = rdtsc() - traceLoggers.startupTime;
|
||||
StackEntry *parent = &stack[0];
|
||||
for (uint32_t i = 1; i < stack.size(); i++) {
|
||||
if (!traceLoggers.isTextIdEnabled(stack[i].textId()))
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
TreeEntry entry;
|
||||
if (!getTreeEntry(parent->treeId(), &entry))
|
||||
return false;
|
||||
#endif
|
||||
JSScript *script = nullptr;
|
||||
int32_t engine = 0;
|
||||
|
||||
if (parent->lastChildId() == 0) {
|
||||
MOZ_ASSERT(!entry.hasChildren());
|
||||
MOZ_ASSERT(parent->treeId() == tree.currentId() + treeOffset);
|
||||
if (!updateHasChildren(parent->treeId())) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't update an entry.\n");
|
||||
failed = true;
|
||||
return false;
|
||||
if (act->isJit()) {
|
||||
JSRuntime *rt = cx->runtime();
|
||||
|
||||
JitFrameIterator it(rt->mainThread.jitTop, SequentialExecution);
|
||||
|
||||
JS_ASSERT(it.type() == JitFrame_Exit);
|
||||
++it;
|
||||
|
||||
if (it.type() == JitFrame_Rectifier ||
|
||||
it.type() == JitFrame_Unwound_Rectifier)
|
||||
{
|
||||
++it;
|
||||
JS_ASSERT(it.type() == JitFrame_BaselineStub ||
|
||||
it.type() == JitFrame_BaselineJS ||
|
||||
it.type() == JitFrame_IonJS);
|
||||
}
|
||||
if (it.type() == JitFrame_BaselineStub ||
|
||||
it.type() == JitFrame_Unwound_BaselineStub)
|
||||
{
|
||||
++it;
|
||||
JS_ASSERT(it.type() == JitFrame_BaselineJS);
|
||||
}
|
||||
|
||||
script = it.script();
|
||||
engine = it.isIonJS() ? IonMonkey : Baseline;
|
||||
} else {
|
||||
MOZ_ASSERT(entry.hasChildren() == 1);
|
||||
if (!updateNextId(parent->lastChildId(), tree.nextId() + treeOffset)) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't update an entry.\n");
|
||||
JS_ASSERT(act->isInterpreter());
|
||||
InterpreterFrame *fp = act->asInterpreter()->current();
|
||||
JS_ASSERT(!fp->runningInJit());
|
||||
|
||||
script = fp->script();
|
||||
engine = Interpreter;
|
||||
if (script->compartment() != cx->compartment()) {
|
||||
failed = true;
|
||||
enabled = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
TreeEntry &treeEntry = tree.pushUninitialized();
|
||||
treeEntry.setStart(start);
|
||||
treeEntry.setStop(0);
|
||||
treeEntry.setTextId(stack[i].textId());
|
||||
treeEntry.setHasChildren(false);
|
||||
treeEntry.setNextId(0);
|
||||
|
||||
stack[i].setActive(true);
|
||||
stack[i].setTreeId(tree.currentId() + treeOffset);
|
||||
stack[i].setLastChildId(0);
|
||||
|
||||
parent->setLastChildId(tree.currentId() + treeOffset);
|
||||
|
||||
parent = &stack[i];
|
||||
startEvent(createTextId(script));
|
||||
startEvent(engine);
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
enabledTimes = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -242,32 +251,19 @@ TraceLogger::disable()
|
||||
if (failed)
|
||||
return false;
|
||||
|
||||
if (!enabled)
|
||||
if (enabled == 0)
|
||||
return true;
|
||||
|
||||
if (enabledTimes > 1) {
|
||||
enabledTimes--;
|
||||
if (enabled > 1) {
|
||||
enabled--;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t stop = rdtsc() - traceLoggers.startupTime;
|
||||
for (uint32_t i = 1; i < stack.size(); i++) {
|
||||
if (!stack[i].active())
|
||||
continue;
|
||||
JS_ASSERT(enabled == 1);
|
||||
while (stack.currentId() > 0)
|
||||
stopEvent();
|
||||
|
||||
if (!updateStop(stack[i].treeId(), stop)) {
|
||||
fprintf(stderr, "TraceLogging: Failed to stop an event.\n");
|
||||
failed = true;
|
||||
enabled = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
stack[i].setActive(false);
|
||||
}
|
||||
|
||||
|
||||
enabled = false;
|
||||
enabledTimes = 0;
|
||||
enabled = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -326,15 +322,15 @@ TraceLogger::~TraceLogger()
|
||||
// Make sure every start entry has a corresponding stop value.
|
||||
// We temporary enable logging for this. Stop doesn't need any extra data,
|
||||
// so is safe to do, even when we encountered OOM.
|
||||
enabled = true;
|
||||
enabled = 1;
|
||||
while (stack.currentId() > 0)
|
||||
stopEvent();
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
}
|
||||
|
||||
if (!failed && !flush()) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
failed = true;
|
||||
}
|
||||
|
||||
@ -439,12 +435,12 @@ TraceLogger::createTextId(const JS::ReadOnlyCompileOptions &compileOptions)
|
||||
void
|
||||
TraceLogger::logTimestamp(uint32_t id)
|
||||
{
|
||||
if (!enabled)
|
||||
if (enabled == 0)
|
||||
return;
|
||||
|
||||
if (!events.ensureSpaceBeforeAdd()) {
|
||||
fprintf(stderr, "TraceLogging: Disabled a tracelogger due to OOM.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -569,31 +565,15 @@ TraceLogger::updateStop(uint32_t treeId, uint64_t timestamp)
|
||||
void
|
||||
TraceLogger::startEvent(uint32_t id)
|
||||
{
|
||||
if (failed)
|
||||
if (failed || enabled == 0)
|
||||
return;
|
||||
|
||||
if (!stack.ensureSpaceBeforeAdd()) {
|
||||
fprintf(stderr, "TraceLogging: Failed to allocate space to keep track of the stack.\n");
|
||||
enabled = false;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enabled) {
|
||||
StackEntry &stackEntry = stack.pushUninitialized();
|
||||
stackEntry.setTreeId(tree.currentId() + treeOffset);
|
||||
stackEntry.setLastChildId(0);
|
||||
stackEntry.setTextId(id);
|
||||
stackEntry.setActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tree.hasSpaceForAdd()){
|
||||
uint64_t start = rdtsc() - traceLoggers.startupTime;
|
||||
if (!tree.ensureSpaceBeforeAdd()) {
|
||||
if (!flush()) {
|
||||
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
@ -603,7 +583,7 @@ TraceLogger::startEvent(uint32_t id)
|
||||
// Tracelogger.
|
||||
if (!startEvent(TraceLogger::TL, start)) {
|
||||
fprintf(stderr, "TraceLogging: Failed to start an event.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
@ -613,7 +593,7 @@ TraceLogger::startEvent(uint32_t id)
|
||||
uint64_t start = rdtsc() - traceLoggers.startupTime;
|
||||
if (!startEvent(id, start)) {
|
||||
fprintf(stderr, "TraceLogging: Failed to start an event.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
@ -631,6 +611,9 @@ TraceLogger::getActiveAncestor()
|
||||
bool
|
||||
TraceLogger::startEvent(uint32_t id, uint64_t timestamp)
|
||||
{
|
||||
if (!stack.ensureSpaceBeforeAdd())
|
||||
return false;
|
||||
|
||||
// When a textId is disabled, a stack entry still needs to be pushed,
|
||||
// together with an annotation that nothing needs to get done when receiving
|
||||
// the stop event.
|
||||
@ -688,9 +671,11 @@ void
|
||||
TraceLogger::stopEvent(uint32_t id)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
TreeEntry entry;
|
||||
MOZ_ASSERT_IF(stack.current().active(), getTreeEntry(stack.current().treeId(), &entry));
|
||||
MOZ_ASSERT_IF(stack.current().active(), entry.textId() == id);
|
||||
if (stack.currentId() > 0) {
|
||||
TreeEntry entry;
|
||||
MOZ_ASSERT_IF(stack.current().active(), getTreeEntry(stack.current().treeId(), &entry));
|
||||
MOZ_ASSERT_IF(stack.current().active(), entry.textId() == id);
|
||||
}
|
||||
#endif
|
||||
stopEvent();
|
||||
}
|
||||
@ -698,23 +683,31 @@ TraceLogger::stopEvent(uint32_t id)
|
||||
void
|
||||
TraceLogger::stopEvent()
|
||||
{
|
||||
if (enabled && stack.current().active()) {
|
||||
if (enabled > 0 && stack.current().active()) {
|
||||
uint64_t stop = rdtsc() - traceLoggers.startupTime;
|
||||
if (!updateStop(stack.current().treeId(), stop)) {
|
||||
fprintf(stderr, "TraceLogging: Failed to stop an event.\n");
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
JS_ASSERT(stack.currentId() > 0);
|
||||
if (stack.currentId() == 0) {
|
||||
if (enabled == 0)
|
||||
return;
|
||||
|
||||
// Forcefully disable logging. We have no stack information anymore.
|
||||
enabled = 1;
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
TraceLogging::TraceLogging()
|
||||
{
|
||||
initialized = false;
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
mainThreadEnabled = true;
|
||||
offThreadEnabled = true;
|
||||
loggerId = 0;
|
||||
@ -749,7 +742,7 @@ TraceLogging::~TraceLogging()
|
||||
lock = nullptr;
|
||||
}
|
||||
|
||||
enabled = false;
|
||||
enabled = 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -769,7 +762,7 @@ bool
|
||||
TraceLogging::lazyInit()
|
||||
{
|
||||
if (initialized)
|
||||
return enabled;
|
||||
return enabled > 0;
|
||||
|
||||
initialized = true;
|
||||
|
||||
@ -877,18 +870,18 @@ TraceLogging::lazyInit()
|
||||
}
|
||||
|
||||
startupTime = rdtsc();
|
||||
enabled = true;
|
||||
enabled = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
TraceLogger *
|
||||
js::TraceLoggerForMainThread(jit::CompileRuntime *runtime)
|
||||
js::TraceLoggerForMainThread(CompileRuntime *runtime)
|
||||
{
|
||||
return traceLoggers.forMainThread(runtime);
|
||||
}
|
||||
|
||||
TraceLogger *
|
||||
TraceLogging::forMainThread(jit::CompileRuntime *runtime)
|
||||
TraceLogging::forMainThread(CompileRuntime *runtime)
|
||||
{
|
||||
return forMainThread(runtime->mainThread());
|
||||
}
|
||||
|
@ -387,8 +387,7 @@ class TraceLogger
|
||||
FILE *treeFile;
|
||||
FILE *eventFile;
|
||||
|
||||
bool enabled;
|
||||
uint32_t enabledTimes;
|
||||
uint32_t enabled;
|
||||
bool failed;
|
||||
uint32_t nextTextId;
|
||||
|
||||
@ -436,6 +435,7 @@ class TraceLogger
|
||||
bool init(uint32_t loggerId);
|
||||
|
||||
bool enable();
|
||||
bool enable(JSContext *cx);
|
||||
bool disable();
|
||||
|
||||
// The createTextId functions map a unique input to a logger ID.
|
||||
@ -455,6 +455,10 @@ class TraceLogger
|
||||
void stopEvent(uint32_t id);
|
||||
void stopEvent();
|
||||
|
||||
static unsigned offsetOfEnabled() {
|
||||
return offsetof(TraceLogger, enabled);
|
||||
}
|
||||
|
||||
private:
|
||||
void assertNoQuotes(const char *text) {
|
||||
#ifdef DEBUG
|
||||
@ -531,6 +535,13 @@ inline bool TraceLoggerEnable(TraceLogger *logger) {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
inline bool TraceLoggerEnable(TraceLogger *logger, JSContext *cx) {
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
if (logger)
|
||||
return logger->enable(cx);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
inline bool TraceLoggerDisable(TraceLogger *logger) {
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
if (logger)
|
||||
|
Loading…
Reference in New Issue
Block a user