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

Side by Side Diff: src/deoptimizer.cc

Issue 1136223004: Unify reading of deoptimization information. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years, 6 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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/codegen.h" 8 #include "src/codegen.h"
9 #include "src/cpu-profiler.h" 9 #include "src/cpu-profiler.h"
10 #include "src/deoptimizer.h" 10 #include "src/deoptimizer.h"
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 frame_index >= construct_offset && 187 frame_index >= construct_offset &&
188 deoptimizer->output_[frame_index - construct_offset]->GetFrameType() == 188 deoptimizer->output_[frame_index - construct_offset]->GetFrameType() ==
189 StackFrame::CONSTRUCT; 189 StackFrame::CONSTRUCT;
190 190
191 DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer, 191 DeoptimizedFrameInfo* info = new DeoptimizedFrameInfo(deoptimizer,
192 frame_index, 192 frame_index,
193 has_arguments_adaptor, 193 has_arguments_adaptor,
194 has_construct_stub); 194 has_construct_stub);
195 isolate->deoptimizer_data()->deoptimized_frame_info_ = info; 195 isolate->deoptimizer_data()->deoptimized_frame_info_ = info;
196 196
197 // Get the "simulated" top and size for the requested frame.
198 FrameDescription* parameters_frame =
199 deoptimizer->output_[
200 has_arguments_adaptor ? (frame_index - 1) : frame_index];
201
202 uint32_t parameters_size = (info->parameters_count() + 1) * kPointerSize;
203 Address parameters_top = reinterpret_cast<Address>(
204 parameters_frame->GetTop() + (parameters_frame->GetFrameSize() -
205 parameters_size));
206
207 uint32_t expressions_size = info->expression_count() * kPointerSize;
208 Address expressions_top = reinterpret_cast<Address>(
209 deoptimizer->output_[frame_index]->GetTop());
210
211 // Done with the GC-unsafe frame descriptions. This re-enables allocation. 197 // Done with the GC-unsafe frame descriptions. This re-enables allocation.
212 deoptimizer->DeleteFrameDescriptions(); 198 deoptimizer->DeleteFrameDescriptions();
213 199
214 // Allocate a heap number for the doubles belonging to this frame. 200 // Allocate a heap number for the doubles belonging to this frame.
215 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( 201 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
216 parameters_top, parameters_size, expressions_top, expressions_size, info); 202 frame_index, info->parameters_count(), info->expression_count(), info);
217 203
218 // Finished using the deoptimizer instance. 204 // Finished using the deoptimizer instance.
219 delete deoptimizer; 205 delete deoptimizer;
220 206
221 return info; 207 return info;
222 } 208 }
223 209
224 210
225 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, 211 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
226 Isolate* isolate) { 212 Isolate* isolate) {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 case EAGER: return "eager"; 525 case EAGER: return "eager";
540 case SOFT: return "soft"; 526 case SOFT: return "soft";
541 case LAZY: return "lazy"; 527 case LAZY: return "lazy";
542 case DEBUGGER: return "debugger"; 528 case DEBUGGER: return "debugger";
543 } 529 }
544 FATAL("Unsupported deopt type"); 530 FATAL("Unsupported deopt type");
545 return NULL; 531 return NULL;
546 } 532 }
547 533
548 534
549 Deoptimizer::Deoptimizer(Isolate* isolate, 535 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
550 JSFunction* function, 536 BailoutType type, unsigned bailout_id, Address from,
551 BailoutType type, 537 int fp_to_sp_delta, Code* optimized_code)
552 unsigned bailout_id,
553 Address from,
554 int fp_to_sp_delta,
555 Code* optimized_code)
556 : isolate_(isolate), 538 : isolate_(isolate),
557 function_(function), 539 function_(function),
558 bailout_id_(bailout_id), 540 bailout_id_(bailout_id),
559 bailout_type_(type), 541 bailout_type_(type),
560 from_(from), 542 from_(from),
561 fp_to_sp_delta_(fp_to_sp_delta), 543 fp_to_sp_delta_(fp_to_sp_delta),
562 has_alignment_padding_(0), 544 has_alignment_padding_(0),
563 input_(NULL), 545 input_(nullptr),
564 output_count_(0), 546 output_count_(0),
565 jsframe_count_(0), 547 jsframe_count_(0),
566 output_(NULL), 548 output_(nullptr),
567 deferred_objects_tagged_values_(0),
568 deferred_objects_double_values_(0),
569 deferred_objects_(0),
570 deferred_heap_numbers_(0),
571 jsframe_functions_(0), 549 jsframe_functions_(0),
572 jsframe_has_adapted_arguments_(0), 550 jsframe_has_adapted_arguments_(0),
573 materialized_values_(NULL), 551 trace_scope_(nullptr) {
574 materialized_objects_(NULL),
575 materialization_value_index_(0),
576 materialization_object_index_(0),
577 trace_scope_(NULL) {
578 // For COMPILED_STUBs called from builtins, the function pointer is a SMI 552 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
579 // indicating an internal frame. 553 // indicating an internal frame.
580 if (function->IsSmi()) { 554 if (function->IsSmi()) {
581 function = NULL; 555 function = nullptr;
582 } 556 }
583 DCHECK(from != NULL); 557 DCHECK(from != nullptr);
584 if (function != NULL && function->IsOptimized()) { 558 if (function != nullptr && function->IsOptimized()) {
585 function->shared()->increment_deopt_count(); 559 function->shared()->increment_deopt_count();
586 if (bailout_type_ == Deoptimizer::SOFT) { 560 if (bailout_type_ == Deoptimizer::SOFT) {
587 isolate->counters()->soft_deopts_executed()->Increment(); 561 isolate->counters()->soft_deopts_executed()->Increment();
588 // Soft deopts shouldn't count against the overall re-optimization count 562 // Soft deopts shouldn't count against the overall re-optimization count
589 // that can eventually lead to disabling optimization for a function. 563 // that can eventually lead to disabling optimization for a function.
590 int opt_count = function->shared()->opt_count(); 564 int opt_count = function->shared()->opt_count();
591 if (opt_count > 0) opt_count--; 565 if (opt_count > 0) opt_count--;
592 function->shared()->set_opt_count(opt_count); 566 function->shared()->set_opt_count(opt_count);
593 } 567 }
594 } 568 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 (compiled_code_->is_hydrogen_stub())) { 747 (compiled_code_->is_hydrogen_stub())) {
774 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_); 748 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
775 } 749 }
776 } 750 }
777 751
778 BailoutId node_id = input_data->AstId(bailout_id_); 752 BailoutId node_id = input_data->AstId(bailout_id_);
779 ByteArray* translations = input_data->TranslationByteArray(); 753 ByteArray* translations = input_data->TranslationByteArray();
780 unsigned translation_index = 754 unsigned translation_index =
781 input_data->TranslationIndex(bailout_id_)->value(); 755 input_data->TranslationIndex(bailout_id_)->value();
782 756
757 TranslationIterator state_iterator(translations, translation_index);
758 translated_state_.Init(
759 input_->GetFramePointerAddress(), function_, &state_iterator,
760 input_data->LiteralArray(), input_->GetRegisterValues(),
761 trace_scope_ == nullptr ? nullptr : trace_scope_->file());
762
783 // Do the input frame to output frame(s) translation. 763 // Do the input frame to output frame(s) translation.
784 TranslationIterator iterator(translations, translation_index); 764 size_t count = translated_state_.frames().size();
785 Translation::Opcode opcode =
786 static_cast<Translation::Opcode>(iterator.Next());
787 DCHECK(Translation::BEGIN == opcode);
788 USE(opcode);
789 // Read the number of output frames and allocate an array for their
790 // descriptions.
791 int count = iterator.Next();
792 iterator.Next(); // Drop JS frames count.
793 DCHECK(output_ == NULL); 765 DCHECK(output_ == NULL);
794 output_ = new FrameDescription*[count]; 766 output_ = new FrameDescription*[count];
795 for (int i = 0; i < count; ++i) { 767 for (size_t i = 0; i < count; ++i) {
796 output_[i] = NULL; 768 output_[i] = NULL;
797 } 769 }
798 output_count_ = count; 770 output_count_ = static_cast<int>(count);
799 771
800 Register fp_reg = JavaScriptFrame::fp_register(); 772 Register fp_reg = JavaScriptFrame::fp_register();
801 stack_fp_ = reinterpret_cast<Address>( 773 stack_fp_ = reinterpret_cast<Address>(
802 input_->GetRegister(fp_reg.code()) + 774 input_->GetRegister(fp_reg.code()) +
803 has_alignment_padding_ * kPointerSize); 775 has_alignment_padding_ * kPointerSize);
804 776
805 // Translate each output frame. 777 // Translate each output frame.
806 for (int i = 0; i < count; ++i) { 778 for (size_t i = 0; i < count; ++i) {
807 // Read the ast node id, function, and frame height for this output frame. 779 // Read the ast node id, function, and frame height for this output frame.
808 Translation::Opcode opcode = 780 int frame_index = static_cast<int>(i);
Benedikt Meurer 2015/06/03 04:02:17 Remove this static_cast and change the functions b
Jarin 2015/06/03 09:28:07 Yeah, I tried that, but in those functions we comp
809 static_cast<Translation::Opcode>(iterator.Next()); 781 switch (translated_state_.frames()[i].kind()) {
810 switch (opcode) { 782 case TranslatedFrame::Function:
811 case Translation::JS_FRAME: 783 DoComputeJSFrame(nullptr, frame_index);
812 DoComputeJSFrame(&iterator, i);
813 jsframe_count_++; 784 jsframe_count_++;
814 break; 785 break;
815 case Translation::ARGUMENTS_ADAPTOR_FRAME: 786 case TranslatedFrame::ArgumentsAdaptor:
816 DoComputeArgumentsAdaptorFrame(&iterator, i); 787 DoComputeArgumentsAdaptorFrame(nullptr, frame_index);
817 break; 788 break;
818 case Translation::CONSTRUCT_STUB_FRAME: 789 case TranslatedFrame::ConstructStub:
819 DoComputeConstructStubFrame(&iterator, i); 790 DoComputeConstructStubFrame(nullptr, frame_index);
820 break; 791 break;
821 case Translation::GETTER_STUB_FRAME: 792 case TranslatedFrame::Getter:
822 DoComputeAccessorStubFrame(&iterator, i, false); 793 DoComputeAccessorStubFrame(nullptr, frame_index, false);
823 break; 794 break;
824 case Translation::SETTER_STUB_FRAME: 795 case TranslatedFrame::Setter:
825 DoComputeAccessorStubFrame(&iterator, i, true); 796 DoComputeAccessorStubFrame(nullptr, frame_index, true);
826 break; 797 break;
827 case Translation::COMPILED_STUB_FRAME: 798 case TranslatedFrame::CompiledStub:
828 DoComputeCompiledStubFrame(&iterator, i); 799 DoComputeCompiledStubFrame(nullptr, frame_index);
829 break; 800 break;
830 case Translation::BEGIN: 801 case TranslatedFrame::Invalid:
831 case Translation::REGISTER: 802 FATAL("invalid frame");
832 case Translation::INT32_REGISTER:
833 case Translation::UINT32_REGISTER:
834 case Translation::BOOL_REGISTER:
835 case Translation::DOUBLE_REGISTER:
836 case Translation::STACK_SLOT:
837 case Translation::INT32_STACK_SLOT:
838 case Translation::UINT32_STACK_SLOT:
839 case Translation::BOOL_STACK_SLOT:
840 case Translation::DOUBLE_STACK_SLOT:
841 case Translation::LITERAL:
842 case Translation::ARGUMENTS_OBJECT:
843 case Translation::DUPLICATED_OBJECT:
844 case Translation::CAPTURED_OBJECT:
845 FATAL("Unsupported translation");
846 break; 803 break;
847 } 804 }
848 } 805 }
849 806
850 // Print some helpful diagnostic information. 807 // Print some helpful diagnostic information.
851 if (trace_scope_ != NULL) { 808 if (trace_scope_ != NULL) {
852 double ms = timer.Elapsed().InMillisecondsF(); 809 double ms = timer.Elapsed().InMillisecondsF();
853 int index = output_count_ - 1; // Index of the topmost frame. 810 int index = output_count_ - 1; // Index of the topmost frame.
854 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", 811 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
855 MessageFor(bailout_type_)); 812 MessageFor(bailout_type_));
856 PrintFunctionName(); 813 PrintFunctionName();
857 PrintF(trace_scope_->file(), 814 PrintF(trace_scope_->file(),
858 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," 815 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
859 " took %0.3f ms]\n", 816 " took %0.3f ms]\n",
860 bailout_id_, 817 bailout_id_,
861 node_id.ToInt(), 818 node_id.ToInt(),
862 output_[index]->GetPc(), 819 output_[index]->GetPc(),
863 FullCodeGenerator::State2String( 820 FullCodeGenerator::State2String(
864 static_cast<FullCodeGenerator::State>( 821 static_cast<FullCodeGenerator::State>(
865 output_[index]->GetState()->value())), 822 output_[index]->GetState()->value())),
866 has_alignment_padding_ ? "with padding" : "no padding", 823 has_alignment_padding_ ? "with padding" : "no padding",
867 ms); 824 ms);
868 } 825 }
869 } 826 }
870 827
871 828
872 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, 829 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
873 int frame_index) { 830 int frame_index) {
874 BailoutId node_id = BailoutId(iterator->Next()); 831 TranslatedFrame* translated_frame =
875 JSFunction* function; 832 &(translated_state_.frames()[frame_index]);
876 if (frame_index != 0) { 833 TranslatedFrame::ValueIterator value_iterator = translated_frame->begin();
877 function = JSFunction::cast(ComputeLiteral(iterator->Next())); 834 int input_index = 0;
878 } else { 835
879 int closure_id = iterator->Next(); 836 BailoutId node_id = translated_frame->node_id();
880 USE(closure_id); 837 JSFunction* function = translated_frame->raw_function();
881 CHECK_EQ(Translation::kSelfLiteralId, closure_id); 838 unsigned height =
882 function = function_; 839 translated_frame->height() - 1; // Do not count the context.
883 }
884 unsigned height = iterator->Next() - 1; // Do not count the context.
885 unsigned height_in_bytes = height * kPointerSize; 840 unsigned height_in_bytes = height * kPointerSize;
886 if (trace_scope_ != NULL) { 841 if (trace_scope_ != NULL) {
887 PrintF(trace_scope_->file(), " translating "); 842 PrintF(trace_scope_->file(), " translating frame ");
888 function->PrintName(trace_scope_->file()); 843 function->PrintName(trace_scope_->file());
889 PrintF(trace_scope_->file(), 844 PrintF(trace_scope_->file(),
890 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); 845 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
891 } 846 }
892 847
848 CHECK(translated_frame->kind() == TranslatedFrame::Function);
849 CHECK(function == translated_frame->raw_function());
850
893 // The 'fixed' part of the frame consists of the incoming parameters and 851 // The 'fixed' part of the frame consists of the incoming parameters and
894 // the part described by JavaScriptFrameConstants. 852 // the part described by JavaScriptFrameConstants.
895 unsigned fixed_frame_size = ComputeFixedSize(function); 853 unsigned fixed_frame_size = ComputeFixedSize(function);
896 unsigned input_frame_size = input_->GetFrameSize(); 854 unsigned input_frame_size = input_->GetFrameSize();
897 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 855 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
898 856
899 // Allocate and store the output frame description. 857 // Allocate and store the output frame description.
900 FrameDescription* output_frame = 858 FrameDescription* output_frame =
901 new(output_frame_size) FrameDescription(output_frame_size, function); 859 new(output_frame_size) FrameDescription(output_frame_size, function);
902 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); 860 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
(...skipping 28 matching lines...) Expand all
931 } 889 }
932 output_frame->SetTop(top_address); 890 output_frame->SetTop(top_address);
933 891
934 // Compute the incoming parameter translation. 892 // Compute the incoming parameter translation.
935 int parameter_count = 893 int parameter_count =
936 function->shared()->internal_formal_parameter_count() + 1; 894 function->shared()->internal_formal_parameter_count() + 1;
937 unsigned output_offset = output_frame_size; 895 unsigned output_offset = output_frame_size;
938 unsigned input_offset = input_frame_size; 896 unsigned input_offset = input_frame_size;
939 for (int i = 0; i < parameter_count; ++i) { 897 for (int i = 0; i < parameter_count; ++i) {
940 output_offset -= kPointerSize; 898 output_offset -= kPointerSize;
941 DoTranslateCommand(iterator, frame_index, output_offset); 899 WriteValueToOutput(&value_iterator, &input_index, frame_index,
900 output_offset);
942 } 901 }
943 input_offset -= (parameter_count * kPointerSize); 902 input_offset -= (parameter_count * kPointerSize);
944 903
945 // There are no translation commands for the caller's pc and fp, the 904 // There are no translation commands for the caller's pc and fp, the
946 // context, and the function. Synthesize their values and set them up 905 // context, and the function. Synthesize their values and set them up
947 // explicitly. 906 // explicitly.
948 // 907 //
949 // The caller's pc for the bottommost output frame is the same as in the 908 // The caller's pc for the bottommost output frame is the same as in the
950 // input frame. For all subsequent output frames, it can be read from the 909 // input frame. For all subsequent output frames, it can be read from the
951 // previous one. This frame's pc can be computed from the non-optimized 910 // previous one. This frame's pc can be computed from the non-optimized
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 } 970 }
1012 } 971 }
1013 972
1014 // For the bottommost output frame the context can be gotten from the input 973 // For the bottommost output frame the context can be gotten from the input
1015 // frame. For all subsequent output frames it can be gotten from the function 974 // frame. For all subsequent output frames it can be gotten from the function
1016 // so long as we don't inline functions that need local contexts. 975 // so long as we don't inline functions that need local contexts.
1017 Register context_reg = JavaScriptFrame::context_register(); 976 Register context_reg = JavaScriptFrame::context_register();
1018 output_offset -= kPointerSize; 977 output_offset -= kPointerSize;
1019 input_offset -= kPointerSize; 978 input_offset -= kPointerSize;
1020 // Read the context from the translations. 979 // Read the context from the translations.
1021 DoTranslateCommand(iterator, frame_index, output_offset); 980 WriteValueToOutput(&value_iterator, &input_index, frame_index, output_offset);
1022 value = output_frame->GetFrameSlot(output_offset); 981 value = output_frame->GetFrameSlot(output_offset);
1023 // The context should not be a placeholder for a materialized object. 982 // The context should not be a placeholder for a materialized object.
1024 CHECK(value != 983 CHECK(value !=
1025 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker())); 984 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker()));
1026 if (value == 985 if (value ==
1027 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) { 986 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) {
1028 // If the context was optimized away, just use the context from 987 // If the context was optimized away, just use the context from
1029 // the activation. This should only apply to Crankshaft code. 988 // the activation. This should only apply to Crankshaft code.
1030 CHECK(!compiled_code_->is_turbofanned()); 989 CHECK(!compiled_code_->is_turbofanned());
1031 if (is_bottommost) { 990 if (is_bottommost) {
(...skipping 23 matching lines...) Expand all
1055 if (trace_scope_ != NULL) { 1014 if (trace_scope_ != NULL) {
1056 PrintF(trace_scope_->file(), 1015 PrintF(trace_scope_->file(),
1057 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1016 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1058 V8PRIxPTR "; function\n", 1017 V8PRIxPTR "; function\n",
1059 top_address + output_offset, output_offset, value); 1018 top_address + output_offset, output_offset, value);
1060 } 1019 }
1061 1020
1062 // Translate the rest of the frame. 1021 // Translate the rest of the frame.
1063 for (unsigned i = 0; i < height; ++i) { 1022 for (unsigned i = 0; i < height; ++i) {
1064 output_offset -= kPointerSize; 1023 output_offset -= kPointerSize;
1065 DoTranslateCommand(iterator, frame_index, output_offset); 1024 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1025 output_offset);
1066 } 1026 }
1067 CHECK_EQ(0u, output_offset); 1027 CHECK_EQ(0u, output_offset);
1068 1028
1069 // Compute this frame's PC, state, and continuation. 1029 // Compute this frame's PC, state, and continuation.
1070 Code* non_optimized_code = function->shared()->code(); 1030 Code* non_optimized_code = function->shared()->code();
1071 FixedArray* raw_data = non_optimized_code->deoptimization_data(); 1031 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1072 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 1032 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1073 Address start = non_optimized_code->instruction_start(); 1033 Address start = non_optimized_code->instruction_start();
1074 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 1034 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1075 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 1035 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
(...skipping 28 matching lines...) Expand all
1104 CHECK_EQ(bailout_type_, EAGER); 1064 CHECK_EQ(bailout_type_, EAGER);
1105 } 1065 }
1106 output_frame->SetContinuation( 1066 output_frame->SetContinuation(
1107 reinterpret_cast<intptr_t>(continuation->entry())); 1067 reinterpret_cast<intptr_t>(continuation->entry()));
1108 } 1068 }
1109 } 1069 }
1110 1070
1111 1071
1112 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 1072 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
1113 int frame_index) { 1073 int frame_index) {
1114 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 1074 TranslatedFrame* translated_frame =
1115 unsigned height = iterator->Next(); 1075 &(translated_state_.frames()[frame_index]);
1076 TranslatedFrame::ValueIterator value_iterator = translated_frame->begin();
1077 int input_index = 0;
1078
1079 JSFunction* function = translated_frame->raw_function();
1080 unsigned height = translated_frame->height();
1116 unsigned height_in_bytes = height * kPointerSize; 1081 unsigned height_in_bytes = height * kPointerSize;
1117 if (trace_scope_ != NULL) { 1082 if (trace_scope_ != NULL) {
1118 PrintF(trace_scope_->file(), 1083 PrintF(trace_scope_->file(),
1119 " translating arguments adaptor => height=%d\n", height_in_bytes); 1084 " translating arguments adaptor => height=%d\n", height_in_bytes);
1120 } 1085 }
1121 1086
1122 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; 1087 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
1123 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1088 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1124 1089
1125 // Allocate and store the output frame description. 1090 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1136 // frame's top and this frame's size. 1101 // frame's top and this frame's size.
1137 intptr_t top_address; 1102 intptr_t top_address;
1138 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1103 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1139 output_frame->SetTop(top_address); 1104 output_frame->SetTop(top_address);
1140 1105
1141 // Compute the incoming parameter translation. 1106 // Compute the incoming parameter translation.
1142 int parameter_count = height; 1107 int parameter_count = height;
1143 unsigned output_offset = output_frame_size; 1108 unsigned output_offset = output_frame_size;
1144 for (int i = 0; i < parameter_count; ++i) { 1109 for (int i = 0; i < parameter_count; ++i) {
1145 output_offset -= kPointerSize; 1110 output_offset -= kPointerSize;
1146 DoTranslateCommand(iterator, frame_index, output_offset); 1111 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1112 output_offset);
1147 } 1113 }
1148 1114
1149 // Read caller's PC from the previous frame. 1115 // Read caller's PC from the previous frame.
1150 output_offset -= kPCOnStackSize; 1116 output_offset -= kPCOnStackSize;
1151 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1117 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1152 output_frame->SetCallerPc(output_offset, callers_pc); 1118 output_frame->SetCallerPc(output_offset, callers_pc);
1153 if (trace_scope_ != NULL) { 1119 if (trace_scope_ != NULL) {
1154 PrintF(trace_scope_->file(), 1120 PrintF(trace_scope_->file(),
1155 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1121 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1156 V8PRIxPTR " ; caller's pc\n", 1122 V8PRIxPTR " ; caller's pc\n",
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 if (FLAG_enable_ool_constant_pool) { 1194 if (FLAG_enable_ool_constant_pool) {
1229 intptr_t constant_pool_value = 1195 intptr_t constant_pool_value =
1230 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool()); 1196 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1231 output_frame->SetConstantPool(constant_pool_value); 1197 output_frame->SetConstantPool(constant_pool_value);
1232 } 1198 }
1233 } 1199 }
1234 1200
1235 1201
1236 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, 1202 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
1237 int frame_index) { 1203 int frame_index) {
1204 TranslatedFrame* translated_frame =
1205 &(translated_state_.frames()[frame_index]);
1206 TranslatedFrame::ValueIterator value_iterator = translated_frame->begin();
1207 int input_index = 0;
1208
1238 Builtins* builtins = isolate_->builtins(); 1209 Builtins* builtins = isolate_->builtins();
1239 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); 1210 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
1240 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 1211 JSFunction* function = translated_frame->raw_function();
1241 unsigned height = iterator->Next(); 1212 unsigned height = translated_frame->height();
1242 unsigned height_in_bytes = height * kPointerSize; 1213 unsigned height_in_bytes = height * kPointerSize;
1243 if (trace_scope_ != NULL) { 1214 if (trace_scope_ != NULL) {
1244 PrintF(trace_scope_->file(), 1215 PrintF(trace_scope_->file(),
1245 " translating construct stub => height=%d\n", height_in_bytes); 1216 " translating construct stub => height=%d\n", height_in_bytes);
1246 } 1217 }
1247 1218
1248 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize; 1219 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
1249 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1220 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1250 1221
1251 // Allocate and store the output frame description. 1222 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1262 // frame's top and this frame's size. 1233 // frame's top and this frame's size.
1263 intptr_t top_address; 1234 intptr_t top_address;
1264 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1235 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1265 output_frame->SetTop(top_address); 1236 output_frame->SetTop(top_address);
1266 1237
1267 // Compute the incoming parameter translation. 1238 // Compute the incoming parameter translation.
1268 int parameter_count = height; 1239 int parameter_count = height;
1269 unsigned output_offset = output_frame_size; 1240 unsigned output_offset = output_frame_size;
1270 for (int i = 0; i < parameter_count; ++i) { 1241 for (int i = 0; i < parameter_count; ++i) {
1271 output_offset -= kPointerSize; 1242 output_offset -= kPointerSize;
1272 int deferred_object_index = deferred_objects_.length();
1273 DoTranslateCommand(iterator, frame_index, output_offset);
1274 // The allocated receiver of a construct stub frame is passed as the 1243 // The allocated receiver of a construct stub frame is passed as the
1275 // receiver parameter through the translation. It might be encoding 1244 // receiver parameter through the translation. It might be encoding
1276 // a captured object, patch the slot address for a captured object. 1245 // a captured object, override the slot address for a captured object.
1277 if (i == 0 && deferred_objects_.length() > deferred_object_index) { 1246 WriteValueToOutput(
1278 CHECK(!deferred_objects_[deferred_object_index].is_arguments()); 1247 &value_iterator, &input_index, frame_index, output_offset,
1279 deferred_objects_[deferred_object_index].patch_slot_address(top_address); 1248 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
1280 }
1281 } 1249 }
1282 1250
1283 // Read caller's PC from the previous frame. 1251 // Read caller's PC from the previous frame.
1284 output_offset -= kPCOnStackSize; 1252 output_offset -= kPCOnStackSize;
1285 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1253 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1286 output_frame->SetCallerPc(output_offset, callers_pc); 1254 output_frame->SetCallerPc(output_offset, callers_pc);
1287 if (trace_scope_ != NULL) { 1255 if (trace_scope_ != NULL) {
1288 PrintF(trace_scope_->file(), 1256 PrintF(trace_scope_->file(),
1289 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1257 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1290 V8PRIxPTR " ; caller's pc\n", 1258 V8PRIxPTR " ; caller's pc\n",
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 intptr_t constant_pool_value = 1364 intptr_t constant_pool_value =
1397 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); 1365 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1398 output_frame->SetConstantPool(constant_pool_value); 1366 output_frame->SetConstantPool(constant_pool_value);
1399 } 1367 }
1400 } 1368 }
1401 1369
1402 1370
1403 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, 1371 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
1404 int frame_index, 1372 int frame_index,
1405 bool is_setter_stub_frame) { 1373 bool is_setter_stub_frame) {
1406 JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next())); 1374 TranslatedFrame* translated_frame =
1375 &(translated_state_.frames()[frame_index]);
1376 TranslatedFrame::ValueIterator value_iterator = translated_frame->begin();
1377 int input_index = 0;
1378
1379 JSFunction* accessor = translated_frame->raw_function();
1407 // The receiver (and the implicit return value, if any) are expected in 1380 // The receiver (and the implicit return value, if any) are expected in
1408 // registers by the LoadIC/StoreIC, so they don't belong to the output stack 1381 // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1409 // frame. This means that we have to use a height of 0. 1382 // frame. This means that we have to use a height of 0.
1410 unsigned height = 0; 1383 unsigned height = 0;
1411 unsigned height_in_bytes = height * kPointerSize; 1384 unsigned height_in_bytes = height * kPointerSize;
1412 const char* kind = is_setter_stub_frame ? "setter" : "getter"; 1385 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1413 if (trace_scope_ != NULL) { 1386 if (trace_scope_ != NULL) {
1414 PrintF(trace_scope_->file(), 1387 PrintF(trace_scope_->file(),
1415 " translating %s stub => height=%u\n", kind, height_in_bytes); 1388 " translating %s stub => height=%u\n", kind, height_in_bytes);
1416 } 1389 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 value = reinterpret_cast<intptr_t>(accessor_stub); 1483 value = reinterpret_cast<intptr_t>(accessor_stub);
1511 output_frame->SetFrameSlot(output_offset, value); 1484 output_frame->SetFrameSlot(output_offset, value);
1512 if (trace_scope_ != NULL) { 1485 if (trace_scope_ != NULL) {
1513 PrintF(trace_scope_->file(), 1486 PrintF(trace_scope_->file(),
1514 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR 1487 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1515 " ; code object\n", 1488 " ; code object\n",
1516 top_address + output_offset, output_offset, value); 1489 top_address + output_offset, output_offset, value);
1517 } 1490 }
1518 1491
1519 // Skip receiver. 1492 // Skip receiver.
1520 DoTranslateObjectAndSkip(iterator); 1493 value_iterator++;
1521 1494
1522 if (is_setter_stub_frame) { 1495 if (is_setter_stub_frame) {
1523 // The implicit return value was part of the artificial setter stub 1496 // The implicit return value was part of the artificial setter stub
1524 // environment. 1497 // environment.
1525 output_offset -= kPointerSize; 1498 output_offset -= kPointerSize;
1526 DoTranslateCommand(iterator, frame_index, output_offset); 1499 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1500 output_offset);
1527 } 1501 }
1528 1502
1529 CHECK_EQ(0u, output_offset); 1503 CHECK_EQ(0u, output_offset);
1530 1504
1531 Smi* offset = is_setter_stub_frame ? 1505 Smi* offset = is_setter_stub_frame ?
1532 isolate_->heap()->setter_stub_deopt_pc_offset() : 1506 isolate_->heap()->setter_stub_deopt_pc_offset() :
1533 isolate_->heap()->getter_stub_deopt_pc_offset(); 1507 isolate_->heap()->getter_stub_deopt_pc_offset();
1534 intptr_t pc = reinterpret_cast<intptr_t>( 1508 intptr_t pc = reinterpret_cast<intptr_t>(
1535 accessor_stub->instruction_start() + offset->value()); 1509 accessor_stub->instruction_start() + offset->value());
1536 output_frame->SetPc(pc); 1510 output_frame->SetPc(pc);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 // and spilled to stack | .... | 1543 // and spilled to stack | .... |
1570 // +-------------------------+ 1544 // +-------------------------+
1571 // | caller stack param n | 1545 // | caller stack param n |
1572 // +-------------------------+<-spreg 1546 // +-------------------------+<-spreg
1573 // reg = number of parameters 1547 // reg = number of parameters
1574 // reg = failure handler address 1548 // reg = failure handler address
1575 // reg = saved frame 1549 // reg = saved frame
1576 // reg = JSFunction context 1550 // reg = JSFunction context
1577 // 1551 //
1578 1552
1553 TranslatedFrame* translated_frame =
1554 &(translated_state_.frames()[frame_index]);
1555 TranslatedFrame::ValueIterator value_iterator = translated_frame->begin();
1556 int input_index = 0;
1557
1579 CHECK(compiled_code_->is_hydrogen_stub()); 1558 CHECK(compiled_code_->is_hydrogen_stub());
1580 int major_key = CodeStub::GetMajorKey(compiled_code_); 1559 int major_key = CodeStub::GetMajorKey(compiled_code_);
1581 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key()); 1560 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1582 1561
1583 // The output frame must have room for all pushed register parameters 1562 // The output frame must have room for all pushed register parameters
1584 // and the standard stack frame slots. Include space for an argument 1563 // and the standard stack frame slots. Include space for an argument
1585 // object to the callee and optionally the space to pass the argument 1564 // object to the callee and optionally the space to pass the argument
1586 // object to the stub failure handler. 1565 // object to the stub failure handler.
1587 int param_count = descriptor.GetEnvironmentParameterCount(); 1566 int param_count = descriptor.GetEnvironmentParameterCount();
1567 CHECK_EQ(translated_frame->height(), param_count);
1588 CHECK_GE(param_count, 0); 1568 CHECK_GE(param_count, 0);
1589 1569
1590 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) + 1570 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) +
1591 kPointerSize; 1571 kPointerSize;
1592 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; 1572 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
1593 int input_frame_size = input_->GetFrameSize(); 1573 int input_frame_size = input_->GetFrameSize();
1594 int output_frame_size = height_in_bytes + fixed_frame_size; 1574 int output_frame_size = height_in_bytes + fixed_frame_size;
1595 if (trace_scope_ != NULL) { 1575 if (trace_scope_ != NULL) {
1596 PrintF(trace_scope_->file(), 1576 PrintF(trace_scope_->file(),
1597 " translating %s => StubFailureTrampolineStub, height=%d\n", 1577 " translating %s => StubFailureTrampolineStub, height=%d\n",
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1725 PrintF(trace_scope_->file(), 1705 PrintF(trace_scope_->file(),
1726 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1706 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1727 V8PRIxPTR " ; args*\n", 1707 V8PRIxPTR " ; args*\n",
1728 top_address + output_frame_offset, output_frame_offset, value); 1708 top_address + output_frame_offset, output_frame_offset, value);
1729 } 1709 }
1730 1710
1731 // Copy the register parameters to the failure frame. 1711 // Copy the register parameters to the failure frame.
1732 int arguments_length_offset = -1; 1712 int arguments_length_offset = -1;
1733 for (int i = 0; i < param_count; ++i) { 1713 for (int i = 0; i < param_count; ++i) {
1734 output_frame_offset -= kPointerSize; 1714 output_frame_offset -= kPointerSize;
1735 DoTranslateCommand(iterator, 0, output_frame_offset); 1715 WriteValueToOutput(&value_iterator, &input_index, 0, output_frame_offset);
1736 1716
1737 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) { 1717 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) {
1738 arguments_length_offset = output_frame_offset; 1718 arguments_length_offset = output_frame_offset;
1739 } 1719 }
1740 } 1720 }
1741 1721
1742 CHECK_EQ(0u, output_frame_offset); 1722 CHECK_EQ(0u, output_frame_offset);
1743 1723
1744 if (!arg_count_known) { 1724 if (!arg_count_known) {
1745 CHECK_GE(arguments_length_offset, 0); 1725 CHECK_GE(arguments_length_offset, 0);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); 1772 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1793 } 1773 }
1794 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); 1774 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
1795 Code* notify_failure = 1775 Code* notify_failure =
1796 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); 1776 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
1797 output_frame->SetContinuation( 1777 output_frame->SetContinuation(
1798 reinterpret_cast<intptr_t>(notify_failure->entry())); 1778 reinterpret_cast<intptr_t>(notify_failure->entry()));
1799 } 1779 }
1800 1780
1801 1781
1802 Handle<Object> Deoptimizer::MaterializeNextHeapObject() {
1803 int object_index = materialization_object_index_++;
1804 ObjectMaterializationDescriptor desc = deferred_objects_[object_index];
1805 const int length = desc.object_length();
1806
1807 if (desc.duplicate_object() >= 0) {
1808 // Found a previously materialized object by de-duplication.
1809 object_index = desc.duplicate_object();
1810 materialized_objects_->Add(Handle<Object>());
1811 } else if (desc.is_arguments() && ArgumentsObjectIsAdapted(object_index)) {
1812 // Use the arguments adapter frame we just built to materialize the
1813 // arguments object. FunctionGetArguments can't throw an exception.
1814 Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
1815 Handle<JSObject> arguments = Handle<JSObject>::cast(
1816 Accessors::FunctionGetArguments(function));
1817 materialized_objects_->Add(arguments);
1818 // To keep consistent object counters, we still materialize the
1819 // nested values (but we throw them away).
1820 for (int i = 0; i < length; ++i) {
1821 MaterializeNextValue();
1822 }
1823 } else if (desc.is_arguments()) {
1824 // Construct an arguments object and copy the parameters to a newly
1825 // allocated arguments object backing store.
1826 Handle<JSFunction> function = ArgumentsObjectFunction(object_index);
1827 Handle<JSObject> arguments =
1828 isolate_->factory()->NewArgumentsObject(function, length);
1829 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
1830 DCHECK_EQ(array->length(), length);
1831 arguments->set_elements(*array);
1832 materialized_objects_->Add(arguments);
1833 for (int i = 0; i < length; ++i) {
1834 Handle<Object> value = MaterializeNextValue();
1835 array->set(i, *value);
1836 }
1837 } else {
1838 // Dispatch on the instance type of the object to be materialized.
1839 // We also need to make sure that the representation of all fields
1840 // in the given object are general enough to hold a tagged value.
1841 Handle<Map> map = Map::GeneralizeAllFieldRepresentations(
1842 Handle<Map>::cast(MaterializeNextValue()));
1843 switch (map->instance_type()) {
1844 case MUTABLE_HEAP_NUMBER_TYPE:
1845 case HEAP_NUMBER_TYPE: {
1846 // Reuse the HeapNumber value directly as it is already properly
1847 // tagged and skip materializing the HeapNumber explicitly. Turn mutable
1848 // heap numbers immutable.
1849 Handle<Object> object = MaterializeNextValue();
1850 if (object_index < prev_materialized_count_) {
1851 materialized_objects_->Add(Handle<Object>(
1852 previously_materialized_objects_->get(object_index), isolate_));
1853 } else {
1854 materialized_objects_->Add(object);
1855 }
1856 materialization_value_index_ += kDoubleSize / kPointerSize - 1;
1857 break;
1858 }
1859 case JS_OBJECT_TYPE: {
1860 Handle<JSObject> object =
1861 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
1862 if (object_index < prev_materialized_count_) {
1863 materialized_objects_->Add(Handle<Object>(
1864 previously_materialized_objects_->get(object_index), isolate_));
1865 } else {
1866 materialized_objects_->Add(object);
1867 }
1868 Handle<Object> properties = MaterializeNextValue();
1869 Handle<Object> elements = MaterializeNextValue();
1870 object->set_properties(FixedArray::cast(*properties));
1871 object->set_elements(FixedArrayBase::cast(*elements));
1872 for (int i = 0; i < length - 3; ++i) {
1873 Handle<Object> value = MaterializeNextValue();
1874 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
1875 object->FastPropertyAtPut(index, *value);
1876 }
1877 break;
1878 }
1879 case JS_ARRAY_TYPE: {
1880 Handle<JSArray> object =
1881 isolate_->factory()->NewJSArray(0, map->elements_kind());
1882 if (object_index < prev_materialized_count_) {
1883 materialized_objects_->Add(Handle<Object>(
1884 previously_materialized_objects_->get(object_index), isolate_));
1885 } else {
1886 materialized_objects_->Add(object);
1887 }
1888 Handle<Object> properties = MaterializeNextValue();
1889 Handle<Object> elements = MaterializeNextValue();
1890 Handle<Object> length = MaterializeNextValue();
1891 object->set_properties(FixedArray::cast(*properties));
1892 object->set_elements(FixedArrayBase::cast(*elements));
1893 object->set_length(*length);
1894 break;
1895 }
1896 default:
1897 PrintF(stderr,
1898 "[couldn't handle instance type %d]\n", map->instance_type());
1899 FATAL("Unsupported instance type");
1900 }
1901 }
1902
1903 return materialized_objects_->at(object_index);
1904 }
1905
1906
1907 Handle<Object> Deoptimizer::MaterializeNextValue() {
1908 int value_index = materialization_value_index_++;
1909 Handle<Object> value = materialized_values_->at(value_index);
1910 if (value->IsMutableHeapNumber()) {
1911 HeapNumber::cast(*value)->set_map(isolate_->heap()->heap_number_map());
1912 }
1913 if (*value == isolate_->heap()->arguments_marker()) {
1914 value = MaterializeNextHeapObject();
1915 }
1916 return value;
1917 }
1918
1919
1920 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { 1782 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
1921 DCHECK_NE(DEBUGGER, bailout_type_); 1783 DCHECK_NE(DEBUGGER, bailout_type_);
1922 1784
1923 MaterializedObjectStore* materialized_store = 1785 MaterializedObjectStore* materialized_store =
1924 isolate_->materialized_object_store(); 1786 isolate_->materialized_object_store();
1925 previously_materialized_objects_ = materialized_store->Get(stack_fp_); 1787 previously_materialized_objects_ = materialized_store->Get(stack_fp_);
1926 prev_materialized_count_ = previously_materialized_objects_.is_null() ? 1788 prev_materialized_count_ = previously_materialized_objects_.is_null() ?
1927 0 : previously_materialized_objects_->length(); 1789 0 : previously_materialized_objects_->length();
1928 1790
1929 // Walk all JavaScript output frames with the given frame iterator. 1791 // Walk all JavaScript output frames with the given frame iterator.
1930 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { 1792 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
1931 if (frame_index != 0) it->Advance(); 1793 if (frame_index != 0) it->Advance();
1932 JavaScriptFrame* frame = it->frame(); 1794 JavaScriptFrame* frame = it->frame();
1933 jsframe_functions_.Add(handle(frame->function(), isolate_)); 1795 jsframe_functions_.Add(handle(frame->function(), isolate_));
1934 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments()); 1796 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments());
1935 } 1797 }
1936 1798
1937 // Handlify all tagged object values before triggering any allocation. 1799 translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_);
1938 List<Handle<Object> > values(deferred_objects_tagged_values_.length()); 1800
1939 for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) { 1801 for (auto& materialization : values_to_materialize_) {
1940 values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_)); 1802 Handle<Object> value = materialization.value_->GetValue();
1803
1804 if (trace_scope_ != nullptr) {
1805 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ",
1806 reinterpret_cast<intptr_t>(materialization.output_slot_address_),
1807 reinterpret_cast<intptr_t>(*value));
1808 value->ShortPrint(trace_scope_->file());
1809 PrintF(trace_scope_->file(), "\n");
1810 }
1811
1812 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
1813 reinterpret_cast<intptr_t>(*value);
1941 } 1814 }
1942 1815
1943 // Play it safe and clear all unhandlified values before we continue. 1816 isolate_->materialized_object_store()->Remove(stack_fp_);
1944 deferred_objects_tagged_values_.Clear();
1945
1946 // Materialize all heap numbers before looking at arguments because when the
1947 // output frames are used to materialize arguments objects later on they need
1948 // to already contain valid heap numbers.
1949 for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
1950 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
1951 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1952 if (trace_scope_ != NULL) {
1953 PrintF(trace_scope_->file(),
1954 "Materialized a new heap number %p [%e] in slot %p\n",
1955 reinterpret_cast<void*>(*num),
1956 d.value(),
1957 d.destination());
1958 }
1959 Memory::Object_at(d.destination()) = *num;
1960 }
1961
1962 // Materialize all heap numbers required for arguments/captured objects.
1963 for (int i = 0; i < deferred_objects_double_values_.length(); i++) {
1964 HeapNumberMaterializationDescriptor<int> d =
1965 deferred_objects_double_values_[i];
1966 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1967 if (trace_scope_ != NULL) {
1968 PrintF(trace_scope_->file(),
1969 "Materialized a new heap number %p [%e] for object at %d\n",
1970 reinterpret_cast<void*>(*num),
1971 d.value(),
1972 d.destination());
1973 }
1974 DCHECK(values.at(d.destination())->IsTheHole());
1975 values.Set(d.destination(), num);
1976 }
1977
1978 // Play it safe and clear all object double values before we continue.
1979 deferred_objects_double_values_.Clear();
1980
1981 // Materialize arguments/captured objects.
1982 if (!deferred_objects_.is_empty()) {
1983 List<Handle<Object> > materialized_objects(deferred_objects_.length());
1984 materialized_objects_ = &materialized_objects;
1985 materialized_values_ = &values;
1986
1987 while (materialization_object_index_ < deferred_objects_.length()) {
1988 int object_index = materialization_object_index_;
1989 ObjectMaterializationDescriptor descriptor =
1990 deferred_objects_.at(object_index);
1991
1992 // Find a previously materialized object by de-duplication or
1993 // materialize a new instance of the object if necessary. Store
1994 // the materialized object into the frame slot.
1995 Handle<Object> object = MaterializeNextHeapObject();
1996 if (descriptor.slot_address() != NULL) {
1997 Memory::Object_at(descriptor.slot_address()) = *object;
1998 }
1999 if (trace_scope_ != NULL) {
2000 if (descriptor.is_arguments()) {
2001 PrintF(trace_scope_->file(),
2002 "Materialized %sarguments object of length %d for %p: ",
2003 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "",
2004 Handle<JSObject>::cast(object)->elements()->length(),
2005 reinterpret_cast<void*>(descriptor.slot_address()));
2006 } else {
2007 PrintF(trace_scope_->file(),
2008 "Materialized captured object of size %d for %p: ",
2009 Handle<HeapObject>::cast(object)->Size(),
2010 reinterpret_cast<void*>(descriptor.slot_address()));
2011 }
2012 object->ShortPrint(trace_scope_->file());
2013 PrintF(trace_scope_->file(), "\n");
2014 }
2015 }
2016
2017 CHECK_EQ(materialization_object_index_, materialized_objects_->length());
2018 CHECK_EQ(materialization_value_index_, materialized_values_->length());
2019 }
2020
2021 if (prev_materialized_count_ > 0) {
2022 bool removed = materialized_store->Remove(stack_fp_);
2023 CHECK(removed);
2024 }
2025 } 1817 }
2026 1818
2027 1819
2028 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( 1820 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
2029 Address parameters_top, 1821 int frame_index, int parameter_count, int expression_count,
2030 uint32_t parameters_size,
2031 Address expressions_top,
2032 uint32_t expressions_size,
2033 DeoptimizedFrameInfo* info) { 1822 DeoptimizedFrameInfo* info) {
2034 CHECK_EQ(DEBUGGER, bailout_type_); 1823 CHECK_EQ(DEBUGGER, bailout_type_);
2035 Address parameters_bottom = parameters_top + parameters_size;
2036 Address expressions_bottom = expressions_top + expressions_size;
2037 for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
2038 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
2039 1824
2040 // Check of the heap number to materialize actually belong to the frame 1825 translated_state_.Prepare(false, nullptr);
2041 // being extracted.
2042 Address slot = d.destination();
2043 if (parameters_top <= slot && slot < parameters_bottom) {
2044 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
2045 1826
2046 int index = (info->parameters_count() - 1) - 1827 TranslatedFrame* frame = &(translated_state_.frames()[frame_index]);
2047 static_cast<int>(slot - parameters_top) / kPointerSize; 1828 CHECK(frame->kind() == TranslatedFrame::Function);
1829 int frame_arg_count =
1830 frame->function()->shared()->internal_formal_parameter_count();
2048 1831
2049 if (trace_scope_ != NULL) { 1832 // The height is #expressions + 1 for context.
2050 PrintF(trace_scope_->file(), 1833 CHECK_EQ(expression_count + 1, frame->height());
2051 "Materializing a new heap number %p [%e] in slot %p" 1834 TranslatedFrame* argument_frame = frame;
2052 "for parameter slot #%d\n", 1835 if (frame_index > 0) {
2053 reinterpret_cast<void*>(*num), 1836 TranslatedFrame* previous_frame =
2054 d.value(), 1837 &(translated_state_.frames()[frame_index - 1]);
2055 d.destination(), 1838 if (previous_frame->kind() == TranslatedFrame::ArgumentsAdaptor) {
2056 index); 1839 argument_frame = previous_frame;
2057 } 1840 CHECK_EQ(parameter_count, argument_frame->height() - 1);
1841 } else {
1842 CHECK_EQ(frame_arg_count, parameter_count);
1843 }
1844 } else {
1845 CHECK_EQ(frame_arg_count, parameter_count);
1846 }
2058 1847
2059 info->SetParameter(index, *num); 1848 TranslatedFrame::ValueIterator arg_iter = argument_frame->begin();
2060 } else if (expressions_top <= slot && slot < expressions_bottom) { 1849 arg_iter++; // Skip the receiver.
2061 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); 1850 for (int i = 0; i < parameter_count; i++, arg_iter++) {
1851 if (!arg_iter->IsMaterializedObject()) {
1852 info->SetParameter(i, *(arg_iter->GetValue()));
1853 }
1854 }
2062 1855
2063 int index = info->expression_count() - 1 - 1856 TranslatedFrame::ValueIterator iter = frame->begin();
2064 static_cast<int>(slot - expressions_top) / kPointerSize; 1857 // Skip the arguments, receiver and context.
1858 for (int i = 0; i < frame_arg_count + 2; i++, iter++) {
1859 }
2065 1860
2066 if (trace_scope_ != NULL) { 1861 for (int i = 0; i < expression_count; i++, iter++) {
2067 PrintF(trace_scope_->file(), 1862 if (!iter->IsMaterializedObject()) {
2068 "Materializing a new heap number %p [%e] in slot %p" 1863 info->SetExpression(i, *(iter->GetValue()));
2069 "for expression slot #%d\n",
2070 reinterpret_cast<void*>(*num),
2071 d.value(),
2072 d.destination(),
2073 index);
2074 }
2075
2076 info->SetExpression(index, *num);
2077 } 1864 }
2078 } 1865 }
2079 } 1866 }
2080 1867
2081 1868
2082 static const char* TraceValueType(bool is_smi) { 1869 void Deoptimizer::WriteValueToOutput(
2083 if (is_smi) { 1870 TranslatedFrame::ValueIterator* iterator, int* input_index, int frame_index,
2084 return "smi"; 1871 unsigned output_offset, Address output_address_for_materialization) {
1872 Object* value = (*iterator)->GetRawValue();
1873 output_[frame_index]->SetFrameSlot(output_offset,
1874 reinterpret_cast<intptr_t>(value));
1875
1876 Address output_address =
1877 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + output_offset;
1878 if (trace_scope_ != nullptr) {
1879 PrintF(trace_scope_->file(),
1880 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; ",
1881 reinterpret_cast<intptr_t>(output_address), output_offset,
1882 reinterpret_cast<intptr_t>(value));
1883 value->ShortPrint(trace_scope_->file());
1884 PrintF(trace_scope_->file(), " (input #%d)\n", *input_index);
2085 } 1885 }
2086 1886
2087 return "heap number"; 1887 if (value == isolate_->heap()->arguments_marker()) {
2088 } 1888 if (output_address_for_materialization == nullptr) {
2089 1889 output_address_for_materialization = output_address;
2090
2091 void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) {
2092 Translation::Opcode opcode =
2093 static_cast<Translation::Opcode>(iterator->Next());
2094
2095 switch (opcode) {
2096 case Translation::BEGIN:
2097 case Translation::JS_FRAME:
2098 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2099 case Translation::CONSTRUCT_STUB_FRAME:
2100 case Translation::GETTER_STUB_FRAME:
2101 case Translation::SETTER_STUB_FRAME:
2102 case Translation::COMPILED_STUB_FRAME: {
2103 FATAL("Unexpected frame start translation opcode");
2104 return;
2105 } 1890 }
2106 1891 values_to_materialize_.push_back(
2107 case Translation::REGISTER: 1892 {output_address_for_materialization, *iterator});
2108 case Translation::INT32_REGISTER:
2109 case Translation::UINT32_REGISTER:
2110 case Translation::BOOL_REGISTER:
2111 case Translation::DOUBLE_REGISTER:
2112 case Translation::STACK_SLOT:
2113 case Translation::INT32_STACK_SLOT:
2114 case Translation::UINT32_STACK_SLOT:
2115 case Translation::BOOL_STACK_SLOT:
2116 case Translation::DOUBLE_STACK_SLOT:
2117 case Translation::LITERAL: {
2118 // The value is not part of any materialized object, so we can ignore it.
2119 iterator->Skip(Translation::NumberOfOperandsFor(opcode));
2120 return;
2121 }
2122
2123 case Translation::DUPLICATED_OBJECT: {
2124 int object_index = iterator->Next();
2125 if (trace_scope_ != NULL) {
2126 PrintF(trace_scope_->file(), " skipping object ");
2127 PrintF(trace_scope_->file(),
2128 " ; duplicate of object #%d\n", object_index);
2129 }
2130 AddObjectDuplication(0, object_index);
2131 return;
2132 }
2133
2134 case Translation::ARGUMENTS_OBJECT:
2135 case Translation::CAPTURED_OBJECT: {
2136 int length = iterator->Next();
2137 bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2138 if (trace_scope_ != NULL) {
2139 PrintF(trace_scope_->file(), " skipping object ");
2140 PrintF(trace_scope_->file(),
2141 " ; object (length = %d, is_args = %d)\n", length, is_args);
2142 }
2143
2144 AddObjectStart(0, length, is_args);
2145
2146 // We save the object values on the side and materialize the actual
2147 // object after the deoptimized frame is built.
2148 int object_index = deferred_objects_.length() - 1;
2149 for (int i = 0; i < length; i++) {
2150 DoTranslateObject(iterator, object_index, i);
2151 }
2152 return;
2153 }
2154 } 1893 }
2155 1894
2156 FATAL("Unexpected translation opcode"); 1895 (*iterator)++;
2157 } 1896 (*input_index)++;
2158
2159
2160 void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
2161 int object_index,
2162 int field_index) {
2163 disasm::NameConverter converter;
2164 Address object_slot = deferred_objects_[object_index].slot_address();
2165
2166 Translation::Opcode opcode =
2167 static_cast<Translation::Opcode>(iterator->Next());
2168
2169 switch (opcode) {
2170 case Translation::BEGIN:
2171 case Translation::JS_FRAME:
2172 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2173 case Translation::CONSTRUCT_STUB_FRAME:
2174 case Translation::GETTER_STUB_FRAME:
2175 case Translation::SETTER_STUB_FRAME:
2176 case Translation::COMPILED_STUB_FRAME:
2177 FATAL("Unexpected frame start translation opcode");
2178 return;
2179
2180 case Translation::REGISTER: {
2181 int input_reg = iterator->Next();
2182 intptr_t input_value = input_->GetRegister(input_reg);
2183 if (trace_scope_ != NULL) {
2184 PrintF(trace_scope_->file(),
2185 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2186 reinterpret_cast<intptr_t>(object_slot),
2187 field_index);
2188 PrintF(trace_scope_->file(),
2189 "0x%08" V8PRIxPTR " ; %s ", input_value,
2190 converter.NameOfCPURegister(input_reg));
2191 reinterpret_cast<Object*>(input_value)->ShortPrint(
2192 trace_scope_->file());
2193 PrintF(trace_scope_->file(),
2194 "\n");
2195 }
2196 AddObjectTaggedValue(input_value);
2197 return;
2198 }
2199
2200 case Translation::INT32_REGISTER: {
2201 int input_reg = iterator->Next();
2202 intptr_t value = input_->GetRegister(input_reg);
2203 bool is_smi = Smi::IsValid(value);
2204 if (trace_scope_ != NULL) {
2205 PrintF(trace_scope_->file(),
2206 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2207 reinterpret_cast<intptr_t>(object_slot),
2208 field_index);
2209 PrintF(trace_scope_->file(),
2210 "%" V8PRIdPTR " ; %s (%s)\n", value,
2211 converter.NameOfCPURegister(input_reg),
2212 TraceValueType(is_smi));
2213 }
2214 if (is_smi) {
2215 intptr_t tagged_value =
2216 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2217 AddObjectTaggedValue(tagged_value);
2218 } else {
2219 double double_value = static_cast<double>(static_cast<int32_t>(value));
2220 AddObjectDoubleValue(double_value);
2221 }
2222 return;
2223 }
2224
2225 case Translation::UINT32_REGISTER: {
2226 int input_reg = iterator->Next();
2227 uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2228 bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2229 if (trace_scope_ != NULL) {
2230 PrintF(trace_scope_->file(),
2231 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2232 reinterpret_cast<intptr_t>(object_slot),
2233 field_index);
2234 PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; uint %s (%s)\n", value,
2235 converter.NameOfCPURegister(input_reg), TraceValueType(is_smi));
2236 }
2237 if (is_smi) {
2238 intptr_t tagged_value =
2239 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2240 AddObjectTaggedValue(tagged_value);
2241 } else {
2242 double double_value = static_cast<double>(static_cast<uint32_t>(value));
2243 AddObjectDoubleValue(double_value);
2244 }
2245 return;
2246 }
2247
2248 case Translation::BOOL_REGISTER: {
2249 int input_reg = iterator->Next();
2250 uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2251 bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2252 if (trace_scope_ != NULL) {
2253 PrintF(trace_scope_->file(),
2254 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2255 reinterpret_cast<intptr_t>(object_slot), field_index);
2256 PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; bool %s (%s)\n", value,
2257 converter.NameOfCPURegister(input_reg), TraceValueType(is_smi));
2258 }
2259 if (value == 0) {
2260 AddObjectTaggedValue(
2261 reinterpret_cast<intptr_t>(isolate_->heap()->false_value()));
2262 } else {
2263 DCHECK_EQ(1U, value);
2264 AddObjectTaggedValue(
2265 reinterpret_cast<intptr_t>(isolate_->heap()->true_value()));
2266 }
2267 return;
2268 }
2269
2270 case Translation::DOUBLE_REGISTER: {
2271 int input_reg = iterator->Next();
2272 double value = input_->GetDoubleRegister(input_reg);
2273 int int_value = FastD2IChecked(value);
2274 bool is_smi =
2275 !IsMinusZero(value) && value == int_value && Smi::IsValid(int_value);
2276 if (trace_scope_ != NULL) {
2277 PrintF(trace_scope_->file(),
2278 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2279 reinterpret_cast<intptr_t>(object_slot),
2280 field_index);
2281 PrintF(trace_scope_->file(),
2282 "%e ; %s\n", value,
2283 DoubleRegister::AllocationIndexToString(input_reg));
2284 }
2285 if (is_smi) {
2286 intptr_t tagged_value =
2287 reinterpret_cast<intptr_t>(Smi::FromInt(int_value));
2288 AddObjectTaggedValue(tagged_value);
2289 } else {
2290 AddObjectDoubleValue(value);
2291 }
2292 return;
2293 }
2294
2295 case Translation::STACK_SLOT: {
2296 int input_slot_index = iterator->Next();
2297 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2298 intptr_t input_value = input_->GetFrameSlot(input_offset);
2299 if (trace_scope_ != NULL) {
2300 PrintF(trace_scope_->file(),
2301 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2302 reinterpret_cast<intptr_t>(object_slot),
2303 field_index);
2304 PrintF(trace_scope_->file(),
2305 "0x%08" V8PRIxPTR " ; [sp + %d] ", input_value, input_offset);
2306 reinterpret_cast<Object*>(input_value)->ShortPrint(
2307 trace_scope_->file());
2308 PrintF(trace_scope_->file(),
2309 "\n");
2310 }
2311 AddObjectTaggedValue(input_value);
2312 return;
2313 }
2314
2315 case Translation::INT32_STACK_SLOT: {
2316 int input_slot_index = iterator->Next();
2317 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2318 intptr_t value = input_->GetFrameSlot(input_offset);
2319 bool is_smi = Smi::IsValid(value);
2320 if (trace_scope_ != NULL) {
2321 PrintF(trace_scope_->file(),
2322 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2323 reinterpret_cast<intptr_t>(object_slot),
2324 field_index);
2325 PrintF(trace_scope_->file(),
2326 "%" V8PRIdPTR " ; [sp + %d] (%s)\n",
2327 value, input_offset, TraceValueType(is_smi));
2328 }
2329 if (is_smi) {
2330 intptr_t tagged_value =
2331 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2332 AddObjectTaggedValue(tagged_value);
2333 } else {
2334 double double_value = static_cast<double>(static_cast<int32_t>(value));
2335 AddObjectDoubleValue(double_value);
2336 }
2337 return;
2338 }
2339
2340 case Translation::UINT32_STACK_SLOT: {
2341 int input_slot_index = iterator->Next();
2342 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2343 uintptr_t value =
2344 static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2345 bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2346 if (trace_scope_ != NULL) {
2347 PrintF(trace_scope_->file(),
2348 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2349 reinterpret_cast<intptr_t>(object_slot),
2350 field_index);
2351 PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; [sp + %d] (uint %s)\n",
2352 value, input_offset, TraceValueType(is_smi));
2353 }
2354 if (is_smi) {
2355 intptr_t tagged_value =
2356 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2357 AddObjectTaggedValue(tagged_value);
2358 } else {
2359 double double_value = static_cast<double>(static_cast<uint32_t>(value));
2360 AddObjectDoubleValue(double_value);
2361 }
2362 return;
2363 }
2364
2365 case Translation::BOOL_STACK_SLOT: {
2366 int input_slot_index = iterator->Next();
2367 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2368 uintptr_t value =
2369 static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2370 bool is_smi = (value <= static_cast<uintptr_t>(Smi::kMaxValue));
2371 if (trace_scope_ != NULL) {
2372 PrintF(trace_scope_->file(),
2373 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2374 reinterpret_cast<intptr_t>(object_slot), field_index);
2375 PrintF(trace_scope_->file(), "%" V8PRIuPTR " ; [sp + %d] (bool %s)\n",
2376 value, input_offset, TraceValueType(is_smi));
2377 }
2378 if (value == 0) {
2379 AddObjectTaggedValue(
2380 reinterpret_cast<intptr_t>(isolate_->heap()->false_value()));
2381 } else {
2382 DCHECK_EQ(1U, value);
2383 AddObjectTaggedValue(
2384 reinterpret_cast<intptr_t>(isolate_->heap()->true_value()));
2385 }
2386 return;
2387 }
2388
2389 case Translation::DOUBLE_STACK_SLOT: {
2390 int input_slot_index = iterator->Next();
2391 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2392 double value = input_->GetDoubleFrameSlot(input_offset);
2393 int int_value = FastD2IChecked(value);
2394 bool is_smi =
2395 !IsMinusZero(value) && value == int_value && Smi::IsValid(int_value);
2396 if (trace_scope_ != NULL) {
2397 PrintF(trace_scope_->file(),
2398 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2399 reinterpret_cast<intptr_t>(object_slot),
2400 field_index);
2401 PrintF(trace_scope_->file(),
2402 "%e ; [sp + %d]\n", value, input_offset);
2403 }
2404 if (is_smi) {
2405 intptr_t tagged_value =
2406 reinterpret_cast<intptr_t>(Smi::FromInt(int_value));
2407 AddObjectTaggedValue(tagged_value);
2408 } else {
2409 AddObjectDoubleValue(value);
2410 }
2411 return;
2412 }
2413
2414 case Translation::LITERAL: {
2415 Object* literal = ComputeLiteral(iterator->Next());
2416 if (trace_scope_ != NULL) {
2417 PrintF(trace_scope_->file(),
2418 " object @0x%08" V8PRIxPTR ": [field #%d] <- ",
2419 reinterpret_cast<intptr_t>(object_slot),
2420 field_index);
2421 literal->ShortPrint(trace_scope_->file());
2422 PrintF(trace_scope_->file(),
2423 " ; literal\n");
2424 }
2425 intptr_t value = reinterpret_cast<intptr_t>(literal);
2426 AddObjectTaggedValue(value);
2427 return;
2428 }
2429
2430 case Translation::DUPLICATED_OBJECT: {
2431 int object_index = iterator->Next();
2432 if (trace_scope_ != NULL) {
2433 PrintF(trace_scope_->file(),
2434 " nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
2435 reinterpret_cast<intptr_t>(object_slot),
2436 field_index);
2437 isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2438 PrintF(trace_scope_->file(),
2439 " ; duplicate of object #%d\n", object_index);
2440 }
2441 // Use the materialization marker value as a sentinel and fill in
2442 // the object after the deoptimized frame is built.
2443 intptr_t value = reinterpret_cast<intptr_t>(
2444 isolate_->heap()->arguments_marker());
2445 AddObjectDuplication(0, object_index);
2446 AddObjectTaggedValue(value);
2447 return;
2448 }
2449
2450 case Translation::ARGUMENTS_OBJECT:
2451 case Translation::CAPTURED_OBJECT: {
2452 int length = iterator->Next();
2453 bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2454 if (trace_scope_ != NULL) {
2455 PrintF(trace_scope_->file(),
2456 " nested @0x%08" V8PRIxPTR ": [field #%d] <- ",
2457 reinterpret_cast<intptr_t>(object_slot),
2458 field_index);
2459 isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2460 PrintF(trace_scope_->file(),
2461 " ; object (length = %d, is_args = %d)\n", length, is_args);
2462 }
2463 // Use the materialization marker value as a sentinel and fill in
2464 // the object after the deoptimized frame is built.
2465 intptr_t value = reinterpret_cast<intptr_t>(
2466 isolate_->heap()->arguments_marker());
2467 AddObjectStart(0, length, is_args);
2468 AddObjectTaggedValue(value);
2469 // We save the object values on the side and materialize the actual
2470 // object after the deoptimized frame is built.
2471 int object_index = deferred_objects_.length() - 1;
2472 for (int i = 0; i < length; i++) {
2473 DoTranslateObject(iterator, object_index, i);
2474 }
2475 return;
2476 }
2477 }
2478
2479 FATAL("Unexpected translation opcode");
2480 }
2481
2482
2483 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
2484 int frame_index,
2485 unsigned output_offset) {
2486 disasm::NameConverter converter;
2487 // A GC-safe temporary placeholder that we can put in the output frame.
2488 const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
2489
2490 Translation::Opcode opcode =
2491 static_cast<Translation::Opcode>(iterator->Next());
2492
2493 switch (opcode) {
2494 case Translation::BEGIN:
2495 case Translation::JS_FRAME:
2496 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2497 case Translation::CONSTRUCT_STUB_FRAME:
2498 case Translation::GETTER_STUB_FRAME:
2499 case Translation::SETTER_STUB_FRAME:
2500 case Translation::COMPILED_STUB_FRAME:
2501 FATAL("Unexpected translation opcode");
2502 return;
2503
2504 case Translation::REGISTER: {
2505 int input_reg = iterator->Next();
2506 intptr_t input_value = input_->GetRegister(input_reg);
2507 if (trace_scope_ != NULL) {
2508 PrintF(
2509 trace_scope_->file(),
2510 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s ",
2511 output_[frame_index]->GetTop() + output_offset,
2512 output_offset,
2513 input_value,
2514 converter.NameOfCPURegister(input_reg));
2515 reinterpret_cast<Object*>(input_value)->ShortPrint(
2516 trace_scope_->file());
2517 PrintF(trace_scope_->file(), "\n");
2518 }
2519 output_[frame_index]->SetFrameSlot(output_offset, input_value);
2520 return;
2521 }
2522
2523 case Translation::INT32_REGISTER: {
2524 int input_reg = iterator->Next();
2525 intptr_t value = input_->GetRegister(input_reg);
2526 bool is_smi = Smi::IsValid(value);
2527 if (trace_scope_ != NULL) {
2528 PrintF(
2529 trace_scope_->file(),
2530 " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
2531 output_[frame_index]->GetTop() + output_offset,
2532 output_offset,
2533 value,
2534 converter.NameOfCPURegister(input_reg),
2535 TraceValueType(is_smi));
2536 }
2537 if (is_smi) {
2538 intptr_t tagged_value =
2539 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2540 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2541 } else {
2542 // We save the untagged value on the side and store a GC-safe
2543 // temporary placeholder in the frame.
2544 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2545 static_cast<double>(static_cast<int32_t>(value)));
2546 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2547 }
2548 return;
2549 }
2550
2551 case Translation::UINT32_REGISTER: {
2552 int input_reg = iterator->Next();
2553 uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2554 bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2555 if (trace_scope_ != NULL) {
2556 PrintF(
2557 trace_scope_->file(),
2558 " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIuPTR
2559 " ; uint %s (%s)\n",
2560 output_[frame_index]->GetTop() + output_offset,
2561 output_offset,
2562 value,
2563 converter.NameOfCPURegister(input_reg),
2564 TraceValueType(is_smi));
2565 }
2566 if (is_smi) {
2567 intptr_t tagged_value =
2568 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2569 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2570 } else {
2571 // We save the untagged value on the side and store a GC-safe
2572 // temporary placeholder in the frame.
2573 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2574 static_cast<double>(static_cast<uint32_t>(value)));
2575 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2576 }
2577 return;
2578 }
2579
2580 case Translation::BOOL_REGISTER: {
2581 int input_reg = iterator->Next();
2582 uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
2583 bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2584 if (trace_scope_ != NULL) {
2585 PrintF(trace_scope_->file(),
2586 " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIuPTR
2587 " ; bool %s (%s)\n",
2588 output_[frame_index]->GetTop() + output_offset, output_offset,
2589 value, converter.NameOfCPURegister(input_reg),
2590 TraceValueType(is_smi));
2591 }
2592 if (value == 0) {
2593 output_[frame_index]->SetFrameSlot(
2594 output_offset,
2595 reinterpret_cast<intptr_t>(isolate_->heap()->false_value()));
2596 } else {
2597 DCHECK_EQ(1U, value);
2598 output_[frame_index]->SetFrameSlot(
2599 output_offset,
2600 reinterpret_cast<intptr_t>(isolate_->heap()->true_value()));
2601 }
2602 return;
2603 }
2604
2605 case Translation::DOUBLE_REGISTER: {
2606 int input_reg = iterator->Next();
2607 double value = input_->GetDoubleRegister(input_reg);
2608 int int_value = FastD2IChecked(value);
2609 bool is_smi =
2610 !IsMinusZero(value) && value == int_value && Smi::IsValid(int_value);
2611 if (trace_scope_ != NULL) {
2612 PrintF(trace_scope_->file(),
2613 " 0x%08" V8PRIxPTR ": [top + %d] <- %e ; %s\n",
2614 output_[frame_index]->GetTop() + output_offset, output_offset,
2615 value, DoubleRegister::AllocationIndexToString(input_reg));
2616 }
2617 if (is_smi) {
2618 intptr_t tagged_value =
2619 reinterpret_cast<intptr_t>(Smi::FromInt(int_value));
2620 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2621 } else {
2622 // We save the untagged value on the side and store a GC-safe
2623 // temporary placeholder in the frame.
2624 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
2625 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2626 }
2627 return;
2628 }
2629
2630 case Translation::STACK_SLOT: {
2631 int input_slot_index = iterator->Next();
2632 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2633 intptr_t input_value = input_->GetFrameSlot(input_offset);
2634 if (trace_scope_ != NULL) {
2635 PrintF(trace_scope_->file(),
2636 " 0x%08" V8PRIxPTR ": ",
2637 output_[frame_index]->GetTop() + output_offset);
2638 PrintF(trace_scope_->file(),
2639 "[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
2640 output_offset,
2641 input_value,
2642 input_offset);
2643 reinterpret_cast<Object*>(input_value)->ShortPrint(
2644 trace_scope_->file());
2645 PrintF(trace_scope_->file(), "\n");
2646 }
2647 output_[frame_index]->SetFrameSlot(output_offset, input_value);
2648 return;
2649 }
2650
2651 case Translation::INT32_STACK_SLOT: {
2652 int input_slot_index = iterator->Next();
2653 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2654 intptr_t value = input_->GetFrameSlot(input_offset);
2655 bool is_smi = Smi::IsValid(value);
2656 if (trace_scope_ != NULL) {
2657 PrintF(trace_scope_->file(),
2658 " 0x%08" V8PRIxPTR ": ",
2659 output_[frame_index]->GetTop() + output_offset);
2660 PrintF(trace_scope_->file(),
2661 "[top + %d] <- %" V8PRIdPTR " ; [sp + %d] (%s)\n",
2662 output_offset,
2663 value,
2664 input_offset,
2665 TraceValueType(is_smi));
2666 }
2667 if (is_smi) {
2668 intptr_t tagged_value =
2669 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2670 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2671 } else {
2672 // We save the untagged value on the side and store a GC-safe
2673 // temporary placeholder in the frame.
2674 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2675 static_cast<double>(static_cast<int32_t>(value)));
2676 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2677 }
2678 return;
2679 }
2680
2681 case Translation::UINT32_STACK_SLOT: {
2682 int input_slot_index = iterator->Next();
2683 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2684 uintptr_t value =
2685 static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2686 bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2687 if (trace_scope_ != NULL) {
2688 PrintF(trace_scope_->file(),
2689 " 0x%08" V8PRIxPTR ": ",
2690 output_[frame_index]->GetTop() + output_offset);
2691 PrintF(trace_scope_->file(),
2692 "[top + %d] <- %" V8PRIuPTR " ; [sp + %d] (uint32 %s)\n",
2693 output_offset,
2694 value,
2695 input_offset,
2696 TraceValueType(is_smi));
2697 }
2698 if (is_smi) {
2699 intptr_t tagged_value =
2700 reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
2701 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2702 } else {
2703 // We save the untagged value on the side and store a GC-safe
2704 // temporary placeholder in the frame.
2705 AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
2706 static_cast<double>(static_cast<uint32_t>(value)));
2707 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2708 }
2709 return;
2710 }
2711
2712 case Translation::BOOL_STACK_SLOT: {
2713 int input_slot_index = iterator->Next();
2714 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2715 uintptr_t value =
2716 static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
2717 bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
2718 if (trace_scope_ != NULL) {
2719 PrintF(trace_scope_->file(), " 0x%08" V8PRIxPTR ": ",
2720 output_[frame_index]->GetTop() + output_offset);
2721 PrintF(trace_scope_->file(),
2722 "[top + %d] <- %" V8PRIuPTR " ; [sp + %d] (uint32 %s)\n",
2723 output_offset, value, input_offset, TraceValueType(is_smi));
2724 }
2725 if (value == 0) {
2726 output_[frame_index]->SetFrameSlot(
2727 output_offset,
2728 reinterpret_cast<intptr_t>(isolate_->heap()->false_value()));
2729 } else {
2730 DCHECK_EQ(1U, value);
2731 output_[frame_index]->SetFrameSlot(
2732 output_offset,
2733 reinterpret_cast<intptr_t>(isolate_->heap()->true_value()));
2734 }
2735 return;
2736 }
2737
2738 case Translation::DOUBLE_STACK_SLOT: {
2739 int input_slot_index = iterator->Next();
2740 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2741 double value = input_->GetDoubleFrameSlot(input_offset);
2742 int int_value = FastD2IChecked(value);
2743 bool is_smi =
2744 !IsMinusZero(value) && value == int_value && Smi::IsValid(int_value);
2745 if (trace_scope_ != NULL) {
2746 PrintF(trace_scope_->file(),
2747 " 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
2748 output_[frame_index]->GetTop() + output_offset,
2749 output_offset,
2750 value,
2751 input_offset);
2752 }
2753 if (is_smi) {
2754 intptr_t tagged_value =
2755 reinterpret_cast<intptr_t>(Smi::FromInt(int_value));
2756 output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
2757 } else {
2758 // We save the untagged value on the side and store a GC-safe
2759 // temporary placeholder in the frame.
2760 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
2761 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2762 }
2763 return;
2764 }
2765
2766 case Translation::LITERAL: {
2767 Object* literal = ComputeLiteral(iterator->Next());
2768 if (trace_scope_ != NULL) {
2769 PrintF(trace_scope_->file(),
2770 " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2771 output_[frame_index]->GetTop() + output_offset,
2772 output_offset);
2773 literal->ShortPrint(trace_scope_->file());
2774 PrintF(trace_scope_->file(), " ; literal\n");
2775 }
2776 intptr_t value = reinterpret_cast<intptr_t>(literal);
2777 output_[frame_index]->SetFrameSlot(output_offset, value);
2778 return;
2779 }
2780
2781 case Translation::DUPLICATED_OBJECT: {
2782 int object_index = iterator->Next();
2783 if (trace_scope_ != NULL) {
2784 PrintF(trace_scope_->file(),
2785 " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2786 output_[frame_index]->GetTop() + output_offset,
2787 output_offset);
2788 isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2789 PrintF(trace_scope_->file(),
2790 " ; duplicate of object #%d\n", object_index);
2791 }
2792 // Use the materialization marker value as a sentinel and fill in
2793 // the object after the deoptimized frame is built.
2794 intptr_t value = reinterpret_cast<intptr_t>(
2795 isolate_->heap()->arguments_marker());
2796 AddObjectDuplication(output_[frame_index]->GetTop() + output_offset,
2797 object_index);
2798 output_[frame_index]->SetFrameSlot(output_offset, value);
2799 return;
2800 }
2801
2802 case Translation::ARGUMENTS_OBJECT:
2803 case Translation::CAPTURED_OBJECT: {
2804 int length = iterator->Next();
2805 bool is_args = opcode == Translation::ARGUMENTS_OBJECT;
2806 if (trace_scope_ != NULL) {
2807 PrintF(trace_scope_->file(),
2808 " 0x%08" V8PRIxPTR ": [top + %d] <- ",
2809 output_[frame_index]->GetTop() + output_offset,
2810 output_offset);
2811 isolate_->heap()->arguments_marker()->ShortPrint(trace_scope_->file());
2812 PrintF(trace_scope_->file(),
2813 " ; object (length = %d, is_args = %d)\n", length, is_args);
2814 }
2815 // Use the materialization marker value as a sentinel and fill in
2816 // the object after the deoptimized frame is built.
2817 intptr_t value = reinterpret_cast<intptr_t>(
2818 isolate_->heap()->arguments_marker());
2819 AddObjectStart(output_[frame_index]->GetTop() + output_offset,
2820 length, is_args);
2821 output_[frame_index]->SetFrameSlot(output_offset, value);
2822 // We save the object values on the side and materialize the actual
2823 // object after the deoptimized frame is built.
2824 int object_index = deferred_objects_.length() - 1;
2825 for (int i = 0; i < length; i++) {
2826 DoTranslateObject(iterator, object_index, i);
2827 }
2828 return;
2829 }
2830 }
2831 } 1897 }
2832 1898
2833 1899
2834 unsigned Deoptimizer::ComputeInputFrameSize() const { 1900 unsigned Deoptimizer::ComputeInputFrameSize() const {
2835 unsigned fixed_size = ComputeFixedSize(function_); 1901 unsigned fixed_size = ComputeFixedSize(function_);
2836 // The fp-to-sp delta already takes the context, constant pool pointer and the 1902 // The fp-to-sp delta already takes the context, constant pool pointer and the
2837 // function into account so we have to avoid double counting them. 1903 // function into account so we have to avoid double counting them.
2838 unsigned result = fixed_size + fp_to_sp_delta_ - 1904 unsigned result = fixed_size + fp_to_sp_delta_ -
2839 StandardFrameConstants::kFixedFrameSizeFromFp; 1905 StandardFrameConstants::kFixedFrameSizeFromFp;
2840 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { 1906 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2841 unsigned stack_slots = compiled_code_->stack_slots(); 1907 unsigned stack_slots = compiled_code_->stack_slots();
2842 unsigned outgoing_size = ComputeOutgoingArgumentSize(); 1908 unsigned outgoing_size = ComputeOutgoingArgumentSize();
2843 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 1909 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
2844 } 1910 }
2845 return result; 1911 return result;
2846 } 1912 }
2847 1913
2848 1914
2849 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 1915 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
2850 // The fixed part of the frame consists of the return address, frame 1916 // The fixed part of the frame consists of the return address, frame
2851 // pointer, function, context, and all the incoming arguments. 1917 // pointer, function, context, and all the incoming arguments.
2852 return ComputeIncomingArgumentSize(function) + 1918 return ComputeIncomingArgumentSize(function) +
2853 StandardFrameConstants::kFixedFrameSize; 1919 StandardFrameConstants::kFixedFrameSize;
2854 } 1920 }
2855 1921
2856 1922
2857 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 1923 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
2858 // The incoming arguments is the values for formal parameters and 1924 // The incoming arguments is the values for formal parameters and
2859 // the receiver. Every slot contains a pointer. 1925 // the receiver. Every slot contains a pointer.
2860 if (function->IsSmi()) { 1926 if (function->IsSmi()) {
2861 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); 1927 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
2862 return 0; 1928 return 0;
2863 } 1929 }
2864 unsigned arguments = 1930 unsigned arguments =
2865 function->shared()->internal_formal_parameter_count() + 1; 1931 function->shared()->internal_formal_parameter_count() + 1;
2866 return arguments * kPointerSize; 1932 return arguments * kPointerSize;
2867 } 1933 }
2868 1934
2869 1935
2870 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 1936 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
2871 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1937 DeoptimizationInputData* data =
2872 compiled_code_->deoptimization_data()); 1938 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
2873 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 1939 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
2874 return height * kPointerSize; 1940 return height * kPointerSize;
2875 } 1941 }
2876 1942
2877 1943
2878 Object* Deoptimizer::ComputeLiteral(int index) const { 1944 Object* Deoptimizer::ComputeLiteral(int index) const {
2879 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1945 DeoptimizationInputData* data =
2880 compiled_code_->deoptimization_data()); 1946 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
2881 FixedArray* literals = data->LiteralArray(); 1947 FixedArray* literals = data->LiteralArray();
2882 return literals->get(index); 1948 return literals->get(index);
2883 } 1949 }
2884 1950
2885 1951
2886 void Deoptimizer::AddObjectStart(intptr_t slot, int length, bool is_args) {
2887 ObjectMaterializationDescriptor object_desc(
2888 reinterpret_cast<Address>(slot), jsframe_count_, length, -1, is_args);
2889 deferred_objects_.Add(object_desc);
2890 }
2891
2892
2893 void Deoptimizer::AddObjectDuplication(intptr_t slot, int object_index) {
2894 ObjectMaterializationDescriptor object_desc(
2895 reinterpret_cast<Address>(slot), jsframe_count_, -1, object_index, false);
2896 deferred_objects_.Add(object_desc);
2897 }
2898
2899
2900 void Deoptimizer::AddObjectTaggedValue(intptr_t value) {
2901 deferred_objects_tagged_values_.Add(reinterpret_cast<Object*>(value));
2902 }
2903
2904
2905 void Deoptimizer::AddObjectDoubleValue(double value) {
2906 deferred_objects_tagged_values_.Add(isolate()->heap()->the_hole_value());
2907 HeapNumberMaterializationDescriptor<int> value_desc(
2908 deferred_objects_tagged_values_.length() - 1, value);
2909 deferred_objects_double_values_.Add(value_desc);
2910 }
2911
2912
2913 void Deoptimizer::AddDoubleValue(intptr_t slot_address, double value) {
2914 HeapNumberMaterializationDescriptor<Address> value_desc(
2915 reinterpret_cast<Address>(slot_address), value);
2916 deferred_heap_numbers_.Add(value_desc);
2917 }
2918
2919
2920 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, 1952 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
2921 BailoutType type, 1953 BailoutType type,
2922 int max_entry_id) { 1954 int max_entry_id) {
2923 // We cannot run this if the serializer is enabled because this will 1955 // We cannot run this if the serializer is enabled because this will
2924 // cause us to emit relocation information for the external 1956 // cause us to emit relocation information for the external
2925 // references. This is fine because the deoptimizer's code section 1957 // references. This is fine because the deoptimizer's code section
2926 // isn't meant to be serialized at all. 1958 // isn't meant to be serialized at all.
2927 CHECK(type == EAGER || type == SOFT || type == LAZY); 1959 CHECK(type == EAGER || type == SOFT || type == LAZY);
2928 DeoptimizerData* data = isolate->deoptimizer_data(); 1960 DeoptimizerData* data = isolate->deoptimizer_data();
2929 int entry_count = data->deopt_entry_code_entries_[type]; 1961 int entry_count = data->deopt_entry_code_entries_[type];
(...skipping 10 matching lines...) Expand all
2940 DCHECK(!RelocInfo::RequiresRelocation(desc)); 1972 DCHECK(!RelocInfo::RequiresRelocation(desc));
2941 1973
2942 MemoryChunk* chunk = data->deopt_entry_code_[type]; 1974 MemoryChunk* chunk = data->deopt_entry_code_[type];
2943 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= 1975 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2944 desc.instr_size); 1976 desc.instr_size);
2945 if (!chunk->CommitArea(desc.instr_size)) { 1977 if (!chunk->CommitArea(desc.instr_size)) {
2946 V8::FatalProcessOutOfMemory( 1978 V8::FatalProcessOutOfMemory(
2947 "Deoptimizer::EnsureCodeForDeoptimizationEntry"); 1979 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
2948 } 1980 }
2949 CopyBytes(chunk->area_start(), desc.buffer, 1981 CopyBytes(chunk->area_start(), desc.buffer,
2950 static_cast<size_t>(desc.instr_size)); 1982 static_cast<size_t>(desc.instr_size));
2951 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size); 1983 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size);
2952 1984
2953 data->deopt_entry_code_entries_[type] = entry_count; 1985 data->deopt_entry_code_entries_[type] = entry_count;
2954 } 1986 }
2955 1987
2956 1988
2957 FrameDescription::FrameDescription(uint32_t frame_size, 1989 FrameDescription::FrameDescription(uint32_t frame_size,
2958 JSFunction* function) 1990 JSFunction* function)
2959 : frame_size_(frame_size), 1991 : frame_size_(frame_size),
2960 function_(function), 1992 function_(function),
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
3111 void Translation::BeginJSFrame(BailoutId node_id, 2143 void Translation::BeginJSFrame(BailoutId node_id,
3112 int literal_id, 2144 int literal_id,
3113 unsigned height) { 2145 unsigned height) {
3114 buffer_->Add(JS_FRAME, zone()); 2146 buffer_->Add(JS_FRAME, zone());
3115 buffer_->Add(node_id.ToInt(), zone()); 2147 buffer_->Add(node_id.ToInt(), zone());
3116 buffer_->Add(literal_id, zone()); 2148 buffer_->Add(literal_id, zone());
3117 buffer_->Add(height, zone()); 2149 buffer_->Add(height, zone());
3118 } 2150 }
3119 2151
3120 2152
3121 void Translation::BeginCompiledStubFrame() { 2153 void Translation::BeginCompiledStubFrame(int height) {
3122 buffer_->Add(COMPILED_STUB_FRAME, zone()); 2154 buffer_->Add(COMPILED_STUB_FRAME, zone());
2155 buffer_->Add(height, zone());
3123 } 2156 }
3124 2157
3125 2158
3126 void Translation::BeginArgumentsObject(int args_length) { 2159 void Translation::BeginArgumentsObject(int args_length) {
3127 buffer_->Add(ARGUMENTS_OBJECT, zone()); 2160 buffer_->Add(ARGUMENTS_OBJECT, zone());
3128 buffer_->Add(args_length, zone()); 2161 buffer_->Add(args_length, zone());
3129 } 2162 }
3130 2163
3131 2164
3132 void Translation::BeginCapturedObject(int length) { 2165 void Translation::BeginCapturedObject(int length) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) 2290 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
3258 } 2291 }
3259 #undef TRANSLATION_OPCODE_CASE 2292 #undef TRANSLATION_OPCODE_CASE
3260 UNREACHABLE(); 2293 UNREACHABLE();
3261 return ""; 2294 return "";
3262 } 2295 }
3263 2296
3264 #endif 2297 #endif
3265 2298
3266 2299
2300 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2301 int index = StackIdToIndex(fp);
2302 if (index == -1) {
2303 return Handle<FixedArray>::null();
2304 }
2305 Handle<FixedArray> array = GetStackEntries();
2306 CHECK_GT(array->length(), index);
2307 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
2308 }
2309
2310
2311 void MaterializedObjectStore::Set(Address fp,
2312 Handle<FixedArray> materialized_objects) {
2313 int index = StackIdToIndex(fp);
2314 if (index == -1) {
2315 index = frame_fps_.length();
2316 frame_fps_.Add(fp);
2317 }
2318
2319 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2320 array->set(index, *materialized_objects);
2321 }
2322
2323
2324 bool MaterializedObjectStore::Remove(Address fp) {
2325 int index = StackIdToIndex(fp);
2326 if (index == -1) {
2327 return false;
2328 }
2329 CHECK_GE(index, 0);
2330
2331 frame_fps_.Remove(index);
2332 FixedArray* array = isolate()->heap()->materialized_objects();
2333 CHECK_LT(index, array->length());
2334 for (int i = index; i < frame_fps_.length(); i++) {
2335 array->set(i, array->get(i + 1));
2336 }
2337 array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
2338 return true;
2339 }
2340
2341
2342 int MaterializedObjectStore::StackIdToIndex(Address fp) {
2343 for (int i = 0; i < frame_fps_.length(); i++) {
2344 if (frame_fps_[i] == fp) {
2345 return i;
2346 }
2347 }
2348 return -1;
2349 }
2350
2351
2352 Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
2353 return Handle<FixedArray>(isolate()->heap()->materialized_objects());
2354 }
2355
2356
2357 Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
2358 Handle<FixedArray> array = GetStackEntries();
2359 if (array->length() >= length) {
2360 return array;
2361 }
2362
2363 int new_length = length > 10 ? length : 10;
2364 if (new_length < 2 * array->length()) {
2365 new_length = 2 * array->length();
2366 }
2367
2368 Handle<FixedArray> new_array =
2369 isolate()->factory()->NewFixedArray(new_length, TENURED);
2370 for (int i = 0; i < array->length(); i++) {
2371 new_array->set(i, array->get(i));
2372 }
2373 for (int i = array->length(); i < length; i++) {
2374 new_array->set(i, isolate()->heap()->undefined_value());
2375 }
2376 isolate()->heap()->public_set_materialized_objects(*new_array);
2377 return new_array;
2378 }
2379
2380
2381 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
2382 int frame_index,
2383 bool has_arguments_adaptor,
2384 bool has_construct_stub) {
2385 FrameDescription* output_frame = deoptimizer->output_[frame_index];
2386 function_ = output_frame->GetFunction();
2387 context_ = reinterpret_cast<Object*>(output_frame->GetContext());
2388 has_construct_stub_ = has_construct_stub;
2389 expression_count_ = output_frame->GetExpressionCount();
2390 expression_stack_ = new Object* [expression_count_];
2391 // Get the source position using the unoptimized code.
2392 Address pc = reinterpret_cast<Address>(output_frame->GetPc());
2393 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc));
2394 source_position_ = code->SourcePosition(pc);
2395
2396 for (int i = 0; i < expression_count_; i++) {
2397 SetExpression(i, output_frame->GetExpression(i));
2398 }
2399
2400 if (has_arguments_adaptor) {
2401 output_frame = deoptimizer->output_[frame_index - 1];
2402 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
2403 }
2404
2405 parameters_count_ = output_frame->ComputeParametersCount();
2406 parameters_ = new Object* [parameters_count_];
2407 for (int i = 0; i < parameters_count_; i++) {
2408 SetParameter(i, output_frame->GetParameter(i));
2409 }
2410 }
2411
2412
2413 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
2414 delete[] expression_stack_;
2415 delete[] parameters_;
2416 }
2417
2418
2419 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
2420 v->VisitPointer(bit_cast<Object**>(&function_));
2421 v->VisitPointer(&context_);
2422 v->VisitPointers(parameters_, parameters_ + parameters_count_);
2423 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
2424 }
2425
2426
2427 const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
2428 DCHECK(deopt_reason < kLastDeoptReason);
2429 #define DEOPT_MESSAGES_TEXTS(C, T) T,
2430 static const char* deopt_messages_[] = {
2431 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
2432 #undef DEOPT_MESSAGES_TEXTS
2433 return deopt_messages_[deopt_reason];
2434 }
2435
2436
2437 Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
2438 SourcePosition last_position = SourcePosition::Unknown();
2439 Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
2440 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
2441 RelocInfo::ModeMask(RelocInfo::POSITION);
2442 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2443 RelocInfo* info = it.rinfo();
2444 if (info->pc() >= pc) return DeoptInfo(last_position, NULL, last_reason);
2445 if (info->rmode() == RelocInfo::POSITION) {
2446 int raw_position = static_cast<int>(info->data());
2447 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
2448 : SourcePosition::Unknown();
2449 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2450 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
2451 }
2452 }
2453 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
2454 }
2455
2456
2457 // static
2458 TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
2459 int length,
2460 int object_index) {
2461 TranslatedValue slot(container, ARGUMENTS_OBJECT);
2462 slot.deferred_object_length_ = length;
2463 slot.object_index_ = object_index;
2464 return slot;
2465 }
2466
2467
2468 // static
2469 TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2470 int length,
2471 int object_index) {
2472 TranslatedValue slot(container, DEFERRED_OBJECT);
2473 slot.deferred_object_length_ = length;
2474 slot.object_index_ = object_index;
2475 return slot;
2476 }
2477
2478
2479 // static
2480 TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2481 int id) {
2482 TranslatedValue slot(container, DUPLICATE_OBJECT);
2483 slot.object_index_ = id;
2484 return slot;
2485 }
2486
2487
2488 // static
2489 TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2490 double value) {
2491 TranslatedValue slot(container, DOUBLE);
2492 slot.double_value_ = value;
2493 return slot;
2494 }
2495
2496
2497 // static
2498 TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2499 uint32_t value) {
2500 TranslatedValue slot(container, INT32);
2501 slot.integral_value_ = value;
2502 return slot;
2503 }
2504
2505
2506 // static
2507 TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2508 uint32_t value) {
2509 TranslatedValue slot(container, UINT32);
2510 slot.integral_value_ = value;
2511 return slot;
2512 }
2513
2514
2515 // static
2516 TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2517 uint32_t value) {
2518 TranslatedValue slot(container, BOOLBIT);
2519 slot.integral_value_ = value;
2520 return slot;
2521 }
2522
2523
2524 // static
2525 TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2526 Object* literal) {
2527 TranslatedValue slot(container, TAGGED);
2528 slot.raw_literal_ = literal;
2529 return slot;
2530 }
2531
2532
2533 // static
2534 TranslatedValue TranslatedValue::NewInvalid() {
2535 return TranslatedValue(nullptr, UNKNOWN);
2536 }
2537
2538
2539 Isolate* TranslatedValue::isolate() { return container_->isolate(); }
2540
2541
2542 Object* TranslatedValue::GetRawValue() {
2543 // If we have a value, return it.
2544 Handle<Object> result_handle;
2545 if (value_.ToHandle(&result_handle)) {
2546 return *result_handle;
2547 }
2548
2549 // Otherwise, do a best effort to get the value without allocation.
2550 switch (kind()) {
2551 case TAGGED:
2552 return raw_literal_;
2553
2554 case INT32: {
2555 int32_t i32_value = static_cast<int32_t>(integral_value_);
2556 bool is_smi = Smi::IsValid(i32_value);
2557 if (is_smi) {
2558 return Smi::FromInt(i32_value);
2559 }
2560 break;
2561 }
2562
2563 case UINT32: {
2564 bool is_smi = (integral_value_ <= static_cast<uintptr_t>(Smi::kMaxValue));
2565 if (is_smi) {
2566 return Smi::FromInt(static_cast<int32_t>(integral_value_));
2567 }
2568 break;
2569 }
2570
2571 case DOUBLE: {
2572 int int_value = FastD2IChecked(double_value_);
2573 bool is_smi = !IsMinusZero(double_value_) && double_value_ == int_value &&
2574 Smi::IsValid(int_value);
2575 if (is_smi) {
2576 return Smi::FromInt(static_cast<int32_t>(int_value));
2577 }
2578 break;
2579 }
2580
2581 case BOOLBIT: {
2582 if (integral_value_ == 0) {
2583 return isolate()->heap()->false_value();
2584 } else {
2585 CHECK_EQ(1, integral_value_);
2586 return isolate()->heap()->true_value();
2587 }
2588 }
2589
2590 default:
2591 break;
2592 }
2593
2594 // If we could not get the value without allocation, return the arguments
2595 // marker.
2596 return isolate()->heap()->arguments_marker();
2597 }
2598
2599
2600 Handle<Object> TranslatedValue::GetValue() {
2601 Handle<Object> result;
2602 // If we already have a value, then get it.
2603 if (value_.ToHandle(&result)) return result;
2604
2605 // Otherwise we have to materialize.
2606 switch (kind()) {
2607 case TranslatedValue::TAGGED:
2608 case TranslatedValue::INT32:
2609 case TranslatedValue::UINT32:
2610 case TranslatedValue::BOOLBIT:
2611 case TranslatedValue::DOUBLE: {
2612 MaterializeSimple();
2613 return value_.ToHandleChecked();
2614 }
2615
2616 case TranslatedValue::ARGUMENTS_OBJECT:
2617 case TranslatedValue::DEFERRED_OBJECT:
2618 case TranslatedValue::DUPLICATE_OBJECT:
2619 return container_->MaterializeObjectAt(ObjectIndex());
2620
2621 case TranslatedValue::UNKNOWN:
2622 FATAL("unexpected case");
2623 return Handle<Object>::null();
2624 }
2625
2626 FATAL("internal error: value missing");
2627 return Handle<Object>::null();
2628 }
2629
2630
2631 void TranslatedValue::MaterializeSimple() {
2632 // If we already have materialized, return.
2633 if (!value_.is_null()) return;
2634
2635 Object* raw_value = GetRawValue();
2636 if (raw_value != isolate()->heap()->arguments_marker()) {
2637 // We can get the value without allocation, just return it here.
2638 value_ = Handle<Object>(raw_value, isolate());
2639 return;
2640 }
2641
2642 switch (kind()) {
2643 case INT32: {
2644 int32_t i32_value = static_cast<int32_t>(integral_value_);
Benedikt Meurer 2015/06/03 04:02:17 Use a bit_cast<int32_t> here, or if you turn the f
Jarin 2015/06/03 09:28:07 Turned to unions.
2645 value_ = Handle<Object>(isolate()->factory()->NewNumber(i32_value));
2646 return;
2647 }
2648
2649 case UINT32:
2650 value_ = Handle<Object>(isolate()->factory()->NewNumber(integral_value_));
2651 return;
2652
2653 case DOUBLE:
2654 value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value_));
2655 return;
2656
2657 case DEFERRED_OBJECT:
2658 case DUPLICATE_OBJECT:
2659 case ARGUMENTS_OBJECT:
2660 case UNKNOWN:
2661 case TAGGED:
2662 case BOOLBIT:
2663 FATAL("internal error: unexpected materialization.");
2664 break;
2665 }
2666 }
2667
2668
2669 bool TranslatedValue::IsMaterializedObject() {
2670 switch (kind()) {
2671 case DEFERRED_OBJECT:
2672 case DUPLICATE_OBJECT:
2673 case ARGUMENTS_OBJECT:
2674 return true;
2675 default:
2676 return false;
2677 }
2678 }
2679
2680
2681 int TranslatedState::SlotOffsetFp(int slot_index) {
2682 if (slot_index >= 0) {
2683 const int offset = StandardFrameConstants::kExpressionsOffset;
2684 return offset - (slot_index * kPointerSize);
2685 } else {
2686 const int offset = StandardFrameConstants::kCallerSPOffset;
2687 return offset - ((slot_index + 1) * kPointerSize);
2688 }
2689 }
2690
2691
2692 Address TranslatedState::SlotAddress(Address fp, int slot_index) {
2693 return fp + SlotOffsetFp(slot_index);
2694 }
2695
2696
2697 uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
2698 Address address = fp + slot_offset;
2699 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
2700 return Memory::uint32_at(address + kIntSize);
2701 #else
2702 return Memory::uint32_at(address);
2703 #endif
2704 }
2705
2706
2707 void TranslatedValue::Handlify() {
2708 if (raw_literal_ != nullptr) {
2709 value_ = Handle<Object>(raw_literal_, isolate());
2710 raw_literal_ = nullptr;
2711 }
2712 }
2713
2714
2715 TranslatedFrame TranslatedFrame::JSFrame(BailoutId node_id,
2716 JSFunction* function, int height) {
2717 TranslatedFrame frame(Function, function->GetIsolate(), function, height);
2718 frame.node_id_ = node_id;
2719 return frame;
2720 }
2721
2722
2723 TranslatedFrame TranslatedFrame::AccessorFrame(Kind kind,
2724 JSFunction* function) {
2725 DCHECK(kind == Setter || kind == Getter);
2726 return TranslatedFrame(kind, function->GetIsolate(), function);
2727 }
2728
2729
2730 TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(JSFunction* function,
2731 int height) {
2732 return TranslatedFrame(ArgumentsAdaptor, function->GetIsolate(), function,
2733 height);
2734 }
2735
2736
2737 TranslatedFrame TranslatedFrame::ConstructStubFrame(JSFunction* function,
2738 int height) {
2739 return TranslatedFrame(ConstructStub, function->GetIsolate(), function,
2740 height);
2741 }
2742
2743
2744 int TranslatedFrame::GetValueCount() {
2745 switch (kind()) {
2746 case Function: {
2747 int parameter_count =
2748 (raw_function_ == nullptr
2749 ? function_->shared()->internal_formal_parameter_count()
2750 : raw_function_->shared()->internal_formal_parameter_count()) +
2751 1;
2752 return height_ + parameter_count;
2753 }
2754
2755 case Getter:
2756 return 1; // Receiver.
2757
2758 case Setter:
2759 return 2; // Receiver and the value to set.
2760
2761 case ArgumentsAdaptor:
2762 case ConstructStub:
2763 case CompiledStub:
2764 return height_;
2765
2766 case Invalid:
2767 UNREACHABLE();
2768 break;
2769 }
2770 UNREACHABLE();
2771 return -1;
2772 }
2773
2774
2775 void TranslatedFrame::Handlify(Isolate* isolate) {
2776 if (raw_function_ != nullptr) {
2777 function_ = Handle<JSFunction>(raw_function_, isolate);
2778 raw_function_ = nullptr;
2779 }
2780 for (auto& value : values_) {
2781 value.Handlify();
2782 }
2783 }
2784
2785
2786 TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
2787 TranslationIterator* iterator, FixedArray* literal_array, Address fp,
2788 JSFunction* frame_function, FILE* trace_file) {
2789 Translation::Opcode opcode =
2790 static_cast<Translation::Opcode>(iterator->Next());
2791 switch (opcode) {
2792 case Translation::JS_FRAME: {
2793 BailoutId node_id = BailoutId(iterator->Next());
2794 int closure_id = iterator->Next();
2795 JSFunction* function =
2796 (closure_id == Translation::kSelfLiteralId)
2797 ? frame_function
2798 : JSFunction::cast(literal_array->get(closure_id));
2799 int height = iterator->Next();
2800 if (trace_file != nullptr) {
2801 PrintF(trace_file, " reading input frame ");
2802 function->PrintName(trace_file);
2803 int arg_count =
2804 function->shared()->internal_formal_parameter_count() + 1;
2805 PrintF(trace_file, " => node=%d, args=%d, height=%d; inputs:\n",
2806 arg_count, node_id.ToInt(), height);
2807 }
2808 return TranslatedFrame::JSFrame(node_id, function, height);
2809 }
2810
2811 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
2812 JSFunction* function =
2813 JSFunction::cast(literal_array->get(iterator->Next()));
2814 int height = iterator->Next();
2815 if (trace_file != nullptr) {
2816 PrintF(trace_file, " reading arguments adaptor frame");
2817 function->PrintName(trace_file);
2818 PrintF(trace_file, " => height=%d; inputs:\n", height);
2819 }
2820 return TranslatedFrame::ArgumentsAdaptorFrame(function, height);
2821 }
2822
2823 case Translation::CONSTRUCT_STUB_FRAME: {
2824 JSFunction* function =
2825 JSFunction::cast(literal_array->get(iterator->Next()));
2826 int height = iterator->Next();
2827 if (trace_file != nullptr) {
2828 PrintF(trace_file, " reading construct stub frame ");
2829 function->PrintName(trace_file);
2830 PrintF(trace_file, " => height=%d; inputs:\n", height);
2831 }
2832 return TranslatedFrame::ConstructStubFrame(function, height);
2833 }
2834
2835 case Translation::GETTER_STUB_FRAME: {
2836 JSFunction* function =
2837 JSFunction::cast(literal_array->get(iterator->Next()));
2838 if (trace_file != nullptr) {
2839 PrintF(trace_file, " reading getter frame ");
2840 function->PrintName(trace_file);
2841 PrintF(trace_file, "; inputs:\n");
2842 }
2843 return TranslatedFrame::AccessorFrame(TranslatedFrame::Getter, function);
2844 }
2845
2846 case Translation::SETTER_STUB_FRAME: {
2847 JSFunction* function =
2848 JSFunction::cast(literal_array->get(iterator->Next()));
2849 if (trace_file != nullptr) {
2850 PrintF(trace_file, " reading setter frame ");
2851 function->PrintName(trace_file);
2852 PrintF(trace_file, "; inputs:\n");
2853 }
2854 return TranslatedFrame::AccessorFrame(TranslatedFrame::Setter, function);
2855 }
2856
2857 case Translation::COMPILED_STUB_FRAME: {
2858 int height = iterator->Next();
2859 if (trace_file != nullptr) {
2860 PrintF(trace_file,
2861 " reading compiler stub frame => height=%d; inputs:\n", height);
2862 }
2863 return TranslatedFrame::CompiledStubFrame(height,
2864 literal_array->GetIsolate());
2865 }
2866
2867 case Translation::BEGIN:
2868 case Translation::DUPLICATED_OBJECT:
2869 case Translation::ARGUMENTS_OBJECT:
2870 case Translation::CAPTURED_OBJECT:
2871 case Translation::REGISTER:
2872 case Translation::INT32_REGISTER:
2873 case Translation::UINT32_REGISTER:
2874 case Translation::BOOL_REGISTER:
2875 case Translation::DOUBLE_REGISTER:
2876 case Translation::STACK_SLOT:
2877 case Translation::INT32_STACK_SLOT:
2878 case Translation::UINT32_STACK_SLOT:
2879 case Translation::BOOL_STACK_SLOT:
2880 case Translation::DOUBLE_STACK_SLOT:
2881 case Translation::LITERAL:
2882 break;
2883 }
2884 FATAL("We should never get here - unexpected deopt info.");
2885 return TranslatedFrame::InvalidFrame();
2886 }
2887
2888
2889 // static
2890 void TranslatedFrame::AdvanceIterator(
2891 std::deque<TranslatedValue>::iterator* iter) {
2892 int values_to_skip = 1;
2893 while (values_to_skip > 0) {
2894 // Consume the current element.
2895 values_to_skip--;
2896 // Add all the children.
2897 values_to_skip += (*iter)->GetChildrenCount();
2898
2899 (*iter)++;
2900 }
2901 }
2902
2903
3267 // We can't intermix stack decoding and allocations because 2904 // We can't intermix stack decoding and allocations because
3268 // deoptimization infrastracture is not GC safe. 2905 // deoptimization infrastracture is not GC safe.
3269 // Thus we build a temporary structure in malloced space. 2906 // Thus we build a temporary structure in malloced space.
3270 SlotRef SlotRefValueBuilder::ComputeSlotForNextArgument( 2907 TranslatedValue TranslatedState::CreateNextTranslatedValue(
3271 Translation::Opcode opcode, 2908 int frame_index, int value_index, TranslationIterator* iterator,
3272 TranslationIterator* iterator, 2909 FixedArray* literal_array, Address fp, RegisterValues* registers,
3273 DeoptimizationInputData* data, 2910 FILE* trace_file) {
3274 JavaScriptFrame* frame) { 2911 disasm::NameConverter converter;
2912
2913 Translation::Opcode opcode =
2914 static_cast<Translation::Opcode>(iterator->Next());
3275 switch (opcode) { 2915 switch (opcode) {
3276 case Translation::BEGIN: 2916 case Translation::BEGIN:
3277 case Translation::JS_FRAME: 2917 case Translation::JS_FRAME:
3278 case Translation::ARGUMENTS_ADAPTOR_FRAME: 2918 case Translation::ARGUMENTS_ADAPTOR_FRAME:
3279 case Translation::CONSTRUCT_STUB_FRAME: 2919 case Translation::CONSTRUCT_STUB_FRAME:
3280 case Translation::GETTER_STUB_FRAME: 2920 case Translation::GETTER_STUB_FRAME:
3281 case Translation::SETTER_STUB_FRAME: 2921 case Translation::SETTER_STUB_FRAME:
2922 case Translation::COMPILED_STUB_FRAME:
3282 // Peeled off before getting here. 2923 // Peeled off before getting here.
3283 break; 2924 break;
3284 2925
3285 case Translation::DUPLICATED_OBJECT: { 2926 case Translation::DUPLICATED_OBJECT: {
3286 return SlotRef::NewDuplicateObject(iterator->Next()); 2927 int object_id = iterator->Next();
3287 } 2928 if (trace_file != nullptr) {
3288 2929 PrintF(trace_file, "duplicated object #%d", object_id);
3289 case Translation::ARGUMENTS_OBJECT: 2930 }
3290 return SlotRef::NewArgumentsObject(iterator->Next()); 2931 object_positions_.push_back(object_positions_[object_id]);
2932 return TranslatedValue::NewDuplicateObject(this, object_id);
2933 }
2934
2935 case Translation::ARGUMENTS_OBJECT: {
2936 int arg_count = iterator->Next();
2937 int object_index = static_cast<int>(object_positions_.size());
2938 if (trace_file != nullptr) {
2939 PrintF(trace_file, "argumets object #%d (length = %d)", object_index,
2940 arg_count);
2941 }
2942 object_positions_.push_back({frame_index, value_index});
2943 return TranslatedValue::NewArgumentsObject(this, arg_count, object_index);
2944 }
3291 2945
3292 case Translation::CAPTURED_OBJECT: { 2946 case Translation::CAPTURED_OBJECT: {
3293 return SlotRef::NewDeferredObject(iterator->Next()); 2947 int field_count = iterator->Next();
3294 } 2948 int object_index = static_cast<int>(object_positions_.size());
3295 2949 if (trace_file != nullptr) {
3296 case Translation::REGISTER: 2950 PrintF(trace_file, "captured object #%d (length = %d)", object_index,
3297 case Translation::INT32_REGISTER: 2951 field_count);
3298 case Translation::UINT32_REGISTER: 2952 }
3299 case Translation::BOOL_REGISTER: 2953 object_positions_.push_back({frame_index, value_index});
3300 case Translation::DOUBLE_REGISTER: 2954 return TranslatedValue::NewDeferredObject(this, field_count,
3301 // We are at safepoint which corresponds to call. All registers are 2955 object_index);
3302 // saved by caller so there would be no live registers at this 2956 }
3303 // point. Thus these translation commands should not be used. 2957
3304 break; 2958 case Translation::REGISTER: {
2959 int input_reg = iterator->Next();
2960 if (registers == nullptr) return TranslatedValue::NewInvalid();
2961 intptr_t value = registers->GetRegister(input_reg);
2962 if (trace_file != nullptr) {
2963 PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
2964 converter.NameOfCPURegister(input_reg));
2965 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
2966 }
2967 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
2968 }
2969
2970 case Translation::INT32_REGISTER: {
2971 int input_reg = iterator->Next();
2972 if (registers == nullptr) return TranslatedValue::NewInvalid();
2973 intptr_t value = registers->GetRegister(input_reg);
2974 if (trace_file != nullptr) {
2975 PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
2976 converter.NameOfCPURegister(input_reg));
2977 }
2978 return TranslatedValue::NewInt32(this, static_cast<uint32_t>(value));
2979 }
2980
2981 case Translation::UINT32_REGISTER: {
2982 int input_reg = iterator->Next();
2983 if (registers == nullptr) return TranslatedValue::NewInvalid();
2984 intptr_t value = registers->GetRegister(input_reg);
2985 if (trace_file != nullptr) {
2986 PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
2987 converter.NameOfCPURegister(input_reg));
2988 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
2989 }
2990 return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
2991 }
2992
2993 case Translation::BOOL_REGISTER: {
2994 int input_reg = iterator->Next();
2995 if (registers == nullptr) return TranslatedValue::NewInvalid();
2996 intptr_t value = registers->GetRegister(input_reg);
2997 if (trace_file != nullptr) {
2998 PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
2999 converter.NameOfCPURegister(input_reg));
3000 }
3001 return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
3002 }
3003
3004 case Translation::DOUBLE_REGISTER: {
3005 int input_reg = iterator->Next();
3006 if (registers == nullptr) return TranslatedValue::NewInvalid();
3007 double value = registers->GetDoubleRegister(input_reg);
3008 if (trace_file != nullptr) {
3009 PrintF(trace_file, "%e ; %s (bool)", value,
3010 DoubleRegister::AllocationIndexToString(input_reg));
3011 }
3012 return TranslatedValue::NewDouble(this, value);
3013 }
3305 3014
3306 case Translation::STACK_SLOT: { 3015 case Translation::STACK_SLOT: {
3307 int slot_index = iterator->Next(); 3016 int slot_offset = SlotOffsetFp(iterator->Next());
3308 Address slot_addr = SlotAddress(frame, slot_index); 3017 intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
3309 return SlotRef(slot_addr, SlotRef::TAGGED); 3018 if (trace_file != nullptr) {
3019 PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
3020 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3021 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3022 }
3023 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3310 } 3024 }
3311 3025
3312 case Translation::INT32_STACK_SLOT: { 3026 case Translation::INT32_STACK_SLOT: {
3313 int slot_index = iterator->Next(); 3027 int slot_offset = SlotOffsetFp(iterator->Next());
3314 Address slot_addr = SlotAddress(frame, slot_index); 3028 uint32_t value = GetUInt32Slot(fp, slot_offset);
3315 return SlotRef(slot_addr, SlotRef::INT32); 3029 if (trace_file != nullptr) {
3030 PrintF(trace_file, "%d ; (int) [fp %c %d] ",
3031 static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
3032 std::abs(slot_offset));
3033 }
3034 return TranslatedValue::NewInt32(this, value);
3316 } 3035 }
3317 3036
3318 case Translation::UINT32_STACK_SLOT: { 3037 case Translation::UINT32_STACK_SLOT: {
3319 int slot_index = iterator->Next(); 3038 int slot_offset = SlotOffsetFp(iterator->Next());
3320 Address slot_addr = SlotAddress(frame, slot_index); 3039 uint32_t value = GetUInt32Slot(fp, slot_offset);
3321 return SlotRef(slot_addr, SlotRef::UINT32); 3040 if (trace_file != nullptr) {
3041 PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
3042 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3043 }
3044 return TranslatedValue::NewUInt32(this, value);
3322 } 3045 }
3323 3046
3324 case Translation::BOOL_STACK_SLOT: { 3047 case Translation::BOOL_STACK_SLOT: {
3325 int slot_index = iterator->Next(); 3048 int slot_offset = SlotOffsetFp(iterator->Next());
3326 Address slot_addr = SlotAddress(frame, slot_index); 3049 uint32_t value = GetUInt32Slot(fp, slot_offset);
3327 return SlotRef(slot_addr, SlotRef::BOOLBIT); 3050 if (trace_file != nullptr) {
3051 PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
3052 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3053 }
3054 return TranslatedValue::NewBool(this, value);
3328 } 3055 }
3329 3056
3330 case Translation::DOUBLE_STACK_SLOT: { 3057 case Translation::DOUBLE_STACK_SLOT: {
3331 int slot_index = iterator->Next(); 3058 int slot_offset = SlotOffsetFp(iterator->Next());
3332 Address slot_addr = SlotAddress(frame, slot_index); 3059 double value = *(reinterpret_cast<double*>(fp + slot_offset));
3333 return SlotRef(slot_addr, SlotRef::DOUBLE); 3060 if (trace_file != nullptr) {
3061 PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
3062 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3063 }
3064 return TranslatedValue::NewDouble(this, value);
3334 } 3065 }
3335 3066
3336 case Translation::LITERAL: { 3067 case Translation::LITERAL: {
3337 int literal_index = iterator->Next(); 3068 int literal_index = iterator->Next();
3338 return SlotRef(data->GetIsolate(), 3069 Object* value = literal_array->get(literal_index);
3339 data->LiteralArray()->get(literal_index)); 3070 if (trace_file != nullptr) {
3340 } 3071 PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
3341 3072 reinterpret_cast<intptr_t>(value), literal_index);
3342 case Translation::COMPILED_STUB_FRAME: 3073 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3343 UNREACHABLE(); 3074 }
3344 break; 3075
3076 return TranslatedValue::NewTagged(this, value);
3077 }
3345 } 3078 }
3346 3079
3347 FATAL("We should never get here - unexpected deopt info."); 3080 FATAL("We should never get here - unexpected deopt info.");
3348 return SlotRef(); 3081 return TranslatedValue(nullptr, TranslatedValue::UNKNOWN);
3349 } 3082 }
3350 3083
3351 3084
3352 SlotRefValueBuilder::SlotRefValueBuilder(JavaScriptFrame* frame, 3085 TranslatedState::TranslatedState(JavaScriptFrame* frame)
3353 int inlined_jsframe_index, 3086 : isolate_(nullptr),
3354 int formal_parameter_count) 3087 stack_frame_pointer_(nullptr),
3355 : current_slot_(0), 3088 has_adapted_arguments_(false) {
3356 args_length_(-1),
3357 first_slot_index_(-1),
3358 should_deoptimize_(false) {
3359 DisallowHeapAllocation no_gc;
3360
3361 int deopt_index = Safepoint::kNoDeoptimizationIndex; 3089 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3362 DeoptimizationInputData* data = 3090 DeoptimizationInputData* data =
3363 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); 3091 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
3364 TranslationIterator it(data->TranslationByteArray(), 3092 TranslationIterator it(data->TranslationByteArray(),
3365 data->TranslationIndex(deopt_index)->value()); 3093 data->TranslationIndex(deopt_index)->value());
3366 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 3094 Init(frame->fp(), frame->function(), &it, data->LiteralArray(),
3367 CHECK_EQ(opcode, Translation::BEGIN); 3095 nullptr /* registers */, nullptr /* trace file */);
3368 it.Next(); // Drop frame count. 3096 }
3369 3097
3370 stack_frame_id_ = frame->fp(); 3098
3371 3099 TranslatedState::TranslatedState()
3372 int jsframe_count = it.Next(); 3100 : isolate_(nullptr),
3373 CHECK_GT(jsframe_count, inlined_jsframe_index); 3101 stack_frame_pointer_(nullptr),
3374 int jsframes_to_skip = inlined_jsframe_index; 3102 has_adapted_arguments_(false) {}
3375 int number_of_slots = -1; // Number of slots inside our frame (yet unknown) 3103
3376 while (number_of_slots != 0) { 3104
3377 opcode = static_cast<Translation::Opcode>(it.Next()); 3105 void TranslatedState::Init(Address input_frame_pointer,
3378 bool processed = false; 3106 JSFunction* input_frame_function,
3379 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) { 3107 TranslationIterator* iterator,
3380 if (jsframes_to_skip == 0) { 3108 FixedArray* literal_array, RegisterValues* registers,
3381 CHECK_EQ(Translation::NumberOfOperandsFor(opcode), 2); 3109 FILE* trace_file) {
3382 3110 DCHECK(frames_.empty());
3383 it.Skip(1); // literal id 3111
3384 int height = it.Next(); 3112 isolate_ = literal_array->GetIsolate();
3385 3113 // Read out the 'header' translation.
3386 // Skip the translation command for the receiver. 3114 Translation::Opcode opcode =
3387 it.Skip(Translation::NumberOfOperandsFor( 3115 static_cast<Translation::Opcode>(iterator->Next());
3388 static_cast<Translation::Opcode>(it.Next()))); 3116 CHECK(opcode == Translation::BEGIN);
3389 3117
3390 // We reached the arguments adaptor frame corresponding to the 3118 int count = iterator->Next();
3391 // inlined function in question. Number of arguments is height - 1. 3119 iterator->Next(); // Drop JS frames count.
3392 first_slot_index_ = slot_refs_.length(); 3120
3393 args_length_ = height - 1; 3121 frames_.reserve(count);
3394 number_of_slots = height - 1; 3122
3395 processed = true; 3123 std::stack<int> nested_counts;
3396 } 3124
3397 } else if (opcode == Translation::JS_FRAME) { 3125 // Read the frames
3398 if (jsframes_to_skip == 0) { 3126 for (int i = 0; i < count; i++) {
3399 // Skip over operands to advance to the next opcode. 3127 // Read the frame descriptor.
3400 it.Skip(Translation::NumberOfOperandsFor(opcode)); 3128 frames_.push_back(
3401 3129 CreateNextTranslatedFrame(iterator, literal_array, input_frame_pointer,
3402 // Skip the translation command for the receiver. 3130 input_frame_function, trace_file));
3403 it.Skip(Translation::NumberOfOperandsFor( 3131 TranslatedFrame& frame = frames_.back();
3404 static_cast<Translation::Opcode>(it.Next()))); 3132
3405 3133 // Read the values.
3406 // We reached the frame corresponding to the inlined function 3134 int values_to_process = frame.GetValueCount();
3407 // in question. Process the translation commands for the 3135 while (values_to_process > 0 || !nested_counts.empty()) {
3408 // arguments. Number of arguments is equal to the number of 3136 if (trace_file != nullptr) {
3409 // format parameter count. 3137 if (nested_counts.empty()) {
3410 first_slot_index_ = slot_refs_.length(); 3138 // For top level values, print the value number.
3411 args_length_ = formal_parameter_count; 3139 PrintF(trace_file, " %3i: ",
3412 number_of_slots = formal_parameter_count; 3140 frame.GetValueCount() - values_to_process);
3413 processed = true; 3141 } else {
3414 } 3142 // Take care of indenting for nested values.
3415 jsframes_to_skip--; 3143 PrintF(trace_file, " ");
3416 } else if (opcode != Translation::BEGIN && 3144 for (size_t j = 0; j < nested_counts.size(); j++) {
3417 opcode != Translation::CONSTRUCT_STUB_FRAME && 3145 PrintF(trace_file, " ");
3418 opcode != Translation::GETTER_STUB_FRAME && 3146 }
3419 opcode != Translation::SETTER_STUB_FRAME &&
3420 opcode != Translation::COMPILED_STUB_FRAME) {
3421 slot_refs_.Add(ComputeSlotForNextArgument(opcode, &it, data, frame));
3422
3423 if (first_slot_index_ >= 0) {
3424 // We have found the beginning of our frame -> make sure we count
3425 // the nested slots of captured objects
3426 number_of_slots--;
3427 SlotRef& slot = slot_refs_.last();
3428 CHECK_NE(slot.Representation(), SlotRef::ARGUMENTS_OBJECT);
3429 number_of_slots += slot.GetChildrenCount();
3430 if (slot.Representation() == SlotRef::DEFERRED_OBJECT ||
3431 slot.Representation() == SlotRef::DUPLICATE_OBJECT) {
3432 should_deoptimize_ = true;
3433 } 3147 }
3434 } 3148 }
3435 3149
3436 processed = true; 3150 TranslatedValue value = CreateNextTranslatedValue(
3437 } 3151 i, static_cast<int>(frame.values_.size()), iterator, literal_array,
3438 if (!processed) { 3152 input_frame_pointer, registers, trace_file);
3439 // Skip over operands to advance to the next opcode. 3153 frame.Add(value);
3440 it.Skip(Translation::NumberOfOperandsFor(opcode)); 3154
3441 } 3155 if (trace_file != nullptr) {
3442 } 3156 PrintF(trace_file, "\n");
3443 if (should_deoptimize_) { 3157 }
3444 List<JSFunction*> functions(2); 3158
3445 frame->GetFunctions(&functions); 3159 // Update the value count and resolve the nesting.
3446 Deoptimizer::DeoptimizeFunction(functions[0]); 3160 values_to_process--;
3447 } 3161 int children_count = value.GetChildrenCount();
3448 } 3162 if (children_count > 0) {
3449 3163 nested_counts.push(values_to_process);
3450 3164 values_to_process = children_count;
3451 Handle<Object> SlotRef::GetValue(Isolate* isolate) { 3165 } else {
3452 switch (representation_) { 3166 while (values_to_process == 0 && !nested_counts.empty()) {
3453 case TAGGED: { 3167 values_to_process = nested_counts.top();
3454 Handle<Object> value(Memory::Object_at(addr_), isolate); 3168 nested_counts.pop();
3169 }
3170 }
3171 }
3172 }
3173
3174 CHECK(!iterator->HasNext() ||
3175 static_cast<Translation::Opcode>(iterator->Next()) ==
3176 Translation::BEGIN);
3177 }
3178
3179
3180 void TranslatedState::Prepare(bool has_adapted_arguments,
3181 Address stack_frame_pointer) {
3182 for (auto& frame : frames_) {
3183 frame.Handlify(isolate_);
3184 }
3185
3186 stack_frame_pointer_ = stack_frame_pointer;
3187 has_adapted_arguments_ = has_adapted_arguments;
3188
3189 UpdateFromPreviouslyMaterializedObjects();
3190 }
3191
3192
3193 Handle<Object> TranslatedState::MaterializeAt(int frame_index,
3194 int* value_index) {
3195 TranslatedFrame* frame = &(frames_[frame_index]);
3196 DCHECK(static_cast<size_t>(*value_index) < frame->values_.size());
3197
3198 TranslatedValue* slot = &(frame->values_[*value_index]);
3199 (*value_index)++;
3200
3201 switch (slot->kind()) {
3202 case TranslatedValue::TAGGED:
3203 case TranslatedValue::INT32:
3204 case TranslatedValue::UINT32:
3205 case TranslatedValue::BOOLBIT:
3206 case TranslatedValue::DOUBLE: {
3207 slot->MaterializeSimple();
3208 Handle<Object> value = slot->GetValue();
3455 if (value->IsMutableHeapNumber()) { 3209 if (value->IsMutableHeapNumber()) {
3456 HeapNumber::cast(*value)->set_map(isolate->heap()->heap_number_map()); 3210 HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
3457 } 3211 }
3458 return value; 3212 return value;
3459 } 3213 }
3460 3214
3461 case INT32: { 3215 case TranslatedValue::ARGUMENTS_OBJECT: {
3462 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT 3216 int length = slot->GetChildrenCount();
3463 int value = Memory::int32_at(addr_ + kIntSize); 3217 Handle<JSObject> arguments;
3464 #else 3218 if (GetAdaptedArguments(&arguments, frame_index)) {
3465 int value = Memory::int32_at(addr_); 3219 // Store the materialized object and consume the nested values.
3466 #endif 3220 for (int i = 0; i < length; ++i) {
3467 if (Smi::IsValid(value)) { 3221 MaterializeAt(frame_index, value_index);
3468 return Handle<Object>(Smi::FromInt(value), isolate); 3222 }
3469 } else { 3223 } else {
3470 return isolate->factory()->NewNumberFromInt(value); 3224 Handle<JSFunction> function = frame->function();
3471 } 3225 arguments = isolate_->factory()->NewArgumentsObject(function, length);
3472 } 3226 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3473 3227 DCHECK_EQ(array->length(), length);
3474 case UINT32: { 3228 arguments->set_elements(*array);
3475 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT 3229 for (int i = 0; i < length; ++i) {
3476 uint32_t value = Memory::uint32_at(addr_ + kIntSize); 3230 Handle<Object> value = MaterializeAt(frame_index, value_index);
3477 #else 3231 array->set(i, *value);
3478 uint32_t value = Memory::uint32_at(addr_); 3232 }
3479 #endif 3233 }
3480 if (value <= static_cast<uint32_t>(Smi::kMaxValue)) { 3234 slot->value_ = arguments;
3481 return Handle<Object>(Smi::FromInt(static_cast<int>(value)), isolate); 3235 return arguments;
3482 } else { 3236 }
3483 return isolate->factory()->NewNumber(static_cast<double>(value)); 3237 case TranslatedValue::DEFERRED_OBJECT: {
3484 } 3238 int length = slot->GetChildrenCount();
3485 } 3239
3486 3240 // The map must be a tagged object.
3487 case BOOLBIT: { 3241 CHECK(frame->values_[*value_index].kind() == TranslatedValue::TAGGED);
3488 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT 3242
3489 uint32_t value = Memory::uint32_at(addr_ + kIntSize); 3243 Handle<Object> result;
3490 #else 3244 if (slot->value_.ToHandle(&result)) {
3491 uint32_t value = Memory::uint32_at(addr_); 3245 // This has been previously materialized, return the previous value.
3492 #endif 3246 // We still need to skip all the nested objects.
3493 if (value == 0) { 3247 for (int i = 0; i < length; i++) {
3494 return isolate->factory()->false_value(); 3248 MaterializeAt(frame_index, value_index);
3495 } else { 3249 }
3496 DCHECK_EQ(1U, value); 3250
3497 return isolate->factory()->true_value(); 3251 return result;
3498 } 3252 }
3499 } 3253
3500 3254 Handle<Object> map_object = MaterializeAt(frame_index, value_index);
3501 case DOUBLE: { 3255 Handle<Map> map =
3502 double value = read_double_value(addr_); 3256 Map::GeneralizeAllFieldRepresentations(Handle<Map>::cast(map_object));
3503 return isolate->factory()->NewNumber(value);
3504 }
3505
3506 case LITERAL:
3507 return literal_;
3508
3509 default:
3510 FATAL("We should never get here - unexpected deopt info.");
3511 return Handle<Object>::null();
3512 }
3513 }
3514
3515
3516 void SlotRefValueBuilder::Prepare(Isolate* isolate) {
3517 MaterializedObjectStore* materialized_store =
3518 isolate->materialized_object_store();
3519 previously_materialized_objects_ = materialized_store->Get(stack_frame_id_);
3520 prev_materialized_count_ = previously_materialized_objects_.is_null()
3521 ? 0 : previously_materialized_objects_->length();
3522
3523 // Skip any materialized objects of the inlined "parent" frames.
3524 // (Note that we still need to materialize them because they might be
3525 // referred to as duplicated objects.)
3526 while (current_slot_ < first_slot_index_) {
3527 GetNext(isolate, 0);
3528 }
3529 CHECK_EQ(current_slot_, first_slot_index_);
3530 }
3531
3532
3533 Handle<Object> SlotRefValueBuilder::GetPreviouslyMaterialized(
3534 Isolate* isolate, int length) {
3535 int object_index = materialized_objects_.length();
3536 Handle<Object> return_value = Handle<Object>(
3537 previously_materialized_objects_->get(object_index), isolate);
3538 materialized_objects_.Add(return_value);
3539
3540 // Now need to skip all the nested objects (and possibly read them from
3541 // the materialization store, too).
3542 for (int i = 0; i < length; i++) {
3543 SlotRef& slot = slot_refs_[current_slot_];
3544 current_slot_++;
3545
3546 // We need to read all the nested objects - add them to the
3547 // number of objects we need to process.
3548 length += slot.GetChildrenCount();
3549
3550 // Put the nested deferred/duplicate objects into our materialization
3551 // array.
3552 if (slot.Representation() == SlotRef::DEFERRED_OBJECT ||
3553 slot.Representation() == SlotRef::DUPLICATE_OBJECT) {
3554 int nested_object_index = materialized_objects_.length();
3555 Handle<Object> nested_object = Handle<Object>(
3556 previously_materialized_objects_->get(nested_object_index),
3557 isolate);
3558 materialized_objects_.Add(nested_object);
3559 }
3560 }
3561
3562 return return_value;
3563 }
3564
3565
3566 Handle<Object> SlotRefValueBuilder::GetNext(Isolate* isolate, int lvl) {
3567 SlotRef& slot = slot_refs_[current_slot_];
3568 current_slot_++;
3569 switch (slot.Representation()) {
3570 case SlotRef::TAGGED:
3571 case SlotRef::INT32:
3572 case SlotRef::UINT32:
3573 case SlotRef::BOOLBIT:
3574 case SlotRef::DOUBLE:
3575 case SlotRef::LITERAL:
3576 return slot.GetValue(isolate);
3577
3578 case SlotRef::ARGUMENTS_OBJECT: {
3579 // We should never need to materialize an arguments object,
3580 // but we still need to put something into the array
3581 // so that the indexing is consistent.
3582 materialized_objects_.Add(isolate->factory()->undefined_value());
3583 int length = slot.GetChildrenCount();
3584 for (int i = 0; i < length; ++i) {
3585 // We don't need the argument, just ignore it
3586 GetNext(isolate, lvl + 1);
3587 }
3588 return isolate->factory()->undefined_value();
3589 }
3590 case SlotRef::DEFERRED_OBJECT: {
3591 int length = slot.GetChildrenCount();
3592 CHECK(slot_refs_[current_slot_].Representation() == SlotRef::LITERAL ||
3593 slot_refs_[current_slot_].Representation() == SlotRef::TAGGED);
3594
3595 int object_index = materialized_objects_.length();
3596 if (object_index < prev_materialized_count_) {
3597 return GetPreviouslyMaterialized(isolate, length);
3598 }
3599
3600 Handle<Object> map_object = slot_refs_[current_slot_].GetValue(isolate);
3601 Handle<Map> map = Map::GeneralizeAllFieldRepresentations(
3602 Handle<Map>::cast(map_object));
3603 current_slot_++;
3604 // TODO(jarin) this should be unified with the code in
3605 // Deoptimizer::MaterializeNextHeapObject()
3606 switch (map->instance_type()) { 3257 switch (map->instance_type()) {
3607 case MUTABLE_HEAP_NUMBER_TYPE: 3258 case MUTABLE_HEAP_NUMBER_TYPE:
3608 case HEAP_NUMBER_TYPE: { 3259 case HEAP_NUMBER_TYPE: {
3609 // Reuse the HeapNumber value directly as it is already properly 3260 // Reuse the HeapNumber value directly as it is already properly
3610 // tagged and skip materializing the HeapNumber explicitly. 3261 // tagged and skip materializing the HeapNumber explicitly.
3611 Handle<Object> object = GetNext(isolate, lvl + 1); 3262 Handle<Object> object = MaterializeAt(frame_index, value_index);
3612 materialized_objects_.Add(object); 3263 slot->value_ = object;
3613 // On 32-bit architectures, there is an extra slot there because 3264 // On 32-bit architectures, there is an extra slot there because
3614 // the escape analysis calculates the number of slots as 3265 // the escape analysis calculates the number of slots as
3615 // object-size/pointer-size. To account for this, we read out 3266 // object-size/pointer-size. To account for this, we read out
3616 // any extra slots. 3267 // any extra slots.
3617 for (int i = 0; i < length - 2; i++) { 3268 for (int i = 0; i < length - 2; i++) {
3618 GetNext(isolate, lvl + 1); 3269 MaterializeAt(frame_index, value_index);
3619 } 3270 }
3620 return object; 3271 return object;
3621 } 3272 }
3622 case JS_OBJECT_TYPE: { 3273 case JS_OBJECT_TYPE: {
3623 Handle<JSObject> object = 3274 Handle<JSObject> object =
3624 isolate->factory()->NewJSObjectFromMap(map, NOT_TENURED, false); 3275 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
3625 materialized_objects_.Add(object); 3276 slot->value_ = object;
3626 Handle<Object> properties = GetNext(isolate, lvl + 1); 3277 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3627 Handle<Object> elements = GetNext(isolate, lvl + 1); 3278 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3628 object->set_properties(FixedArray::cast(*properties)); 3279 object->set_properties(FixedArray::cast(*properties));
3629 object->set_elements(FixedArrayBase::cast(*elements)); 3280 object->set_elements(FixedArrayBase::cast(*elements));
3630 for (int i = 0; i < length - 3; ++i) { 3281 for (int i = 0; i < length - 3; ++i) {
3631 Handle<Object> value = GetNext(isolate, lvl + 1); 3282 Handle<Object> value = MaterializeAt(frame_index, value_index);
3632 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i); 3283 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3633 object->FastPropertyAtPut(index, *value); 3284 object->FastPropertyAtPut(index, *value);
3634 } 3285 }
3635 return object; 3286 return object;
3636 } 3287 }
3637 case JS_ARRAY_TYPE: { 3288 case JS_ARRAY_TYPE: {
3638 Handle<JSArray> object = 3289 Handle<JSArray> object =
3639 isolate->factory()->NewJSArray(0, map->elements_kind()); 3290 isolate_->factory()->NewJSArray(0, map->elements_kind());
3640 materialized_objects_.Add(object); 3291 slot->value_ = object;
3641 Handle<Object> properties = GetNext(isolate, lvl + 1); 3292 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3642 Handle<Object> elements = GetNext(isolate, lvl + 1); 3293 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3643 Handle<Object> length = GetNext(isolate, lvl + 1); 3294 Handle<Object> length = MaterializeAt(frame_index, value_index);
3644 object->set_properties(FixedArray::cast(*properties)); 3295 object->set_properties(FixedArray::cast(*properties));
3645 object->set_elements(FixedArrayBase::cast(*elements)); 3296 object->set_elements(FixedArrayBase::cast(*elements));
3646 object->set_length(*length); 3297 object->set_length(*length);
3647 return object; 3298 return object;
3648 } 3299 }
3649 default: 3300 default:
3650 PrintF(stderr, 3301 PrintF(stderr, "[couldn't handle instance type %d]\n",
3651 "[couldn't handle instance type %d]\n", map->instance_type()); 3302 map->instance_type());
3652 UNREACHABLE(); 3303 FATAL("unreachable");
3653 break; 3304 return Handle<Object>::null();
3654 } 3305 }
3655 UNREACHABLE(); 3306 UNREACHABLE();
3656 break; 3307 break;
3657 } 3308 }
3658 3309
3659 case SlotRef::DUPLICATE_OBJECT: { 3310 case TranslatedValue::DUPLICATE_OBJECT: {
3660 int object_index = slot.DuplicateObjectId(); 3311 int object_index = slot->ObjectIndex();
3661 Handle<Object> object = materialized_objects_[object_index]; 3312 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3662 materialized_objects_.Add(object); 3313
3314 // Make sure the duplicate is refering to a previous object.
3315 DCHECK(pos.frame_index_ < frame_index ||
3316 (pos.frame_index_ == frame_index &&
3317 pos.value_index_ < *value_index - 1));
3318
3319 Handle<Object> object =
3320 frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
3321
3322 // The object should have a (non-sentinel) value.
3323 DCHECK(!object.is_null() &&
3324 !object.is_identical_to(isolate_->factory()->arguments_marker()));
3325
3326 slot->value_ = object;
3663 return object; 3327 return object;
3664 } 3328 }
3665 default: 3329
3330 case TranslatedValue::UNKNOWN:
3666 UNREACHABLE(); 3331 UNREACHABLE();
3667 break; 3332 break;
3668 } 3333 }
3669 3334
3670 FATAL("We should never get here - unexpected deopt slot kind."); 3335 FATAL("We should never get here - unexpected deopt slot kind.");
3671 return Handle<Object>::null(); 3336 return Handle<Object>::null();
3672 } 3337 }
3673 3338
3674 3339
3675 void SlotRefValueBuilder::Finish(Isolate* isolate) { 3340 Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
3676 // We should have processed all the slots 3341 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3677 CHECK_EQ(slot_refs_.length(), current_slot_); 3342 return MaterializeAt(pos.frame_index_, &(pos.value_index_));
3343 }
3678 3344
3679 if (should_deoptimize_ && 3345
3680 materialized_objects_.length() > prev_materialized_count_) { 3346 bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result,
3681 // We have materialized some new objects and they might be accessible 3347 int frame_index) {
3682 // from the arguments object, so we have to store them 3348 if (frame_index == 0) {
3683 // to prevent duplicate materialization. 3349 // Top level frame -> we need to go to the parent frame on the stack.
3684 Handle<FixedArray> array = isolate->factory()->NewFixedArray( 3350 if (!has_adapted_arguments_) return false;
3685 materialized_objects_.length()); 3351
3686 for (int i = 0; i < materialized_objects_.length(); i++) { 3352 // This is top level frame, so we need to go to the stack to get
3687 array->set(i, *(materialized_objects_.at(i))); 3353 // this function's argument. (Note that this relies on not inlining
3354 // recursive functions!)
3355 Handle<JSFunction> function = frames_[frame_index].function();
3356 *result = Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
3357 return true;
3358 } else {
3359 TranslatedFrame* previous_frame = &(frames_[frame_index]);
3360 if (previous_frame->kind() != TranslatedFrame::ArgumentsAdaptor) {
3361 return false;
3688 } 3362 }
3689 isolate->materialized_object_store()->Set(stack_frame_id_, array); 3363 // We get the adapted arguments from the parent translation.
3364 int length = previous_frame->GetValueCount();
3365 Handle<JSFunction> function = previous_frame->function();
3366 Handle<JSObject> arguments =
3367 isolate_->factory()->NewArgumentsObject(function, length);
3368 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3369 arguments->set_elements(*array);
3370 TranslatedFrame::ValueIterator arg_iterator = previous_frame->begin();
3371 for (int i = 0; i < length; ++i) {
3372 Handle<Object> value = arg_iterator->GetValue();
3373 array->set(i, *value);
3374 arg_iterator++;
3375 }
3376 CHECK(arg_iterator == previous_frame->end());
3377 *result = arguments;
3378 return true;
3690 } 3379 }
3691 } 3380 }
3692 3381
3693 3382
3694 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { 3383 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3695 int index = StackIdToIndex(fp); 3384 int jsframe_index, int* args_count) {
3696 if (index == -1) { 3385 for (size_t i = 0; i < frames_.size(); i++) {
3697 return Handle<FixedArray>::null(); 3386 if (frames_[i].kind() == TranslatedFrame::Function) {
3387 if (jsframe_index > 0) {
3388 jsframe_index--;
3389 } else {
3390 // We have the JS function frame, now check if it has arguments adaptor.
3391 if (i > 0 &&
3392 frames_[i - 1].kind() == TranslatedFrame::ArgumentsAdaptor) {
3393 *args_count = frames_[i - 1].height();
3394 return &(frames_[i - 1]);
3395 }
3396 *args_count =
3397 frames_[i].function()->shared()->internal_formal_parameter_count() +
3398 1;
3399 return &(frames_[i]);
3400 }
3401 }
3698 } 3402 }
3699 Handle<FixedArray> array = GetStackEntries(); 3403 return nullptr;
3700 CHECK_GT(array->length(), index);
3701 return Handle<FixedArray>::cast(Handle<Object>(array->get(index),
3702 isolate()));
3703 } 3404 }
3704 3405
3705 3406
3706 void MaterializedObjectStore::Set(Address fp, 3407 void TranslatedState::StoreMaterializedValuesAndDeopt() {
3707 Handle<FixedArray> materialized_objects) { 3408 MaterializedObjectStore* materialized_store =
3708 int index = StackIdToIndex(fp); 3409 isolate_->materialized_object_store();
3709 if (index == -1) { 3410 Handle<FixedArray> previously_materialized_objects =
3710 index = frame_fps_.length(); 3411 materialized_store->Get(stack_frame_pointer_);
3711 frame_fps_.Add(fp); 3412
3413 Handle<Object> marker = isolate_->factory()->arguments_marker();
3414
3415 int length = static_cast<int>(object_positions_.size());
3416 bool new_store = false;
3417 if (previously_materialized_objects.is_null()) {
3418 previously_materialized_objects =
3419 isolate_->factory()->NewFixedArray(length);
3420 for (int i = 0; i < length; i++) {
3421 previously_materialized_objects->set(i, *marker);
3422 }
3423 new_store = true;
3712 } 3424 }
3713 3425
3714 Handle<FixedArray> array = EnsureStackEntries(index + 1); 3426 DCHECK_EQ(length, previously_materialized_objects->length());
3715 array->set(index, *materialized_objects);
3716 }
3717 3427
3428 bool value_changed = false;
3429 for (int i = 0; i < length; i++) {
3430 TranslatedState::ObjectPosition pos = object_positions_[i];
3431 TranslatedValue* value_info =
3432 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3718 3433
3719 bool MaterializedObjectStore::Remove(Address fp) { 3434 DCHECK(value_info->IsMaterializedObject());
3720 int index = StackIdToIndex(fp);
3721 if (index == -1) {
3722 return false;
3723 }
3724 CHECK_GE(index, 0);
3725 3435
3726 frame_fps_.Remove(index); 3436 Handle<Object> value(value_info->GetRawValue(), isolate_);
3727 FixedArray* array = isolate()->heap()->materialized_objects();
3728 CHECK_LT(index, array->length());
3729 for (int i = index; i < frame_fps_.length(); i++) {
3730 array->set(i, array->get(i + 1));
3731 }
3732 array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
3733 return true;
3734 }
3735 3437
3736 3438 if (!value.is_identical_to(marker)) {
3737 int MaterializedObjectStore::StackIdToIndex(Address fp) { 3439 if (previously_materialized_objects->get(i) == *marker) {
3738 for (int i = 0; i < frame_fps_.length(); i++) { 3440 previously_materialized_objects->set(i, *value);
3739 if (frame_fps_[i] == fp) { 3441 value_changed = true;
3740 return i; 3442 } else {
3443 DCHECK(previously_materialized_objects->get(i) == *value);
3444 }
3741 } 3445 }
3742 } 3446 }
3743 return -1; 3447 if (new_store && value_changed) {
3744 } 3448 materialized_store->Set(stack_frame_pointer_,
3745 3449 previously_materialized_objects);
3746 3450 DCHECK(frames_[0].kind() == TranslatedFrame::Function);
3747 Handle<FixedArray> MaterializedObjectStore::GetStackEntries() { 3451 Deoptimizer::DeoptimizeFunction(*(frames_[0].function()));
3748 return Handle<FixedArray>(isolate()->heap()->materialized_objects());
3749 }
3750
3751
3752 Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
3753 Handle<FixedArray> array = GetStackEntries();
3754 if (array->length() >= length) {
3755 return array;
3756 }
3757
3758 int new_length = length > 10 ? length : 10;
3759 if (new_length < 2 * array->length()) {
3760 new_length = 2 * array->length();
3761 }
3762
3763 Handle<FixedArray> new_array =
3764 isolate()->factory()->NewFixedArray(new_length, TENURED);
3765 for (int i = 0; i < array->length(); i++) {
3766 new_array->set(i, array->get(i));
3767 }
3768 for (int i = array->length(); i < length; i++) {
3769 new_array->set(i, isolate()->heap()->undefined_value());
3770 }
3771 isolate()->heap()->public_set_materialized_objects(*new_array);
3772 return new_array;
3773 }
3774
3775
3776 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
3777 int frame_index,
3778 bool has_arguments_adaptor,
3779 bool has_construct_stub) {
3780 FrameDescription* output_frame = deoptimizer->output_[frame_index];
3781 function_ = output_frame->GetFunction();
3782 context_ = reinterpret_cast<Object*>(output_frame->GetContext());
3783 has_construct_stub_ = has_construct_stub;
3784 expression_count_ = output_frame->GetExpressionCount();
3785 expression_stack_ = new Object*[expression_count_];
3786 // Get the source position using the unoptimized code.
3787 Address pc = reinterpret_cast<Address>(output_frame->GetPc());
3788 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc));
3789 source_position_ = code->SourcePosition(pc);
3790
3791 for (int i = 0; i < expression_count_; i++) {
3792 SetExpression(i, output_frame->GetExpression(i));
3793 }
3794
3795 if (has_arguments_adaptor) {
3796 output_frame = deoptimizer->output_[frame_index - 1];
3797 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
3798 }
3799
3800 parameters_count_ = output_frame->ComputeParametersCount();
3801 parameters_ = new Object*[parameters_count_];
3802 for (int i = 0; i < parameters_count_; i++) {
3803 SetParameter(i, output_frame->GetParameter(i));
3804 } 3452 }
3805 } 3453 }
3806 3454
3807 3455
3808 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { 3456 void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
3809 delete[] expression_stack_; 3457 MaterializedObjectStore* materialized_store =
3810 delete[] parameters_; 3458 isolate_->materialized_object_store();
3459 Handle<FixedArray> previously_materialized_objects =
3460 materialized_store->Get(stack_frame_pointer_);
3461
3462 // If we have no previously materialized objects, there is nothing to do.
3463 if (previously_materialized_objects.is_null()) return;
3464
3465 Handle<Object> marker = isolate_->factory()->arguments_marker();
3466
3467 int length = static_cast<int>(object_positions_.size());
3468 DCHECK_EQ(length, previously_materialized_objects->length());
3469
3470 for (int i = 0; i < length; i++) {
3471 // For a previously materialized objects, inject their value into the
3472 // translated values.
3473 if (previously_materialized_objects->get(i) != *marker) {
3474 TranslatedState::ObjectPosition pos = object_positions_[i];
3475 TranslatedValue* value_info =
3476 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3477 DCHECK(value_info->IsMaterializedObject());
3478
3479 value_info->value_ =
3480 Handle<Object>(previously_materialized_objects->get(i), isolate_);
3481 }
3482 }
3811 } 3483 }
3812 3484
3813
3814 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
3815 v->VisitPointer(bit_cast<Object**>(&function_));
3816 v->VisitPointer(&context_);
3817 v->VisitPointers(parameters_, parameters_ + parameters_count_);
3818 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
3819 }
3820
3821
3822 const char* Deoptimizer::GetDeoptReason(DeoptReason deopt_reason) {
3823 DCHECK(deopt_reason < kLastDeoptReason);
3824 #define DEOPT_MESSAGES_TEXTS(C, T) T,
3825 static const char* deopt_messages_[] = {
3826 DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_TEXTS)};
3827 #undef DEOPT_MESSAGES_TEXTS
3828 return deopt_messages_[deopt_reason];
3829 }
3830
3831
3832 Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
3833 SourcePosition last_position = SourcePosition::Unknown();
3834 Deoptimizer::DeoptReason last_reason = Deoptimizer::kNoReason;
3835 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
3836 RelocInfo::ModeMask(RelocInfo::POSITION);
3837 for (RelocIterator it(code, mask); !it.done(); it.next()) {
3838 RelocInfo* info = it.rinfo();
3839 if (info->pc() >= pc) return DeoptInfo(last_position, NULL, last_reason);
3840 if (info->rmode() == RelocInfo::POSITION) {
3841 int raw_position = static_cast<int>(info->data());
3842 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
3843 : SourcePosition::Unknown();
3844 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
3845 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
3846 }
3847 }
3848 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
3849 }
3850 } // namespace internal 3485 } // namespace internal
3851 } // namespace v8 3486 } // namespace v8
OLDNEW
« src/deoptimizer.h ('K') | « src/deoptimizer.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698