author | Hannes Verschore <hv1989@gmail.com> |
Fri, 19 Jul 2013 09:31:12 -0700 | |
changeset 139265 | 0f046ccc7b5388dc94182d3a86e4d7ebbc8934ab |
parent 139264 | e0dd0605ba1cf443752e8c59a5389b357f932a59 |
child 139266 | c30555419404d0aec3369cf416c877aef9eb81ad |
push id | 24983 |
push user | ryanvm@gmail.com |
push date | Sat, 20 Jul 2013 00:51:06 +0000 |
treeherder | mozilla-central@6030c759a502 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jandem |
bugs | 895019 |
milestone | 25.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
|
--- 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, ®s, 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;