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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 | 467 |
468 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, | 468 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, |
469 BailoutType type, unsigned bailout_id, Address from, | 469 BailoutType type, unsigned bailout_id, Address from, |
470 int fp_to_sp_delta, Code* optimized_code) | 470 int fp_to_sp_delta, Code* optimized_code) |
471 : isolate_(isolate), | 471 : isolate_(isolate), |
472 function_(function), | 472 function_(function), |
473 bailout_id_(bailout_id), | 473 bailout_id_(bailout_id), |
474 bailout_type_(type), | 474 bailout_type_(type), |
475 from_(from), | 475 from_(from), |
476 fp_to_sp_delta_(fp_to_sp_delta), | 476 fp_to_sp_delta_(fp_to_sp_delta), |
477 has_alignment_padding_(0), | |
478 deoptimizing_throw_(false), | 477 deoptimizing_throw_(false), |
479 catch_handler_data_(-1), | 478 catch_handler_data_(-1), |
480 catch_handler_pc_offset_(-1), | 479 catch_handler_pc_offset_(-1), |
481 input_(nullptr), | 480 input_(nullptr), |
482 output_count_(0), | 481 output_count_(0), |
483 jsframe_count_(0), | 482 jsframe_count_(0), |
484 output_(nullptr), | 483 output_(nullptr), |
485 trace_scope_(nullptr) { | 484 trace_scope_(nullptr) { |
486 if (isolate->deoptimizer_lazy_throw()) { | 485 if (isolate->deoptimizer_lazy_throw()) { |
487 isolate->set_deoptimizer_lazy_throw(false); | 486 isolate->set_deoptimizer_lazy_throw(false); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 } | 756 } |
758 | 757 |
759 DCHECK(output_ == NULL); | 758 DCHECK(output_ == NULL); |
760 output_ = new FrameDescription*[count]; | 759 output_ = new FrameDescription*[count]; |
761 for (size_t i = 0; i < count; ++i) { | 760 for (size_t i = 0; i < count; ++i) { |
762 output_[i] = NULL; | 761 output_[i] = NULL; |
763 } | 762 } |
764 output_count_ = static_cast<int>(count); | 763 output_count_ = static_cast<int>(count); |
765 | 764 |
766 Register fp_reg = JavaScriptFrame::fp_register(); | 765 Register fp_reg = JavaScriptFrame::fp_register(); |
767 stack_fp_ = reinterpret_cast<Address>( | 766 stack_fp_ = reinterpret_cast<Address>(input_->GetRegister(fp_reg.code())); |
768 input_->GetRegister(fp_reg.code()) + | |
769 has_alignment_padding_ * kPointerSize); | |
770 | 767 |
771 // Translate each output frame. | 768 // Translate each output frame. |
772 for (size_t i = 0; i < count; ++i) { | 769 for (size_t i = 0; i < count; ++i) { |
773 // Read the ast node id, function, and frame height for this output frame. | 770 // Read the ast node id, function, and frame height for this output frame. |
774 int frame_index = static_cast<int>(i); | 771 int frame_index = static_cast<int>(i); |
775 switch (translated_state_.frames()[i].kind()) { | 772 switch (translated_state_.frames()[i].kind()) { |
776 case TranslatedFrame::kFunction: | 773 case TranslatedFrame::kFunction: |
777 DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1); | 774 DoComputeJSFrame(frame_index, deoptimizing_throw_ && i == count - 1); |
778 jsframe_count_++; | 775 jsframe_count_++; |
779 break; | 776 break; |
(...skipping 23 matching lines...) Expand all Loading... |
803 } | 800 } |
804 } | 801 } |
805 | 802 |
806 // Print some helpful diagnostic information. | 803 // Print some helpful diagnostic information. |
807 if (trace_scope_ != NULL) { | 804 if (trace_scope_ != NULL) { |
808 double ms = timer.Elapsed().InMillisecondsF(); | 805 double ms = timer.Elapsed().InMillisecondsF(); |
809 int index = output_count_ - 1; // Index of the topmost frame. | 806 int index = output_count_ - 1; // Index of the topmost frame. |
810 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", | 807 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", |
811 MessageFor(bailout_type_)); | 808 MessageFor(bailout_type_)); |
812 PrintFunctionName(); | 809 PrintFunctionName(); |
813 PrintF(trace_scope_->file(), | 810 PrintF( |
814 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," | 811 trace_scope_->file(), |
815 " took %0.3f ms]\n", | 812 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, took %0.3f ms]\n", |
816 bailout_id_, | 813 bailout_id_, node_id.ToInt(), output_[index]->GetPc(), |
817 node_id.ToInt(), | 814 FullCodeGenerator::State2String(static_cast<FullCodeGenerator::State>( |
818 output_[index]->GetPc(), | 815 output_[index]->GetState()->value())), |
819 FullCodeGenerator::State2String( | 816 ms); |
820 static_cast<FullCodeGenerator::State>( | |
821 output_[index]->GetState()->value())), | |
822 has_alignment_padding_ ? "with padding" : "no padding", | |
823 ms); | |
824 } | 817 } |
825 } | 818 } |
826 | 819 |
827 void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) { | 820 void Deoptimizer::DoComputeJSFrame(int frame_index, bool goto_catch_handler) { |
828 TranslatedFrame* translated_frame = | 821 TranslatedFrame* translated_frame = |
829 &(translated_state_.frames()[frame_index]); | 822 &(translated_state_.frames()[frame_index]); |
830 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); | 823 SharedFunctionInfo* shared = translated_frame->raw_shared_info(); |
831 | 824 |
832 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 825 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
833 bool is_bottommost = (0 == frame_index); | 826 bool is_bottommost = (0 == frame_index); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 CHECK_NULL(output_[frame_index]); | 868 CHECK_NULL(output_[frame_index]); |
876 output_[frame_index] = output_frame; | 869 output_[frame_index] = output_frame; |
877 | 870 |
878 // The top address for the bottommost output frame can be computed from | 871 // The top address for the bottommost output frame can be computed from |
879 // the input frame pointer and the output frame's height. For all | 872 // the input frame pointer and the output frame's height. For all |
880 // subsequent output frames, it can be computed from the previous one's | 873 // subsequent output frames, it can be computed from the previous one's |
881 // top address and the current frame's size. | 874 // top address and the current frame's size. |
882 Register fp_reg = JavaScriptFrame::fp_register(); | 875 Register fp_reg = JavaScriptFrame::fp_register(); |
883 intptr_t top_address; | 876 intptr_t top_address; |
884 if (is_bottommost) { | 877 if (is_bottommost) { |
885 // Determine whether the input frame contains alignment padding. | |
886 has_alignment_padding_ = | |
887 (!compiled_code_->is_turbofanned() && HasAlignmentPadding(shared)) ? 1 | |
888 : 0; | |
889 // 2 = context and function in the frame. | 878 // 2 = context and function in the frame. |
890 // If the optimized frame had alignment padding, adjust the frame pointer | 879 // If the optimized frame had alignment padding, adjust the frame pointer |
891 // to point to the new position of the old frame pointer after padding | 880 // to point to the new position of the old frame pointer after padding |
892 // is removed. Subtract 2 * kPointerSize for the context and function slots. | 881 // is removed. Subtract 2 * kPointerSize for the context and function slots. |
893 top_address = input_->GetRegister(fp_reg.code()) - | 882 top_address = input_->GetRegister(fp_reg.code()) - |
894 StandardFrameConstants::kFixedFrameSizeFromFp - | 883 StandardFrameConstants::kFixedFrameSizeFromFp - |
895 height_in_bytes + has_alignment_padding_ * kPointerSize; | 884 height_in_bytes; |
896 } else { | 885 } else { |
897 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 886 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
898 } | 887 } |
899 output_frame->SetTop(top_address); | 888 output_frame->SetTop(top_address); |
900 | 889 |
901 // Compute the incoming parameter translation. | 890 // Compute the incoming parameter translation. |
902 unsigned output_offset = output_frame_size; | 891 unsigned output_offset = output_frame_size; |
903 unsigned input_offset = input_frame_size; | 892 unsigned input_offset = input_frame_size; |
904 for (int i = 0; i < parameter_count; ++i) { | 893 for (int i = 0; i < parameter_count; ++i) { |
905 output_offset -= kPointerSize; | 894 output_offset -= kPointerSize; |
(...skipping 27 matching lines...) Expand all Loading... |
933 // pointer. | 922 // pointer. |
934 output_offset -= kFPOnStackSize; | 923 output_offset -= kFPOnStackSize; |
935 input_offset -= kFPOnStackSize; | 924 input_offset -= kFPOnStackSize; |
936 if (is_bottommost) { | 925 if (is_bottommost) { |
937 value = input_->GetFrameSlot(input_offset); | 926 value = input_->GetFrameSlot(input_offset); |
938 } else { | 927 } else { |
939 value = output_[frame_index - 1]->GetFp(); | 928 value = output_[frame_index - 1]->GetFp(); |
940 } | 929 } |
941 output_frame->SetCallerFp(output_offset, value); | 930 output_frame->SetCallerFp(output_offset, value); |
942 intptr_t fp_value = top_address + output_offset; | 931 intptr_t fp_value = top_address + output_offset; |
943 DCHECK(!is_bottommost || (input_->GetRegister(fp_reg.code()) + | 932 DCHECK(!is_bottommost || input_->GetRegister(fp_reg.code()) == fp_value); |
944 has_alignment_padding_ * kPointerSize) == fp_value); | |
945 output_frame->SetFp(fp_value); | 933 output_frame->SetFp(fp_value); |
946 if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); | 934 if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); |
947 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 935 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
948 DCHECK(!is_bottommost || !has_alignment_padding_ || | |
949 (fp_value & kPointerSize) != 0); | |
950 | 936 |
951 if (FLAG_enable_embedded_constant_pool) { | 937 if (FLAG_enable_embedded_constant_pool) { |
952 // For the bottommost output frame the constant pool pointer can be gotten | 938 // For the bottommost output frame the constant pool pointer can be gotten |
953 // from the input frame. For subsequent output frames, it can be read from | 939 // from the input frame. For subsequent output frames, it can be read from |
954 // the previous frame. | 940 // the previous frame. |
955 output_offset -= kPointerSize; | 941 output_offset -= kPointerSize; |
956 input_offset -= kPointerSize; | 942 input_offset -= kPointerSize; |
957 if (is_bottommost) { | 943 if (is_bottommost) { |
958 value = input_->GetFrameSlot(input_offset); | 944 value = input_->GetFrameSlot(input_offset); |
959 } else { | 945 } else { |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 // pointer. | 1164 // pointer. |
1179 output_offset -= kFPOnStackSize; | 1165 output_offset -= kFPOnStackSize; |
1180 input_offset -= kFPOnStackSize; | 1166 input_offset -= kFPOnStackSize; |
1181 if (is_bottommost) { | 1167 if (is_bottommost) { |
1182 value = input_->GetFrameSlot(input_offset); | 1168 value = input_->GetFrameSlot(input_offset); |
1183 } else { | 1169 } else { |
1184 value = output_[frame_index - 1]->GetFp(); | 1170 value = output_[frame_index - 1]->GetFp(); |
1185 } | 1171 } |
1186 output_frame->SetCallerFp(output_offset, value); | 1172 output_frame->SetCallerFp(output_offset, value); |
1187 intptr_t fp_value = top_address + output_offset; | 1173 intptr_t fp_value = top_address + output_offset; |
1188 DCHECK(!is_bottommost || | 1174 DCHECK(!is_bottommost || input_->GetRegister(fp_reg.code()) == fp_value); |
1189 (input_->GetRegister(fp_reg.code()) + | |
1190 has_alignment_padding_ * kPointerSize) == fp_value); | |
1191 output_frame->SetFp(fp_value); | 1175 output_frame->SetFp(fp_value); |
1192 if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); | 1176 if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); |
1193 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 1177 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
1194 DCHECK(!is_bottommost || !has_alignment_padding_ || | |
1195 (fp_value & kPointerSize) != 0); | |
1196 | 1178 |
1197 if (FLAG_enable_embedded_constant_pool) { | 1179 if (FLAG_enable_embedded_constant_pool) { |
1198 // For the bottommost output frame the constant pool pointer can be gotten | 1180 // For the bottommost output frame the constant pool pointer can be gotten |
1199 // from the input frame. For subsequent output frames, it can be read from | 1181 // from the input frame. For subsequent output frames, it can be read from |
1200 // the previous frame. | 1182 // the previous frame. |
1201 output_offset -= kPointerSize; | 1183 output_offset -= kPointerSize; |
1202 input_offset -= kPointerSize; | 1184 input_offset -= kPointerSize; |
1203 if (is_bottommost) { | 1185 if (is_bottommost) { |
1204 value = input_->GetFrameSlot(input_offset); | 1186 value = input_->GetFrameSlot(input_offset); |
1205 } else { | 1187 } else { |
(...skipping 2550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3756 CHECK(value_info->IsMaterializedObject()); | 3738 CHECK(value_info->IsMaterializedObject()); |
3757 | 3739 |
3758 value_info->value_ = | 3740 value_info->value_ = |
3759 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3741 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3760 } | 3742 } |
3761 } | 3743 } |
3762 } | 3744 } |
3763 | 3745 |
3764 } // namespace internal | 3746 } // namespace internal |
3765 } // namespace v8 | 3747 } // namespace v8 |
OLD | NEW |