Bug 1072906 - TraceLogger: Part 1: Make it possible to toggle text ids dynamically in Baseline and IonMonkey, r=jandem

This commit is contained in:
Hannes Verschore 2014-11-20 17:44:02 +01:00
parent 41f6795e6f
commit 7d56eb8578
12 changed files with 311 additions and 35 deletions

View File

@ -177,6 +177,11 @@ BaselineCompiler::compile()
prologueOffset_.fixup(&masm);
epilogueOffset_.fixup(&masm);
spsPushToggleOffset_.fixup(&masm);
#ifdef JS_TRACE_LOGGING
traceLoggerEnterToggleOffset_.fixup(&masm);
traceLoggerExitToggleOffset_.fixup(&masm);
traceLoggerScriptTextIdOffset_.fixup(&masm);
#endif
postDebugPrologueOffset_.fixup(&masm);
// Note: There is an extra entry in the bytecode type map for the search hint, see below.
@ -186,6 +191,9 @@ BaselineCompiler::compile()
BaselineScript::New(script, prologueOffset_.offset(),
epilogueOffset_.offset(),
spsPushToggleOffset_.offset(),
traceLoggerEnterToggleOffset_.offset(),
traceLoggerExitToggleOffset_.offset(),
traceLoggerScriptTextIdOffset_.offset(),
postDebugPrologueOffset_.offset(),
icEntries_.length(),
pcMappingIndexEntries.length(),
@ -241,6 +249,11 @@ BaselineCompiler::compile()
if (cx->runtime()->spsProfiler.enabled())
baselineScript->toggleSPS(true);
if (TraceLogTextIdEnabled(TraceLogger_Scripts))
baselineScript->toggleTraceLoggerScripts(cx->runtime(), script, true);
if (TraceLogTextIdEnabled(TraceLogger_Engine))
baselineScript->toggleTraceLoggerEngine(true);
uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
types::FillBytecodeTypeMap(script, bytecodeMap);
@ -372,15 +385,8 @@ BaselineCompiler::emitPrologue()
if (needsEarlyStackCheck())
masm.bind(&earlyStackCheckFailed);
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
Register loggerReg = RegisterSet::Volatile().takeGeneral();
masm.Push(loggerReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.tracelogStart(loggerReg, TraceLogCreateTextId(logger, script));
masm.tracelogStart(loggerReg, TraceLogger_Baseline);
masm.Pop(loggerReg);
#endif
if (!emitTraceLoggerEnter())
return false;
// Record the offset of the prologue, because Ion can bailout before
// the scope chain is initialized.
@ -419,13 +425,8 @@ BaselineCompiler::emitEpilogue()
masm.bind(&return_);
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
Register loggerReg = RegisterSet::Volatile().takeGeneral();
masm.Push(loggerReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.tracelogStop(loggerReg, TraceLogger_Baseline);
masm.tracelogStop(loggerReg, TraceLogger_Scripts);
masm.Pop(loggerReg);
if (!emitTraceLoggerExit())
return false;
#endif
// Pop SPS frame if necessary
@ -765,6 +766,60 @@ BaselineCompiler::emitDebugTrap()
return true;
}
bool
BaselineCompiler::emitTraceLoggerEnter()
{
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
RegisterSet regs = RegisterSet::Volatile();
Register loggerReg = regs.takeGeneral();
Register scriptReg = regs.takeGeneral();
Label noTraceLogger;
traceLoggerEnterToggleOffset_ = masm.toggledJump(&noTraceLogger);
masm.Push(loggerReg);
masm.Push(scriptReg);
masm.movePtr(ImmPtr(logger), loggerReg);
// Script start.
traceLoggerScriptTextIdOffset_ =
masm.movWithPatch(ImmWord(uintptr_t(TraceLogger_Scripts)), scriptReg);
masm.tracelogStart(loggerReg, scriptReg);
// Engine start.
masm.tracelogStart(loggerReg, TraceLogger_Baseline, /* force = */ true);
masm.Pop(scriptReg);
masm.Pop(loggerReg);
masm.bind(&noTraceLogger);
return true;
}
bool
BaselineCompiler::emitTraceLoggerExit()
{
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
Register loggerReg = RegisterSet::Volatile().takeGeneral();
Label noTraceLogger;
traceLoggerExitToggleOffset_ = masm.toggledJump(&noTraceLogger);
masm.Push(loggerReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.tracelogStop(loggerReg, TraceLogger_Baseline, /* force = */ true);
masm.tracelogStop(loggerReg, TraceLogger_Scripts, /* force = */ true);
masm.Pop(loggerReg);
masm.bind(&noTraceLogger);
return true;
}
bool
BaselineCompiler::emitSPSPush()
{

View File

@ -250,6 +250,8 @@ class BaselineCompiler : public BaselineCompilerSpecific
bool emitArgumentTypeChecks();
bool emitDebugPrologue();
bool emitDebugTrap();
bool emitTraceLoggerEnter();
bool emitTraceLoggerExit();
bool emitSPSPush();
void emitSPSPop();

View File

@ -41,7 +41,10 @@ PCMappingSlotInfo::ToSlotLocation(const StackValue *stackVal)
}
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset)
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset,
uint32_t traceLoggerScriptTextIdOffset,
uint32_t postDebugPrologueOffset)
: method_(nullptr),
templateScope_(nullptr),
fallbackStubSpace_(),
@ -51,6 +54,13 @@ BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
spsOn_(false),
#endif
spsPushToggleOffset_(spsPushToggleOffset),
#ifdef DEBUG
traceLoggerScriptsEnabled_(false),
traceLoggerEngineEnabled_(false),
#endif
traceLoggerEnterToggleOffset_(traceLoggerEnterToggleOffset),
traceLoggerExitToggleOffset_(traceLoggerExitToggleOffset),
traceLoggerScriptTextIdOffset_(traceLoggerScriptTextIdOffset),
postDebugPrologueOffset_(postDebugPrologueOffset),
flags_(0)
{ }
@ -339,8 +349,10 @@ jit::CanEnterBaselineMethod(JSContext *cx, RunState &state)
BaselineScript *
BaselineScript::New(JSScript *jsscript, uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset,
size_t icEntries, size_t pcMappingIndexEntries, size_t pcMappingSize,
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset, uint32_t traceLoggerScriptTextIdOffset,
uint32_t postDebugPrologueOffset, size_t icEntries,
size_t pcMappingIndexEntries, size_t pcMappingSize,
size_t bytecodeTypeMapEntries, size_t yieldEntries)
{
static const unsigned DataAlignment = sizeof(uintptr_t);
@ -366,7 +378,9 @@ BaselineScript::New(JSScript *jsscript, uint32_t prologueOffset, uint32_t epilog
if (!script)
return nullptr;
new (script) BaselineScript(prologueOffset, epilogueOffset,
spsPushToggleOffset, postDebugPrologueOffset);
spsPushToggleOffset, traceLoggerEnterToggleOffset,
traceLoggerExitToggleOffset, traceLoggerScriptTextIdOffset,
postDebugPrologueOffset);
size_t offsetCursor = sizeof(BaselineScript);
MOZ_ASSERT(offsetCursor == AlignBytes(sizeof(BaselineScript), DataAlignment));
@ -834,6 +848,73 @@ BaselineScript::toggleSPS(bool enable)
#endif
}
void
BaselineScript::toggleTraceLoggerScripts(JSRuntime *runtime, JSScript *script, bool enable)
{
bool engineEnabled = TraceLogTextIdEnabled(TraceLogger_Engine);
MOZ_ASSERT(enable == !traceLoggerScriptsEnabled_);
MOZ_ASSERT(engineEnabled == traceLoggerEngineEnabled_);
// Patch the logging script textId to be correct.
// When logging log the specific textId else the global Scripts textId.
TraceLoggerThread *logger = TraceLoggerForMainThread(runtime);
uint32_t textId = TraceLogCreateTextId(logger, script);
CodeLocationLabel patchLocation(method()->raw() + traceLoggerScriptTextIdOffset_);
if (enable) {
Assembler::PatchDataWithValueCheck(patchLocation,
PatchedImmPtr((void *)textId),
PatchedImmPtr((void *)TraceLogger_Scripts));
} else {
Assembler::PatchDataWithValueCheck(patchLocation,
PatchedImmPtr((void *)TraceLogger_Scripts),
PatchedImmPtr((void *)textId));
}
// Enable/Disable the traceLogger prologue and epilogue.
CodeLocationLabel enter(method_, CodeOffsetLabel(traceLoggerEnterToggleOffset_));
CodeLocationLabel exit(method_, CodeOffsetLabel(traceLoggerExitToggleOffset_));
if (!engineEnabled) {
if (enable) {
Assembler::ToggleToCmp(enter);
Assembler::ToggleToCmp(exit);
} else {
Assembler::ToggleToJmp(enter);
Assembler::ToggleToJmp(exit);
}
}
#if DEBUG
traceLoggerScriptsEnabled_ = enable;
#endif
}
void
BaselineScript::toggleTraceLoggerEngine(bool enable)
{
bool scriptsEnabled = TraceLogTextIdEnabled(TraceLogger_Scripts);
MOZ_ASSERT(enable == !traceLoggerEngineEnabled_);
MOZ_ASSERT(scriptsEnabled == traceLoggerScriptsEnabled_);
// Enable/Disable the traceLogger prologue and epilogue.
CodeLocationLabel enter(method_, CodeOffsetLabel(traceLoggerEnterToggleOffset_));
CodeLocationLabel exit(method_, CodeOffsetLabel(traceLoggerExitToggleOffset_));
if (!scriptsEnabled) {
if (enable) {
Assembler::ToggleToCmp(enter);
Assembler::ToggleToCmp(exit);
} else {
Assembler::ToggleToJmp(enter);
Assembler::ToggleToJmp(exit);
}
}
#if DEBUG
traceLoggerEngineEnabled_ = enable;
#endif
}
void
BaselineScript::purgeOptimizedStubs(Zone *zone)
{
@ -941,6 +1022,32 @@ jit::ToggleBaselineSPS(JSRuntime *runtime, bool enable)
}
}
void
jit::ToggleBaselineTraceLoggerScripts(JSRuntime *runtime, bool enable)
{
for (ZonesIter zone(runtime, SkipAtoms); !zone.done(); zone.next()) {
for (gc::ZoneCellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
if (!script->hasBaselineScript())
continue;
script->baselineScript()->toggleTraceLoggerScripts(runtime, script, enable);
}
}
}
void
jit::ToggleBaselineTraceLoggerEngine(JSRuntime *runtime, bool enable)
{
for (ZonesIter zone(runtime, SkipAtoms); !zone.done(); zone.next()) {
for (gc::ZoneCellIter i(zone, gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
if (!script->hasBaselineScript())
continue;
script->baselineScript()->toggleTraceLoggerEngine(enable);
}
}
}
static void
MarkActiveBaselineScripts(JSRuntime *rt, const JitActivationIterator &activation)
{

View File

@ -127,6 +127,16 @@ struct BaselineScript
#endif
uint32_t spsPushToggleOffset_;
#ifdef JS_TRACE_LOGGING
#ifdef DEBUG
bool traceLoggerScriptsEnabled_;
bool traceLoggerEngineEnabled_;
#endif
uint32_t traceLoggerEnterToggleOffset_;
uint32_t traceLoggerExitToggleOffset_;
uint32_t traceLoggerScriptTextIdOffset_;
#endif
// Native code offsets right after the debug prologue VM call returns, or
// would have returned. This offset is recorded even when debug mode is
// off to aid on-stack debug mode recompilation.
@ -185,11 +195,15 @@ struct BaselineScript
public:
// Do not call directly, use BaselineScript::New. This is public for cx->new_.
BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset);
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset, uint32_t traceLoggerScriptTextIdOffset,
uint32_t postDebugPrologueOffset);
static BaselineScript *New(JSScript *jsscript, uint32_t prologueOffset,
uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
uint32_t spsPushToggleOffset, size_t icEntries,
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset,
uint32_t traceLoggerScriptTextIdOffset, size_t icEntries,
size_t pcMappingIndexEntries, size_t pcMappingSize,
size_t bytecodeTypeMapEntries, size_t yieldEntries);
@ -358,6 +372,9 @@ struct BaselineScript
void toggleSPS(bool enable);
void toggleTraceLoggerScripts(JSRuntime *runtime, JSScript *script, bool enable);
void toggleTraceLoggerEngine(bool enable);
void noteAccessedGetter(uint32_t pcOffset);
void noteArrayWriteHole(uint32_t pcOffset);
@ -410,6 +427,11 @@ AddSizeOfBaselineData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf, size
void
ToggleBaselineSPS(JSRuntime *runtime, bool enable);
void
ToggleBaselineTraceLoggerScripts(JSRuntime *runtime, bool enable);
void
ToggleBaselineTraceLoggerEngine(JSRuntime *runtime, bool enable);
struct BaselineBailoutInfo
{
// Pointer into the current C stack, where overwriting will start.

View File

@ -1668,13 +1668,11 @@ MacroAssembler::printf(const char *output, Register value)
#ifdef JS_TRACE_LOGGING
void
MacroAssembler::tracelogStart(Register logger, uint32_t textId)
MacroAssembler::tracelogStart(Register logger, uint32_t textId, bool force)
{
if (!TraceLogTextIdEnabled(textId))
if (!force && !TraceLogTextIdEnabled(textId))
return;
void (&TraceLogFunc)(TraceLoggerThread*, uint32_t) = TraceLogStartEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
@ -1686,7 +1684,7 @@ MacroAssembler::tracelogStart(Register logger, uint32_t textId)
passABIArg(logger);
move32(Imm32(textId), temp);
passABIArg(temp);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogStartEvent));
PopRegsInMask(RegisterSet::Volatile());
}
@ -1694,8 +1692,6 @@ MacroAssembler::tracelogStart(Register logger, uint32_t textId)
void
MacroAssembler::tracelogStart(Register logger, Register textId)
{
void (&TraceLogFunc)(TraceLoggerThread*, uint32_t) = TraceLogStartEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
@ -1707,15 +1703,15 @@ MacroAssembler::tracelogStart(Register logger, Register textId)
setupUnalignedABICall(2, temp);
passABIArg(logger);
passABIArg(textId);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogStartEvent));
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStop(Register logger, uint32_t textId)
MacroAssembler::tracelogStop(Register logger, uint32_t textId, bool force)
{
if (!TraceLogTextIdEnabled(textId))
if (!force && !TraceLogTextIdEnabled(textId))
return;
PushRegsInMask(RegisterSet::Volatile());

View File

@ -1207,9 +1207,9 @@ class MacroAssembler : public MacroAssemblerSpecific
void printf(const char *output, Register value);
#ifdef JS_TRACE_LOGGING
void tracelogStart(Register logger, uint32_t textId);
void tracelogStart(Register logger, uint32_t textId, bool force = false);
void tracelogStart(Register logger, Register textId);
void tracelogStop(Register logger, uint32_t textId);
void tracelogStop(Register logger, uint32_t textId, bool force = false);
void tracelogStop(Register logger, Register textId);
#endif

View File

@ -30,7 +30,10 @@ BaselineCompilerShared::BaselineCompilerShared(JSContext *cx, TempAllocator &all
icLoadLabels_(),
pushedBeforeCall_(0),
inCall_(false),
spsPushToggleOffset_()
spsPushToggleOffset_(),
traceLoggerEnterToggleOffset_(),
traceLoggerExitToggleOffset_(),
traceLoggerScriptTextIdOffset_()
{ }
bool

View File

@ -68,6 +68,9 @@ class BaselineCompilerShared
mozilla::DebugOnly<bool> inCall_;
CodeOffsetLabel spsPushToggleOffset_;
CodeOffsetLabel traceLoggerEnterToggleOffset_;
CodeOffsetLabel traceLoggerExitToggleOffset_;
CodeOffsetLabel traceLoggerScriptTextIdOffset_;
BaselineCompilerShared(JSContext *cx, TempAllocator &alloc, JSScript *script);

View File

@ -26,6 +26,7 @@
#include "vm/ArgumentsObject.h"
#include "vm/DebuggerMemory.h"
#include "vm/SPSProfiler.h"
#include "vm/TraceLogging.h"
#include "vm/WrapperObject.h"
#include "jsgcinlines.h"
@ -3770,6 +3771,26 @@ Debugger::makeGlobalObjectReference(JSContext *cx, unsigned argc, Value *vp)
return dbg->wrapDebuggeeValue(cx, args.rval());
}
bool
Debugger::enableTraceItem(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "enableTraceItem", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.enableTraceItem", 1))
return false;
uint32_t id = args[0].toInt32();
if (!TLTextIdIsToggable(id)) {
args.rval().setBoolean(false);
return true;
}
TraceLogEnableTextId(cx, id);
args.rval().setBoolean(true);
return true;
}
const JSPropertySpec Debugger::properties[] = {
JS_PSGS("enabled", Debugger::getEnabled, Debugger::setEnabled, 0),
JS_PSGS("onDebuggerStatement", Debugger::getOnDebuggerStatement,
@ -3799,6 +3820,7 @@ const JSFunctionSpec Debugger::methods[] = {
JS_FN("findObjects", Debugger::findObjects, 1, 0),
JS_FN("findAllGlobals", Debugger::findAllGlobals, 0, 0),
JS_FN("makeGlobalObjectReference", Debugger::makeGlobalObjectReference, 1, 0),
JS_FN("enableTraceItem", Debugger::enableTraceItem, 1, 0),
JS_FS_END
};

View File

@ -394,6 +394,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static bool findObjects(JSContext *cx, unsigned argc, Value *vp);
static bool findAllGlobals(JSContext *cx, unsigned argc, Value *vp);
static bool makeGlobalObjectReference(JSContext *cx, unsigned argc, Value *vp);
static bool enableTraceItem(JSContext *cx, unsigned argc, Value *vp);
static bool construct(JSContext *cx, unsigned argc, Value *vp);
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];

View File

@ -14,6 +14,7 @@
#include "jsprf.h"
#include "jsscript.h"
#include "jit/BaselineJIT.h"
#include "jit/CompileWrappers.h"
#include "vm/Runtime.h"
#include "vm/TraceLoggingGraph.h"
@ -577,6 +578,53 @@ TraceLoggerThreadState::lazyInit()
return true;
}
void
TraceLoggerThreadState::enableTextId(JSContext *cx, uint32_t textId)
{
MOZ_ASSERT(TLTextIdIsToggable(textId));
if (enabledTextIds[textId])
return;
enabledTextIds[textId] = true;
if (textId == TraceLogger_Engine) {
enabledTextIds[TraceLogger_IonMonkey] = true;
enabledTextIds[TraceLogger_Baseline] = true;
enabledTextIds[TraceLogger_Interpreter] = true;
}
ReleaseAllJITCode(cx->runtime()->defaultFreeOp());
if (textId == TraceLogger_Scripts)
jit::ToggleBaselineTraceLoggerScripts(cx->runtime(), true);
if (textId == TraceLogger_Engine)
jit::ToggleBaselineTraceLoggerEngine(cx->runtime(), true);
}
void
TraceLoggerThreadState::disableTextId(JSContext *cx, uint32_t textId)
{
MOZ_ASSERT(TLTextIdIsToggable(textId));
if (!enabledTextIds[textId])
return;
enabledTextIds[textId] = false;
if (textId == TraceLogger_Engine) {
enabledTextIds[TraceLogger_IonMonkey] = false;
enabledTextIds[TraceLogger_Baseline] = false;
enabledTextIds[TraceLogger_Interpreter] = false;
}
ReleaseAllJITCode(cx->runtime()->defaultFreeOp());
if (textId == TraceLogger_Scripts)
jit::ToggleBaselineTraceLoggerScripts(cx->runtime(), false);
if (textId == TraceLogger_Engine)
jit::ToggleBaselineTraceLoggerEngine(cx->runtime(), false);
}
TraceLoggerThread *
js::TraceLoggerForMainThread(CompileRuntime *runtime)
{
@ -684,3 +732,14 @@ js::TraceLogTextIdEnabled(uint32_t textId)
{
return traceLoggers.isTextIdEnabled(textId);
}
void
js::TraceLogEnableTextId(JSContext *cx, uint32_t textId)
{
traceLoggers.enableTextId(cx, textId);
}
void
js::TraceLogDisableTextId(JSContext *cx, uint32_t textId)
{
traceLoggers.disableTextId(cx, textId);
}

View File

@ -171,6 +171,8 @@ class TraceLoggerThreadState
return enabledTextIds[textId];
return true;
}
void enableTextId(JSContext *cx, uint32_t textId);
void disableTextId(JSContext *cx, uint32_t textId);
private:
TraceLoggerThread *forMainThread(PerThreadData *mainThread);
@ -242,10 +244,14 @@ inline uint32_t TraceLogCreateTextId(TraceLoggerThread *logger, const char *text
}
#ifdef JS_TRACE_LOGGING
bool TraceLogTextIdEnabled(uint32_t textId);
void TraceLogEnableTextId(JSContext *cx, uint32_t textId);
void TraceLogDisableTextId(JSContext *cx, uint32_t textId);
#else
inline bool TraceLogTextIdEnabled(uint32_t textId) {
return false;
}
inline void TraceLogEnableTextId(JSContext *cx, uint32_t textId) {}
inline void TraceLogDisableTextId(JSContext *cx, uint32_t textId) {}
#endif
inline void TraceLogTimestamp(TraceLoggerThread *logger, uint32_t textId) {
#ifdef JS_TRACE_LOGGING