From 826712af6b162206a951e78b2b06df245799b6f7 Mon Sep 17 00:00:00 2001 From: Hannes Verschore Date: Tue, 18 Nov 2014 01:08:34 +0100 Subject: [PATCH] Bug 1092947: IonMonkey: Improve ion entry sequence, r=djvj --- js/src/jit/CodeGenerator.cpp | 58 ++++++------------- js/src/jit/arm/CodeGenerator-arm.cpp | 1 + js/src/jit/mips/CodeGenerator-mips.cpp | 2 + .../jit/shared/CodeGenerator-x86-shared.cpp | 2 +- js/src/jit/x64/MacroAssembler-x64.h | 16 ++++- js/src/jit/x86/MacroAssembler-x86.h | 16 ++++- 6 files changed, 50 insertions(+), 45 deletions(-) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 725171a12ee5..9704630a1e3e 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -2097,10 +2097,12 @@ CodeGenerator::visitOsrEntry(LOsrEntry *lir) } #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; } @@ -3594,23 +3596,6 @@ CodeGenerator::generateArgumentsChecks(bool bailout) 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(); @@ -3645,8 +3630,6 @@ CodeGenerator::generateArgumentsChecks(bool bailout) } } - masm.freeStack(frameSize()); - return true; } @@ -7456,14 +7439,8 @@ CodeGenerator::generate() 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 @@ -7477,14 +7454,19 @@ CodeGenerator::generate() return false; } -#ifdef JS_TRACE_LOGGING - Label skip; - masm.jump(&skip); -#endif + // Skip over the alternative entry to IonScript code. + Label skipPrologue; + masm.jump(&skipPrologue); - // Remember the entry offset to skip the argument check. + // 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) { @@ -7493,7 +7475,6 @@ CodeGenerator::generate() if (!emitTracelogStartEvent(TraceLogger::IonMonkey)) return false; } - masm.bind(&skip); #endif #ifdef DEBUG @@ -7502,9 +7483,6 @@ CodeGenerator::generate() return false; #endif - if (!generatePrologue()) - return false; - // Reset native => bytecode map table with top-level script and startPc. if (!addNativeToBytecodeEntry(startSite)) return false; diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 0f1eb14fbc09..a57c927bac91 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -40,6 +40,7 @@ CodeGeneratorARM::CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAsse bool CodeGeneratorARM::generatePrologue() { + MOZ_ASSERT(masm.framePushed() == 0); MOZ_ASSERT(!gen->compilingAsmJS()); // Note that this automatically sets MacroAssembler::framePushed(). diff --git a/js/src/jit/mips/CodeGenerator-mips.cpp b/js/src/jit/mips/CodeGenerator-mips.cpp index cc7eaab816f7..5daa595fa64e 100644 --- a/js/src/jit/mips/CodeGenerator-mips.cpp +++ b/js/src/jit/mips/CodeGenerator-mips.cpp @@ -40,7 +40,9 @@ CodeGeneratorMIPS::CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAs bool CodeGeneratorMIPS::generatePrologue() { + MOZ_ASSERT(masm.framePushed() == 0); MOZ_ASSERT(!gen->compilingAsmJS()); + // Note that this automatically sets MacroAssembler::framePushed(). masm.reserveStack(frameSize()); masm.checkStackAlignment(); diff --git a/js/src/jit/shared/CodeGenerator-x86-shared.cpp b/js/src/jit/shared/CodeGenerator-x86-shared.cpp index 9ee8ff3f50ac..c1f4980a277c 100644 --- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp @@ -41,11 +41,11 @@ CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *grap bool CodeGeneratorX86Shared::generatePrologue() { + MOZ_ASSERT(masm.framePushed() == 0); MOZ_ASSERT(!gen->compilingAsmJS()); // Note that this automatically sets MacroAssembler::framePushed(). masm.reserveStack(frameSize()); - return true; } diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index 9daf53b03579..72de86f59761 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -552,8 +552,20 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared // 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(4096), StackPointer); + store32(Imm32(0), Address(StackPointer, 0)); + amountLeft -= 4096; + } + subq(Imm32(amountLeft), StackPointer); + } framePushed_ += amount; } void freeStack(uint32_t amount) { diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 0694481ac905..0be91e26d5c9 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -565,8 +565,20 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared // 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) {