Bug 736299: Prevent the frame pointer from being allocated when profiling is enabled. r=nbp

This commit is contained in:
Alex Crichton 2012-08-15 16:30:23 -07:00
parent c74e64e4b2
commit 7e5f28dc59
8 changed files with 45 additions and 23 deletions

View File

@ -435,6 +435,8 @@ void
MacroAssembler::performOsr()
{
GeneralRegisterSet regs = GeneralRegisterSet::All();
if (FramePointer != InvalidReg && sps && sps->enabled())
regs.take(FramePointer);
// This register must be fixed as it's used in the Osr prologue.
regs.take(OsrFrameReg);

View File

@ -523,7 +523,7 @@ LinearScanAllocator::buildLivenessInfo()
for (LInstructionReverseIterator ins = block->rbegin(); ins != block->rend(); ins++) {
// Calls may clobber registers, so force a spill and reload around the callsite.
if (ins->isCall()) {
for (AnyRegisterIterator iter(RegisterSet::All()); iter.more(); iter++) {
for (AnyRegisterIterator iter(allRegisters); iter.more(); iter++) {
if (!addFixedRangeAtHead(*iter, inputOf(*ins), outputOf(*ins)))
return false;
}
@ -1611,7 +1611,7 @@ LinearScanAllocator::findBestFreeRegister(CodePosition *freeUntil)
// Compute free-until positions for all registers
CodePosition freeUntilPos[AnyRegister::Total];
bool needFloat = current->reg()->isDouble();
for (AnyRegisterIterator regs(RegisterSet::All()); regs.more(); regs++) {
for (AnyRegisterIterator regs(allRegisters); regs.more(); regs++) {
AnyRegister reg = *regs;
if (reg.isFloat() == needFloat)
freeUntilPos[reg.code()] = CodePosition::MAX;
@ -1704,7 +1704,7 @@ LinearScanAllocator::findBestBlockedRegister(CodePosition *nextUsed)
// Compute next-used positions for all registers
CodePosition nextUsePos[AnyRegister::Total];
bool needFloat = current->reg()->isDouble();
for (AnyRegisterIterator regs(RegisterSet::All()); regs.more(); regs++) {
for (AnyRegisterIterator regs(allRegisters); regs.more(); regs++) {
AnyRegister reg = *regs;
if (reg.isFloat() == needFloat)
nextUsePos[reg.code()] = CodePosition::MAX;

View File

@ -611,6 +611,9 @@ class LinearScanAllocator
SlotList finishedSlots_;
SlotList finishedDoubleSlots_;
// Pool of all registers that should be considered allocateable
RegisterSet allRegisters;
// Run-time state
UnhandledQueue unhandled;
InlineList<LiveInterval> active;
@ -684,8 +687,12 @@ class LinearScanAllocator
public:
LinearScanAllocator(LIRGenerator *lir, LIRGraph &graph)
: lir(lir),
graph(graph)
{ }
graph(graph),
allRegisters(RegisterSet::All())
{
if (FramePointer != InvalidReg && lir->mir()->instrumentedProfiling())
allRegisters.take(AnyRegister(FramePointer));
}
bool go();
};

View File

@ -62,6 +62,7 @@ static const FloatRegister InvalidFloatReg = { FloatRegisters::invalid_freg };
static const Register JSReturnReg_Type = r3;
static const Register JSReturnReg_Data = r2;
static const Register StackPointer = sp;
static const Register FramePointer = InvalidReg;
static const Register ReturnReg = r0;
static const FloatRegister ReturnFloatReg = { FloatRegisters::d1 };
static const FloatRegister ScratchFloatReg = { FloatRegisters::d0 };

View File

@ -63,6 +63,7 @@ static const Register InvalidReg = { JSC::X86Registers::invalid_reg };
static const FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
static const Register StackPointer = rsp;
static const Register FramePointer = rbp;
static const Register JSReturnReg = rcx;
// Avoid, except for assertions.
static const Register JSReturnReg_Type = JSReturnReg;

View File

@ -209,6 +209,8 @@ IonCompartment::generateInvalidator(JSContext *cx)
IonCode *
IonCompartment::generateArgumentsRectifier(JSContext *cx)
{
// Do not erase the frame pointer in this function.
MacroAssembler masm(cx);
// ArgumentsRectifierReg contains the |nargs| pushed onto the current frame.
@ -225,7 +227,7 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.moveValue(UndefinedValue(), r10);
masm.movq(rsp, rbp); // Save %rsp.
masm.movq(rsp, r9); // Save %rsp.
// Push undefined.
{
@ -240,7 +242,7 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
}
// Get the topmost argument.
BaseIndex b = BaseIndex(rbp, r8, TimesEight, sizeof(IonRectifierFrameLayout));
BaseIndex b = BaseIndex(r9, r8, TimesEight, sizeof(IonRectifierFrameLayout));
masm.lea(Operand(b), rcx);
// Push arguments, |nargs| + 1 times (to include |this|).
@ -261,13 +263,13 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
}
// Construct descriptor.
masm.subq(rsp, rbp);
masm.makeFrameDescriptor(rbp, IonFrame_Rectifier);
masm.subq(rsp, r9);
masm.makeFrameDescriptor(r9, IonFrame_Rectifier);
// Construct IonJSFrameLayout.
masm.push(rdx); // numActualArgs
masm.push(rax); // calleeToken
masm.push(rbp); // descriptor
masm.push(r9); // descriptor
// Call the target function.
// Note that this code assumes the function is JITted.
@ -278,11 +280,11 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.call(rax);
// Remove the rectifier frame.
masm.pop(rbp); // rbp <- descriptor with FrameType.
masm.shrq(Imm32(FRAMESIZE_SHIFT), rbp);
masm.pop(r9); // r9 <- descriptor with FrameType.
masm.shrq(Imm32(FRAMESIZE_SHIFT), r9);
masm.pop(r11); // Discard calleeToken.
masm.pop(r11); // Discard numActualArgs.
masm.addq(rbp, rsp); // Discard pushed arguments.
masm.addq(r9, rsp); // Discard pushed arguments.
masm.ret();

View File

@ -40,6 +40,7 @@ static const FloatRegister InvalidFloatReg = { JSC::X86Registers::invalid_xmm };
static const Register JSReturnReg_Type = ecx;
static const Register JSReturnReg_Data = edx;
static const Register StackPointer = esp;
static const Register FramePointer = ebp;
static const Register ReturnReg = eax;
static const FloatRegister ReturnFloatReg = xmm0;
static const FloatRegister ScratchFloatReg = xmm7;

View File

@ -227,7 +227,8 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.moveValue(UndefinedValue(), ebx, edi);
masm.movl(esp, ebp); // Save %esp.
masm.push(FramePointer);
masm.movl(esp, FramePointer); // Save %esp.
// Push undefined.
{
@ -242,8 +243,10 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.j(Assembler::NonZero, &undefLoopTop);
}
// Get the topmost argument.
BaseIndex b = BaseIndex(ebp, esi, TimesEight, sizeof(IonRectifierFrameLayout));
// Get the topmost argument. We did a push of %ebp earlier, so be sure to
// account for this in the offset
BaseIndex b = BaseIndex(FramePointer, esi, TimesEight,
sizeof(IonRectifierFrameLayout) + sizeof(void*));
masm.lea(Operand(b), ecx);
// Push arguments, |nargs| + 1 times (to include |this|).
@ -264,14 +267,15 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.j(Assembler::NonZero, &copyLoopTop);
}
// Construct descriptor.
masm.subl(esp, ebp);
masm.makeFrameDescriptor(ebp, IonFrame_Rectifier);
// Construct descriptor, accounting for pushed frame pointer above
masm.lea(Operand(FramePointer, sizeof(void*)), ebx);
masm.subl(esp, ebx);
masm.makeFrameDescriptor(ebx, IonFrame_Rectifier);
// Construct IonJSFrameLayout.
masm.push(edx); // number of actual arguments
masm.push(eax); // calleeToken
masm.push(ebp); // descriptor
masm.push(ebx); // descriptor
// Call the target function.
// Note that this assumes the function is JITted.
@ -282,12 +286,16 @@ IonCompartment::generateArgumentsRectifier(JSContext *cx)
masm.call(eax);
// Remove the rectifier frame.
masm.pop(ebp); // ebp <- descriptor with FrameType.
masm.shrl(Imm32(FRAMESIZE_SHIFT), ebp); // ebp <- descriptor.
masm.pop(ebx); // ebx <- descriptor with FrameType.
masm.shrl(Imm32(FRAMESIZE_SHIFT), ebx); // ebx <- descriptor.
masm.pop(edi); // Discard calleeToken.
masm.pop(edi); // Discard number of actual arguments.
masm.addl(ebp, esp); // Discard pushed arguments.
// Discard pushed arguments, but not the pushed frame pointer.
BaseIndex unwind = BaseIndex(esp, ebx, TimesOne, -sizeof(void*));
masm.lea(Operand(unwind), esp);
masm.pop(FramePointer);
masm.ret();
Linker linker(masm);