From 173796cc35640a600e0cf978226deaaa98dde01d Mon Sep 17 00:00:00 2001 From: Sean Stangl Date: Wed, 14 Sep 2011 11:13:50 -0700 Subject: [PATCH] Mark frame types correctly. (Bug 685099, r=dvander) --- js/src/ion/IonFrames.h | 17 +++++++++-- .../ion/shared/CodeGenerator-x86-shared.cpp | 4 +-- js/src/ion/x64/Trampoline-x64.cpp | 30 ++++++++++--------- js/src/ion/x86/Trampoline-x86.cpp | 23 ++++++++------ 4 files changed, 46 insertions(+), 28 deletions(-) diff --git a/js/src/ion/IonFrames.h b/js/src/ion/IonFrames.h index ab8b604c5da3..de919c124374 100644 --- a/js/src/ion/IonFrames.h +++ b/js/src/ion/IonFrames.h @@ -57,7 +57,7 @@ namespace ion { // arg0 / // this _/ // calleeToken - Encodes script or JSFunction -// descriptor - Size of the parent frame +// sizeDescriptor - Size of the parent frame, with lower bits for FrameType. // returnAddr - Return address, entering into the next call. // .. locals .. @@ -72,15 +72,26 @@ struct IonFrameData class IonFramePrefix : protected IonFrameData { + public: + enum FrameType { + JSFrame, + EntryFrame, + RectifierFrame + }; + + // The FrameType is packed into the sizeDescriptor by left-shifting the + // sizeDescriptor by FrameTypeBits, then ORing in the FrameType. + static const unsigned FrameTypeBits = 2; + public: // True if this is the frame passed into EnterIonCode. bool isEntryFrame() const { - return !(sizeDescriptor_ & 1); + return !!(sizeDescriptor_ & EntryFrame); } // The depth of the parent frame. size_t prevFrameDepth() const { JS_ASSERT(!isEntryFrame()); - return sizeDescriptor_ >> 1; + return sizeDescriptor_ >> FrameTypeBits; } IonFramePrefix *prev() const { JS_ASSERT(!isEntryFrame()); diff --git a/js/src/ion/shared/CodeGenerator-x86-shared.cpp b/js/src/ion/shared/CodeGenerator-x86-shared.cpp index b8f9710410f4..72157051b197 100644 --- a/js/src/ion/shared/CodeGenerator-x86-shared.cpp +++ b/js/src/ion/shared/CodeGenerator-x86-shared.cpp @@ -727,9 +727,9 @@ CodeGeneratorX86Shared::visitCallGeneric(LCallGeneric *call) return false; // Remember the size of the frame above this point, in case of bailout. + JS_STATIC_ASSERT(IonFramePrefix::JSFrame == 0x0); uint32 stack_size = masm.framePushed() - unused_stack; - // Mark !IonFramePrefix::isEntryFrame(). - uint32 size_descriptor = stack_size << 1; + uint32 size_descriptor = stack_size << IonFramePrefix::FrameTypeBits; // Nestle %esp up to the argument vector. if (unused_stack) diff --git a/js/src/ion/x64/Trampoline-x64.cpp b/js/src/ion/x64/Trampoline-x64.cpp index 9d6f53e3eb59..4941f023546c 100644 --- a/js/src/ion/x64/Trampoline-x64.cpp +++ b/js/src/ion/x64/Trampoline-x64.cpp @@ -154,14 +154,17 @@ IonCompartment::generateEnterJIT(JSContext *cx) Push the number of bytes we've pushed so far on the stack and call *****************************************************************/ masm.subq(rsp, r14); + // Safe to not shift sizeDescriptor: no other consumers. + masm.orl(Imm32(0x1), r14); // Mark EntryFrame. masm.push(r14); // Call function. masm.call(reg_code); // Pop arguments and padding from stack. - masm.pop(r14); - masm.addq(r14, rsp); + masm.pop(r14); // sizeDescriptor. + masm.xorl(Imm32(0x1), r14); // Unmark EntryFrame. + masm.addq(r14, rsp); // Remove arguments. /***************************************************************** Place return value where it belongs, pop all saved registers @@ -180,13 +183,10 @@ IonCompartment::generateReturnError(JSContext *cx) { MacroAssembler masm(cx); - // Pop arguments off the stack. - // eax <- 8*argc (size of all arguments we pushed on the stack) - masm.pop(r14); - masm.addq(r14, rsp); - - // Discard pushed vp. - masm.pop(r11); + masm.pop(r14); // sizeDescriptor. + masm.xorl(Imm32(0x1), r14); // Unmark EntryFrame. + masm.addq(r14, rsp); // Remove arguments. + masm.pop(r11); // Discard |vp|: returning from error. GenerateReturn(masm, JS_FALSE); @@ -250,8 +250,10 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx) masm.j(Assembler::NonZero, ©LoopTop); } + // Construct sizeDescriptor. masm.subq(rsp, rbp); - masm.shll(Imm32(1), rbp); // construct sizeDescriptor. + masm.shll(Imm32(IonFramePrefix::FrameTypeBits), rbp); + masm.orl(Imm32(IonFramePrefix::RectifierFrame), rbp); // Construct IonFrameData. masm.push(rax); // calleeToken. @@ -266,10 +268,10 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx) masm.call(rax); // Remove the rectifier frame. - masm.pop(rbx); // rbx <- sizeDescriptor_ - masm.shrl(Imm32(1), rbx); // rbx <- size of pushed arguments - masm.pop(r11); // Discard calleeToken_ - masm.addq(rbx, rsp); // Discard pushed arguments. + masm.pop(rbp); // rbp <- sizeDescriptor with FrameType. + masm.shrl(Imm32(IonFramePrefix::FrameTypeBits), rbp); // rbp <- size of pushed arguments. + masm.pop(r11); // Discard calleeToken. + masm.addq(rbp, rsp); // Discard pushed arguments. masm.ret(); diff --git a/js/src/ion/x86/Trampoline-x86.cpp b/js/src/ion/x86/Trampoline-x86.cpp index e5216377b652..84c095d7704d 100644 --- a/js/src/ion/x86/Trampoline-x86.cpp +++ b/js/src/ion/x86/Trampoline-x86.cpp @@ -141,6 +141,9 @@ IonCompartment::generateEnterJIT(JSContext *cx) masm.shll(Imm32(3), eax); masm.addl(eax, ecx); masm.addl(Imm32(4), ecx); + + // Safe to take lowest bit without shifting: aligned, and no other consumers. + masm.orl(Imm32(0x1), ecx); // Mark EntryFrame. masm.push(ecx); /*************************************************************** @@ -153,6 +156,7 @@ IonCompartment::generateEnterJIT(JSContext *cx) // Pop arguments off the stack. // eax <- 8*argc (size of all arugments we pushed on the stack) masm.pop(eax); + masm.xorl(Imm32(0x1), eax); // Unmark EntryFrame. masm.addl(eax, esp); // |ebp| could have been clobbered by the inner function. For now, re-grab @@ -185,10 +189,9 @@ IonCompartment::generateReturnError(JSContext *cx) { MacroAssembler masm(cx); - // Pop arguments off the stack. - // eax <- 8*argc (size of all arugments we pushed on the stack) - masm.pop(eax); - masm.addl(eax, esp); + masm.pop(eax); // sizeDescriptor. + masm.xorl(Imm32(0x1), eax); // Unmark EntryFrame. + masm.addl(eax, esp); // Remove arguments. GenerateReturn(masm, JS_FALSE); @@ -255,8 +258,10 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx) masm.j(Assembler::NonZero, ©LoopTop); } + // Construct sizeDescriptor. masm.subl(esp, ebp); - masm.shll(Imm32(1), ebp); // construct sizeDescriptor. + masm.shll(Imm32(IonFramePrefix::FrameTypeBits), ebp); + masm.orl(Imm32(IonFramePrefix::RectifierFrame), ebp); // Construct IonFrameData. masm.push(eax); // calleeToken @@ -271,10 +276,10 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx) masm.call(eax); // Remove the rectifier frame. - masm.pop(ebx); // ebx <- sizeDescriptor - masm.shrl(Imm32(1), ebx); // ebx <- size of pushed arguments - masm.pop(edi); // Discard calleeToken - masm.addl(ebx, esp); // Discard pushed arguments. + masm.pop(ebp); // ebp <- sizeDescriptor with FrameType. + masm.shrl(Imm32(IonFramePrefix::FrameTypeBits), ebp); // ebp <- sizeDescriptor. + masm.pop(edi); // Discard calleeToken. + masm.addl(ebp, esp); // Discard pushed arguments. masm.ret();