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

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

Powered by Google App Engine
This is Rietveld 408576698