Bug 1479970 - Enable building Tracelogger by default; r=tcampbell
authorJim Porter <jporter@mozilla.com>
Thu, 11 Apr 2019 23:52:41 +0000
changeset 469273 32342cbe673a3fb37e9e9de2e818c379198a292c
parent 469272 2cc7599b9e92b2ff0d17e6f70b6cad4e0efcc8a4
child 469274 c49b36c011b2e462a9cf66a31ace780e3ef66b73
push id112776
push usershindli@mozilla.com
push dateFri, 12 Apr 2019 16:20:17 +0000
treeherdermozilla-inbound@b4501ced5619 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1479970
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1479970 - Enable building Tracelogger by default; r=tcampbell This patch enables compilation of the tracelogger by default on nightly builds as well as providing an environment variable (JS_TRACE_LOGGING) to enable or disable tracelogger instrumentation when compiling Javascript. This helps to reduce the performance impact of the Tracelogger code when not in use. In the future, this could be improved to recompile the JS with/without Tracelogger instrumentation when toggling Tracelogger support. Differential Revision: https://phabricator.services.mozilla.com/D26255
js/moz.configure
js/public/TraceLoggerAPI.h
js/src/jit/BaselineCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/shared/CodeGenerator-shared.cpp
js/src/vm/Initialization.cpp
js/src/vm/TraceLogging.cpp
tools/profiler/core/platform.cpp
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -281,18 +281,23 @@ js_option('--enable-small-chunk-size',
           help='Allocate memory for JS GC things in smaller chunks')
 
 set_define('JS_GC_SMALL_CHUNK_SIZE',
            depends(when='--enable-small-chunk-size')(lambda: True))
 
 
 # Trace logging.
 # =======================================================
+@depends(milestone)
+def default_trace_logging(milestone):
+    return milestone.is_nightly
+
+
 js_option('--enable-trace-logging',
-          default=depends(when=moz_debug)(lambda: True),
+          default=default_trace_logging,
           help='{Enable|Disable} trace logging')
 
 set_config('ENABLE_TRACE_LOGGING',
            depends_if('--enable-trace-logging')(lambda x: True))
 set_define('JS_TRACE_LOGGING',
            depends_if('--enable-trace-logging')(lambda x: True))
 
 
--- a/js/public/TraceLoggerAPI.h
+++ b/js/public/TraceLoggerAPI.h
@@ -121,16 +121,24 @@ class TraceLoggerCollectorBuffer {
   JSContext* cx_;
   size_t length_;
   size_t dataIndex_;
   size_t bufferIndex_;
   ImplType* buffer_;
 };
 
 #ifdef JS_TRACE_LOGGING
+
+// Initialize the trace logger.  This must be called before using any of the
+// other trace logging functions.
+extern JS_PUBLIC_API bool InitTraceLogger();
+
+// Return whether the trace logger is supported in this browser session.
+extern JS_PUBLIC_API bool TraceLoggerSupported();
+
 // Begin trace logging events.  This will activate some of the
 // textId's for various events and set the global option
 // JSJITCOMPILER_ENABLE_TRACELOGGER to true.
 // This does nothing except return if the trace logger is already active.
 extern JS_PUBLIC_API void StartTraceLogger(JSContext* cx);
 
 // Stop trace logging events.  All textId's will be set to false, and the
 // global JSJITCOMPILER_ENABLE_TRACELOGGER will be set to false.
@@ -139,16 +147,18 @@ extern JS_PUBLIC_API void StopTraceLogge
 
 // Clear and free any event data that was recorded by the trace logger.
 extern JS_PUBLIC_API void ResetTraceLogger(void);
 
 #else
 // Define empty inline functions for when trace logging compilation is not
 // enabled.  TraceLogging.cpp will not be built in that case so we need to
 // provide something for any routines that reference these.
