Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(481)

Side by Side Diff: src/deoptimizer.cc

Issue 1416543006: [turbofan] Unwind and jump to the catch handler in the deoptimizer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove the hack signpost Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698