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

Side by Side Diff: src/deoptimizer.cc

Issue 1210413005: Revert of Unify reading of deoptimization information. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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
197 // Done with the GC-unsafe frame descriptions. This re-enables allocation. 211 // Done with the GC-unsafe frame descriptions. This re-enables allocation.
198 deoptimizer->DeleteFrameDescriptions(); 212 deoptimizer->DeleteFrameDescriptions();
199 213
200 // Allocate a heap number for the doubles belonging to this frame. 214 // Allocate a heap number for the doubles belonging to this frame.
201 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame( 215 deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
202 frame_index, info->parameters_count(), info->expression_count(), info); 216 parameters_top, parameters_size, expressions_top, expressions_size, info);
203 217
204 // Finished using the deoptimizer instance. 218 // Finished using the deoptimizer instance.
205 delete deoptimizer; 219 delete deoptimizer;
206 220
207 return info; 221 return info;
208 } 222 }
209 223
210 224
211 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info, 225 void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
212 Isolate* isolate) { 226 Isolate* isolate) {
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
525 case EAGER: return "eager"; 539 case EAGER: return "eager";
526 case SOFT: return "soft"; 540 case SOFT: return "soft";
527 case LAZY: return "lazy"; 541 case LAZY: return "lazy";
528 case DEBUGGER: return "debugger"; 542 case DEBUGGER: return "debugger";
529 } 543 }
530 FATAL("Unsupported deopt type"); 544 FATAL("Unsupported deopt type");
531 return NULL; 545 return NULL;
532 } 546 }
533 547
534 548
535 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function, 549 Deoptimizer::Deoptimizer(Isolate* isolate,
536 BailoutType type, unsigned bailout_id, Address from, 550 JSFunction* function,
537 int fp_to_sp_delta, Code* optimized_code) 551 BailoutType type,
552 unsigned bailout_id,
553 Address from,
554 int fp_to_sp_delta,
555 Code* optimized_code)
538 : isolate_(isolate), 556 : isolate_(isolate),
539 function_(function), 557 function_(function),
540 bailout_id_(bailout_id), 558 bailout_id_(bailout_id),
541 bailout_type_(type), 559 bailout_type_(type),
542 from_(from), 560 from_(from),
543 fp_to_sp_delta_(fp_to_sp_delta), 561 fp_to_sp_delta_(fp_to_sp_delta),
544 has_alignment_padding_(0), 562 has_alignment_padding_(0),
545 input_(nullptr), 563 input_(NULL),
546 output_count_(0), 564 output_count_(0),
547 jsframe_count_(0), 565 jsframe_count_(0),
548 output_(nullptr), 566 output_(NULL),
549 trace_scope_(nullptr) { 567 deferred_objects_tagged_values_(0),
568 deferred_objects_double_values_(0),
569 deferred_objects_(0),
570 deferred_heap_numbers_(0),
571 jsframe_functions_(0),
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) {
550 // For COMPILED_STUBs called from builtins, the function pointer is a SMI 578 // For COMPILED_STUBs called from builtins, the function pointer is a SMI
551 // indicating an internal frame. 579 // indicating an internal frame.
552 if (function->IsSmi()) { 580 if (function->IsSmi()) {
553 function = nullptr; 581 function = NULL;
554 } 582 }
555 DCHECK(from != nullptr); 583 DCHECK(from != NULL);
556 if (function != nullptr && function->IsOptimized()) { 584 if (function != NULL && function->IsOptimized()) {
557 function->shared()->increment_deopt_count(); 585 function->shared()->increment_deopt_count();
558 if (bailout_type_ == Deoptimizer::SOFT) { 586 if (bailout_type_ == Deoptimizer::SOFT) {
559 isolate->counters()->soft_deopts_executed()->Increment(); 587 isolate->counters()->soft_deopts_executed()->Increment();
560 // Soft deopts shouldn't count against the overall re-optimization count 588 // Soft deopts shouldn't count against the overall re-optimization count
561 // that can eventually lead to disabling optimization for a function. 589 // that can eventually lead to disabling optimization for a function.
562 int opt_count = function->shared()->opt_count(); 590 int opt_count = function->shared()->opt_count();
563 if (opt_count > 0) opt_count--; 591 if (opt_count > 0) opt_count--;
564 function->shared()->set_opt_count(opt_count); 592 function->shared()->set_opt_count(opt_count);
565 } 593 }
566 } 594 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 (compiled_code_->is_hydrogen_stub())) { 773 (compiled_code_->is_hydrogen_stub())) {
746 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_); 774 compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
747 } 775 }
748 } 776 }
749 777
750 BailoutId node_id = input_data->AstId(bailout_id_); 778 BailoutId node_id = input_data->AstId(bailout_id_);
751 ByteArray* translations = input_data->TranslationByteArray(); 779 ByteArray* translations = input_data->TranslationByteArray();
752 unsigned translation_index = 780 unsigned translation_index =
753 input_data->TranslationIndex(bailout_id_)->value(); 781 input_data->TranslationIndex(bailout_id_)->value();
754 782
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
761 // Do the input frame to output frame(s) translation. 783 // Do the input frame to output frame(s) translation.
762 size_t count = translated_state_.frames().size(); 784 TranslationIterator iterator(translations, translation_index);
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.
763 DCHECK(output_ == NULL); 793 DCHECK(output_ == NULL);
764 output_ = new FrameDescription*[count]; 794 output_ = new FrameDescription*[count];
765 for (size_t i = 0; i < count; ++i) { 795 for (int i = 0; i < count; ++i) {
766 output_[i] = NULL; 796 output_[i] = NULL;
767 } 797 }
768 output_count_ = static_cast<int>(count); 798 output_count_ = count;
769 799
770 Register fp_reg = JavaScriptFrame::fp_register(); 800 Register fp_reg = JavaScriptFrame::fp_register();
771 stack_fp_ = reinterpret_cast<Address>( 801 stack_fp_ = reinterpret_cast<Address>(
772 input_->GetRegister(fp_reg.code()) + 802 input_->GetRegister(fp_reg.code()) +
773 has_alignment_padding_ * kPointerSize); 803 has_alignment_padding_ * kPointerSize);
774 804
775 // Translate each output frame. 805 // Translate each output frame.
776 for (size_t i = 0; i < count; ++i) { 806 for (int i = 0; i < count; ++i) {
777 // Read the ast node id, function, and frame height for this output frame. 807 // Read the ast node id, function, and frame height for this output frame.
778 int frame_index = static_cast<int>(i); 808 Translation::Opcode opcode =
779 switch (translated_state_.frames()[i].kind()) { 809 static_cast<Translation::Opcode>(iterator.Next());
780 case TranslatedFrame::kFunction: 810 switch (opcode) {
781 DoComputeJSFrame(nullptr, frame_index); 811 case Translation::JS_FRAME:
812 DoComputeJSFrame(&iterator, i);
782 jsframe_count_++; 813 jsframe_count_++;
783 break; 814 break;
784 case TranslatedFrame::kArgumentsAdaptor: 815 case Translation::ARGUMENTS_ADAPTOR_FRAME:
785 DoComputeArgumentsAdaptorFrame(nullptr, frame_index); 816 DoComputeArgumentsAdaptorFrame(&iterator, i);
786 break; 817 break;
787 case TranslatedFrame::kConstructStub: 818 case Translation::CONSTRUCT_STUB_FRAME:
788 DoComputeConstructStubFrame(nullptr, frame_index); 819 DoComputeConstructStubFrame(&iterator, i);
789 break; 820 break;
790 case TranslatedFrame::kGetter: 821 case Translation::GETTER_STUB_FRAME:
791 DoComputeAccessorStubFrame(nullptr, frame_index, false); 822 DoComputeAccessorStubFrame(&iterator, i, false);
792 break; 823 break;
793 case TranslatedFrame::kSetter: 824 case Translation::SETTER_STUB_FRAME:
794 DoComputeAccessorStubFrame(nullptr, frame_index, true); 825 DoComputeAccessorStubFrame(&iterator, i, true);
795 break; 826 break;
796 case TranslatedFrame::kCompiledStub: 827 case Translation::COMPILED_STUB_FRAME:
797 DoComputeCompiledStubFrame(nullptr, frame_index); 828 DoComputeCompiledStubFrame(&iterator, i);
798 break; 829 break;
799 case TranslatedFrame::kInvalid: 830 case Translation::BEGIN:
800 FATAL("invalid frame"); 831 case Translation::REGISTER:
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");
801 break; 846 break;
802 } 847 }
803 } 848 }
804 849
805 // Print some helpful diagnostic information. 850 // Print some helpful diagnostic information.
806 if (trace_scope_ != NULL) { 851 if (trace_scope_ != NULL) {
807 double ms = timer.Elapsed().InMillisecondsF(); 852 double ms = timer.Elapsed().InMillisecondsF();
808 int index = output_count_ - 1; // Index of the topmost frame. 853 int index = output_count_ - 1; // Index of the topmost frame.
809 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ", 854 PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
810 MessageFor(bailout_type_)); 855 MessageFor(bailout_type_));
811 PrintFunctionName(); 856 PrintFunctionName();
812 PrintF(trace_scope_->file(), 857 PrintF(trace_scope_->file(),
813 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s," 858 " @%d => node=%d, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
814 " took %0.3f ms]\n", 859 " took %0.3f ms]\n",
815 bailout_id_, 860 bailout_id_,
816 node_id.ToInt(), 861 node_id.ToInt(),
817 output_[index]->GetPc(), 862 output_[index]->GetPc(),
818 FullCodeGenerator::State2String( 863 FullCodeGenerator::State2String(
819 static_cast<FullCodeGenerator::State>( 864 static_cast<FullCodeGenerator::State>(
820 output_[index]->GetState()->value())), 865 output_[index]->GetState()->value())),
821 has_alignment_padding_ ? "with padding" : "no padding", 866 has_alignment_padding_ ? "with padding" : "no padding",
822 ms); 867 ms);
823 } 868 }
824 } 869 }
825 870
826 871
827 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, 872 void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
828 int frame_index) { 873 int frame_index) {
829 TranslatedFrame* translated_frame = 874 BailoutId node_id = BailoutId(iterator->Next());
830 &(translated_state_.frames()[frame_index]); 875 JSFunction* function;
831 TranslatedFrame::iterator value_iterator = translated_frame->begin(); 876 if (frame_index != 0) {
832 int input_index = 0; 877 function = JSFunction::cast(ComputeLiteral(iterator->Next()));
833 878 } else {
834 BailoutId node_id = translated_frame->node_id(); 879 int closure_id = iterator->Next();
835 JSFunction* function = translated_frame->raw_function(); 880 USE(closure_id);
836 unsigned height = 881 CHECK_EQ(Translation::kSelfLiteralId, closure_id);
837 translated_frame->height() - 1; // Do not count the context. 882 function = function_;
883 }
884 unsigned height = iterator->Next() - 1; // Do not count the context.
838 unsigned height_in_bytes = height * kPointerSize; 885 unsigned height_in_bytes = height * kPointerSize;
839 if (trace_scope_ != NULL) { 886 if (trace_scope_ != NULL) {
840 PrintF(trace_scope_->file(), " translating frame "); 887 PrintF(trace_scope_->file(), " translating ");
841 function->PrintName(trace_scope_->file()); 888 function->PrintName(trace_scope_->file());
842 PrintF(trace_scope_->file(), 889 PrintF(trace_scope_->file(),
843 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); 890 " => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes);
844 } 891 }
845 892
846 // The 'fixed' part of the frame consists of the incoming parameters and 893 // The 'fixed' part of the frame consists of the incoming parameters and
847 // the part described by JavaScriptFrameConstants. 894 // the part described by JavaScriptFrameConstants.
848 unsigned fixed_frame_size = ComputeFixedSize(function); 895 unsigned fixed_frame_size = ComputeFixedSize(function);
849 unsigned input_frame_size = input_->GetFrameSize(); 896 unsigned input_frame_size = input_->GetFrameSize();
850 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 897 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 } 931 }
885 output_frame->SetTop(top_address); 932 output_frame->SetTop(top_address);
886 933
887 // Compute the incoming parameter translation. 934 // Compute the incoming parameter translation.
888 int parameter_count = 935 int parameter_count =
889 function->shared()->internal_formal_parameter_count() + 1; 936 function->shared()->internal_formal_parameter_count() + 1;
890 unsigned output_offset = output_frame_size; 937 unsigned output_offset = output_frame_size;
891 unsigned input_offset = input_frame_size; 938 unsigned input_offset = input_frame_size;
892 for (int i = 0; i < parameter_count; ++i) { 939 for (int i = 0; i < parameter_count; ++i) {
893 output_offset -= kPointerSize; 940 output_offset -= kPointerSize;
894 WriteValueToOutput(&value_iterator, &input_index, frame_index, 941 DoTranslateCommand(iterator, frame_index, output_offset);
895 output_offset);
896 } 942 }
897 input_offset -= (parameter_count * kPointerSize); 943 input_offset -= (parameter_count * kPointerSize);
898 944
899 // There are no translation commands for the caller's pc and fp, the 945 // There are no translation commands for the caller's pc and fp, the
900 // context, and the function. Synthesize their values and set them up 946 // context, and the function. Synthesize their values and set them up
901 // explicitly. 947 // explicitly.
902 // 948 //
903 // The caller's pc for the bottommost output frame is the same as in the 949 // The caller's pc for the bottommost output frame is the same as in the
904 // input frame. For all subsequent output frames, it can be read from the 950 // input frame. For all subsequent output frames, it can be read from the
905 // previous one. This frame's pc can be computed from the non-optimized 951 // 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
965 } 1011 }
966 } 1012 }
967 1013
968 // For the bottommost output frame the context can be gotten from the input 1014 // For the bottommost output frame the context can be gotten from the input
969 // frame. For all subsequent output frames it can be gotten from the function 1015 // frame. For all subsequent output frames it can be gotten from the function
970 // so long as we don't inline functions that need local contexts. 1016 // so long as we don't inline functions that need local contexts.
971 Register context_reg = JavaScriptFrame::context_register(); 1017 Register context_reg = JavaScriptFrame::context_register();
972 output_offset -= kPointerSize; 1018 output_offset -= kPointerSize;
973 input_offset -= kPointerSize; 1019 input_offset -= kPointerSize;
974 // Read the context from the translations. 1020 // Read the context from the translations.
975 WriteValueToOutput(&value_iterator, &input_index, frame_index, output_offset); 1021 DoTranslateCommand(iterator, frame_index, output_offset);
976 value = output_frame->GetFrameSlot(output_offset); 1022 value = output_frame->GetFrameSlot(output_offset);
977 // The context should not be a placeholder for a materialized object. 1023 // The context should not be a placeholder for a materialized object.
978 CHECK(value != 1024 CHECK(value !=
979 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker())); 1025 reinterpret_cast<intptr_t>(isolate_->heap()->arguments_marker()));
980 if (value == 1026 if (value ==
981 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) { 1027 reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value())) {
982 // If the context was optimized away, just use the context from 1028 // If the context was optimized away, just use the context from
983 // the activation. This should only apply to Crankshaft code. 1029 // the activation. This should only apply to Crankshaft code.
984 CHECK(!compiled_code_->is_turbofanned()); 1030 CHECK(!compiled_code_->is_turbofanned());
985 if (is_bottommost) { 1031 if (is_bottommost) {
(...skipping 23 matching lines...) Expand all
1009 if (trace_scope_ != NULL) { 1055 if (trace_scope_ != NULL) {
1010 PrintF(trace_scope_->file(), 1056 PrintF(trace_scope_->file(),
1011 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1057 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1012 V8PRIxPTR "; function\n", 1058 V8PRIxPTR "; function\n",
1013 top_address + output_offset, output_offset, value); 1059 top_address + output_offset, output_offset, value);
1014 } 1060 }
1015 1061
1016 // Translate the rest of the frame. 1062 // Translate the rest of the frame.
1017 for (unsigned i = 0; i < height; ++i) { 1063 for (unsigned i = 0; i < height; ++i) {
1018 output_offset -= kPointerSize; 1064 output_offset -= kPointerSize;
1019 WriteValueToOutput(&value_iterator, &input_index, frame_index, 1065 DoTranslateCommand(iterator, frame_index, output_offset);
1020 output_offset);
1021 } 1066 }
1022 CHECK_EQ(0u, output_offset); 1067 CHECK_EQ(0u, output_offset);
1023 1068
1024 // Compute this frame's PC, state, and continuation. 1069 // Compute this frame's PC, state, and continuation.
1025 Code* non_optimized_code = function->shared()->code(); 1070 Code* non_optimized_code = function->shared()->code();
1026 FixedArray* raw_data = non_optimized_code->deoptimization_data(); 1071 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1027 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 1072 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1028 Address start = non_optimized_code->instruction_start(); 1073 Address start = non_optimized_code->instruction_start();
1029 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 1074 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1030 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 1075 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
(...skipping 28 matching lines...) Expand all
1059 CHECK_EQ(bailout_type_, EAGER); 1104 CHECK_EQ(bailout_type_, EAGER);
1060 } 1105 }
1061 output_frame->SetContinuation( 1106 output_frame->SetContinuation(
1062 reinterpret_cast<intptr_t>(continuation->entry())); 1107 reinterpret_cast<intptr_t>(continuation->entry()));
1063 } 1108 }
1064 } 1109 }
1065 1110
1066 1111
1067 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 1112 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
1068 int frame_index) { 1113 int frame_index) {
1069 TranslatedFrame* translated_frame = 1114 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
1070 &(translated_state_.frames()[frame_index]); 1115 unsigned height = iterator->Next();
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();
1076 unsigned height_in_bytes = height * kPointerSize; 1116 unsigned height_in_bytes = height * kPointerSize;
1077 if (trace_scope_ != NULL) { 1117 if (trace_scope_ != NULL) {
1078 PrintF(trace_scope_->file(), 1118 PrintF(trace_scope_->file(),
1079 " translating arguments adaptor => height=%d\n", height_in_bytes); 1119 " translating arguments adaptor => height=%d\n", height_in_bytes);
1080 } 1120 }
1081 1121
1082 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; 1122 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
1083 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1123 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1084 1124
1085 // Allocate and store the output frame description. 1125 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1096 // frame's top and this frame's size. 1136 // frame's top and this frame's size.
1097 intptr_t top_address; 1137 intptr_t top_address;
1098 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1138 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1099 output_frame->SetTop(top_address); 1139 output_frame->SetTop(top_address);
1100 1140
1101 // Compute the incoming parameter translation. 1141 // Compute the incoming parameter translation.
1102 int parameter_count = height; 1142 int parameter_count = height;
1103 unsigned output_offset = output_frame_size; 1143 unsigned output_offset = output_frame_size;
1104 for (int i = 0; i < parameter_count; ++i) { 1144 for (int i = 0; i < parameter_count; ++i) {
1105 output_offset -= kPointerSize; 1145 output_offset -= kPointerSize;
1106 WriteValueToOutput(&value_iterator, &input_index, frame_index, 1146 DoTranslateCommand(iterator, frame_index, output_offset);
1107 output_offset);
1108 } 1147 }
1109 1148
1110 // Read caller's PC from the previous frame. 1149 // Read caller's PC from the previous frame.
1111 output_offset -= kPCOnStackSize; 1150 output_offset -= kPCOnStackSize;
1112 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1151 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1113 output_frame->SetCallerPc(output_offset, callers_pc); 1152 output_frame->SetCallerPc(output_offset, callers_pc);
1114 if (trace_scope_ != NULL) { 1153 if (trace_scope_ != NULL) {
1115 PrintF(trace_scope_->file(), 1154 PrintF(trace_scope_->file(),
1116 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1155 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1117 V8PRIxPTR " ; caller's pc\n", 1156 V8PRIxPTR " ; caller's pc\n",
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 if (FLAG_enable_ool_constant_pool) { 1228 if (FLAG_enable_ool_constant_pool) {
1190 intptr_t constant_pool_value = 1229 intptr_t constant_pool_value =
1191 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool()); 1230 reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
1192 output_frame->SetConstantPool(constant_pool_value); 1231 output_frame->SetConstantPool(constant_pool_value);
1193 } 1232 }
1194 } 1233 }
1195 1234
1196 1235
1197 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, 1236 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
1198 int frame_index) { 1237 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
1204 Builtins* builtins = isolate_->builtins(); 1238 Builtins* builtins = isolate_->builtins();
1205 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); 1239 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
1206 JSFunction* function = translated_frame->raw_function(); 1240 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
1207 unsigned height = translated_frame->height(); 1241 unsigned height = iterator->Next();
1208 unsigned height_in_bytes = height * kPointerSize; 1242 unsigned height_in_bytes = height * kPointerSize;
1209 if (trace_scope_ != NULL) { 1243 if (trace_scope_ != NULL) {
1210 PrintF(trace_scope_->file(), 1244 PrintF(trace_scope_->file(),
1211 " translating construct stub => height=%d\n", height_in_bytes); 1245 " translating construct stub => height=%d\n", height_in_bytes);
1212 } 1246 }
1213 1247
1214 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize; 1248 unsigned fixed_frame_size = ConstructFrameConstants::kFrameSize;
1215 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 1249 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1216 1250
1217 // Allocate and store the output frame description. 1251 // Allocate and store the output frame description.
(...skipping 10 matching lines...) Expand all
1228 // frame's top and this frame's size. 1262 // frame's top and this frame's size.
1229 intptr_t top_address; 1263 intptr_t top_address;
1230 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 1264 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1231 output_frame->SetTop(top_address); 1265 output_frame->SetTop(top_address);
1232 1266
1233 // Compute the incoming parameter translation. 1267 // Compute the incoming parameter translation.
1234 int parameter_count = height; 1268 int parameter_count = height;
1235 unsigned output_offset = output_frame_size; 1269 unsigned output_offset = output_frame_size;
1236 for (int i = 0; i < parameter_count; ++i) { 1270 for (int i = 0; i < parameter_count; ++i) {
1237 output_offset -= kPointerSize; 1271 output_offset -= kPointerSize;
1272 int deferred_object_index = deferred_objects_.length();
1273 DoTranslateCommand(iterator, frame_index, output_offset);
1238 // The allocated receiver of a construct stub frame is passed as the 1274 // The allocated receiver of a construct stub frame is passed as the
1239 // receiver parameter through the translation. It might be encoding 1275 // receiver parameter through the translation. It might be encoding
1240 // a captured object, override the slot address for a captured object. 1276 // a captured object, patch the slot address for a captured object.
1241 WriteValueToOutput( 1277 if (i == 0 && deferred_objects_.length() > deferred_object_index) {
1242 &value_iterator, &input_index, frame_index, output_offset, 1278 CHECK(!deferred_objects_[deferred_object_index].is_arguments());
1243 (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr); 1279 deferred_objects_[deferred_object_index].patch_slot_address(top_address);
1280 }
1244 } 1281 }
1245 1282
1246 // Read caller's PC from the previous frame. 1283 // Read caller's PC from the previous frame.
1247 output_offset -= kPCOnStackSize; 1284 output_offset -= kPCOnStackSize;
1248 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 1285 intptr_t callers_pc = output_[frame_index - 1]->GetPc();
1249 output_frame->SetCallerPc(output_offset, callers_pc); 1286 output_frame->SetCallerPc(output_offset, callers_pc);
1250 if (trace_scope_ != NULL) { 1287 if (trace_scope_ != NULL) {
1251 PrintF(trace_scope_->file(), 1288 PrintF(trace_scope_->file(),
1252 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1289 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1253 V8PRIxPTR " ; caller's pc\n", 1290 V8PRIxPTR " ; caller's pc\n",
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 intptr_t constant_pool_value = 1396 intptr_t constant_pool_value =
1360 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); 1397 reinterpret_cast<intptr_t>(construct_stub->constant_pool());
1361 output_frame->SetConstantPool(constant_pool_value); 1398 output_frame->SetConstantPool(constant_pool_value);
1362 } 1399 }
1363 } 1400 }
1364 1401
1365 1402
1366 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator, 1403 void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
1367 int frame_index, 1404 int frame_index,
1368 bool is_setter_stub_frame) { 1405 bool is_setter_stub_frame) {
1369 TranslatedFrame* translated_frame = 1406 JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
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();
1375 // The receiver (and the implicit return value, if any) are expected in 1407 // The receiver (and the implicit return value, if any) are expected in
1376 // registers by the LoadIC/StoreIC, so they don't belong to the output stack 1408 // registers by the LoadIC/StoreIC, so they don't belong to the output stack
1377 // frame. This means that we have to use a height of 0. 1409 // frame. This means that we have to use a height of 0.
1378 unsigned height = 0; 1410 unsigned height = 0;
1379 unsigned height_in_bytes = height * kPointerSize; 1411 unsigned height_in_bytes = height * kPointerSize;
1380 const char* kind = is_setter_stub_frame ? "setter" : "getter"; 1412 const char* kind = is_setter_stub_frame ? "setter" : "getter";
1381 if (trace_scope_ != NULL) { 1413 if (trace_scope_ != NULL) {
1382 PrintF(trace_scope_->file(), 1414 PrintF(trace_scope_->file(),
1383 " translating %s stub => height=%u\n", kind, height_in_bytes); 1415 " translating %s stub => height=%u\n", kind, height_in_bytes);
1384 } 1416 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 value = reinterpret_cast<intptr_t>(accessor_stub); 1510 value = reinterpret_cast<intptr_t>(accessor_stub);
1479 output_frame->SetFrameSlot(output_offset, value); 1511 output_frame->SetFrameSlot(output_offset, value);
1480 if (trace_scope_ != NULL) { 1512 if (trace_scope_ != NULL) {
1481 PrintF(trace_scope_->file(), 1513 PrintF(trace_scope_->file(),
1482 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR 1514 " 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
1483 " ; code object\n", 1515 " ; code object\n",
1484 top_address + output_offset, output_offset, value); 1516 top_address + output_offset, output_offset, value);
1485 } 1517 }
1486 1518
1487 // Skip receiver. 1519 // Skip receiver.
1488 value_iterator++; 1520 DoTranslateObjectAndSkip(iterator);
1489 1521
1490 if (is_setter_stub_frame) { 1522 if (is_setter_stub_frame) {
1491 // The implicit return value was part of the artificial setter stub 1523 // The implicit return value was part of the artificial setter stub
1492 // environment. 1524 // environment.
1493 output_offset -= kPointerSize; 1525 output_offset -= kPointerSize;
1494 WriteValueToOutput(&value_iterator, &input_index, frame_index, 1526 DoTranslateCommand(iterator, frame_index, output_offset);
1495 output_offset);
1496 } 1527 }
1497 1528
1498 CHECK_EQ(0u, output_offset); 1529 CHECK_EQ(0u, output_offset);
1499 1530
1500 Smi* offset = is_setter_stub_frame ? 1531 Smi* offset = is_setter_stub_frame ?
1501 isolate_->heap()->setter_stub_deopt_pc_offset() : 1532 isolate_->heap()->setter_stub_deopt_pc_offset() :
1502 isolate_->heap()->getter_stub_deopt_pc_offset(); 1533 isolate_->heap()->getter_stub_deopt_pc_offset();
1503 intptr_t pc = reinterpret_cast<intptr_t>( 1534 intptr_t pc = reinterpret_cast<intptr_t>(
1504 accessor_stub->instruction_start() + offset->value()); 1535 accessor_stub->instruction_start() + offset->value());
1505 output_frame->SetPc(pc); 1536 output_frame->SetPc(pc);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 // and spilled to stack | .... | 1569 // and spilled to stack | .... |
1539 // +-------------------------+ 1570 // +-------------------------+
1540 // | caller stack param n | 1571 // | caller stack param n |
1541 // +-------------------------+<-spreg 1572 // +-------------------------+<-spreg
1542 // reg = number of parameters 1573 // reg = number of parameters
1543 // reg = failure handler address 1574 // reg = failure handler address
1544 // reg = saved frame 1575 // reg = saved frame
1545 // reg = JSFunction context 1576 // reg = JSFunction context
1546 // 1577 //
1547 1578
1548 TranslatedFrame* translated_frame =
1549 &(translated_state_.frames()[frame_index]);
1550 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1551 int input_index = 0;
1552
1553 CHECK(compiled_code_->is_hydrogen_stub()); 1579 CHECK(compiled_code_->is_hydrogen_stub());
1554 int major_key = CodeStub::GetMajorKey(compiled_code_); 1580 int major_key = CodeStub::GetMajorKey(compiled_code_);
1555 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key()); 1581 CodeStubDescriptor descriptor(isolate_, compiled_code_->stub_key());
1556 1582
1557 // The output frame must have room for all pushed register parameters 1583 // The output frame must have room for all pushed register parameters
1558 // and the standard stack frame slots. Include space for an argument 1584 // and the standard stack frame slots. Include space for an argument
1559 // object to the callee and optionally the space to pass the argument 1585 // object to the callee and optionally the space to pass the argument
1560 // object to the stub failure handler. 1586 // object to the stub failure handler.
1561 int param_count = descriptor.GetEnvironmentParameterCount(); 1587 int param_count = descriptor.GetEnvironmentParameterCount();
1562 CHECK_EQ(translated_frame->height(), param_count);
1563 CHECK_GE(param_count, 0); 1588 CHECK_GE(param_count, 0);
1564 1589
1565 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) + 1590 int height_in_bytes = kPointerSize * param_count + sizeof(Arguments) +
1566 kPointerSize; 1591 kPointerSize;
1567 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize; 1592 int fixed_frame_size = StandardFrameConstants::kFixedFrameSize;
1568 int input_frame_size = input_->GetFrameSize(); 1593 int input_frame_size = input_->GetFrameSize();
1569 int output_frame_size = height_in_bytes + fixed_frame_size; 1594 int output_frame_size = height_in_bytes + fixed_frame_size;
1570 if (trace_scope_ != NULL) { 1595 if (trace_scope_ != NULL) {
1571 PrintF(trace_scope_->file(), 1596 PrintF(trace_scope_->file(),
1572 " translating %s => StubFailureTrampolineStub, height=%d\n", 1597 " translating %s => StubFailureTrampolineStub, height=%d\n",
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1700 PrintF(trace_scope_->file(), 1725 PrintF(trace_scope_->file(),
1701 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1726 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
1702 V8PRIxPTR " ; args*\n", 1727 V8PRIxPTR " ; args*\n",
1703 top_address + output_frame_offset, output_frame_offset, value); 1728 top_address + output_frame_offset, output_frame_offset, value);
1704 } 1729 }
1705 1730
1706 // Copy the register parameters to the failure frame. 1731 // Copy the register parameters to the failure frame.
1707 int arguments_length_offset = -1; 1732 int arguments_length_offset = -1;
1708 for (int i = 0; i < param_count; ++i) { 1733 for (int i = 0; i < param_count; ++i) {
1709 output_frame_offset -= kPointerSize; 1734 output_frame_offset -= kPointerSize;
1710 WriteValueToOutput(&value_iterator, &input_index, 0, output_frame_offset); 1735 DoTranslateCommand(iterator, 0, output_frame_offset);
1711 1736
1712 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) { 1737 if (!arg_count_known && descriptor.IsEnvironmentParameterCountRegister(i)) {
1713 arguments_length_offset = output_frame_offset; 1738 arguments_length_offset = output_frame_offset;
1714 } 1739 }
1715 } 1740 }
1716 1741
1717 CHECK_EQ(0u, output_frame_offset); 1742 CHECK_EQ(0u, output_frame_offset);
1718 1743
1719 if (!arg_count_known) { 1744 if (!arg_count_known) {
1720 CHECK_GE(arguments_length_offset, 0); 1745 CHECK_GE(arguments_length_offset, 0);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); 1792 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1768 } 1793 }
1769 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); 1794 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
1770 Code* notify_failure = 1795 Code* notify_failure =
1771 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles); 1796 isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
1772 output_frame->SetContinuation( 1797 output_frame->SetContinuation(
1773 reinterpret_cast<intptr_t>(notify_failure->entry())); 1798 reinterpret_cast<intptr_t>(notify_failure->entry()));
1774 } 1799 }
1775 1800
1776 1801
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
1777 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { 1920 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
1778 DCHECK_NE(DEBUGGER, bailout_type_); 1921 DCHECK_NE(DEBUGGER, bailout_type_);
1779 1922
1780 // Walk to the last JavaScript output frame to find out if it has 1923 MaterializedObjectStore* materialized_store =
1781 // adapted arguments. 1924 isolate_->materialized_object_store();
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.
1782 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { 1930 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) {
1783 if (frame_index != 0) it->Advance(); 1931 if (frame_index != 0) it->Advance();
1784 } 1932 JavaScriptFrame* frame = it->frame();
1785 translated_state_.Prepare(it->frame()->has_adapted_arguments(), stack_fp_); 1933 jsframe_functions_.Add(handle(frame->function(), isolate_));
1786 1934 jsframe_has_adapted_arguments_.Add(frame->has_adapted_arguments());
1787 for (auto& materialization : values_to_materialize_) { 1935 }
1788 Handle<Object> value = materialization.value_->GetValue(); 1936
1789 1937 // Handlify all tagged object values before triggering any allocation.
1790 if (trace_scope_ != nullptr) { 1938 List<Handle<Object> > values(deferred_objects_tagged_values_.length());
1791 PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ; ", 1939 for (int i = 0; i < deferred_objects_tagged_values_.length(); ++i) {
1792 reinterpret_cast<intptr_t>(materialization.output_slot_address_), 1940 values.Add(Handle<Object>(deferred_objects_tagged_values_[i], isolate_));
1793 reinterpret_cast<intptr_t>(*value)); 1941 }
1794 value->ShortPrint(trace_scope_->file()); 1942
1795 PrintF(trace_scope_->file(), "\n"); 1943 // Play it safe and clear all unhandlified values before we continue.
1796 } 1944 deferred_objects_tagged_values_.Clear();
1797 1945
1798 *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) = 1946 // Materialize all heap numbers before looking at arguments because when the
1799 reinterpret_cast<intptr_t>(*value); 1947 // output frames are used to materialize arguments objects later on they need
1800 } 1948 // to already contain valid heap numbers.
1801 1949 for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
1802 isolate_->materialized_object_store()->Remove(stack_fp_); 1950 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
1951 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1952 if (trace_scope_ != NULL) {
1953 PrintF(trace_scope_->file(),
1954 "Materialized a new heap number %p [%e] in slot %p\n",
1955 reinterpret_cast<void*>(*num),
1956 d.value(),
1957 d.destination());
1958 }
1959 Memory::Object_at(d.destination()) = *num;
1960 }
1961
1962 // Materialize all heap numbers required for arguments/captured objects.
1963 for (int i = 0; i < deferred_objects_double_values_.length(); i++) {
1964 HeapNumberMaterializationDescriptor<int> d =
1965 deferred_objects_double_values_[i];
1966 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1967 if (trace_scope_ != NULL) {
1968 PrintF(trace_scope_->file(),
1969 "Materialized a new heap number %p [%e] for object at %d\n",
1970 reinterpret_cast<void*>(*num),
1971 d.value(),
1972 d.destination());
1973 }
1974 DCHECK(values.at(d.destination())->IsTheHole());
1975 values.Set(d.destination(), num);
1976 }
1977
1978 // Play it safe and clear all object double values before we continue.
1979 deferred_objects_double_values_.Clear();
1980
1981 // Materialize arguments/captured objects.
1982 if (!deferred_objects_.is_empty()) {
1983 List<Handle<Object> > materialized_objects(deferred_objects_.length());
1984 materialized_objects_ = &materialized_objects;
1985 materialized_values_ = &values;
1986
1987 while (materialization_object_index_ < deferred_objects_.length()) {
1988 int object_index = materialization_object_index_;
1989 ObjectMaterializationDescriptor descriptor =
1990 deferred_objects_.at(object_index);
1991
1992 // Find a previously materialized object by de-duplication or
1993 // materialize a new instance of the object if necessary. Store
1994 // the materialized object into the frame slot.
1995 Handle<Object> object = MaterializeNextHeapObject();
1996 if (descriptor.slot_address() != NULL) {
1997 Memory::Object_at(descriptor.slot_address()) = *object;
1998 }
1999 if (trace_scope_ != NULL) {
2000 if (descriptor.is_arguments()) {
2001 PrintF(trace_scope_->file(),
2002 "Materialized %sarguments object of length %d for %p: ",
2003 ArgumentsObjectIsAdapted(object_index) ? "(adapted) " : "",
2004 Handle<JSObject>::cast(object)->elements()->length(),
2005 reinterpret_cast<void*>(descriptor.slot_address()));
2006 } else {
2007 PrintF(trace_scope_->file(),
2008 "Materialized captured object of size %d for %p: ",
2009 Handle<HeapObject>::cast(object)->Size(),
2010 reinterpret_cast<void*>(descriptor.slot_address()));
2011 }
2012 object->ShortPrint(trace_scope_->file());
2013 PrintF(trace_scope_->file(), "\n");
2014 }
2015 }
2016
2017 CHECK_EQ(materialization_object_index_, materialized_objects_->length());
2018 CHECK_EQ(materialization_value_index_, materialized_values_->length());
2019 }
2020
2021 if (prev_materialized_count_ > 0) {
2022 bool removed = materialized_store->Remove(stack_fp_);
2023 CHECK(removed);
2024 }
1803 } 2025 }
1804 2026
1805 2027
1806 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( 2028 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
1807 int frame_index, int parameter_count, int expression_count, 2029 Address parameters_top,
2030 uint32_t parameters_size,
2031 Address expressions_top,
2032 uint32_t expressions_size,
1808 DeoptimizedFrameInfo* info) { 2033 DeoptimizedFrameInfo* info) {
1809 CHECK_EQ(DEBUGGER, bailout_type_); 2034 CHECK_EQ(DEBUGGER, bailout_type_);
1810 2035 Address parameters_bottom = parameters_top + parameters_size;
1811 translated_state_.Prepare(false, nullptr); 2036 Address expressions_bottom = expressions_top + expressions_size;
1812 2037 for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
1813 TranslatedFrame* frame = &(translated_state_.frames()[frame_index]); 2038 HeapNumberMaterializationDescriptor<Address> d = deferred_heap_numbers_[i];
1814 CHECK(frame->kind() == TranslatedFrame::kFunction); 2039
1815 int frame_arg_count = 2040 // Check of the heap number to materialize actually belong to the frame
1816 frame->function()->shared()->internal_formal_parameter_count(); 2041 // being extracted.
1817 2042 Address slot = d.destination();
1818 // The height is #expressions + 1 for context. 2043 if (parameters_top <= slot && slot < parameters_bottom) {
1819 CHECK_EQ(expression_count + 1, frame->height()); 2044 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1820 TranslatedFrame* argument_frame = frame; 2045
1821 if (frame_index > 0) { 2046 int index = (info->parameters_count() - 1) -
1822 TranslatedFrame* previous_frame = 2047 static_cast<int>(slot - parameters_top) / kPointerSize;
1823 &(translated_state_.frames()[frame_index - 1]); 2048
1824 if (previous_frame->kind() == TranslatedFrame::kArgumentsAdaptor) { 2049 if (trace_scope_ != NULL) {
1825 argument_frame = previous_frame; 2050 PrintF(trace_scope_->file(),
1826 CHECK_EQ(parameter_count, argument_frame->height() - 1); 2051 "Materializing a new heap number %p [%e] in slot %p"
1827 } else { 2052 "for parameter slot #%d\n",
1828 CHECK_EQ(frame_arg_count, parameter_count); 2053 reinterpret_cast<void*>(*num),
1829 } 2054 d.value(),
1830 } else { 2055 d.destination(),
1831 CHECK_EQ(frame_arg_count, parameter_count); 2056 index);
1832 } 2057 }
1833 2058
1834 TranslatedFrame::iterator arg_iter = argument_frame->begin(); 2059 info->SetParameter(index, *num);
1835 arg_iter++; // Skip the receiver. 2060 } else if (expressions_top <= slot && slot < expressions_bottom) {
1836 for (int i = 0; i < parameter_count; i++, arg_iter++) { 2061 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
1837 if (!arg_iter->IsMaterializedObject()) { 2062
1838 info->SetParameter(i, *(arg_iter->GetValue())); 2063 int index = info->expression_count() - 1 -
1839 } 2064 static_cast<int>(slot - expressions_top) / kPointerSize;
1840 } 2065
1841 2066 if (trace_scope_ != NULL) {
1842 TranslatedFrame::iterator iter = frame->begin(); 2067 PrintF(trace_scope_->file(),
1843 // Skip the arguments, receiver and context. 2068 "Materializing a new heap number %p [%e] in slot %p"
1844 for (int i = 0; i < frame_arg_count + 2; i++, iter++) { 2069 "for expression slot #%d\n",
1845 } 2070 reinterpret_cast<void*>(*num),
1846 2071 d.value(),
1847 for (int i = 0; i < expression_count; i++, iter++) { 2072 d.destination(),
1848 if (!iter->IsMaterializedObject()) { 2073 index);
1849 info->SetExpression(i, *(iter->GetValue())); 2074 }
2075
2076 info->SetExpression(index, *num);
1850 } 2077 }
1851 } 2078 }
1852 } 2079 }
1853 2080
1854 2081
1855 void Deoptimizer::WriteValueToOutput( 2082 static const char* TraceValueType(bool is_smi) {
1856 TranslatedFrame::iterator* iterator, int* input_index, int frame_index, 2083 if (is_smi) {
1857 unsigned output_offset, Address output_address_for_materialization) { 2084 return "smi";
1858 Object* value = (*iterator)->GetRawValue(); 2085 }
1859 output_[frame_index]->SetFrameSlot(output_offset, 2086
1860 reinterpret_cast<intptr_t>(value)); 2087 return "heap number";
1861
1862 Address output_address =
1863 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + output_offset;
1864 if (trace_scope_ != nullptr) {
1865 PrintF(trace_scope_->file(),
1866 " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; ",
1867 reinterpret_cast<intptr_t>(output_address), output_offset,
1868 reinterpret_cast<intptr_t>(value));
1869 value->ShortPrint(trace_scope_->file());
1870 PrintF(trace_scope_->file(), " (input #%d)\n", *input_index);
1871 }
1872
1873 if (value == isolate_->heap()->arguments_marker()) {
1874 if (output_address_for_materialization == nullptr) {
1875 output_address_for_materialization = output_address;
1876 }
1877 values_to_materialize_.push_back(
1878 {output_address_for_materialization, *iterator});
1879 }
1880
1881 (*iterator)++;
1882 (*input_index)++;
1883 } 2088 }
1884 2089
1885 2090
2091 void Deoptimizer::DoTranslateObjectAndSkip(TranslationIterator* iterator) {
2092 Translation::Opcode opcode =
2093 static_cast<Translation::Opcode>(iterator->Next());
2094
2095 switch (opcode) {
2096 case Translation::BEGIN:
2097 case Translation::JS_FRAME:
2098 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2099 case Translation::CONSTRUCT_STUB_FRAME:
2100 case Translation::GETTER_STUB_FRAME:
2101 case Translation::SETTER_STUB_FRAME:
2102 case Translation::COMPILED_STUB_FRAME: {
2103 FATAL("Unexpected frame start translation opcode");
2104 return;
2105 }
2106
2107 case Translation::REGISTER:
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 }
2832
2833
1886 unsigned Deoptimizer::ComputeInputFrameSize() const { 2834 unsigned Deoptimizer::ComputeInputFrameSize() const {
1887 unsigned fixed_size = ComputeFixedSize(function_); 2835 unsigned fixed_size = ComputeFixedSize(function_);
1888 // The fp-to-sp delta already takes the context, constant pool pointer and the 2836 // The fp-to-sp delta already takes the context, constant pool pointer and the
1889 // function into account so we have to avoid double counting them. 2837 // function into account so we have to avoid double counting them.
1890 unsigned result = fixed_size + fp_to_sp_delta_ - 2838 unsigned result = fixed_size + fp_to_sp_delta_ -
1891 StandardFrameConstants::kFixedFrameSizeFromFp; 2839 StandardFrameConstants::kFixedFrameSizeFromFp;
1892 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { 2840 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
1893 unsigned stack_slots = compiled_code_->stack_slots(); 2841 unsigned stack_slots = compiled_code_->stack_slots();
1894 unsigned outgoing_size = ComputeOutgoingArgumentSize(); 2842 unsigned outgoing_size = ComputeOutgoingArgumentSize();
1895 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 2843 CHECK(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
1896 } 2844 }
1897 return result; 2845 return result;
1898 } 2846 }
1899 2847
1900 2848
1901 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 2849 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
1902 // The fixed part of the frame consists of the return address, frame 2850 // The fixed part of the frame consists of the return address, frame
1903 // pointer, function, context, and all the incoming arguments. 2851 // pointer, function, context, and all the incoming arguments.
1904 return ComputeIncomingArgumentSize(function) + 2852 return ComputeIncomingArgumentSize(function) +
1905 StandardFrameConstants::kFixedFrameSize; 2853 StandardFrameConstants::kFixedFrameSize;
1906 } 2854 }
1907 2855
1908 2856
1909 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 2857 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
1910 // The incoming arguments is the values for formal parameters and 2858 // The incoming arguments is the values for formal parameters and
1911 // the receiver. Every slot contains a pointer. 2859 // the receiver. Every slot contains a pointer.
1912 if (function->IsSmi()) { 2860 if (function->IsSmi()) {
1913 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB)); 2861 CHECK_EQ(Smi::cast(function), Smi::FromInt(StackFrame::STUB));
1914 return 0; 2862 return 0;
1915 } 2863 }
1916 unsigned arguments = 2864 unsigned arguments =
1917 function->shared()->internal_formal_parameter_count() + 1; 2865 function->shared()->internal_formal_parameter_count() + 1;
1918 return arguments * kPointerSize; 2866 return arguments * kPointerSize;
1919 } 2867 }
1920 2868
1921 2869
1922 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 2870 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
1923 DeoptimizationInputData* data = 2871 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1924 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); 2872 compiled_code_->deoptimization_data());
1925 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 2873 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
1926 return height * kPointerSize; 2874 return height * kPointerSize;
1927 } 2875 }
1928 2876
1929 2877
1930 Object* Deoptimizer::ComputeLiteral(int index) const { 2878 Object* Deoptimizer::ComputeLiteral(int index) const {
1931 DeoptimizationInputData* data = 2879 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1932 DeoptimizationInputData::cast(compiled_code_->deoptimization_data()); 2880 compiled_code_->deoptimization_data());
1933 FixedArray* literals = data->LiteralArray(); 2881 FixedArray* literals = data->LiteralArray();
1934 return literals->get(index); 2882 return literals->get(index);
1935 } 2883 }
1936 2884
1937 2885
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
1938 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate, 2920 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
1939 BailoutType type, 2921 BailoutType type,
1940 int max_entry_id) { 2922 int max_entry_id) {
1941 // We cannot run this if the serializer is enabled because this will 2923 // We cannot run this if the serializer is enabled because this will
1942 // cause us to emit relocation information for the external 2924 // cause us to emit relocation information for the external
1943 // references. This is fine because the deoptimizer's code section 2925 // references. This is fine because the deoptimizer's code section
1944 // isn't meant to be serialized at all. 2926 // isn't meant to be serialized at all.
1945 CHECK(type == EAGER || type == SOFT || type == LAZY); 2927 CHECK(type == EAGER || type == SOFT || type == LAZY);
1946 DeoptimizerData* data = isolate->deoptimizer_data(); 2928 DeoptimizerData* data = isolate->deoptimizer_data();
1947 int entry_count = data->deopt_entry_code_entries_[type]; 2929 int entry_count = data->deopt_entry_code_entries_[type];
(...skipping 10 matching lines...) Expand all
1958 DCHECK(!RelocInfo::RequiresRelocation(desc)); 2940 DCHECK(!RelocInfo::RequiresRelocation(desc));
1959 2941
1960 MemoryChunk* chunk = data->deopt_entry_code_[type]; 2942 MemoryChunk* chunk = data->deopt_entry_code_[type];
1961 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >= 2943 CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
1962 desc.instr_size); 2944 desc.instr_size);
1963 if (!chunk->CommitArea(desc.instr_size)) { 2945 if (!chunk->CommitArea(desc.instr_size)) {
1964 V8::FatalProcessOutOfMemory( 2946 V8::FatalProcessOutOfMemory(
1965 "Deoptimizer::EnsureCodeForDeoptimizationEntry"); 2947 "Deoptimizer::EnsureCodeForDeoptimizationEntry");
1966 } 2948 }
1967 CopyBytes(chunk->area_start(), desc.buffer, 2949 CopyBytes(chunk->area_start(), desc.buffer,
1968 static_cast<size_t>(desc.instr_size)); 2950 static_cast<size_t>(desc.instr_size));
1969 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size); 2951 CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size);
1970 2952
1971 data->deopt_entry_code_entries_[type] = entry_count; 2953 data->deopt_entry_code_entries_[type] = entry_count;
1972 } 2954 }
1973 2955
1974 2956
1975 FrameDescription::FrameDescription(uint32_t frame_size, 2957 FrameDescription::FrameDescription(uint32_t frame_size,
1976 JSFunction* function) 2958 JSFunction* function)
1977 : frame_size_(frame_size), 2959 : frame_size_(frame_size),
1978 function_(function), 2960 function_(function),
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2129 void Translation::BeginJSFrame(BailoutId node_id, 3111 void Translation::BeginJSFrame(BailoutId node_id,
2130 int literal_id, 3112 int literal_id,
2131 unsigned height) { 3113 unsigned height) {
2132 buffer_->Add(JS_FRAME, zone()); 3114 buffer_->Add(JS_FRAME, zone());
2133 buffer_->Add(node_id.ToInt(), zone()); 3115 buffer_->Add(node_id.ToInt(), zone());
2134 buffer_->Add(literal_id, zone()); 3116 buffer_->Add(literal_id, zone());
2135 buffer_->Add(height, zone()); 3117 buffer_->Add(height, zone());
2136 } 3118 }
2137 3119
2138 3120
2139 void Translation::BeginCompiledStubFrame(int height) { 3121 void Translation::BeginCompiledStubFrame() {
2140 buffer_->Add(COMPILED_STUB_FRAME, zone()); 3122 buffer_->Add(COMPILED_STUB_FRAME, zone());
2141 buffer_->Add(height, zone());
2142 } 3123 }
2143 3124
2144 3125
2145 void Translation::BeginArgumentsObject(int args_length) { 3126 void Translation::BeginArgumentsObject(int args_length) {
2146 buffer_->Add(ARGUMENTS_OBJECT, zone()); 3127 buffer_->Add(ARGUMENTS_OBJECT, zone());
2147 buffer_->Add(args_length, zone()); 3128 buffer_->Add(args_length, zone());
2148 } 3129 }
2149 3130
2150 3131
2151 void Translation::BeginCapturedObject(int length) { 3132 void Translation::BeginCapturedObject(int length) {
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE) 3257 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
2277 } 3258 }
2278 #undef TRANSLATION_OPCODE_CASE 3259 #undef TRANSLATION_OPCODE_CASE
2279 UNREACHABLE(); 3260 UNREACHABLE();
2280 return ""; 3261 return "";
2281 } 3262 }
2282 3263
2283 #endif 3264 #endif
2284 3265
2285 3266
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
2286 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) { 3694 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2287 int index = StackIdToIndex(fp); 3695 int index = StackIdToIndex(fp);
2288 if (index == -1) { 3696 if (index == -1) {
2289 return Handle<FixedArray>::null(); 3697 return Handle<FixedArray>::null();
2290 } 3698 }
2291 Handle<FixedArray> array = GetStackEntries(); 3699 Handle<FixedArray> array = GetStackEntries();
2292 CHECK_GT(array->length(), index); 3700 CHECK_GT(array->length(), index);
2293 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate())); 3701 return Handle<FixedArray>::cast(Handle<Object>(array->get(index),
3702 isolate()));
2294 } 3703 }
2295 3704
2296 3705
2297 void MaterializedObjectStore::Set(Address fp, 3706 void MaterializedObjectStore::Set(Address fp,
2298 Handle<FixedArray> materialized_objects) { 3707 Handle<FixedArray> materialized_objects) {
2299 int index = StackIdToIndex(fp); 3708 int index = StackIdToIndex(fp);
2300 if (index == -1) { 3709 if (index == -1) {
2301 index = frame_fps_.length(); 3710 index = frame_fps_.length();
2302 frame_fps_.Add(fp); 3711 frame_fps_.Add(fp);
2303 } 3712 }
2304 3713
2305 Handle<FixedArray> array = EnsureStackEntries(index + 1); 3714 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2306 array->set(index, *materialized_objects); 3715 array->set(index, *materialized_objects);
2307 } 3716 }
2308 3717
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 3775
2367 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer, 3776 DeoptimizedFrameInfo::DeoptimizedFrameInfo(Deoptimizer* deoptimizer,
2368 int frame_index, 3777 int frame_index,
2369 bool has_arguments_adaptor, 3778 bool has_arguments_adaptor,
2370 bool has_construct_stub) { 3779 bool has_construct_stub) {
2371 FrameDescription* output_frame = deoptimizer->output_[frame_index]; 3780 FrameDescription* output_frame = deoptimizer->output_[frame_index];
2372 function_ = output_frame->GetFunction(); 3781 function_ = output_frame->GetFunction();
2373 context_ = reinterpret_cast<Object*>(output_frame->GetContext()); 3782 context_ = reinterpret_cast<Object*>(output_frame->GetContext());
2374 has_construct_stub_ = has_construct_stub; 3783 has_construct_stub_ = has_construct_stub;
2375 expression_count_ = output_frame->GetExpressionCount(); 3784 expression_count_ = output_frame->GetExpressionCount();
2376 expression_stack_ = new Object* [expression_count_]; 3785 expression_stack_ = new Object*[expression_count_];
2377 // Get the source position using the unoptimized code. 3786 // Get the source position using the unoptimized code.
2378 Address pc = reinterpret_cast<Address>(output_frame->GetPc()); 3787 Address pc = reinterpret_cast<Address>(output_frame->GetPc());
2379 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc)); 3788 Code* code = Code::cast(deoptimizer->isolate()->FindCodeObject(pc));
2380 source_position_ = code->SourcePosition(pc); 3789 source_position_ = code->SourcePosition(pc);
2381 3790
2382 for (int i = 0; i < expression_count_; i++) { 3791 for (int i = 0; i < expression_count_; i++) {
2383 SetExpression(i, output_frame->GetExpression(i)); 3792 SetExpression(i, output_frame->GetExpression(i));
2384 } 3793 }
2385 3794
2386 if (has_arguments_adaptor) { 3795 if (has_arguments_adaptor) {
2387 output_frame = deoptimizer->output_[frame_index - 1]; 3796 output_frame = deoptimizer->output_[frame_index - 1];
2388 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR); 3797 CHECK_EQ(output_frame->GetFrameType(), StackFrame::ARGUMENTS_ADAPTOR);
2389 } 3798 }
2390 3799
2391 parameters_count_ = output_frame->ComputeParametersCount(); 3800 parameters_count_ = output_frame->ComputeParametersCount();
2392 parameters_ = new Object* [parameters_count_]; 3801 parameters_ = new Object*[parameters_count_];
2393 for (int i = 0; i < parameters_count_; i++) { 3802 for (int i = 0; i < parameters_count_; i++) {
2394 SetParameter(i, output_frame->GetParameter(i)); 3803 SetParameter(i, output_frame->GetParameter(i));
2395 } 3804 }
2396 } 3805 }
2397 3806
2398 3807
2399 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() { 3808 DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
2400 delete[] expression_stack_; 3809 delete[] expression_stack_;
2401 delete[] parameters_; 3810 delete[] parameters_;
2402 } 3811 }
(...skipping 28 matching lines...) Expand all
2431 if (info->rmode() == RelocInfo::POSITION) { 3840 if (info->rmode() == RelocInfo::POSITION) {
2432 int raw_position = static_cast<int>(info->data()); 3841 int raw_position = static_cast<int>(info->data());
2433 last_position = raw_position ? SourcePosition::FromRaw(raw_position) 3842 last_position = raw_position ? SourcePosition::FromRaw(raw_position)
2434 : SourcePosition::Unknown(); 3843 : SourcePosition::Unknown();
2435 } else if (info->rmode() == RelocInfo::DEOPT_REASON) { 3844 } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2436 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data()); 3845 last_reason = static_cast<Deoptimizer::DeoptReason>(info->data());
2437 } 3846 }
2438 } 3847 }
2439 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason); 3848 return DeoptInfo(SourcePosition::Unknown(), NULL, Deoptimizer::kNoReason);
2440 } 3849 }
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
3513 } // namespace internal 3850 } // namespace internal
3514 } // namespace v8 3851 } // 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