+inline bool InitTraceLogger() { return true; }
+inline bool TraceLoggerSupported() { return false; }
 inline void StartTraceLogger(JSContext* cx) {}
 inline void StopTraceLogger(JSContext* cx) {}
 inline void ResetTraceLogger(void) {}
 inline size_t TraceLoggerDictionaryImpl::NextChunk(JSContext* cx,
                                                    size_t* dataIndex,
                                                    ImplType buffer[],
                                                    size_t bufferSize) {
   return 0;
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -321,17 +321,19 @@ MethodStatus BaselineCompiler::compile()
     baselineScript->setModifiesArguments();
   }
   if (handler.analysis().usesEnvironmentChain()) {
     baselineScript->setUsesEnvironmentChain();
   }
 
 #ifdef JS_TRACE_LOGGING
   // Initialize the tracelogger instrumentation.
-  baselineScript->initTraceLogger(script, traceLoggerToggleOffsets_);
+  if (JS::TraceLoggerSupported()) {
+    baselineScript->initTraceLogger(script, traceLoggerToggleOffsets_);
+  }
 #endif
 
   // Compute yield/await native resume addresses.
   baselineScript->computeResumeNativeOffsets(script);
 
   if (compileDebugInstrumentation()) {
     baselineScript->setHasDebugInstrumentation();
   }
@@ -5528,17 +5530,17 @@ bool BaselineCompilerCodeGen::emit_JSOP_
 
   // Load the BaselineScript or call a stub if we don't have one.
   Label interpret;
   masm.loadPtr(Address(scratch1, JSScript::offsetOfBaselineScript()), scratch1);
   masm.branchPtr(Assembler::BelowOrEqual, scratch1,
                  ImmPtr(BASELINE_DISABLED_SCRIPT), &interpret);
 
 #ifdef JS_TRACE_LOGGING
-  if (!emitTraceLoggerResume(scratch1, regs)) {
+  if (JS::TraceLoggerSupported() && !emitTraceLoggerResume(scratch1, regs)) {
     return false;
   }
 #endif
 
   // Push |undefined| for all formals.
   Register scratch2 = regs.takeAny();
   Label loop, loopDone;
   masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch2);
@@ -6110,17 +6112,17 @@ bool BaselineCodeGen<Handler>::emitProlo
 
   emitInitializeLocals();
 
   if (handler.needsEarlyStackCheck()) {
     masm.bind(&earlyStackCheckFailed);
   }
 
 #ifdef JS_TRACE_LOGGING
