| 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 {
|
|
|