| Index: src/ia32/deoptimizer-ia32.cc
|
| ===================================================================
|
| --- src/ia32/deoptimizer-ia32.cc (revision 6955)
|
| +++ src/ia32/deoptimizer-ia32.cc (working copy)
|
| @@ -107,44 +107,71 @@
|
| }
|
|
|
|
|
| -void Deoptimizer::PatchStackCheckCode(RelocInfo* rinfo,
|
| +void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
|
| + Code* check_code,
|
| Code* replacement_code) {
|
| - // The stack check code matches the pattern:
|
| - //
|
| - // cmp esp, <limit>
|
| - // jae ok
|
| - // call <stack guard>
|
| - // test eax, <loop nesting depth>
|
| - // ok: ...
|
| - //
|
| - // We will patch away the branch so the code is:
|
| - //
|
| - // cmp esp, <limit> ;; Not changed
|
| - // nop
|
| - // nop
|
| - // call <on-stack replacment>
|
| - // test eax, <loop nesting depth>
|
| - // ok:
|
| - Address call_target_address = rinfo->pc();
|
| - ASSERT(*(call_target_address - 3) == 0x73 && // jae
|
| - *(call_target_address - 2) == 0x07 && // offset
|
| - *(call_target_address - 1) == 0xe8); // call
|
| - *(call_target_address - 3) = 0x90; // nop
|
| - *(call_target_address - 2) = 0x90; // nop
|
| - rinfo->set_target_address(replacement_code->entry());
|
| + // Iterate the unoptimized code and patch every stack check except at
|
| + // the function entry. This code assumes the function entry stack
|
| + // check appears first i.e., is not deferred or otherwise reordered.
|
| + ASSERT(unoptimized_code->kind() == Code::FUNCTION);
|
| + bool first = true;
|
| + for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
|
| + !it.done();
|
| + it.next()) {
|
| + RelocInfo* rinfo = it.rinfo();
|
| + if (rinfo->target_address() == Code::cast(check_code)->entry()) {
|
| + if (first) {
|
| + first = false;
|
| + } else {
|
| + // The stack check code matches the pattern:
|
| + //
|
| + // cmp esp, <limit>
|
| + // jae ok
|
| + // call <stack guard>
|
| + // test eax, <loop nesting depth>
|
| + // ok: ...
|
| + //
|
| + // We will patch away the branch so the code is:
|
| + //
|
| + // cmp esp, <limit> ;; Not changed
|
| + // nop
|
| + // nop
|
| + // call <on-stack replacment>
|
| + // test eax, <loop nesting depth>
|
| + // ok:
|
| + Address call_target_address = rinfo->pc();
|
| + ASSERT(*(call_target_address - 3) == 0x73 && // jae
|
| + *(call_target_address - 2) == 0x07 && // offset
|
| + *(call_target_address - 1) == 0xe8); // call
|
| + *(call_target_address - 3) = 0x90; // nop
|
| + *(call_target_address - 2) = 0x90; // nop
|
| + rinfo->set_target_address(replacement_code->entry());
|
| + }
|
| + }
|
| + }
|
| }
|
|
|
|
|
| -void Deoptimizer::RevertStackCheckCode(RelocInfo* rinfo, Code* check_code) {
|
| - // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
|
| - // restore the conditional branch.
|
| - Address call_target_address = rinfo->pc();
|
| - ASSERT(*(call_target_address - 3) == 0x90 && // nop
|
| - *(call_target_address - 2) == 0x90 && // nop
|
| - *(call_target_address - 1) == 0xe8); // call
|
| - *(call_target_address - 3) = 0x73; // jae
|
| - *(call_target_address - 2) = 0x07; // offset
|
| - rinfo->set_target_address(check_code->entry());
|
| +void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
|
| + Code* check_code,
|
| + Code* replacement_code) {
|
| + // Iterate the unoptimized code and revert all the patched stack checks.
|
| + for (RelocIterator it(unoptimized_code, RelocInfo::kCodeTargetMask);
|
| + !it.done();
|
| + it.next()) {
|
| + RelocInfo* rinfo = it.rinfo();
|
| + if (rinfo->target_address() == replacement_code->entry()) {
|
| + // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
|
| + // restore the conditional branch.
|
| + Address call_target_address = rinfo->pc();
|
| + ASSERT(*(call_target_address - 3) == 0x90 && // nop
|
| + *(call_target_address - 2) == 0x90 && // nop
|
| + *(call_target_address - 1) == 0xe8); // call
|
| + *(call_target_address - 3) = 0x73; // jae
|
| + *(call_target_address - 2) = 0x07; // offset
|
| + rinfo->set_target_address(check_code->entry());
|
| + }
|
| + }
|
| }
|
|
|
|
|
| @@ -510,26 +537,25 @@
|
| __ mov(ebx, Operand(eax, Deoptimizer::input_offset()));
|
|
|
| // Fill in the input registers.
|
| - for (int i = 0; i < kNumberOfRegisters; i++) {
|
| - int offset = (i * kIntSize) + FrameDescription::registers_offset();
|
| - __ mov(ecx, Operand(esp, (kNumberOfRegisters - 1 - i) * kPointerSize));
|
| - __ mov(Operand(ebx, offset), ecx);
|
| + for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
|
| + int offset = (i * kPointerSize) + FrameDescription::registers_offset();
|
| + __ pop(Operand(ebx, offset));
|
| }
|
|
|
| // Fill in the double input registers.
|
| int double_regs_offset = FrameDescription::double_registers_offset();
|
| for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
|
| int dst_offset = i * kDoubleSize + double_regs_offset;
|
| - int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
|
| + int src_offset = i * kDoubleSize;
|
| __ movdbl(xmm0, Operand(esp, src_offset));
|
| __ movdbl(Operand(ebx, dst_offset), xmm0);
|
| }
|
|
|
| - // Remove the bailout id and the general purpose registers from the stack.
|
| + // Remove the bailout id and the double registers from the stack.
|
| if (type() == EAGER) {
|
| - __ add(Operand(esp), Immediate(kSavedRegistersAreaSize + kPointerSize));
|
| + __ add(Operand(esp), Immediate(kDoubleRegsSize + kPointerSize));
|
| } else {
|
| - __ add(Operand(esp), Immediate(kSavedRegistersAreaSize + 2 * kPointerSize));
|
| + __ add(Operand(esp), Immediate(kDoubleRegsSize + 2 * kPointerSize));
|
| }
|
|
|
| // Compute a pointer to the unwinding limit in register ecx; that is
|
| @@ -594,7 +620,7 @@
|
|
|
| // Push the registers from the last output frame.
|
| for (int i = 0; i < kNumberOfRegisters; i++) {
|
| - int offset = (i * kIntSize) + FrameDescription::registers_offset();
|
| + int offset = (i * kPointerSize) + FrameDescription::registers_offset();
|
| __ push(Operand(ebx, offset));
|
| }
|
|
|
|
|