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_, BailoutStateToString(static_cast<BailoutState>( | 844 caller_frame_top_, FullCodeGenerator::State2String( |
845 output_[index]->GetState()->value())), | 845 static_cast<FullCodeGenerator::State>( |
| 846 output_[index]->GetState()->value())), |
846 ms); | 847 ms); |
847 } | 848 } |
848 } | 849 } |
849 | 850 |
850 void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, | 851 void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame, |
851 int frame_index, bool goto_catch_handler) { | 852 int frame_index, bool goto_catch_handler) { |
852 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); | 853 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); |
853 | 854 |
854 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 855 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
855 bool is_bottommost = (0 == frame_index); | 856 bool is_bottommost = (0 == frame_index); |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1047 Address start = non_optimized_code->instruction_start(); | 1048 Address start = non_optimized_code->instruction_start(); |
1048 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | 1049 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
1049 unsigned pc_offset = goto_catch_handler | 1050 unsigned pc_offset = goto_catch_handler |
1050 ? catch_handler_pc_offset_ | 1051 ? catch_handler_pc_offset_ |
1051 : FullCodeGenerator::PcField::decode(pc_and_state); | 1052 : FullCodeGenerator::PcField::decode(pc_and_state); |
1052 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | 1053 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
1053 output_frame->SetPc(pc_value); | 1054 output_frame->SetPc(pc_value); |
1054 | 1055 |
1055 // If we are going to the catch handler, then the exception lives in | 1056 // If we are going to the catch handler, then the exception lives in |
1056 // the accumulator. | 1057 // the accumulator. |
1057 BailoutState state = | 1058 FullCodeGenerator::State state = |
1058 goto_catch_handler | 1059 goto_catch_handler ? FullCodeGenerator::TOS_REG |
1059 ? BailoutState::TOS_REGISTER | 1060 : FullCodeGenerator::StateField::decode(pc_and_state); |
1060 : FullCodeGenerator::BailoutStateField::decode(pc_and_state); | 1061 output_frame->SetState(Smi::FromInt(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 // Restore accumulator (TOS) register. | 1277 output_frame->SetState(0); |
1278 output_frame->SetState( | |
1279 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER))); | |
1280 | 1278 |
1281 // Update constant pool. | 1279 // Update constant pool. |
1282 if (FLAG_enable_embedded_constant_pool) { | 1280 if (FLAG_enable_embedded_constant_pool) { |
1283 intptr_t constant_pool_value = | 1281 intptr_t constant_pool_value = |
1284 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); | 1282 reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool()); |
1285 output_frame->SetConstantPool(constant_pool_value); | 1283 output_frame->SetConstantPool(constant_pool_value); |
1286 if (is_topmost) { | 1284 if (is_topmost) { |
1287 Register constant_pool_reg = | 1285 Register constant_pool_reg = |
1288 InterpretedFrame::constant_pool_pointer_register(); | 1286 InterpretedFrame::constant_pool_pointer_register(); |
1289 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 1287 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
1290 } | 1288 } |
1291 } | 1289 } |
1292 | 1290 |
1293 // Set the continuation for the topmost frame. | 1291 // Set the continuation for the topmost frame. |
1294 if (is_topmost) { | 1292 if (is_topmost) { |
1295 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1293 Code* continuation = |
| 1294 builtins->builtin(Builtins::kInterpreterNotifyDeoptimized); |
1296 if (bailout_type_ == LAZY) { | 1295 if (bailout_type_ == LAZY) { |
1297 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1296 continuation = |
| 1297 builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized); |
1298 } else if (bailout_type_ == SOFT) { | 1298 } else if (bailout_type_ == SOFT) { |
1299 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1299 continuation = |
| 1300 builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized); |
1300 } else { | 1301 } else { |
1301 CHECK_EQ(bailout_type_, EAGER); | 1302 CHECK_EQ(bailout_type_, EAGER); |
1302 } | 1303 } |
1303 output_frame->SetContinuation( | 1304 output_frame->SetContinuation( |
1304 reinterpret_cast<intptr_t>(continuation->entry())); | 1305 reinterpret_cast<intptr_t>(continuation->entry())); |
1305 } | 1306 } |
1306 } | 1307 } |
1307 | 1308 |
1308 void Deoptimizer::DoComputeArgumentsAdaptorFrame( | 1309 void Deoptimizer::DoComputeArgumentsAdaptorFrame( |
1309 TranslatedFrame* translated_frame, int frame_index) { | 1310 TranslatedFrame* translated_frame, int frame_index) { |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 | 1504 |
1504 Builtins* builtins = isolate_->builtins(); | 1505 Builtins* builtins = isolate_->builtins(); |
1505 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 1506 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
1506 unsigned height = translated_frame->height(); | 1507 unsigned height = translated_frame->height(); |
1507 unsigned height_in_bytes = height * kPointerSize; | 1508 unsigned height_in_bytes = height * kPointerSize; |
1508 | 1509 |
1509 // If the construct frame appears to be topmost we should ensure that the | 1510 // If the construct frame appears to be topmost we should ensure that the |
1510 // value of result register is preserved during continuation execution. | 1511 // value of result register is preserved during continuation execution. |
1511 // We do this here by "pushing" the result of the constructor function to the | 1512 // We do this here by "pushing" the result of the constructor function to the |
1512 // top of the reconstructed stack and then using the | 1513 // top of the reconstructed stack and then using the |
1513 // BailoutState::TOS_REGISTER machinery. | 1514 // FullCodeGenerator::TOS_REG machinery. |
1514 if (is_topmost) { | 1515 if (is_topmost) { |
1515 height_in_bytes += kPointerSize; | 1516 height_in_bytes += kPointerSize; |
1516 } | 1517 } |
1517 | 1518 |
1518 // Skip function. | 1519 // Skip function. |
1519 value_iterator++; | 1520 value_iterator++; |
1520 input_index++; | 1521 input_index++; |
1521 if (trace_scope_ != NULL) { | 1522 if (trace_scope_ != NULL) { |
1522 PrintF(trace_scope_->file(), | 1523 PrintF(trace_scope_->file(), |
1523 " translating construct stub => height=%d\n", height_in_bytes); | 1524 " translating construct stub => height=%d\n", height_in_bytes); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1624 | 1625 |
1625 if (is_topmost) { | 1626 if (is_topmost) { |
1626 // Ensure the result is restored back when we return to the stub. | 1627 // Ensure the result is restored back when we return to the stub. |
1627 output_offset -= kPointerSize; | 1628 output_offset -= kPointerSize; |
1628 Register result_reg = FullCodeGenerator::result_register(); | 1629 Register result_reg = FullCodeGenerator::result_register(); |
1629 value = input_->GetRegister(result_reg.code()); | 1630 value = input_->GetRegister(result_reg.code()); |
1630 output_frame->SetFrameSlot(output_offset, value); | 1631 output_frame->SetFrameSlot(output_offset, value); |
1631 DebugPrintOutputSlot(value, frame_index, output_offset, | 1632 DebugPrintOutputSlot(value, frame_index, output_offset, |
1632 "constructor result\n"); | 1633 "constructor result\n"); |
1633 | 1634 |
1634 output_frame->SetState( | 1635 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
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 // BailoutState::TOS_REGISTER machinery. | 1689 // FullCodeGenerator::TOS_REG 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( | 1808 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
1809 Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER))); | |
1810 } else { | 1809 } else { |
1811 output_frame->SetState( | 1810 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
1812 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS))); | |
1813 } | 1811 } |
1814 | 1812 |
1815 CHECK_EQ(0u, output_offset); | 1813 CHECK_EQ(0u, output_offset); |
1816 | 1814 |
1817 Smi* offset = is_setter_stub_frame ? | 1815 Smi* offset = is_setter_stub_frame ? |
1818 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1816 isolate_->heap()->setter_stub_deopt_pc_offset() : |
1819 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1817 isolate_->heap()->getter_stub_deopt_pc_offset(); |
1820 intptr_t pc = reinterpret_cast<intptr_t>( | 1818 intptr_t pc = reinterpret_cast<intptr_t>( |
1821 accessor_stub->instruction_start() + offset->value()); | 1819 accessor_stub->instruction_start() + offset->value()); |
1822 output_frame->SetPc(pc); | 1820 output_frame->SetPc(pc); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2057 output_frame->SetPc(reinterpret_cast<intptr_t>( | 2055 output_frame->SetPc(reinterpret_cast<intptr_t>( |
2058 trampoline->instruction_start())); | 2056 trampoline->instruction_start())); |
2059 if (FLAG_enable_embedded_constant_pool) { | 2057 if (FLAG_enable_embedded_constant_pool) { |
2060 Register constant_pool_reg = | 2058 Register constant_pool_reg = |
2061 StubFailureTrampolineFrame::constant_pool_pointer_register(); | 2059 StubFailureTrampolineFrame::constant_pool_pointer_register(); |
2062 intptr_t constant_pool_value = | 2060 intptr_t constant_pool_value = |
2063 reinterpret_cast<intptr_t>(trampoline->constant_pool()); | 2061 reinterpret_cast<intptr_t>(trampoline->constant_pool()); |
2064 output_frame->SetConstantPool(constant_pool_value); | 2062 output_frame->SetConstantPool(constant_pool_value); |
2065 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 2063 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
2066 } | 2064 } |
2067 output_frame->SetState( | 2065 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
2068 Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS))); | |
2069 Code* notify_failure = | 2066 Code* notify_failure = |
2070 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); | 2067 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); |
2071 output_frame->SetContinuation( | 2068 output_frame->SetContinuation( |
2072 reinterpret_cast<intptr_t>(notify_failure->entry())); | 2069 reinterpret_cast<intptr_t>(notify_failure->entry())); |
2073 } | 2070 } |
2074 | 2071 |
2075 | 2072 |
2076 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | 2073 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { |
2077 // Walk to the last JavaScript output frame to find out if it has | 2074 // Walk to the last JavaScript output frame to find out if it has |
2078 // adapted arguments. | 2075 // adapted arguments. |
(...skipping 1847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3926 CHECK(value_info->IsMaterializedObject()); | 3923 CHECK(value_info->IsMaterializedObject()); |
3927 | 3924 |
3928 value_info->value_ = | 3925 value_info->value_ = |
3929 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3926 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3930 } | 3927 } |
3931 } | 3928 } |
3932 } | 3929 } |
3933 | 3930 |
3934 } // namespace internal | 3931 } // namespace internal |
3935 } // namespace v8 | 3932 } // namespace v8 |
OLD | NEW |