| Index: src/ia32/deoptimizer-ia32.cc
|
| diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
|
| index 8cdcf9965f0e399e6124b019def79fca269cfb01..1c1b3a0ba30f6273d64dae70973eb045f418a9cb 100644
|
| --- a/src/ia32/deoptimizer-ia32.cc
|
| +++ b/src/ia32/deoptimizer-ia32.cc
|
| @@ -211,41 +211,39 @@ void Deoptimizer::DeoptimizeFunctionWithPreparedFunctionList(
|
|
|
|
|
| static const byte kJnsInstruction = 0x79;
|
| -static const byte kJnsOffset = 0x13;
|
| +static const byte kJnsOffset = 0x11;
|
| static const byte kCallInstruction = 0xe8;
|
| static const byte kNopByteOne = 0x66;
|
| static const byte kNopByteTwo = 0x90;
|
|
|
| -
|
| -void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
|
| - Address pc_after,
|
| - Code* check_code,
|
| - Code* replacement_code) {
|
| +// The back edge bookkeeping code matches the pattern:
|
| +//
|
| +// sub <profiling_counter>, <delta>
|
| +// jns ok
|
| +// call <interrupt stub>
|
| +// ok:
|
| +//
|
| +// The patched back edge looks like this:
|
| +//
|
| +// sub <profiling_counter>, <delta> ;; Not changed
|
| +// nop
|
| +// nop
|
| +// call <on-stack replacment>
|
| +// ok:
|
| +
|
| +void Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + ASSERT(!InterruptCodeIsPatched(unoptimized_code,
|
| + pc_after,
|
| + interrupt_code,
|
| + replacement_code));
|
| + // Turn the jump into nops.
|
| Address call_target_address = pc_after - kIntSize;
|
| - ASSERT_EQ(check_code->entry(),
|
| - Assembler::target_address_at(call_target_address));
|
| - // The back edge bookkeeping code matches the pattern:
|
| - //
|
| - // sub <profiling_counter>, <delta>
|
| - // jns ok
|
| - // call <stack guard>
|
| - // test eax, <loop nesting depth>
|
| - // ok: ...
|
| - //
|
| - // We will patch away the branch so the code is:
|
| - //
|
| - // sub <profiling_counter>, <delta> ;; Not changed
|
| - // nop
|
| - // nop
|
| - // call <on-stack replacment>
|
| - // test eax, <loop nesting depth>
|
| - // ok:
|
| -
|
| - ASSERT_EQ(kJnsInstruction, *(call_target_address - 3));
|
| - ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
|
| - ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
|
| *(call_target_address - 3) = kNopByteOne;
|
| *(call_target_address - 2) = kNopByteTwo;
|
| + // Replace the call address.
|
| Assembler::set_target_address_at(call_target_address,
|
| replacement_code->entry());
|
|
|
| @@ -254,27 +252,48 @@ void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
|
| }
|
|
|
|
|
| -void Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code,
|
| - Address pc_after,
|
| - Code* check_code,
|
| - Code* replacement_code) {
|
| +void Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + ASSERT(InterruptCodeIsPatched(unoptimized_code,
|
| + pc_after,
|
| + interrupt_code,
|
| + replacement_code));
|
| + // Restore the original jump.
|
| Address call_target_address = pc_after - kIntSize;
|
| - ASSERT_EQ(replacement_code->entry(),
|
| - Assembler::target_address_at(call_target_address));
|
| -
|
| - // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
|
| - // restore the conditional branch.
|
| - ASSERT_EQ(kNopByteOne, *(call_target_address - 3));
|
| - ASSERT_EQ(kNopByteTwo, *(call_target_address - 2));
|
| - ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
|
| *(call_target_address - 3) = kJnsInstruction;
|
| *(call_target_address - 2) = kJnsOffset;
|
| + // Restore the original call address.
|
| Assembler::set_target_address_at(call_target_address,
|
| - check_code->entry());
|
| + interrupt_code->entry());
|
|
|
| - check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| - unoptimized_code, call_target_address, check_code);
|
| + interrupt_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
|
| + unoptimized_code, call_target_address, interrupt_code);
|
| +}
|
| +
|
| +
|
| +#ifdef DEBUG
|
| +bool Deoptimizer::InterruptCodeIsPatched(Code* unoptimized_code,
|
| + Address pc_after,
|
| + Code* interrupt_code,
|
| + Code* replacement_code) {
|
| + Address call_target_address = pc_after - kIntSize;
|
| + ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
|
| + if (*(call_target_address - 3) == kNopByteOne) {
|
| + ASSERT_EQ(replacement_code->entry(),
|
| + Assembler::target_address_at(call_target_address));
|
| + ASSERT_EQ(kNopByteTwo, *(call_target_address - 2));
|
| + return true;
|
| + } else {
|
| + ASSERT_EQ(interrupt_code->entry(),
|
| + Assembler::target_address_at(call_target_address));
|
| + ASSERT_EQ(kJnsInstruction, *(call_target_address - 3));
|
| + ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
|
| + return false;
|
| + }
|
| }
|
| +#endif // DEBUG
|
|
|
|
|
| static int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) {
|
|
|