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

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: Fix too restrictive check 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
« no previous file with comments | « src/deoptimizer.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/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), 549 trace_scope_(nullptr) {
568 deferred_objects_double_values_(0),
569 deferred_objects_(0),
570 deferred_heap_numbers_(0),
571 jsframe_functions_(0),
572 jsframe_has_adapted_arguments_(0),
573 materialized_values_(NULL),
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 550 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
579 // indicating an internal frame. 551 // indicating an internal frame.
580 if (function->IsSmi()) { 552 if (function->IsSmi()) {
581 function = NULL; 553 function = nullptr;
582 } 554 }
583 DCHECK(from != NULL); 555 DCHECK(from != nullptr);
584 if (function != NULL && function->IsOptimized()) { 556 if (function != nullptr && function->IsOptimized()) {
585 function->shared()->increment_deopt_count(); 557 function->shared()->increment_deopt_count();
586 if (bailout_type_ == Deoptimizer::SOFT) { 558 if (bailout_type_ == Deoptimizer::SOFT) {
587 isolate->counters()->soft_deopts_executed()->Increment(); 559 isolate->counters()->soft_deopts_executed()->Increment();
588 // Soft deopts shouldn't count against the overall re-optimization count 560 // Soft deopts shouldn't count against the overall re-optimization count
589 // that can eventually lead to disabling optimization for a function. 561 // that can eventually lead to disabling optimization for a function.
590 int opt_count = function->shared()->opt_count(); 562 int opt_count = function->shared()->opt_count();
591 if (opt_count > 0) opt_count--; 563 if (opt_count > 0) opt_count--;
592 function->shared()->set_opt_count(opt_count); 564 function->shared()->set_opt_count(opt_count);
593 } 565 }
594 } 566 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 (compiled_code_->is_hydrogen_stub())) { 745 (compiled_code_->is_hydrogen_stub())) {
774 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_); 746 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
775 } 747 }
776 } 748 }
777 749
778 BailoutId node_id = input_data->AstId(bailout_id_); 750 BailoutId node_id = input_data->AstId(bailout_id_);
779 ByteArray* translations = input_data->TranslationByteArray(); 751 ByteArray* translations = input_data->TranslationByteArray();
780 unsigned translation_index = 752 unsigned translation_index =
781 input_data->TranslationIndex(bailout_id_)->value(); 753 input_data->TranslationIndex(bailout_id_)->value();
782 754
755 TranslationIterator state_iterator(translations, translation_index);
756 translated_state_.Init(
757 input_->GetFramePointerAddress(), function_, &state_iterator,
758 input_data->LiteralArray(), input_->GetRegisterValues(),
759 trace_scope_ == nullptr ? nullptr : trace_scope_->file());
760
783 // Do the input frame to output frame(s) translation. 761 // Do the input frame to output frame(s) translation.
784 TranslationIterator iterator(translations, translation_index); 762 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); 763 DCHECK(output_ == NULL);
794 output_ = new FrameDescription*[count]; 764 output_ = new FrameDescription*[count];
795 for (int i = 0; i < count; ++i) { 765 for (size_t i = 0; i < count; ++i) {
796 output_[i] = NULL; 766 output_[i] = NULL;
797 } 767 }
798 output_count_ = count; 768 output_count_ = static_cast<int>(count);
799 769
800 Register fp_reg = JavaScriptFrame::fp_register(); 770 Register fp_reg = JavaScriptFrame::fp_register();
801 stack_fp_ = reinterpret_cast<Address>( 771 stack_fp_ = reinterpret_cast<Address>(
802 input_->GetRegister(fp_reg.code()) + 772 input_->GetRegister(fp_reg.code()) +
803 has_alignment_padding_ * kPointerSize); 773 has_alignment_padding_ * kPointerSize);
804 774
805 // Translate each output frame. 775 // Translate each output frame.
806 for (int i = 0; i < count; ++i) { 776 for (size_t i = 0; i < count; ++i) {
807 // Read the ast node id, function, and frame height for this output frame. 777 // Read the ast node id, function, and frame height for this output frame.
808 Translation::Opcode opcode = 778 int frame_index = static_cast<int>(i);
809 static_cast<Translation::Opcode>(iterator.Next()); 779 switch (translated_state_.frames()[i].kind()) {
810 switch (opcode) { 780 case TranslatedFrame::kFunction:
811 case Translation::JS_FRAME: 781 DoComputeJSFrame(nullptr, frame_index);
812 DoComputeJSFrame(&iterator, i);
813 jsframe_count_++; 782 jsframe_count_++;
814 break; 783 break;
815 case Translation::ARGUMENTS_ADAPTOR_FRAME: 784 case TranslatedFrame::kArgumentsAdaptor:
816 DoComputeArgumentsAdaptorFrame(&iterator, i); 785 DoComputeArgumentsAdaptorFrame(nullptr, frame_index);
817 break; 786 break;
818 case Translation::CONSTRUCT_STUB_FRAME: 787 case TranslatedFrame::kConstructStub:
819 DoComputeConstructStubFrame(&iterator, i); 788 DoComputeConstructStubFrame(nullptr, frame_index);
820 break; 789 break;
821 case Translation::GETTER_STUB_FRAME: 790 case TranslatedFrame::kGetter:
822 DoComputeAccessorStubFrame(&iterator, i, false); 791 DoComputeAccessorStubFrame(nullptr, frame_index, false);
823 break; 792 break;
824 case Translation::SETTER_STUB_FRAME: 793 case TranslatedFrame::kSetter:
825 DoComputeAccessorStubFrame(&iterator, i, true); 794 DoComputeAccessorStubFrame(nullptr, frame_index, true);
826 break; 795 break;
827 case Translation::COMPILED_STUB_FRAME: 796 case TranslatedFrame::kCompiledStub:
828 DoComputeCompiledStubFrame(&iterator, i); 797 DoComputeCompiledStubFrame(nullptr, frame_index);
829 break; 798 break;
830 case Translation::BEGIN: 799 case TranslatedFrame::kInvalid:
831 case Translation::REGISTER: 800 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; 801 break;
847 } 802 }
848 } 803 }
849 804
850 // Print some helpful diagnostic information. 805 // Print some helpful diagnostic information.
851 if (trace_scope_ != NULL) { 806 if (trace_scope_ != NULL) {
852 double ms = timer.Elapsed().InMillisecondsF(); 807 double ms = timer.Elapsed().InMillisecondsF();
853 int index = output_count_ - 1; // Index of the topmost frame. 808 int index = output_count_ - 1; // Index of the topmost frame.
854 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", 809 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
855 MessageFor(bailout_type_)); 810 MessageFor(bailout_type_));
856 PrintFunctionName(); 811 PrintFunctionName();
857 PrintF(trace_scope_->file(), 812 PrintF(trace_scope_->file(),
858 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," 813 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
859 " took %0.3f ms]\n", 814 " took %0.3f ms]\n",
860 bailout_id_, 815 bailout_id_,
861 node_id.ToInt(), 816 node_id.ToInt(),
862 output_[index]->GetPc(), 817 output_[index]->GetPc(),
863 FullCodeGenerator::State2String( 818 FullCodeGenerator::State2String(
864 static_cast<FullCodeGenerator::State>( 819 static_cast<FullCodeGenerator::State>(
865 output_[index]->GetState()->value())), 820 output_[index]->GetState()->value())),
866 has_alignment_padding_ ? "with padding" : "no padding", 821 has_alignment_padding_ ? "with padding" : "no padding",
867 ms); 822 ms);
868 } 823 }
869 } 824 }
870 825
871 826
872 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, 827 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
873 int frame_index) { 828 int frame_index) {
874 BailoutId node_id = BailoutId(iterator->Next()); 829 TranslatedFrame* translated_frame =
875 JSFunction* function; 830 &(translated_state_.frames()[frame_index]);
876 if (frame_index != 0) { 831 TranslatedFrame::iterator value_iterator = translated_frame->begin();
877 function = JSFunction::cast(ComputeLiteral(iterator->Next())); 832 int input_index = 0;
878 } else { 833
879 int closure_id = iterator->Next(); 834 BailoutId node_id = translated_frame->node_id();
880 USE(closure_id); 835 JSFunction* function = translated_frame->raw_function();
881 CHECK_EQ(Translation::kSelfLiteralId, closure_id); 836 unsigned height =
882 function = function_; 837 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; 838 unsigned height_in_bytes = height * kPointerSize;
886 if (trace_scope_ != NULL) { 839 if (trace_scope_ != NULL) {
887 PrintF(trace_scope_->file(), " translating "); 840 PrintF(trace_scope_->file(), " translating frame ");
888 function->PrintName(trace_scope_->file()); 841 function->PrintName(trace_scope_->file());
889 PrintF(trace_scope_->file(), 842 PrintF(trace_scope_->file(),
890 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); 843 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
891 } 844 }
892 845
893 // The 'fixed' part of the frame consists of the incoming parameters and 846 // The 'fixed' part of the frame consists of the incoming parameters and
894 // the part described by JavaScriptFrameConstants. 847 // the part described by JavaScriptFrameConstants.
895 unsigned fixed_frame_size = ComputeFixedSize(function); 848 unsigned fixed_frame_size = ComputeFixedSize(function);
896 unsigned input_frame_size = input_->GetFrameSize(); 849 unsigned input_frame_size = input_->GetFrameSize();
897 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 850 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
931 } 884 }
932 output_frame->SetTop(top_address); 885 output_frame->SetTop(top_address);
933 886
934 // Compute the incoming parameter translation. 887 // Compute the incoming parameter translation.
935 int parameter_count = 888 int parameter_count =
936 function->shared()->internal_formal_parameter_count() + 1; 889 function->shared()->internal_formal_parameter_count() + 1;
937 unsigned output_offset = output_frame_size; 890 unsigned output_offset = output_frame_size;
938 unsigned input_offset = input_frame_size; 891 unsigned input_offset = input_frame_size;
939 for (int i = 0; i < parameter_count; ++i) { 892 for (int i = 0; i < parameter_count; ++i) {
940 output_offset -= kPointerSize; 893 output_offset -= kPointerSize;
941 DoTranslateCommand(iterator, frame_index, output_offset); 894 WriteValueToOutput(&value_iterator, &input_index, frame_index,
895 output_offset);
942 } 896 }
943 input_offset -= (parameter_count * kPointerSize); 897 input_offset -= (parameter_count * kPointerSize);
944 898
945 // There are no translation commands for the caller's pc and fp, the 899 // 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 900 // context, and the function. Synthesize their values and set them up
947 // explicitly. 901 // explicitly.
948 // 902 //
949 // The caller's pc for the bottommost output frame is the same as in the 903 // 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 904 // 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 905 // 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 } 965 }
1012 } 966 }
1013 967
1014 // For the bottommost output frame the context can be gotten from the input 968 // 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 969 // 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. 970 // so long as we don't inline functions that need local contexts.
1017 Register context_reg = JavaScriptFrame::context_register(); 971 Register context_reg = JavaScriptFrame::context_register();
1018 output_offset -= kPointerSize; 972 output_offset -= kPointerSize;
1019 input_offset -= kPointerSize; 973 input_offset -= kPointerSize;
1020 // Read the context from the translations. 974 // Read the context from the translations.
1021 DoTranslateCommand(iterator, frame_index, output_offset); 975 WriteValueToOutput(&value_iterator, &input_index, frame_index, output_offset);
1022 value = output_frame->GetFrameSlot(output_offset); 976 value = output_frame->GetFrameSlot(output_offset);
1023 // The context should not be a placeholder for a materialized object. 977 // The context should not be a placeholder for a materialized object.
1024 CHECK(value != 978 CHECK(value !=
1025 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker())); 979 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker()));
1026 if (value == 980 if (value ==
1027 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) { 981 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) {
1028 // If the context was optimized away, just use the context from 982 // If the context was optimized away, just use the context from
1029 // the activation. This should only apply to Crankshaft code. 983 // the activation. This should only apply to Crankshaft code.
1030 CHECK(!compiled_code_->is_turbofanned()); 984 CHECK(!compiled_code_->is_turbofanned());
1031 if (is_bottommost) { 985 if (is_bottommost) {
(...skipping 23 matching lines...) Expand all
1055 if (trace_scope_ != NULL) { 1009 if (trace_scope_ != NULL) {
1056 PrintF(trace_scope_->file(), 1010 PrintF(trace_scope_->file(),
1057 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1011 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1058 V8PRIxPTR "; function\n", 1012 V8PRIxPTR "; function\n",
1059 top_address + output_offset, output_offset, value); 1013 top_address + output_offset, output_offset, value);
1060 } 1014 }
1061 1015
1062 // Translate the rest of the frame. 1016 // Translate the rest of the frame.
1063 for (unsigned i = 0; i < height; ++i) { 1017 for (unsigned i = 0; i < height; ++i) {
1064 output_offset -= kPointerSize; 1018 output_offset -= kPointerSize;
1065 DoTranslateCommand(iterator, frame_index, output_offset); 1019 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1020 output_offset);
1066 } 1021 }
1067 CHECK_EQ(0u, output_offset); 1022 CHECK_EQ(0u, output_offset);
1068 1023
1069 // Compute this frame's PC, state, and continuation. 1024 // Compute this frame's PC, state, and continuation.
1070 Code* non_optimized_code = function->shared()->code(); 1025 Code* non_optimized_code = function->shared()->code();
1071 FixedArray* raw_data = non_optimized_code->deoptimization_data(); 1026 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1072 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 1027 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1073 Address start = non_optimized_code->instruction_start(); 1028 Address start = non_optimized_code->instruction_start();
1074 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 1029 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1075 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 1030 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
(...skipping 28 matching lines...) Expand all
1104 CHECK_EQ(bailout_type_, EAGER); 1059 CHECK_EQ(bailout_type_, EAGER);
1105 } 1060 }
1106 output_frame->SetContinuation( 1061 output_frame->SetContinuation(
1107 reinterpret_cast<intptr_t>(continuation->entry())); 1062 reinterpret_cast<intptr_t>(continuation->entry()));
1108 } 1063 }
1109 } 1064 }
1110 1065
1111 1066
1112 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 1067 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
1113 int frame_index) { 1068 int frame_index) {
1114 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 1069 TranslatedFrame* translated_frame =
1115 unsigned height = iterator->Next(); 1070 &(translated_state_.frames()[frame_index]);
1071 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1072 int input_index = 0;
1073
1074 JSFunction* function = translated_frame->raw_function();
1075 unsigned height = translated_frame->height();
1116 unsigned height_in_bytes = height * kPointerSize; 1076 unsigned height_in_bytes = height * kPointerSize;
1117 if (trace_scope_ != NULL) { 1077 if (trace_scope_ != NULL) {
1118 PrintF(trace_scope_->file(), 1078 PrintF(trace_scope_->file(),
1119 " translating arguments adaptor => height=%d\n", height_in_bytes); 1079 " translating arguments adaptor => height=%d\n", height_in_bytes);
1120 } 1080 }
1121 1081
1122 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; 1082 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
1123 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1083 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1124 1084
1125 // Allocate and store the output frame description. 1085 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1136 // frame's top and this frame's size. 1096 // frame's top and this frame's size.
1137 intptr_t top_address; 1097 intptr_t top_address;
1138 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1098 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1139 output_frame->SetTop(top_address); 1099 output_frame->SetTop(top_address);
1140 1100
1141 // Compute the incoming parameter translation. 1101 // Compute the incoming parameter translation.
1142 int parameter_count = height; 1102 int parameter_count = height;
1143 unsigned output_offset = output_frame_size; 1103 unsigned output_offset = output_frame_size;
1144 for (int i = 0; i < parameter_count; ++i) { 1104 for (int i = 0; i < parameter_count; ++i) {
1145 output_offset -= kPointerSize; 1105 output_offset -= kPointerSize;
1146 DoTranslateCommand(iterator, frame_index, output_offset); 1106 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1107 output_offset);
1147 } 1108 }
1148 1109
1149 // Read caller's PC from the previous frame. 1110 // Read caller's PC from the previous frame.
1150 output_offset -= kPCOnStackSize; 1111 output_offset -= kPCOnStackSize;
1151 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1112 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1152 output_frame->SetCallerPc(output_offset, callers_pc); 1113 output_frame->SetCallerPc(output_offset, callers_pc);
1153 if (trace_scope_ != NULL) { 1114 if (trace_scope_ != NULL) {
1154 PrintF(trace_scope_->file(), 1115 PrintF(trace_scope_->file(),
1155 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1116 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1156 V8PRIxPTR " ; caller's pc\n", 1117 V8PRIxPTR " ; caller's pc\n",
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 if (FLAG_enable_ool_constant_pool) { 1189 if (FLAG_enable_ool_constant_pool) {
1229 intptr_t constant_pool_value = 1190 intptr_t constant_pool_value =
1230 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool()); 1191 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1231 output_frame->SetConstantPool(constant_pool_value); 1192 output_frame->SetConstantPool(constant_pool_value);
1232 } 1193 }
1233 } 1194 }
1234 1195
1235 1196
1236 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, 1197 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
1237 int frame_index) { 1198 int frame_index) {
1199 TranslatedFrame* translated_frame =
1200 &(translated_state_.frames()[frame_index]);
1201 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1202 int input_index = 0;
1203
1238 Builtins* builtins = isolate_->builtins(); 1204 Builtins* builtins = isolate_->builtins();
1239 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); 1205 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
1240 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 1206 JSFunction* function = translated_frame->raw_function();
1241 unsigned height = iterator->Next(); 1207 unsigned height = translated_frame->height();
1242 unsigned height_in_bytes = height * kPointerSize; 1208 unsigned height_in_bytes = height * kPointerSize;
1243 if (trace_scope_ != NULL) { 1209 if (trace_scope_ != NULL) {
1244 PrintF(trace_scope_->file(), 1210 PrintF(trace_scope_->file(),
1245 " translating construct stub => height=%d\n", height_in_bytes); 1211 " translating construct stub => height=%d\n", height_in_bytes);
1246 } 1212 }
1247 1213
1248 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize; 1214 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
1249 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1215 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1250 1216
1251 // Allocate and store the output frame description. 1217 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1262 // frame's top and this frame's size. 1228 // frame's top and this frame's size.
1263 intptr_t top_address; 1229 intptr_t top_address;
1264 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1230 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1265 output_frame->SetTop(top_address); 1231 output_frame->SetTop(top_address);
1266 1232
1267 // Compute the incoming parameter translation. 1233 // Compute the incoming parameter translation.
1268 int parameter_count = height; 1234 int parameter_count = height;
1269 unsigned output_offset = output_frame_size; 1235 unsigned output_offset = output_frame_size;
1270 for (int i = 0; i < parameter_count; ++i) { 1236 for (int i = 0; i < parameter_count; ++i) {
1271 output_offset -= kPointerSize; 1237 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 1238 // The allocated receiver of a construct stub frame is passed as the
1275 // receiver parameter through the translation. It might be encoding 1239 // receiver parameter through the translation. It might be encoding
1276 // a captured object, patch the slot address for a captured object. 1240 // a captured object, override the slot address for a captured object.
1277 if (i == 0 && deferred_objects_.length() > deferred_object_index) { 1241 WriteValueToOutput(
1278 CHECK(!deferred_objects_[deferred_object_index].is_arguments()); 1242 &value_iterator, &input_index, frame_index, output_offset,
1279 deferred_objects_[deferred_object_index].patch_slot_address(top_address); 1243 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
1280 }
1281 } 1244 }
1282 1245
1283 // Read caller's PC from the previous frame. 1246 // Read caller's PC from the previous frame.
1284 output_offset -= kPCOnStackSize; 1247 output_offset -= kPCOnStackSize;
1285 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1248 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1286 output_frame->SetCallerPc(output_offset, callers_pc); 1249 output_frame->SetCallerPc(output_offset, callers_pc);
1287 if (trace_scope_ != NULL) { 1250 if (trace_scope_ != NULL) {
1288 PrintF(trace_scope_->file(), 1251 PrintF(trace_scope_->file(),
1289 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1252 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1290 V8PRIxPTR " ; caller's pc\n", 1253 V8PRIxPTR " ; caller's pc\n",
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 intptr_t constant_pool_value = 1359 intptr_t constant_pool_value =
1397 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); 1360 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1398 output_frame->SetConstantPool(constant_pool_value); 1361 output_frame->SetConstantPool(constant_pool_value);
1399 } 1362 }
1400 } 1363 }
1401 1364
1402 1365
1403 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, 1366 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
1404 int frame_index, 1367 int frame_index,
1405 bool is_setter_stub_frame) { 1368 bool is_setter_stub_frame) {
1406 JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next())); 1369 TranslatedFrame* translated_frame =
1370 &(translated_state_.frames()[frame_index]);
1371 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1372 int input_index = 0;
1373
1374 JSFunction* accessor = translated_frame->raw_function();
1407 // The receiver (and the implicit return value, if any) are expected in 1375 // 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 1376 // 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. 1377 // frame. This means that we have to use a height of 0.
1410 unsigned height = 0; 1378 unsigned height = 0;
1411 unsigned height_in_bytes = height * kPointerSize; 1379 unsigned height_in_bytes = height * kPointerSize;
1412 const char* kind = is_setter_stub_frame ? "setter" : "getter"; 1380 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1413 if (trace_scope_ != NULL) { 1381 if (trace_scope_ != NULL) {
1414 PrintF(trace_scope_->file(), 1382 PrintF(trace_scope_->file(),
1415 " translating %s stub => height=%u\n", kind, height_in_bytes); 1383 " translating %s stub => height=%u\n", kind, height_in_bytes);
1416 } 1384 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 value = reinterpret_cast<intptr_t>(accessor_stub); 1478 value = reinterpret_cast<intptr_t>(accessor_stub);
1511 output_frame->SetFrameSlot(output_offset, value); 1479 output_frame->SetFrameSlot(output_offset, value);
1512 if (trace_scope_ != NULL) { 1480 if (trace_scope_ != NULL) {
1513 PrintF(trace_scope_->file(), 1481 PrintF(trace_scope_->file(),
1514 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR 1482 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1515 " ; code object\n", 1483 " ; code object\n",
1516 top_address + output_offset, output_offset, value); 1484 top_address + output_offset, output_offset, value);
1517 } 1485 }
1518 1486
1519 // Skip receiver. 1487 // Skip receiver.
1520 DoTranslateObjectAndSkip(iterator); 1488 value_iterator++;
1521 1489
1522 if (is_setter_stub_frame) { 1490 if (is_setter_stub_frame) {
1523 // The implicit return value was part of the artificial setter stub 1491 // The implicit return value was part of the artificial setter stub
1524 // environment. 1492 // environment.
1525 output_offset -= kPointerSize; 1493 output_offset -= kPointerSize;
1526 DoTranslateCommand(iterator, frame_index, output_offset); 1494 WriteValueToOutput(&value_iterator, &input_index, frame_index,
1495 output_offset);
1527 } 1496 }
1528 1497
1529 CHECK_EQ(0u, output_offset); 1498 CHECK_EQ(0u, output_offset);
1530 1499
1531 Smi* offset = is_setter_stub_frame ? 1500 Smi* offset = is_setter_stub_frame ?
1532 isolate_->heap()->setter_stub_deopt_pc_offset() : 1501 isolate_->heap()->setter_stub_deopt_pc_offset() :
1533 isolate_->heap()->getter_stub_deopt_pc_offset(); 1502 isolate_->heap()->getter_stub_deopt_pc_offset();
1534 intptr_t pc = reinterpret_cast<intptr_t>( 1503 intptr_t pc = reinterpret_cast<intptr_t>(
1535 accessor_stub->instruction_start() + offset->value()); 1504 accessor_stub->instruction_start() + offset->value());
1536 output_frame->SetPc(pc); 1505 output_frame->SetPc(pc);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 // and spilled to stack | .... | 1538 // and spilled to stack | .... |
1570 // +-------------------------+ 1539 // +-------------------------+
1571 // | caller stack param n | 1540 // | caller stack param n |
1572 // +-------------------------+<-spreg 1541 // +-------------------------+<-spreg
1573 // reg = number of parameters 1542 // reg = number of parameters
1574 // reg = failure handler address 1543 // reg = failure handler address
1575 // reg = saved frame 1544 // reg = saved frame
1576 // reg = JSFunction context 1545 // reg = JSFunction context
1577 // 1546 //
1578 1547
1548 TranslatedFrame* translated_frame =
1549 &(translated_state_.frames()[frame_index]);
1550 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1551 int input_index = 0;
1552
1579 CHECK(compiled_code_->is_hydrogen_stub()); 1553 CHECK(compiled_code_->is_hydrogen_stub());
1580 int major_key = CodeStub::GetMajorKey(compiled_code_); 1554 int major_key = CodeStub::GetMajorKey(compiled_code_);
1581 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key()); 1555 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1582 1556
1583 // The output frame must have room for all pushed register parameters 1557 // The output frame must have room for all pushed register parameters
1584 // and the standard stack frame slots. Include space for an argument 1558 // and the standard stack frame slots. Include space for an argument
1585 // object to the callee and optionally the space to pass the argument 1559 // object to the callee and optionally the space to pass the argument
1586 // object to the stub failure handler. 1560 // object to the stub failure handler.
1587 int param_count = descriptor.GetEnvironmentParameterCount(); 1561 int param_count = descriptor.GetEnvironmentParameterCount();
1562 CHECK_EQ(translated_frame->height(), param_count);
1588 CHECK_GE(param_count, 0); 1563 CHECK_GE(param_count, 0);
1589 1564
1590 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) + 1565 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) +
1591 kPointerSize; 1566 kPointerSize;
1592 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; 1567 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
1593 int input_frame_size = input_->GetFrameSize(); 1568 int input_frame_size = input_->GetFrameSize();
1594 int output_frame_size = height_in_bytes + fixed_frame_size; 1569 int output_frame_size = height_in_bytes + fixed_frame_size;
1595 if (trace_scope_ != NULL) { 1570 if (trace_scope_ != NULL) {
1596 PrintF(trace_scope_->file(), 1571 PrintF(trace_scope_->file(),
1597 " translating %s => StubFailureTrampolineStub, height=%d\n", 1572 " translating %s => StubFailureTrampolineStub, height=%d\n",
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1725 PrintF(trace_scope_->file(), 1700 PrintF(trace_scope_->file(),
1726 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1701 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1727 V8PRIxPTR " ; args*\n", 1702 V8PRIxPTR " ; args*\n",
1728 top_address + output_frame_offset, output_frame_offset, value); 1703 top_address + output_frame_offset, output_frame_offset, value);
1729 } 1704 }
1730 1705
1731 // Copy the register parameters to the failure frame. 1706 // Copy the register parameters to the failure frame.
1732 int arguments_length_offset = -1; 1707 int arguments_length_offset = -1;
1733 for (int i = 0; i < param_count; ++i) { 1708 for (int i = 0; i < param_count; ++i) {
1734 output_frame_offset -= kPointerSize; 1709 output_frame_offset -= kPointerSize;
1735 DoTranslateCommand(iterator, 0, output_frame_offset); 1710 WriteValueToOutput(&value_iterator, &input_index, 0, output_frame_offset);
1736 1711
1737 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) { 1712 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) {
1738 arguments_length_offset = output_frame_offset; 1713 arguments_length_offset = output_frame_offset;
1739 } 1714 }
1740 } 1715 }
1741 1716
1742 CHECK_EQ(0u, output_frame_offset); 1717 CHECK_EQ(0u, output_frame_offset);
1743 1718
1744 if (!arg_count_known) { 1719 if (!arg_count_known) {
1745 CHECK_GE(arguments_length_offset, 0); 1720 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); 1767 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1793 } 1768 }
1794 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); 1769 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
1795 Code* notify_failure = 1770 Code* notify_failure =
1796 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); 1771 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
1797 output_frame->SetContinuation( 1772 output_frame->SetContinuation(
1798 reinterpret_cast<intptr_t>(notify_failure->entry())); 1773 reinterpret_cast<intptr_t>(notify_failure->entry()));
1799 } 1774 }
1800 1775
1801 1776
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) { 1777 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
1921 DCHECK_NE(DEBUGGER, bailout_type_); 1778 DCHECK_NE(DEBUGGER, bailout_type_);
1922 1779
1923 MaterializedObjectStore* materialized_store = 1780 // Walk to the last JavaScript output frame to find out if it has
1924 isolate_->materialized_object_store(); 1781 // adapted arguments.
1925 previously_materialized_objects_ = materialized_store->Get(stack_fp_);
1926 prev_materialized_count_ = previously_materialized_objects_.is_null() ?
1927 0 : previously_materialized_objects_->length();
1928
1929 // Walk all JavaScript output frames with the given frame iterator.
1930 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { 1782 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
1931 if (frame_index != 0) it->Advance(); 1783 if (frame_index != 0) it->Advance();
1932 JavaScriptFrame* frame = it->frame(); 1784 }
1933 jsframe_functions_.Add(handle(frame->function(), isolate_)); 1785 translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_);
1934 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments()); 1786
1935 } 1787 for (auto& materialization : values_to_materialize_) {
1936 1788 Handle<Object> value = materialization.value_->GetValue();
1937 // Handlify all tagged object values before triggering any allocation. 1789
1938 List<Handle<Object> > values(deferred_objects_tagged_values_.length()); 1790 if (trace_scope_ != nullptr) {
1939 for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) { 1791 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ",
1940 values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_)); 1792 reinterpret_cast<intptr_t>(materialization.output_slot_address_),
1941 } 1793 reinterpret_cast<intptr_t>(*value));
1942 1794 value->ShortPrint(trace_scope_->file());
1943 // Play it safe and clear all unhandlified values before we continue. 1795 PrintF(trace_scope_->file(), "\n");
1944 deferred_objects_tagged_values_.Clear(); 1796 }
1945 1797
1946 // Materialize all heap numbers before looking at arguments because when the 1798 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
1947 // output frames are used to materialize arguments objects later on they need 1799 reinterpret_cast<intptr_t>(*value);
1948 // to already contain valid heap numbers. 1800 }
1949 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { 1801
1950 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; 1802 isolate_->materialized_object_store()->Remove(stack_fp_);
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 } 1803 }
2026 1804
2027 1805
2028 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( 1806 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
2029 Address parameters_top, 1807 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) { 1808 DeoptimizedFrameInfo* info) {
2034 CHECK_EQ(DEBUGGER, bailout_type_); 1809 CHECK_EQ(DEBUGGER, bailout_type_);
2035 Address parameters_bottom = parameters_top + parameters_size; 1810
2036 Address expressions_bottom = expressions_top + expressions_size; 1811 translated_state_.Prepare(false, nullptr);
2037 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { 1812
2038 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i]; 1813 TranslatedFrame* frame = &(translated_state_.frames()[frame_index]);
2039 1814 CHECK(frame->kind() == TranslatedFrame::kFunction);
2040 // Check of the heap number to materialize actually belong to the frame 1815 int frame_arg_count =
2041 // being extracted. 1816 frame->function()->shared()->internal_formal_parameter_count();
2042 Address slot = d.destination(); 1817
2043 if (parameters_top <= slot && slot < parameters_bottom) { 1818 // The height is #expressions + 1 for context.
2044 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); 1819 CHECK_EQ(expression_count + 1, frame->height());
2045 1820 TranslatedFrame* argument_frame = frame;
2046 int index = (info->parameters_count() - 1) - 1821 if (frame_index > 0) {
2047 static_cast<int>(slot - parameters_top) / kPointerSize; 1822 TranslatedFrame* previous_frame =
2048 1823 &(translated_state_.frames()[frame_index - 1]);
2049 if (trace_scope_ != NULL) { 1824 if (previous_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
2050 PrintF(trace_scope_->file(), 1825 argument_frame = previous_frame;
2051 "Materializing a new heap number %p [%e] in slot %p" 1826 CHECK_EQ(parameter_count, argument_frame->height() - 1);
2052 "for parameter slot #%d\n", 1827 } else {
2053 reinterpret_cast<void*>(*num), 1828 CHECK_EQ(frame_arg_count, parameter_count);
2054 d.value(), 1829 }
2055 d.destination(), 1830 } else {
2056 index); 1831 CHECK_EQ(frame_arg_count, parameter_count);
2057 } 1832 }
2058 1833
2059 info->SetParameter(index, *num); 1834 TranslatedFrame::iterator arg_iter = argument_frame->begin();
2060 } else if (expressions_top <= slot && slot < expressions_bottom) { 1835 arg_iter++; // Skip the receiver.
2061 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); 1836 for (int i = 0; i < parameter_count; i++, arg_iter++) {
2062 1837 if (!arg_iter->IsMaterializedObject()) {
2063 int index = info->expression_count() - 1 - 1838 info->SetParameter(i, *(arg_iter->GetValue()));
2064 static_cast<int>(slot - expressions_top) / kPointerSize; 1839 }
2065 1840 }
2066 if (trace_scope_ != NULL) { 1841
2067 PrintF(trace_scope_->file(), 1842 TranslatedFrame::iterator iter = frame->begin();
2068 "Materializing a new heap number %p [%e] in slot %p" 1843 // Skip the arguments, receiver and context.
2069 "for expression slot #%d\n", 1844 for (int i = 0; i < frame_arg_count + 2; i++, iter++) {
2070 reinterpret_cast<void*>(*num), 1845 }
2071 d.value(), 1846
2072 d.destination(), 1847 for (int i = 0; i < expression_count; i++, iter++) {
2073 index); 1848 if (!iter->IsMaterializedObject()) {
2074 } 1849 info->SetExpression(i, *(iter->GetValue()));
2075 1850 }
2076 info->SetExpression(index, *num); 1851 }
2077 } 1852 }
2078 } 1853
2079 } 1854
2080 1855 void Deoptimizer::WriteValueToOutput(
2081 1856 TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
2082 static const char* TraceValueType(bool is_smi) { 1857 unsigned output_offset, Address output_address_for_materialization) {
2083 if (is_smi) { 1858 Object* value = (*iterator)->GetRawValue();
2084 return "smi"; 1859 output_[frame_index]->SetFrameSlot(output_offset,
2085 } 1860 reinterpret_cast<intptr_t>(value));
2086 1861
2087 return "heap number"; 1862 Address output_address =
2088 } 1863 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + output_offset;
2089 1864 if (trace_scope_ != nullptr) {
2090 1865 PrintF(trace_scope_->file(),
2091 void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) { 1866 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; ",
2092 Translation::Opcode opcode = 1867 reinterpret_cast<intptr_t>(output_address), output_offset,
2093 static_cast<Translation::Opcode>(iterator->Next()); 1868 reinterpret_cast<intptr_t>(value));
2094 1869 value->ShortPrint(trace_scope_->file());
2095 switch (opcode) { 1870 PrintF(trace_scope_->file(), " (input #%d)\n", *input_index);
2096 case Translation::BEGIN: 1871 }
2097 case Translation::JS_FRAME: 1872
2098 case Translation::ARGUMENTS_ADAPTOR_FRAME: 1873 if (value == isolate_->heap()->arguments_marker()) {
2099 case Translation::CONSTRUCT_STUB_FRAME: 1874 if (output_address_for_materialization == nullptr) {
2100 case Translation::GETTER_STUB_FRAME: 1875 output_address_for_materialization = output_address;
2101 case Translation::SETTER_STUB_FRAME: 1876 }
2102 case Translation::COMPILED_STUB_FRAME: { 1877 values_to_materialize_.push_back(
2103 FATAL("Unexpected frame start translation opcode"); 1878 {output_address_for_materialization, *iterator});
2104 return; 1879 }
2105 } 1880
2106 1881 (*iterator)++;
2107 case Translation::REGISTER: 1882 (*input_index)++;
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 }
2155
2156 FATAL("Unexpected translation opcode");
2157 }
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 } 1883 }
2832 1884
2833 1885
2834 unsigned Deoptimizer::ComputeInputFrameSize() const { 1886 unsigned Deoptimizer::ComputeInputFrameSize() const {
2835 unsigned fixed_size = ComputeFixedSize(function_); 1887 unsigned fixed_size = ComputeFixedSize(function_);
2836 // The fp-to-sp delta already takes the context, constant pool pointer and the 1888 // 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. 1889 // function into account so we have to avoid double counting them.
2838 unsigned result = fixed_size + fp_to_sp_delta_ - 1890 unsigned result = fixed_size + fp_to_sp_delta_ -
2839 StandardFrameConstants::kFixedFrameSizeFromFp; 1891 StandardFrameConstants::kFixedFrameSizeFromFp;
2840 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { 1892 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2841 unsigned stack_slots = compiled_code_->stack_slots(); 1893 unsigned stack_slots = compiled_code_->stack_slots();
2842 unsigned outgoing_size = ComputeOutgoingArgumentSize(); 1894 unsigned outgoing_size = ComputeOutgoingArgumentSize();
2843 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 1895 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
2844 } 1896 }
2845 return result; 1897 return result;
2846 } 1898 }
2847 1899
2848 1900
2849 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 1901 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
2850 // The fixed part of the frame consists of the return address, frame 1902 // The fixed part of the frame consists of the return address, frame
2851 // pointer, function, context, and all the incoming arguments. 1903 // pointer, function, context, and all the incoming arguments.
2852 return ComputeIncomingArgumentSize(function) + 1904 return ComputeIncomingArgumentSize(function) +
2853 StandardFrameConstants::kFixedFrameSize; 1905 StandardFrameConstants::kFixedFrameSize;
2854 } 1906 }
2855 1907
2856 1908
2857 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 1909 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
2858 // The incoming arguments is the values for formal parameters and 1910 // The incoming arguments is the values for formal parameters and
2859 // the receiver. Every slot contains a pointer. 1911 // the receiver. Every slot contains a pointer.
2860 if (function->IsSmi()) { 1912 if (function->IsSmi()) {
2861 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); 1913 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
2862 return 0; 1914 return 0;
2863 } 1915 }
2864 unsigned arguments = 1916 unsigned arguments =
2865 function->shared()->internal_formal_parameter_count() + 1; 1917 function->shared()->internal_formal_parameter_count() + 1;
2866 return arguments * kPointerSize; 1918 return arguments * kPointerSize;
2867 } 1919 }
2868 1920
2869 1921
2870 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 1922 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
2871 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1923 DeoptimizationInputData* data =
2872 compiled_code_->deoptimization_data()); 1924 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
2873 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 1925 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
2874 return height * kPointerSize; 1926 return height * kPointerSize;
2875 } 1927 }
2876 1928
2877 1929
2878 Object* Deoptimizer::ComputeLiteral(int index) const { 1930 Object* Deoptimizer::ComputeLiteral(int index) const {
2879 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1931 DeoptimizationInputData* data =
2880 compiled_code_->deoptimization_data()); 1932 DeoptimizationInputData::cast(compiled_code_->deoptimization_data());
2881 FixedArray* literals = data->LiteralArray(); 1933 FixedArray* literals = data->LiteralArray();
2882 return literals->get(index); 1934 return literals->get(index);
2883 } 1935 }
2884 1936
2885 1937
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, 1938 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
2921 BailoutType type, 1939 BailoutType type,
2922 int max_entry_id) { 1940 int max_entry_id) {
2923 // We cannot run this if the serializer is enabled because this will 1941 // We cannot run this if the serializer is enabled because this will
2924 // cause us to emit relocation information for the external 1942 // cause us to emit relocation information for the external
2925 // references. This is fine because the deoptimizer's code section 1943 // references. This is fine because the deoptimizer's code section
2926 // isn't meant to be serialized at all. 1944 // isn't meant to be serialized at all.
2927 CHECK(type == EAGER || type == SOFT || type == LAZY); 1945 CHECK(type == EAGER || type == SOFT || type == LAZY);
2928 DeoptimizerData* data = isolate->deoptimizer_data(); 1946 DeoptimizerData* data = isolate->deoptimizer_data();
2929 int entry_count = data->deopt_entry_code_entries_[type]; 1947 int entry_count = data->deopt_entry_code_entries_[type];
(...skipping 10 matching lines...) Expand all
2940 DCHECK(!RelocInfo::RequiresRelocation(desc)); 1958 DCHECK(!RelocInfo::RequiresRelocation(desc));
2941 1959
2942 MemoryChunk* chunk = data->deopt_entry_code_[type]; 1960 MemoryChunk* chunk = data->deopt_entry_code_[type];
2943 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= 1961 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
2944 desc.instr_size); 1962 desc.instr_size);
2945 if (!chunk->CommitArea(desc.instr_size)) { 1963 if (!chunk->CommitArea(desc.instr_size)) {
2946 V8::FatalProcessOutOfMemory( 1964 V8::FatalProcessOutOfMemory(
2947 "Deoptimizer::EnsureCodeForDeoptimizationEntry"); 1965 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
2948 } 1966 }
2949 CopyBytes(chunk->area_start(), desc.buffer, 1967 CopyBytes(chunk->area_start(), desc.buffer,
2950 static_cast<size_t>(desc.instr_size)); 1968 static_cast<size_t>(desc.instr_size));
2951 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size); 1969 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size);
2952 1970
2953 data->deopt_entry_code_entries_[type] = entry_count; 1971 data->deopt_entry_code_entries_[type] = entry_count;
2954 } 1972 }
2955 1973
2956 1974
2957 FrameDescription::FrameDescription(uint32_t frame_size, 1975 FrameDescription::FrameDescription(uint32_t frame_size,
2958 JSFunction* function) 1976 JSFunction* function)
2959 : frame_size_(frame_size), 1977 : frame_size_(frame_size),
2960 function_(function), 1978 function_(function),
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
3111 void Translation::BeginJSFrame(BailoutId node_id, 2129 void Translation::BeginJSFrame(BailoutId node_id,
3112 int literal_id, 2130 int literal_id,
3113 unsigned height) { 2131 unsigned height) {
3114 buffer_->Add(JS_FRAME, zone()); 2132 buffer_->Add(JS_FRAME, zone());
3115 buffer_->Add(node_id.ToInt(), zone()); 2133 buffer_->Add(node_id.ToInt(), zone());
3116 buffer_->Add(literal_id, zone()); 2134 buffer_->Add(literal_id, zone());
3117 buffer_->Add(height, zone()); 2135 buffer_->Add(height, zone());
3118 } 2136 }
3119 2137
3120 2138
3121 void Translation::BeginCompiledStubFrame() { 2139 void Translation::BeginCompiledStubFrame(int height) {
3122 buffer_->Add(COMPILED_STUB_FRAME, zone()); 2140 buffer_->Add(COMPILED_STUB_FRAME, zone());
2141 buffer_->Add(height, zone());
3123 } 2142 }
3124 2143
3125 2144
3126 void Translation::BeginArgumentsObject(int args_length) { 2145 void Translation::BeginArgumentsObject(int args_length) {
3127 buffer_->Add(ARGUMENTS_OBJECT, zone()); 2146 buffer_->Add(ARGUMENTS_OBJECT, zone());
3128 buffer_->Add(args_length, zone()); 2147 buffer_->Add(args_length, zone());
3129 } 2148 }
3130 2149
3131 2150
3132 void Translation::BeginCapturedObject(int length) { 2151 void Translation::BeginCapturedObject(int length) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3257 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) 2276 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
3258 } 2277 }
3259 #undef TRANSLATION_OPCODE_CASE 2278 #undef TRANSLATION_OPCODE_CASE
3260 UNREACHABLE(); 2279 UNREACHABLE();
3261 return ""; 2280 return "";
3262 } 2281 }
3263 2282
3264 #endif 2283 #endif
3265 2284
3266 2285
3267 // We can't intermix stack decoding and allocations because
3268 // deoptimization infrastracture is not GC safe.
3269 // Thus we build a temporary structure in malloced space.
3270 SlotRef SlotRefValueBuilder::ComputeSlotForNextArgument(
3271 Translation::Opcode opcode,
3272 TranslationIterator* iterator,
3273 DeoptimizationInputData* data,
3274 JavaScriptFrame* frame) {
3275 switch (opcode) {
3276 case Translation::BEGIN:
3277 case Translation::JS_FRAME:
3278 case Translation::ARGUMENTS_ADAPTOR_FRAME:
3279 case Translation::CONSTRUCT_STUB_FRAME:
3280 case Translation::GETTER_STUB_FRAME:
3281 case Translation::SETTER_STUB_FRAME:
3282 // Peeled off before getting here.
3283 break;
3284
3285 case Translation::DUPLICATED_OBJECT: {
3286 return SlotRef::NewDuplicateObject(iterator->Next());
3287 }
3288
3289 case Translation::ARGUMENTS_OBJECT:
3290 return SlotRef::NewArgumentsObject(iterator->Next());
3291
3292 case Translation::CAPTURED_OBJECT: {
3293 return SlotRef::NewDeferredObject(iterator->Next());
3294 }
3295
3296 case Translation::REGISTER:
3297 case Translation::INT32_REGISTER:
3298 case Translation::UINT32_REGISTER:
3299 case Translation::BOOL_REGISTER:
3300 case Translation::DOUBLE_REGISTER:
3301 // We are at safepoint which corresponds to call. All registers are
3302 // saved by caller so there would be no live registers at this
3303 // point. Thus these translation commands should not be used.
3304 break;
3305
3306 case Translation::STACK_SLOT: {
3307 int slot_index = iterator->Next();
3308 Address slot_addr = SlotAddress(frame, slot_index);
3309 return SlotRef(slot_addr, SlotRef::TAGGED);
3310 }
3311
3312 case Translation::INT32_STACK_SLOT: {
3313 int slot_index = iterator->Next();
3314 Address slot_addr = SlotAddress(frame, slot_index);
3315 return SlotRef(slot_addr, SlotRef::INT32);
3316 }
3317
3318 case Translation::UINT32_STACK_SLOT: {
3319 int slot_index = iterator->Next();
3320 Address slot_addr = SlotAddress(frame, slot_index);
3321 return SlotRef(slot_addr, SlotRef::UINT32);
3322 }
3323
3324 case Translation::BOOL_STACK_SLOT: {
3325 int slot_index = iterator->Next();
3326 Address slot_addr = SlotAddress(frame, slot_index);
3327 return SlotRef(slot_addr, SlotRef::BOOLBIT);
3328 }
3329
3330 case Translation::DOUBLE_STACK_SLOT: {
3331 int slot_index = iterator->Next();
3332 Address slot_addr = SlotAddress(frame, slot_index);
3333 return SlotRef(slot_addr, SlotRef::DOUBLE);
3334 }
3335
3336 case Translation::LITERAL: {
3337 int literal_index = iterator->Next();
3338 return SlotRef(data->GetIsolate(),
3339 data->LiteralArray()->get(literal_index));
3340 }
3341
3342 case Translation::COMPILED_STUB_FRAME:
3343 UNREACHABLE();
3344 break;
3345 }
3346
3347 FATAL("We should never get here - unexpected deopt info.");
3348 return SlotRef();
3349 }
3350
3351
3352 SlotRefValueBuilder::SlotRefValueBuilder(JavaScriptFrame* frame,
3353 int inlined_jsframe_index,
3354 int formal_parameter_count)
3355 : current_slot_(0),
3356 args_length_(-1),
3357 first_slot_index_(-1),
3358 should_deoptimize_(false) {
3359 DisallowHeapAllocation no_gc;
3360
3361 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3362 DeoptimizationInputData* data =
3363 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
3364 TranslationIterator it(data->TranslationByteArray(),
3365 data->TranslationIndex(deopt_index)->value());
3366 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
3367 CHECK_EQ(opcode, Translation::BEGIN);
3368 it.Next(); // Drop frame count.
3369
3370 stack_frame_id_ = frame->fp();
3371
3372 int jsframe_count = it.Next();
3373 CHECK_GT(jsframe_count, inlined_jsframe_index);
3374 int jsframes_to_skip = inlined_jsframe_index;
3375 int number_of_slots = -1; // Number of slots inside our frame (yet unknown)
3376 while (number_of_slots != 0) {
3377 opcode = static_cast<Translation::Opcode>(it.Next());
3378 bool processed = false;
3379 if (opcode == Translation::ARGUMENTS_ADAPTOR_FRAME) {
3380 if (jsframes_to_skip == 0) {
3381 CHECK_EQ(Translation::NumberOfOperandsFor(opcode), 2);
3382
3383 it.Skip(1); // literal id
3384 int height = it.Next();
3385
3386 // Skip the translation command for the receiver.
3387 it.Skip(Translation::NumberOfOperandsFor(
3388 static_cast<Translation::Opcode>(it.Next())));
3389
3390 // We reached the arguments adaptor frame corresponding to the
3391 // inlined function in question. Number of arguments is height - 1.
3392 first_slot_index_ = slot_refs_.length();
3393 args_length_ = height - 1;
3394 number_of_slots = height - 1;
3395 processed = true;
3396 }
3397 } else if (opcode == Translation::JS_FRAME) {
3398 if (jsframes_to_skip == 0) {
3399 // Skip over operands to advance to the next opcode.
3400 it.Skip(Translation::NumberOfOperandsFor(opcode));
3401
3402 // Skip the translation command for the receiver.
3403 it.Skip(Translation::NumberOfOperandsFor(
3404 static_cast<Translation::Opcode>(it.Next())));
3405
3406 // We reached the frame corresponding to the inlined function
3407 // in question. Process the translation commands for the
3408 // arguments. Number of arguments is equal to the number of
3409 // format parameter count.
3410 first_slot_index_ = slot_refs_.length();
3411 args_length_ = formal_parameter_count;
3412 number_of_slots = formal_parameter_count;
3413 processed = true;
3414 }
3415 jsframes_to_skip--;
3416 } else if (opcode != Translation::BEGIN &&
3417 opcode != Translation::CONSTRUCT_STUB_FRAME &&
3418 opcode != Translation::GETTER_STUB_FRAME &&
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 }
3434 }
3435
3436 processed = true;
3437 }
3438 if (!processed) {
3439 // Skip over operands to advance to the next opcode.
3440 it.Skip(Translation::NumberOfOperandsFor(opcode));
3441 }
3442 }
3443 if (should_deoptimize_) {
3444 List<JSFunction*> functions(2);
3445 frame->GetFunctions(&functions);
3446 Deoptimizer::DeoptimizeFunction(functions[0]);
3447 }
3448 }
3449
3450
3451 Handle<Object> SlotRef::GetValue(Isolate* isolate) {
3452 switch (representation_) {
3453 case TAGGED: {
3454 Handle<Object> value(Memory::Object_at(addr_), isolate);
3455 if (value->IsMutableHeapNumber()) {
3456 HeapNumber::cast(*value)->set_map(isolate->heap()->heap_number_map());
3457 }
3458 return value;
3459 }
3460
3461 case INT32: {
3462 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3463 int value = Memory::int32_at(addr_ + kIntSize);
3464 #else
3465 int value = Memory::int32_at(addr_);
3466 #endif
3467 if (Smi::IsValid(value)) {
3468 return Handle<Object>(Smi::FromInt(value), isolate);
3469 } else {
3470 return isolate->factory()->NewNumberFromInt(value);
3471 }
3472 }
3473
3474 case UINT32: {
3475 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3476 uint32_t value = Memory::uint32_at(addr_ + kIntSize);
3477 #else
3478 uint32_t value = Memory::uint32_at(addr_);
3479 #endif
3480 if (value <= static_cast<uint32_t>(Smi::kMaxValue)) {
3481 return Handle<Object>(Smi::FromInt(static_cast<int>(value)), isolate);
3482 } else {
3483 return isolate->factory()->NewNumber(static_cast<double>(value));
3484 }
3485 }
3486
3487 case BOOLBIT: {
3488 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
3489 uint32_t value = Memory::uint32_at(addr_ + kIntSize);
3490 #else
3491 uint32_t value = Memory::uint32_at(addr_);
3492 #endif
3493 if (value == 0) {
3494 return isolate->factory()->false_value();
3495 } else {
3496 DCHECK_EQ(1U, value);
3497 return isolate->factory()->true_value();
3498 }
3499 }
3500
3501 case DOUBLE: {
3502 double value = read_double_value(addr_);
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()) {
3607 case MUTABLE_HEAP_NUMBER_TYPE:
3608 case HEAP_NUMBER_TYPE: {
3609 // Reuse the HeapNumber value directly as it is already properly
3610 // tagged and skip materializing the HeapNumber explicitly.
3611 Handle<Object> object = GetNext(isolate, lvl + 1);
3612 materialized_objects_.Add(object);
3613 // On 32-bit architectures, there is an extra slot there because
3614 // the escape analysis calculates the number of slots as
3615 // object-size/pointer-size. To account for this, we read out
3616 // any extra slots.
3617 for (int i = 0; i < length - 2; i++) {
3618 GetNext(isolate, lvl + 1);
3619 }
3620 return object;
3621 }
3622 case JS_OBJECT_TYPE: {
3623 Handle<JSObject> object =
3624 isolate->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
3625 materialized_objects_.Add(object);
3626 Handle<Object> properties = GetNext(isolate, lvl + 1);
3627 Handle<Object> elements = GetNext(isolate, lvl + 1);
3628 object->set_properties(FixedArray::cast(*properties));
3629 object->set_elements(FixedArrayBase::cast(*elements));
3630 for (int i = 0; i < length - 3; ++i) {
3631 Handle<Object> value = GetNext(isolate, lvl + 1);
3632 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3633 object->FastPropertyAtPut(index, *value);
3634 }
3635 return object;
3636 }
3637 case JS_ARRAY_TYPE: {
3638 Handle<JSArray> object =
3639 isolate->factory()->NewJSArray(0, map->elements_kind());
3640 materialized_objects_.Add(object);
3641 Handle<Object> properties = GetNext(isolate, lvl + 1);
3642 Handle<Object> elements = GetNext(isolate, lvl + 1);
3643 Handle<Object> length = GetNext(isolate, lvl + 1);
3644 object->set_properties(FixedArray::cast(*properties));
3645 object->set_elements(FixedArrayBase::cast(*elements));
3646 object->set_length(*length);
3647 return object;
3648 }
3649 default:
3650 PrintF(stderr,
3651 "[couldn't handle instance type %d]\n", map->instance_type());
3652 UNREACHABLE();
3653 break;
3654 }
3655 UNREACHABLE();
3656 break;
3657 }
3658
3659 case SlotRef::DUPLICATE_OBJECT: {
3660 int object_index = slot.DuplicateObjectId();
3661 Handle<Object> object = materialized_objects_[object_index];
3662 materialized_objects_.Add(object);
3663 return object;
3664 }
3665 default:
3666 UNREACHABLE();
3667 break;
3668 }
3669
3670 FATAL("We should never get here - unexpected deopt slot kind.");
3671 return Handle<Object>::null();
3672 }
3673
3674
3675 void SlotRefValueBuilder::Finish(Isolate* isolate) {
3676 // We should have processed all the slots
3677 CHECK_EQ(slot_refs_.length(), current_slot_);
3678
3679 if (should_deoptimize_ &&
3680 materialized_objects_.length() > prev_materialized_count_) {
3681 // We have materialized some new objects and they might be accessible
3682 // from the arguments object, so we have to store them
3683 // to prevent duplicate materialization.
3684 Handle<FixedArray> array = isolate->factory()->NewFixedArray(
3685 materialized_objects_.length());
3686 for (int i = 0; i < materialized_objects_.length(); i++) {
3687 array->set(i, *(materialized_objects_.at(i)));
3688 }
3689 isolate->materialized_object_store()->Set(stack_frame_id_, array);
3690 }
3691 }
3692
3693
3694 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { 2286 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
3695 int index = StackIdToIndex(fp); 2287 int index = StackIdToIndex(fp);
3696 if (index == -1) { 2288 if (index == -1) {
3697 return Handle<FixedArray>::null(); 2289 return Handle<FixedArray>::null();
3698 } 2290 }
3699 Handle<FixedArray> array = GetStackEntries(); 2291 Handle<FixedArray> array = GetStackEntries();
3700 CHECK_GT(array->length(), index); 2292 CHECK_GT(array->length(), index);
3701 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), 2293 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
3702 isolate()));
3703 } 2294 }
3704 2295
3705 2296
3706 void MaterializedObjectStore::Set(Address fp, 2297 void MaterializedObjectStore::Set(Address fp,
3707 Handle<FixedArray> materialized_objects) { 2298 Handle<FixedArray> materialized_objects) {
3708 int index = StackIdToIndex(fp); 2299 int index = StackIdToIndex(fp);
3709 if (index == -1) { 2300 if (index == -1) {
3710 index = frame_fps_.length(); 2301 index = frame_fps_.length();
3711 frame_fps_.Add(fp); 2302 frame_fps_.Add(fp);
3712 } 2303 }
3713 2304
3714 Handle<FixedArray> array = EnsureStackEntries(index + 1); 2305 Handle<FixedArray> array = EnsureStackEntries(index + 1);
3715 array->set(index, *materialized_objects); 2306 array->set(index, *materialized_objects);
3716 } 2307 }
3717 2308
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
3775 2366
3776 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, 2367 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
3777 int frame_index, 2368 int frame_index,
3778 bool has_arguments_adaptor, 2369 bool has_arguments_adaptor,
3779 bool has_construct_stub) { 2370 bool has_construct_stub) {
3780 FrameDescription* output_frame = deoptimizer->output_[frame_index]; 2371 FrameDescription* output_frame = deoptimizer->output_[frame_index];
3781 function_ = output_frame->GetFunction(); 2372 function_ = output_frame->GetFunction();
3782 context_ = reinterpret_cast<Object*>(output_frame->GetContext()); 2373 context_ = reinterpret_cast<Object*>(output_frame->GetContext());
3783 has_construct_stub_ = has_construct_stub; 2374 has_construct_stub_ = has_construct_stub;
3784 expression_count_ = output_frame->GetExpressionCount(); 2375 expression_count_ = output_frame->GetExpressionCount();
3785 expression_stack_ = new Object*[expression_count_]; 2376 expression_stack_ = new Object* [expression_count_];
3786 // Get the source position using the unoptimized code. 2377 // Get the source position using the unoptimized code.
3787 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); 2378 Address pc = reinterpret_cast<Address>(output_frame->GetPc());
3788 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); 2379 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc));
3789 source_position_ = code->SourcePosition(pc); 2380 source_position_ = code->SourcePosition(pc);
3790 2381
3791 for (int i = 0; i < expression_count_; i++) { 2382 for (int i = 0; i < expression_count_; i++) {
3792 SetExpression(i, output_frame->GetExpression(i)); 2383 SetExpression(i, output_frame->GetExpression(i));
3793 } 2384 }
3794 2385
3795 if (has_arguments_adaptor) { 2386 if (has_arguments_adaptor) {
3796 output_frame = deoptimizer->output_[frame_index - 1]; 2387 output_frame = deoptimizer->output_[frame_index - 1];
3797 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); 2388 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
3798 } 2389 }
3799 2390
3800 parameters_count_ = output_frame->ComputeParametersCount(); 2391 parameters_count_ = output_frame->ComputeParametersCount();
3801 parameters_ = new Object*[parameters_count_]; 2392 parameters_ = new Object* [parameters_count_];
3802 for (int i = 0; i < parameters_count_; i++) { 2393 for (int i = 0; i < parameters_count_; i++) {
3803 SetParameter(i, output_frame->GetParameter(i)); 2394 SetParameter(i, output_frame->GetParameter(i));
3804 } 2395 }
3805 } 2396 }
3806 2397
3807 2398
3808 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { 2399 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
3809 delete[] expression_stack_; 2400 delete[] expression_stack_;
3810 delete[] parameters_; 2401 delete[] parameters_;
3811 } 2402 }
(...skipping 28 matching lines...) Expand all
3840 if (info->rmode() == RelocInfo::POSITION) { 2431 if (info->rmode() == RelocInfo::POSITION) {
3841 int raw_position = static_cast<int>(info->data()); 2432 int raw_position = static_cast<int>(info->data());
3842 last_position = raw_position ? SourcePosition::FromRaw(raw_position) 2433 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
3843 : SourcePosition::Unknown(); 2434 : SourcePosition::Unknown();
3844 } else if (info->rmode() == RelocInfo::DEOPT_REASON) { 2435 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
3845 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data()); 2436 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
3846 } 2437 }
3847 } 2438 }
3848 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason); 2439 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
3849 } 2440 }
2441
2442
2443 // static
2444 TranslatedValue TranslatedValue::NewArgumentsObject(TranslatedState* container,
2445 int length,
2446 int object_index) {
2447 TranslatedValue slot(container, kArgumentsObject);
2448 slot.materialization_info_ = {object_index, length};
2449 return slot;
2450 }
2451
2452
2453 // static
2454 TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2455 int length,
2456 int object_index) {
2457 TranslatedValue slot(container, kCapturedObject);
2458 slot.materialization_info_ = {object_index, length};
2459 return slot;
2460 }
2461
2462
2463 // static
2464 TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2465 int id) {
2466 TranslatedValue slot(container, kDuplicatedObject);
2467 slot.materialization_info_ = {id, -1};
2468 return slot;
2469 }
2470
2471
2472 // static
2473 TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2474 double value) {
2475 TranslatedValue slot(container, kDouble);
2476 slot.double_value_ = value;
2477 return slot;
2478 }
2479
2480
2481 // static
2482 TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2483 int32_t value) {
2484 TranslatedValue slot(container, kInt32);
2485 slot.int32_value_ = value;
2486 return slot;
2487 }
2488
2489
2490 // static
2491 TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2492 uint32_t value) {
2493 TranslatedValue slot(container, kUInt32);
2494 slot.uint32_value_ = value;
2495 return slot;
2496 }
2497
2498
2499 // static
2500 TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2501 uint32_t value) {
2502 TranslatedValue slot(container, kBoolBit);
2503 slot.uint32_value_ = value;
2504 return slot;
2505 }
2506
2507
2508 // static
2509 TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2510 Object* literal) {
2511 TranslatedValue slot(container, kTagged);
2512 slot.raw_literal_ = literal;
2513 return slot;
2514 }
2515
2516
2517 // static
2518 TranslatedValue TranslatedValue::NewInvalid() {
2519 return TranslatedValue(nullptr, kInvalid);
2520 }
2521
2522
2523 Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
2524
2525
2526 Object* TranslatedValue::raw_literal() const {
2527 DCHECK_EQ(kTagged, kind());
2528 return raw_literal_;
2529 }
2530
2531
2532 int32_t TranslatedValue::int32_value() const {
2533 DCHECK_EQ(kInt32, kind());
2534 return int32_value_;
2535 }
2536
2537
2538 uint32_t TranslatedValue::uint32_value() const {
2539 DCHECK(kind() == kUInt32 || kind() == kBoolBit);
2540 return uint32_value_;
2541 }
2542
2543
2544 double TranslatedValue::double_value() const {
2545 DCHECK_EQ(kDouble, kind());
2546 return double_value_;
2547 }
2548
2549
2550 int TranslatedValue::object_length() const {
2551 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject);
2552 return materialization_info_.length_;
2553 }
2554
2555
2556 int TranslatedValue::object_index() const {
2557 DCHECK(kind() == kArgumentsObject || kind() == kCapturedObject ||
2558 kind() == kDuplicatedObject);
2559 return materialization_info_.id_;
2560 }
2561
2562
2563 Object* TranslatedValue::GetRawValue() const {
2564 // If we have a value, return it.
2565 Handle<Object> result_handle;
2566 if (value_.ToHandle(&result_handle)) {
2567 return *result_handle;
2568 }
2569
2570 // Otherwise, do a best effort to get the value without allocation.
2571 switch (kind()) {
2572 case kTagged:
2573 return raw_literal();
2574
2575 case kInt32: {
2576 bool is_smi = Smi::IsValid(int32_value());
2577 if (is_smi) {
2578 return Smi::FromInt(int32_value());
2579 }
2580 break;
2581 }
2582
2583 case kUInt32: {
2584 bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
2585 if (is_smi) {
2586 return Smi::FromInt(static_cast<int32_t>(uint32_value()));
2587 }
2588 break;
2589 }
2590
2591 case kDouble: {
2592 int int_value = FastD2IChecked(double_value());
2593 bool is_smi = !IsMinusZero(double_value()) &&
2594 double_value() == int_value && Smi::IsValid(int_value);
2595 if (is_smi) {
2596 return Smi::FromInt(static_cast<int32_t>(int_value));
2597 }
2598 break;
2599 }
2600
2601 case kBoolBit: {
2602 if (uint32_value() == 0) {
2603 return isolate()->heap()->false_value();
2604 } else {
2605 CHECK_EQ(1, uint32_value());
2606 return isolate()->heap()->true_value();
2607 }
2608 }
2609
2610 default:
2611 break;
2612 }
2613
2614 // If we could not get the value without allocation, return the arguments
2615 // marker.
2616 return isolate()->heap()->arguments_marker();
2617 }
2618
2619
2620 Handle<Object> TranslatedValue::GetValue() {
2621 Handle<Object> result;
2622 // If we already have a value, then get it.
2623 if (value_.ToHandle(&result)) return result;
2624
2625 // Otherwise we have to materialize.
2626 switch (kind()) {
2627 case TranslatedValue::kTagged:
2628 case TranslatedValue::kInt32:
2629 case TranslatedValue::kUInt32:
2630 case TranslatedValue::kBoolBit:
2631 case TranslatedValue::kDouble: {
2632 MaterializeSimple();
2633 return value_.ToHandleChecked();
2634 }
2635
2636 case TranslatedValue::kArgumentsObject:
2637 case TranslatedValue::kCapturedObject:
2638 case TranslatedValue::kDuplicatedObject:
2639 return container_->MaterializeObjectAt(object_index());
2640
2641 case TranslatedValue::kInvalid:
2642 FATAL("unexpected case");
2643 return Handle<Object>::null();
2644 }
2645
2646 FATAL("internal error: value missing");
2647 return Handle<Object>::null();
2648 }
2649
2650
2651 void TranslatedValue::MaterializeSimple() {
2652 // If we already have materialized, return.
2653 if (!value_.is_null()) return;
2654
2655 Object* raw_value = GetRawValue();
2656 if (raw_value != isolate()->heap()->arguments_marker()) {
2657 // We can get the value without allocation, just return it here.
2658 value_ = Handle<Object>(raw_value, isolate());
2659 return;
2660 }
2661
2662 switch (kind()) {
2663 case kInt32: {
2664 value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
2665 return;
2666 }
2667
2668 case kUInt32:
2669 value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
2670 return;
2671
2672 case kDouble:
2673 value_ = Handle<Object>(isolate()->factory()->NewNumber(double_value()));
2674 return;
2675
2676 case kCapturedObject:
2677 case kDuplicatedObject:
2678 case kArgumentsObject:
2679 case kInvalid:
2680 case kTagged:
2681 case kBoolBit:
2682 FATAL("internal error: unexpected materialization.");
2683 break;
2684 }
2685 }
2686
2687
2688 bool TranslatedValue::IsMaterializedObject() const {
2689 switch (kind()) {
2690 case kCapturedObject:
2691 case kDuplicatedObject:
2692 case kArgumentsObject:
2693 return true;
2694 default:
2695 return false;
2696 }
2697 }
2698
2699
2700 int TranslatedValue::GetChildrenCount() const {
2701 if (kind() == kCapturedObject || kind() == kArgumentsObject) {
2702 return object_length();
2703 } else {
2704 return 0;
2705 }
2706 }
2707
2708
2709 int TranslatedState::SlotOffsetFp(int slot_index) {
2710 if (slot_index >= 0) {
2711 const int offset = StandardFrameConstants::kExpressionsOffset;
2712 return offset - (slot_index * kPointerSize);
2713 } else {
2714 const int offset = StandardFrameConstants::kCallerSPOffset;
2715 return offset - ((slot_index + 1) * kPointerSize);
2716 }
2717 }
2718
2719
2720 Address TranslatedState::SlotAddress(Address fp, int slot_index) {
2721 return fp + SlotOffsetFp(slot_index);
2722 }
2723
2724
2725 uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
2726 Address address = fp + slot_offset;
2727 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
2728 return Memory::uint32_at(address + kIntSize);
2729 #else
2730 return Memory::uint32_at(address);
2731 #endif
2732 }
2733
2734
2735 void TranslatedValue::Handlify() {
2736 if (kind() == kTagged) {
2737 value_ = Handle<Object>(raw_literal(), isolate());
2738 raw_literal_ = nullptr;
2739 }
2740 }
2741
2742
2743 TranslatedFrame TranslatedFrame::JSFrame(BailoutId node_id,
2744 JSFunction* function, int height) {
2745 TranslatedFrame frame(kFunction, function->GetIsolate(), function, height);
2746 frame.node_id_ = node_id;
2747 return frame;
2748 }
2749
2750
2751 TranslatedFrame TranslatedFrame::AccessorFrame(Kind kind,
2752 JSFunction* function) {
2753 DCHECK(kind == kSetter || kind == kGetter);
2754 return TranslatedFrame(kind, function->GetIsolate(), function);
2755 }
2756
2757
2758 TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(JSFunction* function,
2759 int height) {
2760 return TranslatedFrame(kArgumentsAdaptor, function->GetIsolate(), function,
2761 height);
2762 }
2763
2764
2765 TranslatedFrame TranslatedFrame::ConstructStubFrame(JSFunction* function,
2766 int height) {
2767 return TranslatedFrame(kConstructStub, function->GetIsolate(), function,
2768 height);
2769 }
2770
2771
2772 int TranslatedFrame::GetValueCount() {
2773 switch (kind()) {
2774 case kFunction: {
2775 int parameter_count =
2776 (raw_function_ == nullptr
2777 ? function_->shared()->internal_formal_parameter_count()
2778 : raw_function_->shared()->internal_formal_parameter_count()) +
2779 1;
2780 return height_ + parameter_count;
2781 }
2782
2783 case kGetter:
2784 return 1; // Receiver.
2785
2786 case kSetter:
2787 return 2; // Receiver and the value to set.
2788
2789 case kArgumentsAdaptor:
2790 case kConstructStub:
2791 case kCompiledStub:
2792 return height_;
2793
2794 case kInvalid:
2795 UNREACHABLE();
2796 break;
2797 }
2798 UNREACHABLE();
2799 return -1;
2800 }
2801
2802
2803 void TranslatedFrame::Handlify(Isolate* isolate) {
2804 if (raw_function_ != nullptr) {
2805 function_ = Handle<JSFunction>(raw_function_, isolate);
2806 raw_function_ = nullptr;
2807 }
2808 for (auto& value : values_) {
2809 value.Handlify();
2810 }
2811 }
2812
2813
2814 TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
2815 TranslationIterator* iterator, FixedArray* literal_array, Address fp,
2816 JSFunction* frame_function, FILE* trace_file) {
2817 Translation::Opcode opcode =
2818 static_cast<Translation::Opcode>(iterator->Next());
2819 switch (opcode) {
2820 case Translation::JS_FRAME: {
2821 BailoutId node_id = BailoutId(iterator->Next());
2822 int closure_id = iterator->Next();
2823 JSFunction* function =
2824 (closure_id == Translation::kSelfLiteralId)
2825 ? frame_function
2826 : JSFunction::cast(literal_array->get(closure_id));
2827 int height = iterator->Next();
2828 if (trace_file != nullptr) {
2829 PrintF(trace_file, " reading input frame ");
2830 function->PrintName(trace_file);
2831 int arg_count =
2832 function->shared()->internal_formal_parameter_count() + 1;
2833 PrintF(trace_file, " => node=%d, args=%d, height=%d; inputs:\n",
2834 arg_count, node_id.ToInt(), height);
2835 }
2836 return TranslatedFrame::JSFrame(node_id, function, height);
2837 }
2838
2839 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
2840 JSFunction* function =
2841 JSFunction::cast(literal_array->get(iterator->Next()));
2842 int height = iterator->Next();
2843 if (trace_file != nullptr) {
2844 PrintF(trace_file, " reading arguments adaptor frame");
2845 function->PrintName(trace_file);
2846 PrintF(trace_file, " => height=%d; inputs:\n", height);
2847 }
2848 return TranslatedFrame::ArgumentsAdaptorFrame(function, height);
2849 }
2850
2851 case Translation::CONSTRUCT_STUB_FRAME: {
2852 JSFunction* function =
2853 JSFunction::cast(literal_array->get(iterator->Next()));
2854 int height = iterator->Next();
2855 if (trace_file != nullptr) {
2856 PrintF(trace_file, " reading construct stub frame ");
2857 function->PrintName(trace_file);
2858 PrintF(trace_file, " => height=%d; inputs:\n", height);
2859 }
2860 return TranslatedFrame::ConstructStubFrame(function, height);
2861 }
2862
2863 case Translation::GETTER_STUB_FRAME: {
2864 JSFunction* function =
2865 JSFunction::cast(literal_array->get(iterator->Next()));
2866 if (trace_file != nullptr) {
2867 PrintF(trace_file, " reading getter frame ");
2868 function->PrintName(trace_file);
2869 PrintF(trace_file, "; inputs:\n");
2870 }
2871 return TranslatedFrame::AccessorFrame(TranslatedFrame::kGetter, function);
2872 }
2873
2874 case Translation::SETTER_STUB_FRAME: {
2875 JSFunction* function =
2876 JSFunction::cast(literal_array->get(iterator->Next()));
2877 if (trace_file != nullptr) {
2878 PrintF(trace_file, " reading setter frame ");
2879 function->PrintName(trace_file);
2880 PrintF(trace_file, "; inputs:\n");
2881 }
2882 return TranslatedFrame::AccessorFrame(TranslatedFrame::kSetter, function);
2883 }
2884
2885 case Translation::COMPILED_STUB_FRAME: {
2886 int height = iterator->Next();
2887 if (trace_file != nullptr) {
2888 PrintF(trace_file,
2889 " reading compiler stub frame => height=%d; inputs:\n", height);
2890 }
2891 return TranslatedFrame::CompiledStubFrame(height,
2892 literal_array->GetIsolate());
2893 }
2894
2895 case Translation::BEGIN:
2896 case Translation::DUPLICATED_OBJECT:
2897 case Translation::ARGUMENTS_OBJECT:
2898 case Translation::CAPTURED_OBJECT:
2899 case Translation::REGISTER:
2900 case Translation::INT32_REGISTER:
2901 case Translation::UINT32_REGISTER:
2902 case Translation::BOOL_REGISTER:
2903 case Translation::DOUBLE_REGISTER:
2904 case Translation::STACK_SLOT:
2905 case Translation::INT32_STACK_SLOT:
2906 case Translation::UINT32_STACK_SLOT:
2907 case Translation::BOOL_STACK_SLOT:
2908 case Translation::DOUBLE_STACK_SLOT:
2909 case Translation::LITERAL:
2910 break;
2911 }
2912 FATAL("We should never get here - unexpected deopt info.");
2913 return TranslatedFrame::InvalidFrame();
2914 }
2915
2916
2917 // static
2918 void TranslatedFrame::AdvanceIterator(
2919 std::deque<TranslatedValue>::iterator* iter) {
2920 int values_to_skip = 1;
2921 while (values_to_skip > 0) {
2922 // Consume the current element.
2923 values_to_skip--;
2924 // Add all the children.
2925 values_to_skip += (*iter)->GetChildrenCount();
2926
2927 (*iter)++;
2928 }
2929 }
2930
2931
2932 // We can't intermix stack decoding and allocations because
2933 // deoptimization infrastracture is not GC safe.
2934 // Thus we build a temporary structure in malloced space.
2935 TranslatedValue TranslatedState::CreateNextTranslatedValue(
2936 int frame_index, int value_index, TranslationIterator* iterator,
2937 FixedArray* literal_array, Address fp, RegisterValues* registers,
2938 FILE* trace_file) {
2939 disasm::NameConverter converter;
2940
2941 Translation::Opcode opcode =
2942 static_cast<Translation::Opcode>(iterator->Next());
2943 switch (opcode) {
2944 case Translation::BEGIN:
2945 case Translation::JS_FRAME:
2946 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2947 case Translation::CONSTRUCT_STUB_FRAME:
2948 case Translation::GETTER_STUB_FRAME:
2949 case Translation::SETTER_STUB_FRAME:
2950 case Translation::COMPILED_STUB_FRAME:
2951 // Peeled off before getting here.
2952 break;
2953
2954 case Translation::DUPLICATED_OBJECT: {
2955 int object_id = iterator->Next();
2956 if (trace_file != nullptr) {
2957 PrintF(trace_file, "duplicated object #%d", object_id);
2958 }
2959 object_positions_.push_back(object_positions_[object_id]);
2960 return TranslatedValue::NewDuplicateObject(this, object_id);
2961 }
2962
2963 case Translation::ARGUMENTS_OBJECT: {
2964 int arg_count = iterator->Next();
2965 int object_index = static_cast<int>(object_positions_.size());
2966 if (trace_file != nullptr) {
2967 PrintF(trace_file, "argumets object #%d (length = %d)", object_index,
2968 arg_count);
2969 }
2970 object_positions_.push_back({frame_index, value_index});
2971 return TranslatedValue::NewArgumentsObject(this, arg_count, object_index);
2972 }
2973
2974 case Translation::CAPTURED_OBJECT: {
2975 int field_count = iterator->Next();
2976 int object_index = static_cast<int>(object_positions_.size());
2977 if (trace_file != nullptr) {
2978 PrintF(trace_file, "captured object #%d (length = %d)", object_index,
2979 field_count);
2980 }
2981 object_positions_.push_back({frame_index, value_index});
2982 return TranslatedValue::NewDeferredObject(this, field_count,
2983 object_index);
2984 }
2985
2986 case Translation::REGISTER: {
2987 int input_reg = iterator->Next();
2988 if (registers == nullptr) return TranslatedValue::NewInvalid();
2989 intptr_t value = registers->GetRegister(input_reg);
2990 if (trace_file != nullptr) {
2991 PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
2992 converter.NameOfCPURegister(input_reg));
2993 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
2994 }
2995 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
2996 }
2997
2998 case Translation::INT32_REGISTER: {
2999 int input_reg = iterator->Next();
3000 if (registers == nullptr) return TranslatedValue::NewInvalid();
3001 intptr_t value = registers->GetRegister(input_reg);
3002 if (trace_file != nullptr) {
3003 PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
3004 converter.NameOfCPURegister(input_reg));
3005 }
3006 return TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
3007 }
3008
3009 case Translation::UINT32_REGISTER: {
3010 int input_reg = iterator->Next();
3011 if (registers == nullptr) return TranslatedValue::NewInvalid();
3012 intptr_t value = registers->GetRegister(input_reg);
3013 if (trace_file != nullptr) {
3014 PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
3015 converter.NameOfCPURegister(input_reg));
3016 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3017 }
3018 return TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
3019 }
3020
3021 case Translation::BOOL_REGISTER: {
3022 int input_reg = iterator->Next();
3023 if (registers == nullptr) return TranslatedValue::NewInvalid();
3024 intptr_t value = registers->GetRegister(input_reg);
3025 if (trace_file != nullptr) {
3026 PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
3027 converter.NameOfCPURegister(input_reg));
3028 }
3029 return TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
3030 }
3031
3032 case Translation::DOUBLE_REGISTER: {
3033 int input_reg = iterator->Next();
3034 if (registers == nullptr) return TranslatedValue::NewInvalid();
3035 double value = registers->GetDoubleRegister(input_reg);
3036 if (trace_file != nullptr) {
3037 PrintF(trace_file, "%e ; %s (bool)", value,
3038 DoubleRegister::AllocationIndexToString(input_reg));
3039 }
3040 return TranslatedValue::NewDouble(this, value);
3041 }
3042
3043 case Translation::STACK_SLOT: {
3044 int slot_offset = SlotOffsetFp(iterator->Next());
3045 intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
3046 if (trace_file != nullptr) {
3047 PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
3048 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3049 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3050 }
3051 return TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
3052 }
3053
3054 case Translation::INT32_STACK_SLOT: {
3055 int slot_offset = SlotOffsetFp(iterator->Next());
3056 uint32_t value = GetUInt32Slot(fp, slot_offset);
3057 if (trace_file != nullptr) {
3058 PrintF(trace_file, "%d ; (int) [fp %c %d] ",
3059 static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
3060 std::abs(slot_offset));
3061 }
3062 return TranslatedValue::NewInt32(this, value);
3063 }
3064
3065 case Translation::UINT32_STACK_SLOT: {
3066 int slot_offset = SlotOffsetFp(iterator->Next());
3067 uint32_t value = GetUInt32Slot(fp, slot_offset);
3068 if (trace_file != nullptr) {
3069 PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
3070 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3071 }
3072 return TranslatedValue::NewUInt32(this, value);
3073 }
3074
3075 case Translation::BOOL_STACK_SLOT: {
3076 int slot_offset = SlotOffsetFp(iterator->Next());
3077 uint32_t value = GetUInt32Slot(fp, slot_offset);
3078 if (trace_file != nullptr) {
3079 PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
3080 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3081 }
3082 return TranslatedValue::NewBool(this, value);
3083 }
3084
3085 case Translation::DOUBLE_STACK_SLOT: {
3086 int slot_offset = SlotOffsetFp(iterator->Next());
3087 double value = *(reinterpret_cast<double*>(fp + slot_offset));
3088 if (trace_file != nullptr) {
3089 PrintF(trace_file, "%e ; (double) [fp %c %d] ", value,
3090 slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
3091 }
3092 return TranslatedValue::NewDouble(this, value);
3093 }
3094
3095 case Translation::LITERAL: {
3096 int literal_index = iterator->Next();
3097 Object* value = literal_array->get(literal_index);
3098 if (trace_file != nullptr) {
3099 PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
3100 reinterpret_cast<intptr_t>(value), literal_index);
3101 reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
3102 }
3103
3104 return TranslatedValue::NewTagged(this, value);
3105 }
3106 }
3107
3108 FATAL("We should never get here - unexpected deopt info.");
3109 return TranslatedValue(nullptr, TranslatedValue::kInvalid);
3110 }
3111
3112
3113 TranslatedState::TranslatedState(JavaScriptFrame* frame)
3114 : isolate_(nullptr),
3115 stack_frame_pointer_(nullptr),
3116 has_adapted_arguments_(false) {
3117 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3118 DeoptimizationInputData* data =
3119 static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
3120 TranslationIterator it(data->TranslationByteArray(),
3121 data->TranslationIndex(deopt_index)->value());
3122 Init(frame->fp(), frame->function(), &it, data->LiteralArray(),
3123 nullptr /* registers */, nullptr /* trace file */);
3124 }
3125
3126
3127 TranslatedState::TranslatedState()
3128 : isolate_(nullptr),
3129 stack_frame_pointer_(nullptr),
3130 has_adapted_arguments_(false) {}
3131
3132
3133 void TranslatedState::Init(Address input_frame_pointer,
3134 JSFunction* input_frame_function,
3135 TranslationIterator* iterator,
3136 FixedArray* literal_array, RegisterValues* registers,
3137 FILE* trace_file) {
3138 DCHECK(frames_.empty());
3139
3140 isolate_ = literal_array->GetIsolate();
3141 // Read out the 'header' translation.
3142 Translation::Opcode opcode =
3143 static_cast<Translation::Opcode>(iterator->Next());
3144 CHECK(opcode == Translation::BEGIN);
3145
3146 int count = iterator->Next();
3147 iterator->Next(); // Drop JS frames count.
3148
3149 frames_.reserve(count);
3150
3151 std::stack<int> nested_counts;
3152
3153 // Read the frames
3154 for (int i = 0; i < count; i++) {
3155 // Read the frame descriptor.
3156 frames_.push_back(
3157 CreateNextTranslatedFrame(iterator, literal_array, input_frame_pointer,
3158 input_frame_function, trace_file));
3159 TranslatedFrame& frame = frames_.back();
3160
3161 // Read the values.
3162 int values_to_process = frame.GetValueCount();
3163 while (values_to_process > 0 || !nested_counts.empty()) {
3164 if (trace_file != nullptr) {
3165 if (nested_counts.empty()) {
3166 // For top level values, print the value number.
3167 PrintF(trace_file, " %3i: ",
3168 frame.GetValueCount() - values_to_process);
3169 } else {
3170 // Take care of indenting for nested values.
3171 PrintF(trace_file, " ");
3172 for (size_t j = 0; j < nested_counts.size(); j++) {
3173 PrintF(trace_file, " ");
3174 }
3175 }
3176 }
3177
3178 TranslatedValue value = CreateNextTranslatedValue(
3179 i, static_cast<int>(frame.values_.size()), iterator, literal_array,
3180 input_frame_pointer, registers, trace_file);
3181 frame.Add(value);
3182
3183 if (trace_file != nullptr) {
3184 PrintF(trace_file, "\n");
3185 }
3186
3187 // Update the value count and resolve the nesting.
3188 values_to_process--;
3189 int children_count = value.GetChildrenCount();
3190 if (children_count > 0) {
3191 nested_counts.push(values_to_process);
3192 values_to_process = children_count;
3193 } else {
3194 while (values_to_process == 0 && !nested_counts.empty()) {
3195 values_to_process = nested_counts.top();
3196 nested_counts.pop();
3197 }
3198 }
3199 }
3200 }
3201
3202 CHECK(!iterator->HasNext() ||
3203 static_cast<Translation::Opcode>(iterator->Next()) ==
3204 Translation::BEGIN);
3205 }
3206
3207
3208 void TranslatedState::Prepare(bool has_adapted_arguments,
3209 Address stack_frame_pointer) {
3210 for (auto& frame : frames_) {
3211 frame.Handlify(isolate_);
3212 }
3213
3214 stack_frame_pointer_ = stack_frame_pointer;
3215 has_adapted_arguments_ = has_adapted_arguments;
3216
3217 UpdateFromPreviouslyMaterializedObjects();
3218 }
3219
3220
3221 Handle<Object> TranslatedState::MaterializeAt(int frame_index,
3222 int* value_index) {
3223 TranslatedFrame* frame = &(frames_[frame_index]);
3224 DCHECK(static_cast<size_t>(*value_index) < frame->values_.size());
3225
3226 TranslatedValue* slot = &(frame->values_[*value_index]);
3227 (*value_index)++;
3228
3229 switch (slot->kind()) {
3230 case TranslatedValue::kTagged:
3231 case TranslatedValue::kInt32:
3232 case TranslatedValue::kUInt32:
3233 case TranslatedValue::kBoolBit:
3234 case TranslatedValue::kDouble: {
3235 slot->MaterializeSimple();
3236 Handle<Object> value = slot->GetValue();
3237 if (value->IsMutableHeapNumber()) {
3238 HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
3239 }
3240 return value;
3241 }
3242
3243 case TranslatedValue::kArgumentsObject: {
3244 int length = slot->GetChildrenCount();
3245 Handle<JSObject> arguments;
3246 if (GetAdaptedArguments(&arguments, frame_index)) {
3247 // Store the materialized object and consume the nested values.
3248 for (int i = 0; i < length; ++i) {
3249 MaterializeAt(frame_index, value_index);
3250 }
3251 } else {
3252 Handle<JSFunction> function = frame->function();
3253 arguments = isolate_->factory()->NewArgumentsObject(function, length);
3254 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3255 DCHECK_EQ(array->length(), length);
3256 arguments->set_elements(*array);
3257 for (int i = 0; i < length; ++i) {
3258 Handle<Object> value = MaterializeAt(frame_index, value_index);
3259 array->set(i, *value);
3260 }
3261 }
3262 slot->value_ = arguments;
3263 return arguments;
3264 }
3265 case TranslatedValue::kCapturedObject: {
3266 int length = slot->GetChildrenCount();
3267
3268 // The map must be a tagged object.
3269 CHECK(frame->values_[*value_index].kind() == TranslatedValue::kTagged);
3270
3271 Handle<Object> result;
3272 if (slot->value_.ToHandle(&result)) {
3273 // This has been previously materialized, return the previous value.
3274 // We still need to skip all the nested objects.
3275 for (int i = 0; i < length; i++) {
3276 MaterializeAt(frame_index, value_index);
3277 }
3278
3279 return result;
3280 }
3281
3282 Handle<Object> map_object = MaterializeAt(frame_index, value_index);
3283 Handle<Map> map =
3284 Map::GeneralizeAllFieldRepresentations(Handle<Map>::cast(map_object));
3285 switch (map->instance_type()) {
3286 case MUTABLE_HEAP_NUMBER_TYPE:
3287 case HEAP_NUMBER_TYPE: {
3288 // Reuse the HeapNumber value directly as it is already properly
3289 // tagged and skip materializing the HeapNumber explicitly.
3290 Handle<Object> object = MaterializeAt(frame_index, value_index);
3291 slot->value_ = object;
3292 // On 32-bit architectures, there is an extra slot there because
3293 // the escape analysis calculates the number of slots as
3294 // object-size/pointer-size. To account for this, we read out
3295 // any extra slots.
3296 for (int i = 0; i < length - 2; i++) {
3297 MaterializeAt(frame_index, value_index);
3298 }
3299 return object;
3300 }
3301 case JS_OBJECT_TYPE: {
3302 Handle<JSObject> object =
3303 isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED, false);
3304 slot->value_ = object;
3305 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3306 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3307 object->set_properties(FixedArray::cast(*properties));
3308 object->set_elements(FixedArrayBase::cast(*elements));
3309 for (int i = 0; i < length - 3; ++i) {
3310 Handle<Object> value = MaterializeAt(frame_index, value_index);
3311 FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
3312 object->FastPropertyAtPut(index, *value);
3313 }
3314 return object;
3315 }
3316 case JS_ARRAY_TYPE: {
3317 Handle<JSArray> object =
3318 isolate_->factory()->NewJSArray(0, map->elements_kind());
3319 slot->value_ = object;
3320 Handle<Object> properties = MaterializeAt(frame_index, value_index);
3321 Handle<Object> elements = MaterializeAt(frame_index, value_index);
3322 Handle<Object> length = MaterializeAt(frame_index, value_index);
3323 object->set_properties(FixedArray::cast(*properties));
3324 object->set_elements(FixedArrayBase::cast(*elements));
3325 object->set_length(*length);
3326 return object;
3327 }
3328 default:
3329 PrintF(stderr, "[couldn't handle instance type %d]\n",
3330 map->instance_type());
3331 FATAL("unreachable");
3332 return Handle<Object>::null();
3333 }
3334 UNREACHABLE();
3335 break;
3336 }
3337
3338 case TranslatedValue::kDuplicatedObject: {
3339 int object_index = slot->object_index();
3340 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3341
3342 // Make sure the duplicate is refering to a previous object.
3343 DCHECK(pos.frame_index_ < frame_index ||
3344 (pos.frame_index_ == frame_index &&
3345 pos.value_index_ < *value_index - 1));
3346
3347 Handle<Object> object =
3348 frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
3349
3350 // The object should have a (non-sentinel) value.
3351 DCHECK(!object.is_null() &&
3352 !object.is_identical_to(isolate_->factory()->arguments_marker()));
3353
3354 slot->value_ = object;
3355 return object;
3356 }
3357
3358 case TranslatedValue::kInvalid:
3359 UNREACHABLE();
3360 break;
3361 }
3362
3363 FATAL("We should never get here - unexpected deopt slot kind.");
3364 return Handle<Object>::null();
3365 }
3366
3367
3368 Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
3369 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3370 return MaterializeAt(pos.frame_index_, &(pos.value_index_));
3371 }
3372
3373
3374 bool TranslatedState::GetAdaptedArguments(Handle<JSObject>* result,
3375 int frame_index) {
3376 if (frame_index == 0) {
3377 // Top level frame -> we need to go to the parent frame on the stack.
3378 if (!has_adapted_arguments_) return false;
3379
3380 // This is top level frame, so we need to go to the stack to get
3381 // this function's argument. (Note that this relies on not inlining
3382 // recursive functions!)
3383 Handle<JSFunction> function = frames_[frame_index].function();
3384 *result = Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
3385 return true;
3386 } else {
3387 TranslatedFrame* previous_frame = &(frames_[frame_index]);
3388 if (previous_frame->kind() != TranslatedFrame::kArgumentsAdaptor) {
3389 return false;
3390 }
3391 // We get the adapted arguments from the parent translation.
3392 int length = previous_frame->GetValueCount();
3393 Handle<JSFunction> function = previous_frame->function();
3394 Handle<JSObject> arguments =
3395 isolate_->factory()->NewArgumentsObject(function, length);
3396 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length);
3397 arguments->set_elements(*array);
3398 TranslatedFrame::iterator arg_iterator = previous_frame->begin();
3399 for (int i = 0; i < length; ++i) {
3400 Handle<Object> value = arg_iterator->GetValue();
3401 array->set(i, *value);
3402 arg_iterator++;
3403 }
3404 CHECK(arg_iterator == previous_frame->end());
3405 *result = arguments;
3406 return true;
3407 }
3408 }
3409
3410
3411 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3412 int jsframe_index, int* args_count) {
3413 for (size_t i = 0; i < frames_.size(); i++) {
3414 if (frames_[i].kind() == TranslatedFrame::kFunction) {
3415 if (jsframe_index > 0) {
3416 jsframe_index--;
3417 } else {
3418 // We have the JS function frame, now check if it has arguments adaptor.
3419 if (i > 0 &&
3420 frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
3421 *args_count = frames_[i - 1].height();
3422 return &(frames_[i - 1]);
3423 }
3424 *args_count =
3425 frames_[i].function()->shared()->internal_formal_parameter_count() +
3426 1;
3427 return &(frames_[i]);
3428 }
3429 }
3430 }
3431 return nullptr;
3432 }
3433
3434
3435 void TranslatedState::StoreMaterializedValuesAndDeopt() {
3436 MaterializedObjectStore* materialized_store =
3437 isolate_->materialized_object_store();
3438 Handle<FixedArray> previously_materialized_objects =
3439 materialized_store->Get(stack_frame_pointer_);
3440
3441 Handle<Object> marker = isolate_->factory()->arguments_marker();
3442
3443 int length = static_cast<int>(object_positions_.size());
3444 bool new_store = false;
3445 if (previously_materialized_objects.is_null()) {
3446 previously_materialized_objects =
3447 isolate_->factory()->NewFixedArray(length);
3448 for (int i = 0; i < length; i++) {
3449 previously_materialized_objects->set(i, *marker);
3450 }
3451 new_store = true;
3452 }
3453
3454 DCHECK_EQ(length, previously_materialized_objects->length());
3455
3456 bool value_changed = false;
3457 for (int i = 0; i < length; i++) {
3458 TranslatedState::ObjectPosition pos = object_positions_[i];
3459 TranslatedValue* value_info =
3460 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3461
3462 DCHECK(value_info->IsMaterializedObject());
3463
3464 Handle<Object> value(value_info->GetRawValue(), isolate_);
3465
3466 if (!value.is_identical_to(marker)) {
3467 if (previously_materialized_objects->get(i) == *marker) {
3468 previously_materialized_objects->set(i, *value);
3469 value_changed = true;
3470 } else {
3471 DCHECK(previously_materialized_objects->get(i) == *value);
3472 }
3473 }
3474 }
3475 if (new_store && value_changed) {
3476 materialized_store->Set(stack_frame_pointer_,
3477 previously_materialized_objects);
3478 DCHECK(frames_[0].kind() == TranslatedFrame::kFunction);
3479 Deoptimizer::DeoptimizeFunction(*(frames_[0].function()));
3480 }
3481 }
3482
3483
3484 void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
3485 MaterializedObjectStore* materialized_store =
3486 isolate_->materialized_object_store();
3487 Handle<FixedArray> previously_materialized_objects =
3488 materialized_store->Get(stack_frame_pointer_);
3489
3490 // If we have no previously materialized objects, there is nothing to do.
3491 if (previously_materialized_objects.is_null()) return;
3492
3493 Handle<Object> marker = isolate_->factory()->arguments_marker();
3494
3495 int length = static_cast<int>(object_positions_.size());
3496 DCHECK_EQ(length, previously_materialized_objects->length());
3497
3498 for (int i = 0; i < length; i++) {
3499 // For a previously materialized objects, inject their value into the
3500 // translated values.
3501 if (previously_materialized_objects->get(i) != *marker) {
3502 TranslatedState::ObjectPosition pos = object_positions_[i];
3503 TranslatedValue* value_info =
3504 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3505 DCHECK(value_info->IsMaterializedObject());
3506
3507 value_info->value_ =
3508 Handle<Object>(previously_materialized_objects->get(i), isolate_);
3509 }
3510 }
3511 }
3512
3850 } // namespace internal 3513 } // namespace internal
3851 } // namespace v8 3514 } // namespace v8
OLDNEW
« no previous file with comments | « 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