OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/ast/prettyprinter.h" | 8 #include "src/ast/prettyprinter.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 if (trace_scope_ != NULL) { | 834 if (trace_scope_ != NULL) { |
835 double ms = timer.Elapsed().InMillisecondsF(); | 835 double ms = timer.Elapsed().InMillisecondsF(); |
836 int index = output_count_ - 1; // Index of the topmost frame. | 836 int index = output_count_ - 1; // Index of the topmost frame. |
837 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", | 837 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", |
838 MessageFor(bailout_type_)); | 838 MessageFor(bailout_type_)); |
839 PrintFunctionName(); | 839 PrintFunctionName(); |
840 PrintF(trace_scope_->file(), | 840 PrintF(trace_scope_->file(), |
841 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR | 841 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR |
842 ", state=%s, took %0.3f ms]\n", | 842 ", state=%s, took %0.3f ms]\n", |
843 bailout_id_, node_id.ToInt(), output_[index]->GetPc(), | 843 bailout_id_, node_id.ToInt(), output_[index]->GetPc(), |
844 caller_frame_top_, FullCodeGenerator::State2String( | 844 caller_frame_top_, BailoutStateToString(static_cast<BailoutState>( |
845 static_cast<FullCodeGenerator::State>( | 845 output_[index]->GetState()->value())), |
846 output_[index]->GetState()->value())), | |
847 ms); | 846 ms); |
848 } | 847 } |
849 } | 848 } |
850 | 849 |
851 void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, | 850 void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, |
852 int frame_index, bool goto_catch_handler) { | 851 int frame_index, bool goto_catch_handler) { |
853 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); | 852 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); |
854 | 853 |
855 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 854 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
856 bool is_bottommost = (0 == frame_index); | 855 bool is_bottommost = (0 == frame_index); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 Address start = non_optimized_code->instruction_start(); | 1047 Address start = non_optimized_code->instruction_start(); |
1049 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 1048 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
1050 unsigned pc_offset = goto_catch_handler | 1049 unsigned pc_offset = goto_catch_handler |
1051 ? catch_handler_pc_offset_ | 1050 ? catch_handler_pc_offset_ |
1052 : FullCodeGenerator::PcField::decode(pc_and_state); | 1051 : FullCodeGenerator::PcField::decode(pc_and_state); |
1053 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 1052 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
1054 output_frame->SetPc(pc_value); | 1053 output_frame->SetPc(pc_value); |
1055 | 1054 |
1056 // If we are going to the catch handler, then the exception lives in | 1055 // If we are going to the catch handler, then the exception lives in |
1057 // the accumulator. | 1056 // the accumulator. |
1058 FullCodeGenerator::State state = | 1057 BailoutState state = |
1059 goto_catch_handler ? FullCodeGenerator::TOS_REG | 1058 goto_catch_handler |
1060 : FullCodeGenerator::StateField::decode(pc_and_state); | 1059 ? BailoutState::TOS_REGISTER |
1061 output_frame->SetState(Smi::FromInt(state)); | 1060 : FullCodeGenerator::BailoutStateField::decode(pc_and_state); |
| 1061 output_frame->SetState(Smi::FromInt(static_cast<int>(state))); |
1062 | 1062 |
1063 // Set the continuation for the topmost frame. | 1063 // Set the continuation for the topmost frame. |
1064 if (is_topmost) { | 1064 if (is_topmost) { |
1065 Builtins* builtins = isolate_->builtins(); | 1065 Builtins* builtins = isolate_->builtins(); |
1066 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1066 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
1067 if (bailout_type_ == LAZY) { | 1067 if (bailout_type_ == LAZY) { |
1068 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1068 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
1069 } else if (bailout_type_ == SOFT) { | 1069 } else if (bailout_type_ == SOFT) { |
1070 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1070 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
1071 } else { | 1071 } else { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1267 } else { | 1267 } else { |
1268 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1268 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
1269 output_offset); | 1269 output_offset); |
1270 } | 1270 } |
1271 CHECK_EQ(0u, output_offset); | 1271 CHECK_EQ(0u, output_offset); |
1272 | 1272 |
1273 Builtins* builtins = isolate_->builtins(); | 1273 Builtins* builtins = isolate_->builtins(); |
1274 Code* dispatch_builtin = | 1274 Code* dispatch_builtin = |
1275 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch); | 1275 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch); |
1276 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry())); | 1276 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry())); |
1277 output_frame->SetState(0); | 1277 // Restore accumulator (TOS) register. |
| 1278 output_frame->SetState( |
| 1279 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER))); |
1278 | 1280 |
1279 // Update constant pool. | 1281 // Update constant pool. |
1280 if (FLAG_enable_embedded_constant_pool) { | 1282 if (FLAG_enable_embedded_constant_pool) { |
1281 intptr_t constant_pool_value = | 1283 intptr_t constant_pool_value = |
1282 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); | 1284 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); |
1283 output_frame->SetConstantPool(constant_pool_value); | 1285 output_frame->SetConstantPool(constant_pool_value); |
1284 if (is_topmost) { | 1286 if (is_topmost) { |
1285 Register constant_pool_reg = | 1287 Register constant_pool_reg = |
1286 InterpretedFrame::constant_pool_pointer_register(); | 1288 InterpretedFrame::constant_pool_pointer_register(); |
1287 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 1289 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
1288 } | 1290 } |
1289 } | 1291 } |
1290 | 1292 |
1291 // Set the continuation for the topmost frame. | 1293 // Set the continuation for the topmost frame. |
1292 if (is_topmost) { | 1294 if (is_topmost) { |
1293 Code* continuation = | 1295 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
1294 builtins->builtin(Builtins::kInterpreterNotifyDeoptimized); | |
1295 if (bailout_type_ == LAZY) { | 1296 if (bailout_type_ == LAZY) { |
1296 continuation = | 1297 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
1297 builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized); | |
1298 } else if (bailout_type_ == SOFT) { | 1298 } else if (bailout_type_ == SOFT) { |
1299 continuation = | 1299 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
1300 builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized); | |
1301 } else { | 1300 } else { |
1302 CHECK_EQ(bailout_type_, EAGER); | 1301 CHECK_EQ(bailout_type_, EAGER); |
1303 } | 1302 } |
1304 output_frame->SetContinuation( | 1303 output_frame->SetContinuation( |
1305 reinterpret_cast<intptr_t>(continuation->entry())); | 1304 reinterpret_cast<intptr_t>(continuation->entry())); |
1306 } | 1305 } |
1307 } | 1306 } |
1308 | 1307 |
1309 void Deoptimizer::DoComputeArgumentsAdaptorFrame( | 1308 void Deoptimizer::DoComputeArgumentsAdaptorFrame( |
1310 TranslatedFrame* translated_frame, int frame_index) { | 1309 TranslatedFrame* translated_frame, int frame_index) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 | 1503 |
1505 Builtins* builtins = isolate_->builtins(); | 1504 Builtins* builtins = isolate_->builtins(); |
1506 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 1505 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
1507 unsigned height = translated_frame->height(); | 1506 unsigned height = translated_frame->height(); |
1508 unsigned height_in_bytes = height * kPointerSize; | 1507 unsigned height_in_bytes = height * kPointerSize; |
1509 | 1508 |
1510 // If the construct frame appears to be topmost we should ensure that the | 1509 // If the construct frame appears to be topmost we should ensure that the |
1511 // value of result register is preserved during continuation execution. | 1510 // value of result register is preserved during continuation execution. |
1512 // We do this here by "pushing" the result of the constructor function to the | 1511 // We do this here by "pushing" the result of the constructor function to the |
1513 // top of the reconstructed stack and then using the | 1512 // top of the reconstructed stack and then using the |
1514 // FullCodeGenerator::TOS_REG machinery. | 1513 // BailoutState::TOS_REGISTER machinery. |
1515 if (is_topmost) { | 1514 if (is_topmost) { |
1516 height_in_bytes += kPointerSize; | 1515 height_in_bytes += kPointerSize; |
1517 } | 1516 } |
1518 | 1517 |
1519 // Skip function. | 1518 // Skip function. |
1520 value_iterator++; | 1519 value_iterator++; |
1521 input_index++; | 1520 input_index++; |
1522 if (trace_scope_ != NULL) { | 1521 if (trace_scope_ != NULL) { |
1523 PrintF(trace_scope_->file(), | 1522 PrintF(trace_scope_->file(), |
1524 " translating construct stub => height=%d\n", height_in_bytes); | 1523 " translating construct stub => height=%d\n", height_in_bytes); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1625 | 1624 |
1626 if (is_topmost) { | 1625 if (is_topmost) { |
1627 // Ensure the result is restored back when we return to the stub. | 1626 // Ensure the result is restored back when we return to the stub. |
1628 output_offset -= kPointerSize; | 1627 output_offset -= kPointerSize; |
1629 Register result_reg = FullCodeGenerator::result_register(); | 1628 Register result_reg = FullCodeGenerator::result_register(); |
1630 value = input_->GetRegister(result_reg.code()); | 1629 value = input_->GetRegister(result_reg.code()); |
1631 output_frame->SetFrameSlot(output_offset, value); | 1630 output_frame->SetFrameSlot(output_offset, value); |
1632 DebugPrintOutputSlot(value, frame_index, output_offset, | 1631 DebugPrintOutputSlot(value, frame_index, output_offset, |
1633 "constructor result\n"); | 1632 "constructor result\n"); |
1634 | 1633 |
1635 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); | 1634 output_frame->SetState( |
| 1635 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER))); |
1636 } | 1636 } |
1637 | 1637 |
1638 CHECK_EQ(0u, output_offset); | 1638 CHECK_EQ(0u, output_offset); |
1639 | 1639 |
1640 intptr_t pc = reinterpret_cast<intptr_t>( | 1640 intptr_t pc = reinterpret_cast<intptr_t>( |
1641 construct_stub->instruction_start() + | 1641 construct_stub->instruction_start() + |
1642 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1642 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
1643 output_frame->SetPc(pc); | 1643 output_frame->SetPc(pc); |
1644 if (FLAG_enable_embedded_constant_pool) { | 1644 if (FLAG_enable_embedded_constant_pool) { |
1645 intptr_t constant_pool_value = | 1645 intptr_t constant_pool_value = |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1679 // The receiver (and the implicit return value, if any) are expected in | 1679 // The receiver (and the implicit return value, if any) are expected in |
1680 // registers by the LoadIC/StoreIC, so they don't belong to the output stack | 1680 // registers by the LoadIC/StoreIC, so they don't belong to the output stack |
1681 // frame. This means that we have to use a height of 0. | 1681 // frame. This means that we have to use a height of 0. |
1682 unsigned height = 0; | 1682 unsigned height = 0; |
1683 unsigned height_in_bytes = height * kPointerSize; | 1683 unsigned height_in_bytes = height * kPointerSize; |
1684 | 1684 |
1685 // If the accessor frame appears to be topmost we should ensure that the | 1685 // If the accessor frame appears to be topmost we should ensure that the |
1686 // value of result register is preserved during continuation execution. | 1686 // value of result register is preserved during continuation execution. |
1687 // We do this here by "pushing" the result of the accessor function to the | 1687 // We do this here by "pushing" the result of the accessor function to the |
1688 // top of the reconstructed stack and then using the | 1688 // top of the reconstructed stack and then using the |
1689 // FullCodeGenerator::TOS_REG machinery. | 1689 // BailoutState::TOS_REGISTER machinery. |
1690 // We don't need to restore the result in case of a setter call because we | 1690 // We don't need to restore the result in case of a setter call because we |
1691 // have to return the stored value but not the result of the setter function. | 1691 // have to return the stored value but not the result of the setter function. |
1692 bool should_preserve_result = is_topmost && !is_setter_stub_frame; | 1692 bool should_preserve_result = is_topmost && !is_setter_stub_frame; |
1693 if (should_preserve_result) { | 1693 if (should_preserve_result) { |
1694 height_in_bytes += kPointerSize; | 1694 height_in_bytes += kPointerSize; |
1695 } | 1695 } |
1696 | 1696 |
1697 const char* kind = is_setter_stub_frame ? "setter" : "getter"; | 1697 const char* kind = is_setter_stub_frame ? "setter" : "getter"; |
1698 if (trace_scope_ != NULL) { | 1698 if (trace_scope_ != NULL) { |
1699 PrintF(trace_scope_->file(), | 1699 PrintF(trace_scope_->file(), |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1798 | 1798 |
1799 if (should_preserve_result) { | 1799 if (should_preserve_result) { |
1800 // Ensure the result is restored back when we return to the stub. | 1800 // Ensure the result is restored back when we return to the stub. |
1801 output_offset -= kPointerSize; | 1801 output_offset -= kPointerSize; |
1802 Register result_reg = FullCodeGenerator::result_register(); | 1802 Register result_reg = FullCodeGenerator::result_register(); |
1803 value = input_->GetRegister(result_reg.code()); | 1803 value = input_->GetRegister(result_reg.code()); |
1804 output_frame->SetFrameSlot(output_offset, value); | 1804 output_frame->SetFrameSlot(output_offset, value); |
1805 DebugPrintOutputSlot(value, frame_index, output_offset, | 1805 DebugPrintOutputSlot(value, frame_index, output_offset, |
1806 "accessor result\n"); | 1806 "accessor result\n"); |
1807 | 1807 |
1808 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); | 1808 output_frame->SetState( |
| 1809 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER))); |
1809 } else { | 1810 } else { |
1810 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | 1811 output_frame->SetState( |
| 1812 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS))); |
1811 } | 1813 } |
1812 | 1814 |
1813 CHECK_EQ(0u, output_offset); | 1815 CHECK_EQ(0u, output_offset); |
1814 | 1816 |
1815 Smi* offset = is_setter_stub_frame ? | 1817 Smi* offset = is_setter_stub_frame ? |
1816 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1818 isolate_->heap()->setter_stub_deopt_pc_offset() : |
1817 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1819 isolate_->heap()->getter_stub_deopt_pc_offset(); |
1818 intptr_t pc = reinterpret_cast<intptr_t>( | 1820 intptr_t pc = reinterpret_cast<intptr_t>( |
1819 accessor_stub->instruction_start() + offset->value()); | 1821 accessor_stub->instruction_start() + offset->value()); |
1820 output_frame->SetPc(pc); | 1822 output_frame->SetPc(pc); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2055 output_frame->SetPc(reinterpret_cast<intptr_t>( | 2057 output_frame->SetPc(reinterpret_cast<intptr_t>( |
2056 trampoline->instruction_start())); | 2058 trampoline->instruction_start())); |
2057 if (FLAG_enable_embedded_constant_pool) { | 2059 if (FLAG_enable_embedded_constant_pool) { |
2058 Register constant_pool_reg = | 2060 Register constant_pool_reg = |
2059 StubFailureTrampolineFrame::constant_pool_pointer_register(); | 2061 StubFailureTrampolineFrame::constant_pool_pointer_register(); |
2060 intptr_t constant_pool_value = | 2062 intptr_t constant_pool_value = |
2061 reinterpret_cast<intptr_t>(trampoline->constant_pool()); | 2063 reinterpret_cast<intptr_t>(trampoline->constant_pool()); |
2062 output_frame->SetConstantPool(constant_pool_value); | 2064 output_frame->SetConstantPool(constant_pool_value); |
2063 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 2065 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
2064 } | 2066 } |
2065 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | 2067 output_frame->SetState( |
| 2068 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS))); |
2066 Code* notify_failure = | 2069 Code* notify_failure = |
2067 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); | 2070 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); |
2068 output_frame->SetContinuation( | 2071 output_frame->SetContinuation( |
2069 reinterpret_cast<intptr_t>(notify_failure->entry())); | 2072 reinterpret_cast<intptr_t>(notify_failure->entry())); |
2070 } | 2073 } |
2071 | 2074 |
2072 | 2075 |
2073 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | 2076 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { |
2074 // Walk to the last JavaScript output frame to find out if it has | 2077 // Walk to the last JavaScript output frame to find out if it has |
2075 // adapted arguments. | 2078 // adapted arguments. |
(...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3923 CHECK(value_info->IsMaterializedObject()); | 3926 CHECK(value_info->IsMaterializedObject()); |
3924 | 3927 |
3925 value_info->value_ = | 3928 value_info->value_ = |
3926 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3929 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3927 } | 3930 } |
3928 } | 3931 } |
3929 } | 3932 } |
3930 | 3933 |
3931 } // namespace internal | 3934 } // namespace internal |
3932 } // namespace v8 | 3935 } // namespace v8 |
OLD | NEW |