-  if (!emitTraceLoggerEnter()) {
+  if (JS::TraceLoggerSupported() && !emitTraceLoggerEnter()) {
     return false;
   }
 #endif
 
   // Record the offset of the prologue, because Ion can bailout before
   // the env chain is initialized.
   bailoutPrologueOffset_ = CodeOffset(masm.currentOffset());
 
@@ -6165,17 +6167,17 @@ template <typename Handler>
 bool BaselineCodeGen<Handler>::emitEpilogue() {
   // Record the offset of the epilogue, so we can do early return from
   // Debugger handlers during on-stack recompile.
   debugOsrEpilogueOffset_ = CodeOffset(masm.currentOffset());
 
   masm.bind(&return_);
 
 #ifdef JS_TRACE_LOGGING
-  if (!emitTraceLoggerExit()) {
+  if (JS::TraceLoggerSupported() && !emitTraceLoggerExit()) {
     return false;
   }
 #endif
 
   masm.moveToStackPtr(BaselineFrameReg);
   masm.pop(BaselineFrameReg);
 
   emitProfilerExitFrame();
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3676,18 +3676,20 @@ void CodeGenerator::visitReturn(LReturn*
 void CodeGenerator::visitOsrEntry(LOsrEntry* lir) {
   Register temp = ToRegister(lir->temp());
 
   // Remember the OSR entry offset into the code buffer.
   masm.flushBuffer();
   setOsrEntryOffset(masm.size());
 
 #ifdef JS_TRACE_LOGGING
-  emitTracelogStopEvent(TraceLogger_Baseline);
-  emitTracelogStartEvent(TraceLogger_IonMonkey);
+  if (JS::TraceLoggerSupported()) {
+    emitTracelogStopEvent(TraceLogger_Baseline);
+    emitTracelogStartEvent(TraceLogger_IonMonkey);
+  }
 #endif
 
   // If profiling, save the current frame pointer to a per-thread global field.
   if (isProfilerInstrumentationEnabled()) {
     masm.profilerEnterFrame(masm.getStackPointer(), temp);
   }
 
   // Allocate the full frame for this function
@@ -4683,34 +4685,38 @@ void CodeGenerator::visitCallNative(LCal
 
   // Construct native exit frame.
   uint32_t safepointOffset = masm.buildFakeExitFrame(tempReg);
   masm.enterFakeExitFrameForNative(argContextReg, tempReg,
                                    call->mir()->isConstructing());
 
   markSafepointAt(safepointOffset, call);
 
-  emitTracelogStartEvent(TraceLogger_Call);
+  if (JS::TraceLoggerSupported()) {
+    emitTracelogStartEvent(TraceLogger_Call);
+  }
 
   // Construct and execute call.
   masm.setupUnalignedABICall(tempReg);
   masm.passABIArg(argContextReg);
   masm.passABIArg(argUintNReg);
   masm.passABIArg(argVpReg);
   JSNative native = target->native();
   if (call->ignoresReturnValue() && target->hasJitInfo()) {
     const JSJitInfo* jitInfo = target->jitInfo();
     if (jitInfo->type() == JSJitInfo::IgnoresReturnValueNative) {
       native = jitInfo->ignoresReturnValueMethod;
     }
   }
   masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, native), MoveOp::GENERAL,
                    CheckUnsafeCallWithABI::DontCheckHasExitFrame);
 
-  emitTracelogStopEvent(TraceLogger_Call);
+  if (JS::TraceLoggerSupported()) {
+    emitTracelogStopEvent(TraceLogger_Call);
+  }
 
   // Test for failure.
   masm.branchIfFalseBool(ReturnReg, masm.failureLabel());
 
   if (call->mir()->maybeCrossRealm()) {
     masm.switchToRealm(gen->realm->realmPtr(), ReturnReg);
   }
 
@@ -10928,16 +10934,17 @@ bool CodeGenerator::link(JSContext* cx, 
     Assembler::PatchDataWithValueCheck(
         CodeLocationLabel(code, ionScriptLabels_[i]), ImmPtr(ionScript),
         ImmPtr((void*)-1));
   }
 
 #ifdef JS_TRACE_LOGGING
   bool TLFailed = false;
 
+  MOZ_ASSERT_IF(!JS::TraceLoggerSupported(), patchableTLEvents_.length() == 0);
   for (uint32_t i = 0; i < patchableTLEvents_.length(); i++) {
     TraceLoggerEvent event(patchableTLEvents_[i].event);
     if (!event.hasTextId() || !ionScript->addTraceLoggerEvent(event)) {
       TLFailed = true;
       break;
     }
     Assembler::PatchDataWithValueCheck(
         CodeLocationLabel(code, patchableTLEvents_[i].offset),
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -128,25 +128,30 @@ bool CodeGeneratorShared::generateProlog
 
   // Ensure that the Ion frame is properly aligned.
   masm.assertStackAlignment(JitStackAlignment, 0);
 
   // Note that this automatically sets MacroAssembler::framePushed().
   masm.reserveStack(frameSize());
   masm.checkStackAlignment();
 
-  emitTracelogIonStart();
+  if (JS::TraceLoggerSupported()) {
+    emitTracelogIonStart();
+  }
+
   return true;
 }
 
 bool CodeGeneratorShared::generateEpilogue() {
   MOZ_ASSERT(!gen->compilingWasm());
   masm.bind(&returnLabel_);
 
-  emitTracelogIonStop();
+  if (JS::TraceLoggerSupported()) {
+    emitTracelogIonStop();
+  }
 
   masm.freeStack(frameSize());
   MOZ_ASSERT(masm.framePushed() == 0);
 
   // If profiling, reset the per-thread global lastJitFrame to point to
   // the previous frame.
   if (isProfilerInstrumentationEnabled()) {
     masm.profilerExitFrame();
--- a/js/src/vm/Initialization.cpp
+++ b/js/src/vm/Initialization.cpp
@@ -146,16 +146,20 @@ JS_PUBLIC_API const char* JS::detail::In
   RETURN_IF_FAIL(js::CreateHelperThreadsState());
   RETURN_IF_FAIL(FutexThread::initialize());
   RETURN_IF_FAIL(js::gcstats::Statistics::initialize());
 
 #ifdef JS_SIMULATOR
   RETURN_IF_FAIL(js::jit::SimulatorProcess::initialize());
 #endif
 
+#ifdef JS_TRACE_LOGGING
+  RETURN_IF_FAIL(JS::InitTraceLogger());
+#endif
+
   libraryInitState = InitState::Running;
   return nullptr;
 }
 
 #undef RETURN_IF_FAIL
 
 JS_PUBLIC_API void JS_ShutDown(void) {
   MOZ_ASSERT(
--- a/js/src/vm/TraceLogging.cpp
+++ b/js/src/vm/TraceLogging.cpp
@@ -23,34 +23,39 @@
 #include "vm/Runtime.h"
 #include "vm/Time.h"
 #include "vm/TraceLoggingGraph.h"
 
 #include "jit/JitFrames-inl.h"
 
 using namespace js;
 
-TraceLoggerThreadState* traceLoggerState = nullptr;
+static TraceLoggerThreadState* traceLoggerState = nullptr;
+
+static bool getTraceLoggerSupported() {
+  char* str = getenv("JS_TRACE_LOGGING");
 
-static bool EnsureTraceLoggerState() {
-  if (MOZ_LIKELY(traceLoggerState)) {
+  if (!str) {
+    // Default to unsupported.
+    return false;
+  }
+
+  if (strcmp(str, "false") == 0 || strcmp(str, "no") == 0 ||
+      strcmp(str, "0") == 0) {
+    return false;
+  }
+
+  if (strcmp(str, "true") == 0 || strcmp(str, "yes") == 0 ||
+      strcmp(str, "1") == 0) {
     return true;
   }
 
-  traceLoggerState = js_new<TraceLoggerThreadState>();
-  if (!traceLoggerState) {
-    return false;
-  }
-
-  if (!traceLoggerState->init()) {
-    DestroyTraceLoggerThreadState();
-    return false;
-  }
-
-  return true;
+  fprintf(stderr, "Warning: I didn't understand JS_TRACE_LOGGING=\"%s\"\n",
+          str);
+  return false;
 }
 
 size_t js::SizeOfTraceLogState(mozilla::MallocSizeOf mallocSizeOf) {
   return traceLoggerState ? traceLoggerState->sizeOfIncludingThis(mallocSizeOf)
                           : 0;
 }
 
 void js::ResetTraceLogger() {
@@ -70,19 +75,17 @@ void js::DestroyTraceLoggerThreadState()
 
 #ifdef DEBUG
 bool js::CurrentThreadOwnsTraceLoggerThreadStateLock() {
   return traceLoggerState && traceLoggerState->lock.ownedByCurrentThread();
 }
 #endif
 
 void js::DestroyTraceLogger(TraceLoggerThread* logger) {
-  if (!EnsureTraceLoggerState()) {
-    return;
-  }
+  MOZ_ASSERT(traceLoggerState);
   traceLoggerState->destroyLogger(logger);
 }
 
 bool TraceLoggerThread::init() {
   if (!events.init()) {
     return false;
   }
 
@@ -1275,17 +1278,17 @@ void TraceLoggerThreadState::disableText
     jit::ToggleBaselineTraceLoggerScripts(cx->runtime(), false);
   }
   if (textId == TraceLogger_Engine) {
     jit::ToggleBaselineTraceLoggerEngine(cx->runtime(), false);
   }
 }
 
 TraceLoggerThread* js::TraceLoggerForCurrentThread(JSContext* maybecx) {
-  if (!EnsureTraceLoggerState()) {
+  if (!traceLoggerState) {
     return nullptr;
   }
   return traceLoggerState->forCurrentThread(maybecx);
 }
 
 TraceLoggerThread* TraceLoggerThreadState::forCurrentThread(
     JSContext* maybecx) {
   if (!jit::JitOptions.enableTraceLogger) {
@@ -1332,30 +1335,30 @@ void TraceLoggerThreadState::destroyLogg
   MOZ_ASSERT(logger);
   LockGuard<Mutex> guard(lock);
 
   logger->remove();
   js_delete(logger);
 }
 
 bool js::TraceLogTextIdEnabled(uint32_t textId) {
-  if (!EnsureTraceLoggerState()) {
+  if (!traceLoggerState) {
     return false;
   }
   return traceLoggerState->isTextIdEnabled(textId);
 }
 
 void js::TraceLogEnableTextId(JSContext* cx, uint32_t textId) {
-  if (!EnsureTraceLoggerState()) {
+  if (!traceLoggerState) {
     return;
   }
   traceLoggerState->enableTextId(cx, textId);
 }
 void js::TraceLogDisableTextId(JSContext* cx, uint32_t textId) {
-  if (!EnsureTraceLoggerState()) {
+  if (!traceLoggerState) {
     return;
   }
   traceLoggerState->disableTextId(cx, textId);
 }
 
 TraceLoggerEvent::TraceLoggerEvent(TraceLoggerTextId type, JSScript* script)
     : TraceLoggerEvent(type, script->filename(), script->lineno(),
                        script->column()) {}
@@ -1417,20 +1420,42 @@ TraceLoggerEvent& TraceLoggerEvent::oper
 
 TraceLoggerEvent::TraceLoggerEvent(const TraceLoggerEvent& other)
     : payload_(other.payload_) {
   if (hasExtPayload()) {
     extPayload()->use();
   }
 }
 
+JS_PUBLIC_API bool JS::InitTraceLogger() {
+  MOZ_RELEASE_ASSERT(!traceLoggerState);
+
+  if (!getTraceLoggerSupported()) {
+    return true;
+  }
+
+  traceLoggerState = js_new<TraceLoggerThreadState>();
+  if (!traceLoggerState) {
+    return false;
+  }
+
+  if (!traceLoggerState->init()) {
+    DestroyTraceLoggerThreadState();
+    return false;
+  }
+
+  return true;
+}
+
+JS_PUBLIC_API bool JS::TraceLoggerSupported() { return traceLoggerState; }
+
 JS_PUBLIC_API void JS::ResetTraceLogger(void) { js::ResetTraceLogger(); }
 
 JS_PUBLIC_API void JS::StartTraceLogger(JSContext* cx) {
-  if (!EnsureTraceLoggerState()) {
+  if (!traceLoggerState) {
     return;
   }
 
   if (!jit::JitOptions.enableTraceLogger) {
     LockGuard<Mutex> guard(traceLoggerState->lock);
     traceLoggerState->enableTextIdsForProfiler();
     jit::JitOptions.enableTraceLogger = true;
   }
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -3144,16 +3144,19 @@ uint32_t profiler_get_available_features
   ProfilerFeature::ClearJava(features);
 #endif
 #if !defined(HAVE_NATIVE_UNWIND)
   ProfilerFeature::ClearStackWalk(features);
 #endif
 #if !defined(MOZ_TASK_TRACER)
   ProfilerFeature::ClearTaskTracer(features);
 #endif
+  if (!JS::TraceLoggerSupported()) {
+    ProfilerFeature::ClearJSTracer(features);
+  }
 
   return features;
 }
 
 Maybe<ProfilerBufferInfo> profiler_get_buffer_info() {
   MOZ_RELEASE_ASSERT(CorePS::Exists());
 
   PSAutoLock lock(gPSMutex);