Bug 1112161 - IonMonkey: Pad fun.apply(...) stack. r=bbouvier

This commit is contained in:
Nicolas B. Pierron 2015-02-12 14:53:05 +01:00
Родитель 494fc62ea5
Коммит 21ff146f90
1 изменённых файлов: 76 добавлений и 19 удалений

Просмотреть файл

@ -3075,43 +3075,100 @@ CodeGenerator::emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSp
{ {
// Holds the function nargs. Initially undefined. // Holds the function nargs. Initially undefined.
Register argcreg = ToRegister(apply->getArgc()); Register argcreg = ToRegister(apply->getArgc());
Register copyreg = ToRegister(apply->getTempObject()); Register copyreg = ToRegister(apply->getTempObject());
size_t argvOffset = frameSize() + JitFrameLayout::offsetOfActualArgs();
Label end;
// Initialize the loop counter AND Compute the stack usage (if == 0) // Initialize the loop counter AND Compute the stack usage (if == 0)
masm.movePtr(argcreg, extraStackSpace); masm.movePtr(argcreg, extraStackSpace);
// Align the JitFrameLayout on the JitStackAlignment.
const uint32_t alignment = JitStackAlignment / sizeof(Value);
if (alignment > 1) {
MOZ_ASSERT(frameSize() % JitStackAlignment == 0,
"Stack padding assumes that the frameSize is correct");
MOZ_ASSERT(alignment == 2);
Label noPaddingNeeded;
// if the number of arguments is odd, then we do not need any padding.
masm.branchTestPtr(Assembler::NonZero, argcreg, Imm32(1), &noPaddingNeeded);
masm.addPtr(Imm32(1), extraStackSpace);
masm.bind(&noPaddingNeeded);
}
// Reserve space for copying the arguments.
NativeObject::elementsSizeMustNotOverflow();
masm.lshiftPtr(Imm32(ValueShift), extraStackSpace);
masm.subPtr(extraStackSpace, StackPointer);
#ifdef DEBUG
// Put a magic value in the space reserved for padding. Note, this code
// cannot be merged with the previous test, as not all architectures can
// write below their stack pointers.
if (alignment > 1) {
MOZ_ASSERT(alignment == 2);
Label noPaddingNeeded;
// if the number of arguments is odd, then we do not need any padding.
masm.branchTestPtr(Assembler::NonZero, argcreg, Imm32(1), &noPaddingNeeded);
BaseValueIndex dstPtr(StackPointer, argcreg);
masm.storeValue(MagicValue(JS_ARG_POISON), dstPtr);
masm.bind(&noPaddingNeeded);
}
#endif
// Skip the copy of arguments.
Label end;
masm.branchTestPtr(Assembler::Zero, argcreg, argcreg, &end); masm.branchTestPtr(Assembler::Zero, argcreg, argcreg, &end);
// We are making a copy of the arguments which are above the JitFrameLayout
// of the current Ion frame.
//
// [arg1] [arg0] <- src [this] [JitFrameLayout] [.. frameSize ..] [pad] [arg1] [arg0] <- dst
// Compute the source and destination offsets into the stack.
size_t argvSrcOffset = frameSize() + JitFrameLayout::offsetOfActualArgs();
size_t argvDstOffset = 0;
// Save the extra stack space, and re-use the register as a base.
masm.push(extraStackSpace);
Register argvSrcBase = extraStackSpace;
argvSrcOffset += sizeof(void *);
argvDstOffset += sizeof(void *);
// Save the actual number of register, and re-use the register as an index register.
masm.push(argcreg);
Register argvIndex = argcreg;
argvSrcOffset += sizeof(void *);
argvDstOffset += sizeof(void *);
// srcPtr = (StackPointer + extraStackSpace) + argvSrcOffset
// dstPtr = (StackPointer ) + argvDstOffset
masm.addPtr(StackPointer, argvSrcBase);
// Copy arguments. // Copy arguments.
{ {
Register count = extraStackSpace; // <- argcreg
Label loop; Label loop;
masm.bind(&loop); masm.bind(&loop);
// We remove sizeof(void*) from argvOffset because without it we target // As argvIndex is off by 1, and we use the decBranchPtr instruction
// the address after the memory area that we want to copy. // to loop back, we have to substract the size of the word which are
BaseValueIndex disp(StackPointer, argcreg, argvOffset - sizeof(void*)); // copied.
BaseValueIndex srcPtr(argvSrcBase, argvIndex, argvSrcOffset - sizeof(void *));
// Do not use Push here because other this account to 1 in the framePushed BaseValueIndex dstPtr(StackPointer, argvIndex, argvDstOffset - sizeof(void *));
// instead of 0. These push are only counted by argcreg. masm.loadPtr(srcPtr, copyreg);
masm.loadPtr(disp, copyreg); masm.storePtr(copyreg, dstPtr);
masm.push(copyreg);
// Handle 32 bits architectures. // Handle 32 bits architectures.
if (sizeof(Value) == 2 * sizeof(void*)) { if (sizeof(Value) == 2 * sizeof(void*)) {
masm.loadPtr(disp, copyreg); BaseValueIndex srcPtrLow(argvSrcBase, argvIndex, argvSrcOffset - 2 * sizeof(void *));
masm.push(copyreg); BaseValueIndex dstPtrLow(StackPointer, argvIndex, argvDstOffset - 2 * sizeof(void *));
masm.loadPtr(srcPtrLow, copyreg);
masm.storePtr(copyreg, dstPtrLow);
} }
masm.decBranchPtr(Assembler::NonZero, count, Imm32(1), &loop); masm.decBranchPtr(Assembler::NonZero, argvIndex, Imm32(1), &loop);
} }
// Compute the stack usage. // Restore argcreg and the extra stack space counter.
masm.movePtr(argcreg, extraStackSpace); masm.pop(argcreg);
NativeObject::elementsSizeMustNotOverflow(); masm.pop(extraStackSpace);
masm.lshiftPtr(Imm32(ValueShift), extraStackSpace);
// Join with all arguments copied and the extra stack usage computed. // Join with all arguments copied and the extra stack usage computed.
masm.bind(&end); masm.bind(&end);