Bug 1112160 - Baseline Stubs: Align the stack when the number of argument is statically known. r=jandem

This commit is contained in:
Nicolas B. Pierron 2015-02-12 14:53:06 +01:00
parent d0f0f47d58
commit 4041d7bf8f
3 changed files with 67 additions and 11 deletions

View File

@ -4099,6 +4099,10 @@ ICGetElemNativeCompiler::emitCallScripted(MacroAssembler &masm, Register objReg)
// Enter stub frame.
enterStubFrame(masm, regs.getAny());
// Align the stack such that the JitFrameLayout is aligned on
// JitStackAlignment.
masm.alignJitStackBasedOnNArgs(0);
// Push |this| for getter (target object).
{
ValueOperand val = regs.takeAnyValue();
@ -7372,6 +7376,10 @@ ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
masm.loadBaselineOrIonRaw(code, code, &failureLeaveStubFrame);
// Align the stack such that the JitFrameLayout is aligned on
// JitStackAlignment.
masm.alignJitStackBasedOnNArgs(0);
// Getter is called with 0 arguments, just |obj| as thisv.
// Note that we use Push, not push, so that callJit will align the stack
// properly on ARM.
@ -8866,14 +8874,17 @@ ICSetProp_CallScripted::Compiler::generateStubCode(MacroAssembler &masm)
masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
masm.loadBaselineOrIonRaw(code, code, &failureLeaveStubFrame);
// Align the stack such that the JitFrameLayout is aligned on
// JitStackAlignment.
masm.alignJitStackBasedOnNArgs(1);
// Setter is called with the new value as the only argument, and |obj| as thisv.
// Note that we use Push, not push, so that callJit will align the stack
// properly on ARM.
// To Push R1, read it off of the stowed values on stack.
// Stack: [ ..., R0, R1, ..STUBFRAME-HEADER.. ]
masm.movePtr(BaselineStackReg, scratch);
masm.PushValue(Address(scratch, STUB_FRAME_SIZE));
// Stack: [ ..., R0, R1, ..STUBFRAME-HEADER.., padding? ]
masm.PushValue(Address(BaselineFrameReg, STUB_FRAME_SIZE));
masm.Push(R0);
EmitCreateStubFrameDescriptor(masm, scratch);
masm.Push(Imm32(1)); // ActualArgc is 1
@ -10835,25 +10846,34 @@ ICCall_ScriptedFunCall::Compiler::generateStubCode(MacroAssembler &masm)
if (canUseTailCallReg)
regs.add(BaselineTailCallReg);
// Decrement argc if argc > 0. If argc == 0, push |undefined| as |this|.
Label zeroArgs, done;
masm.branchTest32(Assembler::Zero, argcReg, argcReg, &zeroArgs);
// Avoid the copy of the callee (function.call).
masm.sub32(Imm32(1), argcReg);
// Values are on the stack left-to-right. Calling convention wants them
// right-to-left so duplicate them on the stack in reverse order.
pushCallArguments(masm, regs, argcReg, /* isJitCall = */ true);
// Discard callee (function.call).
masm.addPtr(Imm32(sizeof(Value)), StackPointer);
// Pop scripted callee (the original |this|).
ValueOperand val = regs.takeAnyValue();
masm.popValue(val);
// Decrement argc if argc > 0. If argc == 0, push |undefined| as |this|.
Label zeroArgs, done;
masm.branchTest32(Assembler::Zero, argcReg, argcReg, &zeroArgs);
masm.sub32(Imm32(1), argcReg);
masm.jump(&done);
masm.bind(&zeroArgs);
// Copy scripted callee (the original |this|).
Address thisSlotFromStubFrame(BaselineFrameReg, STUB_FRAME_SIZE);
masm.loadValue(thisSlotFromStubFrame, val);
// Align the stack.
masm.alignJitStackBasedOnNArgs(0);
// Store the new |this|.
masm.pushValue(UndefinedValue());
masm.bind(&done);
// Unbox scripted callee.

View File

@ -2332,6 +2332,7 @@ MacroAssembler::alignJitStackBasedOnNArgs(Register nargs)
Label assert;
maybeAssert = &assert;
#endif
assertStackAlignment(sizeof(Value), 0);
branchTestPtr(Assembler::NonZero, nargs, Imm32(1), &odd);
branchTestPtr(Assembler::NonZero, StackPointer, Imm32(JitStackAlignment - 1), maybeAssert);
subPtr(Imm32(sizeof(Value)), StackPointer);
@ -2344,3 +2345,37 @@ MacroAssembler::alignJitStackBasedOnNArgs(Register nargs)
andPtr(Imm32(~(JitStackAlignment - 1)), StackPointer);
bind(&end);
}
void
MacroAssembler::alignJitStackBasedOnNArgs(uint32_t nargs)
{
const uint32_t alignment = JitStackAlignment / sizeof(Value);
if (alignment == 1)
return;
// A JitFrameLayout is composed of the following:
// [padding?] [argN] .. [arg1] [this] [[argc] [callee] [descr] [raddr]]
//
// We want to ensure that the |raddr| address is aligned.
// Which implies that we want to ensure that |this| is aligned.
static_assert(sizeof(JitFrameLayout) % JitStackAlignment == 0,
"No need to consider the JitFrameLayout for aligning the stack");
// Which implies that |argN| is aligned if |nargs| is even, and offset by
// |sizeof(Value)| if |nargs| is odd.
MOZ_ASSERT(alignment == 2);
// Thus the |padding| is offset by |sizeof(Value)| if |nargs| is even, and
// aligned if |nargs| is odd.
assertStackAlignment(sizeof(Value), 0);
if (nargs % 2 == 0) {
Label end;
branchTestPtr(Assembler::NonZero, StackPointer, Imm32(JitStackAlignment - 1), &end);
subPtr(Imm32(sizeof(Value)), StackPointer);
bind(&end);
assertStackAlignment(JitStackAlignment, sizeof(Value));
} else {
andPtr(Imm32(~(JitStackAlignment - 1)), StackPointer);
}
}

View File

@ -1256,6 +1256,7 @@ class MacroAssembler : public MacroAssemblerSpecific
// on the stack, such that the JitFrameLayout would be correctly aligned on
// the JitStackAlignment.
void alignJitStackBasedOnNArgs(Register nargs);
void alignJitStackBasedOnNArgs(uint32_t nargs);
void assertStackAlignment(uint32_t alignment, int32_t offset = 0) {
#ifdef DEBUG