Bug 1092947: IonMonkey: Improve ion entry sequence, r=djvj
☠☠ backed out by b5fdc0c44b6c ☠ ☠
authorHannes Verschore <hv1989@gmail.com>
Sat, 15 Nov 2014 00:04:26 +0100
changeset 240180 d94b6a6469b49f666334af051b62ef0a95aceb3d
parent 240179 e2efedec2d60562ea845f32740f8db2703337871
child 240181 08434d415b5c69d764ade5007868f0fb90624019
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdjvj
bugs1092947
milestone36.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 1092947: IonMonkey: Improve ion entry sequence, r=djvj
js/src/jit/CodeGenerator.cpp
js/src/jit/arm/CodeGenerator-arm.cpp
js/src/jit/mips/CodeGenerator-mips.cpp
js/src/jit/shared/CodeGenerator-x86-shared.cpp
js/src/jit/x64/MacroAssembler-x64.h
js/src/jit/x86/MacroAssembler-x86.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -2092,20 +2092,22 @@ CodeGenerator::visitOsrEntry(LOsrEntry *
     if (gen->info().executionMode() == SequentialExecution) {
         if (!emitTracelogStopEvent(TraceLogger::Baseline))
             return false;
         if (!emitTracelogStartEvent(TraceLogger::IonMonkey))
             return false;
     }
 #endif
 
-    // Allocate the full frame for this function.
-    uint32_t size = frameSize();
-    if (size != 0)
-        masm.subPtr(Imm32(size), StackPointer);
+    // Allocate the full frame for this function
+    // Note we have a new entry here. So we reset MacroAssembler::framePushed()
+    // to 0, before reserving the stack.
+    MOZ_ASSERT(masm.framePushed() == frameSize());
+    masm.setFramePushed(0);
+    masm.reserveStack(frameSize());
     return true;
 }
 
 bool
 CodeGenerator::visitOsrScopeChain(LOsrScopeChain *lir)
 {
     const LAllocation *frame   = lir->getOperand(0);
     const LDefinition *object  = lir->getDef(0);
@@ -3588,33 +3590,16 @@ CodeGenerator::generateArgumentsChecks(b
     // This function can be used the normal way to check the argument types,
     // before entering the function and bailout when arguments don't match.
     // For debug purpose, this is can also be used to force/check that the
     // arguments are correct. Upon fail it will hit a breakpoint.
 
     MIRGraph &mir = gen->graph();
     MResumePoint *rp = mir.entryResumePoint();
 
-    // Reserve the amount of stack the actual frame will use. We have to undo
-    // this before falling through to the method proper though, because the
-    // monomorphic call case will bypass this entire path.
-
-    // On windows, we cannot skip very far down the stack without touching the
-    // memory pages in-between.  This is a corner-case code for situations where the
-    // Ion frame data for a piece of code is very large.  To handle this special case,
-    // for frames over 1k in size we allocate memory on the stack incrementally, touching
-    // it as we go.
-    uint32_t frameSizeLeft = frameSize();
-    while (frameSizeLeft > 4096) {
-        masm.reserveStack(4096);
-        masm.store32(Imm32(0), Address(StackPointer, 0));
-        frameSizeLeft -= 4096;
-    }
-    masm.reserveStack(frameSizeLeft);
-
     // No registers are allocated yet, so it's safe to grab anything.
     Register temp = GeneralRegisterSet(EntryTempMask).getAny();
 
     CompileInfo &info = gen->info();
 
     Label miss;
     for (uint32_t i = info.startArgSlot(); i < info.endArgSlot(); i++) {
         // All initial parameters are guaranteed to be MParameters.
@@ -3639,18 +3624,16 @@ CodeGenerator::generateArgumentsChecks(b
             Label success;
             masm.jump(&success);
             masm.bind(&miss);
             masm.assumeUnreachable("Argument check fail.");
             masm.bind(&success);
         }
     }
 
-    masm.freeStack(frameSize());
-
     return true;
 }
 
 // Out-of-line path to report over-recursed error and fail.
 class CheckOverRecursedFailure : public OutOfLineCodeBase<CodeGenerator>
 {
     LInstruction *lir_;
 
@@ -7436,65 +7419,60 @@ CodeGenerator::generate()
         return false;
 
     if (!snapshots_.init())
         return false;
 
     if (!safepoints_.init(gen->alloc(), graph.totalSlotCount()))
         return false;
 
-#ifdef JS_TRACE_LOGGING
-    if (!gen->compilingAsmJS() && gen->info().executionMode() == SequentialExecution) {
-        if (!emitTracelogScriptStart())
-            return false;
-        if (!emitTracelogStartEvent(TraceLogger::IonMonkey))
-            return false;
-    }
-#endif
+    if (!generatePrologue())
+        return false;
 
     // 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_ = gen->jitRuntime()->getBailoutTable(frameClass_);
         if (!deoptTable_)
             return false;
     }
 
-#ifdef JS_TRACE_LOGGING
-    Label skip;
-    masm.jump(&skip);
-#endif
-
-    // Remember the entry offset to skip the argument check.
+    // Skip over the alternative entry to IonScript code.
+    Label skipPrologue;
+    masm.jump(&skipPrologue);
+
+    // An alternative entry to the IonScript code, which doesn't test the
+    // arguments.
     masm.flushBuffer();
     setSkipArgCheckEntryOffset(masm.size());
+    masm.setFramePushed(0);
+    if (!generatePrologue())
+        return false;
+
+    masm.bind(&skipPrologue);
 
 #ifdef JS_TRACE_LOGGING
     if (!gen->compilingAsmJS() && gen->info().executionMode() == SequentialExecution) {
         if (!emitTracelogScriptStart())
             return false;
         if (!emitTracelogStartEvent(TraceLogger::IonMonkey))
             return false;
     }
-    masm.bind(&skip);
 #endif
 
 #ifdef DEBUG
     // Assert that the argument types are correct.
     if (!generateArgumentsChecks(/* bailout = */ false))
         return false;
 #endif
 
-    if (!generatePrologue())
-        return false;
-
     // Reset native => bytecode map table with top-level script and startPc.
     if (!addNativeToBytecodeEntry(startSite))
         return false;
 
     if (!generateBody())
         return false;
 
     // Reset native => bytecode map table with top-level script and startPc.
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -35,16 +35,17 @@ using JS::GenericNaN;
 CodeGeneratorARM::CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorShared(gen, graph, masm)
 {
 }
 
 bool
 CodeGeneratorARM::generatePrologue()
 {
+    MOZ_ASSERT(masm.framePushed() == 0);
     MOZ_ASSERT(!gen->compilingAsmJS());
 
     // Note that this automatically sets MacroAssembler::framePushed().
     masm.reserveStack(frameSize());
     masm.checkStackAlignment();
     return true;
 }
 
--- a/js/src/jit/mips/CodeGenerator-mips.cpp
+++ b/js/src/jit/mips/CodeGenerator-mips.cpp
@@ -35,17 +35,19 @@ using JS::GenericNaN;
 CodeGeneratorMIPS::CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorShared(gen, graph, masm)
 {
 }
 
 bool
 CodeGeneratorMIPS::generatePrologue()
 {
+    MOZ_ASSERT(masm.framePushed() == 0);
     MOZ_ASSERT(!gen->compilingAsmJS());
+
     // Note that this automatically sets MacroAssembler::framePushed().
     masm.reserveStack(frameSize());
     masm.checkStackAlignment();
     return true;
 }
 
 bool
 CodeGeneratorMIPS::generateEpilogue()
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -36,21 +36,21 @@ namespace jit {
 CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm)
   : CodeGeneratorShared(gen, graph, masm)
 {
 }
 
 bool
 CodeGeneratorX86Shared::generatePrologue()
 {
+    MOZ_ASSERT(masm.framePushed() == 0);
     MOZ_ASSERT(!gen->compilingAsmJS());
 
     // Note that this automatically sets MacroAssembler::framePushed().
     masm.reserveStack(frameSize());
-
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::generateEpilogue()
 {
     MOZ_ASSERT(!gen->compilingAsmJS());
 
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -547,18 +547,30 @@ class MacroAssemblerX64 : public MacroAs
         cmpPtr(lhs, rhs);
         emitSet(cond, dest);
     }
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
     void reserveStack(uint32_t amount) {
-        if (amount)
-            subq(Imm32(amount), StackPointer);
+        if (amount) {
+            // On windows, we cannot skip very far down the stack without touching the
+            // memory pages in-between.  This is a corner-case code for situations where the
+            // Ion frame data for a piece of code is very large.  To handle this special case,
+            // for frames over 1k in size we allocate memory on the stack incrementally, touching
+            // it as we go.
+            uint32_t amountLeft = amount;
+            while (amountLeft > 4096) {
+                subq(Imm32(amount), StackPointer);
+                store32(Imm32(0), Address(StackPointer, 0));
+                amountLeft -= 4096;
+            }
+            subq(Imm32(amountLeft), StackPointer);
+        }
         framePushed_ += amount;
     }
     void freeStack(uint32_t amount) {
         MOZ_ASSERT(amount <= framePushed_);
         if (amount)
             addq(Imm32(amount), StackPointer);
         framePushed_ -= amount;
     }
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -560,18 +560,30 @@ class MacroAssemblerX86 : public MacroAs
         cmpPtr(lhs, rhs);
         emitSet(cond, dest);
     }
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
     void reserveStack(uint32_t amount) {
-        if (amount)
-            subl(Imm32(amount), StackPointer);
+        if (amount) {
+            // On windows, we cannot skip very far down the stack without touching the
+            // memory pages in-between.  This is a corner-case code for situations where the
+            // Ion frame data for a piece of code is very large.  To handle this special case,
+            // for frames over 1k in size we allocate memory on the stack incrementally, touching
+            // it as we go.
+            uint32_t amountLeft = amount;
+            while (amountLeft > 4096) {
+                subl(Imm32(4096), StackPointer);
+                store32(Imm32(0), Address(StackPointer, 0));
+                amountLeft -= 4096;
+            }
+            subl(Imm32(amountLeft), StackPointer);
+        }
         framePushed_ += amount;
     }
     void freeStack(uint32_t amount) {
         MOZ_ASSERT(amount <= framePushed_);
         if (amount)
             addl(Imm32(amount), StackPointer);
         framePushed_ -= amount;
     }