Index: src/deoptimizer.cc |
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
index c13713d088bf836c30823cec6e41db40515edc9b..49c8641dbd4e2d720d8e6fc18454a6a191472e31 100644 |
--- a/src/deoptimizer.cc |
+++ b/src/deoptimizer.cc |
@@ -2030,52 +2030,96 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
} |
-void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code, |
- Code* check_code, |
- Code* replacement_code) { |
- // Iterate over the stack check table and patch every stack check |
+void Deoptimizer::PatchInterruptCode(Code* unoptimized_code, |
+ Code* interrupt_code, |
+ Code* replacement_code) { |
+ // Iterate over the back edge table and patch every interrupt |
// call to an unconditional call to the replacement code. |
ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
- ASSERT(!unoptimized_code->stack_check_patched_for_osr()); |
- Address stack_check_cursor = unoptimized_code->instruction_start() + |
- unoptimized_code->stack_check_table_offset(); |
- uint32_t table_length = Memory::uint32_at(stack_check_cursor); |
- stack_check_cursor += kIntSize; |
+ int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level(); |
+ Address back_edge_cursor = unoptimized_code->instruction_start() + |
+ unoptimized_code->back_edge_table_offset(); |
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor); |
+ back_edge_cursor += kIntSize; |
for (uint32_t i = 0; i < table_length; ++i) { |
- uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); |
- Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
- PatchStackCheckCodeAt(unoptimized_code, |
- pc_after, |
- check_code, |
- replacement_code); |
- stack_check_cursor += 2 * kIntSize; |
+ uint8_t loop_depth = Memory::uint8_at(back_edge_cursor + 2 * kIntSize); |
+ if (loop_depth == loop_nesting_level) { |
+ // Loop back edge has the loop depth that we want to patch. |
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); |
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
+ PatchInterruptCodeAt(unoptimized_code, |
+ pc_after, |
+ interrupt_code, |
+ replacement_code); |
+ } |
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; |
} |
- unoptimized_code->set_stack_check_patched_for_osr(true); |
+ unoptimized_code->set_back_edges_patched_for_osr(true); |
+#ifdef DEBUG |
+ Deoptimizer::VerifyInterruptCode( |
+ unoptimized_code, interrupt_code, replacement_code, loop_nesting_level); |
+#endif // DEBUG |
} |
-void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code, |
- Code* check_code, |
- Code* replacement_code) { |
- // Iterate over the stack check table and revert the patched |
- // stack check calls. |
+void Deoptimizer::RevertInterruptCode(Code* unoptimized_code, |
+ Code* interrupt_code, |
+ Code* replacement_code) { |
+ // Iterate over the back edge table and revert the patched interrupt calls. |
ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
- ASSERT(unoptimized_code->stack_check_patched_for_osr()); |
- Address stack_check_cursor = unoptimized_code->instruction_start() + |
- unoptimized_code->stack_check_table_offset(); |
- uint32_t table_length = Memory::uint32_at(stack_check_cursor); |
- stack_check_cursor += kIntSize; |
+ ASSERT(unoptimized_code->back_edges_patched_for_osr()); |
+ int loop_nesting_level = unoptimized_code->allow_osr_at_loop_nesting_level(); |
+ Address back_edge_cursor = unoptimized_code->instruction_start() + |
+ unoptimized_code->back_edge_table_offset(); |
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor); |
+ back_edge_cursor += kIntSize; |
for (uint32_t i = 0; i < table_length; ++i) { |
- uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); |
+ uint8_t loop_depth = Memory::uint8_at(back_edge_cursor + 2 * kIntSize); |
+ if (loop_depth <= loop_nesting_level) { |
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); |
+ Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
+ RevertInterruptCodeAt(unoptimized_code, |
+ pc_after, |
+ interrupt_code, |
+ replacement_code); |
+ } |
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; |
+ } |
+ unoptimized_code->set_back_edges_patched_for_osr(false); |
+#ifdef DEBUG |
+ // Assert that none of the back edges are patched anymore. |
+ Deoptimizer::VerifyInterruptCode( |
+ unoptimized_code, interrupt_code, replacement_code, -1); |
+#endif // DEBUG |
+} |
+ |
+ |
+#ifdef DEBUG |
+void Deoptimizer::VerifyInterruptCode(Code* unoptimized_code, |
+ Code* interrupt_code, |
+ Code* replacement_code, |
+ int loop_nesting_level) { |
+ CHECK(unoptimized_code->kind() == Code::FUNCTION); |
+ Address back_edge_cursor = unoptimized_code->instruction_start() + |
+ unoptimized_code->back_edge_table_offset(); |
+ uint32_t table_length = Memory::uint32_at(back_edge_cursor); |
+ back_edge_cursor += kIntSize; |
+ for (uint32_t i = 0; i < table_length; ++i) { |
+ uint8_t loop_depth = Memory::uint8_at(back_edge_cursor + 2 * kIntSize); |
+ CHECK_LE(loop_depth, Code::kMaxLoopNestingMarker); |
+ // Assert that all back edges for shallower loops (and only those) |
+ // have already been patched. |
+ uint32_t pc_offset = Memory::uint32_at(back_edge_cursor + kIntSize); |
Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
- RevertStackCheckCodeAt(unoptimized_code, |
- pc_after, |
- check_code, |
- replacement_code); |
- stack_check_cursor += 2 * kIntSize; |
+ CHECK_EQ((loop_depth <= loop_nesting_level), |
+ InterruptCodeIsPatched(unoptimized_code, |
+ pc_after, |
+ interrupt_code, |
+ replacement_code)); |
+ back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; |
} |
- unoptimized_code->set_stack_check_patched_for_osr(false); |
} |
+#endif // DEBUG |
unsigned Deoptimizer::ComputeInputFrameSize() const { |