Bug 895019: Cleanup and make the tracelogger work again, r=jandem
authorHannes Verschore <hv1989@gmail.com>
Fri, 19 Jul 2013 09:31:12 -0700
changeset 151550 0f046ccc7b5388dc94182d3a86e4d7ebbc8934ab
parent 151549 e0dd0605ba1cf443752e8c59a5389b357f932a59
child 151551 c30555419404d0aec3369cf416c877aef9eb81ad
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs895019
milestone25.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 895019: Cleanup and make the tracelogger work again, r=jandem
js/src/TraceLogging.cpp
js/src/TraceLogging.h
js/src/ion/BaselineBailouts.cpp
js/src/ion/BaselineCompiler.cpp
js/src/ion/BaselineJIT.cpp
js/src/ion/CodeGenerator.cpp
js/src/ion/Ion.cpp
js/src/ion/IonMacroAssembler.cpp
js/src/ion/IonMacroAssembler.h
js/src/ion/arm/CodeGenerator-arm.cpp
js/src/ion/shared/CodeGenerator-x86-shared.cpp
js/src/vm/Interpreter.cpp
--- a/js/src/TraceLogging.cpp
+++ b/js/src/TraceLogging.cpp
@@ -19,33 +19,33 @@ using namespace js;
 #  define TRACE_LOG_DIR ""
 # else
 #  define TRACE_LOG_DIR "/tmp/"
 # endif
 #endif
 
 #if defined(__i386__)
 static __inline__ uint64_t
-js::rdtsc(void)
+rdtsc(void)
 {
     uint64_t x;
     __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
     return x;
 }
 #elif defined(__x86_64__)
 static __inline__ uint64_t
-js::rdtsc(void)
+rdtsc(void)
 {
     unsigned hi, lo;
     __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
     return ( (uint64_t)lo)|( ((uint64_t)hi)<<32 );
 }
 #elif defined(__powerpc__)
 static __inline__ uint64_t
