Merge mozilla-central to mozilla-inbound on a CLOSED TREE

This commit is contained in:
Carsten "Tomcat" Book 2014-11-21 08:23:35 +01:00
Родитель e025120099 a1e2258ca2
Коммит d6a3510342
41 изменённых файлов: 1274 добавлений и 2793 удалений

Просмотреть файл

@ -1704,7 +1704,7 @@ static bool
EnableTraceLogger(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
args.rval().setBoolean(TraceLoggerEnable(logger, cx));
return true;
@ -1714,7 +1714,7 @@ static bool
DisableTraceLogger(JSContext *cx, unsigned argc, jsval *vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
args.rval().setBoolean(TraceLoggerDisable(logger));
return true;

Просмотреть файл

@ -2985,16 +2985,16 @@ AC_SUBST(MOZ_OPTIMIZE_SIZE_TWEAK)
AC_SUBST(MOZ_PGO_OPTIMIZE_FLAGS)
dnl ========================================================
dnl = Disable trace logging
dnl = Enable trace logging
dnl ========================================================
ENABLE_TRACE_LOGGING=1
MOZ_ARG_DISABLE_BOOL(trace-logging,
[ --disable-trace-logging Disable trace logging],
MOZ_ARG_ENABLE_BOOL(trace-logging,
[ --enable-trace-logging Enable trace logging],
ENABLE_TRACE_LOGGING=1,
ENABLE_TRACE_LOGGING= )
AC_SUBST(ENABLE_TRACE_LOGGING)
if test -n "$ENABLE_TRACE_LOGGING"; then
if test "$ENABLE_TRACE_LOGGING"; then
AC_DEFINE(JS_TRACE_LOGGING)
fi

Просмотреть файл

@ -220,14 +220,14 @@ frontend::CompileScript(ExclusiveContext *cx, LifoAlloc *alloc, HandleObject sco
RootedString source(cx, source_);
js::TraceLoggerThread *logger = nullptr;
js::TraceLogger *logger = nullptr;
if (cx->isJSContext())
logger = TraceLoggerForMainThread(cx->asJSContext()->runtime());
else
logger = TraceLoggerForCurrentThread();
js::TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, options);
js::AutoTraceLog scriptLogger(logger, event);
js::AutoTraceLog typeLogger(logger, TraceLogger_ParserCompileScript);
uint32_t logId = js::TraceLogCreateTextId(logger, options);
js::AutoTraceLog scriptLogger(logger, logId);
js::AutoTraceLog typeLogger(logger, TraceLogger::ParserCompileScript);
/*
* The scripted callerFrame can only be given for compile-and-go scripts
@ -475,10 +475,10 @@ frontend::CompileLazyFunction(JSContext *cx, Handle<LazyScript*> lazy, const cha
.setNoScriptRval(false)
.setSelfHostingMode(false);
js::TraceLoggerThread *logger = js::TraceLoggerForMainThread(cx->runtime());
js::TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, options);
js::AutoTraceLog scriptLogger(logger, event);
js::AutoTraceLog typeLogger(logger, TraceLogger_ParserCompileLazy);
js::TraceLogger *logger = js::TraceLoggerForMainThread(cx->runtime());
uint32_t logId = js::TraceLogCreateTextId(logger, options);
js::AutoTraceLog scriptLogger(logger, logId);
js::AutoTraceLog typeLogger(logger, TraceLogger::ParserCompileLazy);
Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
/* foldConstants = */ true, nullptr, lazy);
@ -533,10 +533,10 @@ CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, const ReadOnlyComp
const AutoNameVector &formals, SourceBufferHolder &srcBuf,
HandleObject enclosingScope, GeneratorKind generatorKind)
{
js::TraceLoggerThread *logger = js::TraceLoggerForMainThread(cx->runtime());
js::TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, options);
js::AutoTraceLog scriptLogger(logger, event);
js::AutoTraceLog typeLogger(logger, TraceLogger_ParserCompileFunction);
js::TraceLogger *logger = js::TraceLoggerForMainThread(cx->runtime());
uint32_t logId = js::TraceLogCreateTextId(logger, options);
js::AutoTraceLog scriptLogger(logger, logId);
js::AutoTraceLog typeLogger(logger, TraceLogger::ParserCompileFunction);
// FIXME: make Function pass in two strings and parse them as arguments and
// ProgramElements respectively.

Просмотреть файл

@ -1,88 +0,0 @@
function TestDrainTraceLoggerInvariants(obj) {
var scripts = 0;
var stops = 0;
for (var i = 0; i < objs.length; i++) {
if (objs[i].logType == "Scripts") {
scripts++;
assertEq("fileName" in objs[i], true);
assertEq("lineNumber" in objs[i], true);
assertEq("columnNumber" in objs[i], true);
} else if (objs[i].logType == "Stop") {
stops++;
} else {
assertEq(true, false);
}
}
assertEq(scripts, stops);
}
function GetMaxScriptDepth(obj) {
var max_depth = 0;
for (var i = 0; i < objs.length; i++) {
if (objs[i].logType == "Stop")
depth--;
else {
depth++;
if (depth > max_depth)
max_depth = depth;
}
}
return max_depth;
}
function foo1() {
foo2();
}
function foo2() {
}
var du = new Debugger();
if (typeof du.drainTraceLoggerTraces == "function") {
print(1);
// Test normal setup.
du = new Debugger();
du.setupTraceLoggerForTraces();
du.startTraceLogger();
du.endTraceLogger();
var objs = du.drainTraceLoggerTraces();
TestDrainTraceLoggerInvariants(objs);
var empty_depth = GetMaxScriptDepth(objs);
var empty_length = objs.length;
// Test basic script.
for (var i=0; i<20; i++)
foo1();
du = new Debugger();
du.setupTraceLoggerTraces();
du.startTraceLogger();
foo1();
du.endTraceLogger();
var objs = du.drainTraceLoggerTraces();
TestDrainTraceLoggerInvariants(objs);
assertEq(empty_depth + 2 == GetMaxScriptDepth(objs));
assertEq(empty_length + 4 == GetMaxScriptDepth(objs));
// Test basic script.
for (var i=0; i<20; i++)
foo1();
du = new Debugger();
du.setupTraceLoggerForTraces();
du.startTraceLogger();
for (var i=0; i<100; i++) {
foo1();
}
du.endTraceLogger();
var objs = du.drainTraceLoggerTraces();
TestDrainTraceLoggerInvariants(objs);
assertEq(empty_depth + 2 == GetMaxScriptDepth(objs));
assertEq(empty_length + 4*100 == GetMaxScriptDepth(objs));
}

Просмотреть файл

@ -1,70 +0,0 @@
var du = new Debugger();
if (typeof du.setupTraceLogger == "function") {
// Try enabling.
assertEq(du.setupTraceLogger({
Scripts: true
}), true);
// No fail on re-enabling.
assertEq(du.setupTraceLogger({
Scripts: true
}), true);
// Try disabling.
assertEq(du.setupTraceLogger({
Scripts: false
}), true);
// No fail on re-disabling.
assertEq(du.setupTraceLogger({
Scripts: false
}), true);
// Throw exception if TraceLog item to report isn't found.
var success = du.setupTraceLogger({
Scripts: false,
Test: true
});
assertEq(success, false);
// SetupTraceLogger only enables individual items,
// when all items can be toggled.
du.startTraceLogger();
var obj = du.drainTraceLogger();
du.setupTraceLogger({
Scripts: true,
Test: true,
});
assertEq(du.drainTraceLogger().length, 0);
du.endTraceLogger();
// Expects an object as first argument.
succes = du.setupTraceLogger("blaat");
assertEq(succes, false);
// Expects an object as first argument.
succes = du.setupTraceLogger("blaat");
assertEq(succes, false);
// Expects an object as first argument.
failed = false;
try {
du.setupTraceLogger();
} catch (e) {
failed = true;
}
assertEq(failed, true);
// No problem with added to many arguments.
succes = du.setupTraceLogger({}, "test");
assertEq(succes, true);
}
var du2 = new Debugger();
if (typeof du2.setupTraceLoggerForTraces == "function") {
du2.setupTraceLoggerForTraces({});
du2.setupTraceLoggerForTraces("test");
du2.setupTraceLoggerForTraces({}, "test");
}

Просмотреть файл

@ -41,8 +41,8 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
JitFrameIterator iter(jitActivations);
MOZ_ASSERT(!iter.ionScript()->invalidated());
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogTimestamp(logger, TraceLogger_Bailout);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogTimestamp(logger, TraceLogger::Bailout);
JitSpew(JitSpew_IonBailouts, "Took bailout! Snapshot offset: %d", iter.snapshotOffset());
@ -107,8 +107,8 @@ jit::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
BailoutFrameInfo bailoutData(jitActivations, sp);
JitFrameIterator iter(jitActivations);
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogTimestamp(logger, TraceLogger_Invalidation);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogTimestamp(logger, TraceLogger::Invalidation);
JitSpew(JitSpew_IonBailouts, "Took invalidation bailout! Snapshot offset: %d", iter.snapshotOffset());

Просмотреть файл

@ -1347,9 +1347,9 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIter
MOZ_ASSERT(poppedLastSPSFrameOut);
MOZ_ASSERT(!*poppedLastSPSFrameOut);
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger_IonMonkey);
TraceLogStartEvent(logger, TraceLogger_Baseline);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger::IonMonkey);
TraceLogStartEvent(logger, TraceLogger::Baseline);
// The caller of the top frame must be one of the following:
// IonJS - Ion calling into Ion.
@ -1460,12 +1460,8 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIter
snapIter.settleOnFrame();
if (frameNo > 0) {
// TraceLogger doesn't create entries for inlined frames. But we
// see them in Baseline. Here we create the start events of those
// entries. So they correspond to what we will see in Baseline.
TraceLoggerEvent scriptEvent(logger, TraceLogger_Scripts, scr);
TraceLogStartEvent(logger, scriptEvent);
TraceLogStartEvent(logger, TraceLogger_Baseline);
TraceLogStartEvent(logger, TraceLogCreateTextId(logger, scr));
TraceLogStartEvent(logger, TraceLogger::Baseline);
}
JitSpew(JitSpew_BaselineBailouts, " FrameNo %d", frameNo);

Просмотреть файл

