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