-js::rdtsc(void)
+rdtsc(void)
 {
     uint64_t result=0;
     uint32_t upper, lower,tmp;
     __asm__ volatile(
             "0:                  \n"
             "\tmftbu   %0           \n"
             "\tmftb    %1           \n"
             "\tmftbu   %2           \n"
@@ -57,36 +57,27 @@ js::rdtsc(void)
     result = result<<32;
     result = result|lower;
 
     return(result);
 }
 #endif
 
 const char* const TraceLogging::type_name[] = {
+    "start,script",
+    "stop,script",
     "start,ion_compile",
     "stop,ion_compile",
-    "start,ion_cannon",
-    "stop,ion_cannon",
-    "stop,ion_cannon_bailout",
-    "start,ion_side_cannon",
-    "stop,ion_side_cannon",
-    "stop,ion_side_cannon_bailout",
     "start,yarr_jit_execute",
     "stop,yarr_jit_execute",
-    "start,jm_safepoint",
-    "stop,jm_safepoint",
-    "start,jm_normal",
-    "stop,jm_normal",
-    "start,jm_compile",
-    "stop,jm_compile",
     "start,gc",
     "stop,gc",
-    "start,interpreter",
-    "stop,interpreter"
+    "info,engine,interpreter",
+    "info,engine,baseline",
+    "info,engine,ionmonkey"
 };
 TraceLogging* TraceLogging::_defaultLogger = NULL;
 
 TraceLogging::TraceLogging()
   : loggingTime(0),
     entries(NULL),
     curEntry(0),
     numEntries(1000000),
@@ -152,17 +143,17 @@ TraceLogging::log(Type type, const char*
     // Save the time spend logging the information in order to discard this time from the logged time.
     // Especially needed when increasing the array or flushing the information.
     loggingTime += rdtsc()-now;
 }
 
 void
 TraceLogging::log(Type type, JSScript* script)
 {
-    this->log(type, script->filename, script->lineno);
+    this->log(type, script->filename(), script->lineno);
 }
 
 void
 TraceLogging::log(const char* log)
 {
     this->log(INFO, log, 0);
 }
 
--- a/js/src/TraceLogging.h
+++ b/js/src/TraceLogging.h
@@ -10,36 +10,27 @@
 #include "jsscript.h"
 
 namespace js {
 
 class TraceLogging
 {
   public:
     enum Type {
+        SCRIPT_START,
+        SCRIPT_STOP,
         ION_COMPILE_START,
         ION_COMPILE_STOP,
-        ION_CANNON_START,
-        ION_CANNON_STOP,
-        ION_CANNON_BAIL,
-        ION_SIDE_CANNON_START,
-        ION_SIDE_CANNON_STOP,
-        ION_SIDE_CANNON_BAIL,
         YARR_JIT_START,
         YARR_JIT_STOP,
-        JM_SAFEPOINT_START,
-        JM_SAFEPOINT_STOP,
-        JM_START,
-        JM_STOP,
-        JM_COMPILE_START,
-        JM_COMPILE_STOP,
         GC_START,
         GC_STOP,
-        INTERPRETER_START,
-        INTERPRETER_STOP,
+        INFO_ENGINE_INTERPRETER,
+        INFO_ENGINE_BASELINE,
+        INFO_ENGINE_IONMONKEY,
         INFO
     };
 
   private:
     struct Entry {
         uint64_t tick_;
         char* file_;
         uint32_t lineno_;
--- a/js/src/ion/BaselineBailouts.cpp
+++ b/js/src/ion/BaselineBailouts.cpp
@@ -1027,16 +1027,20 @@ InitFromBailout(JSContext *cx, HandleScr
 
 uint32_t
 ion::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, IonBailoutIterator &iter,
                           bool invalidate, BaselineBailoutInfo **bailoutInfo)
 {
     JS_ASSERT(bailoutInfo != NULL);
     JS_ASSERT(*bailoutInfo == NULL);
 
+#if JS_TRACE_LOGGING
+    TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_BASELINE);
+#endif
+
     // The caller of the top frame must be one of the following:
     //      OptimizedJS - Ion calling into Ion.
     //      BaselineStub - Baseline calling into Ion.
     //      Entry - Interpreter or other calling into Ion.
     //      Rectifier - Arguments rectifier calling into Ion.
     JS_ASSERT(iter.isOptimizedJS());
     FrameType prevFrameType = iter.prevType();
     JS_ASSERT(prevFrameType == IonFrame_OptimizedJS ||
@@ -1102,16 +1106,22 @@ ion::BailoutIonToBaseline(JSContext *cx,
 
     // Reconstruct baseline frames using the builder.
     RootedScript caller(cx);
     jsbytecode *callerPC = NULL;
     RootedFunction fun(cx, callee);
     RootedScript scr(cx, iter.script());
     AutoValueVector startFrameFormals(cx);
     while (true) {
+#if JS_TRACE_LOGGING
+        if (frameNo > 0) {
+            TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_START, scr);
+            TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_BASELINE);
+        }
+#endif
         IonSpew(IonSpew_BaselineBailouts, "    FrameNo %d", frameNo);
         jsbytecode *callPC = NULL;
         RootedFunction nextCallee(cx, NULL);
         if (!InitFromBailout(cx, caller, callerPC, fun, scr, iter.ionScript(),
                              snapIter, invalidate, builder, startFrameFormals,
                              &nextCallee, &callPC))
         {
             return BAILOUT_RETURN_FATAL_ERROR;
--- a/js/src/ion/BaselineCompiler.cpp
+++ b/js/src/ion/BaselineCompiler.cpp
@@ -79,16 +79,17 @@ BaselineCompiler::compile()
 
     if (!emitPrologue())
         return Method_Error;
 
     MethodStatus status = emitBody();
     if (status != Method_Compiled)
         return status;
 
+
     if (!emitEpilogue())
         return Method_Error;
 
 #ifdef JSGC_GENERATIONAL
     if (!emitOutOfLinePostBarrierSlot())
         return Method_Error;
 #endif
 
@@ -219,16 +220,21 @@ BaselineCompiler::emitPrologue()
 
     // Initialize locals to |undefined|. Use R0 to minimize code size.
     if (frame.nlocals() > 0) {
         masm.moveValue(UndefinedValue(), R0);
         for (size_t i = 0; i < frame.nlocals(); i++)
             masm.pushValue(R0);
     }
 
+#if JS_TRACE_LOGGING
+    masm.tracelogStart(script.get());
+    masm.tracelogLog(TraceLogging::INFO_ENGINE_BASELINE);
+#endif
+
     // Record the offset of the prologue, because Ion can bailout before
     // the scope chain is initialized.
     prologueOffset_ = masm.currentOffset();
 
     // Initialize the scope chain before any operation that may
     // call into the VM and trigger a GC.
     if (!initScopeChain())
         return false;
@@ -251,16 +257,20 @@ BaselineCompiler::emitPrologue()
     return true;
 }
 
 bool
 BaselineCompiler::emitEpilogue()
 {
     masm.bind(&return_);
 
+#if JS_TRACE_LOGGING
+    masm.tracelogStop();
+#endif
+
     // Pop SPS frame if necessary
     emitSPSPop();
 
     masm.mov(BaselineFrameReg, BaselineStackReg);
     masm.pop(BaselineFrameReg);
 
     masm.ret();
     return true;
--- a/js/src/ion/BaselineJIT.cpp
+++ b/js/src/ion/BaselineJIT.cpp
@@ -180,16 +180,20 @@ ion::EnterBaselineAtBranch(JSContext *cx
 
         // For eval function frames, set the callee token to the enclosing function.
         if (fp->isFunctionFrame())
             data.calleeToken = CalleeToToken(&fp->callee());
         else
             data.calleeToken = CalleeToToken(fp->script());
     }
 
+#if JS_TRACE_LOGGING
+    TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_BASELINE);
+#endif
+
     IonExecStatus status = EnterBaseline(cx, data);
     if (status != IonExec_Ok)
         return status;
 
     fp->setReturnValue(data.result);
     return IonExec_Ok;
 }
 
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -892,16 +892,20 @@ CodeGenerator::visitReturn(LReturn *lir)
 
 bool
 CodeGenerator::visitOsrEntry(LOsrEntry *lir)
 {
     // Remember the OSR entry offset into the code buffer.
     masm.flushBuffer();
     setOsrEntryOffset(masm.size());
 
+#if JS_TRACE_LOGGING
+    masm.tracelogLog(TraceLogging::INFO_ENGINE_IONMONKEY);
+#endif
+
     // Allocate the full frame for this function.
     uint32_t size = frameSize();
     if (size != 0)
         masm.subPtr(Imm32(size), StackPointer);
     return true;
 }
 
 bool
@@ -5416,32 +5420,48 @@ CodeGenerator::generateAsmJS()
 }
 
 bool
 CodeGenerator::generate()
 {
     if (!safepoints_.init(graph.totalSlotCount()))
         return false;
 
+#if JS_TRACE_LOGGING
+    masm.tracelogStart(gen->info().script());
+    masm.tracelogLog(TraceLogging::INFO_ENGINE_IONMONKEY);
+#endif
+
     // Before generating any code, we generate type checks for all parameters.
     // This comes before deoptTable_, because we can't use deopt tables without
     // creating the actual frame.
     if (!generateArgumentsChecks())
         return false;
 
     if (frameClass_ != FrameSizeClass::None()) {
         deoptTable_ = GetIonContext()->compartment->ionCompartment()->getBailoutTable(frameClass_);
         if (!deoptTable_)
             return false;
     }
 
+#if JS_TRACE_LOGGING
+    Label skip;
+    masm.jump(&skip);
+#endif
+
     // Remember the entry offset to skip the argument check.
     masm.flushBuffer();
     setSkipArgCheckEntryOffset(masm.size());
 
+#if JS_TRACE_LOGGING
+    masm.tracelogStart(gen->info().script());
+    masm.tracelogLog(TraceLogging::INFO_ENGINE_IONMONKEY);
+    masm.bind(&skip);
+#endif
+
     if (!generatePrologue())
         return false;
     if (!generateBody())
         return false;
     if (!generateEpilogue())
         return false;
     if (!generateInvalidateEpilogue())
         return false;
--- a/js/src/ion/Ion.cpp
+++ b/js/src/ion/Ion.cpp
@@ -1922,30 +1922,18 @@ ion::Cannon(JSContext *cx, RunState &sta
 
     EnterJitData data(cx);
     data.jitcode = ion->method()->raw();
 
     AutoValueVector vals(cx);
     if (!SetEnterJitData(cx, data, state, vals))
         return IonExec_Error;
 
-#if JS_TRACE_LOGGING
-    TraceLog(TraceLogging::defaultLogger(),
-             TraceLogging::ION_CANNON_START,
-             script);
-#endif
-
     IonExecStatus status = EnterIon(cx, data);
 
-#if JS_TRACE_LOGGING
-    TraceLog(TraceLogging::defaultLogger(),
-             TraceLogging::ION_CANNON_STOP,
-             script);
-#endif
-
     if (status == IonExec_Ok)
         state.setReturnValue(data.result);
 
     return status;
 }
 
 IonExecStatus
 ion::FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args)
--- a/js/src/ion/IonMacroAssembler.cpp
+++ b/js/src/ion/IonMacroAssembler.cpp
@@ -1228,16 +1228,84 @@ MacroAssembler::printf(const char *outpu
     movePtr(ImmWord(output), temp);
     passABIArg(temp);
     passABIArg(value);
     callWithABI(JS_FUNC_TO_DATA_PTR(void *, printf1_));
 
     PopRegsInMask(RegisterSet::Volatile());
 }
 
+#if JS_TRACE_LOGGING
+void
+MacroAssembler::tracelogStart(JSScript *script)
+{
+    void (&TraceLogStart)(TraceLogging*, TraceLogging::Type, JSScript*) = TraceLog;
+    RegisterSet regs = RegisterSet::Volatile();
+    PushRegsInMask(regs);
+
+    Register temp = regs.takeGeneral();
+    Register logger = regs.takeGeneral();
+    Register type = regs.takeGeneral();
+    Register rscript = regs.takeGeneral();
+
+    setupUnalignedABICall(3, temp);
+    movePtr(ImmWord((void *)TraceLogging::defaultLogger()), logger);
+    passABIArg(logger);
+    move32(Imm32(TraceLogging::SCRIPT_START), type);
+    passABIArg(type);
+    movePtr(ImmGCPtr(script), rscript);
+    passABIArg(rscript);
+    callWithABI(JS_FUNC_TO_DATA_PTR(void *, TraceLogStart));
+
+    PopRegsInMask(RegisterSet::Volatile());
+}
+
+void
+MacroAssembler::tracelogStop()
+{
+    void (&TraceLogStop)(TraceLogging*, TraceLogging::Type) = TraceLog;
+    RegisterSet regs = RegisterSet::Volatile();
+    PushRegsInMask(regs);
+
+    Register temp = regs.takeGeneral();
+    Register logger = regs.takeGeneral();
+    Register type = regs.takeGeneral();
+
+    setupUnalignedABICall(2, temp);
+    movePtr(ImmWord((void *)TraceLogging::defaultLogger()), logger);
+    passABIArg(logger);
+    move32(Imm32(TraceLogging::SCRIPT_STOP), type);
+    passABIArg(type);
+    callWithABI(JS_FUNC_TO_DATA_PTR(void *, TraceLogStop));
+
+    PopRegsInMask(RegisterSet::Volatile());
+}
+
+void
+MacroAssembler::tracelogLog(TraceLogging::Type type)
+{
+    void (&TraceLogStop)(TraceLogging*, TraceLogging::Type) = TraceLog;
+    RegisterSet regs = RegisterSet::Volatile();
+    PushRegsInMask(regs);
+
+    Register temp = regs.takeGeneral();
+    Register logger = regs.takeGeneral();
+    Register rtype = regs.takeGeneral();
+
+    setupUnalignedABICall(2, temp);
+    movePtr(ImmWord((void *)TraceLogging::defaultLogger()), logger);
+    passABIArg(logger);
+    move32(Imm32(type), rtype);
+    passABIArg(rtype);
+    callWithABI(JS_FUNC_TO_DATA_PTR(void *, TraceLogStop));
+
+    PopRegsInMask(RegisterSet::Volatile());
+}
+#endif
+
 void
 MacroAssembler::convertInt32ValueToDouble(const Address &address, Register scratch, Label *done)
 {
     branchTestInt32(Assembler::NotEqual, address, done);
     unboxInt32(address, scratch);
     convertInt32ToDouble(scratch, ScratchFloatReg);
     storeDouble(ScratchFloatReg, address);
 }
--- a/js/src/ion/IonMacroAssembler.h
+++ b/js/src/ion/IonMacroAssembler.h
@@ -939,16 +939,22 @@ class MacroAssembler : public MacroAssem
     void pushBaselineFramePtr(Register framePtr, Register scratch) {
         loadBaselineFramePtr(framePtr, scratch);
         push(scratch);
     }
 
     void printf(const char *output);
     void printf(const char *output, Register value);
 
+#if JS_TRACE_LOGGING
+    void tracelogStart(JSScript *script);
+    void tracelogStop();
+    void tracelogLog(TraceLogging::Type type);
+#endif
+
     void convertInt32ValueToDouble(const Address &address, Register scratch, Label *done);
     void convertValueToDouble(ValueOperand value, FloatRegister output, Label *fail);
     void convertValueToInt32(ValueOperand value, FloatRegister temp, Register output, Label *fail);
 };
 
 static inline Assembler::DoubleCondition
 JSOpToDoubleCondition(JSOp op)
 {
--- a/js/src/ion/arm/CodeGenerator-arm.cpp
+++ b/js/src/ion/arm/CodeGenerator-arm.cpp
@@ -50,16 +50,19 @@ CodeGeneratorARM::generatePrologue()
 
     return true;
 }
 
 bool
 CodeGeneratorARM::generateEpilogue()
 {
     masm.bind(&returnLabel_); 
+#if JS_TRACE_LOGGING
+    masm.tracelogStop();
+#endif
     if (gen->compilingAsmJS()) {
         // Pop the stack we allocated at the start of the function.
         masm.freeStack(frameDepth_);
         masm.Pop(pc);
         JS_ASSERT(masm.framePushed() == 0);
         //masm.as_bkpt();
     } else {
         // Pop the stack we allocated at the start of the function.
--- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp
@@ -44,16 +44,20 @@ CodeGeneratorX86Shared::generatePrologue
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::generateEpilogue()
 {
     masm.bind(&returnLabel_);
 
+#if JS_TRACE_LOGGING
+    masm.tracelogStop();
+#endif
+
     // Pop the stack we allocated at the start of the function.
     masm.freeStack(frameSize());
     JS_ASSERT(masm.framePushed() == 0);
 
     masm.ret();
     return true;
 }
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1368,20 +1368,18 @@ Interpret(JSContext *cx, RunState &state
     InterpreterFrames interpreterFrame(cx, &regs, interrupts);
 
     /* Copy in hot values that change infrequently. */
     JSRuntime *const rt = cx->runtime();
     RootedScript script(cx);
     SET_SCRIPT(regs.fp()->script());
 
 #if JS_TRACE_LOGGING
-    AutoTraceLog logger(TraceLogging::defaultLogger(),
-                        TraceLogging::INTERPRETER_START,
-                        TraceLogging::INTERPRETER_STOP,
-                        script);
+    TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_START, script);
+    TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_INTERPRETER);
 #endif
 
     /*
      * Pool of rooters for use in this interpreter frame. References to these
      * are used for local variables within interpreter cases. This avoids
      * creating new rooters each time an interpreter case is entered, and also
      * correctness pitfalls due to incorrect compilation of destructor calls
      * around computed gotos.
@@ -1684,16 +1682,20 @@ BEGIN_CASE(JSOP_RETRVAL)    /* fp return
 BEGIN_CASE(JSOP_STOP)
 {
     /*
      * When the inlined frame exits with an exception or an error, ok will be
      * false after the inline_return label.
      */
     CHECK_BRANCH();
 
+#if JS_TRACE_LOGGING
+    TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_STOP);
+#endif
+
     interpReturnOK = true;
     if (entryFrame != regs.fp())
   inline_return:
     {
         if (cx->compartment()->debugMode())
             interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
 
         if (!regs.fp()->isYielding())
@@ -2546,16 +2548,21 @@ BEGIN_CASE(JSOP_FUNCALL)
     if (!activation.pushInlineFrame(args, funScript, initial))
         goto error;
 
     if (newType)
         regs.fp()->setUseNewType();
 
     SET_SCRIPT(regs.fp()->script());
 
+#if JS_TRACE_LOGGING
+    TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_START, script);
+    TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_INTERPRETER);
+#endif
+
     if (!regs.fp()->prologue(cx))
         goto error;
     if (cx->compartment()->debugMode()) {
         switch (ScriptDebugPrologue(cx, regs.fp())) {
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
             interpReturnOK = true;