@ -81,10 +81,9 @@ BaselineCompiler::compile()
JitSpew(JitSpew_Codegen, "# Emitting baseline code for script %s:%d",
script->filename(), script->lineno());
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEvent scriptEvent(logger, TraceLogger_AnnotateScripts, script);
AutoTraceLog logScript(logger, scriptEvent);
AutoTraceLog logCompile(logger, TraceLogger_BaselineCompilation);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, script));
AutoTraceLog logCompile(logger, TraceLogger::BaselineCompilation);
if (!script->ensureHasTypes(cx) || !script->ensureHasAnalyzedArgsUsage(cx))
return Method_Error;
@ -178,10 +177,6 @@ BaselineCompiler::compile()
prologueOffset_.fixup(&masm);
epilogueOffset_.fixup(&masm);
spsPushToggleOffset_.fixup(&masm);
#ifdef JS_TRACE_LOGGING
traceLoggerEnterToggleOffset_.fixup(&masm);
traceLoggerExitToggleOffset_.fixup(&masm);
#endif
postDebugPrologueOffset_.fixup(&masm);
// Note: There is an extra entry in the bytecode type map for the search hint, see below.
@ -191,8 +186,6 @@ BaselineCompiler::compile()
BaselineScript::New(script, prologueOffset_.offset(),
epilogueOffset_.offset(),
spsPushToggleOffset_.offset(),
traceLoggerEnterToggleOffset_.offset(),
traceLoggerExitToggleOffset_.offset(),
postDebugPrologueOffset_.offset(),
icEntries_.length(),
pcMappingIndexEntries.length(),
@ -248,11 +241,6 @@ BaselineCompiler::compile()
if (cx->runtime()->spsProfiler.enabled())
baselineScript->toggleSPS(true);
#ifdef JS_TRACE_LOGGING
// Initialize the tracelogger instrumentation.
baselineScript->initTraceLogger(cx->runtime(), script);
#endif
uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
types::FillBytecodeTypeMap(script, bytecodeMap);
@ -385,8 +373,13 @@ BaselineCompiler::emitPrologue()
masm.bind(&earlyStackCheckFailed);
#ifdef JS_TRACE_LOGGING
if (!emitTraceLoggerEnter())
return false;
TraceLogger *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
// Record the offset of the prologue, because Ion can bailout before
@ -426,8 +419,15 @@ BaselineCompiler::emitEpilogue()
masm.bind(&return_);
#ifdef JS_TRACE_LOGGING
if (!emitTraceLoggerExit())
return false;
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
Register loggerReg = RegisterSet::Volatile().takeGeneral();
masm.Push(loggerReg);
masm.movePtr(ImmPtr(logger), loggerReg);
masm.tracelogStop(loggerReg, TraceLogger::Baseline);
// Stop the script. Using a stop without checking the textId, since we
// we didn't save the textId for the script.
masm.tracelogStop(loggerReg);
masm.Pop(loggerReg);
#endif
// Pop SPS frame if necessary
@ -767,64 +767,6 @@ BaselineCompiler::emitDebugTrap()
return true;
}
#ifdef JS_TRACE_LOGGING
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.
masm.movePtr(ImmGCPtr(script), scriptReg);
masm.loadPtr(Address(scriptReg, JSScript::offsetOfBaselineScript()), scriptReg);
Address scriptEvent(scriptReg, BaselineScript::offsetOfTraceLoggerScriptEvent());
masm.computeEffectiveAddress(scriptEvent, scriptReg);
masm.tracelogStartEvent(loggerReg, scriptReg);
// Engine start.
masm.tracelogStartId(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.tracelogStopId(loggerReg, TraceLogger_Baseline, /* force = */ true);
masm.tracelogStopId(loggerReg, TraceLogger_Scripts, /* force = */ true);
masm.Pop(loggerReg);
masm.bind(&noTraceLogger);
return true;
}
#endif
bool
BaselineCompiler::emitSPSPush()
{

Просмотреть файл

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

Просмотреть файл

@ -41,9 +41,7 @@ PCMappingSlotInfo::ToSlotLocation(const StackValue *stackVal)
}
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset,
uint32_t postDebugPrologueOffset)
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset)
: method_(nullptr),
templateScope_(nullptr),
fallbackStubSpace_(),
@ -53,15 +51,6 @@ BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
spsOn_(false),
#endif
spsPushToggleOffset_(spsPushToggleOffset),
#ifdef JS_TRACE_LOGGING
# ifdef DEBUG
traceLoggerScriptsEnabled_(false),
traceLoggerEngineEnabled_(false),
# endif
traceLoggerEnterToggleOffset_(traceLoggerEnterToggleOffset),
traceLoggerExitToggleOffset_(traceLoggerExitToggleOffset),
traceLoggerScriptEvent_(),
#endif
postDebugPrologueOffset_(postDebugPrologueOffset),
flags_(0)
{ }
@ -201,9 +190,9 @@ jit::EnterBaselineAtBranch(JSContext *cx, InterpreterFrame *fp, jsbytecode *pc)
data.calleeToken = CalleeToToken(fp->script());
}
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger_Interpreter);
TraceLogStartEvent(logger, TraceLogger_Baseline);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger::Interpreter);
TraceLogStartEvent(logger, TraceLogger::Baseline);
IonExecStatus status = EnterBaseline(cx, data);
if (status != IonExec_Ok)
@ -350,8 +339,7 @@ jit::CanEnterBaselineMethod(JSContext *cx, RunState &state)
BaselineScript *
BaselineScript::New(JSScript *jsscript, uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset, uint32_t postDebugPrologueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset,
size_t icEntries, size_t pcMappingIndexEntries, size_t pcMappingSize,
size_t bytecodeTypeMapEntries, size_t yieldEntries)
{
@ -378,8 +366,7 @@ BaselineScript::New(JSScript *jsscript, uint32_t prologueOffset, uint32_t epilog
if (!script)
return nullptr;
new (script) BaselineScript(prologueOffset, epilogueOffset,
spsPushToggleOffset, traceLoggerEnterToggleOffset,
traceLoggerExitToggleOffset, postDebugPrologueOffset);
spsPushToggleOffset, postDebugPrologueOffset);
size_t offsetCursor = sizeof(BaselineScript);
MOZ_ASSERT(offsetCursor == AlignBytes(sizeof(BaselineScript), DataAlignment));
@ -847,90 +834,6 @@ BaselineScript::toggleSPS(bool enable)
#endif
}
#ifdef JS_TRACE_LOGGING
void
BaselineScript::initTraceLogger(JSRuntime *runtime, JSScript *script)
{
#ifdef DEBUG
traceLoggerScriptsEnabled_ = TraceLogTextIdEnabled(TraceLogger_Scripts);
traceLoggerEngineEnabled_ = TraceLogTextIdEnabled(TraceLogger_Engine);
#endif
TraceLoggerThread *logger = TraceLoggerForMainThread(runtime);
if (TraceLogTextIdEnabled(TraceLogger_Scripts))
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts, script);
else
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts);
if (TraceLogTextIdEnabled(TraceLogger_Engine) || TraceLogTextIdEnabled(TraceLogger_Scripts)) {
CodeLocationLabel enter(method_, CodeOffsetLabel(traceLoggerEnterToggleOffset_));
CodeLocationLabel exit(method_, CodeOffsetLabel(traceLoggerExitToggleOffset_));
Assembler::ToggleToCmp(enter);
Assembler::ToggleToCmp(exit);
}
}
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);
if (enable)
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts, script);
else
traceLoggerScriptEvent_ = TraceLoggerEvent(logger, TraceLogger_Scripts);
// 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
}
#endif
void
BaselineScript::purgeOptimizedStubs(Zone *zone)
{
@ -1038,34 +941,6 @@ jit::ToggleBaselineSPS(JSRuntime *runtime, bool enable)
}
}
#ifdef JS_TRACE_LOGGING
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);
}
}
}
#endif
static void
MarkActiveBaselineScripts(JSRuntime *rt, const JitActivationIterator &activation)
{

Просмотреть файл

@ -16,7 +16,6 @@
#include "jit/Bailouts.h"
#include "jit/IonCode.h"
#include "jit/IonMacroAssembler.h"
#include "vm/TraceLogging.h"
namespace js {
namespace jit {
@ -128,17 +127,6 @@ struct BaselineScript
#endif
uint32_t spsPushToggleOffset_;
// The offsets and event used for Tracelogger toggling.
#ifdef JS_TRACE_LOGGING
# ifdef DEBUG
bool traceLoggerScriptsEnabled_;
bool traceLoggerEngineEnabled_;
# endif
uint32_t traceLoggerEnterToggleOffset_;
uint32_t traceLoggerExitToggleOffset_;
TraceLoggerEvent traceLoggerScriptEvent_;
#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.
@ -197,13 +185,11 @@ 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 traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset, uint32_t postDebugPrologueOffset);
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset);
static BaselineScript *New(JSScript *jsscript, uint32_t prologueOffset,
uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
uint32_t spsPushToggleOffset, uint32_t traceLoggerEnterToggleOffset,
uint32_t traceLoggerExitToggleOffset, size_t icEntries,
uint32_t spsPushToggleOffset, size_t icEntries,
size_t pcMappingIndexEntries, size_t pcMappingSize,
size_t bytecodeTypeMapEntries, size_t yieldEntries);
@ -372,16 +358,6 @@ struct BaselineScript
void toggleSPS(bool enable);
#ifdef JS_TRACE_LOGGING
void initTraceLogger(JSRuntime *runtime, JSScript *script);
void toggleTraceLoggerScripts(JSRuntime *runtime, JSScript *script, bool enable);
void toggleTraceLoggerEngine(bool enable);
static size_t offsetOfTraceLoggerScriptEvent() {
return offsetof(BaselineScript, traceLoggerScriptEvent_);
}
#endif
void noteAccessedGetter(uint32_t pcOffset);
void noteArrayWriteHole(uint32_t pcOffset);
@ -434,11 +410,6 @@ 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.

Просмотреть файл

@ -2090,9 +2090,9 @@ CodeGenerator::visitOsrEntry(LOsrEntry *lir)
#ifdef JS_TRACE_LOGGING
if (gen->info().executionMode() == SequentialExecution) {
if (!emitTracelogStopEvent(TraceLogger_Baseline))
if (!emitTracelogStopEvent(TraceLogger::Baseline))
return false;
if (!emitTracelogStartEvent(TraceLogger_IonMonkey))
if (!emitTracelogStartEvent(TraceLogger::IonMonkey))
return false;
}
#endif
@ -7652,7 +7652,7 @@ CodeGenerator::generate()
if (!gen->compilingAsmJS() && gen->info().executionMode() == SequentialExecution) {
if (!emitTracelogScriptStart())
return false;
if (!emitTracelogStartEvent(TraceLogger_IonMonkey))
if (!emitTracelogStartEvent(TraceLogger::IonMonkey))
return false;
}
#endif
@ -7928,25 +7928,19 @@ CodeGenerator::link(JSContext *cx, types::CompilerConstraintList *constraints)
ionScript->copyPatchableBackedges(cx, code, patchableBackedges_.begin(), masm);
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
for (uint32_t i = 0; i < patchableTraceLoggers_.length(); i++) {
patchableTraceLoggers_[i].fixup(&masm);
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, patchableTraceLoggers_[i]),
ImmPtr(logger),
ImmPtr(nullptr));
}
if (patchableTLScripts_.length() > 0) {
MOZ_ASSERT(TraceLogTextIdEnabled(TraceLogger_Scripts));
TraceLoggerEvent event(logger, TraceLogger_Scripts, script);
ionScript->setTraceLoggerEvent(event);
uint32_t textId = event.payload()->textId();
for (uint32_t i = 0; i < patchableTLScripts_.length(); i++) {
patchableTLScripts_[i].fixup(&masm);
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, patchableTLScripts_[i]),
ImmPtr((void *) uintptr_t(textId)),
ImmPtr((void *)0));
}
uint32_t scriptId = TraceLogCreateTextId(logger, script);
for (uint32_t i = 0; i < patchableTLScripts_.length(); i++) {
patchableTLScripts_[i].fixup(&masm);
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, patchableTLScripts_[i]),
ImmPtr((void *) uintptr_t(scriptId)),
ImmPtr((void *)0));
}
#endif

Просмотреть файл

