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 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 switch (type) { | 506 switch (type) { |
507 case EAGER: return "eager"; | 507 case EAGER: return "eager"; |
508 case SOFT: return "soft"; | 508 case SOFT: return "soft"; |
509 case LAZY: return "lazy"; | 509 case LAZY: return "lazy"; |
510 case DEBUGGER: return "debugger"; | 510 case DEBUGGER: return "debugger"; |
511 } | 511 } |
512 FATAL("Unsupported deopt type"); | 512 FATAL("Unsupported deopt type"); |
513 return NULL; | 513 return NULL; |
514 } | 514 } |
515 | 515 |
516 | |
517 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, | 516 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, |
518 BailoutType type, unsigned bailout_id, Address from, | 517 BailoutType type, unsigned bailout_id, Address from, |
519 int fp_to_sp_delta, Code* optimized_code) | 518 int fp_to_sp_delta, Code* optimized_code) |
520 : isolate_(isolate), | 519 : isolate_(isolate), |
521 function_(function), | 520 function_(function), |
522 bailout_id_(bailout_id), | 521 bailout_id_(bailout_id), |
523 bailout_type_(type), | 522 bailout_type_(type), |
524 from_(from), | 523 from_(from), |
525 fp_to_sp_delta_(fp_to_sp_delta), | 524 fp_to_sp_delta_(fp_to_sp_delta), |
526 has_alignment_padding_(0), | 525 has_alignment_padding_(0), |
| 526 deoptimizing_throw_(false), |
| 527 catch_handler_data_(-1), |
| 528 catch_handler_pc_offset_(-1), |
527 input_(nullptr), | 529 input_(nullptr), |
528 output_count_(0), | 530 output_count_(0), |
529 jsframe_count_(0), | 531 jsframe_count_(0), |
530 output_(nullptr), | 532 output_(nullptr), |
531 trace_scope_(nullptr) { | 533 trace_scope_(nullptr) { |
| 534 if (isolate->deoptimizer_lazy_throw()) { |
| 535 isolate->set_deoptimizer_lazy_throw(false); |
| 536 deoptimizing_throw_ = true; |
| 537 } |
| 538 |
532 // For COMPILED_STUBs called from builtins, the function pointer is a SMI | 539 // For COMPILED_STUBs called from builtins, the function pointer is a SMI |
533 // indicating an internal frame. | 540 // indicating an internal frame. |
534 if (function->IsSmi()) { | 541 if (function->IsSmi()) { |
535 function = nullptr; | 542 function = nullptr; |
536 } | 543 } |
537 DCHECK(from != nullptr); | 544 DCHECK(from != nullptr); |
538 if (function != nullptr && function->IsOptimized()) { | 545 if (function != nullptr && function->IsOptimized()) { |
539 function->shared()->increment_deopt_count(); | 546 function->shared()->increment_deopt_count(); |
540 if (bailout_type_ == Deoptimizer::SOFT) { | 547 if (bailout_type_ == Deoptimizer::SOFT) { |
541 isolate->counters()->soft_deopts_executed()->Increment(); | 548 isolate->counters()->soft_deopts_executed()->Increment(); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 Code* code = Code::cast(element); | 702 Code* code = Code::cast(element); |
696 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 703 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
697 length++; | 704 length++; |
698 element = code->next_code_link(); | 705 element = code->next_code_link(); |
699 } | 706 } |
700 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); | 707 context = Context::cast(context)->get(Context::NEXT_CONTEXT_LINK); |
701 } | 708 } |
702 return length; | 709 return length; |
703 } | 710 } |
704 | 711 |
| 712 namespace { |
| 713 |
| 714 int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) { |
| 715 switch (translated_frame->kind()) { |
| 716 case TranslatedFrame::kFunction: { |
| 717 BailoutId node_id = translated_frame->node_id(); |
| 718 JSFunction* function = |
| 719 JSFunction::cast(translated_frame->begin()->GetRawValue()); |
| 720 Code* non_optimized_code = function->shared()->code(); |
| 721 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
| 722 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
| 723 unsigned pc_and_state = |
| 724 Deoptimizer::GetOutputInfo(data, node_id, function->shared()); |
| 725 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
| 726 HandlerTable* table = |
| 727 HandlerTable::cast(non_optimized_code->handler_table()); |
| 728 HandlerTable::CatchPrediction prediction; |
| 729 return table->LookupRange(pc_offset, data_out, &prediction); |
| 730 } |
| 731 case TranslatedFrame::kInterpretedFunction: { |
| 732 int bytecode_offset = translated_frame->node_id().ToInt(); |
| 733 JSFunction* function = |
| 734 JSFunction::cast(translated_frame->begin()->GetRawValue()); |
| 735 BytecodeArray* bytecode = function->shared()->bytecode_array(); |
| 736 HandlerTable* table = HandlerTable::cast(bytecode->handler_table()); |
| 737 HandlerTable::CatchPrediction prediction; |
| 738 return table->LookupRange(bytecode_offset, data_out, &prediction); |
| 739 } |
| 740 default: |
| 741 break; |
| 742 } |
| 743 return -1; |
| 744 } |
| 745 |
| 746 } // namespace |
705 | 747 |
706 // We rely on this function not causing a GC. It is called from generated code | 748 // We rely on this function not causing a GC. It is called from generated code |
707 // without having a real stack frame in place. | 749 // without having a real stack frame in place. |
708 void Deoptimizer::DoComputeOutputFrames() { | 750 void Deoptimizer::DoComputeOutputFrames() { |
709 base::ElapsedTimer timer; | 751 base::ElapsedTimer timer; |
710 | 752 |
711 // Determine basic deoptimization information. The optimized frame is | 753 // Determine basic deoptimization information. The optimized frame is |
712 // described by the input data. | 754 // described by the input data. |
713 DeoptimizationInputData* input_data = | 755 DeoptimizationInputData* input_data = |
714 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); | 756 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); |
(...skipping 20 matching lines...) Expand all Loading... |
735 input_data->TranslationIndex(bailout_id_)->value(); | 777 input_data->TranslationIndex(bailout_id_)->value(); |
736 | 778 |
737 TranslationIterator state_iterator(translations, translation_index); | 779 TranslationIterator state_iterator(translations, translation_index); |
738 translated_state_.Init( | 780 translated_state_.Init( |
739 input_->GetFramePointerAddress(), &state_iterator, | 781 input_->GetFramePointerAddress(), &state_iterator, |
740 input_data->LiteralArray(), input_->GetRegisterValues(), | 782 input_data->LiteralArray(), input_->GetRegisterValues(), |
741 trace_scope_ == nullptr ? nullptr : trace_scope_->file()); | 783 trace_scope_ == nullptr ? nullptr : trace_scope_->file()); |
742 | 784 |
743 // Do the input frame to output frame(s) translation. | 785 // Do the input frame to output frame(s) translation. |
744 size_t count = translated_state_.frames().size(); | 786 size_t count = translated_state_.frames().size(); |
| 787 // If we are supposed to go to the catch handler, find the catching frame |
| 788 // for the catch and make sure we only deoptimize upto that frame. |
| 789 if (deoptimizing_throw_) { |
| 790 size_t catch_handler_frame_index = count; |
| 791 for (size_t i = count; i-- > 0;) { |
| 792 catch_handler_pc_offset_ = LookupCatchHandler( |
| 793 &(translated_state_.frames()[i]), &catch_handler_data_); |
| 794 if (catch_handler_pc_offset_ >= 0) { |
| 795 catch_handler_frame_index = i; |
| 796 break; |
| 797 } |
| 798 } |
| 799 CHECK_LT(catch_handler_frame_index, count); |
| 800 count = catch_handler_frame_index + 1; |
| 801 } |
| 802 |
745 DCHECK(output_ == NULL); | 803 DCHECK(output_ == NULL); |
746 output_ = new FrameDescription*[count]; | 804 output_ = new FrameDescription*[count]; |
747 for (size_t i = 0; i < count; ++i) { | 805 for (size_t i = 0; i < count; ++i) { |
748 output_[i] = NULL; | 806 output_[i] = NULL; |
749 } | 807 } |
750 output_count_ = static_cast<int>(count); | 808 output_count_ = static_cast<int>(count); |
751 | 809 |
752 Register fp_reg = JavaScriptFrame::fp_register(); | 810 Register fp_reg = JavaScriptFrame::fp_register(); |
753 stack_fp_ = reinterpret_cast<Address>( | 811 stack_fp_ = reinterpret_cast<Address>( |
754 input_->GetRegister(fp_reg.code()) + | 812 input_->GetRegister(fp_reg.code()) + |
755 has_alignment_padding_ * kPointerSize); | 813 has_alignment_padding_ * kPointerSize); |
756 | 814 |
757 // Translate each output frame. | 815 // Translate each output frame. |
758 for (size_t i = 0; i < count; ++i) { | 816 for (size_t i = 0; i < count; ++i) { |
759 // Read the ast node id, function, and frame height for this output frame. | 817 // Read the ast node id, function, and frame height for this output frame. |
760 int frame_index = static_cast<int>(i); | 818 int frame_index = static_cast<int>(i); |
761 switch (translated_state_.frames()[i].kind()) { | 819 switch (translated_state_.frames()[i].kind()) { |
762 case TranslatedFrame::kFunction: | 820 case TranslatedFrame::kFunction: |
763 DoComputeJSFrame(frame_index); | 821 DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1); |
764 jsframe_count_++; | 822 jsframe_count_++; |
765 break; | 823 break; |
766 case TranslatedFrame::kInterpretedFunction: | 824 case TranslatedFrame::kInterpretedFunction: |
767 DoComputeInterpretedFrame(frame_index); | 825 DoComputeInterpretedFrame(frame_index, |
| 826 deoptimizing_throw_ && i == count - 1); |
768 jsframe_count_++; | 827 jsframe_count_++; |
769 break; | 828 break; |
770 case TranslatedFrame::kArgumentsAdaptor: | 829 case TranslatedFrame::kArgumentsAdaptor: |
771 DoComputeArgumentsAdaptorFrame(frame_index); | 830 DoComputeArgumentsAdaptorFrame(frame_index); |
772 break; | 831 break; |
773 case TranslatedFrame::kConstructStub: | 832 case TranslatedFrame::kConstructStub: |
774 DoComputeConstructStubFrame(frame_index); | 833 DoComputeConstructStubFrame(frame_index); |
775 break; | 834 break; |
776 case TranslatedFrame::kGetter: | 835 case TranslatedFrame::kGetter: |
777 DoComputeAccessorStubFrame(frame_index, false); | 836 DoComputeAccessorStubFrame(frame_index, false); |
(...skipping 24 matching lines...) Expand all Loading... |
802 node_id.ToInt(), | 861 node_id.ToInt(), |
803 output_[index]->GetPc(), | 862 output_[index]->GetPc(), |
804 FullCodeGenerator::State2String( | 863 FullCodeGenerator::State2String( |
805 static_cast<FullCodeGenerator::State>( | 864 static_cast<FullCodeGenerator::State>( |
806 output_[index]->GetState()->value())), | 865 output_[index]->GetState()->value())), |
807 has_alignment_padding_ ? "with padding" : "no padding", | 866 has_alignment_padding_ ? "with padding" : "no padding", |
808 ms); | 867 ms); |
809 } | 868 } |
810 } | 869 } |
811 | 870 |
812 | 871 void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) { |
813 void Deoptimizer::DoComputeJSFrame(int frame_index) { | |
814 TranslatedFrame* translated_frame = | 872 TranslatedFrame* translated_frame = |
815 &(translated_state_.frames()[frame_index]); | 873 &(translated_state_.frames()[frame_index]); |
816 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 874 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
| 875 bool is_bottommost = (0 == frame_index); |
| 876 bool is_topmost = (output_count_ - 1 == frame_index); |
817 int input_index = 0; | 877 int input_index = 0; |
818 | 878 |
819 BailoutId node_id = translated_frame->node_id(); | 879 BailoutId node_id = translated_frame->node_id(); |
820 unsigned height = | 880 unsigned height = |
821 translated_frame->height() - 1; // Do not count the context. | 881 translated_frame->height() - 1; // Do not count the context. |
822 unsigned height_in_bytes = height * kPointerSize; | 882 unsigned height_in_bytes = height * kPointerSize; |
| 883 if (goto_catch_handler) { |
| 884 // Take the stack height from the handler table. |
| 885 height = catch_handler_data_; |
| 886 // We also make space for the exception itself. |
| 887 height_in_bytes = (height + 1) * kPointerSize; |
| 888 DCHECK(is_topmost); |
| 889 } |
| 890 |
823 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); | 891 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); |
824 value_iterator++; | 892 value_iterator++; |
825 input_index++; | 893 input_index++; |
826 if (trace_scope_ != NULL) { | 894 if (trace_scope_ != NULL) { |
827 PrintF(trace_scope_->file(), " translating frame "); | 895 PrintF(trace_scope_->file(), " translating frame "); |
828 function->PrintName(trace_scope_->file()); | 896 function->PrintName(trace_scope_->file()); |
829 PrintF(trace_scope_->file(), | 897 PrintF(trace_scope_->file(), " => node=%d, height=%d%s\n", node_id.ToInt(), |
830 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); | 898 height_in_bytes, goto_catch_handler ? " (throw)" : ""); |
831 } | 899 } |
832 | 900 |
833 // The 'fixed' part of the frame consists of the incoming parameters and | 901 // The 'fixed' part of the frame consists of the incoming parameters and |
834 // the part described by JavaScriptFrameConstants. | 902 // the part described by JavaScriptFrameConstants. |
835 unsigned fixed_frame_size = ComputeJavascriptFixedSize(function); | 903 unsigned fixed_frame_size = ComputeJavascriptFixedSize(function); |
836 unsigned input_frame_size = input_->GetFrameSize(); | 904 unsigned input_frame_size = input_->GetFrameSize(); |
837 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 905 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
838 | 906 |
839 // Allocate and store the output frame description. | 907 // Allocate and store the output frame description. |
840 FrameDescription* output_frame = | 908 FrameDescription* output_frame = |
841 new(output_frame_size) FrameDescription(output_frame_size, function); | 909 new(output_frame_size) FrameDescription(output_frame_size, function); |
842 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); | 910 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
843 | 911 |
844 bool is_bottommost = (0 == frame_index); | |
845 bool is_topmost = (output_count_ - 1 == frame_index); | |
846 CHECK(frame_index >= 0 && frame_index < output_count_); | 912 CHECK(frame_index >= 0 && frame_index < output_count_); |
847 CHECK_NULL(output_[frame_index]); | 913 CHECK_NULL(output_[frame_index]); |
848 output_[frame_index] = output_frame; | 914 output_[frame_index] = output_frame; |
849 | 915 |
850 // The top address for the bottommost output frame can be computed from | 916 // The top address for the bottommost output frame can be computed from |
851 // the input frame pointer and the output frame's height. For all | 917 // the input frame pointer and the output frame's height. For all |
852 // subsequent output frames, it can be computed from the previous one's | 918 // subsequent output frames, it can be computed from the previous one's |
853 // top address and the current frame's size. | 919 // top address and the current frame's size. |
854 Register fp_reg = JavaScriptFrame::fp_register(); | 920 Register fp_reg = JavaScriptFrame::fp_register(); |
855 intptr_t top_address; | 921 intptr_t top_address; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 DebugPrintOutputSlot(value, frame_index, output_offset, | 1004 DebugPrintOutputSlot(value, frame_index, output_offset, |
939 "caller's constant_pool\n"); | 1005 "caller's constant_pool\n"); |
940 } | 1006 } |
941 | 1007 |
942 // For the bottommost output frame the context can be gotten from the input | 1008 // For the bottommost output frame the context can be gotten from the input |
943 // frame. For all subsequent output frames it can be gotten from the function | 1009 // frame. For all subsequent output frames it can be gotten from the function |
944 // so long as we don't inline functions that need local contexts. | 1010 // so long as we don't inline functions that need local contexts. |
945 Register context_reg = JavaScriptFrame::context_register(); | 1011 Register context_reg = JavaScriptFrame::context_register(); |
946 output_offset -= kPointerSize; | 1012 output_offset -= kPointerSize; |
947 input_offset -= kPointerSize; | 1013 input_offset -= kPointerSize; |
| 1014 |
| 1015 TranslatedFrame::iterator context_pos = value_iterator; |
| 1016 int context_input_index = input_index; |
| 1017 // When deoptimizing into a catch block, we need to take the context |
| 1018 // from just above the top of the operand stack (we push the context |
| 1019 // at the entry of the try block). |
| 1020 if (goto_catch_handler) { |
| 1021 for (unsigned i = 0; i < height + 1; ++i) { |
| 1022 context_pos++; |
| 1023 context_input_index++; |
| 1024 } |
| 1025 } |
948 // Read the context from the translations. | 1026 // Read the context from the translations. |
949 Object* context = value_iterator->GetRawValue(); | 1027 Object* context = context_pos->GetRawValue(); |
950 if (context == isolate_->heap()->undefined_value()) { | 1028 if (context == isolate_->heap()->undefined_value()) { |
951 // If the context was optimized away, just use the context from | 1029 // If the context was optimized away, just use the context from |
952 // the activation. This should only apply to Crankshaft code. | 1030 // the activation. This should only apply to Crankshaft code. |
953 CHECK(!compiled_code_->is_turbofanned()); | 1031 CHECK(!compiled_code_->is_turbofanned()); |
954 context = | 1032 context = |
955 is_bottommost | 1033 is_bottommost |
956 ? reinterpret_cast<Object*>(input_->GetFrameSlot(input_offset)) | 1034 ? reinterpret_cast<Object*>(input_->GetFrameSlot(input_offset)) |
957 : function->context(); | 1035 : function->context(); |
958 } | 1036 } |
959 value = reinterpret_cast<intptr_t>(context); | 1037 value = reinterpret_cast<intptr_t>(context); |
960 output_frame->SetContext(value); | 1038 output_frame->SetContext(value); |
961 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); | 1039 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); |
962 WriteValueToOutput(context, input_index, frame_index, output_offset, | 1040 WriteValueToOutput(context, context_input_index, frame_index, output_offset, |
963 "context "); | 1041 "context "); |
964 if (context == isolate_->heap()->arguments_marker()) { | 1042 if (context == isolate_->heap()->arguments_marker()) { |
965 Address output_address = | 1043 Address output_address = |
966 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + | 1044 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + |
967 output_offset; | 1045 output_offset; |
968 values_to_materialize_.push_back({output_address, value_iterator}); | 1046 values_to_materialize_.push_back({output_address, context_pos}); |
969 } | 1047 } |
970 value_iterator++; | 1048 value_iterator++; |
971 input_index++; | 1049 input_index++; |
972 | 1050 |
973 // The function was mentioned explicitly in the BEGIN_FRAME. | 1051 // The function was mentioned explicitly in the BEGIN_FRAME. |
974 output_offset -= kPointerSize; | 1052 output_offset -= kPointerSize; |
975 input_offset -= kPointerSize; | 1053 input_offset -= kPointerSize; |
976 value = reinterpret_cast<intptr_t>(function); | 1054 value = reinterpret_cast<intptr_t>(function); |
977 // The function for the bottommost output frame should also agree with the | 1055 // The function for the bottommost output frame should also agree with the |
978 // input frame. | 1056 // input frame. |
979 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); | 1057 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); |
980 WriteValueToOutput(function, 0, frame_index, output_offset, "function "); | 1058 WriteValueToOutput(function, 0, frame_index, output_offset, "function "); |
981 | 1059 |
982 // Translate the rest of the frame. | 1060 // Translate the rest of the frame. |
983 for (unsigned i = 0; i < height; ++i) { | 1061 for (unsigned i = 0; i < height; ++i) { |
984 output_offset -= kPointerSize; | 1062 output_offset -= kPointerSize; |
985 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1063 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
986 output_offset); | 1064 output_offset); |
987 } | 1065 } |
| 1066 if (goto_catch_handler) { |
| 1067 // Write out the exception for the catch handler. |
| 1068 output_offset -= kPointerSize; |
| 1069 Object* exception_obj = reinterpret_cast<Object*>( |
| 1070 input_->GetRegister(FullCodeGenerator::result_register().code())); |
| 1071 WriteValueToOutput(exception_obj, input_index, frame_index, output_offset, |
| 1072 "exception "); |
| 1073 input_index++; |
| 1074 } |
988 CHECK_EQ(0u, output_offset); | 1075 CHECK_EQ(0u, output_offset); |
989 | 1076 |
990 // Compute this frame's PC, state, and continuation. | |
991 Code* non_optimized_code = function->shared()->code(); | 1077 Code* non_optimized_code = function->shared()->code(); |
992 FixedArray* raw_data = non_optimized_code->deoptimization_data(); | |
993 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); | |
994 Address start = non_optimized_code->instruction_start(); | |
995 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); | |
996 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); | |
997 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); | |
998 output_frame->SetPc(pc_value); | |
999 | 1078 |
1000 // Update constant pool. | 1079 // Update constant pool. |
1001 if (FLAG_enable_embedded_constant_pool) { | 1080 if (FLAG_enable_embedded_constant_pool) { |
1002 intptr_t constant_pool_value = | 1081 intptr_t constant_pool_value = |
1003 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool()); | 1082 reinterpret_cast<intptr_t>(non_optimized_code->constant_pool()); |
1004 output_frame->SetConstantPool(constant_pool_value); | 1083 output_frame->SetConstantPool(constant_pool_value); |
1005 if (is_topmost) { | 1084 if (is_topmost) { |
1006 Register constant_pool_reg = | 1085 Register constant_pool_reg = |
1007 JavaScriptFrame::constant_pool_pointer_register(); | 1086 JavaScriptFrame::constant_pool_pointer_register(); |
1008 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); | 1087 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); |
1009 } | 1088 } |
1010 } | 1089 } |
1011 | 1090 |
| 1091 // Compute this frame's PC, state, and continuation. |
| 1092 FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
| 1093 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
| 1094 Address start = non_optimized_code->instruction_start(); |
| 1095 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
| 1096 unsigned pc_offset = goto_catch_handler |
| 1097 ? catch_handler_pc_offset_ |
| 1098 : FullCodeGenerator::PcField::decode(pc_and_state); |
| 1099 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
| 1100 output_frame->SetPc(pc_value); |
| 1101 |
| 1102 // If we are going to the catch handler, then the exception lives in |
| 1103 // the accumulator. |
1012 FullCodeGenerator::State state = | 1104 FullCodeGenerator::State state = |
1013 FullCodeGenerator::StateField::decode(pc_and_state); | 1105 goto_catch_handler ? FullCodeGenerator::TOS_REG |
| 1106 : FullCodeGenerator::StateField::decode(pc_and_state); |
1014 output_frame->SetState(Smi::FromInt(state)); | 1107 output_frame->SetState(Smi::FromInt(state)); |
1015 | 1108 |
1016 // Set the continuation for the topmost frame. | 1109 // Set the continuation for the topmost frame. |
1017 if (is_topmost && bailout_type_ != DEBUGGER) { | 1110 if (is_topmost && bailout_type_ != DEBUGGER) { |
1018 Builtins* builtins = isolate_->builtins(); | 1111 Builtins* builtins = isolate_->builtins(); |
1019 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); | 1112 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
1020 if (bailout_type_ == LAZY) { | 1113 if (bailout_type_ == LAZY) { |
1021 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); | 1114 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
1022 } else if (bailout_type_ == SOFT) { | 1115 } else if (bailout_type_ == SOFT) { |
1023 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); | 1116 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
1024 } else { | 1117 } else { |
1025 CHECK_EQ(bailout_type_, EAGER); | 1118 CHECK_EQ(bailout_type_, EAGER); |
1026 } | 1119 } |
1027 output_frame->SetContinuation( | 1120 output_frame->SetContinuation( |
1028 reinterpret_cast<intptr_t>(continuation->entry())); | 1121 reinterpret_cast<intptr_t>(continuation->entry())); |
1029 } | 1122 } |
1030 } | 1123 } |
1031 | 1124 |
1032 | 1125 void Deoptimizer::DoComputeInterpretedFrame(int frame_index, |
1033 void Deoptimizer::DoComputeInterpretedFrame(int frame_index) { | 1126 bool goto_catch_handler) { |
1034 TranslatedFrame* translated_frame = | 1127 TranslatedFrame* translated_frame = |
1035 &(translated_state_.frames()[frame_index]); | 1128 &(translated_state_.frames()[frame_index]); |
1036 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 1129 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
1037 int input_index = 0; | 1130 int input_index = 0; |
1038 | 1131 |
1039 BailoutId bytecode_offset = translated_frame->node_id(); | 1132 int bytecode_offset = translated_frame->node_id().ToInt(); |
1040 unsigned height = translated_frame->height(); | 1133 unsigned height = translated_frame->height(); |
1041 unsigned height_in_bytes = height * kPointerSize; | 1134 unsigned height_in_bytes = height * kPointerSize; |
1042 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); | 1135 JSFunction* function = JSFunction::cast(value_iterator->GetRawValue()); |
1043 value_iterator++; | 1136 value_iterator++; |
1044 input_index++; | 1137 input_index++; |
1045 if (trace_scope_ != NULL) { | 1138 if (trace_scope_ != NULL) { |
1046 PrintF(trace_scope_->file(), " translating interpreted frame "); | 1139 PrintF(trace_scope_->file(), " translating interpreted frame "); |
1047 function->PrintName(trace_scope_->file()); | 1140 function->PrintName(trace_scope_->file()); |
1048 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d\n", | 1141 PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n", |
1049 bytecode_offset.ToInt(), height_in_bytes); | 1142 bytecode_offset, height_in_bytes, |
| 1143 goto_catch_handler ? " (throw)" : ""); |
| 1144 } |
| 1145 if (goto_catch_handler) { |
| 1146 bytecode_offset = catch_handler_pc_offset_; |
1050 } | 1147 } |
1051 | 1148 |
1052 // The 'fixed' part of the frame consists of the incoming parameters and | 1149 // The 'fixed' part of the frame consists of the incoming parameters and |
1053 // the part described by InterpreterFrameConstants. | 1150 // the part described by InterpreterFrameConstants. |
1054 unsigned fixed_frame_size = ComputeInterpretedFixedSize(function); | 1151 unsigned fixed_frame_size = ComputeInterpretedFixedSize(function); |
1055 unsigned input_frame_size = input_->GetFrameSize(); | 1152 unsigned input_frame_size = input_->GetFrameSize(); |
1056 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1153 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1057 | 1154 |
1058 // Allocate and store the output frame description. | 1155 // Allocate and store the output frame description. |
1059 FrameDescription* output_frame = | 1156 FrameDescription* output_frame = |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 DebugPrintOutputSlot(value, frame_index, output_offset, | 1249 DebugPrintOutputSlot(value, frame_index, output_offset, |
1153 "caller's constant_pool\n"); | 1250 "caller's constant_pool\n"); |
1154 } | 1251 } |
1155 | 1252 |
1156 // For the bottommost output frame the context can be gotten from the input | 1253 // For the bottommost output frame the context can be gotten from the input |
1157 // frame. For all subsequent output frames it can be gotten from the function | 1254 // frame. For all subsequent output frames it can be gotten from the function |
1158 // so long as we don't inline functions that need local contexts. | 1255 // so long as we don't inline functions that need local contexts. |
1159 Register context_reg = InterpretedFrame::context_register(); | 1256 Register context_reg = InterpretedFrame::context_register(); |
1160 output_offset -= kPointerSize; | 1257 output_offset -= kPointerSize; |
1161 input_offset -= kPointerSize; | 1258 input_offset -= kPointerSize; |
| 1259 |
| 1260 // When deoptimizing into a catch block, we need to take the context |
| 1261 // from a register that was specified in the handler table. |
| 1262 TranslatedFrame::iterator context_pos = value_iterator; |
| 1263 int context_input_index = input_index; |
| 1264 if (goto_catch_handler) { |
| 1265 // Skip to the translated value of the register specified |
| 1266 // in the handler table. |
| 1267 for (int i = 0; i < catch_handler_data_ + 1; ++i) { |
| 1268 context_pos++; |
| 1269 context_input_index++; |
| 1270 } |
| 1271 } |
1162 // Read the context from the translations. | 1272 // Read the context from the translations. |
1163 Object* context = value_iterator->GetRawValue(); | 1273 Object* context = context_pos->GetRawValue(); |
1164 // The context should not be a placeholder for a materialized object. | 1274 // The context should not be a placeholder for a materialized object. |
1165 CHECK(context != isolate_->heap()->arguments_marker()); | 1275 CHECK(context != isolate_->heap()->arguments_marker()); |
1166 value = reinterpret_cast<intptr_t>(context); | 1276 value = reinterpret_cast<intptr_t>(context); |
1167 output_frame->SetContext(value); | 1277 output_frame->SetContext(value); |
1168 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); | 1278 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); |
1169 WriteValueToOutput(context, input_index, frame_index, output_offset, | 1279 WriteValueToOutput(context, context_input_index, frame_index, output_offset, |
1170 "context "); | 1280 "context "); |
1171 value_iterator++; | 1281 value_iterator++; |
1172 input_index++; | 1282 input_index++; |
1173 | 1283 |
1174 // The function was mentioned explicitly in the BEGIN_FRAME. | 1284 // The function was mentioned explicitly in the BEGIN_FRAME. |
1175 output_offset -= kPointerSize; | 1285 output_offset -= kPointerSize; |
1176 input_offset -= kPointerSize; | 1286 input_offset -= kPointerSize; |
1177 value = reinterpret_cast<intptr_t>(function); | 1287 value = reinterpret_cast<intptr_t>(function); |
1178 // The function for the bottommost output frame should also agree with the | 1288 // The function for the bottommost output frame should also agree with the |
1179 // input frame. | 1289 // input frame. |
1180 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); | 1290 DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value); |
1181 WriteValueToOutput(function, 0, frame_index, output_offset, "function "); | 1291 WriteValueToOutput(function, 0, frame_index, output_offset, "function "); |
1182 | 1292 |
1183 // TODO(rmcilroy): Deal with new.target correctly - currently just set it to | 1293 // TODO(rmcilroy): Deal with new.target correctly - currently just set it to |
1184 // undefined. | 1294 // undefined. |
1185 output_offset -= kPointerSize; | 1295 output_offset -= kPointerSize; |
1186 input_offset -= kPointerSize; | 1296 input_offset -= kPointerSize; |
1187 Object* new_target = isolate_->heap()->undefined_value(); | 1297 Object* new_target = isolate_->heap()->undefined_value(); |
1188 WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target "); | 1298 WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target "); |
1189 | 1299 |
1190 // The bytecode offset was mentioned explicitly in the BEGIN_FRAME. | 1300 // The bytecode offset was mentioned explicitly in the BEGIN_FRAME. |
1191 output_offset -= kPointerSize; | 1301 output_offset -= kPointerSize; |
1192 input_offset -= kPointerSize; | 1302 input_offset -= kPointerSize; |
1193 int raw_bytecode_offset = | 1303 int raw_bytecode_offset = |
1194 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset.ToInt(); | 1304 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset; |
1195 Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset); | 1305 Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset); |
1196 WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset, | 1306 WriteValueToOutput(smi_bytecode_offset, 0, frame_index, output_offset, |
1197 "bytecode offset "); | 1307 "bytecode offset "); |
1198 | 1308 |
1199 // Translate the rest of the interpreter registers in the frame. | 1309 // Translate the rest of the interpreter registers in the frame. |
1200 for (unsigned i = 0; i < height; ++i) { | 1310 for (unsigned i = 0; i < height; ++i) { |
1201 output_offset -= kPointerSize; | 1311 output_offset -= kPointerSize; |
1202 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1312 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
1203 output_offset); | 1313 output_offset); |
1204 } | 1314 } |
1205 CHECK_EQ(0u, output_offset); | 1315 CHECK_EQ(0u, output_offset); |
1206 | 1316 |
1207 // Set the accumulator register. | 1317 // Set the accumulator register. If we are lazy deopting to a catch handler, |
1208 output_frame->SetRegister( | 1318 // we set the accumulator to the exception (which lives in the result |
1209 kInterpreterAccumulatorRegister.code(), | 1319 // register). |
1210 reinterpret_cast<intptr_t>(value_iterator->GetRawValue())); | 1320 intptr_t accumulator_value = |
| 1321 goto_catch_handler |
| 1322 ? input_->GetRegister(FullCodeGenerator::result_register().code()) |
| 1323 : reinterpret_cast<intptr_t>(value_iterator->GetRawValue()); |
| 1324 output_frame->SetRegister(kInterpreterAccumulatorRegister.code(), |
| 1325 accumulator_value); |
1211 value_iterator++; | 1326 value_iterator++; |
1212 | 1327 |
1213 Builtins* builtins = isolate_->builtins(); | 1328 Builtins* builtins = isolate_->builtins(); |
1214 Code* dispatch_builtin = | 1329 Code* dispatch_builtin = |
1215 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch); | 1330 builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch); |
1216 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry())); | 1331 output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry())); |
1217 output_frame->SetState(0); | 1332 output_frame->SetState(0); |
1218 | 1333 |
1219 // Update constant pool. | 1334 // Update constant pool. |
1220 if (FLAG_enable_embedded_constant_pool) { | 1335 if (FLAG_enable_embedded_constant_pool) { |
(...skipping 2490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3711 DCHECK(value_info->IsMaterializedObject()); | 3826 DCHECK(value_info->IsMaterializedObject()); |
3712 | 3827 |
3713 value_info->value_ = | 3828 value_info->value_ = |
3714 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3829 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3715 } | 3830 } |
3716 } | 3831 } |
3717 } | 3832 } |
3718 | 3833 |
3719 } // namespace internal | 3834 } // namespace internal |
3720 } // namespace v8 | 3835 } // namespace v8 |
OLD | NEW |