@ -539,10 +539,9 @@ jit::LazyLinkTopActivation(JSContext *cx)
builder->remove();
if (CodeGenerator *codegen = builder->backgroundCodegen()) {
js::TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, script);
AutoTraceLog logScript(logger, event);
AutoTraceLog logLink(logger, TraceLogger_IonLinking);
js::TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, script));
AutoTraceLog logLink(logger, TraceLogger::IonLinking);
IonContext ictx(cx, &builder->alloc());
@ -1290,7 +1289,7 @@ bool
OptimizeMIR(MIRGenerator *mir)
{
MIRGraph &graph = mir->graph();
TraceLoggerThread *logger;
TraceLogger *logger;
if (GetIonContext()->runtime->onMainThread())
logger = TraceLoggerForMainThread(GetIonContext()->runtime);
else
@ -1308,7 +1307,7 @@ OptimizeMIR(MIRGenerator *mir)
return false;
if (!mir->compilingAsmJS()) {
AutoTraceLog log(logger, TraceLogger_FoldTests);
AutoTraceLog log(logger, TraceLogger::FoldTests);
FoldTests(graph);
IonSpewPass("Fold Tests");
AssertBasicGraphCoherency(graph);
@ -1318,7 +1317,7 @@ OptimizeMIR(MIRGenerator *mir)
}
{
AutoTraceLog log(logger, TraceLogger_SplitCriticalEdges);
AutoTraceLog log(logger, TraceLogger::SplitCriticalEdges);
if (!SplitCriticalEdges(graph))
return false;
IonSpewPass("Split Critical Edges");
@ -1329,7 +1328,7 @@ OptimizeMIR(MIRGenerator *mir)
}
{
AutoTraceLog log(logger, TraceLogger_RenumberBlocks);
AutoTraceLog log(logger, TraceLogger::RenumberBlocks);
if (!RenumberBlocks(graph))
return false;
IonSpewPass("Renumber Blocks");
@ -1340,7 +1339,7 @@ OptimizeMIR(MIRGenerator *mir)
}
{
AutoTraceLog log(logger, TraceLogger_DominatorTree);
AutoTraceLog log(logger, TraceLogger::DominatorTree);
if (!BuildDominatorTree(graph))
return false;
// No spew: graph not changed.
@ -1350,7 +1349,7 @@ OptimizeMIR(MIRGenerator *mir)
}
{
AutoTraceLog log(logger, TraceLogger_PhiAnalysis);
AutoTraceLog log(logger, TraceLogger::PhiAnalysis);
// Aggressive phi elimination must occur before any code elimination. If the
// script contains a try-statement, we only compiled the try block and not
// the catch or finally blocks, so in this case it's also invalid to use
@ -1376,7 +1375,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().scalarReplacementEnabled()) {
AutoTraceLog log(logger, TraceLogger_ScalarReplacement);
AutoTraceLog log(logger, TraceLogger::ScalarReplacement);
if (!ScalarReplacement(mir, graph))
return false;
IonSpewPass("Scalar Replacement");
@ -1387,7 +1386,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (!mir->compilingAsmJS()) {
AutoTraceLog log(logger, TraceLogger_ApplyTypes);
AutoTraceLog log(logger, TraceLogger::ApplyTypes);
if (!ApplyTypeInformation(mir, graph))
return false;
IonSpewPass("Apply types");
@ -1402,7 +1401,7 @@ OptimizeMIR(MIRGenerator *mir)
// are not deleted, leaving them dangling. This is ok, since we'll rerun
// AliasAnalysis, which recomputes them, before they're needed.
if (graph.entryBlock()->info().executionMode() == ParallelExecution) {
AutoTraceLog log(logger, TraceLogger_ParallelSafetyAnalysis);
AutoTraceLog log(logger, TraceLogger::ParallelSafetyAnalysis);
ParallelSafetyAnalysis analysis(mir, graph);
if (!analysis.analyze())
return false;
@ -1421,7 +1420,7 @@ OptimizeMIR(MIRGenerator *mir)
if (mir->optimizationInfo().licmEnabled() ||
mir->optimizationInfo().gvnEnabled())
{
AutoTraceLog log(logger, TraceLogger_AliasAnalysis);
AutoTraceLog log(logger, TraceLogger::AliasAnalysis);
AliasAnalysis analysis(mir, graph);
if (!analysis.analyze())
return false;
@ -1444,7 +1443,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().gvnEnabled()) {
AutoTraceLog log(logger, TraceLogger_GVN);
AutoTraceLog log(logger, TraceLogger::GVN);
if (!gvn.run(ValueNumberer::UpdateAliasAnalysis))
return false;
IonSpewPass("GVN");
@ -1455,7 +1454,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().licmEnabled()) {
AutoTraceLog log(logger, TraceLogger_LICM);
AutoTraceLog log(logger, TraceLogger::LICM);
// LICM can hoist instructions from conditional branches and trigger
// repeated bailouts. Disable it if this script is known to bailout
// frequently.
@ -1472,7 +1471,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().rangeAnalysisEnabled()) {
AutoTraceLog log(logger, TraceLogger_RangeAnalysis);
AutoTraceLog log(logger, TraceLogger::RangeAnalysis);
RangeAnalysis r(mir, graph);
if (!r.addBetaNodes())
return false;
@ -1530,7 +1529,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().loopUnrollingEnabled()) {
AutoTraceLog log(logger, TraceLogger_LoopUnrolling);
AutoTraceLog log(logger, TraceLogger::LoopUnrolling);
if (!UnrollLoops(graph, r.loopIterationBounds))
return false;
@ -1541,7 +1540,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().eaaEnabled()) {
AutoTraceLog log(logger, TraceLogger_EffectiveAddressAnalysis);
AutoTraceLog log(logger, TraceLogger::EffectiveAddressAnalysis);
EffectiveAddressAnalysis eaa(graph);
if (!eaa.analyze())
return false;
@ -1553,7 +1552,7 @@ OptimizeMIR(MIRGenerator *mir)
}
{
AutoTraceLog log(logger, TraceLogger_EliminateDeadCode);
AutoTraceLog log(logger, TraceLogger::EliminateDeadCode);
if (!EliminateDeadCode(mir, graph))
return false;
IonSpewPass("DCE");
@ -1566,7 +1565,7 @@ OptimizeMIR(MIRGenerator *mir)
// Make loops contiguous. We do this after GVN/UCE and range analysis,
// which can remove CFG edges, exposing more blocks that can be moved.
{
AutoTraceLog log(logger, TraceLogger_MakeLoopsContiguous);
AutoTraceLog log(logger, TraceLogger::MakeLoopsContiguous);
if (!MakeLoopsContiguous(graph))
return false;
IonSpewPass("Make loops contiguous");
@ -1580,7 +1579,7 @@ OptimizeMIR(MIRGenerator *mir)
// depend on knowing the final order in which instructions will execute.
if (mir->optimizationInfo().edgeCaseAnalysisEnabled()) {
AutoTraceLog log(logger, TraceLogger_EdgeCaseAnalysis);
AutoTraceLog log(logger, TraceLogger::EdgeCaseAnalysis);
EdgeCaseAnalysis edgeCaseAnalysis(mir, graph);
if (!edgeCaseAnalysis.analyzeLate())
return false;
@ -1592,7 +1591,7 @@ OptimizeMIR(MIRGenerator *mir)
}
if (mir->optimizationInfo().eliminateRedundantChecksEnabled()) {
AutoTraceLog log(logger, TraceLogger_EliminateRedundantChecks);
AutoTraceLog log(logger, TraceLogger::EliminateRedundantChecks);
// Note: check elimination has to run after all other passes that move
// instructions. Since check uses are replaced with the actual index,
// code motion after this pass could incorrectly move a load or store
@ -1611,7 +1610,7 @@ GenerateLIR(MIRGenerator *mir)
{
MIRGraph &graph = mir->graph();
TraceLoggerThread *logger;
TraceLogger *logger;
if (GetIonContext()->runtime->onMainThread())
logger = TraceLoggerForMainThread(GetIonContext()->runtime);
else
@ -1623,7 +1622,7 @@ GenerateLIR(MIRGenerator *mir)
LIRGenerator lirgen(mir, graph, *lir);
{
AutoTraceLog log(logger, TraceLogger_GenerateLIR);
AutoTraceLog log(logger, TraceLogger::GenerateLIR);
if (!lirgen.generate())
return nullptr;
IonSpewPass("Generate LIR");
@ -1635,7 +1634,7 @@ GenerateLIR(MIRGenerator *mir)
AllocationIntegrityState integrity(*lir);
{
AutoTraceLog log(logger, TraceLogger_RegisterAllocation);
AutoTraceLog log(logger, TraceLogger::RegisterAllocation);
switch (mir->optimizationInfo().registerAllocator()) {
case RegisterAllocator_LSRA: {
@ -1705,12 +1704,12 @@ GenerateLIR(MIRGenerator *mir)
CodeGenerator *
GenerateCode(MIRGenerator *mir, LIRGraph *lir)
{
TraceLoggerThread *logger;
TraceLogger *logger;
if (GetIonContext()->runtime->onMainThread())
logger = TraceLoggerForMainThread(GetIonContext()->runtime);
else
logger = TraceLoggerForCurrentThread();
AutoTraceLog log(logger, TraceLogger_GenerateCode);
AutoTraceLog log(logger, TraceLogger::GenerateCode);
CodeGenerator *codegen = js_new<CodeGenerator>(mir, lir);
if (!codegen)
@ -1752,7 +1751,7 @@ AttachFinishedCompilations(JSContext *cx)
GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
// Incorporate any off thread compilations for the compartment which have
// finished, failed or have been cancelled.
@ -1804,9 +1803,8 @@ AttachFinishedCompilations(JSContext *cx)
if (CodeGenerator *codegen = builder->backgroundCodegen()) {
RootedScript script(cx, builder->script());
IonContext ictx(cx, &builder->alloc());
TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, script);
AutoTraceLog logScript(logger, event);
AutoTraceLog logLink(logger, TraceLogger_IonLinking);
AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, script));
AutoTraceLog logLink(logger, TraceLogger::IonLinking);
// Root the assembler until the builder is finished below. As it
// was constructed off thread, the assembler has not been rooted
@ -1884,10 +1882,9 @@ IonCompile(JSContext *cx, JSScript *script,
ExecutionMode executionMode, bool recompile,
OptimizationLevel optimizationLevel)
{
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, script);
AutoTraceLog logScript(logger, event);
AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, script));
AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
MOZ_ASSERT(optimizationLevel > Optimization_DontCompile);

Просмотреть файл

@ -21,7 +21,6 @@
#include "vm/ArgumentsObject.h"
#include "vm/Opcodes.h"
#include "vm/RegExpStatics.h"
#include "vm/TraceLogging.h"
#include "jsinferinlines.h"
#include "jsobjinlines.h"
@ -343,11 +342,6 @@ IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
if (!optimizationInfo().inlineInterpreted())
return InliningDecision_DontInline;
if (TraceLogTextIdEnabled(TraceLogger_InlinedScripts)) {
return DontInline(nullptr, "Tracelogging of inlined scripts is enabled"
"but Tracelogger cannot do that yet.");
}
if (!target->isInterpreted())
return DontInline(nullptr, "Non-interpreted target");

Просмотреть файл

@ -19,7 +19,6 @@
#include "jit/IonOptimizationLevels.h"
#include "jit/IonTypes.h"
#include "js/UbiNode.h"
#include "vm/TraceLogging.h"
namespace js {
@ -303,9 +302,6 @@ struct IonScript
// that contain an optimized call directly into this IonScript.
Vector<DependentAsmJSModuleExit> *dependentAsmJSModules;
// The tracelogger event used to log the start/stop of this IonScript.
TraceLoggerEvent traceLoggerScriptEvent_;
IonBuilder *pendingBuilder_;
private:
@ -496,9 +492,6 @@ struct IonScript
bool hasSPSInstrumentation() const {
return hasSPSInstrumentation_;
}
void setTraceLoggerEvent(TraceLoggerEvent &event) {
traceLoggerScriptEvent_ = event;
}
const uint8_t *snapshots() const {
return reinterpret_cast<const uint8_t *>(this) + snapshots_;
}

Просмотреть файл

@ -693,7 +693,7 @@ void
HandleException(ResumeFromException *rfe)
{
JSContext *cx = GetJSContextFromJitCode();
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
rfe->kind = ResumeFromException::RESUME_ENTRY_FRAME;
@ -754,8 +754,8 @@ HandleException(ResumeFromException *rfe)
JSScript *script = frames.script();
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
if (!frames.more()) {
TraceLogStopEvent(logger, TraceLogger_IonMonkey);
TraceLogStopEvent(logger, TraceLogger_Scripts);
TraceLogStopEvent(logger, TraceLogger::IonMonkey);
TraceLogStopEvent(logger);
break;
}
++frames;
@ -785,8 +785,8 @@ HandleException(ResumeFromException *rfe)
if (rfe->kind != ResumeFromException::RESUME_ENTRY_FRAME)
return;
TraceLogStopEvent(logger, TraceLogger_Baseline);
TraceLogStopEvent(logger, TraceLogger_Scripts);
TraceLogStopEvent(logger, TraceLogger::Baseline);
TraceLogStopEvent(logger);
// Unwind profiler pseudo-stack
JSScript *script = iter.script();

Просмотреть файл

@ -1668,10 +1668,9 @@ MacroAssembler::printf(const char *output, Register value)
#ifdef JS_TRACE_LOGGING
void
MacroAssembler::tracelogStartId(Register logger, uint32_t textId, bool force)
MacroAssembler::tracelogStart(Register logger, uint32_t textId)
{
if (!force && !TraceLogTextIdEnabled(textId))
return;
void (&TraceLogFunc)(TraceLogger*, uint32_t) = TraceLogStartEvent;
PushRegsInMask(RegisterSet::Volatile());
@ -1684,56 +1683,38 @@ MacroAssembler::tracelogStartId(Register logger, uint32_t textId, bool force)
passABIArg(logger);
move32(Imm32(textId), temp);
passABIArg(temp);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogStartEventPrivate));
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStartId(Register logger, Register textId)
{
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
regs.takeUnchecked(logger);
regs.takeUnchecked(textId);
Register temp = regs.takeGeneral();
setupUnalignedABICall(2, temp);
passABIArg(logger);
passABIArg(textId);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogStartEventPrivate));
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStartEvent(Register logger, Register event)
{
void (&TraceLogFunc)(TraceLoggerThread *, const TraceLoggerEvent &) = TraceLogStartEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
regs.takeUnchecked(logger);
regs.takeUnchecked(event);
Register temp = regs.takeGeneral();
setupUnalignedABICall(2, temp);
passABIArg(logger);
passABIArg(event);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStopId(Register logger, uint32_t textId, bool force)
MacroAssembler::tracelogStart(Register logger, Register textId)
{
if (!force && !TraceLogTextIdEnabled(textId))
return;
void (&TraceLogFunc)(TraceLogger*, uint32_t) = TraceLogStartEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
regs.takeUnchecked(logger);
regs.takeUnchecked(textId);
Register temp = regs.takeGeneral();
setupUnalignedABICall(2, temp);
passABIArg(logger);
passABIArg(textId);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
regs.add(temp);
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStop(Register logger, uint32_t textId)
{
void (&TraceLogFunc)(TraceLogger*, uint32_t) = TraceLogStopEvent;
PushRegsInMask(RegisterSet::Volatile());
@ -1746,19 +1727,23 @@ MacroAssembler::tracelogStopId(Register logger, uint32_t textId, bool force)
passABIArg(logger);
move32(Imm32(textId), temp);
passABIArg(temp);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogStopEventPrivate));
regs.add(temp);
PopRegsInMask(RegisterSet::Volatile());
}
void
MacroAssembler::tracelogStopId(Register logger, Register textId)
MacroAssembler::tracelogStop(Register logger, Register textId)
{
#ifdef DEBUG
void (&TraceLogFunc)(TraceLogger*, uint32_t) = TraceLogStopEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
regs.takeUnchecked(logger);
regs.takeUnchecked(textId);
Register temp = regs.takeGeneral();
@ -1766,8 +1751,33 @@ MacroAssembler::tracelogStopId(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 *, TraceLogStopEventPrivate));
regs.add(temp);
PopRegsInMask(RegisterSet::Volatile());
#else
tracelogStop(logger);
#endif
}
void
MacroAssembler::tracelogStop(Register logger)
{
void (&TraceLogFunc)(TraceLogger*) = TraceLogStopEvent;
PushRegsInMask(RegisterSet::Volatile());
RegisterSet regs = RegisterSet::Volatile();
regs.takeUnchecked(logger);
Register temp = regs.takeGeneral();
setupUnalignedABICall(1, temp);
passABIArg(logger);
callWithABINoProfiling(JS_FUNC_TO_DATA_PTR(void *, TraceLogFunc));
regs.add(temp);
PopRegsInMask(RegisterSet::Volatile());
}

Просмотреть файл

@ -1207,11 +1207,11 @@ class MacroAssembler : public MacroAssemblerSpecific
void printf(const char *output, Register value);
#ifdef JS_TRACE_LOGGING
void tracelogStartId(Register logger, uint32_t textId, bool force = false);
void tracelogStartId(Register logger, Register textId);
void tracelogStartEvent(Register logger, Register event);
void tracelogStopId(Register logger, uint32_t textId, bool force = false);
void tracelogStopId(Register logger, Register textId);
void tracelogStart(Register logger, uint32_t textId);
void tracelogStart(Register logger, Register textId);
void tracelogStop(Register logger, uint32_t textId);
void tracelogStop(Register logger, Register textId);
void tracelogStop(Register logger);
#endif
#define DISPATCH_FLOATING_POINT_OP(method, type, arg1d, arg1f, arg2) \

Просмотреть файл

@ -778,9 +778,9 @@ DebugEpilogueOnBaselineReturn(JSContext *cx, BaselineFrame *frame, jsbytecode *p
if (!DebugEpilogue(cx, frame, pc, true)) {
// DebugEpilogue popped the frame by updating jitTop, so run the stop event
// here before we enter the exception handler.
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger_Baseline);
TraceLogStopEvent(logger, TraceLogger_Scripts);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogStopEvent(logger, TraceLogger::Baseline);
TraceLogStopEvent(logger); // Leave script.
return false;
}

Просмотреть файл

@ -57,7 +57,7 @@ CodeGeneratorARM::generateEpilogue()
#ifdef JS_TRACE_LOGGING
if (gen->info().executionMode() == SequentialExecution) {
if (!emitTracelogStopEvent(TraceLogger_IonMonkey))
if (!emitTracelogStopEvent(TraceLogger::IonMonkey))
return false;
if (!emitTracelogScriptStop())
return false;

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1011,7 +1011,7 @@ CodeGeneratorShared::callVM(const VMFunction &fun, LInstruction *ins, const Regi
#endif
#ifdef JS_TRACE_LOGGING
if (!emitTracelogStartEvent(TraceLogger_VM))
if (!emitTracelogStartEvent(TraceLogger::VM))
return false;
#endif
@ -1056,7 +1056,7 @@ CodeGeneratorShared::callVM(const VMFunction &fun, LInstruction *ins, const Regi
// ... frame ...
#ifdef JS_TRACE_LOGGING
if (!emitTracelogStopEvent(TraceLogger_VM))
if (!emitTracelogStopEvent(TraceLogger::VM))
return false;
#endif
@ -1402,9 +1402,6 @@ CodeGeneratorShared::computeDivisionConstants(int d) {
bool
CodeGeneratorShared::emitTracelogScript(bool isStart)
{
if (!TraceLogTextIdEnabled(TraceLogger_Scripts))
return true;
Label done;
RegisterSet regs = RegisterSet::Volatile();
@ -1417,7 +1414,7 @@ CodeGeneratorShared::emitTracelogScript(bool isStart)
if (!patchableTraceLoggers_.append(patchLogger))
return false;
Address enabledAddress(logger, TraceLoggerThread::offsetOfEnabled());
Address enabledAddress(logger, TraceLogger::offsetOfEnabled());
masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
masm.Push(script);
@ -1427,9 +1424,9 @@ CodeGeneratorShared::emitTracelogScript(bool isStart)
return false;
if (isStart)
masm.tracelogStartId(logger, script);
masm.tracelogStart(logger, script);
else
masm.tracelogStopId(logger, script);
masm.tracelogStop(logger, script);
masm.Pop(script);
@ -1455,13 +1452,18 @@ CodeGeneratorShared::emitTracelogTree(bool isStart, uint32_t textId)
if (!patchableTraceLoggers_.append(patchLocation))
return false;
Address enabledAddress(logger, TraceLoggerThread::offsetOfEnabled());
Address enabledAddress(logger, TraceLogger::offsetOfEnabled());
masm.branch32(Assembler::Equal, enabledAddress, Imm32(0), &done);
if (isStart)
masm.tracelogStartId(logger, textId);
else
masm.tracelogStopId(logger, textId);
if (isStart) {
masm.tracelogStart(logger, textId);
} else {
#ifdef DEBUG
masm.tracelogStop(logger, textId);
#else
masm.tracelogStop(logger);
#endif
}
masm.bind(&done);

Просмотреть файл

@ -58,7 +58,7 @@ CodeGeneratorX86Shared::generateEpilogue()
#ifdef JS_TRACE_LOGGING
if (gen->info().executionMode() == SequentialExecution) {
if (!emitTracelogStopEvent(TraceLogger_IonMonkey))
if (!emitTracelogStopEvent(TraceLogger::IonMonkey))
return false;
if (!emitTracelogScriptStop())
return false;

Просмотреть файл

@ -3605,7 +3605,7 @@ GCHelperState::work()
MOZ_ASSERT(!thread);
thread = PR_GetCurrentThread();
TraceLoggerThread *logger = TraceLoggerForCurrentThread();
TraceLogger *logger = TraceLoggerForCurrentThread();
switch (state()) {
@ -3614,7 +3614,7 @@ GCHelperState::work()
break;
case SWEEPING: {
AutoTraceLog logSweeping(logger, TraceLogger_GCSweeping);
AutoTraceLog logSweeping(logger, TraceLogger::GCSweeping);
doSweep(lock);
MOZ_ASSERT(state() == SWEEPING);
break;
@ -3638,8 +3638,8 @@ BackgroundAllocTask::BackgroundAllocTask(JSRuntime *rt, ChunkPool &pool)
/* virtual */ void
BackgroundAllocTask::run()
{
TraceLoggerThread *logger = TraceLoggerForCurrentThread();
AutoTraceLog logAllocation(logger, TraceLogger_GCAllocation);
TraceLogger *logger = TraceLoggerForCurrentThread();
AutoTraceLog logAllocation(logger, TraceLogger::GCAllocation);
AutoLockGC lock(runtime);
while (!cancel_ && runtime->gc.wantBackgroundAllocation(lock)) {
@ -6249,8 +6249,8 @@ GCRuntime::collect(bool incremental, SliceBudget &budget, JSGCInvocationKind gck
if (rt->mainThread.suppressGC)
return;
TraceLoggerThread *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logGC(logger, TraceLogger_GC);
TraceLogger *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logGC(logger, TraceLogger::GC);
#ifdef JS_GC_ZEAL
if (deterministicOnly && !IsDeterministicGCReason(reason))
@ -6456,8 +6456,8 @@ GCRuntime::minorGC(JS::gcreason::Reason reason)
{
#ifdef JSGC_GENERATIONAL
minorGCRequested = false;
TraceLoggerThread *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logMinorGC(logger, TraceLogger_MinorGC);
TraceLogger *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
nursery.collect(rt, reason, nullptr);
MOZ_ASSERT_IF(!rt->mainThread.suppressGC, nursery.isEmpty());
#endif
@ -6470,8 +6470,8 @@ GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason)
// objects as needing pretenuring.
#ifdef JSGC_GENERATIONAL
minorGCRequested = false;
TraceLoggerThread *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logMinorGC(logger, TraceLogger_MinorGC);
TraceLogger *logger = TraceLoggerForMainThread(rt);
AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC);
Nursery::TypeObjectList pretenureTypes;
nursery.collect(rt, reason, &pretenureTypes);
for (size_t i = 0; i < pretenureTypes.length(); i++) {

Просмотреть файл

@ -5126,10 +5126,6 @@ template size_t
js::PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, const Latin1Char *chars,
size_t length, uint32_t quote);
template size_t
js::PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, const char *chars,
size_t length, uint32_t quote);
template size_t
js::PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp, const char16_t *chars,
size_t length, uint32_t quote);

Просмотреть файл

@ -400,12 +400,6 @@ FileEscapedString(FILE *fp, JSLinearString *str, uint32_t quote)
return PutEscapedStringImpl(nullptr, 0, fp, str, quote) != size_t(-1);
}
inline bool
FileEscapedString(FILE *fp, const char *chars, size_t length, uint32_t quote)
{
return PutEscapedStringImpl(nullptr, 0, fp, chars, length, quote) != size_t(-1);
}
bool
str_match(JSContext *cx, unsigned argc, Value *vp);

Просмотреть файл

@ -312,8 +312,6 @@ if CONFIG['MOZ_INSTRUMENTS']:
if CONFIG['ENABLE_TRACE_LOGGING']:
SOURCES += [
'vm/TraceLogging.cpp',
'vm/TraceLoggingGraph.cpp',
'vm/TraceLoggingTypes.cpp',
]
if not CONFIG['ENABLE_ION']:

Просмотреть файл

@ -26,7 +26,6 @@
#include "vm/ArgumentsObject.h"
#include "vm/DebuggerMemory.h"
#include "vm/SPSProfiler.h"
#include "vm/TraceLogging.h"
#include "vm/WrapperObject.h"
#include "jsgcinlines.h"
@ -45,6 +44,7 @@ using js::frontend::IsIdentifier;
using mozilla::ArrayLength;
using mozilla::Maybe;
/*** Forward declarations ************************************************************************/
extern const Class DebuggerFrame_class;
@ -359,13 +359,7 @@ Debugger::Debugger(JSContext *cx, NativeObject *dbg)
scripts(cx),
sources(cx),
objects(cx),
environments(cx),
#ifdef NIGHTLY_BUILD
traceLoggerLastDrainedId(0),
traceLoggerLastDrainedIteration(0),
#endif
traceLoggerScriptedCallsLastDrainedId(0),
traceLoggerScriptedCallsLastDrainedIteration(0)
environments(cx)
{
assertSameCompartment(cx, dbg);
@ -3776,253 +3770,6 @@ Debugger::makeGlobalObjectReference(JSContext *cx, unsigned argc, Value *vp)
return dbg->wrapDebuggeeValue(cx, args.rval());
}
static bool
DefineProperty(JSContext *cx, HandleObject obj, HandleId id, const char *value, size_t n)
{
JSString *text = JS_NewStringCopyN(cx, value, n);
if (!text)
return false;
RootedValue str(cx, StringValue(text));
return JS_DefinePropertyById(cx, obj, id, str, JSPROP_ENUMERATE);
}
#ifdef JS_TRACE_LOGGING
# ifdef NIGHTLY_BUILD
bool
Debugger::setupTraceLogger(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "setupTraceLogger", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.setupTraceLogger", 1))
return false;
RootedObject obj(cx, ToObject(cx, args[0]));
if (!obj)
return false;
AutoIdVector ids(cx);
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &ids))
return false;
if (ids.length() == 0) {
args.rval().setBoolean(true);
return true;
}
Vector<uint32_t> textIds(cx);
if (!textIds.reserve(ids.length()))
return false;
Vector<bool> values(cx);
if (!values.reserve(ids.length()))
return false;
for (size_t i = 0; i < ids.length(); i++) {
if (!JSID_IS_STRING(ids[i])) {
args.rval().setBoolean(false);
return true;
}
JSString *id = JSID_TO_STRING(ids[i]);
JSLinearString *linear = id->ensureLinear(cx);
if (!linear)
return false;
uint32_t textId = TLStringToTextId(linear);
if (!TLTextIdIsToggable(textId)) {
args.rval().setBoolean(false);
return true;
}
RootedValue v(cx);
if (!JSObject::getGeneric(cx, obj, obj, ids[i], &v))
return false;
textIds.append(textId);
values.append(ToBoolean(v));
}
MOZ_ASSERT(ids.length() == textIds.length());
MOZ_ASSERT(textIds.length() == values.length());
for (size_t i = 0; i < textIds.length(); i++) {
if (values[i])
TraceLogEnableTextId(cx, textIds[i]);
else
TraceLogDisableTextId(cx, textIds[i]);
}
args.rval().setBoolean(true);
return true;
}
bool
Debugger::drainTraceLogger(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "drainTraceLogger", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.drainTraceLogger", 0))
return false;
size_t num;
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
bool lostEvents = logger->lostEvents(dbg->traceLoggerLastDrainedIteration,
dbg->traceLoggerLastDrainedId);
EventEntry *events = logger->getEventsStartingAt(&dbg->traceLoggerLastDrainedIteration,
&dbg->traceLoggerLastDrainedId,
&num);
RootedObject array(cx, NewDenseEmptyArray(cx));
JSAtom *dataAtom = Atomize(cx, "data", strlen("data"));
if (!dataAtom)
return false;
RootedId dataId(cx, AtomToId(dataAtom));
/* Add all events to the array. */
uint32_t index = 0;
for (EventEntry *eventItem = events; eventItem < events + num; eventItem++, index++) {
RootedObject item(cx, NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, cx->global()));
if (!item)
return false;
const char *eventText = logger->eventText(eventItem->textId);
if (!DefineProperty(cx, item, dataId, eventText, strlen(eventText)))
return false;
RootedValue obj(cx, ObjectValue(*item));
if (!JS_DefineElement(cx, array, index, obj, JSPROP_ENUMERATE))
return false;
}
/* Add "lostEvents" indicating if there are events that were lost. */
RootedValue lost(cx, BooleanValue(lostEvents));
if (!JS_DefineProperty(cx, array, "lostEvents", lost, JSPROP_ENUMERATE))
return false;
args.rval().setObject(*array);
return true;
}
# endif // NIGHTLY_BUILD
bool
Debugger::setupTraceLoggerScriptCalls(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "setupTraceLoggerScriptCalls", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.setupTraceLoggerScriptCalls", 0))
return false;
TraceLogEnableTextId(cx, TraceLogger_Scripts);
TraceLogEnableTextId(cx, TraceLogger_InlinedScripts);
TraceLogDisableTextId(cx, TraceLogger_AnnotateScripts);
args.rval().setBoolean(true);
return true;
}
bool
Debugger::startTraceLogger(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "startTraceLogger", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.startTraceLogger", 0))
return false;
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEnable(logger, cx);
args.rval().setUndefined();
return true;
}
bool
Debugger::endTraceLogger(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "endTraceLogger", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.endTraceLogger", 0))
return false;
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerDisable(logger);
args.rval().setUndefined();
return true;
}
bool
Debugger::drainTraceLoggerScriptCalls(JSContext *cx, unsigned argc, Value *vp)
{
THIS_DEBUGGER(cx, argc, vp, "drainTraceLoggerScriptCalls", args, dbg);
if (!args.requireAtLeast(cx, "Debugger.drainTraceLoggerScriptCalls", 0))
return false;
size_t num;
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
bool lostEvents = logger->lostEvents(dbg->traceLoggerScriptedCallsLastDrainedIteration,
dbg->traceLoggerScriptedCallsLastDrainedId);
EventEntry *events = logger->getEventsStartingAt(
&dbg->traceLoggerScriptedCallsLastDrainedIteration,
&dbg->traceLoggerScriptedCallsLastDrainedId,
&num);
RootedObject array(cx, NewDenseEmptyArray(cx));
RootedId fileNameId(cx, AtomToId(cx->names().fileName));
RootedId lineNumberId(cx, AtomToId(cx->names().lineNumber));
RootedId columnNumberId(cx, AtomToId(cx->names().columnNumber));
JSAtom *logTypeAtom = Atomize(cx, "logType", strlen("logType"));
if (!logTypeAtom)
return false;
RootedId logTypeId(cx, AtomToId(logTypeAtom));
/* Add all events to the array. */
uint32_t index = 0;
for (EventEntry *eventItem = events; eventItem < events + num; eventItem++) {
RootedObject item(cx, NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, cx->global()));
if (!item)
return false;
uint32_t textId = eventItem->textId;
if (textId != TraceLogger_Stop && !logger->textIdIsScriptEvent(textId))
continue;
const char *type = (textId == TraceLogger_Stop) ? "Stop" : "Script";
if (!DefineProperty(cx, item, logTypeId, type, strlen(type)))
return false;
if (textId != TraceLogger_Stop) {
const char *filename, *lineno, *colno;
size_t filename_len, lineno_len, colno_len;
logger->extractScriptDetails(textId, &filename, &filename_len, &lineno, &lineno_len,
&colno, &colno_len);
if (!DefineProperty(cx, item, fileNameId, filename, filename_len))
return false;
if (!DefineProperty(cx, item, lineNumberId, lineno, lineno_len))
return false;
if (!DefineProperty(cx, item, columnNumberId, colno, colno_len))
return false;
}
RootedValue obj(cx, ObjectValue(*item));
if (!JS_DefineElement(cx, array, index, obj, JSPROP_ENUMERATE))
return false;
index++;
}
/* Add "lostEvents" indicating if there are events that were lost. */
RootedValue lost(cx, BooleanValue(lostEvents));
if (!JS_DefineProperty(cx, array, "lostEvents", lost, JSPROP_ENUMERATE))
return false;
args.rval().setObject(*array);
return true;
}
#endif
const JSPropertySpec Debugger::properties[] = {
JS_PSGS("enabled", Debugger::getEnabled, Debugger::setEnabled, 0),
JS_PSGS("onDebuggerStatement", Debugger::getOnDebuggerStatement,
@ -4052,16 +3799,6 @@ 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),
#ifdef JS_TRACE_LOGGING
JS_FN("setupTraceLoggerScriptCalls", Debugger::setupTraceLoggerScriptCalls, 0, 0),
JS_FN("drainTraceLoggerScriptCalls", Debugger::drainTraceLoggerScriptCalls, 0, 0),
JS_FN("startTraceLogger", Debugger::startTraceLogger, 0, 0),
JS_FN("endTraceLogger", Debugger::endTraceLogger, 0, 0),
# ifdef NIGHTLY_BUILD
JS_FN("setupTraceLogger", Debugger::setupTraceLogger, 1, 0),
JS_FN("drainTraceLogger", Debugger::drainTraceLogger, 0, 0),
# endif
#endif
JS_FS_END
};

Просмотреть файл

@ -296,17 +296,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
/* The map from debuggee Envs to Debugger.Environment instances. */
ObjectWeakMap environments;
/*
* Keep track of tracelogger last drained identifiers to know if there are
* lost events.
*/
#ifdef NIGHTLY_BUILD
uint32_t traceLoggerLastDrainedId;
uint32_t traceLoggerLastDrainedIteration;
#endif
uint32_t traceLoggerScriptedCallsLastDrainedId;
uint32_t traceLoggerScriptedCallsLastDrainedIteration;
class FrameRange;
class ScriptQuery;
class ObjectQuery;
@ -405,14 +394,6 @@ 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 setupTraceLoggerScriptCalls(JSContext *cx, unsigned argc, Value *vp);
static bool drainTraceLoggerScriptCalls(JSContext *cx, unsigned argc, Value *vp);
static bool startTraceLogger(JSContext *cx, unsigned argc, Value *vp);
static bool endTraceLogger(JSContext *cx, unsigned argc, Value *vp);
#ifdef NIGHTLY_BUILD
static bool setupTraceLogger(JSContext *cx, unsigned argc, Value *vp);
static bool drainTraceLogger(JSContext *cx, unsigned argc, Value *vp);
#endif
static bool construct(JSContext *cx, unsigned argc, Value *vp);
static const JSPropertySpec properties[];
static const JSFunctionSpec methods[];

Просмотреть файл

@ -1047,10 +1047,9 @@ HelperThread::handleIonWorkload()
ionBuilder = builder;
ionBuilder->setPauseFlag(&pause);
TraceLoggerThread *logger = TraceLoggerForCurrentThread();
TraceLoggerEvent event(logger, TraceLogger_AnnotateScripts, ionBuilder->script());
AutoTraceLog logScript(logger, event);
AutoTraceLog logCompile(logger, TraceLogger_IonCompilation);
TraceLogger *logger = TraceLoggerForCurrentThread();
AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, ionBuilder->script()));
AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
JSRuntime *rt = ionBuilder->script()->compartment()->runtimeFromAnyThread();
@ -1118,8 +1117,8 @@ CurrentHelperThread()
void
js::PauseCurrentHelperThread()
{
TraceLoggerThread *logger = TraceLoggerForCurrentThread();
AutoTraceLog logPaused(logger, TraceLogger_IonCompilationPaused);
TraceLogger *logger = TraceLoggerForCurrentThread();
AutoTraceLog logPaused(logger, TraceLogger::IonCompilationPaused);
HelperThread *thread = CurrentHelperThread();

Просмотреть файл

@ -1462,10 +1462,10 @@ Interpret(JSContext *cx, RunState &state)
RootedScript script(cx);
SET_SCRIPT(REGS.fp()->script());
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLoggerEvent scriptEvent(logger, TraceLogger_Scripts, script);
TraceLogStartEvent(logger, scriptEvent);
TraceLogStartEvent(logger, TraceLogger_Interpreter);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
uint32_t scriptLogId = TraceLogCreateTextId(logger, script);
TraceLogStartEvent(logger, scriptLogId);
TraceLogStartEvent(logger, TraceLogger::Interpreter);
/*
* Pool of rooters for use in this interpreter frame. References to these
@ -1763,8 +1763,9 @@ CASE(JSOP_RETRVAL)
if (activation.entryFrame() != REGS.fp()) {
// Stop the engine. (No details about which engine exactly, could be
// interpreter, Baseline or IonMonkey.)
TraceLogStopEvent(logger, TraceLogger_Engine);
TraceLogStopEvent(logger, TraceLogger_Scripts);
TraceLogStopEvent(logger);
// Stop the script. (Again no details about which script exactly.)
TraceLogStopEvent(logger);
interpReturnOK = Debugger::onLeaveFrame(cx, REGS.fp(), interpReturnOK);
@ -2577,11 +2578,9 @@ CASE(JSOP_FUNCALL)
SET_SCRIPT(REGS.fp()->script());
{
TraceLoggerEvent event(logger, TraceLogger_Scripts, script);
TraceLogStartEvent(logger, event);
TraceLogStartEvent(logger, TraceLogger_Interpreter);
}
uint32_t scriptLogId = TraceLogCreateTextId(logger, script);
TraceLogStartEvent(logger, scriptLogId);
TraceLogStartEvent(logger, TraceLogger::Interpreter);
if (!REGS.fp()->prologue(cx))
goto error;
@ -3493,8 +3492,8 @@ DEFAULT()
gc::MaybeVerifyBarriers(cx, true);
TraceLogStopEvent(logger, TraceLogger_Engine);
TraceLogStopEvent(logger, scriptEvent);
TraceLogStopEvent(logger);
TraceLogStopEvent(logger, scriptLogId);
/*
* This path is used when it's guaranteed the method can be finished

Просмотреть файл

@ -458,8 +458,8 @@ bool
RegExpShared::compile(JSContext *cx, HandleLinearString input,
CompilationMode mode, ForceByteCodeEnum force)
{
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logCompile(logger, TraceLogger_IrregexpCompile);
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
AutoTraceLog logCompile(logger, TraceLogger::IrregexpCompile);
if (!sticky()) {
RootedAtom pattern(cx, source);
@ -548,7 +548,7 @@ RegExpRunStatus
RegExpShared::execute(JSContext *cx, HandleLinearString input, size_t start,
MatchPairs *matches)
{
TraceLoggerThread *logger = TraceLoggerForMainThread(cx->runtime());
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
CompilationMode mode = matches ? Normal : MatchOnly;
@ -604,7 +604,7 @@ RegExpShared::execute(JSContext *cx, HandleLinearString input, size_t start,
RegExpRunStatus result;
{
AutoTraceLog logJIT(logger, TraceLogger_IrregexpExecute);
AutoTraceLog logJIT(logger, TraceLogger::IrregexpExecute);
AutoCheckCannotGC nogc;
if (input->hasLatin1Chars()) {
const Latin1Char *chars = input->latin1Chars(nogc) + charsOffset;
@ -643,7 +643,7 @@ RegExpShared::execute(JSContext *cx, HandleLinearString input, size_t start,
return RegExpRunStatus_Error;
uint8_t *byteCode = compilation(mode, input->hasLatin1Chars()).byteCode;
AutoTraceLog logInterpreter(logger, TraceLogger_IrregexpExecute);
AutoTraceLog logInterpreter(logger, TraceLogger::IrregexpExecute);
AutoStableStringChars inputChars(cx);
if (!inputChars.init(cx, input))

Просмотреть файл

@ -54,7 +54,7 @@ class PerThreadData;
struct ThreadSafeContext;
class AutoKeepAtoms;
#ifdef JS_TRACE_LOGGING
class TraceLoggerThread;
class TraceLogger;
#endif
/* Thread Local Storage slot for storing the runtime for a thread. */
@ -537,7 +537,7 @@ class PerThreadData : public PerThreadDataFriendFields
irregexp::RegExpStack regexpStack;
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *traceLogger;
TraceLogger *traceLogger;
#endif
private:

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -8,7 +8,6 @@
#define TraceLogging_h
#include "mozilla/GuardObjects.h"
#include "mozilla/UniquePtr.h"
#include "jsalloc.h"
#include "jslock.h"
@ -16,8 +15,6 @@
#include "js/HashTable.h"
#include "js/TypeDecls.h"
#include "js/Vector.h"
#include "vm/TraceLoggingGraph.h"
#include "vm/TraceLoggingTypes.h"
struct JSRuntime;
@ -35,315 +32,513 @@ namespace jit {
/*
* Tracelogging overview.
*
* Tracelogging makes it possible to trace the occurence of a single event and/or
* the start and stop of an event. This is implemented to give an as low overhead as
* Tracelogging makes it possible to trace the timestamp of a single event and/or
* the duration of an event. This is implemented to give an as low overhead as
* possible so it doesn't interfere with running.
*
* The output of a tracelogging session is saved in /tmp/tl-data.json.
* The format of that file is a JS array per tracelogger (=thread), with a map
* containing:
* - dict: Name of the file containing a json table with the log text.
* All other files only contain a index to this table when logging.
* - events: Name of the file containing a flat list of log events saved
* in binary format.
* (64bit: Time Stamp Counter, 32bit index to dict)
* - tree: Name of the file containing the events with duration. The content
* is already in a tree data structure. This is also saved in a
* binary file.
* - treeFormat: The format used to encode the tree. By default "64,64,31,1,32".
* There are currently no other formats to save the tree.
* - 64,64,31,1,31 signifies how many bytes are used for the different
* parts of the tree.
* => 64 bits: Time Stamp Counter of start of event.
* => 64 bits: Time Stamp Counter of end of event.
* => 31 bits: Index to dict file containing the log text.
* => 1 bit: Boolean signifying if this entry has children.
* When true, the child can be found just behind this entry.
* => 32 bits: Containing the ID of the next event on the same depth
* or 0 if there isn't an event on the same depth anymore.
*
* /-> The position in the file. Id is this divided by size of entry.
* | So in this case this would be 1 (192bits per entry).
* | /-> Indicates there are children. The
* | | first child is located at current
* | | ID + 1. So 1 + 1 in this case: 2.
* | | Or 0x00180 in the tree file.
* | | /-> Next event on the same depth is
* | | | located at 4. So 0x00300 in the
* | | | tree file.
* 0x0000C0: [start, end, dictId, 1, 4]
*
*
* Example:
* 0x0: [start, end, dictId, 1, 0]
* |
* /----------------------------------\
* | |
* 0xC0: [start, end, dictId, 0, 2] 0x180 [start, end, dictId, 1, 0]
* |
* /----------------------------------\
* | |
* 0x240: [start, end, dictId, 0, 4] 0x300 [start, end, dictId, 0, 0]
*
*
* Logging something is done in 3 stages.
* 1) Get the tracelogger of the current thread.
* - TraceLoggerForMainThread(JSRuntime *)
* - TraceLoggerForCurrentThread(); // Should NOT be used for the mainthread.
*
* 2) Optionally create a TraceLoggerEvent for the text that needs to get logged. This
* 2) Optionally create a textId for the text that needs to get logged. This
* step takes some time, so try to do this beforehand, outside the hot
* path and don't do unnecessary repetitions, since it will criple
* performance.
* - TraceLoggerEvent event(logger, "foo");
* - TraceLogCreateTextId(logger, ...);
*
* There are also some predefined events. They are located in
* TraceLoggerTextId. They don't require to create an TraceLoggerEvent and
* can also be used as an argument to these functions.
* 3) Log the occurence of a single event:
* - TraceLogTimestamp(logger, TraceLoggerTextId);
* Note: it is temporarily not supported to provide an TraceLoggerEvent as
* argument to log the occurence of a single event.
* There are also some text IDs created beforehand. They are located in
* Tracelogger::TextId.
* 3) Log the timestamp of an event:
* - TraceLogTimestamp(logger, textId);
*
* or log the start and stop of an event:
* - TraceLogStartEvent(logger, TraceLoggerTextId);
* - TraceLogStartEvent(logger, TraceLoggerEvent);
* - TraceLogStopEvent(logger, TraceLoggerTextId);
* - TraceLogStopEvent(logger, TraceLoggerEvent);
* or the duration:
* - TraceLogStartEvent(logger, textId);
* - TraceLogStopEvent(logger, textId);
*
* or the start/stop of an event with a RAII class:
* - AutoTraceLog logger(logger, TraceLoggerTextId);
* - AutoTraceLog logger(logger, TraceLoggerEvent);
* or the duration with a RAII class:
* - AutoTraceLog logger(logger, textId);
*/
#define TRACELOGGER_TEXT_ID_LIST(_) \
_(Bailout) \
_(Baseline) \
_(BaselineCompilation) \
_(GC) \
_(GCAllocation) \
_(GCSweeping) \
_(Interpreter) \
_(Invalidation) \
_(IonCompilation) \
_(IonCompilationPaused) \
_(IonLinking) \
_(IonMonkey) \
_(MinorGC) \
_(ParserCompileFunction) \
_(ParserCompileLazy) \
_(ParserCompileScript) \
_(TL) \
_(IrregexpCompile) \
_(IrregexpExecute) \
_(VM) \
\
/* Specific passes during ion compilation */ \
_(FoldTests) \
_(SplitCriticalEdges) \
_(RenumberBlocks) \
_(ScalarReplacement) \
_(DominatorTree) \
_(PhiAnalysis) \
_(MakeLoopsContiguous) \
_(ApplyTypes) \
_(ParallelSafetyAnalysis) \
_(AliasAnalysis) \
_(GVN) \
_(LICM) \
_(RangeAnalysis) \
_(LoopUnrolling) \
_(EffectiveAddressAnalysis) \
_(EliminateDeadCode) \
_(EdgeCaseAnalysis) \
_(EliminateRedundantChecks) \
_(GenerateLIR) \
_(RegisterAllocation) \
_(GenerateCode) \
class AutoTraceLog;
class TraceLoggerEventPayload;
class TraceLoggerThread;
/**
* An event that can be used to report start/stop events to TraceLogger.
* It prepares the given info, by requesting a TraceLoggerEventPayload for the
* given info. (Which contains the string that needs to get reported and an
* unique id). It also increases the useCount of this payload, so it cannot
* get removed.
*/
class TraceLoggerEvent {
private:
TraceLoggerEventPayload *payload_;
template <class T>
class ContinuousSpace {
T *data_;
uint32_t size_;
uint32_t capacity_;
public:
TraceLoggerEvent() { payload_ = nullptr; };
#ifdef JS_TRACE_LOGGING
TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId textId);
TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId type, JSScript *script);
TraceLoggerEvent(TraceLoggerThread *logger, TraceLoggerTextId type,
const JS::ReadOnlyCompileOptions &compileOptions);
TraceLoggerEvent(TraceLoggerThread *logger, const char *text);
~TraceLoggerEvent();
#else
TraceLoggerEvent (TraceLoggerThread *logger, TraceLoggerTextId textId) {}
TraceLoggerEvent (TraceLoggerThread *logger, TraceLoggerTextId type, JSScript *script) {}
TraceLoggerEvent (TraceLoggerThread *logger, TraceLoggerTextId type,
const JS::ReadOnlyCompileOptions &compileOptions) {}
TraceLoggerEvent (TraceLoggerThread *logger, const char *text) {}
~TraceLoggerEvent() {}
#endif
TraceLoggerEventPayload *payload() const {
MOZ_ASSERT(hasPayload());
return payload_;
}
bool hasPayload() const {
return !!payload_;
}
};
/**
* An internal class holding the to-report string information, together with an
* unique id and a useCount. Whenever this useCount reaches 0, this event
* cannot get started/stopped anymore. Though consumers might still request the
* to-report string information.
*/
class TraceLoggerEventPayload {
uint32_t textId_;
mozilla::UniquePtr<char, JS::FreePolicy> string_;
uint32_t uses_;
public:
TraceLoggerEventPayload(uint32_t textId, char *string)
: textId_(textId),
string_(string),
uses_(0)
ContinuousSpace ()
: data_(nullptr)
{ }
uint32_t textId() {
return textId_;
bool init() {
capacity_ = 64;
size_ = 0;
data_ = (T *) js_malloc(capacity_ * sizeof(T));
if (!data_)
return false;
return true;
}
const char *string() {
return string_.get();
T *data() {
return data_;
}
uint32_t uses() {
return uses_;
uint32_t capacity() {
return capacity_;
}
void use() {
uses_++;
uint32_t size() {
return size_;
}
void release() {
uses_--;
bool empty() {
return size_ == 0;
}
uint32_t lastEntryId() {
MOZ_ASSERT(!empty());
return size_ - 1;
}
T &lastEntry() {
return data()[lastEntryId()];
}
bool hasSpaceForAdd(uint32_t count = 1) {
if (size_ + count <= capacity_)
return true;
return false;
}
bool ensureSpaceBeforeAdd(uint32_t count = 1) {
if (hasSpaceForAdd(count))
return true;
uint32_t nCapacity = capacity_ * 2;
if (size_ + count > nCapacity)
nCapacity = size_ + count;
T *entries = (T *) js_realloc(data_, nCapacity * sizeof(T));
if (!entries)
return false;
data_ = entries;
capacity_ = nCapacity;
return true;
}
T &operator[](size_t i) {
MOZ_ASSERT(i < size_);
return data()[i];
}
void push(T &data) {
MOZ_ASSERT(size_ < capacity_);
data()[size_++] = data;
}
T &pushUninitialized() {
MOZ_ASSERT(size_ < capacity_);
return data()[size_++];
}
void pop() {
MOZ_ASSERT(!empty());
size_--;
}
void clear() {
size_ = 0;
}
};
class TraceLoggerThread
class TraceLogger
{
public:
// Predefined IDs for common operations. These IDs can be used
// without using TraceLogCreateTextId, because there are already created.
enum TextId {
TL_Error = 0,
# define DEFINE_TEXT_ID(textId) textId,
TRACELOGGER_TEXT_ID_LIST(DEFINE_TEXT_ID)
# undef DEFINE_TEXT_ID
LAST
};
#ifdef JS_TRACE_LOGGING
private:
typedef HashMap<const void *,
TraceLoggerEventPayload *,
uint32_t,
PointerHasher<const void *, 3>,
SystemAllocPolicy> PointerHashMap;
typedef HashMap<uint32_t,
TraceLoggerEventPayload *,
DefaultHasher<uint32_t>,
SystemAllocPolicy> TextIdHashMap;
// The layout of the tree in memory and in the log file. Readable by JS
// using TypedArrays.
struct TreeEntry {
uint64_t start_;
uint64_t stop_;
union {
struct {
uint32_t textId_: 31;
uint32_t hasChildren_: 1;
} s;
uint32_t value_;
} u;
uint32_t nextId_;
TreeEntry(uint64_t start, uint64_t stop, uint32_t textId, bool hasChildren,
uint32_t nextId)
{
start_ = start;
stop_ = stop;
u.s.textId_ = textId;
u.s.hasChildren_ = hasChildren;
nextId_ = nextId;
}
TreeEntry()
{ }
uint64_t start() {
return start_;
}
uint64_t stop() {
return stop_;
}
uint32_t textId() {
return u.s.textId_;
}
bool hasChildren() {
return u.s.hasChildren_;
}
uint32_t nextId() {
return nextId_;
}
void setStart(uint64_t start) {
start_ = start;
}
void setStop(uint64_t stop) {
stop_ = stop;
}
void setTextId(uint32_t textId) {
MOZ_ASSERT(textId < uint32_t(1<<31) );
u.s.textId_ = textId;
}
void setHasChildren(bool hasChildren) {
u.s.hasChildren_ = hasChildren;
}
void setNextId(uint32_t nextId) {
nextId_ = nextId;
}
};
// Helper structure for keeping track of the current entries in
// the tree. Pushed by `start(id)`, popped by `stop(id)`. The active flag
// is used to know if a subtree doesn't need to get logged.
struct StackEntry {
uint32_t treeId_;
uint32_t lastChildId_;
struct {
uint32_t textId_: 31;
uint32_t active_: 1;
} s;
StackEntry(uint32_t treeId, uint32_t lastChildId, bool active = true)
: treeId_(treeId), lastChildId_(lastChildId)
{
s.textId_ = 0;
s.active_ = active;
}
uint32_t treeId() {
return treeId_;
}
uint32_t lastChildId() {
return lastChildId_;
}
uint32_t textId() {
return s.textId_;
}
bool active() {
return s.active_;
}
void setTreeId(uint32_t treeId) {
treeId_ = treeId;
}
void setLastChildId(uint32_t lastChildId) {
lastChildId_ = lastChildId;
}
void setTextId(uint32_t textId) {
MOZ_ASSERT(textId < uint32_t(1<<31) );
s.textId_ = textId;
}
void setActive(bool active) {
s.active_ = active;
}
};
// The layout of the event log in memory and in the log file.
// Readable by JS using TypedArrays.
struct EventEntry {
uint64_t time;
uint32_t textId;
EventEntry(uint64_t time, uint32_t textId)
: time(time), textId(textId)
{ }
};
FILE *dictFile;
FILE *treeFile;
FILE *eventFile;
uint32_t enabled;
bool failed;
mozilla::UniquePtr<TraceLoggerGraph> graph;
uint32_t nextTextId;
PointerHashMap pointerMap;
TextIdHashMap extraTextId;
ContinuousSpace<TreeEntry> tree;
ContinuousSpace<StackEntry> stack;
ContinuousSpace<EventEntry> events;
// Every time the events get flushed, this count is increased by one.
// This together with events.lastEntryId(), gives an unique position.
uint32_t iteration_;
uint32_t treeOffset;
public:
AutoTraceLog *top;
TraceLoggerThread();
bool init();
~TraceLoggerThread();
private:
// Helper functions that convert a TreeEntry in different endianness
// in place.
void entryToBigEndian(TreeEntry *entry);
void entryToSystemEndian(TreeEntry *entry);
// Helper functions to get/save a tree from file.
bool getTreeEntry(uint32_t treeId, TreeEntry *entry);
bool saveTreeEntry(uint32_t treeId, TreeEntry *entry);
// Return the first StackEntry that is active.
StackEntry &getActiveAncestor();
// This contains the meat of startEvent, except the test for enough space,
// the test if tracelogger is enabled and the timestamp computation.
bool startEvent(uint32_t id, uint64_t timestamp);
// Update functions that can adjust the items in the tree,
// both in memory or already written to disk.
bool updateHasChildren(uint32_t treeId, bool hasChildren = true);
bool updateNextId(uint32_t treeId, uint32_t nextId);
bool updateStop(uint32_t treeId, uint64_t timestamp);
// Flush the tree and events.
bool flush();
public:
TraceLogger();
~TraceLogger();
bool init(uint32_t loggerId);
void initGraph();
bool enable();
bool enable(JSContext *cx);
bool disable();
// Given the previous iteration and lastEntryId, return an array of events
// (there could be lost events). At the same time update the iteration and
// lastEntry and gives back how many events there are.
EventEntry *getEventsStartingAt(uint32_t *lastIteration, uint32_t *lastEntryId, size_t *num) {
EventEntry *start;
if (iteration_ == *lastIteration) {
MOZ_ASSERT(events.lastEntryId() >= *lastEntryId);
*num = events.lastEntryId() - *lastEntryId;
start = events.data() + *lastEntryId + 1;
} else {
*num = events.lastEntryId() + 1;
start = events.data();
}
*lastIteration = iteration_;
*lastEntryId = events.lastEntryId();
return start;
}
// Extract the details filename, lineNumber and columnNumber out of a event
// containing script information.
void extractScriptDetails(uint32_t textId, const char **filename, size_t *filename_len,
const char **lineno, size_t *lineno_len, const char **colno,
size_t *colno_len);
bool lostEvents(uint32_t lastIteration, uint32_t lastEntryId) {
// If still logging in the same iteration, there are no lost events.
if (lastIteration == iteration_) {
MOZ_ASSERT(lastEntryId <= events.lastEntryId());
return false;
}
// When proceeded to the next iteration and lastEntryId points to
// the maximum capacity there are no logs that are lost.
if (lastIteration + 1 == iteration_ && lastEntryId == events.capacity())
return false;
return true;
}
const char *eventText(uint32_t id);
bool textIdIsScriptEvent(uint32_t id);
// The createTextId functions map a unique input to a logger ID.
// This can be used to give start and stop events. Calls to these functions should be
// This ID can be used to log something. Calls to these functions should be
// limited if possible, because of the overhead.
// Note: it is not allowed to use them in logTimestamp.
TraceLoggerEventPayload *getOrCreateEventPayload(TraceLoggerTextId textId);
TraceLoggerEventPayload *getOrCreateEventPayload(const char *text);
TraceLoggerEventPayload *getOrCreateEventPayload(TraceLoggerTextId type, JSScript *script);
TraceLoggerEventPayload *getOrCreateEventPayload(TraceLoggerTextId type,
const JS::ReadOnlyCompileOptions &script);
private:
TraceLoggerEventPayload *getOrCreateEventPayload(TraceLoggerTextId type, const char *filename,
size_t lineno, size_t colno, const void *p);
uint32_t createTextId(const char *text);
uint32_t createTextId(JSScript *script);
uint32_t createTextId(const JS::ReadOnlyCompileOptions &script);
public:
// Log an event (no start/stop, only the timestamp is recorded).
void logTimestamp(TraceLoggerTextId id);
void logTimestamp(uint32_t id);
// Record timestamps for start and stop of an event.
void startEvent(TraceLoggerTextId id);
void startEvent(const TraceLoggerEvent &event);
void stopEvent(TraceLoggerTextId id);
void stopEvent(const TraceLoggerEvent &event);
// These functions are actually private and shouldn't be used in normal
// code. They are made public so they can get used in assembly.
void logTimestamp(uint32_t id);
// In the stop method, the ID is only used in debug builds to test
// correctness.
void startEvent(uint32_t id);
void stopEvent(uint32_t id);
private:
void stopEvent();
public:
static unsigned offsetOfEnabled() {
return offsetof(TraceLoggerThread, enabled);
return offsetof(TraceLogger, enabled);
}
private:
void assertNoQuotes(const char *text) {
#ifdef DEBUG
const char *quote = strchr(text, '"');
MOZ_ASSERT(!quote);
#endif
}
#endif
};
class TraceLoggerThreadState
class TraceLogging
{
#ifdef JS_TRACE_LOGGING
typedef HashMap<PRThread *,
TraceLoggerThread *,
TraceLogger *,
PointerHasher<PRThread *, 3>,
SystemAllocPolicy> ThreadLoggerHashMap;
typedef Vector<TraceLoggerThread *, 1, js::SystemAllocPolicy > MainThreadLoggers;
typedef Vector<TraceLogger *, 1, js::SystemAllocPolicy > MainThreadLoggers;
bool initialized;
bool enabled;
bool enabledTextIds[TraceLogger_Last];
bool enabledTextIds[TraceLogger::LAST];
bool mainThreadEnabled;
bool offThreadEnabled;
bool graphSpewingEnabled;
ThreadLoggerHashMap threadLoggers;
MainThreadLoggers mainThreadLoggers;
uint32_t loggerId;
FILE *out;
public:
uint64_t startupTime;
PRLock *lock;
TraceLoggerThreadState();
~TraceLoggerThreadState();
TraceLogging();
~TraceLogging();
TraceLoggerThread *forMainThread(JSRuntime *runtime);
TraceLoggerThread *forMainThread(jit::CompileRuntime *runtime);
TraceLoggerThread *forThread(PRThread *thread);
TraceLogger *forMainThread(JSRuntime *runtime);
TraceLogger *forMainThread(jit::CompileRuntime *runtime);
TraceLogger *forThread(PRThread *thread);
bool isTextIdEnabled(uint32_t textId) {
if (textId < TraceLogger_Last)
if (textId < TraceLogger::LAST)
return enabledTextIds[textId];
return true;
}
void enableTextId(JSContext *cx, uint32_t textId);
void disableTextId(JSContext *cx, uint32_t textId);
private:
TraceLoggerThread *forMainThread(PerThreadData *mainThread);
TraceLoggerThread *create();
TraceLogger *forMainThread(PerThreadData *mainThread);
TraceLogger *create();
bool lazyInit();
#endif
};
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *TraceLoggerForMainThread(JSRuntime *runtime);
TraceLoggerThread *TraceLoggerForMainThread(jit::CompileRuntime *runtime);
TraceLoggerThread *TraceLoggerForCurrentThread();
TraceLogger *TraceLoggerForMainThread(JSRuntime *runtime);
TraceLogger *TraceLoggerForMainThread(jit::CompileRuntime *runtime);
TraceLogger *TraceLoggerForCurrentThread();
#else
inline TraceLoggerThread *TraceLoggerForMainThread(JSRuntime *runtime) {
inline TraceLogger *TraceLoggerForMainThread(JSRuntime *runtime) {
return nullptr;
};
inline TraceLoggerThread *TraceLoggerForMainThread(jit::CompileRuntime *runtime) {
inline TraceLogger *TraceLoggerForMainThread(jit::CompileRuntime *runtime) {
return nullptr;
};
inline TraceLoggerThread *TraceLoggerForCurrentThread() {
inline TraceLogger *TraceLoggerForCurrentThread() {
return nullptr;
};
#endif
inline bool TraceLoggerEnable(TraceLoggerThread *logger) {
inline bool TraceLoggerEnable(TraceLogger *logger) {
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->enable();
#endif
return false;
}
inline bool TraceLoggerEnable(TraceLoggerThread *logger, JSContext *cx) {
inline bool TraceLoggerEnable(TraceLogger *logger, JSContext *cx) {
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->enable(cx);
#endif
return false;
}
inline bool TraceLoggerDisable(TraceLoggerThread *logger) {
inline bool TraceLoggerDisable(TraceLogger *logger) {
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->disable();
@ -351,107 +546,78 @@ inline bool TraceLoggerDisable(TraceLoggerThread *logger) {
return false;
}
inline uint32_t TraceLogCreateTextId(TraceLogger *logger, JSScript *script) {
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->createTextId(script);
#endif
return TraceLogger::TL_Error;
}
inline uint32_t TraceLogCreateTextId(TraceLogger *logger,
const JS::ReadOnlyCompileOptions &compileOptions)
{
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->createTextId(compileOptions);
#endif
return TraceLogger::TL_Error;
}
inline uint32_t TraceLogCreateTextId(TraceLogger *logger, const char *text) {
#ifdef JS_TRACE_LOGGING
if (logger)
return logger->createTextId(text);
#endif
return TraceLogger::TL_Error;
}
#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, TraceLoggerTextId textId) {
inline void TraceLogTimestamp(TraceLogger *logger, uint32_t textId) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->logTimestamp(textId);
#endif
}
inline void TraceLogStartEvent(TraceLoggerThread *logger, TraceLoggerTextId textId) {
inline void TraceLogStartEvent(TraceLogger *logger, uint32_t textId) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->startEvent(textId);
#endif
}
inline void TraceLogStartEvent(TraceLoggerThread *logger, const TraceLoggerEvent &event) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->startEvent(event);
#endif
}
inline void TraceLogStopEvent(TraceLoggerThread *logger, TraceLoggerTextId textId) {
inline void TraceLogStopEvent(TraceLogger *logger, uint32_t textId) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->stopEvent(textId);
#endif
}
inline void TraceLogStopEvent(TraceLoggerThread *logger, const TraceLoggerEvent &event) {
inline void TraceLogStopEvent(TraceLogger *logger) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->stopEvent(event);
#endif
}
// Helper functions for assembly. May not be used otherwise.
inline void TraceLogTimestampPrivate(TraceLoggerThread *logger, uint32_t id) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->logTimestamp(id);
#endif
}
inline void TraceLogStartEventPrivate(TraceLoggerThread *logger, uint32_t id) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->startEvent(id);
#endif
}
inline void TraceLogStopEventPrivate(TraceLoggerThread *logger, uint32_t id) {
#ifdef JS_TRACE_LOGGING
if (logger)
logger->stopEvent(id);
logger->stopEvent();
#endif
}
// Automatic logging at the start and end of function call.
class AutoTraceLog
{
class AutoTraceLog {
#ifdef JS_TRACE_LOGGING
TraceLoggerThread *logger;
union {
const TraceLoggerEvent *event;
TraceLoggerTextId id;
} payload;
bool isEvent;
TraceLogger *logger;
uint32_t textId;
bool executed;
AutoTraceLog *prev;
public:
AutoTraceLog(TraceLoggerThread *logger,
const TraceLoggerEvent &event MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoTraceLog(TraceLogger *logger, uint32_t textId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: logger(logger),
isEvent(true),
textId(textId),
executed(false)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
payload.event = &event;
if (logger) {
logger->startEvent(event);
prev = logger->top;
logger->top = this;
}
}
AutoTraceLog(TraceLoggerThread *logger, TraceLoggerTextId id MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: logger(logger),
isEvent(false),
executed(false)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
payload.id = id;
if (logger) {
logger->startEvent(id);
TraceLogStartEvent(logger, textId);
prev = logger->top;
logger->top = this;
@ -470,10 +636,7 @@ class AutoTraceLog
void stop() {
if (!executed) {
executed = true;
if (isEvent)
logger->stopEvent(*payload.event);
else
logger->stopEvent(payload.id);
TraceLogStopEvent(logger, textId);
}
if (logger->top == this)
@ -481,12 +644,7 @@ class AutoTraceLog
}
#else
public:
AutoTraceLog(TraceLoggerThread *logger, uint32_t textId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
AutoTraceLog(TraceLoggerThread *logger,
const TraceLoggerEvent &event MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoTraceLog(TraceLogger *logger, uint32_t textId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
@ -496,6 +654,26 @@ class AutoTraceLog
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
#ifdef JS_TRACE_LOGGING
class AutoTraceLoggingLock
{
TraceLogging *logging;
public:
AutoTraceLoggingLock(TraceLogging *logging MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: logging(logging)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
PR_Lock(logging->lock);
}
~AutoTraceLoggingLock() {
PR_Unlock(logging->lock);
}
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
#endif
} /* namedata js */
#endif /* TraceLogging_h */

Просмотреть файл

@ -1,570 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
#include "vm/TraceLoggingGraph.h"
#include "mozilla/Endian.h"
#include "jsstr.h"
#include "vm/TraceLogging.h"
#ifndef TRACE_LOG_DIR
# if defined(_WIN32)
# define TRACE_LOG_DIR ""
# else
# define TRACE_LOG_DIR "/tmp/"
# endif
#endif
using mozilla::NativeEndian;
TraceLoggerGraphState traceLoggersGraph;
class AutoTraceLoggerGraphStateLock
{
TraceLoggerGraphState *graph;
public:
AutoTraceLoggerGraphStateLock(TraceLoggerGraphState *graph MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: graph(graph)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
PR_Lock(graph->lock);
}
~AutoTraceLoggerGraphStateLock() {
PR_Unlock(graph->lock);
}
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
TraceLoggerGraphState::TraceLoggerGraphState()
: numLoggers(0),
out(nullptr)
{
lock = PR_NewLock();
if (!lock)
MOZ_CRASH();
}
bool
TraceLoggerGraphState::ensureInitialized()
{
if (out)
return true;
out = fopen(TRACE_LOG_DIR "tl-data.json", "w");
if (!out)
return false;
fprintf(out, "[");
return true;
}
TraceLoggerGraphState::~TraceLoggerGraphState()
{
if (out) {
fprintf(out, "]");
fclose(out);
out = nullptr;
}
if (lock) {
PR_DestroyLock(lock);
lock = nullptr;
}
}
uint32_t
TraceLoggerGraphState::nextLoggerId()
{
AutoTraceLoggerGraphStateLock lock(this);
if (!ensureInitialized()) {
fprintf(stderr, "TraceLogging: Couldn't create the main log file.");
return uint32_t(-1);
}
if (numLoggers > 999) {
fprintf(stderr, "TraceLogging: Can't create more than 999 different loggers.");
return uint32_t(-1);
}
if (numLoggers > 0) {
int written = fprintf(out, ",\n");
if (written < 0) {
fprintf(stderr, "TraceLogging: Error while writing.\n");
return uint32_t(-1);
}
}
int written = fprintf(out, "{\"tree\":\"tl-tree.%d.tl\", \"events\":\"tl-event.%d.tl\", "
"\"dict\":\"tl-dict.%d.json\", \"treeFormat\":\"64,64,31,1,32\"}",
numLoggers, numLoggers, numLoggers);
if (written < 0) {
fprintf(stderr, "TraceLogging: Error while writing.\n");
return uint32_t(-1);
}
return numLoggers++;
}
bool
TraceLoggerGraph::init(uint64_t startTimestamp)
{
if (!tree.init()) {
failed = true;
return false;
}
if (!stack.init()) {
failed = true;
return false;
}
uint32_t loggerId = traceLoggersGraph.nextLoggerId();
if (loggerId == uint32_t(-1)) {
failed = true;
return false;
}
char dictFilename[sizeof TRACE_LOG_DIR "tl-dict.100.json"];
sprintf(dictFilename, TRACE_LOG_DIR "tl-dict.%d.json", loggerId);
dictFile = fopen(dictFilename, "w");
if (!dictFile) {
failed = true;
return false;
}
char treeFilename[sizeof TRACE_LOG_DIR "tl-tree.100.tl"];
sprintf(treeFilename, TRACE_LOG_DIR "tl-tree.%d.tl", loggerId);
treeFile = fopen(treeFilename, "wb");
if (!treeFile) {
fclose(dictFile);
dictFile = nullptr;
failed = true;
return false;
}
char eventFilename[sizeof TRACE_LOG_DIR "tl-event.100.tl"];
sprintf(eventFilename, TRACE_LOG_DIR "tl-event.%d.tl", loggerId);
eventFile = fopen(eventFilename, "wb");
if (!eventFile) {
fclose(dictFile);
fclose(treeFile);
dictFile = nullptr;
treeFile = nullptr;
failed = true;
return false;
}
// Create the top tree node and corresponding first stack item.
TreeEntry &treeEntry = tree.pushUninitialized();
treeEntry.setStart(startTimestamp);
treeEntry.setStop(0);
treeEntry.setTextId(0);
treeEntry.setHasChildren(false);
treeEntry.setNextId(0);
StackEntry &stackEntry = stack.pushUninitialized();
stackEntry.setTreeId(0);
stackEntry.setLastChildId(0);
stackEntry.setActive(true);
int written = fprintf(dictFile, "[");
if (written < 0) {
fprintf(stderr, "TraceLogging: Error while writing.\n");
fclose(dictFile);
fclose(treeFile);
fclose(eventFile);
dictFile = nullptr;
treeFile = nullptr;
eventFile = nullptr;
failed = true;
return false;
}
return true;
}
TraceLoggerGraph::~TraceLoggerGraph()
{
// Write dictionary to disk
if (dictFile) {
int written = fprintf(dictFile, "]");
if (written < 0)
fprintf(stderr, "TraceLogging: Error while writing.\n");
fclose(dictFile);
dictFile = nullptr;
}
if (!failed && treeFile) {
// 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 = 1;
while (stack.size() > 1)
stopEvent(0);
enabled = 0;
}
if (!failed && !flush()) {
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
enabled = 0;
failed = true;
}
if (treeFile) {
fclose(treeFile);
treeFile = nullptr;
}
if (eventFile) {
fclose(eventFile);
eventFile = nullptr;
}
}
bool
TraceLoggerGraph::flush()
{
MOZ_ASSERT(!failed);
if (treeFile) {
// Format data in big endian.
for (size_t i = 0; i < tree.size(); i++)
entryToBigEndian(&tree[i]);
int success = fseek(treeFile, 0, SEEK_END);
if (success != 0)
return false;
size_t bytesWritten = fwrite(tree.data(), sizeof(TreeEntry), tree.size(), treeFile);
if (bytesWritten < tree.size())
return false;
treeOffset += tree.lastEntryId();
tree.clear();
}
return true;
}
void
TraceLoggerGraph::entryToBigEndian(TreeEntry *entry)
{
entry->start_ = NativeEndian::swapToBigEndian(entry->start_);
entry->stop_ = NativeEndian::swapToBigEndian(entry->stop_);
uint32_t data = (entry->u.s.textId_ << 1) + entry->u.s.hasChildren_;
entry->u.value_ = NativeEndian::swapToBigEndian(data);
entry->nextId_ = NativeEndian::swapToBigEndian(entry->nextId_);
}
void
TraceLoggerGraph::entryToSystemEndian(TreeEntry *entry)
{
entry->start_ = NativeEndian::swapFromBigEndian(entry->start_);
entry->stop_ = NativeEndian::swapFromBigEndian(entry->stop_);
uint32_t data = NativeEndian::swapFromBigEndian(entry->u.value_);
entry->u.s.textId_ = data >> 1;
entry->u.s.hasChildren_ = data & 0x1;
entry->nextId_ = NativeEndian::swapFromBigEndian(entry->nextId_);
}
void
TraceLoggerGraph::startEvent(uint32_t id, uint64_t timestamp)
{
if (failed || enabled == 0)
return;
if (!tree.hasSpaceForAdd()) {
if (!tree.ensureSpaceBeforeAdd()) {
if (!flush()) {
fprintf(stderr, "TraceLogging: Couldn't write the data to disk.\n");
enabled = 0;
failed = true;
return;
}
}
}
if (!startEventInternal(id, timestamp)) {
fprintf(stderr, "TraceLogging: Failed to start an event.\n");
enabled = 0;
failed = true;
return;
}
}
TraceLoggerGraph::StackEntry &
TraceLoggerGraph::getActiveAncestor()
{
uint32_t parentId = stack.lastEntryId();
while (!stack[parentId].active())
parentId--;
return stack[parentId];
}
bool
TraceLoggerGraph::startEventInternal(uint32_t id, uint64_t timestamp)
{
if (!stack.ensureSpaceBeforeAdd())
return false;
// Patch up the tree to be correct. There are two scenarios:
// 1) Parent has no children yet. So update parent to include children.
// 2) Parent has already children. Update last child to link to the new
// child.
StackEntry &parent = getActiveAncestor();
#ifdef DEBUG
TreeEntry entry;
if (!getTreeEntry(parent.treeId(), &entry))
return false;
#endif
if (parent.lastChildId() == 0) {
MOZ_ASSERT(!entry.hasChildren());
MOZ_ASSERT(parent.treeId() == tree.lastEntryId() + treeOffset);
if (!updateHasChildren(parent.treeId()))
return false;
} else {
MOZ_ASSERT(entry.hasChildren());
if (!updateNextId(parent.lastChildId(), tree.size() + treeOffset))
return false;
}
// Add a new tree entry.
TreeEntry &treeEntry = tree.pushUninitialized();
treeEntry.setStart(timestamp);
treeEntry.setStop(0);
treeEntry.setTextId(id);
treeEntry.setHasChildren(false);
treeEntry.setNextId(0);
// Add a new stack entry.
StackEntry &stackEntry = stack.pushUninitialized();
stackEntry.setTreeId(tree.lastEntryId() + treeOffset);
stackEntry.setLastChildId(0);
stackEntry.setActive(true);
// Set the last child of the parent to this newly added entry.
parent.setLastChildId(tree.lastEntryId() + treeOffset);
return true;
}
void
TraceLoggerGraph::stopEvent(uint32_t id, uint64_t timestamp)
{
#ifdef DEBUG
if (id != TraceLogger_Scripts &&
id != TraceLogger_Engine &&
stack.size() > 1 &&
stack.lastEntry().active())
{
TreeEntry entry;
MOZ_ASSERT(getTreeEntry(stack.lastEntry().treeId(), &entry));
MOZ_ASSERT(entry.textId() == id);
}
#endif
stopEvent(timestamp);
}
void
TraceLoggerGraph::stopEvent(uint64_t timestamp)
{
if (enabled && stack.lastEntry().active()) {
if (!updateStop(stack.lastEntry().treeId(), timestamp)) {
fprintf(stderr, "TraceLogging: Failed to stop an event.\n");
enabled = 0;
failed = true;
return;
}
}
if (stack.size() == 1) {
if (!enabled)
return;
// Forcefully disable logging. We have no stack information anymore.
logTimestamp(TraceLogger_Disable, timestamp);
return;
}
stack.pop();
}
void
TraceLoggerGraph::logTimestamp(uint32_t id, uint64_t timestamp)
{
if (failed)
return;
if (id == TraceLogger_Enable)
enabled = true;
if (!enabled)
return;
if (id == TraceLogger_Disable)
disable(timestamp);
MOZ_ASSERT(eventFile);
// Format data in big endian
timestamp = NativeEndian::swapToBigEndian(timestamp);
id = NativeEndian::swapToBigEndian(id);
// The layout of the event log in the log file is:
// [timestamp, textId]
size_t itemsWritten = 0;
itemsWritten += fwrite(&timestamp, sizeof(uint64_t), 1, eventFile);
itemsWritten += fwrite(&id, sizeof(uint32_t), 1, eventFile);
if (itemsWritten < 2) {
failed = true;
enabled = false;
}
}
bool
TraceLoggerGraph::getTreeEntry(uint32_t treeId, TreeEntry *entry)
{
// Entry is still in memory
if (treeId >= treeOffset) {
*entry = tree[treeId - treeOffset];
return true;
}
int success = fseek(treeFile, treeId * sizeof(TreeEntry), SEEK_SET);
if (success != 0)
return false;
size_t itemsRead = fread((void *)entry, sizeof(TreeEntry), 1, treeFile);
if (itemsRead < 1)
return false;
entryToSystemEndian(entry);
return true;
}
bool
TraceLoggerGraph::saveTreeEntry(uint32_t treeId, TreeEntry *entry)
{
int success = fseek(treeFile, treeId * sizeof(TreeEntry), SEEK_SET);
if (success != 0)
return false;
entryToBigEndian(entry);
size_t itemsWritten = fwrite(entry, sizeof(TreeEntry), 1, treeFile);
if (itemsWritten < 1)
return false;
return true;
}
bool
TraceLoggerGraph::updateHasChildren(uint32_t treeId, bool hasChildren)
{
if (treeId < treeOffset) {
TreeEntry entry;
if (!getTreeEntry(treeId, &entry))
return false;
entry.setHasChildren(hasChildren);
if (!saveTreeEntry(treeId, &entry))
return false;
return true;
}
tree[treeId - treeOffset].setHasChildren(hasChildren);
return true;
}
bool
TraceLoggerGraph::updateNextId(uint32_t treeId, uint32_t nextId)
{
if (treeId < treeOffset) {
TreeEntry entry;
if (!getTreeEntry(treeId, &entry))
return false;
entry.setNextId(nextId);
if (!saveTreeEntry(treeId, &entry))
return false;
return true;
}
tree[treeId - treeOffset].setNextId(nextId);
return true;
}
bool
TraceLoggerGraph::updateStop(uint32_t treeId, uint64_t timestamp)
{
if (treeId < treeOffset) {
TreeEntry entry;
if (!getTreeEntry(treeId, &entry))
return false;
entry.setStop(timestamp);
if (!saveTreeEntry(treeId, &entry))
return false;
return true;
}
tree[treeId - treeOffset].setStop(timestamp);
return true;
}
void
TraceLoggerGraph::disable(uint64_t timestamp)
{
MOZ_ASSERT(enabled);
while (stack.size() > 1)
stopEvent(timestamp);
enabled = false;
}
void
TraceLoggerGraph::log(ContinuousSpace<EventEntry> &events)
{
if (!enabled)
return;
for (uint32_t i = 0; i < events.size(); i++) {
if (events[i].textId == TraceLogger_Stop)
stopEvent(events[i].time);
else if (TLTextIdIsTreeEvent(events[i].textId))
startEvent(events[i].textId, events[i].time);
else
logTimestamp(events[i].textId, events[i].time);
}
}
void
TraceLoggerGraph::addTextId(uint32_t id, const char *text)
{
if (failed)
return;
// Assume ids are given in order. Which is currently true.
MOZ_ASSERT(id == nextTextId);
nextTextId++;
if (id > 0) {
int written = fprintf(dictFile, ",\n");
if (written < 0) {
failed = true;
return;
}
}
if (!js::FileEscapedString(dictFile, text, strlen(text), '"'))
failed = true;
}

Просмотреть файл

@ -1,255 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 TraceLoggingGraph_h
#define TraceLoggingGraph_h
#include "mozilla/DebugOnly.h"
#include "jslock.h"
#include "js/TypeDecls.h"
#include "vm/TraceLoggingTypes.h"
/*
* The output of a tracelogging session is saved in /tmp/tl-data.json.
* The format of that file is a JS array per tracelogger (=thread), with a map
* containing:
* - dict: Name of the file containing a json table with the log text.
* All other files only contain a index to this table when logging.
* - events: Name of the file containing a flat list of log events saved
* in binary format.
* (64bit: Time Stamp Counter, 32bit index to dict)
* - tree: Name of the file containing the events with duration. The content
* is already in a tree data structure. This is also saved in a
* binary file.
* - treeFormat: The format used to encode the tree. By default "64,64,31,1,32".
* There are currently no other formats to save the tree.
* - 64,64,31,1,31 signifies how many bytes are used for the different
* parts of the tree.
* => 64 bits: Time Stamp Counter of start of event.
* => 64 bits: Time Stamp Counter of end of event.
* => 31 bits: Index to dict file containing the log text.
* => 1 bit: Boolean signifying if this entry has children.
* When true, the child can be found just right after this entry.
* => 32 bits: Containing the ID of the next event on the same depth
* or 0 if there isn't an event on the same depth anymore.
*
* /-> The position in the file. Id is this divided by size of entry.
* | So in this case this would be 1 (192bits per entry).
* | /-> Indicates there are children. The
* | | first child is located at current
* | | ID + 1. So 1 + 1 in this case: 2.
* | | Or 0x00180 in the tree file.
* | | /-> Next event on the same depth is
* | | | located at 4. So 0x00300 in the
* | | | tree file.
* 0x0000C0: [start, end, dictId, 1, 4]
*
*
* Example:
* 0x0: [start, end, dictId, 1, 0]
* |
* /----------------------------------\
* | |
* 0xC0: [start, end, dictId, 0, 2] 0x180 [start, end, dictId, 1, 0]
* |
* /----------------------------------\
* | |
* 0x240: [start, end, dictId, 0, 4] 0x300 [start, end, dictId, 0, 0]
*/
class TraceLoggerGraphState
{
size_t numLoggers;
// File pointer to the "tl-data.json" file. (Explained above).
FILE *out;
public:
PRLock *lock;
public:
TraceLoggerGraphState();
~TraceLoggerGraphState();
uint32_t nextLoggerId();
private:
bool ensureInitialized();
};
class TraceLoggerGraph
{
// The layout of the tree in memory and in the log file. Readable by JS
// using TypedArrays.
struct TreeEntry {
uint64_t start_;
uint64_t stop_;
union {
struct {
uint32_t textId_: 31;
uint32_t hasChildren_: 1;
} s;
uint32_t value_;
} u;
uint32_t nextId_;
TreeEntry(uint64_t start, uint64_t stop, uint32_t textId, bool hasChildren,
uint32_t nextId)
{
start_ = start;
stop_ = stop;
u.s.textId_ = textId;
u.s.hasChildren_ = hasChildren;
nextId_ = nextId;
}
TreeEntry()
{ }
uint64_t start() {
return start_;
}
uint64_t stop() {
return stop_;
}
uint32_t textId() {
return u.s.textId_;
}
bool hasChildren() {
return u.s.hasChildren_;
}
uint32_t nextId() {
return nextId_;
}
void setStart(uint64_t start) {
start_ = start;
}
void setStop(uint64_t stop) {
stop_ = stop;
}
void setTextId(uint32_t textId) {
MOZ_ASSERT(textId < uint32_t(1 << 31));
u.s.textId_ = textId;
}
void setHasChildren(bool hasChildren) {
u.s.hasChildren_ = hasChildren;
}
void setNextId(uint32_t nextId) {
nextId_ = nextId;
}
};
// Helper structure for keeping track of the current entries in
// the tree. Pushed by `start(id)`, popped by `stop(id)`. The active flag
// is used to know if a subtree doesn't need to get logged.
struct StackEntry {
uint32_t treeId_;
uint32_t lastChildId_;
struct {
uint32_t textId_: 31;
uint32_t active_: 1;
} s;
StackEntry(uint32_t treeId, uint32_t lastChildId, bool active = true)
: treeId_(treeId), lastChildId_(lastChildId)
{
s.textId_ = 0;
s.active_ = active;
}
uint32_t treeId() {
return treeId_;
}
uint32_t lastChildId() {
return lastChildId_;
}
uint32_t textId() {
return s.textId_;
}
bool active() {
return s.active_;
}
void setTreeId(uint32_t treeId) {
treeId_ = treeId;
}
void setLastChildId(uint32_t lastChildId) {
lastChildId_ = lastChildId;
}
void setTextId(uint32_t textId) {
MOZ_ASSERT(textId < uint32_t(1<<31));
s.textId_ = textId;
}
void setActive(bool active) {
s.active_ = active;
}
};
public:
TraceLoggerGraph()
: failed(false),
enabled(false),
nextTextId(0)
{ }
~TraceLoggerGraph();
bool init(uint64_t timestamp);
// Link a textId with a particular text.
void addTextId(uint32_t id, const char *text);
// Create a tree out of all the given events.
void log(ContinuousSpace<EventEntry> &events);
private:
bool failed;
bool enabled;
mozilla::DebugOnly<uint32_t> nextTextId;
FILE *dictFile;
FILE *treeFile;
FILE *eventFile;
ContinuousSpace<TreeEntry> tree;
ContinuousSpace<StackEntry> stack;
uint32_t treeOffset;
// Helper functions that convert a TreeEntry in different endianness
// in place.
void entryToBigEndian(TreeEntry *entry);
void entryToSystemEndian(TreeEntry *entry);
// Helper functions to get/save a tree from file.
bool getTreeEntry(uint32_t treeId, TreeEntry *entry);
bool saveTreeEntry(uint32_t treeId, TreeEntry *entry);
// Return the first StackEntry that is active.
StackEntry &getActiveAncestor();
// This contains the meat of startEvent, except the test for enough space,
// the test if tracelogger is enabled and the timestamp computation.
void startEvent(uint32_t id, uint64_t timestamp);
bool startEventInternal(uint32_t id, uint64_t timestamp);
// Update functions that can adjust the items in the tree,
// both in memory or already written to disk.
bool updateHasChildren(uint32_t treeId, bool hasChildren = true);
bool updateNextId(uint32_t treeId, uint32_t nextId);
bool updateStop(uint32_t treeId, uint64_t timestamp);
// Flush the tree.
bool flush();
// Stop a tree event.
void stopEvent(uint32_t id, uint64_t timestamp);
void stopEvent(uint64_t timestamp);
// Log an (non-tree) event.
void logTimestamp(uint32_t id, uint64_t timestamp);
// Disable logging and forcefully report all not yet stopped tree events
// as stopped.
void disable(uint64_t timestamp);
};
#endif /* TraceLoggingGraph_h */

Просмотреть файл

@ -1,20 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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/. */
#include "vm/TraceLoggingTypes.h"
class JSLinearString;
uint32_t
TLStringToTextId(JSLinearString *str)
{
#define NAME(textId) if (js::StringEqualsAscii(str, #textId)) return TraceLogger_ ## textId;
TRACELOGGER_TREE_ITEMS(NAME)
TRACELOGGER_LOG_ITEMS(NAME)
#undef NAME
return TraceLogger_Error;
}

Просмотреть файл

@ -1,239 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 TraceLoggingTypes_h
#define TraceLoggingTypes_h
#include "jsalloc.h"
#include "jsstr.h"
#define TRACELOGGER_TREE_ITEMS(_) \
_(AnnotateScripts) \
_(Baseline) \
_(BaselineCompilation) \
_(Engine) \
_(GC) \
_(GCAllocation) \
_(GCSweeping) \
_(Internal) \
_(Interpreter) \
_(InlinedScripts) \
_(Invalidation) \
_(IonCompilation) \
_(IonCompilationPaused) \
_(IonLinking) \
_(IonMonkey) \
_(IrregexpCompile) \
_(IrregexpExecute) \
_(MinorGC) \
_(ParserCompileFunction) \
_(ParserCompileLazy) \
_(ParserCompileScript) \
_(Scripts) \
_(VM) \
\
/* Specific passes during ion compilation */ \
_(FoldTests) \
_(SplitCriticalEdges) \
_(RenumberBlocks) \
_(ScalarReplacement) \
_(DominatorTree) \
_(PhiAnalysis) \
_(MakeLoopsContiguous) \
_(ApplyTypes) \
_(ParallelSafetyAnalysis) \
_(AliasAnalysis) \
_(GVN) \
_(LICM) \
_(RangeAnalysis) \
_(LoopUnrolling) \
_(EffectiveAddressAnalysis) \
_(EliminateDeadCode) \
_(EdgeCaseAnalysis) \
_(EliminateRedundantChecks) \
_(GenerateLIR) \
_(RegisterAllocation) \
_(GenerateCode)
#define TRACELOGGER_LOG_ITEMS(_) \
_(Bailout) \
_(Disable) \
_(Enable) \
_(Stop)
// Predefined IDs for common operations. These IDs can be used
// without using TraceLogCreateTextId, because there are already created.
enum TraceLoggerTextId {
TraceLogger_Error = 0,
#define DEFINE_TEXT_ID(textId) TraceLogger_ ## textId,
TRACELOGGER_TREE_ITEMS(DEFINE_TEXT_ID)
TraceLogger_LastTreeItem,
TRACELOGGER_LOG_ITEMS(DEFINE_TEXT_ID)
#undef DEFINE_TEXT_ID
TraceLogger_Last
};
inline const char *
TLTextIdString(TraceLoggerTextId id)
{
switch (id) {
case TraceLogger_Error:
return "TraceLogger failed to process text";
#define NAME(textId) case TraceLogger_ ## textId: return #textId;
TRACELOGGER_TREE_ITEMS(NAME)
TRACELOGGER_LOG_ITEMS(NAME)
#undef NAME
default:
MOZ_CRASH();
}
}
uint32_t
TLStringToTextId(JSLinearString *str);
inline bool
TLTextIdIsToggable(uint32_t id)
{
if (id == TraceLogger_Error)
return false;
if (id == TraceLogger_Internal)
return false;
if (id == TraceLogger_Stop)
return false;
// Actually never used. But added here so it doesn't show as toggle
if (id == TraceLogger_LastTreeItem)
return false;
if (id == TraceLogger_Last)
return false;
// Cannot toggle the logging of one engine on/off, because at the stop
// event it is sometimes unknown which engine was running.
if (id == TraceLogger_IonMonkey || id == TraceLogger_Baseline || id == TraceLogger_Interpreter)
return false;
return true;
}
inline bool
TLTextIdIsTreeEvent(uint32_t id)
{
// Everything between TraceLogger_Error and TraceLogger_LastTreeItem are tree events and
// atm also every custom event.
return (id > TraceLogger_Error && id < TraceLogger_LastTreeItem) ||
id >= TraceLogger_Last;
}
template <class T>
class ContinuousSpace {
T *data_;
uint32_t size_;
uint32_t capacity_;
public:
ContinuousSpace ()
: data_(nullptr)
{ }
bool init() {
capacity_ = 64;
size_ = 0;
data_ = (T *) js_malloc(capacity_ * sizeof(T));
if (!data_)
return false;
return true;
}
~ContinuousSpace()
{
js_free(data_);
data_ = nullptr;
}
T *data() {
return data_;
}
uint32_t capacity() {
return capacity_;
}
uint32_t size() {
return size_;
}
bool empty() {
return size_ == 0;
}
uint32_t lastEntryId() {
MOZ_ASSERT(!empty());
return size_ - 1;
}
T &lastEntry() {
return data()[lastEntryId()];
}
bool hasSpaceForAdd(uint32_t count = 1) {
if (size_ + count <= capacity_)
return true;
return false;
}
bool ensureSpaceBeforeAdd(uint32_t count = 1) {
MOZ_ASSERT(data_);
if (hasSpaceForAdd(count))
return true;
uint32_t nCapacity = capacity_ * 2;
if (size_ + count > nCapacity)
nCapacity = size_ + count;
T *entries = (T *) js_realloc(data_, nCapacity * sizeof(T));
if (!entries)
return false;
data_ = entries;
capacity_ = nCapacity;
return true;
}
T &operator[](size_t i) {
MOZ_ASSERT(i < size_);
return data()[i];
}
void push(T &data) {
MOZ_ASSERT(size_ < capacity_);
data()[size_++] = data;
}
T &pushUninitialized() {
MOZ_ASSERT(size_ < capacity_);
return data()[size_++];
}
void pop() {
MOZ_ASSERT(!empty());
size_--;
}
void clear() {
size_ = 0;
}
};
// The layout of the event log in memory and in the log file.
// Readable by JS using TypedArrays.
struct EventEntry {
uint64_t time;
uint32_t textId;
EventEntry(uint64_t time, uint32_t textId)
: time(time), textId(textId)
{ }
};
#endif /* TraceLoggingTypes_h */

Просмотреть файл

@ -1711,10 +1711,8 @@ class Mochitest(MochitestUtilsMixin):
self.setTestRoot(options)
# This runs on bc* and dt* jobs only
# We need to fix tests on plain|chrome|webapprt|a11y before making this default
# We need to ignore dt* jobs on e10s runs
if options.browserChrome and not (options.subsuite and options.e10s):
# Until we have all green, this only runs on bc* jobs (not dt* jobs)
if options.browserChrome and not options.subsuite:
options.runByDir = True
if not options.runByDir: