LCOV - code coverage report
Current view: top level - src - deoptimizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1394 1634 85.3 %
Date: 2017-10-20 Functions: 102 143 71.3 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/deoptimizer.h"
       6             : 
       7             : #include <memory>
       8             : 
       9             : #include "src/accessors.h"
      10             : #include "src/assembler-inl.h"
      11             : #include "src/ast/prettyprinter.h"
      12             : #include "src/callable.h"
      13             : #include "src/disasm.h"
      14             : #include "src/frames-inl.h"
      15             : #include "src/global-handles.h"
      16             : #include "src/interpreter/interpreter.h"
      17             : #include "src/macro-assembler.h"
      18             : #include "src/objects/debug-objects-inl.h"
      19             : #include "src/tracing/trace-event.h"
      20             : #include "src/v8.h"
      21             : 
      22             : 
      23             : namespace v8 {
      24             : namespace internal {
      25             : 
      26      164997 : static MemoryChunk* AllocateCodeChunk(MemoryAllocator* allocator) {
      27             :   return allocator->AllocateChunk(Deoptimizer::GetMaxDeoptTableSize(),
      28      164997 :                                   MemoryAllocator::GetCommitPageSize(),
      29      164997 :                                   EXECUTABLE, nullptr);
      30             : }
      31             : 
      32       54999 : DeoptimizerData::DeoptimizerData(MemoryAllocator* allocator)
      33       54999 :     : allocator_(allocator), current_(nullptr) {
      34      219996 :   for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
      35      164997 :     deopt_entry_code_entries_[i] = -1;
      36      164997 :     deopt_entry_code_[i] = AllocateCodeChunk(allocator);
      37             :   }
      38       54999 : }
      39             : 
      40             : 
      41       53365 : DeoptimizerData::~DeoptimizerData() {
      42      213460 :   for (int i = 0; i <= Deoptimizer::kLastBailoutType; ++i) {
      43      160095 :     allocator_->Free<MemoryAllocator::kFull>(deopt_entry_code_[i]);
      44      160095 :     deopt_entry_code_[i] = nullptr;
      45             :   }
      46       53365 : }
      47             : 
      48             : 
      49      146823 : Code* Deoptimizer::FindDeoptimizingCode(Address addr) {
      50      293646 :   if (function_->IsHeapObject()) {
      51             :     // Search all deoptimizing code in the native context of the function.
      52             :     Isolate* isolate = function_->GetIsolate();
      53             :     Context* native_context = function_->context()->native_context();
      54      146823 :     Object* element = native_context->DeoptimizedCodeListHead();
      55     6492821 :     while (!element->IsUndefined(isolate)) {
      56             :       Code* code = Code::cast(element);
      57     6325987 :       CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
      58     6325987 :       if (code->contains(addr)) return code;
      59             :       element = code->next_code_link();
      60             :     }
      61             :   }
      62             :   return nullptr;
      63             : }
      64             : 
      65             : 
      66             : // We rely on this function not causing a GC.  It is called from generated code
      67             : // without having a real stack frame in place.
      68      146823 : Deoptimizer* Deoptimizer::New(JSFunction* function,
      69             :                               BailoutType type,
      70             :                               unsigned bailout_id,
      71             :                               Address from,
      72             :                               int fp_to_sp_delta,
      73      146823 :                               Isolate* isolate) {
      74             :   Deoptimizer* deoptimizer = new Deoptimizer(isolate, function, type,
      75      146823 :                                              bailout_id, from, fp_to_sp_delta);
      76      146823 :   CHECK_NULL(isolate->deoptimizer_data()->current_);
      77      146823 :   isolate->deoptimizer_data()->current_ = deoptimizer;
      78      146823 :   return deoptimizer;
      79             : }
      80             : 
      81             : 
      82             : // No larger than 2K on all platforms
      83             : static const int kDeoptTableMaxEpilogueCodeSize = 2 * KB;
      84             : 
      85             : 
      86      203429 : size_t Deoptimizer::GetMaxDeoptTableSize() {
      87             :   int entries_size =
      88      203429 :       Deoptimizer::kMaxNumberOfEntries * Deoptimizer::table_entry_size_;
      89      203429 :   int commit_page_size = static_cast<int>(MemoryAllocator::GetCommitPageSize());
      90      203429 :   int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) /
      91      203429 :                     commit_page_size) + 1;
      92      203429 :   return static_cast<size_t>(commit_page_size * page_count);
      93             : }
      94             : 
      95             : 
      96      293646 : Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
      97      146823 :   Deoptimizer* result = isolate->deoptimizer_data()->current_;
      98      146823 :   CHECK_NOT_NULL(result);
      99      146823 :   result->DeleteFrameDescriptions();
     100      146823 :   isolate->deoptimizer_data()->current_ = nullptr;
     101      146823 :   return result;
     102             : }
     103             : 
     104       34855 : DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
     105             :     JavaScriptFrame* frame,
     106             :     int jsframe_index,
     107             :     Isolate* isolate) {
     108      104565 :   CHECK(frame->is_optimized());
     109             : 
     110       34855 :   TranslatedState translated_values(frame);
     111       34855 :   translated_values.Prepare(frame->fp());
     112             : 
     113             :   TranslatedState::iterator frame_it = translated_values.end();
     114             :   int counter = jsframe_index;
     115      138696 :   for (auto it = translated_values.begin(); it != translated_values.end();
     116             :        it++) {
     117      103841 :     if (it->kind() == TranslatedFrame::kInterpretedFunction ||
     118             :         it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation) {
     119       70381 :       if (counter == 0) {
     120             :         frame_it = it;
     121             :         break;
     122             :       }
     123       35526 :       counter--;
     124             :     }
     125             :   }
     126       34855 :   CHECK(frame_it != translated_values.end());
     127             :   // We only include kJavaScriptBuiltinContinuation frames above to get the
     128             :   // counting right.
     129       34855 :   CHECK_EQ(frame_it->kind(), TranslatedFrame::kInterpretedFunction);
     130             : 
     131             :   DeoptimizedFrameInfo* info =
     132       69710 :       new DeoptimizedFrameInfo(&translated_values, frame_it, isolate);
     133             : 
     134       34855 :   return info;
     135             : }
     136             : 
     137           0 : void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
     138             :                                                 int count,
     139             :                                                 BailoutType type) {
     140             :   TableEntryGenerator generator(masm, type, count);
     141       38432 :   generator.Generate();
     142           0 : }
     143             : 
     144             : namespace {
     145       67089 : class ActivationsFinder : public ThreadVisitor {
     146             :  public:
     147             :   explicit ActivationsFinder(std::set<Code*>* codes,
     148             :                              Code* topmost_optimized_code,
     149             :                              bool safe_to_deopt_topmost_optimized_code)
     150       67089 :       : codes_(codes) {
     151             : #ifdef DEBUG
     152             :     topmost_ = topmost_optimized_code;
     153             :     safe_to_deopt_ = safe_to_deopt_topmost_optimized_code;
     154             : #endif
     155             :   }
     156             : 
     157             :   // Find the frames with activations of codes marked for deoptimization, search
     158             :   // for the trampoline to the deoptimizer call respective to each code, and use
     159             :   // it to replace the current pc on the stack.
     160      159615 :   void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
     161      969067 :     for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
     162      809452 :       if (it.frame()->type() == StackFrame::OPTIMIZED) {
     163      336996 :         Code* code = it.frame()->LookupCode();
     164      663659 :         if (code->kind() == Code::OPTIMIZED_FUNCTION &&
     165             :             code->marked_for_deoptimization()) {
     166      280988 :           codes_->erase(code);
     167             :           // Obtain the trampoline to the deoptimizer call.
     168      561976 :           SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
     169      280988 :           int trampoline_pc = safepoint.trampoline_pc();
     170             :           DCHECK_IMPLIES(code == topmost_, safe_to_deopt_);
     171             :           // Replace the current pc on the stack with the trampoline.
     172      280988 :           it.frame()->set_pc(code->instruction_start() + trampoline_pc);
     173             :         }
     174             :       }
     175             :     }
     176      159615 :   }
     177             : 
     178             :  private:
     179             :   std::set<Code*>* codes_;
     180             : 
     181             : #ifdef DEBUG
     182             :   Code* topmost_;
     183             :   bool safe_to_deopt_;
     184             : #endif
     185             : };
     186             : }  // namespace
     187             : 
     188             : // Move marked code from the optimized code list to the deoptimized code list,
     189             : // and replace pc on the stack for codes marked for deoptimization.
     190       67089 : void Deoptimizer::DeoptimizeMarkedCodeForContext(Context* context) {
     191             :   DisallowHeapAllocation no_allocation;
     192             : 
     193       67089 :   Isolate* isolate = context->GetHeap()->isolate();
     194             :   Code* topmost_optimized_code = nullptr;
     195             :   bool safe_to_deopt_topmost_optimized_code = false;
     196             : #ifdef DEBUG
     197             :   // Make sure all activations of optimized code can deopt at their current PC.
     198             :   // The topmost optimized code has special handling because it cannot be
     199             :   // deoptimized due to weak object dependency.
     200             :   for (StackFrameIterator it(isolate, isolate->thread_local_top());
     201             :        !it.done(); it.Advance()) {
     202             :     StackFrame::Type type = it.frame()->type();
     203             :     if (type == StackFrame::OPTIMIZED) {
     204             :       Code* code = it.frame()->LookupCode();
     205             :       JSFunction* function =
     206             :           static_cast<OptimizedFrame*>(it.frame())->function();
     207             :       if (FLAG_trace_deopt) {
     208             :         CodeTracer::Scope scope(isolate->GetCodeTracer());
     209             :         PrintF(scope.file(), "[deoptimizer found activation of function: ");
     210             :         function->PrintName(scope.file());
     211             :         PrintF(scope.file(),
     212             :                " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
     213             :       }
     214             :       SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
     215             :       int deopt_index = safepoint.deoptimization_index();
     216             : 
     217             :       // Turbofan deopt is checked when we are patching addresses on stack.
     218             :       bool is_non_deoptimizing_asm_code =
     219             :           code->is_turbofanned() && !function->shared()->HasBytecodeArray();
     220             :       bool safe_if_deopt_triggered =
     221             :           deopt_index != Safepoint::kNoDeoptimizationIndex ||
     222             :           is_non_deoptimizing_asm_code;
     223             :       bool is_builtin_code = code->kind() == Code::BUILTIN;
     224             :       DCHECK(topmost_optimized_code == nullptr || safe_if_deopt_triggered ||
     225             :              is_non_deoptimizing_asm_code || is_builtin_code);
     226             :       if (topmost_optimized_code == nullptr) {
     227             :         topmost_optimized_code = code;
     228             :         safe_to_deopt_topmost_optimized_code = safe_if_deopt_triggered;
     229             :       }
     230             :     }
     231             :   }
     232             : #endif
     233             : 
     234             :   // We will use this set to mark those Code objects that are marked for
     235             :   // deoptimization and have not been found in stack frames.
     236             :   std::set<Code*> codes;
     237             : 
     238             :   // Move marked code from the optimized code list to the deoptimized
     239             :   // code list.
     240             :   // Walk over all optimized code objects in this native context.
     241             :   Code* prev = nullptr;
     242       67089 :   Object* element = context->OptimizedCodeListHead();
     243      753100 :   while (!element->IsUndefined(isolate)) {
     244      618922 :     Code* code = Code::cast(element);
     245      618922 :     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     246             :     Object* next = code->next_code_link();
     247             : 
     248      618922 :     if (code->marked_for_deoptimization()) {
     249             :       // Make sure that this object does not point to any garbage.
     250      253425 :       code->InvalidateEmbeddedObjects();
     251             :       codes.insert(code);
     252             : 
     253      253425 :       if (prev != nullptr) {
     254             :         // Skip this code in the optimized code list.
     255        3649 :         prev->set_next_code_link(next);
     256             :       } else {
     257             :         // There was no previous node, the next node is the new head.
     258      249776 :         context->SetOptimizedCodeListHead(next);
     259             :       }
     260             : 
     261             :       // Move the code to the _deoptimized_ code list.
     262      253425 :       code->set_next_code_link(context->DeoptimizedCodeListHead());
     263      253425 :       context->SetDeoptimizedCodeListHead(code);
     264             :     } else {
     265             :       // Not marked; preserve this element.
     266             :       prev = code;
     267             :     }
     268             :     element = next;
     269             :   }
     270             : 
     271             :   ActivationsFinder visitor(&codes, topmost_optimized_code,
     272             :                             safe_to_deopt_topmost_optimized_code);
     273             :   // Iterate over the stack of this thread.
     274       67089 :   visitor.VisitThread(isolate, isolate->thread_local_top());
     275             :   // In addition to iterate over the stack of this thread, we also
     276             :   // need to consider all the other threads as they may also use
     277             :   // the code currently beings deoptimized.
     278       67089 :   isolate->thread_manager()->IterateArchivedThreads(&visitor);
     279             : 
     280             :   // If there's no activation of a code in any stack then we can remove its
     281             :   // deoptimization data. We do this to ensure that Code objects that will be
     282             :   // unlinked won't be kept alive.
     283             :   std::set<Code*>::iterator it;
     284      384254 :   for (it = codes.begin(); it != codes.end(); ++it) {
     285      250076 :     Code* code = *it;
     286      250076 :     code->set_deoptimization_data(isolate->heap()->empty_fixed_array());
     287             :   }
     288       67089 : }
     289             : 
     290             : 
     291        5524 : void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
     292             :   RuntimeCallTimerScope runtimeTimer(isolate,
     293        5524 :                                      &RuntimeCallStats::DeoptimizeCode);
     294             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     295       16572 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     296        5524 :   if (FLAG_trace_deopt) {
     297           0 :     CodeTracer::Scope scope(isolate->GetCodeTracer());
     298           0 :     PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
     299             :   }
     300             :   DisallowHeapAllocation no_allocation;
     301             :   // For all contexts, mark all code, then deoptimize.
     302        5524 :   Object* context = isolate->heap()->native_contexts_list();
     303       33944 :   while (!context->IsUndefined(isolate)) {
     304             :     Context* native_context = Context::cast(context);
     305       22896 :     MarkAllCodeForContext(native_context);
     306       22896 :     DeoptimizeMarkedCodeForContext(native_context);
     307             :     context = native_context->next_context_link();
     308             :   }
     309        5524 : }
     310             : 
     311             : 
     312        3443 : void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
     313             :   RuntimeCallTimerScope runtimeTimer(isolate,
     314        3443 :                                      &RuntimeCallStats::DeoptimizeCode);
     315             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     316       10329 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     317        3443 :   if (FLAG_trace_deopt) {
     318           0 :     CodeTracer::Scope scope(isolate->GetCodeTracer());
     319           0 :     PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
     320             :   }
     321             :   DisallowHeapAllocation no_allocation;
     322             :   // For all contexts, deoptimize code already marked.
     323        3443 :   Object* context = isolate->heap()->native_contexts_list();
     324       15580 :   while (!context->IsUndefined(isolate)) {
     325             :     Context* native_context = Context::cast(context);
     326        8694 :     DeoptimizeMarkedCodeForContext(native_context);
     327             :     context = native_context->next_context_link();
     328             :   }
     329        3443 : }
     330             : 
     331       22896 : void Deoptimizer::MarkAllCodeForContext(Context* context) {
     332       22896 :   Object* element = context->OptimizedCodeListHead();
     333             :   Isolate* isolate = context->GetIsolate();
     334      258935 :   while (!element->IsUndefined(isolate)) {
     335             :     Code* code = Code::cast(element);
     336      213143 :     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     337             :     code->set_marked_for_deoptimization(true);
     338             :     element = code->next_code_link();
     339             :   }
     340       22896 : }
     341             : 
     342       57165 : void Deoptimizer::DeoptimizeFunction(JSFunction* function, Code* code) {
     343             :   Isolate* isolate = function->GetIsolate();
     344             :   RuntimeCallTimerScope runtimeTimer(isolate,
     345       57165 :                                      &RuntimeCallStats::DeoptimizeCode);
     346             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     347      171495 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     348       57165 :   if (code == nullptr) code = function->code();
     349             : 
     350       57165 :   if (code->kind() == Code::OPTIMIZED_FUNCTION) {
     351             :     // Mark the code for deoptimization and unlink any functions that also
     352             :     // refer to that code. The code cannot be shared across native contexts,
     353             :     // so we only need to search one.
     354             :     code->set_marked_for_deoptimization(true);
     355             :     // The code in the function's optimized code feedback vector slot might
     356             :     // be different from the code on the function - evict it if necessary.
     357             :     function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
     358       35499 :         function->shared(), "unlinking code marked for deopt");
     359       35499 :     if (!code->deopt_already_counted()) {
     360             :       function->feedback_vector()->increment_deopt_count();
     361             :       code->set_deopt_already_counted(true);
     362             :     }
     363       35499 :     DeoptimizeMarkedCodeForContext(function->context()->native_context());
     364             :   }
     365       57165 : }
     366             : 
     367             : 
     368      146823 : void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
     369      146823 :   deoptimizer->DoComputeOutputFrames();
     370      146823 : }
     371             : 
     372             : 
     373           0 : const char* Deoptimizer::MessageFor(BailoutType type) {
     374           0 :   switch (type) {
     375             :     case EAGER: return "eager";
     376           0 :     case SOFT: return "soft";
     377           0 :     case LAZY: return "lazy";
     378             :   }
     379           0 :   FATAL("Unsupported deopt type");
     380             :   return nullptr;
     381             : }
     382             : 
     383             : namespace {
     384             : 
     385      146823 : CodeEventListener::DeoptKind DeoptKindOfBailoutType(
     386             :     Deoptimizer::BailoutType bailout_type) {
     387      146823 :   switch (bailout_type) {
     388             :     case Deoptimizer::EAGER:
     389             :       return CodeEventListener::kEager;
     390             :     case Deoptimizer::SOFT:
     391        3619 :       return CodeEventListener::kSoft;
     392             :     case Deoptimizer::LAZY:
     393      126812 :       return CodeEventListener::kLazy;
     394             :   }
     395           0 :   UNREACHABLE();
     396             : }
     397             : 
     398             : }  // namespace
     399             : 
     400      293646 : Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction* function,
     401             :                          BailoutType type, unsigned bailout_id, Address from,
     402             :                          int fp_to_sp_delta)
     403             :     : isolate_(isolate),
     404             :       function_(function),
     405             :       bailout_id_(bailout_id),
     406             :       bailout_type_(type),
     407             :       preserve_optimized_(false),
     408             :       from_(from),
     409             :       fp_to_sp_delta_(fp_to_sp_delta),
     410             :       deoptimizing_throw_(false),
     411             :       catch_handler_data_(-1),
     412             :       catch_handler_pc_offset_(-1),
     413             :       input_(nullptr),
     414             :       output_count_(0),
     415             :       jsframe_count_(0),
     416             :       output_(nullptr),
     417             :       caller_frame_top_(0),
     418             :       caller_fp_(0),
     419             :       caller_pc_(0),
     420             :       caller_constant_pool_(0),
     421             :       input_frame_context_(0),
     422             :       stack_fp_(0),
     423      293646 :       trace_scope_(nullptr) {
     424      146823 :   if (isolate->deoptimizer_lazy_throw()) {
     425             :     isolate->set_deoptimizer_lazy_throw(false);
     426        3129 :     deoptimizing_throw_ = true;
     427             :   }
     428             : 
     429             :   DCHECK_NOT_NULL(from);
     430      146823 :   compiled_code_ = FindOptimizedCode();
     431             :   DCHECK_NOT_NULL(compiled_code_);
     432             : 
     433             :   DCHECK(function->IsJSFunction());
     434             :   trace_scope_ = FLAG_trace_deopt
     435             :                      ? new CodeTracer::Scope(isolate->GetCodeTracer())
     436      293646 :                      : nullptr;
     437             : #ifdef DEBUG
     438             :   DCHECK(AllowHeapAllocation::IsAllowed());
     439             :   disallow_heap_allocation_ = new DisallowHeapAllocation();
     440             : #endif  // DEBUG
     441      440469 :   if (compiled_code_->kind() != Code::OPTIMIZED_FUNCTION ||
     442             :       !compiled_code_->deopt_already_counted()) {
     443             :     // If the function is optimized, and we haven't counted that deopt yet, then
     444             :     // increment the function's deopt count so that we can avoid optimising
     445             :     // functions that deopt too often.
     446             : 
     447       20878 :     if (bailout_type_ == Deoptimizer::SOFT) {
     448             :       // Soft deopts shouldn't count against the overall deoptimization count
     449             :       // that can eventually lead to disabling optimization for a function.
     450        3619 :       isolate->counters()->soft_deopts_executed()->Increment();
     451       17259 :     } else if (function != nullptr) {
     452             :       function->feedback_vector()->increment_deopt_count();
     453             :     }
     454             :   }
     455      293646 :   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
     456             :     compiled_code_->set_deopt_already_counted(true);
     457      293646 :     PROFILE(isolate_,
     458             :             CodeDeoptEvent(compiled_code_, DeoptKindOfBailoutType(type), from_,
     459             :                            fp_to_sp_delta_));
     460             :   }
     461      146823 :   unsigned size = ComputeInputFrameSize();
     462             :   int parameter_count =
     463      146823 :       function->shared()->internal_formal_parameter_count() + 1;
     464      146823 :   input_ = new (size) FrameDescription(size, parameter_count);
     465      146823 : }
     466             : 
     467      146823 : Code* Deoptimizer::FindOptimizedCode() {
     468      146823 :   Code* compiled_code = FindDeoptimizingCode(from_);
     469             :   return (compiled_code == nullptr)
     470       20011 :              ? static_cast<Code*>(isolate_->FindCodeObject(from_))
     471      166834 :              : compiled_code;
     472             : }
     473             : 
     474             : 
     475           0 : void Deoptimizer::PrintFunctionName() {
     476           0 :   if (function_->IsHeapObject() && function_->IsJSFunction()) {
     477           0 :     function_->ShortPrint(trace_scope_->file());
     478             :   } else {
     479             :     PrintF(trace_scope_->file(),
     480           0 :            "%s", Code::Kind2String(compiled_code_->kind()));
     481             :   }
     482           0 : }
     483             : 
     484      293646 : Handle<JSFunction> Deoptimizer::function() const {
     485      587292 :   return Handle<JSFunction>(function_);
     486             : }
     487           0 : Handle<Code> Deoptimizer::compiled_code() const {
     488           0 :   return Handle<Code>(compiled_code_);
     489             : }
     490             : 
     491      146823 : Deoptimizer::~Deoptimizer() {
     492             :   DCHECK(input_ == nullptr && output_ == nullptr);
     493             :   DCHECK_NULL(disallow_heap_allocation_);
     494      146823 :   delete trace_scope_;
     495      146823 : }
     496             : 
     497             : 
     498      146823 : void Deoptimizer::DeleteFrameDescriptions() {
     499      146823 :   delete input_;
     500      302689 :   for (int i = 0; i < output_count_; ++i) {
     501      155866 :     if (output_[i] != input_) delete output_[i];
     502             :   }
     503      146823 :   delete[] output_;
     504      146823 :   input_ = nullptr;
     505      146823 :   output_ = nullptr;
     506             : #ifdef DEBUG
     507             :   DCHECK(!AllowHeapAllocation::IsAllowed());
     508             :   DCHECK_NOT_NULL(disallow_heap_allocation_);
     509             :   delete disallow_heap_allocation_;
     510             :   disallow_heap_allocation_ = nullptr;
     511             : #endif  // DEBUG
     512      146823 : }
     513             : 
     514             : 
     515     6175377 : Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
     516             :                                             int id,
     517             :                                             BailoutType type,
     518             :                                             GetEntryMode mode) {
     519     3087685 :   CHECK_GE(id, 0);
     520     3087685 :   if (id >= kMaxNumberOfEntries) return nullptr;
     521     3087690 :   if (mode == ENSURE_ENTRY_CODE) {
     522     3087690 :     EnsureCodeForDeoptimizationEntry(isolate, type, id);
     523             :   } else {
     524           0 :     CHECK_EQ(mode, CALCULATE_ENTRY_ADDRESS);
     525             :   }
     526             :   DeoptimizerData* data = isolate->deoptimizer_data();
     527     3087692 :   CHECK_LE(type, kLastBailoutType);
     528     3087692 :   MemoryChunk* base = data->deopt_entry_code_[type];
     529     3087692 :   return base->area_start() + (id * table_entry_size_);
     530             : }
     531             : 
     532             : 
     533           0 : int Deoptimizer::GetDeoptimizationId(Isolate* isolate,
     534             :                                      Address addr,
     535             :                                      BailoutType type) {
     536             :   DeoptimizerData* data = isolate->deoptimizer_data();
     537           0 :   MemoryChunk* base = data->deopt_entry_code_[type];
     538             :   Address start = base->area_start();
     539           0 :   if (addr < start ||
     540           0 :       addr >= start + (kMaxNumberOfEntries * table_entry_size_)) {
     541             :     return kNotDeoptimizationEntry;
     542             :   }
     543             :   DCHECK_EQ(0,
     544             :             static_cast<int>(addr - start) % table_entry_size_);
     545           0 :   return static_cast<int>(addr - start) / table_entry_size_;
     546             : }
     547             : 
     548             : 
     549         102 : int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
     550             :   int length = 0;
     551             :   // Count all entries in the deoptimizing code list of every context.
     552         102 :   Object* context = isolate->heap()->native_contexts_list();
     553         306 :   while (!context->IsUndefined(isolate)) {
     554             :     Context* native_context = Context::cast(context);
     555         102 :     Object* element = native_context->DeoptimizedCodeListHead();
     556         416 :     while (!element->IsUndefined(isolate)) {
     557             :       Code* code = Code::cast(element);
     558             :       DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
     559         212 :       if (!code->marked_for_deoptimization()) {
     560           0 :         length++;
     561             :       }
     562             :       element = code->next_code_link();
     563             :     }
     564             :     context = Context::cast(context)->next_context_link();
     565             :   }
     566         102 :   return length;
     567             : }
     568             : 
     569             : namespace {
     570             : 
     571        6339 : int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
     572        3179 :   switch (translated_frame->kind()) {
     573             :     case TranslatedFrame::kInterpretedFunction: {
     574             :       int bytecode_offset = translated_frame->node_id().ToInt();
     575             :       BytecodeArray* bytecode =
     576             :           translated_frame->raw_shared_info()->bytecode_array();
     577             :       HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
     578        3160 :       return table->LookupRange(bytecode_offset, data_out, nullptr);
     579             :     }
     580             :     default:
     581             :       break;
     582             :   }
     583             :   return -1;
     584             : }
     585             : 
     586             : }  // namespace
     587             : 
     588             : // We rely on this function not causing a GC.  It is called from generated code
     589             : // without having a real stack frame in place.
     590      146823 : void Deoptimizer::DoComputeOutputFrames() {
     591             :   base::ElapsedTimer timer;
     592             : 
     593             :   // Determine basic deoptimization information.  The optimized frame is
     594             :   // described by the input data.
     595             :   DeoptimizationData* input_data =
     596      146823 :       DeoptimizationData::cast(compiled_code_->deoptimization_data());
     597             : 
     598             :   {
     599             :     // Read caller's PC, caller's FP and caller's constant pool values
     600             :     // from input frame. Compute caller's frame top address.
     601             : 
     602      146823 :     Register fp_reg = JavaScriptFrame::fp_register();
     603      293646 :     stack_fp_ = input_->GetRegister(fp_reg.code());
     604             : 
     605      146823 :     caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
     606             : 
     607             :     Address fp_address = input_->GetFramePointerAddress();
     608      146823 :     caller_fp_ = Memory::intptr_at(fp_address);
     609             :     caller_pc_ =
     610      146823 :         Memory::intptr_at(fp_address + CommonFrameConstants::kCallerPCOffset);
     611             :     input_frame_context_ = Memory::intptr_at(
     612      146823 :         fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
     613             : 
     614             :     if (FLAG_enable_embedded_constant_pool) {
     615             :       caller_constant_pool_ = Memory::intptr_at(
     616             :           fp_address + CommonFrameConstants::kConstantPoolOffset);
     617             :     }
     618             :   }
     619             : 
     620      146823 :   if (trace_scope_ != nullptr) {
     621             :     timer.Start();
     622             :     PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
     623           0 :            MessageFor(bailout_type_));
     624           0 :     PrintFunctionName();
     625             :     PrintF(trace_scope_->file(),
     626             :            " (opt #%d) @%d, FP to SP delta: %d, caller sp: 0x%08" V8PRIxPTR
     627             :            "]\n",
     628             :            input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
     629           0 :            caller_frame_top_);
     630           0 :     if (bailout_type_ == EAGER || bailout_type_ == SOFT) {
     631           0 :       compiled_code_->PrintDeoptLocation(trace_scope_->file(), from_);
     632             :     }
     633             :   }
     634             : 
     635      146823 :   BailoutId node_id = input_data->BytecodeOffset(bailout_id_);
     636             :   ByteArray* translations = input_data->TranslationByteArray();
     637             :   unsigned translation_index =
     638      146823 :       input_data->TranslationIndex(bailout_id_)->value();
     639             : 
     640             :   TranslationIterator state_iterator(translations, translation_index);
     641             :   translated_state_.Init(
     642             :       input_->GetFramePointerAddress(), &state_iterator,
     643             :       input_data->LiteralArray(), input_->GetRegisterValues(),
     644      146823 :       trace_scope_ == nullptr ? nullptr : trace_scope_->file(),
     645      146823 :       function_->IsHeapObject()
     646             :           ? function_->shared()->internal_formal_parameter_count()
     647      734115 :           : 0);
     648             : 
     649             :   // Do the input frame to output frame(s) translation.
     650      146823 :   size_t count = translated_state_.frames().size();
     651             :   // If we are supposed to go to the catch handler, find the catching frame
     652             :   // for the catch and make sure we only deoptimize upto that frame.
     653      146823 :   if (deoptimizing_throw_) {
     654             :     size_t catch_handler_frame_index = count;
     655        3179 :     for (size_t i = count; i-- > 0;) {
     656             :       catch_handler_pc_offset_ = LookupCatchHandler(
     657        6358 :           &(translated_state_.frames()[i]), &catch_handler_data_);
     658        3179 :       if (catch_handler_pc_offset_ >= 0) {
     659             :         catch_handler_frame_index = i;
     660             :         break;
     661             :       }
     662             :     }
     663        3129 :     CHECK_LT(catch_handler_frame_index, count);
     664        3129 :     count = catch_handler_frame_index + 1;
     665             :   }
     666             : 
     667             :   DCHECK_NULL(output_);
     668      146823 :   output_ = new FrameDescription*[count];
     669      302689 :   for (size_t i = 0; i < count; ++i) {
     670      155866 :     output_[i] = nullptr;
     671             :   }
     672      146823 :   output_count_ = static_cast<int>(count);
     673             : 
     674             :   // Translate each output frame.
     675             :   int frame_index = 0;  // output_frame_index
     676      302689 :   for (size_t i = 0; i < count; ++i, ++frame_index) {
     677             :     // Read the ast node id, function, and frame height for this output frame.
     678      311732 :     TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
     679      155866 :     switch (translated_frame->kind()) {
     680             :       case TranslatedFrame::kInterpretedFunction:
     681             :         DoComputeInterpretedFrame(translated_frame, frame_index,
     682      151652 :                                   deoptimizing_throw_ && i == count - 1);
     683      151652 :         jsframe_count_++;
     684      151652 :         break;
     685             :       case TranslatedFrame::kArgumentsAdaptor:
     686         656 :         DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
     687         656 :         break;
     688             :       case TranslatedFrame::kConstructStub:
     689        2546 :         DoComputeConstructStubFrame(translated_frame, frame_index);
     690        2546 :         break;
     691             :       case TranslatedFrame::kGetter:
     692         332 :         DoComputeAccessorStubFrame(translated_frame, frame_index, false);
     693         332 :         break;
     694             :       case TranslatedFrame::kSetter:
     695         542 :         DoComputeAccessorStubFrame(translated_frame, frame_index, true);
     696         542 :         break;
     697             :       case TranslatedFrame::kBuiltinContinuation:
     698          10 :         DoComputeBuiltinContinuation(translated_frame, frame_index, false);
     699          10 :         break;
     700             :       case TranslatedFrame::kJavaScriptBuiltinContinuation:
     701         128 :         DoComputeBuiltinContinuation(translated_frame, frame_index, true);
     702         128 :         break;
     703             :       case TranslatedFrame::kInvalid:
     704           0 :         FATAL("invalid frame");
     705             :         break;
     706             :     }
     707             :   }
     708             : 
     709             :   // Print some helpful diagnostic information.
     710      146823 :   if (trace_scope_ != nullptr) {
     711           0 :     double ms = timer.Elapsed().InMillisecondsF();
     712           0 :     int index = output_count_ - 1;  // Index of the topmost frame.
     713             :     PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
     714           0 :            MessageFor(bailout_type_));
     715           0 :     PrintFunctionName();
     716             :     PrintF(trace_scope_->file(),
     717             :            " @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
     718             :            ", took %0.3f ms]\n",
     719           0 :            bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
     720           0 :            caller_frame_top_, ms);
     721             :   }
     722      146823 : }
     723             : 
     724      303304 : void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
     725             :                                             int frame_index,
     726           0 :                                             bool goto_catch_handler) {
     727             :   SharedFunctionInfo* shared = translated_frame->raw_shared_info();
     728             : 
     729             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
     730      151652 :   bool is_bottommost = (0 == frame_index);
     731      151652 :   bool is_topmost = (output_count_ - 1 == frame_index);
     732      151652 :   int input_index = 0;
     733             : 
     734             :   int bytecode_offset = translated_frame->node_id().ToInt();
     735             :   int height = translated_frame->height();
     736      151652 :   int register_count = height - 1;  // Exclude accumulator.
     737             :   int register_stack_slot_count =
     738      151652 :       InterpreterFrameConstants::RegisterStackSlotCount(register_count);
     739      151652 :   int height_in_bytes = register_stack_slot_count * kPointerSize;
     740             : 
     741             :   // The topmost frame will contain the accumulator.
     742      151652 :   if (is_topmost) {
     743      146717 :     height_in_bytes += kPointerSize;
     744      146717 :     if (PadTopOfStackRegister()) height_in_bytes += kPointerSize;
     745             :   }
     746             : 
     747             :   TranslatedFrame::iterator function_iterator = value_iterator;
     748      151652 :   Object* function = value_iterator->GetRawValue();
     749             :   value_iterator++;
     750      151652 :   input_index++;
     751      151652 :   if (trace_scope_ != nullptr) {
     752           0 :     PrintF(trace_scope_->file(), "  translating interpreted frame ");
     753           0 :     std::unique_ptr<char[]> name = shared->DebugName()->ToCString();
     754           0 :     PrintF(trace_scope_->file(), "%s", name.get());
     755             :     PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
     756             :            bytecode_offset, height_in_bytes,
     757           0 :            goto_catch_handler ? " (throw)" : "");
     758             :   }
     759      151652 :   if (goto_catch_handler) {
     760        3129 :     bytecode_offset = catch_handler_pc_offset_;
     761             :   }
     762             : 
     763             :   // The 'fixed' part of the frame consists of the incoming parameters and
     764             :   // the part described by InterpreterFrameConstants.
     765             :   unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
     766      151652 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
     767             : 
     768             :   // Allocate and store the output frame description.
     769             :   int parameter_count = shared->internal_formal_parameter_count() + 1;
     770             :   FrameDescription* output_frame = new (output_frame_size)
     771      151652 :       FrameDescription(output_frame_size, parameter_count);
     772             : 
     773      151652 :   CHECK(frame_index >= 0 && frame_index < output_count_);
     774      151858 :   CHECK_NULL(output_[frame_index]);
     775      151652 :   output_[frame_index] = output_frame;
     776             : 
     777             :   // The top address of the frame is computed from the previous frame's top and
     778             :   // this frame's size.
     779             :   intptr_t top_address;
     780      151652 :   if (is_bottommost) {
     781      146823 :     top_address = caller_frame_top_ - output_frame_size;
     782             :   } else {
     783       14487 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
     784             :   }
     785             :   output_frame->SetTop(top_address);
     786             : 
     787             :   // Compute the incoming parameter translation.
     788             :   unsigned output_offset = output_frame_size;
     789      351280 :   for (int i = 0; i < parameter_count; ++i) {
     790      199628 :     output_offset -= kPointerSize;
     791             :     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
     792      199628 :                                  output_offset);
     793             :   }
     794             : 
     795      151652 :   if (trace_scope_ != nullptr) {
     796           0 :     PrintF(trace_scope_->file(), "    -------------------------\n");
     797             :   }
     798             : 
     799             :   // There are no translation commands for the caller's pc and fp, the
     800             :   // context, the function and the bytecode offset.  Synthesize
     801             :   // their values and set them up
     802             :   // explicitly.
     803             :   //
     804             :   // The caller's pc for the bottommost output frame is the same as in the
     805             :   // input frame.  For all subsequent output frames, it can be read from the
     806             :   // previous one.  This frame's pc can be computed from the non-optimized
     807             :   // function code and AST id of the bailout.
     808      151652 :   output_offset -= kPCOnStackSize;
     809             :   intptr_t value;
     810      151652 :   if (is_bottommost) {
     811      146823 :     value = caller_pc_;
     812             :   } else {
     813        4829 :     value = output_[frame_index - 1]->GetPc();
     814             :   }
     815      151652 :   output_frame->SetCallerPc(output_offset, value);
     816      151652 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
     817             : 
     818             :   // The caller's frame pointer for the bottommost output frame is the same
     819             :   // as in the input frame.  For all subsequent output frames, it can be
     820             :   // read from the previous one.  Also compute and set this frame's frame
     821             :   // pointer.
     822      151652 :   output_offset -= kFPOnStackSize;
     823      151652 :   if (is_bottommost) {
     824      146823 :     value = caller_fp_;
     825             :   } else {
     826        4829 :     value = output_[frame_index - 1]->GetFp();
     827             :   }
     828      151652 :   output_frame->SetCallerFp(output_offset, value);
     829      151652 :   intptr_t fp_value = top_address + output_offset;
     830             :   output_frame->SetFp(fp_value);
     831      151652 :   if (is_topmost) {
     832      146717 :     Register fp_reg = InterpretedFrame::fp_register();
     833      146717 :     output_frame->SetRegister(fp_reg.code(), fp_value);
     834             :   }
     835      151652 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
     836             : 
     837             :   if (FLAG_enable_embedded_constant_pool) {
     838             :     // For the bottommost output frame the constant pool pointer can be gotten
     839             :     // from the input frame. For subsequent output frames, it can be read from
     840             :     // the previous frame.
     841             :     output_offset -= kPointerSize;
     842             :     if (is_bottommost) {
     843             :       value = caller_constant_pool_;
     844             :     } else {
     845             :       value = output_[frame_index - 1]->GetConstantPool();
     846             :     }
     847             :     output_frame->SetCallerConstantPool(output_offset, value);
     848             :     DebugPrintOutputSlot(value, frame_index, output_offset,
     849             :                          "caller's constant_pool\n");
     850             :   }
     851             : 
     852             :   // For the bottommost output frame the context can be gotten from the input
     853             :   // frame. For all subsequent output frames it can be gotten from the function
     854             :   // so long as we don't inline functions that need local contexts.
     855      151652 :   output_offset -= kPointerSize;
     856             : 
     857             :   // When deoptimizing into a catch block, we need to take the context
     858             :   // from a register that was specified in the handler table.
     859             :   TranslatedFrame::iterator context_pos = value_iterator;
     860      151652 :   int context_input_index = input_index;
     861      151652 :   if (goto_catch_handler) {
     862             :     // Skip to the translated value of the register specified
     863             :     // in the handler table.
     864       57708 :     for (int i = 0; i < catch_handler_data_ + 1; ++i) {
     865             :       context_pos++;
     866       57708 :       context_input_index++;
     867             :     }
     868             :   }
     869             :   // Read the context from the translations.
     870      151652 :   Object* context = context_pos->GetRawValue();
     871      151652 :   value = reinterpret_cast<intptr_t>(context);
     872             :   output_frame->SetContext(value);
     873             :   WriteValueToOutput(context, context_input_index, frame_index, output_offset,
     874      151652 :                      "context    ");
     875      151652 :   if (context == isolate_->heap()->arguments_marker()) {
     876             :     Address output_address =
     877          93 :         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
     878         186 :         output_offset;
     879         279 :     values_to_materialize_.push_back({output_address, context_pos});
     880             :   }
     881             :   value_iterator++;
     882      151652 :   input_index++;
     883             : 
     884             :   // The function was mentioned explicitly in the BEGIN_FRAME.
     885      151652 :   output_offset -= kPointerSize;
     886             :   value = reinterpret_cast<intptr_t>(function);
     887      151652 :   WriteValueToOutput(function, 0, frame_index, output_offset, "function    ");
     888      151652 :   if (function == isolate_->heap()->arguments_marker()) {
     889             :     Address output_address =
     890         113 :         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
     891         226 :         output_offset;
     892         339 :     values_to_materialize_.push_back({output_address, function_iterator});
     893             :   }
     894             : 
     895             :   // Set the bytecode array pointer.
     896      151652 :   output_offset -= kPointerSize;
     897      151652 :   Object* bytecode_array = shared->HasBreakInfo()
     898         253 :                                ? shared->GetDebugInfo()->DebugBytecodeArray()
     899      151652 :                                : shared->bytecode_array();
     900             :   WriteValueToOutput(bytecode_array, 0, frame_index, output_offset,
     901      151652 :                      "bytecode array ");
     902             : 
     903             :   // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
     904      151652 :   output_offset -= kPointerSize;
     905             : 
     906             :   int raw_bytecode_offset =
     907      151652 :       BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
     908             :   Smi* smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
     909      151652 :   output_[frame_index]->SetFrameSlot(
     910      303304 :       output_offset, reinterpret_cast<intptr_t>(smi_bytecode_offset));
     911             : 
     912      151652 :   if (trace_scope_ != nullptr) {
     913             :     DebugPrintOutputSlot(reinterpret_cast<intptr_t>(smi_bytecode_offset),
     914           0 :                          frame_index, output_offset, "bytecode offset @ ");
     915           0 :     PrintF(trace_scope_->file(), "%d\n", bytecode_offset);
     916           0 :     PrintF(trace_scope_->file(), "  (input #0)\n");
     917           0 :     PrintF(trace_scope_->file(), "    -------------------------\n");
     918             :   }
     919             : 
     920             :   // Translate the rest of the interpreter registers in the frame.
     921      637334 :   for (int i = 0; i < register_count; ++i) {
     922      637334 :     output_offset -= kPointerSize;
     923             :     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
     924      637334 :                                  output_offset);
     925             :   }
     926             : 
     927             :   int register_slots_written = register_count;
     928             :   DCHECK_LE(register_slots_written, register_stack_slot_count);
     929             :   // Some architectures must pad the stack frame with extra stack slots
     930             :   // to ensure the stack frame is aligned. Do this now.
     931      151652 :   while (register_slots_written < register_stack_slot_count) {
     932           0 :     register_slots_written++;
     933           0 :     output_offset -= kPointerSize;
     934           0 :     WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
     935           0 :                        output_offset, "padding ");
     936             :   }
     937             : 
     938             :   // Translate the accumulator register (depending on frame position).
     939      151652 :   if (is_topmost) {
     940      146717 :     if (PadTopOfStackRegister()) {
     941           0 :       output_offset -= kPointerSize;
     942           0 :       WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
     943           0 :                          output_offset, "padding ");
     944             :     }
     945             :     // For topmost frame, put the accumulator on the stack. The
     946             :     // {NotifyDeoptimized} builtin pops it off the topmost frame (possibly
     947             :     // after materialization).
     948      146717 :     output_offset -= kPointerSize;
     949      146717 :     if (goto_catch_handler) {
     950             :       // If we are lazy deopting to a catch handler, we set the accumulator to
     951             :       // the exception (which lives in the result register).
     952             :       intptr_t accumulator_value =
     953        3129 :           input_->GetRegister(kInterpreterAccumulatorRegister.code());
     954             :       WriteValueToOutput(reinterpret_cast<Object*>(accumulator_value), 0,
     955        3129 :                          frame_index, output_offset, "accumulator ");
     956             :       value_iterator++;
     957             :     } else {
     958             :       WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
     959      143588 :                                    output_offset, "accumulator ");
     960             :     }
     961             :   } else {
     962             :     // For non-topmost frames, skip the accumulator translation. For those
     963             :     // frames, the return value from the callee will become the accumulator.
     964             :     value_iterator++;
     965        4935 :     input_index++;
     966             :   }
     967      151652 :   CHECK_EQ(0u, output_offset);
     968             : 
     969             :   // Compute this frame's PC and state. The PC will be a special builtin that
     970             :   // continues the bytecode dispatch. Note that non-topmost and lazy-style
     971             :   // bailout handlers also advance the bytecode offset before dispatch, hence
     972             :   // simulating what normal handlers do upon completion of the operation.
     973      151652 :   Builtins* builtins = isolate_->builtins();
     974             :   Code* dispatch_builtin =
     975      146717 :       (!is_topmost || (bailout_type_ == LAZY)) && !goto_catch_handler
     976             :           ? builtins->builtin(Builtins::kInterpreterEnterBytecodeAdvance)
     977      280172 :           : builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
     978      151652 :   output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
     979             : 
     980             :   // Update constant pool.
     981             :   if (FLAG_enable_embedded_constant_pool) {
     982             :     intptr_t constant_pool_value =
     983             :         reinterpret_cast<intptr_t>(dispatch_builtin->constant_pool());
     984             :     output_frame->SetConstantPool(constant_pool_value);
     985             :     if (is_topmost) {
     986             :       Register constant_pool_reg =
     987             :           InterpretedFrame::constant_pool_pointer_register();
     988             :       output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
     989             :     }
     990             :   }
     991             : 
     992             :   // Clear the context register. The context might be a de-materialized object
     993             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
     994             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
     995      151652 :   if (is_topmost) {
     996             :     intptr_t context_value = reinterpret_cast<intptr_t>(Smi::kZero);
     997      146717 :     Register context_reg = JavaScriptFrame::context_register();
     998      146717 :     output_frame->SetRegister(context_reg.code(), context_value);
     999             :     // Set the continuation for the topmost frame.
    1000             :     Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
    1001             :     output_frame->SetContinuation(
    1002      146717 :         reinterpret_cast<intptr_t>(continuation->entry()));
    1003             :   }
    1004      151652 : }
    1005             : 
    1006         656 : void Deoptimizer::DoComputeArgumentsAdaptorFrame(
    1007         656 :     TranslatedFrame* translated_frame, int frame_index) {
    1008             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1009         656 :   bool is_bottommost = (0 == frame_index);
    1010         656 :   int input_index = 0;
    1011             : 
    1012         656 :   unsigned height = translated_frame->height();
    1013         656 :   unsigned height_in_bytes = height * kPointerSize;
    1014             :   TranslatedFrame::iterator function_iterator = value_iterator;
    1015         656 :   Object* function = value_iterator->GetRawValue();
    1016             :   value_iterator++;
    1017         656 :   input_index++;
    1018         656 :   if (trace_scope_ != nullptr) {
    1019             :     PrintF(trace_scope_->file(),
    1020           0 :            "  translating arguments adaptor => height=%d\n", height_in_bytes);
    1021             :   }
    1022             : 
    1023             :   unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
    1024         656 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
    1025             : 
    1026             :   // Allocate and store the output frame description.
    1027             :   int parameter_count = height;
    1028             :   FrameDescription* output_frame = new (output_frame_size)
    1029         656 :       FrameDescription(output_frame_size, parameter_count);
    1030             : 
    1031             :   // Arguments adaptor can not be topmost.
    1032         656 :   CHECK(frame_index < output_count_ - 1);
    1033         663 :   CHECK_NULL(output_[frame_index]);
    1034         656 :   output_[frame_index] = output_frame;
    1035             : 
    1036             :   // The top address of the frame is computed from the previous frame's top and
    1037             :   // this frame's size.
    1038             :   intptr_t top_address;
    1039         656 :   if (is_bottommost) {
    1040           0 :     top_address = caller_frame_top_ - output_frame_size;
    1041             :   } else {
    1042        1968 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1043             :   }
    1044             :   output_frame->SetTop(top_address);
    1045             : 
    1046             :   // Compute the incoming parameter translation.
    1047             :   unsigned output_offset = output_frame_size;
    1048        2242 :   for (int i = 0; i < parameter_count; ++i) {
    1049        1586 :     output_offset -= kPointerSize;
    1050             :     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
    1051        1586 :                                  output_offset);
    1052             :   }
    1053             : 
    1054             :   // Read caller's PC from the previous frame.
    1055         656 :   output_offset -= kPCOnStackSize;
    1056             :   intptr_t value;
    1057         656 :   if (is_bottommost) {
    1058           0 :     value = caller_pc_;
    1059             :   } else {
    1060         656 :     value = output_[frame_index - 1]->GetPc();
    1061             :   }
    1062         656 :   output_frame->SetCallerPc(output_offset, value);
    1063         656 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's pc\n");
    1064             : 
    1065             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1066         656 :   output_offset -= kFPOnStackSize;
    1067         656 :   if (is_bottommost) {
    1068           0 :     value = caller_fp_;
    1069             :   } else {
    1070         656 :     value = output_[frame_index - 1]->GetFp();
    1071             :   }
    1072         656 :   output_frame->SetCallerFp(output_offset, value);
    1073         656 :   intptr_t fp_value = top_address + output_offset;
    1074             :   output_frame->SetFp(fp_value);
    1075         656 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
    1076             : 
    1077             :   if (FLAG_enable_embedded_constant_pool) {
    1078             :     // Read the caller's constant pool from the previous frame.
    1079             :     output_offset -= kPointerSize;
    1080             :     if (is_bottommost) {
    1081             :       value = caller_constant_pool_;
    1082             :     } else {
    1083             :       value = output_[frame_index - 1]->GetConstantPool();
    1084             :     }
    1085             :     output_frame->SetCallerConstantPool(output_offset, value);
    1086             :     DebugPrintOutputSlot(value, frame_index, output_offset,
    1087             :                          "caller's constant_pool\n");
    1088             :   }
    1089             : 
    1090             :   // A marker value is used in place of the context.
    1091         656 :   output_offset -= kPointerSize;
    1092             :   intptr_t context = StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR);
    1093             :   output_frame->SetFrameSlot(output_offset, context);
    1094             :   DebugPrintOutputSlot(context, frame_index, output_offset,
    1095         656 :                        "context (adaptor sentinel)\n");
    1096             : 
    1097             :   // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
    1098         656 :   output_offset -= kPointerSize;
    1099             :   value = reinterpret_cast<intptr_t>(function);
    1100         656 :   WriteValueToOutput(function, 0, frame_index, output_offset, "function    ");
    1101         656 :   if (function == isolate_->heap()->arguments_marker()) {
    1102             :     Address output_address =
    1103           7 :         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
    1104          14 :         output_offset;
    1105          21 :     values_to_materialize_.push_back({output_address, function_iterator});
    1106             :   }
    1107             : 
    1108             :   // Number of incoming arguments.
    1109         656 :   output_offset -= kPointerSize;
    1110        1312 :   value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
    1111             :   output_frame->SetFrameSlot(output_offset, value);
    1112         656 :   DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
    1113         656 :   if (trace_scope_ != nullptr) {
    1114           0 :     PrintF(trace_scope_->file(), "(%d)\n", height - 1);
    1115             :   }
    1116             : 
    1117             :   DCHECK_EQ(0, output_offset);
    1118             : 
    1119         656 :   Builtins* builtins = isolate_->builtins();
    1120             :   Code* adaptor_trampoline =
    1121             :       builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
    1122             :   intptr_t pc_value = reinterpret_cast<intptr_t>(
    1123        1312 :       adaptor_trampoline->instruction_start() +
    1124        1312 :       isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
    1125             :   output_frame->SetPc(pc_value);
    1126             :   if (FLAG_enable_embedded_constant_pool) {
    1127             :     intptr_t constant_pool_value =
    1128             :         reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
    1129             :     output_frame->SetConstantPool(constant_pool_value);
    1130             :   }
    1131         656 : }
    1132             : 
    1133        5092 : void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
    1134           0 :                                               int frame_index) {
    1135             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1136        2546 :   bool is_topmost = (output_count_ - 1 == frame_index);
    1137             :   // The construct frame could become topmost only if we inlined a constructor
    1138             :   // call which does a tail call (otherwise the tail callee's frame would be
    1139             :   // the topmost one). So it could only be the LAZY case.
    1140        2546 :   CHECK(!is_topmost || bailout_type_ == LAZY);
    1141        2546 :   int input_index = 0;
    1142             : 
    1143        2546 :   Builtins* builtins = isolate_->builtins();
    1144             :   Code* construct_stub = builtins->builtin(
    1145             :       FLAG_harmony_restrict_constructor_return
    1146             :           ? Builtins::kJSConstructStubGenericRestrictedReturn
    1147        2546 :           : Builtins::kJSConstructStubGenericUnrestrictedReturn);
    1148             :   BailoutId bailout_id = translated_frame->node_id();
    1149        2546 :   unsigned height = translated_frame->height();
    1150        2546 :   unsigned height_in_bytes = height * kPointerSize;
    1151             : 
    1152             :   // If the construct frame appears to be topmost we should ensure that the
    1153             :   // value of result register is preserved during continuation execution.
    1154             :   // We do this here by "pushing" the result of the constructor function to the
    1155             :   // top of the reconstructed stack and popping it in
    1156             :   // {Builtins::kNotifyDeoptimized}.
    1157        2546 :   if (is_topmost) {
    1158          73 :     height_in_bytes += kPointerSize;
    1159          73 :     if (PadTopOfStackRegister()) height_in_bytes += kPointerSize;
    1160             :   }
    1161             : 
    1162        2546 :   JSFunction* function = JSFunction::cast(value_iterator->GetRawValue());
    1163             :   value_iterator++;
    1164        2546 :   input_index++;
    1165        2546 :   if (trace_scope_ != nullptr) {
    1166             :     PrintF(trace_scope_->file(),
    1167             :            "  translating construct stub => bailout_id=%d (%s), height=%d\n",
    1168             :            bailout_id.ToInt(),
    1169             :            bailout_id == BailoutId::ConstructStubCreate() ? "create" : "invoke",
    1170           0 :            height_in_bytes);
    1171             :   }
    1172             : 
    1173             :   unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
    1174        2546 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
    1175             : 
    1176             :   // Allocate and store the output frame description.
    1177             :   FrameDescription* output_frame =
    1178        2546 :       new (output_frame_size) FrameDescription(output_frame_size);
    1179             : 
    1180             :   // Construct stub can not be topmost.
    1181             :   DCHECK(frame_index > 0 && frame_index < output_count_);
    1182             :   DCHECK_NULL(output_[frame_index]);
    1183        2546 :   output_[frame_index] = output_frame;
    1184             : 
    1185             :   // The top address of the frame is computed from the previous frame's top and
    1186             :   // this frame's size.
    1187             :   intptr_t top_address;
    1188       10184 :   top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1189             :   output_frame->SetTop(top_address);
    1190             : 
    1191             :   // Compute the incoming parameter translation.
    1192             :   int parameter_count = height;
    1193             :   unsigned output_offset = output_frame_size;
    1194       10287 :   for (int i = 0; i < parameter_count; ++i) {
    1195        7741 :     output_offset -= kPointerSize;
    1196             :     // The allocated receiver of a construct stub frame is passed as the
    1197             :     // receiver parameter through the translation. It might be encoding
    1198             :     // a captured object, override the slot address for a captured object.
    1199             :     WriteTranslatedValueToOutput(
    1200             :         &value_iterator, &input_index, frame_index, output_offset, nullptr,
    1201        7741 :         (i == 0) ? reinterpret_cast<Address>(top_address) : nullptr);
    1202             :   }
    1203             : 
    1204             :   // Read caller's PC from the previous frame.
    1205        2546 :   output_offset -= kPCOnStackSize;
    1206        2546 :   intptr_t callers_pc = output_[frame_index - 1]->GetPc();
    1207        2546 :   output_frame->SetCallerPc(output_offset, callers_pc);
    1208        2546 :   DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
    1209             : 
    1210             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1211        2546 :   output_offset -= kFPOnStackSize;
    1212        2546 :   intptr_t value = output_[frame_index - 1]->GetFp();
    1213        2546 :   output_frame->SetCallerFp(output_offset, value);
    1214        2546 :   intptr_t fp_value = top_address + output_offset;
    1215             :   output_frame->SetFp(fp_value);
    1216        2546 :   if (is_topmost) {
    1217          73 :     Register fp_reg = JavaScriptFrame::fp_register();
    1218          73 :     output_frame->SetRegister(fp_reg.code(), fp_value);
    1219             :   }
    1220        2546 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
    1221             : 
    1222             :   if (FLAG_enable_embedded_constant_pool) {
    1223             :     // Read the caller's constant pool from the previous frame.
    1224             :     output_offset -= kPointerSize;
    1225             :     value = output_[frame_index - 1]->GetConstantPool();
    1226             :     output_frame->SetCallerConstantPool(output_offset, value);
    1227             :     DebugPrintOutputSlot(value, frame_index, output_offset,
    1228             :                          "caller's constant_pool\n");
    1229             :   }
    1230             : 
    1231             :   // A marker value is used to mark the frame.
    1232        2546 :   output_offset -= kPointerSize;
    1233             :   value = StackFrame::TypeToMarker(StackFrame::CONSTRUCT);
    1234             :   output_frame->SetFrameSlot(output_offset, value);
    1235             :   DebugPrintOutputSlot(value, frame_index, output_offset,
    1236        2546 :                        "typed frame marker\n");
    1237             : 
    1238             :   // The context can be gotten from the previous frame.
    1239        2546 :   output_offset -= kPointerSize;
    1240        2546 :   value = output_[frame_index - 1]->GetContext();
    1241             :   output_frame->SetFrameSlot(output_offset, value);
    1242        2546 :   DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
    1243             : 
    1244             :   // Number of incoming arguments.
    1245        2546 :   output_offset -= kPointerSize;
    1246        5092 :   value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
    1247             :   output_frame->SetFrameSlot(output_offset, value);
    1248        2546 :   DebugPrintOutputSlot(value, frame_index, output_offset, "argc ");
    1249        2546 :   if (trace_scope_ != nullptr) {
    1250           0 :     PrintF(trace_scope_->file(), "(%d)\n", height - 1);
    1251             :   }
    1252             : 
    1253             :   // The constructor function was mentioned explicitly in the
    1254             :   // CONSTRUCT_STUB_FRAME.
    1255        2546 :   output_offset -= kPointerSize;
    1256             :   value = reinterpret_cast<intptr_t>(function);
    1257             :   WriteValueToOutput(function, 0, frame_index, output_offset,
    1258        2546 :                      "constructor function ");
    1259             : 
    1260             :   // The deopt info contains the implicit receiver or the new target at the
    1261             :   // position of the receiver. Copy it to the top of stack.
    1262        2546 :   output_offset -= kPointerSize;
    1263        2546 :   value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
    1264             :   output_frame->SetFrameSlot(output_offset, value);
    1265        2546 :   if (bailout_id == BailoutId::ConstructStubCreate()) {
    1266          73 :     DebugPrintOutputSlot(value, frame_index, output_offset, "new target\n");
    1267             :   } else {
    1268        2473 :     CHECK(bailout_id == BailoutId::ConstructStubInvoke());
    1269             :     DebugPrintOutputSlot(value, frame_index, output_offset,
    1270        2473 :                          "allocated receiver\n");
    1271             :   }
    1272             : 
    1273        2546 :   if (is_topmost) {
    1274          73 :     if (PadTopOfStackRegister()) {
    1275           0 :       output_offset -= kPointerSize;
    1276           0 :       WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
    1277           0 :                          output_offset, "padding ");
    1278             :     }
    1279             :     // Ensure the result is restored back when we return to the stub.
    1280          73 :     output_offset -= kPointerSize;
    1281             :     Register result_reg = kReturnRegister0;
    1282          73 :     value = input_->GetRegister(result_reg.code());
    1283             :     output_frame->SetFrameSlot(output_offset, value);
    1284          73 :     DebugPrintOutputSlot(value, frame_index, output_offset, "subcall result\n");
    1285             :   }
    1286             : 
    1287        2546 :   CHECK_EQ(0u, output_offset);
    1288             : 
    1289             :   // Compute this frame's PC.
    1290             :   DCHECK(bailout_id.IsValidForConstructStub());
    1291        2546 :   Address start = construct_stub->instruction_start();
    1292             :   int pc_offset =
    1293             :       bailout_id == BailoutId::ConstructStubCreate()
    1294          73 :           ? isolate_->heap()->construct_stub_create_deopt_pc_offset()->value()
    1295        5019 :           : isolate_->heap()->construct_stub_invoke_deopt_pc_offset()->value();
    1296        2546 :   intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
    1297             :   output_frame->SetPc(pc_value);
    1298             : 
    1299             :   // Update constant pool.
    1300             :   if (FLAG_enable_embedded_constant_pool) {
    1301             :     intptr_t constant_pool_value =
    1302             :         reinterpret_cast<intptr_t>(construct_stub->constant_pool());
    1303             :     output_frame->SetConstantPool(constant_pool_value);
    1304             :     if (is_topmost) {
    1305             :       Register constant_pool_reg =
    1306             :           JavaScriptFrame::constant_pool_pointer_register();
    1307             :       output_frame->SetRegister(constant_pool_reg.code(), fp_value);
    1308             :     }
    1309             :   }
    1310             : 
    1311             :   // Clear the context register. The context might be a de-materialized object
    1312             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1313             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1314        2546 :   if (is_topmost) {
    1315             :     intptr_t context_value = reinterpret_cast<intptr_t>(Smi::kZero);
    1316          73 :     Register context_reg = JavaScriptFrame::context_register();
    1317          73 :     output_frame->SetRegister(context_reg.code(), context_value);
    1318             :   }
    1319             : 
    1320             :   // Set the continuation for the topmost frame.
    1321        2546 :   if (is_topmost) {
    1322          73 :     Builtins* builtins = isolate_->builtins();
    1323             :     DCHECK_EQ(LAZY, bailout_type_);
    1324             :     Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
    1325             :     output_frame->SetContinuation(
    1326          73 :         reinterpret_cast<intptr_t>(continuation->entry()));
    1327             :   }
    1328        2546 : }
    1329             : 
    1330         874 : void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
    1331             :                                              int frame_index,
    1332           0 :                                              bool is_setter_stub_frame) {
    1333             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1334         874 :   bool is_topmost = (output_count_ - 1 == frame_index);
    1335             :   // The accessor frame could become topmost only if we inlined an accessor
    1336             :   // call which does a tail call (otherwise the tail callee's frame would be
    1337             :   // the topmost one). So it could only be the LAZY case.
    1338         874 :   CHECK(!is_topmost || bailout_type_ == LAZY);
    1339         874 :   int input_index = 0;
    1340             : 
    1341             :   // Skip accessor.
    1342             :   value_iterator++;
    1343         874 :   input_index++;
    1344             :   // The receiver (and the implicit return value, if any) are expected in
    1345             :   // registers by the LoadIC/StoreIC, so they don't belong to the output stack
    1346             :   // frame. This means that we have to use a height of 0.
    1347             :   unsigned height = 0;
    1348             :   unsigned height_in_bytes = height * kPointerSize;
    1349             : 
    1350             :   // If the accessor frame appears to be topmost we should ensure that the
    1351             :   // value of result register is preserved during continuation execution.
    1352             :   // We do this here by "pushing" the result of the accessor function to the
    1353             :   // top of the reconstructed stack and then popping it in
    1354             :   // {Builtins::kNotifyDeoptimized}.
    1355             :   // For setter calls, since the result register is going to be overwritten
    1356             :   // anyway in the stub, we store a dummy value to pop into the result register
    1357             :   // to keep the code simpler.
    1358         874 :   if (is_topmost) {
    1359             :     height_in_bytes += kPointerSize;
    1360           5 :     if (PadTopOfStackRegister()) height_in_bytes += kPointerSize;
    1361             :   }
    1362             : 
    1363         874 :   const char* kind = is_setter_stub_frame ? "setter" : "getter";
    1364         874 :   if (trace_scope_ != nullptr) {
    1365             :     PrintF(trace_scope_->file(),
    1366           0 :            "  translating %s stub => height=%u\n", kind, height_in_bytes);
    1367             :   }
    1368             : 
    1369             :   // We need 1 stack entry for the return address and enough entries for the
    1370             :   // StackFrame::INTERNAL (FP, frame type, context, code object and constant
    1371             :   // pool (if enabled)- see MacroAssembler::EnterFrame).
    1372             :   // For a setter stub frame we need one additional entry for the implicit
    1373             :   // return value, see StoreStubCompiler::CompileStoreViaSetter.
    1374             :   unsigned fixed_frame_entries =
    1375             :       (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 +
    1376         874 :       (is_setter_stub_frame ? 1 : 0);
    1377         874 :   unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
    1378         874 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
    1379             : 
    1380             :   // Allocate and store the output frame description.
    1381             :   FrameDescription* output_frame =
    1382         874 :       new (output_frame_size) FrameDescription(output_frame_size);
    1383             : 
    1384             :   // A frame for an accessor stub can not be bottommost.
    1385         874 :   CHECK(frame_index > 0 && frame_index < output_count_);
    1386         874 :   CHECK_NULL(output_[frame_index]);
    1387         874 :   output_[frame_index] = output_frame;
    1388             : 
    1389             :   // The top address of the frame is computed from the previous frame's top and
    1390             :   // this frame's size.
    1391        3496 :   intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1392             :   output_frame->SetTop(top_address);
    1393             : 
    1394             :   unsigned output_offset = output_frame_size;
    1395             : 
    1396             :   // Read caller's PC from the previous frame.
    1397         874 :   output_offset -= kPCOnStackSize;
    1398         874 :   intptr_t callers_pc = output_[frame_index - 1]->GetPc();
    1399         874 :   output_frame->SetCallerPc(output_offset, callers_pc);
    1400         874 :   DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n");
    1401             : 
    1402             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1403         874 :   output_offset -= kFPOnStackSize;
    1404         874 :   intptr_t value = output_[frame_index - 1]->GetFp();
    1405         874 :   output_frame->SetCallerFp(output_offset, value);
    1406         874 :   intptr_t fp_value = top_address + output_offset;
    1407             :   output_frame->SetFp(fp_value);
    1408         874 :   if (is_topmost) {
    1409           5 :     Register fp_reg = JavaScriptFrame::fp_register();
    1410           5 :     output_frame->SetRegister(fp_reg.code(), fp_value);
    1411             :   }
    1412         874 :   DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n");
    1413             : 
    1414             :   if (FLAG_enable_embedded_constant_pool) {
    1415             :     // Read the caller's constant pool from the previous frame.
    1416             :     output_offset -= kPointerSize;
    1417             :     value = output_[frame_index - 1]->GetConstantPool();
    1418             :     output_frame->SetCallerConstantPool(output_offset, value);
    1419             :     DebugPrintOutputSlot(value, frame_index, output_offset,
    1420             :                          "caller's constant_pool\n");
    1421             :   }
    1422             : 
    1423             :   // Set the frame type.
    1424         874 :   output_offset -= kPointerSize;
    1425             :   value = StackFrame::TypeToMarker(StackFrame::INTERNAL);
    1426             :   output_frame->SetFrameSlot(output_offset, value);
    1427         874 :   DebugPrintOutputSlot(value, frame_index, output_offset, "frame type ");
    1428         874 :   if (trace_scope_ != nullptr) {
    1429           0 :     PrintF(trace_scope_->file(), "(%s sentinel)\n", kind);
    1430             :   }
    1431             : 
    1432             :   // Get Code object from accessor stub.
    1433         874 :   output_offset -= kPointerSize;
    1434             :   Builtins::Name name = is_setter_stub_frame ?
    1435             :       Builtins::kStoreIC_Setter_ForDeopt :
    1436         874 :       Builtins::kLoadIC_Getter_ForDeopt;
    1437         874 :   Code* accessor_stub = isolate_->builtins()->builtin(name);
    1438         874 :   value = reinterpret_cast<intptr_t>(accessor_stub);
    1439             :   output_frame->SetFrameSlot(output_offset, value);
    1440         874 :   DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n");
    1441             : 
    1442             :   // The context can be gotten from the previous frame.
    1443         874 :   output_offset -= kPointerSize;
    1444         874 :   value = output_[frame_index - 1]->GetContext();
    1445             :   output_frame->SetFrameSlot(output_offset, value);
    1446         874 :   DebugPrintOutputSlot(value, frame_index, output_offset, "context\n");
    1447             : 
    1448             :   // Skip receiver.
    1449             :   value_iterator++;
    1450         874 :   input_index++;
    1451             : 
    1452         874 :   if (is_setter_stub_frame) {
    1453             :     // The implicit return value was part of the artificial setter stub
    1454             :     // environment.
    1455         542 :     output_offset -= kPointerSize;
    1456             :     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
    1457         542 :                                  output_offset);
    1458             :   }
    1459             : 
    1460         874 :   if (is_topmost) {
    1461           5 :     if (PadTopOfStackRegister()) {
    1462           0 :       output_offset -= kPointerSize;
    1463           0 :       WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
    1464           0 :                          output_offset, "padding ");
    1465             :     }
    1466             :     // Ensure the result is restored back when we return to the stub.
    1467           5 :     output_offset -= kPointerSize;
    1468             :     Register result_reg = kReturnRegister0;
    1469           5 :     value = input_->GetRegister(result_reg.code());
    1470             :     output_frame->SetFrameSlot(output_offset, value);
    1471             :     DebugPrintOutputSlot(value, frame_index, output_offset,
    1472           5 :                          "accessor result\n");
    1473             :   }
    1474             : 
    1475         874 :   CHECK_EQ(0u, output_offset);
    1476             : 
    1477             :   Smi* offset = is_setter_stub_frame ?
    1478         542 :       isolate_->heap()->setter_stub_deopt_pc_offset() :
    1479        1206 :       isolate_->heap()->getter_stub_deopt_pc_offset();
    1480             :   intptr_t pc = reinterpret_cast<intptr_t>(
    1481        1748 :       accessor_stub->instruction_start() + offset->value());
    1482             :   output_frame->SetPc(pc);
    1483             : 
    1484             :   // Update constant pool.
    1485             :   if (FLAG_enable_embedded_constant_pool) {
    1486             :     intptr_t constant_pool_value =
    1487             :         reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
    1488             :     output_frame->SetConstantPool(constant_pool_value);
    1489             :     if (is_topmost) {
    1490             :       Register constant_pool_reg =
    1491             :           JavaScriptFrame::constant_pool_pointer_register();
    1492             :       output_frame->SetRegister(constant_pool_reg.code(), fp_value);
    1493             :     }
    1494             :   }
    1495             : 
    1496             :   // Clear the context register. The context might be a de-materialized object
    1497             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1498             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1499         874 :   if (is_topmost) {
    1500             :     intptr_t context_value = reinterpret_cast<intptr_t>(Smi::kZero);
    1501           5 :     Register context_reg = JavaScriptFrame::context_register();
    1502           5 :     output_frame->SetRegister(context_reg.code(), context_value);
    1503             :   }
    1504             : 
    1505             :   // Set the continuation for the topmost frame.
    1506         874 :   if (is_topmost) {
    1507           5 :     Builtins* builtins = isolate_->builtins();
    1508             :     DCHECK_EQ(LAZY, bailout_type_);
    1509             :     Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
    1510             :     output_frame->SetContinuation(
    1511           5 :         reinterpret_cast<intptr_t>(continuation->entry()));
    1512             :   }
    1513         874 : }
    1514             : 
    1515             : // BuiltinContinuationFrames capture the machine state that is expected as input
    1516             : // to a builtin, including both input register values and stack parameters. When
    1517             : // the frame is reactivated (i.e. the frame below it returns), a
    1518             : // ContinueToBuiltin stub restores the register state from the frame and tail
    1519             : // calls to the actual target builtin, making it appear that the stub had been
    1520             : // directly called by the frame above it. The input values to populate the frame
    1521             : // are taken from the deopt's FrameState.
    1522             : //
    1523             : // Frame translation happens in two modes, EAGER and LAZY. In EAGER mode, all of
    1524             : // the parameters to the Builtin are explicitly specified in the TurboFan
    1525             : // FrameState node. In LAZY mode, there is always one fewer parameters specified
    1526             : // in the FrameState than expected by the Builtin. In that case, construction of
    1527             : // BuiltinContinuationFrame adds the final missing parameter during
    1528             : // deoptimization, and that parameter is always on the stack and contains the
    1529             : // value returned from the callee of the call site triggering the LAZY deopt
    1530             : // (e.g. rax on x64). This requires that continuation Builtins for LAZY deopts
    1531             : // must have at least one stack parameter.
    1532             : //
    1533             : //                TO
    1534             : //    |          ....           |
    1535             : //    +-------------------------+
    1536             : //    |     builtin param 0     |<- FrameState input value n becomes
    1537             : //    +-------------------------+
    1538             : //    |           ...           |
    1539             : //    +-------------------------+
    1540             : //    |     builtin param m     |<- FrameState input value n+m-1, or in
    1541             : //    +-------------------------+   the LAZY case, return LAZY result value
    1542             : //    | ContinueToBuiltin entry |
    1543             : //    +-------------------------+
    1544             : // |  |    saved frame (FP)     |
    1545             : // |  +=========================+<- fpreg
    1546             : // |  |constant pool (if ool_cp)|
    1547             : // v  +-------------------------+
    1548             : //    |BUILTIN_CONTINUATION mark|
    1549             : //    +-------------------------+
    1550             : //    |  JS Builtin code object |
    1551             : //    +-------------------------+
    1552             : //    | builtin input GPR reg0  |<- populated from deopt FrameState using
    1553             : //    +-------------------------+   the builtin's CallInterfaceDescriptor
    1554             : //    |          ...            |   to map a FrameState's 0..n-1 inputs to
    1555             : //    +-------------------------+   the builtin's n input register params.
    1556             : //    | builtin input GPR regn  |
    1557             : //    |-------------------------|<- spreg
    1558             : //
    1559         138 : void Deoptimizer::DoComputeBuiltinContinuation(
    1560         138 :     TranslatedFrame* translated_frame, int frame_index,
    1561         552 :     bool java_script_builtin) {
    1562             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1563         138 :   int input_index = 0;
    1564             : 
    1565             :   // The output frame must have room for all of the parameters that need to be
    1566             :   // passed to the builtin continuation.
    1567             :   int height_in_words = translated_frame->height();
    1568             : 
    1569         138 :   BailoutId bailout_id = translated_frame->node_id();
    1570         138 :   Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
    1571             :   Code* builtin = isolate()->builtins()->builtin(builtin_name);
    1572             :   Callable continuation_callable =
    1573         138 :       Builtins::CallableFor(isolate(), builtin_name);
    1574             :   CallInterfaceDescriptor continuation_descriptor =
    1575             :       continuation_callable.descriptor();
    1576             : 
    1577         138 :   bool is_bottommost = (0 == frame_index);
    1578         138 :   bool is_topmost = (output_count_ - 1 == frame_index);
    1579         138 :   bool must_handle_result = !is_topmost || bailout_type_ == LAZY;
    1580             : 
    1581        1932 :   const RegisterConfiguration* config(RegisterConfiguration::Default());
    1582             :   int allocatable_register_count = config->num_allocatable_general_registers();
    1583             :   int padding_slot_count = BuiltinContinuationFrameConstants::PaddingSlotCount(
    1584         138 :       allocatable_register_count);
    1585             : 
    1586             :   int register_parameter_count =
    1587             :       continuation_descriptor.GetRegisterParameterCount();
    1588             :   // Make sure to account for the context by removing it from the register
    1589             :   // parameter count.
    1590         138 :   int stack_param_count = height_in_words - register_parameter_count - 1;
    1591         138 :   if (must_handle_result) stack_param_count++;
    1592             :   int output_frame_size =
    1593         138 :       kPointerSize * (stack_param_count + allocatable_register_count +
    1594         138 :                       padding_slot_count) +
    1595         138 :       BuiltinContinuationFrameConstants::kFixedFrameSize;
    1596             : 
    1597             :   // If the builtins frame appears to be topmost we should ensure that the
    1598             :   // value of result register is preserved during continuation execution.
    1599             :   // We do this here by "pushing" the result of callback function to the
    1600             :   // top of the reconstructed stack and popping it in
    1601             :   // {Builtins::kNotifyDeoptimized}.
    1602         138 :   if (is_topmost) {
    1603          28 :     output_frame_size += kPointerSize;
    1604          28 :     if (PadTopOfStackRegister()) output_frame_size += kPointerSize;
    1605             :   }
    1606             : 
    1607             :   // Validate types of parameters. They must all be tagged except for argc for
    1608             :   // JS builtins.
    1609             :   bool has_argc = false;
    1610         522 :   for (int i = 0; i < register_parameter_count; ++i) {
    1611             :     MachineType type = continuation_descriptor.GetParameterType(i);
    1612             :     int code = continuation_descriptor.GetRegisterParameter(i).code();
    1613             :     // Only tagged and int32 arguments are supported, and int32 only for the
    1614             :     // arguments count on JavaScript builtins.
    1615         384 :     if (type == MachineType::Int32()) {
    1616         128 :       CHECK_EQ(code, kJavaScriptCallArgCountRegister.code());
    1617             :       has_argc = true;
    1618             :     } else {
    1619             :       // Any other argument must be a tagged value.
    1620         256 :       CHECK(IsAnyTagged(type.representation()));
    1621             :     }
    1622             :   }
    1623         138 :   CHECK_EQ(java_script_builtin, has_argc);
    1624             : 
    1625         138 :   if (trace_scope_ != nullptr) {
    1626             :     PrintF(trace_scope_->file(),
    1627             :            "  translating BuiltinContinuation to %s,"
    1628             :            " register param count %d,"
    1629             :            " stack param count %d\n",
    1630             :            Builtins::name(builtin_name), register_parameter_count,
    1631           0 :            stack_param_count);
    1632             :   }
    1633             : 
    1634         138 :   unsigned output_frame_offset = output_frame_size;
    1635             :   FrameDescription* output_frame =
    1636         138 :       new (output_frame_size) FrameDescription(output_frame_size);
    1637         138 :   output_[frame_index] = output_frame;
    1638             : 
    1639             :   // The top address of the frame is computed from the previous frame's top and
    1640             :   // this frame's size.
    1641             :   intptr_t top_address;
    1642         138 :   if (is_bottommost) {
    1643           0 :     top_address = caller_frame_top_ - output_frame_size;
    1644             :   } else {
    1645         552 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1646             :   }
    1647             :   output_frame->SetTop(top_address);
    1648             : 
    1649             :   // Get the possible JSFunction for the case that this is a
    1650             :   // JavaScriptBuiltinContinuationFrame, which needs the JSFunction pointer
    1651             :   // like a normal JavaScriptFrame.
    1652             :   intptr_t maybe_function =
    1653         138 :       reinterpret_cast<intptr_t>(value_iterator->GetRawValue());
    1654         138 :   ++input_index;
    1655             :   ++value_iterator;
    1656             : 
    1657        2208 :   struct RegisterValue {
    1658             :     Object* raw_value_;
    1659             :     TranslatedFrame::iterator iterator_;
    1660             :   };
    1661             :   std::vector<RegisterValue> register_values;
    1662             :   int total_registers = config->num_general_registers();
    1663         276 :   register_values.resize(total_registers, {Smi::kZero, value_iterator});
    1664             : 
    1665             :   intptr_t value;
    1666             : 
    1667             :   int translated_stack_parameters =
    1668         138 :       must_handle_result ? stack_param_count - 1 : stack_param_count;
    1669             : 
    1670         820 :   for (int i = 0; i < translated_stack_parameters; ++i) {
    1671         682 :     output_frame_offset -= kPointerSize;
    1672             :     WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index,
    1673         682 :                                  output_frame_offset);
    1674             :   }
    1675             : 
    1676         138 :   if (must_handle_result) {
    1677         130 :     output_frame_offset -= kPointerSize;
    1678         130 :     WriteValueToOutput(isolate()->heap()->the_hole_value(), input_index,
    1679             :                        frame_index, output_frame_offset,
    1680         260 :                        "placeholder for return result on lazy deopt ");
    1681             :   }
    1682             : 
    1683         522 :   for (int i = 0; i < register_parameter_count; ++i) {
    1684         384 :     Object* object = value_iterator->GetRawValue();
    1685             :     int code = continuation_descriptor.GetRegisterParameter(i).code();
    1686         768 :     register_values[code] = {object, value_iterator};
    1687         384 :     ++input_index;
    1688             :     ++value_iterator;
    1689             :   }
    1690             : 
    1691             :   // The context register is always implicit in the CallInterfaceDescriptor but
    1692             :   // its register must be explicitly set when continuing to the builtin. Make
    1693             :   // sure that it's harvested from the translation and copied into the register
    1694             :   // set (it was automatically added at the end of the FrameState by the
    1695             :   // instruction selector).
    1696         138 :   Object* context = value_iterator->GetRawValue();
    1697         138 :   value = reinterpret_cast<intptr_t>(context);
    1698         138 :   register_values[kContextRegister.code()] = {context, value_iterator};
    1699             :   output_frame->SetContext(value);
    1700             :   output_frame->SetRegister(kContextRegister.code(), value);
    1701         138 :   ++input_index;
    1702             :   ++value_iterator;
    1703             : 
    1704             :   // Set caller's PC (JSFunction continuation).
    1705         138 :   output_frame_offset -= kPCOnStackSize;
    1706         138 :   if (is_bottommost) {
    1707           0 :     value = caller_pc_;
    1708             :   } else {
    1709         138 :     value = output_[frame_index - 1]->GetPc();
    1710             :   }
    1711         138 :   output_frame->SetCallerPc(output_frame_offset, value);
    1712             :   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1713         138 :                        "caller's pc\n");
    1714             : 
    1715             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1716         138 :   output_frame_offset -= kFPOnStackSize;
    1717         138 :   if (is_bottommost) {
    1718           0 :     value = caller_fp_;
    1719             :   } else {
    1720         138 :     value = output_[frame_index - 1]->GetFp();
    1721             :   }
    1722         138 :   output_frame->SetCallerFp(output_frame_offset, value);
    1723         138 :   intptr_t fp_value = top_address + output_frame_offset;
    1724             :   output_frame->SetFp(fp_value);
    1725             :   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1726         138 :                        "caller's fp\n");
    1727             : 
    1728             :   if (FLAG_enable_embedded_constant_pool) {
    1729             :     // Read the caller's constant pool from the previous frame.
    1730             :     output_frame_offset -= kPointerSize;
    1731             :     if (is_bottommost) {
    1732             :       value = caller_constant_pool_;
    1733             :     } else {
    1734             :       value = output_[frame_index - 1]->GetConstantPool();
    1735             :     }
    1736             :     output_frame->SetCallerConstantPool(output_frame_offset, value);
    1737             :     DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1738             :                          "caller's constant_pool\n");
    1739             :   }
    1740             : 
    1741             :   // A marker value is used in place of the context.
    1742         138 :   output_frame_offset -= kPointerSize;
    1743             :   intptr_t marker =
    1744             :       java_script_builtin
    1745             :           ? StackFrame::TypeToMarker(
    1746             :                 StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION)
    1747         138 :           : StackFrame::TypeToMarker(StackFrame::BUILTIN_CONTINUATION);
    1748             :   output_frame->SetFrameSlot(output_frame_offset, marker);
    1749             :   DebugPrintOutputSlot(marker, frame_index, output_frame_offset,
    1750         138 :                        "context (builtin continuation sentinel)\n");
    1751             : 
    1752         138 :   output_frame_offset -= kPointerSize;
    1753         138 :   value = java_script_builtin ? maybe_function : 0;
    1754             :   output_frame->SetFrameSlot(output_frame_offset, value);
    1755             :   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1756         138 :                        java_script_builtin ? "JSFunction\n" : "unused\n");
    1757             : 
    1758             :   // The builtin to continue to
    1759         138 :   output_frame_offset -= kPointerSize;
    1760         138 :   value = reinterpret_cast<intptr_t>(builtin);
    1761             :   output_frame->SetFrameSlot(output_frame_offset, value);
    1762             :   DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1763         138 :                        "builtin address\n");
    1764             : 
    1765        1794 :   for (int i = 0; i < allocatable_register_count; ++i) {
    1766        1656 :     output_frame_offset -= kPointerSize;
    1767             :     int code = config->GetAllocatableGeneralCode(i);
    1768        3312 :     Object* object = register_values[code].raw_value_;
    1769        1656 :     value = reinterpret_cast<intptr_t>(object);
    1770             :     output_frame->SetFrameSlot(output_frame_offset, value);
    1771        1656 :     if (trace_scope_ != nullptr) {
    1772             :       ScopedVector<char> str(128);
    1773           0 :       if (java_script_builtin &&
    1774             :           code == kJavaScriptCallArgCountRegister.code()) {
    1775             :         SNPrintF(
    1776             :             str,
    1777             :             "tagged argument count %s (will be untagged by continuation)\n",
    1778           0 :             config->GetGeneralRegisterName(code));
    1779             :       } else {
    1780             :         SNPrintF(str, "builtin register argument %s\n",
    1781           0 :                  config->GetGeneralRegisterName(code));
    1782             :       }
    1783             :       DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1784           0 :                            str.start());
    1785             :     }
    1786        1656 :     if (object == isolate_->heap()->arguments_marker()) {
    1787             :       Address output_address =
    1788           8 :           reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
    1789           8 :           output_frame_offset;
    1790             :       values_to_materialize_.push_back(
    1791          24 :           {output_address, register_values[code].iterator_});
    1792             :     }
    1793             :   }
    1794             : 
    1795             :   // Some architectures must pad the stack frame with extra stack slots
    1796             :   // to ensure the stack frame is aligned.
    1797           0 :   for (int i = 0; i < padding_slot_count; ++i) {
    1798           0 :     output_frame_offset -= kPointerSize;
    1799           0 :     WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
    1800           0 :                        output_frame_offset, "padding ");
    1801             :   }
    1802             : 
    1803         138 :   if (is_topmost) {
    1804          28 :     if (PadTopOfStackRegister()) {
    1805           0 :       output_frame_offset -= kPointerSize;
    1806           0 :       WriteValueToOutput(isolate()->heap()->the_hole_value(), 0, frame_index,
    1807           0 :                          output_frame_offset, "padding ");
    1808             :     }
    1809             :     // Ensure the result is restored back when we return to the stub.
    1810          28 :     output_frame_offset -= kPointerSize;
    1811             :     Register result_reg = kReturnRegister0;
    1812          28 :     if (must_handle_result) {
    1813          20 :       value = input_->GetRegister(result_reg.code());
    1814             :     } else {
    1815           8 :       value = reinterpret_cast<intptr_t>(isolate()->heap()->undefined_value());
    1816             :     }
    1817             :     output_frame->SetFrameSlot(output_frame_offset, value);
    1818             :     DebugPrintOutputSlot(value, frame_index, output_frame_offset,
    1819          28 :                          "callback result\n");
    1820             :   }
    1821             : 
    1822         138 :   CHECK_EQ(0u, output_frame_offset);
    1823             : 
    1824             :   // Clear the context register. The context might be a de-materialized object
    1825             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1826             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1827         138 :   if (is_topmost) {
    1828             :     intptr_t context_value = reinterpret_cast<intptr_t>(Smi::kZero);
    1829          28 :     Register context_reg = JavaScriptFrame::context_register();
    1830          28 :     output_frame->SetRegister(context_reg.code(), context_value);
    1831             :   }
    1832             : 
    1833             :   // TODO(6898): For eager deopts within builtin stub frames we currently skip
    1834             :   // marking the underlying function as deoptimized. This is to avoid deopt
    1835             :   // loops where we would just generate the same optimized code all over again.
    1836         138 :   if (is_topmost && bailout_type_ != LAZY) {
    1837           8 :     preserve_optimized_ = true;
    1838             :   }
    1839             : 
    1840             :   // Ensure the frame pointer register points to the callee's frame. The builtin
    1841             :   // will build its own frame once we continue to it.
    1842         138 :   Register fp_reg = JavaScriptFrame::fp_register();
    1843         276 :   output_frame->SetRegister(fp_reg.code(), output_[frame_index - 1]->GetFp());
    1844             : 
    1845             :   Code* continue_to_builtin =
    1846             :       java_script_builtin
    1847             :           ? (must_handle_result
    1848             :                  ? isolate()->builtins()->builtin(
    1849             :                        Builtins::kContinueToJavaScriptBuiltinWithResult)
    1850             :                  : isolate()->builtins()->builtin(
    1851             :                        Builtins::kContinueToJavaScriptBuiltin))
    1852             :           : (must_handle_result
    1853             :                  ? isolate()->builtins()->builtin(
    1854             :                        Builtins::kContinueToCodeStubBuiltinWithResult)
    1855             :                  : isolate()->builtins()->builtin(
    1856         148 :                        Builtins::kContinueToCodeStubBuiltin));
    1857             :   output_frame->SetPc(
    1858         138 :       reinterpret_cast<intptr_t>(continue_to_builtin->instruction_start()));
    1859             : 
    1860             :   Code* continuation =
    1861             :       isolate()->builtins()->builtin(Builtins::kNotifyDeoptimized);
    1862             :   output_frame->SetContinuation(
    1863         138 :       reinterpret_cast<intptr_t>(continuation->entry()));
    1864         138 : }
    1865             : 
    1866      146823 : void Deoptimizer::MaterializeHeapObjects() {
    1867      146823 :   translated_state_.Prepare(reinterpret_cast<Address>(stack_fp_));
    1868             : 
    1869      296674 :   for (auto& materialization : values_to_materialize_) {
    1870        3028 :     Handle<Object> value = materialization.value_->GetValue();
    1871             : 
    1872        3028 :     if (trace_scope_ != nullptr) {
    1873             :       PrintF("Materialization [0x%08" V8PRIxPTR "] <- 0x%08" V8PRIxPTR " ;  ",
    1874             :              reinterpret_cast<intptr_t>(materialization.output_slot_address_),
    1875           0 :              reinterpret_cast<intptr_t>(*value));
    1876           0 :       value->ShortPrint(trace_scope_->file());
    1877           0 :       PrintF(trace_scope_->file(), "\n");
    1878             :     }
    1879             : 
    1880             :     *(reinterpret_cast<intptr_t*>(materialization.output_slot_address_)) =
    1881        6056 :         reinterpret_cast<intptr_t>(*value);
    1882             :   }
    1883             : 
    1884             :   isolate_->materialized_object_store()->Remove(
    1885      146823 :       reinterpret_cast<Address>(stack_fp_));
    1886      146823 : }
    1887             : 
    1888             : 
    1889      991101 : void Deoptimizer::WriteTranslatedValueToOutput(
    1890             :     TranslatedFrame::iterator* iterator, int* input_index, int frame_index,
    1891             :     unsigned output_offset, const char* debug_hint_string,
    1892             :     Address output_address_for_materialization) {
    1893      991101 :   Object* value = (*iterator)->GetRawValue();
    1894             : 
    1895             :   WriteValueToOutput(value, *input_index, frame_index, output_offset,
    1896      991101 :                      debug_hint_string);
    1897             : 
    1898      991101 :   if (value == isolate_->heap()->arguments_marker()) {
    1899             :     Address output_address =
    1900        2807 :         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
    1901        5614 :         output_offset;
    1902        2807 :     if (output_address_for_materialization == nullptr) {
    1903             :       output_address_for_materialization = output_address;
    1904             :     }
    1905             :     values_to_materialize_.push_back(
    1906        8421 :         {output_address_for_materialization, *iterator});
    1907             :   }
    1908             : 
    1909             :   (*iterator)++;
    1910      991101 :   (*input_index)++;
    1911      991101 : }
    1912             : 
    1913             : 
    1914     1452518 : void Deoptimizer::WriteValueToOutput(Object* value, int input_index,
    1915             :                                      int frame_index, unsigned output_offset,
    1916             :                                      const char* debug_hint_string) {
    1917     1452518 :   output_[frame_index]->SetFrameSlot(output_offset,
    1918     2905036 :                                      reinterpret_cast<intptr_t>(value));
    1919             : 
    1920     1452518 :   if (trace_scope_ != nullptr) {
    1921             :     DebugPrintOutputSlot(reinterpret_cast<intptr_t>(value), frame_index,
    1922           0 :                          output_offset, debug_hint_string);
    1923           0 :     value->ShortPrint(trace_scope_->file());
    1924           0 :     PrintF(trace_scope_->file(), "  (input #%d)\n", input_index);
    1925             :   }
    1926     1452518 : }
    1927             : 
    1928             : 
    1929      326370 : void Deoptimizer::DebugPrintOutputSlot(intptr_t value, int frame_index,
    1930             :                                        unsigned output_offset,
    1931             :                                        const char* debug_hint_string) {
    1932      326370 :   if (trace_scope_ != nullptr) {
    1933             :     Address output_address =
    1934           0 :         reinterpret_cast<Address>(output_[frame_index]->GetTop()) +
    1935           0 :         output_offset;
    1936             :     PrintF(trace_scope_->file(),
    1937             :            "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ;  %s",
    1938             :            reinterpret_cast<intptr_t>(output_address), output_offset, value,
    1939           0 :            debug_hint_string == nullptr ? "" : debug_hint_string);
    1940             :   }
    1941      326370 : }
    1942             : 
    1943           0 : unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
    1944             :   unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
    1945      587292 :   if (!function_->IsSmi()) {
    1946      293646 :     fixed_size += ComputeIncomingArgumentSize(function_->shared());
    1947             :   }
    1948           0 :   return fixed_size;
    1949             : }
    1950             : 
    1951      146823 : unsigned Deoptimizer::ComputeInputFrameSize() const {
    1952             :   // The fp-to-sp delta already takes the context, constant pool pointer and the
    1953             :   // function into account so we have to avoid double counting them.
    1954             :   unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
    1955      146823 :   unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
    1956      293646 :   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
    1957             :     unsigned stack_slots = compiled_code_->stack_slots();
    1958             :     unsigned outgoing_size = 0;
    1959             :     //        ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
    1960      146823 :     CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
    1961             :                  CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
    1962             :              result);
    1963             :   }
    1964      146823 :   return result;
    1965             : }
    1966             : 
    1967             : // static
    1968           0 : unsigned Deoptimizer::ComputeJavascriptFixedSize(SharedFunctionInfo* shared) {
    1969             :   // The fixed part of the frame consists of the return address, frame
    1970             :   // pointer, function, context, and all the incoming arguments.
    1971             :   return ComputeIncomingArgumentSize(shared) +
    1972           0 :          StandardFrameConstants::kFixedFrameSize;
    1973             : }
    1974             : 
    1975             : // static
    1976           0 : unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
    1977             :   // The fixed part of the frame consists of the return address, frame
    1978             :   // pointer, function, context, bytecode offset and all the incoming arguments.
    1979             :   return ComputeIncomingArgumentSize(shared) +
    1980      151652 :          InterpreterFrameConstants::kFixedFrameSize;
    1981             : }
    1982             : 
    1983             : // static
    1984           0 : unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
    1985      445298 :   return (shared->internal_formal_parameter_count() + 1) * kPointerSize;
    1986             : }
    1987             : 
    1988     8809828 : void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
    1989             :                                                    BailoutType type,
    1990             :                                                    int max_entry_id) {
    1991             :   // We cannot run this if the serializer is enabled because this will
    1992             :   // cause us to emit relocation information for the external
    1993             :   // references. This is fine because the deoptimizer's code section
    1994             :   // isn't meant to be serialized at all.
    1995     4404914 :   CHECK(type == EAGER || type == SOFT || type == LAZY);
    1996             :   DeoptimizerData* data = isolate->deoptimizer_data();
    1997     4404914 :   int entry_count = data->deopt_entry_code_entries_[type];
    1998     8771396 :   if (max_entry_id < entry_count) return;
    1999             :   entry_count = Max(entry_count, Deoptimizer::kMinNumberOfEntries);
    2000       38432 :   while (max_entry_id >= entry_count) entry_count *= 2;
    2001       38432 :   CHECK_LE(entry_count, Deoptimizer::kMaxNumberOfEntries);
    2002             : 
    2003       38432 :   MacroAssembler masm(isolate, nullptr, 16 * KB, CodeObjectRequired::kYes);
    2004             :   masm.set_emit_debug_code(false);
    2005             :   GenerateDeoptimizationEntries(&masm, entry_count, type);
    2006             :   CodeDesc desc;
    2007       38432 :   masm.GetCode(isolate, &desc);
    2008             :   DCHECK(!RelocInfo::RequiresRelocation(isolate, desc));
    2009             : 
    2010      115296 :   MemoryChunk* chunk = data->deopt_entry_code_[type];
    2011       38432 :   CHECK(static_cast<int>(Deoptimizer::GetMaxDeoptTableSize()) >=
    2012             :         desc.instr_size);
    2013       38432 :   if (!chunk->CommitArea(desc.instr_size)) {
    2014             :     V8::FatalProcessOutOfMemory(
    2015           0 :         "Deoptimizer::EnsureCodeForDeoptimizationEntry");
    2016             :   }
    2017             :   CopyBytes(chunk->area_start(), desc.buffer,
    2018       76864 :             static_cast<size_t>(desc.instr_size));
    2019       76864 :   Assembler::FlushICache(isolate, chunk->area_start(), desc.instr_size);
    2020             : 
    2021       38432 :   data->deopt_entry_code_entries_[type] = entry_count;
    2022             : }
    2023             : 
    2024      439074 : void Deoptimizer::EnsureCodeForMaxDeoptimizationEntries(Isolate* isolate) {
    2025      439074 :   EnsureCodeForDeoptimizationEntry(isolate, EAGER, kMaxNumberOfEntries - 1);
    2026      439074 :   EnsureCodeForDeoptimizationEntry(isolate, LAZY, kMaxNumberOfEntries - 1);
    2027      439074 :   EnsureCodeForDeoptimizationEntry(isolate, SOFT, kMaxNumberOfEntries - 1);
    2028      439074 : }
    2029             : 
    2030      302689 : FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
    2031             :     : frame_size_(frame_size),
    2032             :       parameter_count_(parameter_count),
    2033             :       top_(kZapUint32),
    2034             :       pc_(kZapUint32),
    2035             :       fp_(kZapUint32),
    2036             :       context_(kZapUint32),
    2037      605378 :       constant_pool_(kZapUint32) {
    2038             :   // Zap all the registers.
    2039     5145713 :   for (int r = 0; r < Register::kNumRegisters; r++) {
    2040             :     // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
    2041             :     // isn't used before the next safepoint, the GC will try to scan it as a
    2042             :     // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
    2043     4843024 :     SetRegister(r, kZapUint32);
    2044             :   }
    2045             : 
    2046             :   // Zap all the slots.
    2047     3085257 :   for (unsigned o = 0; o < frame_size; o += kPointerSize) {
    2048             :     SetFrameSlot(o, kZapUint32);
    2049             :   }
    2050      302689 : }
    2051             : 
    2052   118221544 : void TranslationBuffer::Add(int32_t value) {
    2053             :   // This wouldn't handle kMinInt correctly if it ever encountered it.
    2054             :   DCHECK_NE(value, kMinInt);
    2055             :   // Encode the sign bit in the least significant bit.
    2056   118221544 :   bool is_negative = (value < 0);
    2057   118221544 :   uint32_t bits = ((is_negative ? -value : value) << 1) |
    2058   118221544 :       static_cast<int32_t>(is_negative);
    2059             :   // Encode the individual bytes using the least significant bit of
    2060             :   // each byte to indicate whether or not more bytes follow.
    2061   120379799 :   do {
    2062   120379713 :     uint32_t next = bits >> 7;
    2063   120379713 :     contents_.push_back(((bits << 1) & 0xFF) | (next != 0));
    2064             :     bits = next;
    2065             :   } while (bits != 0);
    2066   118221630 : }
    2067             : 
    2068       13971 : TranslationIterator::TranslationIterator(ByteArray* buffer, int index)
    2069     1391443 :     : buffer_(buffer), index_(index) {
    2070             :   DCHECK(index >= 0 && index < buffer->length());
    2071       13971 : }
    2072             : 
    2073    46899274 : int32_t TranslationIterator::Next() {
    2074             :   // Run through the bytes until we reach one with a least significant
    2075             :   // bit of zero (marks the end).
    2076             :   uint32_t bits = 0;
    2077      461306 :   for (int i = 0; true; i += 7) {
    2078             :     DCHECK(HasNext());
    2079    47360580 :     uint8_t next = buffer_->get(index_++);
    2080    47360580 :     bits |= (next >> 1) << i;
    2081    47360580 :     if ((next & 1) == 0) break;
    2082      461306 :   }
    2083             :   // The bits encode the sign in the least significant bit.
    2084    46899274 :   bool is_negative = (bits & 1) == 1;
    2085    46899274 :   int32_t result = bits >> 1;
    2086    46899274 :   return is_negative ? -result : result;
    2087             : }
    2088             : 
    2089     1438844 : bool TranslationIterator::HasNext() const { return index_ < buffer_->length(); }
    2090             : 
    2091      442528 : Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
    2092      442528 :   Handle<ByteArray> result = factory->NewByteArray(CurrentIndex(), TENURED);
    2093      442528 :   contents_.CopyTo(result->GetDataStartAddress());
    2094      442528 :   return result;
    2095             : }
    2096             : 
    2097        1299 : void Translation::BeginBuiltinContinuationFrame(BailoutId bailout_id,
    2098             :                                                 int literal_id,
    2099             :                                                 unsigned height) {
    2100        1299 :   buffer_->Add(BUILTIN_CONTINUATION_FRAME);
    2101        1299 :   buffer_->Add(bailout_id.ToInt());
    2102        1299 :   buffer_->Add(literal_id);
    2103        1299 :   buffer_->Add(height);
    2104        1299 : }
    2105             : 
    2106        1415 : void Translation::BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
    2107             :                                                           int literal_id,
    2108             :                                                           unsigned height) {
    2109        1415 :   buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME);
    2110        1415 :   buffer_->Add(bailout_id.ToInt());
    2111        1415 :   buffer_->Add(literal_id);
    2112        1415 :   buffer_->Add(height);
    2113        1415 : }
    2114             : 
    2115       32279 : void Translation::BeginConstructStubFrame(BailoutId bailout_id, int literal_id,
    2116             :                                           unsigned height) {
    2117       32279 :   buffer_->Add(CONSTRUCT_STUB_FRAME);
    2118       32279 :   buffer_->Add(bailout_id.ToInt());
    2119       32279 :   buffer_->Add(literal_id);
    2120       32279 :   buffer_->Add(height);
    2121       32279 : }
    2122             : 
    2123             : 
    2124        2979 : void Translation::BeginGetterStubFrame(int literal_id) {
    2125        2979 :   buffer_->Add(GETTER_STUB_FRAME);
    2126        2979 :   buffer_->Add(literal_id);
    2127        2979 : }
    2128             : 
    2129             : 
    2130        2329 : void Translation::BeginSetterStubFrame(int literal_id) {
    2131        2329 :   buffer_->Add(SETTER_STUB_FRAME);
    2132        2329 :   buffer_->Add(literal_id);
    2133        2329 : }
    2134             : 
    2135             : 
    2136       61562 : void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
    2137       61562 :   buffer_->Add(ARGUMENTS_ADAPTOR_FRAME);
    2138       61562 :   buffer_->Add(literal_id);
    2139       61562 :   buffer_->Add(height);
    2140       61562 : }
    2141             : 
    2142     3258497 : void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
    2143             :                                         int literal_id, unsigned height) {
    2144     3258497 :   buffer_->Add(INTERPRETED_FRAME);
    2145     3258510 :   buffer_->Add(bytecode_offset.ToInt());
    2146     3258515 :   buffer_->Add(literal_id);
    2147     3258518 :   buffer_->Add(height);
    2148     3258513 : }
    2149             : 
    2150        8973 : void Translation::ArgumentsElements(CreateArgumentsType type) {
    2151        8973 :   buffer_->Add(ARGUMENTS_ELEMENTS);
    2152        8973 :   buffer_->Add(static_cast<uint8_t>(type));
    2153        8973 : }
    2154             : 
    2155        9276 : void Translation::ArgumentsLength(CreateArgumentsType type) {
    2156        9276 :   buffer_->Add(ARGUMENTS_LENGTH);
    2157        9276 :   buffer_->Add(static_cast<uint8_t>(type));
    2158        9276 : }
    2159             : 
    2160       57128 : void Translation::BeginCapturedObject(int length) {
    2161       57128 :   buffer_->Add(CAPTURED_OBJECT);
    2162       57128 :   buffer_->Add(length);
    2163       57128 : }
    2164             : 
    2165             : 
    2166       11820 : void Translation::DuplicateObject(int object_index) {
    2167       11820 :   buffer_->Add(DUPLICATED_OBJECT);
    2168       11820 :   buffer_->Add(object_index);
    2169       11820 : }
    2170             : 
    2171             : 
    2172     2121032 : void Translation::StoreRegister(Register reg) {
    2173     2121032 :   buffer_->Add(REGISTER);
    2174     2121038 :   buffer_->Add(reg.code());
    2175     2121042 : }
    2176             : 
    2177             : 
    2178       53795 : void Translation::StoreInt32Register(Register reg) {
    2179       53795 :   buffer_->Add(INT32_REGISTER);
    2180       53795 :   buffer_->Add(reg.code());
    2181       53795 : }
    2182             : 
    2183             : 
    2184        1473 : void Translation::StoreUint32Register(Register reg) {
    2185        1473 :   buffer_->Add(UINT32_REGISTER);
    2186        1473 :   buffer_->Add(reg.code());
    2187        1473 : }
    2188             : 
    2189             : 
    2190        2732 : void Translation::StoreBoolRegister(Register reg) {
    2191        2732 :   buffer_->Add(BOOL_REGISTER);
    2192        2732 :   buffer_->Add(reg.code());
    2193        2732 : }
    2194             : 
    2195         227 : void Translation::StoreFloatRegister(FloatRegister reg) {
    2196         227 :   buffer_->Add(FLOAT_REGISTER);
    2197         227 :   buffer_->Add(reg.code());
    2198         227 : }
    2199             : 
    2200       68907 : void Translation::StoreDoubleRegister(DoubleRegister reg) {
    2201       68907 :   buffer_->Add(DOUBLE_REGISTER);
    2202       68904 :   buffer_->Add(reg.code());
    2203       68905 : }
    2204             : 
    2205             : 
    2206    17085623 : void Translation::StoreStackSlot(int index) {
    2207    17085623 :   buffer_->Add(STACK_SLOT);
    2208    17085639 :   buffer_->Add(index);
    2209    17085617 : }
    2210             : 
    2211             : 
    2212      239055 : void Translation::StoreInt32StackSlot(int index) {
    2213      239055 :   buffer_->Add(INT32_STACK_SLOT);
    2214      239055 :   buffer_->Add(index);
    2215      239055 : }
    2216             : 
    2217             : 
    2218         969 : void Translation::StoreUint32StackSlot(int index) {
    2219         969 :   buffer_->Add(UINT32_STACK_SLOT);
    2220         969 :   buffer_->Add(index);
    2221         969 : }
    2222             : 
    2223             : 
    2224       23961 : void Translation::StoreBoolStackSlot(int index) {
    2225       23961 :   buffer_->Add(BOOL_STACK_SLOT);
    2226       23961 :   buffer_->Add(index);
    2227       23961 : }
    2228             : 
    2229         325 : void Translation::StoreFloatStackSlot(int index) {
    2230         325 :   buffer_->Add(FLOAT_STACK_SLOT);
    2231         325 :   buffer_->Add(index);
    2232         325 : }
    2233             : 
    2234      187771 : void Translation::StoreDoubleStackSlot(int index) {
    2235      187771 :   buffer_->Add(DOUBLE_STACK_SLOT);
    2236      187772 :   buffer_->Add(index);
    2237      187772 : }
    2238             : 
    2239             : 
    2240    27922515 : void Translation::StoreLiteral(int literal_id) {
    2241    27922515 :   buffer_->Add(LITERAL);
    2242    27922497 :   buffer_->Add(literal_id);
    2243    27922489 : }
    2244             : 
    2245             : 
    2246     2989484 : void Translation::StoreJSFrameFunction() {
    2247             :   StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
    2248             :                   StandardFrameConstants::kFunctionOffset) /
    2249     2989484 :                  kPointerSize);
    2250     2989511 : }
    2251             : 
    2252       40438 : int Translation::NumberOfOperandsFor(Opcode opcode) {
    2253       40438 :   switch (opcode) {
    2254             :     case GETTER_STUB_FRAME:
    2255             :     case SETTER_STUB_FRAME:
    2256             :     case DUPLICATED_OBJECT:
    2257             :     case ARGUMENTS_ELEMENTS:
    2258             :     case ARGUMENTS_LENGTH:
    2259             :     case CAPTURED_OBJECT:
    2260             :     case REGISTER:
    2261             :     case INT32_REGISTER:
    2262             :     case UINT32_REGISTER:
    2263             :     case BOOL_REGISTER:
    2264             :     case FLOAT_REGISTER:
    2265             :     case DOUBLE_REGISTER:
    2266             :     case STACK_SLOT:
    2267             :     case INT32_STACK_SLOT:
    2268             :     case UINT32_STACK_SLOT:
    2269             :     case BOOL_STACK_SLOT:
    2270             :     case FLOAT_STACK_SLOT:
    2271             :     case DOUBLE_STACK_SLOT:
    2272             :     case LITERAL:
    2273             :       return 1;
    2274             :     case BEGIN:
    2275             :     case ARGUMENTS_ADAPTOR_FRAME:
    2276        2288 :       return 2;
    2277             :     case INTERPRETED_FRAME:
    2278             :     case CONSTRUCT_STUB_FRAME:
    2279             :     case BUILTIN_CONTINUATION_FRAME:
    2280             :     case JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
    2281       11739 :       return 3;
    2282             :   }
    2283           0 :   FATAL("Unexpected translation type");
    2284             :   return -1;
    2285             : }
    2286             : 
    2287             : 
    2288             : #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
    2289             : 
    2290             : const char* Translation::StringFor(Opcode opcode) {
    2291             : #define TRANSLATION_OPCODE_CASE(item)   case item: return #item;
    2292             :   switch (opcode) {
    2293             :     TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
    2294             :   }
    2295             : #undef TRANSLATION_OPCODE_CASE
    2296             :   UNREACHABLE();
    2297             : }
    2298             : 
    2299             : #endif
    2300             : 
    2301             : 
    2302     1377862 : Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
    2303     1377639 :   int index = StackIdToIndex(fp);
    2304     1377639 :   if (index == -1) {
    2305             :     return Handle<FixedArray>::null();
    2306             :   }
    2307         223 :   Handle<FixedArray> array = GetStackEntries();
    2308         223 :   CHECK_GT(array->length(), index);
    2309             :   return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
    2310             : }
    2311             : 
    2312             : 
    2313         139 : void MaterializedObjectStore::Set(Address fp,
    2314             :                                   Handle<FixedArray> materialized_objects) {
    2315         139 :   int index = StackIdToIndex(fp);
    2316         139 :   if (index == -1) {
    2317         278 :     index = static_cast<int>(frame_fps_.size());
    2318         139 :     frame_fps_.push_back(fp);
    2319             :   }
    2320             : 
    2321         139 :   Handle<FixedArray> array = EnsureStackEntries(index + 1);
    2322         139 :   array->set(index, *materialized_objects);
    2323         139 : }
    2324             : 
    2325             : 
    2326     2768670 : bool MaterializedObjectStore::Remove(Address fp) {
    2327         139 :   auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
    2328     2768392 :   if (it == frame_fps_.end()) return false;
    2329         139 :   int index = static_cast<int>(std::distance(frame_fps_.begin(), it));
    2330             : 
    2331         139 :   frame_fps_.erase(it);
    2332         139 :   FixedArray* array = isolate()->heap()->materialized_objects();
    2333             : 
    2334         139 :   CHECK_LT(index, array->length());
    2335         139 :   int fps_size = static_cast<int>(frame_fps_.size());
    2336         278 :   for (int i = index; i < fps_size; i++) {
    2337           0 :     array->set(i, array->get(i + 1));
    2338             :   }
    2339         139 :   array->set(fps_size, isolate()->heap()->undefined_value());
    2340         139 :   return true;
    2341             : }
    2342             : 
    2343             : 
    2344     1377778 : int MaterializedObjectStore::StackIdToIndex(Address fp) {
    2345             :   auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
    2346             :   return it == frame_fps_.end()
    2347             :              ? -1
    2348     1378001 :              : static_cast<int>(std::distance(frame_fps_.begin(), it));
    2349             : }
    2350             : 
    2351             : 
    2352         362 : Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
    2353         724 :   return Handle<FixedArray>(isolate()->heap()->materialized_objects());
    2354             : }
    2355             : 
    2356             : 
    2357         304 : Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
    2358         139 :   Handle<FixedArray> array = GetStackEntries();
    2359         139 :   if (array->length() >= length) {
    2360          84 :     return array;
    2361             :   }
    2362             : 
    2363          55 :   int new_length = length > 10 ? length : 10;
    2364          55 :   if (new_length < 2 * array->length()) {
    2365             :     new_length = 2 * array->length();
    2366             :   }
    2367             : 
    2368             :   Handle<FixedArray> new_array =
    2369          55 :       isolate()->factory()->NewFixedArray(new_length, TENURED);
    2370         110 :   for (int i = 0; i < array->length(); i++) {
    2371           0 :     new_array->set(i, array->get(i));
    2372             :   }
    2373          55 :   for (int i = array->length(); i < length; i++) {
    2374         110 :     new_array->set(i, isolate()->heap()->undefined_value());
    2375             :   }
    2376             :   isolate()->heap()->SetRootMaterializedObjects(*new_array);
    2377          55 :   return new_array;
    2378             : }
    2379             : 
    2380             : namespace {
    2381             : 
    2382      229316 : Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
    2383             :                                    Isolate* isolate) {
    2384      229316 :   if (it->GetRawValue() == isolate->heap()->arguments_marker()) {
    2385       28367 :     if (!it->IsMaterializableByDebugger()) {
    2386          91 :       return isolate->factory()->optimized_out();
    2387             :     }
    2388             :   }
    2389      229225 :   return it->GetValue();
    2390             : }
    2391             : 
    2392             : }  // namespace
    2393             : 
    2394       34855 : DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
    2395             :                                            TranslatedState::iterator frame_it,
    2396             :                                            Isolate* isolate) {
    2397             :   // If the previous frame is an adaptor frame, we will take the parameters
    2398             :   // from there.
    2399             :   TranslatedState::iterator parameter_frame = frame_it;
    2400       34855 :   if (parameter_frame != state->begin()) {
    2401             :     parameter_frame--;
    2402             :   }
    2403             :   int parameter_count;
    2404       34855 :   if (parameter_frame->kind() == TranslatedFrame::kArgumentsAdaptor) {
    2405        5397 :     parameter_count = parameter_frame->height() - 1;  // Ignore the receiver.
    2406             :   } else {
    2407             :     parameter_frame = frame_it;
    2408             :     parameter_count =
    2409             :         frame_it->shared_info()->internal_formal_parameter_count();
    2410             :   }
    2411             :   TranslatedFrame::iterator parameter_it = parameter_frame->begin();
    2412             :   parameter_it++;  // Skip the function.
    2413             :   parameter_it++;  // Skip the receiver.
    2414             : 
    2415             :   // Figure out whether there is a construct stub frame on top of
    2416             :   // the parameter frame.
    2417             :   has_construct_stub_ =
    2418       48157 :       parameter_frame != state->begin() &&
    2419       48157 :       (parameter_frame - 1)->kind() == TranslatedFrame::kConstructStub;
    2420             : 
    2421             :   DCHECK_EQ(TranslatedFrame::kInterpretedFunction, frame_it->kind());
    2422             :   source_position_ = Deoptimizer::ComputeSourcePositionFromBytecodeArray(
    2423       34855 :       *frame_it->shared_info(), frame_it->node_id());
    2424             : 
    2425             :   TranslatedFrame::iterator value_it = frame_it->begin();
    2426             :   // Get the function. Note that this might materialize the function.
    2427             :   // In case the debugger mutates this value, we should deoptimize
    2428             :   // the function and remember the value in the materialized value store.
    2429       34855 :   function_ = Handle<JSFunction>::cast(value_it->GetValue());
    2430             : 
    2431       34855 :   parameters_.resize(static_cast<size_t>(parameter_count));
    2432       87865 :   for (int i = 0; i < parameter_count; i++) {
    2433       53010 :     Handle<Object> parameter = GetValueForDebugger(parameter_it, isolate);
    2434             :     SetParameter(i, parameter);
    2435             :     parameter_it++;
    2436             :   }
    2437             : 
    2438             :   // Skip the function, the receiver and the arguments.
    2439             :   int skip_count =
    2440       34855 :       frame_it->shared_info()->internal_formal_parameter_count() + 2;
    2441             :   TranslatedFrame::iterator stack_it = frame_it->begin();
    2442      155923 :   for (int i = 0; i < skip_count; i++) {
    2443             :     stack_it++;
    2444             :   }
    2445             : 
    2446             :   // Get the context.
    2447       34855 :   context_ = GetValueForDebugger(stack_it, isolate);
    2448             :   stack_it++;
    2449             : 
    2450             :   // Get the expression stack.
    2451       34855 :   int stack_height = frame_it->height();
    2452       34855 :   if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
    2453             :     // For interpreter frames, we should not count the accumulator.
    2454             :     // TODO(jarin): Clean up the indexing in translated frames.
    2455       34855 :     stack_height--;
    2456             :   }
    2457       34855 :   expression_stack_.resize(static_cast<size_t>(stack_height));
    2458      176306 :   for (int i = 0; i < stack_height; i++) {
    2459      141451 :     Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
    2460             :     SetExpression(i, expression);
    2461             :     stack_it++;
    2462             :   }
    2463             : 
    2464             :   // For interpreter frame, skip the accumulator.
    2465       34855 :   if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
    2466             :     stack_it++;
    2467             :   }
    2468       34855 :   CHECK(stack_it == frame_it->end());
    2469       34855 : }
    2470             : 
    2471             : 
    2472           9 : Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code* code, Address pc) {
    2473          18 :   CHECK(code->instruction_start() <= pc && pc <= code->instruction_end());
    2474             :   SourcePosition last_position = SourcePosition::Unknown();
    2475             :   DeoptimizeReason last_reason = DeoptimizeReason::kNoReason;
    2476             :   int last_deopt_id = kNoDeoptimizationId;
    2477             :   int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
    2478             :              RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
    2479             :              RelocInfo::ModeMask(RelocInfo::DEOPT_SCRIPT_OFFSET) |
    2480             :              RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID);
    2481          27 :   for (RelocIterator it(code, mask); !it.done(); it.next()) {
    2482          60 :     RelocInfo* info = it.rinfo();
    2483          24 :     if (info->pc() >= pc) break;
    2484          18 :     if (info->rmode() == RelocInfo::DEOPT_SCRIPT_OFFSET) {
    2485           6 :       int script_offset = static_cast<int>(info->data());
    2486           6 :       it.next();
    2487             :       DCHECK(it.rinfo()->rmode() == RelocInfo::DEOPT_INLINING_ID);
    2488           6 :       int inlining_id = static_cast<int>(it.rinfo()->data());
    2489             :       last_position = SourcePosition(script_offset, inlining_id);
    2490          12 :     } else if (info->rmode() == RelocInfo::DEOPT_ID) {
    2491           6 :       last_deopt_id = static_cast<int>(info->data());
    2492           6 :     } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
    2493           6 :       last_reason = static_cast<DeoptimizeReason>(info->data());
    2494             :     }
    2495             :   }
    2496           9 :   return DeoptInfo(last_position, last_reason, last_deopt_id);
    2497             : }
    2498             : 
    2499             : 
    2500             : // static
    2501           0 : int Deoptimizer::ComputeSourcePositionFromBytecodeArray(
    2502             :     SharedFunctionInfo* shared, BailoutId node_id) {
    2503             :   DCHECK(shared->HasBytecodeArray());
    2504             :   return AbstractCode::cast(shared->bytecode_array())
    2505       34855 :       ->SourcePosition(node_id.ToInt());
    2506             : }
    2507             : 
    2508             : // static
    2509           0 : TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
    2510             :                                                    int length,
    2511             :                                                    int object_index) {
    2512             :   TranslatedValue slot(container, kCapturedObject);
    2513      115743 :   slot.materialization_info_ = {object_index, length};
    2514           0 :   return slot;
    2515             : }
    2516             : 
    2517             : 
    2518             : // static
    2519           0 : TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
    2520             :                                                     int id) {
    2521             :   TranslatedValue slot(container, kDuplicatedObject);
    2522       99365 :   slot.materialization_info_ = {id, -1};
    2523           0 :   return slot;
    2524             : }
    2525             : 
    2526             : 
    2527             : // static
    2528           0 : TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
    2529             :                                           Float32 value) {
    2530             :   TranslatedValue slot(container, kFloat);
    2531         280 :   slot.float_value_ = value;
    2532           0 :   return slot;
    2533             : }
    2534             : 
    2535             : // static
    2536           0 : TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
    2537             :                                            Float64 value) {
    2538             :   TranslatedValue slot(container, kDouble);
    2539      566140 :   slot.double_value_ = value;
    2540           0 :   return slot;
    2541             : }
    2542             : 
    2543             : 
    2544             : // static
    2545           0 : TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
    2546             :                                           int32_t value) {
    2547             :   TranslatedValue slot(container, kInt32);
    2548      424952 :   slot.int32_value_ = value;
    2549           0 :   return slot;
    2550             : }
    2551             : 
    2552             : 
    2553             : // static
    2554           0 : TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
    2555             :                                            uint32_t value) {
    2556             :   TranslatedValue slot(container, kUInt32);
    2557          14 :   slot.uint32_value_ = value;
    2558           0 :   return slot;
    2559             : }
    2560             : 
    2561             : 
    2562             : // static
    2563           0 : TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
    2564             :                                          uint32_t value) {
    2565             :   TranslatedValue slot(container, kBoolBit);
    2566         584 :   slot.uint32_value_ = value;
    2567           0 :   return slot;
    2568             : }
    2569             : 
    2570             : 
    2571             : // static
    2572           0 : TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
    2573             :                                            Object* literal) {
    2574             :   TranslatedValue slot(container, kTagged);
    2575    14782854 :   slot.raw_literal_ = literal;
    2576           0 :   return slot;
    2577             : }
    2578             : 
    2579             : 
    2580             : // static
    2581           0 : TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
    2582           0 :   return TranslatedValue(container, kInvalid);
    2583             : }
    2584             : 
    2585             : 
    2586    14894420 : Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
    2587             : 
    2588             : 
    2589           0 : Object* TranslatedValue::raw_literal() const {
    2590             :   DCHECK_EQ(kTagged, kind());
    2591    16073903 :   return raw_literal_;
    2592             : }
    2593             : 
    2594             : 
    2595           0 : int32_t TranslatedValue::int32_value() const {
    2596             :   DCHECK_EQ(kInt32, kind());
    2597       35675 :   return int32_value_;
    2598             : }
    2599             : 
    2600             : 
    2601           0 : uint32_t TranslatedValue::uint32_value() const {
    2602             :   DCHECK(kind() == kUInt32 || kind() == kBoolBit);
    2603         142 :   return uint32_value_;
    2604             : }
    2605             : 
    2606           0 : Float32 TranslatedValue::float_value() const {
    2607             :   DCHECK_EQ(kFloat, kind());
    2608         280 :   return float_value_;
    2609             : }
    2610             : 
    2611           0 : Float64 TranslatedValue::double_value() const {
    2612             :   DCHECK_EQ(kDouble, kind());
    2613       31059 :   return double_value_;
    2614             : }
    2615             : 
    2616             : 
    2617           0 : int TranslatedValue::object_length() const {
    2618             :   DCHECK_EQ(kind(), kCapturedObject);
    2619      154006 :   return materialization_info_.length_;
    2620             : }
    2621             : 
    2622             : 
    2623           0 : int TranslatedValue::object_index() const {
    2624             :   DCHECK(kind() == kCapturedObject || kind() == kDuplicatedObject);
    2625       35064 :   return materialization_info_.id_;
    2626             : }
    2627             : 
    2628             : 
    2629     2966477 : Object* TranslatedValue::GetRawValue() const {
    2630             :   // If we have a value, return it.
    2631             :   Handle<Object> result_handle;
    2632     1576856 :   if (value_.ToHandle(&result_handle)) {
    2633      187235 :     return *result_handle;
    2634             :   }
    2635             : 
    2636             :   // Otherwise, do a best effort to get the value without allocation.
    2637     1389621 :   switch (kind()) {
    2638             :     case kTagged:
    2639     1291049 :       return raw_literal();
    2640             : 
    2641             :     case kInt32: {
    2642             :       bool is_smi = Smi::IsValid(int32_value());
    2643             :       if (is_smi) {
    2644       35675 :         return Smi::FromInt(int32_value());
    2645             :       }
    2646             :       break;
    2647             :     }
    2648             : 
    2649             :     case kUInt32: {
    2650          21 :       bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
    2651          21 :       if (is_smi) {
    2652           7 :         return Smi::FromInt(static_cast<int32_t>(uint32_value()));
    2653             :       }
    2654             :       break;
    2655             :     }
    2656             : 
    2657             :     case kBoolBit: {
    2658         114 :       if (uint32_value() == 0) {
    2659          93 :         return isolate()->heap()->false_value();
    2660             :       } else {
    2661          21 :         CHECK_EQ(1U, uint32_value());
    2662          21 :         return isolate()->heap()->true_value();
    2663             :       }
    2664             :     }
    2665             : 
    2666             :     default:
    2667             :       break;
    2668             :   }
    2669             : 
    2670             :   // If we could not get the value without allocation, return the arguments
    2671             :   // marker.
    2672       62776 :   return isolate()->heap()->arguments_marker();
    2673             : }
    2674             : 
    2675             : 
    2676     3304105 : Handle<Object> TranslatedValue::GetValue() {
    2677             :   Handle<Object> result;
    2678             :   // If we already have a value, then get it.
    2679     3221171 :   if (value_.ToHandle(&result)) return result;
    2680             : 
    2681             :   // Otherwise we have to materialize.
    2682       82934 :   switch (kind()) {
    2683             :     case TranslatedValue::kTagged:
    2684             :     case TranslatedValue::kInt32:
    2685             :     case TranslatedValue::kUInt32:
    2686             :     case TranslatedValue::kBoolBit:
    2687             :     case TranslatedValue::kFloat:
    2688             :     case TranslatedValue::kDouble: {
    2689       47924 :       MaterializeSimple();
    2690             :       return value_.ToHandleChecked();
    2691             :     }
    2692             : 
    2693             :     case TranslatedValue::kCapturedObject:
    2694             :     case TranslatedValue::kDuplicatedObject:
    2695       35010 :       return container_->MaterializeObjectAt(object_index());
    2696             : 
    2697             :     case TranslatedValue::kInvalid:
    2698           0 :       FATAL("unexpected case");
    2699             :       return Handle<Object>::null();
    2700             :   }
    2701             : 
    2702           0 :   FATAL("internal error: value missing");
    2703             :   return Handle<Object>::null();
    2704             : }
    2705             : 
    2706             : 
    2707      203203 : void TranslatedValue::MaterializeSimple() {
    2708             :   // If we already have materialized, return.
    2709      171857 :   if (!value_.is_null()) return;
    2710             : 
    2711       48676 :   Object* raw_value = GetRawValue();
    2712       48676 :   if (raw_value != isolate()->heap()->arguments_marker()) {
    2713             :     // We can get the value without allocation, just return it here.
    2714       17330 :     value_ = Handle<Object>(raw_value, isolate());
    2715       17330 :     return;
    2716             :   }
    2717             : 
    2718       31346 :   switch (kind()) {
    2719             :     case kInt32:
    2720           0 :       value_ = Handle<Object>(isolate()->factory()->NewNumber(int32_value()));
    2721           0 :       return;
    2722             : 
    2723             :     case kUInt32:
    2724           7 :       value_ = Handle<Object>(isolate()->factory()->NewNumber(uint32_value()));
    2725           7 :       return;
    2726             : 
    2727             :     case kFloat: {
    2728         280 :       double scalar_value = float_value().get_scalar();
    2729         280 :       value_ = Handle<Object>(isolate()->factory()->NewNumber(scalar_value));
    2730         280 :       return;
    2731             :     }
    2732             : 
    2733             :     case kDouble: {
    2734       31059 :       double scalar_value = double_value().get_scalar();
    2735       31059 :       value_ = Handle<Object>(isolate()->factory()->NewNumber(scalar_value));
    2736       31059 :       return;
    2737             :     }
    2738             : 
    2739             :     case kCapturedObject:
    2740             :     case kDuplicatedObject:
    2741             :     case kInvalid:
    2742             :     case kTagged:
    2743             :     case kBoolBit:
    2744           0 :       FATAL("internal error: unexpected materialization.");
    2745             :       break;
    2746             :   }
    2747             : }
    2748             : 
    2749             : 
    2750        8123 : bool TranslatedValue::IsMaterializedObject() const {
    2751        8123 :   switch (kind()) {
    2752             :     case kCapturedObject:
    2753             :     case kDuplicatedObject:
    2754             :       return true;
    2755             :     default:
    2756        7005 :       return false;
    2757             :   }
    2758             : }
    2759             : 
    2760       28367 : bool TranslatedValue::IsMaterializableByDebugger() const {
    2761             :   // At the moment, we only allow materialization of doubles.
    2762           0 :   return (kind() == kDouble);
    2763             : }
    2764             : 
    2765    21664692 : int TranslatedValue::GetChildrenCount() const {
    2766    21664692 :   if (kind() == kCapturedObject) {
    2767           0 :     return object_length();
    2768             :   } else {
    2769             :     return 0;
    2770             :   }
    2771             : }
    2772             : 
    2773             : 
    2774           0 : uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
    2775      424418 :   Address address = fp + slot_offset;
    2776             : #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
    2777             :   return Memory::uint32_at(address + kIntSize);
    2778             : #else
    2779      424418 :   return Memory::uint32_at(address);
    2780             : #endif
    2781             : }
    2782             : 
    2783           0 : Float32 TranslatedState::GetFloatSlot(Address fp, int slot_offset) {
    2784             : #if !V8_TARGET_ARCH_S390X && !V8_TARGET_ARCH_PPC64
    2785           0 :   return Float32::FromBits(GetUInt32Slot(fp, slot_offset));
    2786             : #else
    2787             :   return Float32::FromBits(Memory::uint32_at(fp + slot_offset));
    2788             : #endif
    2789             : }
    2790             : 
    2791           0 : Float64 TranslatedState::GetDoubleSlot(Address fp, int slot_offset) {
    2792      565729 :   return Float64::FromBits(Memory::uint64_at(fp + slot_offset));
    2793             : }
    2794             : 
    2795    16996925 : void TranslatedValue::Handlify() {
    2796    16996925 :   if (kind() == kTagged) {
    2797    14782854 :     value_ = Handle<Object>(raw_literal(), isolate());
    2798    14782854 :     raw_literal_ = nullptr;
    2799             :   }
    2800    16996925 : }
    2801             : 
    2802             : 
    2803           0 : TranslatedFrame TranslatedFrame::InterpretedFrame(
    2804             :     BailoutId bytecode_offset, SharedFunctionInfo* shared_info, int height) {
    2805             :   TranslatedFrame frame(kInterpretedFunction, shared_info->GetIsolate(),
    2806             :                         shared_info, height);
    2807     1652164 :   frame.node_id_ = bytecode_offset;
    2808           0 :   return frame;
    2809             : }
    2810             : 
    2811             : 
    2812           0 : TranslatedFrame TranslatedFrame::AccessorFrame(
    2813             :     Kind kind, SharedFunctionInfo* shared_info) {
    2814             :   DCHECK(kind == kSetter || kind == kGetter);
    2815           0 :   return TranslatedFrame(kind, shared_info->GetIsolate(), shared_info);
    2816             : }
    2817             : 
    2818             : 
    2819           0 : TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
    2820             :     SharedFunctionInfo* shared_info, int height) {
    2821             :   return TranslatedFrame(kArgumentsAdaptor, shared_info->GetIsolate(),
    2822           0 :                          shared_info, height);
    2823             : }
    2824             : 
    2825           0 : TranslatedFrame TranslatedFrame::ConstructStubFrame(
    2826             :     BailoutId bailout_id, SharedFunctionInfo* shared_info, int height) {
    2827             :   TranslatedFrame frame(kConstructStub, shared_info->GetIsolate(), shared_info,
    2828             :                         height);
    2829       50538 :   frame.node_id_ = bailout_id;
    2830           0 :   return frame;
    2831             : }
    2832             : 
    2833           0 : TranslatedFrame TranslatedFrame::BuiltinContinuationFrame(
    2834             :     BailoutId bailout_id, SharedFunctionInfo* shared_info, int height) {
    2835             :   TranslatedFrame frame(kBuiltinContinuation, shared_info->GetIsolate(),
    2836             :                         shared_info, height);
    2837       46305 :   frame.node_id_ = bailout_id;
    2838           0 :   return frame;
    2839             : }
    2840             : 
    2841           0 : TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationFrame(
    2842             :     BailoutId bailout_id, SharedFunctionInfo* shared_info, int height) {
    2843             :   TranslatedFrame frame(kJavaScriptBuiltinContinuation,
    2844             :                         shared_info->GetIsolate(), shared_info, height);
    2845         969 :   frame.node_id_ = bailout_id;
    2846           0 :   return frame;
    2847             : }
    2848             : 
    2849     1853636 : int TranslatedFrame::GetValueCount() {
    2850     1853636 :   switch (kind()) {
    2851             :     case kInterpretedFunction: {
    2852             :       int parameter_count =
    2853     3304328 :           raw_shared_info_->internal_formal_parameter_count() + 1;
    2854             :       // + 2 for function and context.
    2855     1652164 :       return height_ + parameter_count + 2;
    2856             :     }
    2857             : 
    2858             :     case kGetter:
    2859             :       return 2;  // Function and receiver.
    2860             : 
    2861             :     case kSetter:
    2862         610 :       return 3;  // Function, receiver and the value to set.
    2863             : 
    2864             :     case kArgumentsAdaptor:
    2865             :     case kConstructStub:
    2866             :     case kBuiltinContinuation:
    2867             :     case kJavaScriptBuiltinContinuation:
    2868      200482 :       return 1 + height_;
    2869             : 
    2870             :     case kInvalid:
    2871           0 :       UNREACHABLE();
    2872             :       break;
    2873             :   }
    2874           0 :   UNREACHABLE();
    2875             : }
    2876             : 
    2877             : 
    2878     1853636 : void TranslatedFrame::Handlify() {
    2879     1853636 :   if (raw_shared_info_ != nullptr) {
    2880     1853636 :     shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_);
    2881     1853636 :     raw_shared_info_ = nullptr;
    2882             :   }
    2883    18850561 :   for (auto& value : values_) {
    2884    16996925 :     value.Handlify();
    2885             :   }
    2886     1853636 : }
    2887             : 
    2888             : 
    2889     1853636 : TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
    2890             :     TranslationIterator* iterator, FixedArray* literal_array, Address fp,
    2891             :     FILE* trace_file) {
    2892             :   Translation::Opcode opcode =
    2893     1853636 :       static_cast<Translation::Opcode>(iterator->Next());
    2894     1853636 :   switch (opcode) {
    2895             :     case Translation::INTERPRETED_FRAME: {
    2896     1652164 :       BailoutId bytecode_offset = BailoutId(iterator->Next());
    2897             :       SharedFunctionInfo* shared_info =
    2898     1652164 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2899     1652164 :       int height = iterator->Next();
    2900     1652164 :       if (trace_file != nullptr) {
    2901           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2902           0 :         PrintF(trace_file, "  reading input frame %s", name.get());
    2903           0 :         int arg_count = shared_info->internal_formal_parameter_count() + 1;
    2904             :         PrintF(trace_file,
    2905             :                " => bytecode_offset=%d, args=%d, height=%d; inputs:\n",
    2906           0 :                bytecode_offset.ToInt(), arg_count, height);
    2907             :       }
    2908             :       return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
    2909             :                                                height);
    2910             :     }
    2911             : 
    2912             :     case Translation::ARGUMENTS_ADAPTOR_FRAME: {
    2913             :       SharedFunctionInfo* shared_info =
    2914      102670 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2915      102670 :       int height = iterator->Next();
    2916      102670 :       if (trace_file != nullptr) {
    2917           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2918           0 :         PrintF(trace_file, "  reading arguments adaptor frame %s", name.get());
    2919           0 :         PrintF(trace_file, " => height=%d; inputs:\n", height);
    2920             :       }
    2921             :       return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
    2922             :     }
    2923             : 
    2924             :     case Translation::CONSTRUCT_STUB_FRAME: {
    2925       50538 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2926             :       SharedFunctionInfo* shared_info =
    2927       50538 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2928       50538 :       int height = iterator->Next();
    2929       50538 :       if (trace_file != nullptr) {
    2930           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2931           0 :         PrintF(trace_file, "  reading construct stub frame %s", name.get());
    2932             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2933           0 :                bailout_id.ToInt(), height);
    2934             :       }
    2935             :       return TranslatedFrame::ConstructStubFrame(bailout_id, shared_info,
    2936             :                                                  height);
    2937             :     }
    2938             : 
    2939             :     case Translation::BUILTIN_CONTINUATION_FRAME: {
    2940       46305 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2941             :       SharedFunctionInfo* shared_info =
    2942       46305 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2943       46305 :       int height = iterator->Next();
    2944       46305 :       if (trace_file != nullptr) {
    2945           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2946             :         PrintF(trace_file, "  reading builtin continuation frame %s",
    2947           0 :                name.get());
    2948             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2949           0 :                bailout_id.ToInt(), height);
    2950             :       }
    2951             :       // Add one to the height to account for the context which was implicitly
    2952             :       // added to the translation during code generation.
    2953       46305 :       int height_with_context = height + 1;
    2954             :       return TranslatedFrame::BuiltinContinuationFrame(bailout_id, shared_info,
    2955             :                                                        height_with_context);
    2956             :     }
    2957             : 
    2958             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME: {
    2959         969 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2960             :       SharedFunctionInfo* shared_info =
    2961         969 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2962         969 :       int height = iterator->Next();
    2963         969 :       if (trace_file != nullptr) {
    2964           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2965             :         PrintF(trace_file, "  reading JavaScript builtin continuation frame %s",
    2966           0 :                name.get());
    2967             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2968           0 :                bailout_id.ToInt(), height);
    2969             :       }
    2970             :       // Add one to the height to account for the context which was implicitly
    2971             :       // added to the translation during code generation.
    2972         969 :       int height_with_context = height + 1;
    2973             :       return TranslatedFrame::JavaScriptBuiltinContinuationFrame(
    2974             :           bailout_id, shared_info, height_with_context);
    2975             :     }
    2976             : 
    2977             :     case Translation::GETTER_STUB_FRAME: {
    2978             :       SharedFunctionInfo* shared_info =
    2979         380 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2980         380 :       if (trace_file != nullptr) {
    2981           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2982           0 :         PrintF(trace_file, "  reading getter frame %s; inputs:\n", name.get());
    2983             :       }
    2984             :       return TranslatedFrame::AccessorFrame(TranslatedFrame::kGetter,
    2985             :                                             shared_info);
    2986             :     }
    2987             : 
    2988             :     case Translation::SETTER_STUB_FRAME: {
    2989             :       SharedFunctionInfo* shared_info =
    2990         610 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2991         610 :       if (trace_file != nullptr) {
    2992           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2993           0 :         PrintF(trace_file, "  reading setter frame %s; inputs:\n", name.get());
    2994             :       }
    2995             :       return TranslatedFrame::AccessorFrame(TranslatedFrame::kSetter,
    2996             :                                             shared_info);
    2997             :     }
    2998             : 
    2999             :     case Translation::BEGIN:
    3000             :     case Translation::DUPLICATED_OBJECT:
    3001             :     case Translation::ARGUMENTS_ELEMENTS:
    3002             :     case Translation::ARGUMENTS_LENGTH:
    3003             :     case Translation::CAPTURED_OBJECT:
    3004             :     case Translation::REGISTER:
    3005             :     case Translation::INT32_REGISTER:
    3006             :     case Translation::UINT32_REGISTER:
    3007             :     case Translation::BOOL_REGISTER:
    3008             :     case Translation::FLOAT_REGISTER:
    3009             :     case Translation::DOUBLE_REGISTER:
    3010             :     case Translation::STACK_SLOT:
    3011             :     case Translation::INT32_STACK_SLOT:
    3012             :     case Translation::UINT32_STACK_SLOT:
    3013             :     case Translation::BOOL_STACK_SLOT:
    3014             :     case Translation::FLOAT_STACK_SLOT:
    3015             :     case Translation::DOUBLE_STACK_SLOT:
    3016             :     case Translation::LITERAL:
    3017             :       break;
    3018             :   }
    3019           0 :   FATAL("We should never get here - unexpected deopt info.");
    3020             :   return TranslatedFrame::InvalidFrame();
    3021             : }
    3022             : 
    3023             : 
    3024             : // static
    3025     4619994 : void TranslatedFrame::AdvanceIterator(
    3026     4634255 :     std::deque<TranslatedValue>::iterator* iter) {
    3027             :   int values_to_skip = 1;
    3028    13874243 :   while (values_to_skip > 0) {
    3029             :     // Consume the current element.
    3030     4634255 :     values_to_skip--;
    3031             :     // Add all the children.
    3032     4634255 :     values_to_skip += (*iter)->GetChildrenCount();
    3033             : 
    3034     4634255 :     (*iter)++;
    3035             :   }
    3036     4619994 : }
    3037             : 
    3038         604 : Address TranslatedState::ComputeArgumentsPosition(Address input_frame_pointer,
    3039             :                                                   CreateArgumentsType type,
    3040             :                                                   int* length) {
    3041             :   Address parent_frame_pointer = *reinterpret_cast<Address*>(
    3042         604 :       input_frame_pointer + StandardFrameConstants::kCallerFPOffset);
    3043             :   intptr_t parent_frame_type = Memory::intptr_at(
    3044         604 :       parent_frame_pointer + CommonFrameConstants::kContextOrFrameTypeOffset);
    3045             : 
    3046             :   Address arguments_frame;
    3047         604 :   if (parent_frame_type ==
    3048             :       StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)) {
    3049         370 :     if (length)
    3050             :       *length = Smi::cast(*reinterpret_cast<Object**>(
    3051             :                               parent_frame_pointer +
    3052             :                               ArgumentsAdaptorFrameConstants::kLengthOffset))
    3053         740 :                     ->value();
    3054             :     arguments_frame = parent_frame_pointer;
    3055             :   } else {
    3056         234 :     if (length) *length = formal_parameter_count_;
    3057             :     arguments_frame = input_frame_pointer;
    3058             :   }
    3059             : 
    3060         604 :   if (type == CreateArgumentsType::kRestParameter) {
    3061             :     // If the actual number of arguments is less than the number of formal
    3062             :     // parameters, we have zero rest parameters.
    3063         144 :     if (length) *length = std::max(0, *length - formal_parameter_count_);
    3064             :   }
    3065             : 
    3066         604 :   return arguments_frame;
    3067             : }
    3068             : 
    3069             : // Creates translated values for an arguments backing store, or the backing
    3070             : // store for rest parameters depending on the given {type}. The TranslatedValue
    3071             : // objects for the fields are not read from the TranslationIterator, but instead
    3072             : // created on-the-fly based on dynamic information in the optimized frame.
    3073         302 : void TranslatedState::CreateArgumentsElementsTranslatedValues(
    3074             :     int frame_index, Address input_frame_pointer, CreateArgumentsType type,
    3075             :     FILE* trace_file) {
    3076         302 :   TranslatedFrame& frame = frames_[frame_index];
    3077             : 
    3078             :   int length;
    3079             :   Address arguments_frame =
    3080         302 :       ComputeArgumentsPosition(input_frame_pointer, type, &length);
    3081             : 
    3082         302 :   int object_index = static_cast<int>(object_positions_.size());
    3083         302 :   int value_index = static_cast<int>(frame.values_.size());
    3084         302 :   if (trace_file != nullptr) {
    3085             :     PrintF(trace_file, "arguments elements object #%d (type = %d, length = %d)",
    3086           0 :            object_index, static_cast<uint8_t>(type), length);
    3087             :   }
    3088         604 :   object_positions_.push_back({frame_index, value_index});
    3089             :   frame.Add(TranslatedValue::NewDeferredObject(
    3090         604 :       this, length + FixedArray::kHeaderSize / kPointerSize, object_index));
    3091             : 
    3092             :   frame.Add(
    3093         604 :       TranslatedValue::NewTagged(this, isolate_->heap()->fixed_array_map()));
    3094         604 :   frame.Add(TranslatedValue::NewInt32(this, length));
    3095             : 
    3096             :   int number_of_holes = 0;
    3097         302 :   if (type == CreateArgumentsType::kMappedArguments) {
    3098             :     // If the actual number of arguments is less than the number of formal
    3099             :     // parameters, we have fewer holes to fill to not overshoot the length.
    3100          44 :     number_of_holes = Min(formal_parameter_count_, length);
    3101             :   }
    3102         374 :   for (int i = 0; i < number_of_holes; ++i) {
    3103             :     frame.Add(
    3104         144 :         TranslatedValue::NewTagged(this, isolate_->heap()->the_hole_value()));
    3105             :   }
    3106        1326 :   for (int i = length - number_of_holes - 1; i >= 0; --i) {
    3107             :     Address argument_slot = arguments_frame +
    3108             :                             CommonFrameConstants::kFixedFrameSizeAboveFp +
    3109        1024 :                             i * kPointerSize;
    3110             :     frame.Add(TranslatedValue::NewTagged(
    3111        2048 :         this, *reinterpret_cast<Object**>(argument_slot)));
    3112             :   }
    3113         302 : }
    3114             : 
    3115             : // We can't intermix stack decoding and allocations because the deoptimization
    3116             : // infrastracture is not GC safe.
    3117             : // Thus we build a temporary structure in malloced space.
    3118             : // The TranslatedValue objects created correspond to the static translation
    3119             : // instructions from the TranslationIterator, except for
    3120             : // Translation::ARGUMENTS_ELEMENTS, where the number and values of the
    3121             : // FixedArray elements depend on dynamic information from the optimized frame.
    3122             : // Returns the number of expected nested translations from the
    3123             : // TranslationIterator.
    3124    16995225 : int TranslatedState::CreateNextTranslatedValue(
    3125             :     int frame_index, TranslationIterator* iterator, FixedArray* literal_array,
    3126             :     Address fp, RegisterValues* registers, FILE* trace_file) {
    3127             :   disasm::NameConverter converter;
    3128             : 
    3129    16995225 :   TranslatedFrame& frame = frames_[frame_index];
    3130    16995225 :   int value_index = static_cast<int>(frame.values_.size());
    3131             : 
    3132             :   Translation::Opcode opcode =
    3133    16995225 :       static_cast<Translation::Opcode>(iterator->Next());
    3134    16995225 :   switch (opcode) {
    3135             :     case Translation::BEGIN:
    3136             :     case Translation::INTERPRETED_FRAME:
    3137             :     case Translation::ARGUMENTS_ADAPTOR_FRAME:
    3138             :     case Translation::CONSTRUCT_STUB_FRAME:
    3139             :     case Translation::GETTER_STUB_FRAME:
    3140             :     case Translation::SETTER_STUB_FRAME:
    3141             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
    3142             :     case Translation::BUILTIN_CONTINUATION_FRAME:
    3143             :       // Peeled off before getting here.
    3144             :       break;
    3145             : 
    3146             :     case Translation::DUPLICATED_OBJECT: {
    3147       99365 :       int object_id = iterator->Next();
    3148       99365 :       if (trace_file != nullptr) {
    3149           0 :         PrintF(trace_file, "duplicated object #%d", object_id);
    3150             :       }
    3151       99365 :       object_positions_.push_back(object_positions_[object_id]);
    3152             :       TranslatedValue translated_value =
    3153             :           TranslatedValue::NewDuplicateObject(this, object_id);
    3154             :       frame.Add(translated_value);
    3155             :       return translated_value.GetChildrenCount();
    3156             :     }
    3157             : 
    3158             :     case Translation::ARGUMENTS_ELEMENTS: {
    3159             :       CreateArgumentsType arguments_type =
    3160         302 :           static_cast<CreateArgumentsType>(iterator->Next());
    3161             :       CreateArgumentsElementsTranslatedValues(frame_index, fp, arguments_type,
    3162         302 :                                               trace_file);
    3163         302 :       return 0;
    3164             :     }
    3165             : 
    3166             :     case Translation::ARGUMENTS_LENGTH: {
    3167             :       CreateArgumentsType arguments_type =
    3168         302 :           static_cast<CreateArgumentsType>(iterator->Next());
    3169             :       int length;
    3170         302 :       ComputeArgumentsPosition(fp, arguments_type, &length);
    3171         302 :       if (trace_file != nullptr) {
    3172             :         PrintF(trace_file, "arguments length field (type = %d, length = %d)",
    3173           0 :                static_cast<uint8_t>(arguments_type), length);
    3174             :       }
    3175         604 :       frame.Add(TranslatedValue::NewInt32(this, length));
    3176             :       return 0;
    3177             :     }
    3178             : 
    3179             :     case Translation::CAPTURED_OBJECT: {
    3180      115441 :       int field_count = iterator->Next();
    3181      115441 :       int object_index = static_cast<int>(object_positions_.size());
    3182      115441 :       if (trace_file != nullptr) {
    3183             :         PrintF(trace_file, "captured object #%d (length = %d)", object_index,
    3184           0 :                field_count);
    3185             :       }
    3186      230882 :       object_positions_.push_back({frame_index, value_index});
    3187             :       TranslatedValue translated_value =
    3188             :           TranslatedValue::NewDeferredObject(this, field_count, object_index);
    3189             :       frame.Add(translated_value);
    3190             :       return translated_value.GetChildrenCount();
    3191             :     }
    3192             : 
    3193             :     case Translation::REGISTER: {
    3194     1155897 :       int input_reg = iterator->Next();
    3195     1155897 :       if (registers == nullptr) {
    3196             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3197             :         frame.Add(translated_value);
    3198             :         return translated_value.GetChildrenCount();
    3199             :       }
    3200      148904 :       intptr_t value = registers->GetRegister(input_reg);
    3201      148904 :       if (trace_file != nullptr) {
    3202             :         PrintF(trace_file, "0x%08" V8PRIxPTR " ; %s ", value,
    3203           0 :                converter.NameOfCPURegister(input_reg));
    3204           0 :         reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
    3205             :       }
    3206             :       TranslatedValue translated_value =
    3207      148904 :           TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
    3208             :       frame.Add(translated_value);
    3209      148904 :       return translated_value.GetChildrenCount();
    3210             :     }
    3211             : 
    3212             :     case Translation::INT32_REGISTER: {
    3213         602 :       int input_reg = iterator->Next();
    3214         602 :       if (registers == nullptr) {
    3215             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3216             :         frame.Add(translated_value);
    3217             :         return translated_value.GetChildrenCount();
    3218             :       }
    3219         602 :       intptr_t value = registers->GetRegister(input_reg);
    3220         602 :       if (trace_file != nullptr) {
    3221             :         PrintF(trace_file, "%" V8PRIdPTR " ; %s ", value,
    3222           0 :                converter.NameOfCPURegister(input_reg));
    3223             :       }
    3224             :       TranslatedValue translated_value =
    3225         602 :           TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
    3226             :       frame.Add(translated_value);
    3227         602 :       return translated_value.GetChildrenCount();
    3228             :     }
    3229             : 
    3230             :     case Translation::UINT32_REGISTER: {
    3231          14 :       int input_reg = iterator->Next();
    3232          14 :       if (registers == nullptr) {
    3233             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3234             :         frame.Add(translated_value);
    3235             :         return translated_value.GetChildrenCount();
    3236             :       }
    3237          14 :       intptr_t value = registers->GetRegister(input_reg);
    3238          14 :       if (trace_file != nullptr) {
    3239             :         PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint)", value,
    3240           0 :                converter.NameOfCPURegister(input_reg));
    3241             :       }
    3242             :       TranslatedValue translated_value =
    3243          14 :           TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
    3244             :       frame.Add(translated_value);
    3245          14 :       return translated_value.GetChildrenCount();
    3246             :     }
    3247             : 
    3248             :     case Translation::BOOL_REGISTER: {
    3249         101 :       int input_reg = iterator->Next();
    3250         101 :       if (registers == nullptr) {
    3251             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3252             :         frame.Add(translated_value);
    3253             :         return translated_value.GetChildrenCount();
    3254             :       }
    3255         101 :       intptr_t value = registers->GetRegister(input_reg);
    3256         101 :       if (trace_file != nullptr) {
    3257             :         PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
    3258           0 :                converter.NameOfCPURegister(input_reg));
    3259             :       }
    3260             :       TranslatedValue translated_value =
    3261         101 :           TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
    3262             :       frame.Add(translated_value);
    3263         101 :       return translated_value.GetChildrenCount();
    3264             :     }
    3265             : 
    3266             :     case Translation::FLOAT_REGISTER: {
    3267          91 :       int input_reg = iterator->Next();
    3268          91 :       if (registers == nullptr) {
    3269             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3270             :         frame.Add(translated_value);
    3271             :         return translated_value.GetChildrenCount();
    3272             :       }
    3273         182 :       Float32 value = registers->GetFloatRegister(input_reg);
    3274          91 :       if (trace_file != nullptr) {
    3275             :         PrintF(
    3276             :             trace_file, "%e ; %s (float)", value.get_scalar(),
    3277           0 :             RegisterConfiguration::Default()->GetFloatRegisterName(input_reg));
    3278             :       }
    3279             :       TranslatedValue translated_value = TranslatedValue::NewFloat(this, value);
    3280             :       frame.Add(translated_value);
    3281          91 :       return translated_value.GetChildrenCount();
    3282             :     }
    3283             : 
    3284             :     case Translation::DOUBLE_REGISTER: {
    3285         411 :       int input_reg = iterator->Next();
    3286         411 :       if (registers == nullptr) {
    3287             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3288             :         frame.Add(translated_value);
    3289             :         return translated_value.GetChildrenCount();
    3290             :       }
    3291         822 :       Float64 value = registers->GetDoubleRegister(input_reg);
    3292         411 :       if (trace_file != nullptr) {
    3293             :         PrintF(
    3294             :             trace_file, "%e ; %s (double)", value.get_scalar(),
    3295           0 :             RegisterConfiguration::Default()->GetDoubleRegisterName(input_reg));
    3296             :       }
    3297             :       TranslatedValue translated_value =
    3298             :           TranslatedValue::NewDouble(this, value);
    3299             :       frame.Add(translated_value);
    3300         411 :       return translated_value.GetChildrenCount();
    3301             :     }
    3302             : 
    3303             :     case Translation::STACK_SLOT: {
    3304             :       int slot_offset =
    3305     6906513 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3306     6906513 :       intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
    3307     6906513 :       if (trace_file != nullptr) {
    3308             :         PrintF(trace_file, "0x%08" V8PRIxPTR " ; [fp %c %d] ", value,
    3309           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3310           0 :         reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
    3311             :       }
    3312             :       TranslatedValue translated_value =
    3313     6906513 :           TranslatedValue::NewTagged(this, reinterpret_cast<Object*>(value));
    3314             :       frame.Add(translated_value);
    3315             :       return translated_value.GetChildrenCount();
    3316             :     }
    3317             : 
    3318             :     case Translation::INT32_STACK_SLOT: {
    3319             :       int slot_offset =
    3320      423746 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3321             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3322      423746 :       if (trace_file != nullptr) {
    3323             :         PrintF(trace_file, "%d ; (int) [fp %c %d] ",
    3324             :                static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
    3325           0 :                std::abs(slot_offset));
    3326             :       }
    3327      423746 :       TranslatedValue translated_value = TranslatedValue::NewInt32(this, value);
    3328             :       frame.Add(translated_value);
    3329             :       return translated_value.GetChildrenCount();
    3330             :     }
    3331             : 
    3332             :     case Translation::UINT32_STACK_SLOT: {
    3333             :       int slot_offset =
    3334           0 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3335             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3336           0 :       if (trace_file != nullptr) {
    3337             :         PrintF(trace_file, "%u ; (uint) [fp %c %d] ", value,
    3338           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3339             :       }
    3340             :       TranslatedValue translated_value =
    3341             :           TranslatedValue::NewUInt32(this, value);
    3342             :       frame.Add(translated_value);
    3343             :       return translated_value.GetChildrenCount();
    3344             :     }
    3345             : 
    3346             :     case Translation::BOOL_STACK_SLOT: {
    3347             :       int slot_offset =
    3348         483 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3349             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3350         483 :       if (trace_file != nullptr) {
    3351             :         PrintF(trace_file, "%u ; (bool) [fp %c %d] ", value,
    3352           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3353             :       }
    3354             :       TranslatedValue translated_value = TranslatedValue::NewBool(this, value);
    3355             :       frame.Add(translated_value);
    3356             :       return translated_value.GetChildrenCount();
    3357             :     }
    3358             : 
    3359             :     case Translation::FLOAT_STACK_SLOT: {
    3360             :       int slot_offset =
    3361         189 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3362         189 :       Float32 value = GetFloatSlot(fp, slot_offset);
    3363         189 :       if (trace_file != nullptr) {
    3364             :         PrintF(trace_file, "%e ; (float) [fp %c %d] ", value.get_scalar(),
    3365           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3366             :       }
    3367             :       TranslatedValue translated_value = TranslatedValue::NewFloat(this, value);
    3368             :       frame.Add(translated_value);
    3369             :       return translated_value.GetChildrenCount();
    3370             :     }
    3371             : 
    3372             :     case Translation::DOUBLE_STACK_SLOT: {
    3373             :       int slot_offset =
    3374      565729 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3375      565729 :       Float64 value = GetDoubleSlot(fp, slot_offset);
    3376      565729 :       if (trace_file != nullptr) {
    3377             :         PrintF(trace_file, "%e ; (double) [fp %c %d] ", value.get_scalar(),
    3378           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3379             :       }
    3380             :       TranslatedValue translated_value =
    3381             :           TranslatedValue::NewDouble(this, value);
    3382             :       frame.Add(translated_value);
    3383             :       return translated_value.GetChildrenCount();
    3384             :     }
    3385             : 
    3386             :     case Translation::LITERAL: {
    3387     7726039 :       int literal_index = iterator->Next();
    3388             :       Object* value = literal_array->get(literal_index);
    3389     7726039 :       if (trace_file != nullptr) {
    3390             :         PrintF(trace_file, "0x%08" V8PRIxPTR " ; (literal %d) ",
    3391           0 :                reinterpret_cast<intptr_t>(value), literal_index);
    3392           0 :         reinterpret_cast<Object*>(value)->ShortPrint(trace_file);
    3393             :       }
    3394             : 
    3395             :       TranslatedValue translated_value =
    3396             :           TranslatedValue::NewTagged(this, value);
    3397             :       frame.Add(translated_value);
    3398             :       return translated_value.GetChildrenCount();
    3399             :     }
    3400             :   }
    3401             : 
    3402           0 :   FATAL("We should never get here - unexpected deopt info.");
    3403             : }
    3404             : 
    3405     1230649 : TranslatedState::TranslatedState(const JavaScriptFrame* frame)
    3406     1230649 :     : isolate_(nullptr), stack_frame_pointer_(nullptr) {
    3407     1230649 :   int deopt_index = Safepoint::kNoDeoptimizationIndex;
    3408             :   DeoptimizationData* data =
    3409             :       static_cast<const OptimizedFrame*>(frame)->GetDeoptimizationData(
    3410     1230649 :           &deopt_index);
    3411             :   DCHECK(data != nullptr && deopt_index != Safepoint::kNoDeoptimizationIndex);
    3412             :   TranslationIterator it(data->TranslationByteArray(),
    3413     1230649 :                          data->TranslationIndex(deopt_index)->value());
    3414             :   Init(frame->fp(), &it, data->LiteralArray(), nullptr /* registers */,
    3415             :        nullptr /* trace file */,
    3416     2461298 :        frame->function()->shared()->internal_formal_parameter_count());
    3417     1230649 : }
    3418             : 
    3419           0 : TranslatedState::TranslatedState()
    3420      146823 :     : isolate_(nullptr), stack_frame_pointer_(nullptr) {}
    3421             : 
    3422     1377472 : void TranslatedState::Init(Address input_frame_pointer,
    3423             :                            TranslationIterator* iterator,
    3424             :                            FixedArray* literal_array, RegisterValues* registers,
    3425             :                            FILE* trace_file, int formal_parameter_count) {
    3426             :   DCHECK(frames_.empty());
    3427             : 
    3428     1377472 :   formal_parameter_count_ = formal_parameter_count;
    3429             : 
    3430     1377472 :   isolate_ = literal_array->GetIsolate();
    3431             :   // Read out the 'header' translation.
    3432             :   Translation::Opcode opcode =
    3433     1377472 :       static_cast<Translation::Opcode>(iterator->Next());
    3434     1377472 :   CHECK(opcode == Translation::BEGIN);
    3435             : 
    3436     1377472 :   int count = iterator->Next();
    3437     1377472 :   iterator->Next();  // Drop JS frames count.
    3438             : 
    3439     1377472 :   frames_.reserve(count);
    3440             : 
    3441     1377472 :   std::stack<int> nested_counts;
    3442             : 
    3443             :   // Read the frames
    3444     3231108 :   for (int frame_index = 0; frame_index < count; frame_index++) {
    3445             :     // Read the frame descriptor.
    3446             :     frames_.push_back(CreateNextTranslatedFrame(
    3447     3707272 :         iterator, literal_array, input_frame_pointer, trace_file));
    3448     1853636 :     TranslatedFrame& frame = frames_.back();
    3449             : 
    3450             :     // Read the values.
    3451     1853636 :     int values_to_process = frame.GetValueCount();
    3452    22556133 :     while (values_to_process > 0 || !nested_counts.empty()) {
    3453    16995225 :       if (trace_file != nullptr) {
    3454           0 :         if (nested_counts.empty()) {
    3455             :           // For top level values, print the value number.
    3456             :           PrintF(trace_file, "    %3i: ",
    3457           0 :                  frame.GetValueCount() - values_to_process);
    3458             :         } else {
    3459             :           // Take care of indenting for nested values.
    3460           0 :           PrintF(trace_file, "         ");
    3461           0 :           for (size_t j = 0; j < nested_counts.size(); j++) {
    3462           0 :             PrintF(trace_file, "  ");
    3463             :           }
    3464             :         }
    3465             :       }
    3466             : 
    3467             :       int nested_count =
    3468             :           CreateNextTranslatedValue(frame_index, iterator, literal_array,
    3469    16995225 :                                     input_frame_pointer, registers, trace_file);
    3470             : 
    3471    16995225 :       if (trace_file != nullptr) {
    3472           0 :         PrintF(trace_file, "\n");
    3473             :       }
    3474             : 
    3475             :       // Update the value count and resolve the nesting.
    3476    16995225 :       values_to_process--;
    3477    16995225 :       if (nested_count > 0) {
    3478             :         nested_counts.push(values_to_process);
    3479      115441 :         values_to_process = nested_count;
    3480             :       } else {
    3481    18964302 :         while (values_to_process == 0 && !nested_counts.empty()) {
    3482      115441 :           values_to_process = nested_counts.top();
    3483             :           nested_counts.pop();
    3484             :         }
    3485             :       }
    3486             :     }
    3487             :   }
    3488             : 
    3489     1377472 :   CHECK(!iterator->HasNext() ||
    3490             :         static_cast<Translation::Opcode>(iterator->Next()) ==
    3491             :             Translation::BEGIN);
    3492     1377472 : }
    3493             : 
    3494     1377472 : void TranslatedState::Prepare(Address stack_frame_pointer) {
    3495     4608580 :   for (auto& frame : frames_) frame.Handlify();
    3496             : 
    3497     1377472 :   stack_frame_pointer_ = stack_frame_pointer;
    3498             : 
    3499     1377472 :   UpdateFromPreviouslyMaterializedObjects();
    3500     1377472 : }
    3501             : 
    3502             : class TranslatedState::CapturedObjectMaterializer {
    3503             :  public:
    3504             :   CapturedObjectMaterializer(TranslatedState* state, int frame_index,
    3505             :                              int field_count)
    3506       35816 :       : state_(state), frame_index_(frame_index), field_count_(field_count) {}
    3507             : 
    3508      124793 :   Handle<Object> FieldAt(int* value_index) {
    3509      124793 :     CHECK_GT(field_count_, 0);
    3510      124793 :     --field_count_;
    3511      124793 :     return state_->MaterializeAt(frame_index_, value_index);
    3512             :   }
    3513             : 
    3514       35816 :   ~CapturedObjectMaterializer() { CHECK_EQ(0, field_count_); }
    3515             : 
    3516             :  private:
    3517             :   TranslatedState* state_;
    3518             :   int frame_index_;
    3519             :   int field_count_;
    3520             : };
    3521             : 
    3522       35816 : Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
    3523             :     TranslatedValue* slot, int frame_index, int* value_index) {
    3524             :   int length = slot->GetChildrenCount();
    3525             : 
    3526             :   CapturedObjectMaterializer materializer(this, frame_index, length);
    3527             : 
    3528             :   Handle<Object> result;
    3529       35816 :   if (slot->value_.ToHandle(&result)) {
    3530             :     // This has been previously materialized, return the previous value.
    3531             :     // We still need to skip all the nested objects.
    3532        3448 :     for (int i = 0; i < length; i++) {
    3533        3448 :       materializer.FieldAt(value_index);
    3534             :     }
    3535             : 
    3536         721 :     return result;
    3537             :   }
    3538             : 
    3539       35095 :   Handle<Object> map_object = materializer.FieldAt(value_index);
    3540       35095 :   Handle<Map> map = Map::GeneralizeAllFields(Handle<Map>::cast(map_object));
    3541       35095 :   switch (map->instance_type()) {
    3542             :     case MUTABLE_HEAP_NUMBER_TYPE:
    3543             :     case HEAP_NUMBER_TYPE: {
    3544             :       // Reuse the HeapNumber value directly as it is already properly
    3545             :       // tagged and skip materializing the HeapNumber explicitly.
    3546           0 :       Handle<Object> object = materializer.FieldAt(value_index);
    3547           0 :       slot->value_ = object;
    3548             :       // On 32-bit architectures, there is an extra slot there because
    3549             :       // the escape analysis calculates the number of slots as
    3550             :       // object-size/pointer-size. To account for this, we read out
    3551             :       // any extra slots.
    3552           0 :       for (int i = 0; i < length - 2; i++) {
    3553           0 :         materializer.FieldAt(value_index);
    3554             :       }
    3555           0 :       return object;
    3556             :     }
    3557             :     case JS_OBJECT_TYPE:
    3558             :     case JS_ERROR_TYPE:
    3559             :     case JS_ARGUMENTS_TYPE: {
    3560             :       Handle<JSObject> object =
    3561       33779 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED);
    3562       31546 :       slot->value_ = object;
    3563       31546 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3564       31546 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3565       31546 :       object->set_raw_properties_or_hash(*properties);
    3566       31546 :       object->set_elements(FixedArrayBase::cast(*elements));
    3567             :       int in_object_properties = map->GetInObjectProperties();
    3568       33466 :       for (int i = 0; i < in_object_properties; ++i) {
    3569        1920 :         Handle<Object> value = materializer.FieldAt(value_index);
    3570        1920 :         FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
    3571        1920 :         object->FastPropertyAtPut(index, *value);
    3572             :       }
    3573       31546 :       return object;
    3574             :     }
    3575             :     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    3576             :     case JS_SET_VALUE_ITERATOR_TYPE: {
    3577             :       Handle<JSSetIterator> object = Handle<JSSetIterator>::cast(
    3578           9 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3579           9 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3580           9 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3581           9 :       Handle<Object> table = materializer.FieldAt(value_index);
    3582           9 :       Handle<Object> index = materializer.FieldAt(value_index);
    3583           9 :       object->set_raw_properties_or_hash(*properties);
    3584           9 :       object->set_elements(FixedArrayBase::cast(*elements));
    3585           9 :       object->set_table(*table);
    3586           9 :       object->set_index(*index);
    3587           9 :       return object;
    3588             :     }
    3589             :     case JS_MAP_KEY_ITERATOR_TYPE:
    3590             :     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    3591             :     case JS_MAP_VALUE_ITERATOR_TYPE: {
    3592             :       Handle<JSMapIterator> object = Handle<JSMapIterator>::cast(
    3593           0 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3594           0 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3595           0 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3596           0 :       Handle<Object> table = materializer.FieldAt(value_index);
    3597           0 :       Handle<Object> index = materializer.FieldAt(value_index);
    3598           0 :       object->set_raw_properties_or_hash(*properties);
    3599           0 :       object->set_elements(FixedArrayBase::cast(*elements));
    3600           0 :       object->set_table(*table);
    3601           0 :       object->set_index(*index);
    3602           0 :       return object;
    3603             :     }
    3604             : #define ARRAY_ITERATOR_CASE(type) case type:
    3605             :       ARRAY_ITERATOR_TYPE_LIST(ARRAY_ITERATOR_CASE)
    3606             : #undef ARRAY_ITERATOR_CASE
    3607             :       {
    3608             :         Handle<JSArrayIterator> object = Handle<JSArrayIterator>::cast(
    3609         101 :             isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3610         101 :         slot->value_ = object;
    3611             :         // Initialize the index to zero to make the heap verifier happy.
    3612         101 :         object->set_index(Smi::FromInt(0));
    3613         101 :         Handle<Object> properties = materializer.FieldAt(value_index);
    3614         101 :         Handle<Object> elements = materializer.FieldAt(value_index);
    3615         101 :         Handle<Object> iterated_object = materializer.FieldAt(value_index);
    3616         101 :         Handle<Object> next_index = materializer.FieldAt(value_index);
    3617         101 :         Handle<Object> iterated_object_map = materializer.FieldAt(value_index);
    3618         101 :         object->set_raw_properties_or_hash(*properties);
    3619         101 :         object->set_elements(FixedArrayBase::cast(*elements));
    3620         101 :         object->set_object(*iterated_object);
    3621         101 :         object->set_index(*next_index);
    3622         101 :         object->set_object_map(*iterated_object_map);
    3623         101 :         return object;
    3624             :       }
    3625             :     case JS_STRING_ITERATOR_TYPE: {
    3626             :       Handle<JSStringIterator> object = Handle<JSStringIterator>::cast(
    3627           8 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3628           8 :       slot->value_ = object;
    3629             :       // Initialize the index to zero to make the heap verifier happy.
    3630             :       object->set_index(0);
    3631           8 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3632           8 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3633           8 :       Handle<Object> iterated_string = materializer.FieldAt(value_index);
    3634           8 :       Handle<Object> next_index = materializer.FieldAt(value_index);
    3635           8 :       object->set_raw_properties_or_hash(*properties);
    3636           8 :       object->set_elements(FixedArrayBase::cast(*elements));
    3637           8 :       CHECK(iterated_string->IsString());
    3638           8 :       object->set_string(String::cast(*iterated_string));
    3639           8 :       CHECK(next_index->IsSmi());
    3640             :       object->set_index(Smi::ToInt(*next_index));
    3641           8 :       return object;
    3642             :     }
    3643             :     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE: {
    3644             :       Handle<JSAsyncFromSyncIterator> object =
    3645             :           Handle<JSAsyncFromSyncIterator>::cast(
    3646           0 :               isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3647           0 :       slot->value_ = object;
    3648           0 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3649           0 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3650           0 :       Handle<Object> sync_iterator = materializer.FieldAt(value_index);
    3651           0 :       object->set_raw_properties_or_hash(*properties);
    3652           0 :       object->set_elements(FixedArrayBase::cast(*elements));
    3653           0 :       object->set_sync_iterator(JSReceiver::cast(*sync_iterator));
    3654           0 :       return object;
    3655             :     }
    3656             :     case JS_ARRAY_TYPE: {
    3657             :       Handle<JSArray> object = Handle<JSArray>::cast(
    3658         513 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3659         513 :       slot->value_ = object;
    3660         513 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3661         513 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3662         513 :       Handle<Object> array_length = materializer.FieldAt(value_index);
    3663         513 :       object->set_raw_properties_or_hash(*properties);
    3664         513 :       object->set_elements(FixedArrayBase::cast(*elements));
    3665         513 :       object->set_length(*array_length);
    3666             :       int in_object_properties = map->GetInObjectProperties();
    3667         521 :       for (int i = 0; i < in_object_properties; ++i) {
    3668           8 :         Handle<Object> value = materializer.FieldAt(value_index);
    3669           8 :         FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
    3670           8 :         object->FastPropertyAtPut(index, *value);
    3671             :       }
    3672         513 :       return object;
    3673             :     }
    3674             :     case JS_BOUND_FUNCTION_TYPE: {
    3675             :       Handle<JSBoundFunction> object = Handle<JSBoundFunction>::cast(
    3676          36 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3677          36 :       slot->value_ = object;
    3678          36 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3679          36 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3680          36 :       Handle<Object> bound_target_function = materializer.FieldAt(value_index);
    3681          36 :       Handle<Object> bound_this = materializer.FieldAt(value_index);
    3682          36 :       Handle<Object> bound_arguments = materializer.FieldAt(value_index);
    3683          36 :       object->set_raw_properties_or_hash(*properties);
    3684          36 :       object->set_elements(FixedArrayBase::cast(*elements));
    3685             :       object->set_bound_target_function(
    3686          36 :           JSReceiver::cast(*bound_target_function));
    3687          36 :       object->set_bound_this(*bound_this);
    3688          36 :       object->set_bound_arguments(FixedArray::cast(*bound_arguments));
    3689          36 :       return object;
    3690             :     }
    3691             :     case JS_FUNCTION_TYPE: {
    3692             :       Handle<JSFunction> object = isolate_->factory()->NewFunction(
    3693        2233 :           map, handle(isolate_->object_function()->shared()),
    3694        6699 :           handle(isolate_->context()), NOT_TENURED);
    3695        2233 :       slot->value_ = object;
    3696             :       // We temporarily allocated a JSFunction for the {Object} function
    3697             :       // within the current context, to break cycles in the object graph.
    3698             :       // The correct function and context will be set below once available.
    3699        2233 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3700        2233 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3701        2233 :       Handle<Object> shared = materializer.FieldAt(value_index);
    3702        2233 :       Handle<Object> context = materializer.FieldAt(value_index);
    3703        2233 :       Handle<Object> vector_cell = materializer.FieldAt(value_index);
    3704        2233 :       Handle<Object> code = materializer.FieldAt(value_index);
    3705             :       bool has_prototype_slot = map->has_prototype_slot();
    3706             :       Handle<Object> prototype;
    3707        2233 :       if (has_prototype_slot) {
    3708        2216 :         prototype = materializer.FieldAt(value_index);
    3709             :       }
    3710        2233 :       object->set_map(*map);
    3711        2233 :       object->set_raw_properties_or_hash(*properties);
    3712        2233 :       object->set_elements(FixedArrayBase::cast(*elements));
    3713        2233 :       object->set_shared(SharedFunctionInfo::cast(*shared));
    3714        2233 :       object->set_context(Context::cast(*context));
    3715        2233 :       object->set_feedback_vector_cell(Cell::cast(*vector_cell));
    3716        2233 :       object->set_code(Code::cast(*code));
    3717        2233 :       if (has_prototype_slot) {
    3718        2216 :         object->set_prototype_or_initial_map(*prototype);
    3719             :       }
    3720             :       int in_object_properties = map->GetInObjectProperties();
    3721        2242 :       for (int i = 0; i < in_object_properties; ++i) {
    3722           9 :         Handle<Object> value = materializer.FieldAt(value_index);
    3723           9 :         FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
    3724           9 :         object->FastPropertyAtPut(index, *value);
    3725             :       }
    3726        2233 :       return object;
    3727             :     }
    3728             :     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
    3729             :     case JS_GENERATOR_OBJECT_TYPE: {
    3730             :       Handle<JSGeneratorObject> object = Handle<JSGeneratorObject>::cast(
    3731          23 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3732          23 :       slot->value_ = object;
    3733          23 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3734          23 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3735          23 :       Handle<Object> function = materializer.FieldAt(value_index);
    3736          23 :       Handle<Object> context = materializer.FieldAt(value_index);
    3737          23 :       Handle<Object> receiver = materializer.FieldAt(value_index);
    3738          23 :       Handle<Object> input_or_debug_pos = materializer.FieldAt(value_index);
    3739          23 :       Handle<Object> resume_mode = materializer.FieldAt(value_index);
    3740          23 :       Handle<Object> continuation_offset = materializer.FieldAt(value_index);
    3741          23 :       Handle<Object> register_file = materializer.FieldAt(value_index);
    3742          23 :       object->set_raw_properties_or_hash(*properties);
    3743          23 :       object->set_elements(FixedArrayBase::cast(*elements));
    3744          23 :       object->set_function(JSFunction::cast(*function));
    3745          23 :       object->set_context(Context::cast(*context));
    3746          23 :       object->set_receiver(*receiver);
    3747          23 :       object->set_input_or_debug_pos(*input_or_debug_pos);
    3748             :       object->set_resume_mode(Smi::ToInt(*resume_mode));
    3749             :       object->set_continuation(Smi::ToInt(*continuation_offset));
    3750          23 :       object->set_register_file(FixedArray::cast(*register_file));
    3751             : 
    3752          23 :       if (object->IsJSAsyncGeneratorObject()) {
    3753             :         auto generator = Handle<JSAsyncGeneratorObject>::cast(object);
    3754           7 :         Handle<Object> queue = materializer.FieldAt(value_index);
    3755           7 :         Handle<Object> awaited_promise = materializer.FieldAt(value_index);
    3756           7 :         generator->set_queue(HeapObject::cast(*queue));
    3757           7 :         generator->set_awaited_promise(HeapObject::cast(*awaited_promise));
    3758             :       }
    3759             : 
    3760             :       int in_object_properties = map->GetInObjectProperties();
    3761          31 :       for (int i = 0; i < in_object_properties; ++i) {
    3762           8 :         Handle<Object> value = materializer.FieldAt(value_index);
    3763           8 :         FieldIndex index = FieldIndex::ForPropertyIndex(object->map(), i);
    3764           8 :         object->FastPropertyAtPut(index, *value);
    3765             :       }
    3766          23 :       return object;
    3767             :     }
    3768             :     case CONS_STRING_TYPE: {
    3769             :       Handle<ConsString> object = Handle<ConsString>::cast(
    3770             :           isolate_->factory()
    3771             :               ->NewConsString(isolate_->factory()->undefined_string(),
    3772          19 :                               isolate_->factory()->undefined_string())
    3773          38 :               .ToHandleChecked());
    3774          19 :       slot->value_ = object;
    3775          19 :       Handle<Object> hash = materializer.FieldAt(value_index);
    3776          19 :       Handle<Object> string_length = materializer.FieldAt(value_index);
    3777          19 :       Handle<Object> first = materializer.FieldAt(value_index);
    3778          19 :       Handle<Object> second = materializer.FieldAt(value_index);
    3779          19 :       object->set_map(*map);
    3780             :       object->set_length(Smi::ToInt(*string_length));
    3781          19 :       object->set_first(String::cast(*first));
    3782          19 :       object->set_second(String::cast(*second));
    3783          19 :       CHECK(hash->IsNumber());  // The {Name::kEmptyHashField} value.
    3784          19 :       return object;
    3785             :     }
    3786             :     case CONTEXT_EXTENSION_TYPE: {
    3787             :       Handle<ContextExtension> object =
    3788             :           isolate_->factory()->NewContextExtension(
    3789             :               isolate_->factory()->NewScopeInfo(1),
    3790         124 :               isolate_->factory()->undefined_value());
    3791          62 :       slot->value_ = object;
    3792          62 :       Handle<Object> scope_info = materializer.FieldAt(value_index);
    3793          62 :       Handle<Object> extension = materializer.FieldAt(value_index);
    3794          62 :       object->set_scope_info(ScopeInfo::cast(*scope_info));
    3795          62 :       object->set_extension(*extension);
    3796          62 :       return object;
    3797             :     }
    3798             :     case HASH_TABLE_TYPE:
    3799             :     case FIXED_ARRAY_TYPE: {
    3800         487 :       Handle<Object> lengthObject = materializer.FieldAt(value_index);
    3801         487 :       int32_t array_length = 0;
    3802         487 :       CHECK(lengthObject->ToInt32(&array_length));
    3803             :       Handle<FixedArray> object =
    3804         487 :           isolate_->factory()->NewFixedArray(array_length);
    3805             :       // We need to set the map, because the fixed array we are
    3806             :       // materializing could be a context or an arguments object,
    3807             :       // in which case we must retain that information.
    3808         487 :       object->set_map(*map);
    3809         487 :       slot->value_ = object;
    3810        2645 :       for (int i = 0; i < array_length; ++i) {
    3811        2158 :         Handle<Object> value = materializer.FieldAt(value_index);
    3812        2158 :         object->set(i, *value);
    3813             :       }
    3814         487 :       return object;
    3815             :     }
    3816             :     case PROPERTY_ARRAY_TYPE: {
    3817             :       DCHECK_EQ(*map, isolate_->heap()->property_array_map());
    3818          17 :       Handle<Object> lengthObject = materializer.FieldAt(value_index);
    3819          17 :       int32_t array_length = 0;
    3820          17 :       CHECK(lengthObject->ToInt32(&array_length));
    3821             :       Handle<PropertyArray> object =
    3822          17 :           isolate_->factory()->NewPropertyArray(array_length);
    3823          17 :       slot->value_ = object;
    3824          68 :       for (int i = 0; i < array_length; ++i) {
    3825          51 :         Handle<Object> value = materializer.FieldAt(value_index);
    3826          51 :         object->set(i, *value);
    3827             :       }
    3828          17 :       return object;
    3829             :     }
    3830             :     case FIXED_DOUBLE_ARRAY_TYPE: {
    3831             :       DCHECK_EQ(*map, isolate_->heap()->fixed_double_array_map());
    3832          33 :       Handle<Object> lengthObject = materializer.FieldAt(value_index);
    3833          33 :       int32_t array_length = 0;
    3834          33 :       CHECK(lengthObject->ToInt32(&array_length));
    3835             :       Handle<FixedArrayBase> object =
    3836          33 :           isolate_->factory()->NewFixedDoubleArray(array_length);
    3837          33 :       slot->value_ = object;
    3838          33 :       if (array_length > 0) {
    3839             :         Handle<FixedDoubleArray> double_array =
    3840             :             Handle<FixedDoubleArray>::cast(object);
    3841          92 :         for (int i = 0; i < array_length; ++i) {
    3842          92 :           Handle<Object> value = materializer.FieldAt(value_index);
    3843         184 :           if (value.is_identical_to(isolate_->factory()->the_hole_value())) {
    3844             :             double_array->set_the_hole(isolate_, i);
    3845             :           } else {
    3846          83 :             CHECK(value->IsNumber());
    3847             :             double_array->set(i, value->Number());
    3848             :           }
    3849             :         }
    3850             :       }
    3851          33 :       return object;
    3852             :     }
    3853             :     case JS_REGEXP_TYPE: {
    3854             :       Handle<JSRegExp> object = Handle<JSRegExp>::cast(
    3855           8 :           isolate_->factory()->NewJSObjectFromMap(map, NOT_TENURED));
    3856           8 :       slot->value_ = object;
    3857           8 :       Handle<Object> properties = materializer.FieldAt(value_index);
    3858           8 :       Handle<Object> elements = materializer.FieldAt(value_index);
    3859           8 :       Handle<Object> data = materializer.FieldAt(value_index);
    3860           8 :       Handle<Object> source = materializer.FieldAt(value_index);
    3861           8 :       Handle<Object> flags = materializer.FieldAt(value_index);
    3862           8 :       Handle<Object> last_index = materializer.FieldAt(value_index);
    3863           8 :       object->set_raw_properties_or_hash(*properties);
    3864           8 :       object->set_elements(FixedArrayBase::cast(*elements));
    3865           8 :       object->set_data(*data);
    3866           8 :       object->set_source(*source);
    3867           8 :       object->set_flags(*flags);
    3868           8 :       object->set_last_index(*last_index);
    3869           8 :       return object;
    3870             :     }
    3871             :     case STRING_TYPE:
    3872             :     case ONE_BYTE_STRING_TYPE:
    3873             :     case CONS_ONE_BYTE_STRING_TYPE:
    3874             :     case SLICED_STRING_TYPE:
    3875             :     case SLICED_ONE_BYTE_STRING_TYPE:
    3876             :     case EXTERNAL_STRING_TYPE:
    3877             :     case EXTERNAL_ONE_BYTE_STRING_TYPE:
    3878             :     case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
    3879             :     case SHORT_EXTERNAL_STRING_TYPE:
    3880             :     case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE:
    3881             :     case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
    3882             :     case THIN_STRING_TYPE:
    3883             :     case THIN_ONE_BYTE_STRING_TYPE:
    3884             :     case INTERNALIZED_STRING_TYPE:
    3885             :     case ONE_BYTE_INTERNALIZED_STRING_TYPE:
    3886             :     case EXTERNAL_INTERNALIZED_STRING_TYPE:
    3887             :     case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
    3888             :     case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
    3889             :     case SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE:
    3890             :     case SHORT_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
    3891             :     case SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
    3892             :     case SYMBOL_TYPE:
    3893             :     case ODDBALL_TYPE:
    3894             :     case JS_GLOBAL_OBJECT_TYPE:
    3895             :     case JS_GLOBAL_PROXY_TYPE:
    3896             :     case JS_API_OBJECT_TYPE:
    3897             :     case JS_SPECIAL_API_OBJECT_TYPE:
    3898             :     case JS_VALUE_TYPE:
    3899             :     case JS_MESSAGE_OBJECT_TYPE:
    3900             :     case JS_DATE_TYPE:
    3901             :     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
    3902             :     case JS_MODULE_NAMESPACE_TYPE:
    3903             :     case JS_ARRAY_BUFFER_TYPE:
    3904             :     case JS_TYPED_ARRAY_TYPE:
    3905             :     case JS_DATA_VIEW_TYPE:
    3906             :     case JS_SET_TYPE:
    3907             :     case JS_MAP_TYPE:
    3908             :     case JS_WEAK_MAP_TYPE:
    3909             :     case JS_WEAK_SET_TYPE:
    3910             :     case PROMISE_CAPABILITY_TYPE:
    3911             :     case JS_PROMISE_TYPE:
    3912             :     case JS_PROXY_TYPE:
    3913             :     case MAP_TYPE:
    3914             :     case ALLOCATION_SITE_TYPE:
    3915             :     case ACCESSOR_INFO_TYPE:
    3916             :     case SHARED_FUNCTION_INFO_TYPE:
    3917             :     case FUNCTION_TEMPLATE_INFO_TYPE:
    3918             :     case ACCESSOR_PAIR_TYPE:
    3919             :     case BYTE_ARRAY_TYPE:
    3920             :     case BYTECODE_ARRAY_TYPE:
    3921             :     case TRANSITION_ARRAY_TYPE:
    3922             :     case FEEDBACK_VECTOR_TYPE:
    3923             :     case FOREIGN_TYPE:
    3924             :     case SCRIPT_TYPE:
    3925             :     case CODE_TYPE:
    3926             :     case PROPERTY_CELL_TYPE:
    3927             :     case BIGINT_TYPE:
    3928             :     case MODULE_TYPE:
    3929             :     case MODULE_INFO_ENTRY_TYPE:
    3930             :     case FREE_SPACE_TYPE:
    3931             : #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
    3932             :   case FIXED_##TYPE##_ARRAY_TYPE:
    3933             :       TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE)
    3934             : #undef FIXED_TYPED_ARRAY_CASE
    3935             :     case FILLER_TYPE:
    3936             :     case ACCESS_CHECK_INFO_TYPE:
    3937             :     case INTERCEPTOR_INFO_TYPE:
    3938             :     case OBJECT_TEMPLATE_INFO_TYPE:
    3939             :     case ALLOCATION_MEMENTO_TYPE:
    3940             :     case ALIASED_ARGUMENTS_ENTRY_TYPE:
    3941             :     case PROMISE_RESOLVE_THENABLE_JOB_INFO_TYPE:
    3942             :     case PROMISE_REACTION_JOB_INFO_TYPE:
    3943             :     case DEBUG_INFO_TYPE:
    3944             :     case STACK_FRAME_INFO_TYPE:
    3945             :     case CELL_TYPE:
    3946             :     case WEAK_CELL_TYPE:
    3947             :     case SMALL_ORDERED_HASH_MAP_TYPE:
    3948             :     case SMALL_ORDERED_HASH_SET_TYPE:
    3949             :     case PROTOTYPE_INFO_TYPE:
    3950             :     case TUPLE2_TYPE:
    3951             :     case TUPLE3_TYPE:
    3952             :     case ASYNC_GENERATOR_REQUEST_TYPE:
    3953             :     case WASM_MODULE_TYPE:
    3954             :     case WASM_INSTANCE_TYPE:
    3955             :     case WASM_MEMORY_TYPE:
    3956             :     case WASM_TABLE_TYPE:
    3957           0 :       OFStream os(stderr);
    3958           0 :       os << "[couldn't handle instance type " << map->instance_type() << "]"
    3959             :          << std::endl;
    3960           0 :       UNREACHABLE();
    3961             :       break;
    3962             :   }
    3963           0 :   UNREACHABLE();
    3964             : }
    3965             : 
    3966      159803 : Handle<Object> TranslatedState::MaterializeAt(int frame_index,
    3967           0 :                                               int* value_index) {
    3968      319606 :   CHECK_LT(static_cast<size_t>(frame_index), frames().size());
    3969          54 :   TranslatedFrame* frame = &(frames_[frame_index]);
    3970      159803 :   CHECK_LT(static_cast<size_t>(*value_index), frame->values_.size());
    3971             : 
    3972      159803 :   TranslatedValue* slot = &(frame->values_[*value_index]);
    3973      159803 :   (*value_index)++;
    3974             : 
    3975      159803 :   switch (slot->kind()) {
    3976             :     case TranslatedValue::kTagged:
    3977             :     case TranslatedValue::kInt32:
    3978             :     case TranslatedValue::kUInt32:
    3979             :     case TranslatedValue::kBoolBit:
    3980             :     case TranslatedValue::kFloat:
    3981             :     case TranslatedValue::kDouble: {
    3982      123933 :       slot->MaterializeSimple();
    3983      123933 :       Handle<Object> value = slot->GetValue();
    3984      123933 :       if (value->IsMutableHeapNumber()) {
    3985           0 :         HeapNumber::cast(*value)->set_map(isolate()->heap()->heap_number_map());
    3986             :       }
    3987      123933 :       return value;
    3988             :     }
    3989             : 
    3990             :     case TranslatedValue::kCapturedObject: {
    3991             :       // The map must be a tagged object.
    3992       35816 :       CHECK_EQ(frame->values_[*value_index].kind(), TranslatedValue::kTagged);
    3993      107448 :       CHECK(frame->values_[*value_index].GetValue()->IsMap());
    3994       35816 :       return MaterializeCapturedObjectAt(slot, frame_index, value_index);
    3995             :     }
    3996             :     case TranslatedValue::kDuplicatedObject: {
    3997             :       int object_index = slot->object_index();
    3998          54 :       TranslatedState::ObjectPosition pos = object_positions_[object_index];
    3999             : 
    4000             :       // Make sure the duplicate is referring to a previous object.
    4001          54 :       CHECK(pos.frame_index_ < frame_index ||
    4002             :             (pos.frame_index_ == frame_index &&
    4003             :              pos.value_index_ < *value_index - 1));
    4004             : 
    4005             :       Handle<Object> object =
    4006         108 :           frames_[pos.frame_index_].values_[pos.value_index_].GetValue();
    4007             : 
    4008             :       // The object should have a (non-sentinel) value.
    4009         108 :       CHECK(!object.is_null() &&
    4010             :             !object.is_identical_to(isolate_->factory()->arguments_marker()));
    4011             : 
    4012          54 :       slot->value_ = object;
    4013          54 :       return object;
    4014             :     }
    4015             : 
    4016             :     case TranslatedValue::kInvalid:
    4017           0 :       UNREACHABLE();
    4018             :       break;
    4019             :   }
    4020             : 
    4021           0 :   FATAL("We should never get here - unexpected deopt slot kind.");
    4022             :   return Handle<Object>::null();
    4023             : }
    4024             : 
    4025       35010 : Handle<Object> TranslatedState::MaterializeObjectAt(int object_index) {
    4026       35010 :   CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
    4027       35010 :   TranslatedState::ObjectPosition pos = object_positions_[object_index];
    4028       35010 :   return MaterializeAt(pos.frame_index_, &(pos.value_index_));
    4029             : }
    4030             : 
    4031          36 : TranslatedFrame* TranslatedState::GetFrameFromJSFrameIndex(int jsframe_index) {
    4032         144 :   for (size_t i = 0; i < frames_.size(); i++) {
    4033         144 :     if (frames_[i].kind() == TranslatedFrame::kInterpretedFunction ||
    4034             :         frames_[i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation) {
    4035          72 :       if (jsframe_index > 0) {
    4036          36 :         jsframe_index--;
    4037             :       } else {
    4038             :         return &(frames_[i]);
    4039             :       }
    4040             :     }
    4041             :   }
    4042             :   return nullptr;
    4043             : }
    4044             : 
    4045        2517 : TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
    4046             :     int jsframe_index, int* args_count) {
    4047       27654 :   for (size_t i = 0; i < frames_.size(); i++) {
    4048       30171 :     if (frames_[i].kind() == TranslatedFrame::kInterpretedFunction ||
    4049             :         frames_[i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation) {
    4050        8446 :       if (jsframe_index > 0) {
    4051        5929 :         jsframe_index--;
    4052             :       } else {
    4053             :         // We have the JS function frame, now check if it has arguments
    4054             :         // adaptor.
    4055        5034 :         if (i > 0 &&
    4056        5034 :             frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
    4057        2190 :           *args_count = frames_[i - 1].height();
    4058        1095 :           return &(frames_[i - 1]);
    4059             :         }
    4060             :         *args_count =
    4061        1422 :             frames_[i].shared_info()->internal_formal_parameter_count() + 1;
    4062        1422 :         return &(frames_[i]);
    4063             :       }
    4064             :     }
    4065             :   }
    4066             :   return nullptr;
    4067             : }
    4068             : 
    4069         167 : void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
    4070             :   MaterializedObjectStore* materialized_store =
    4071         167 :       isolate_->materialized_object_store();
    4072             :   Handle<FixedArray> previously_materialized_objects =
    4073         167 :       materialized_store->Get(stack_frame_pointer_);
    4074             : 
    4075         167 :   Handle<Object> marker = isolate_->factory()->arguments_marker();
    4076             : 
    4077         167 :   int length = static_cast<int>(object_positions_.size());
    4078             :   bool new_store = false;
    4079         167 :   if (previously_materialized_objects.is_null()) {
    4080             :     previously_materialized_objects =
    4081         139 :         isolate_->factory()->NewFixedArray(length);
    4082         527 :     for (int i = 0; i < length; i++) {
    4083         388 :       previously_materialized_objects->set(i, *marker);
    4084             :     }
    4085             :     new_store = true;
    4086             :   }
    4087             : 
    4088         167 :   CHECK_EQ(length, previously_materialized_objects->length());
    4089             : 
    4090             :   bool value_changed = false;
    4091         458 :   for (int i = 0; i < length; i++) {
    4092         458 :     TranslatedState::ObjectPosition pos = object_positions_[i];
    4093             :     TranslatedValue* value_info =
    4094         597 :         &(frames_[pos.frame_index_].values_[pos.value_index_]);
    4095             : 
    4096         458 :     CHECK(value_info->IsMaterializedObject());
    4097             : 
    4098         458 :     Handle<Object> value(value_info->GetRawValue(), isolate_);
    4099             : 
    4100         458 :     if (!value.is_identical_to(marker)) {
    4101         423 :       if (previously_materialized_objects->get(i) == *marker) {
    4102         353 :         previously_materialized_objects->set(i, *value);
    4103             :         value_changed = true;
    4104             :       } else {
    4105          70 :         CHECK(previously_materialized_objects->get(i) == *value);
    4106             :       }
    4107             :     }
    4108             :   }
    4109         167 :   if (new_store && value_changed) {
    4110             :     materialized_store->Set(stack_frame_pointer_,
    4111         139 :                             previously_materialized_objects);
    4112         139 :     CHECK_EQ(frames_[0].kind(), TranslatedFrame::kInterpretedFunction);
    4113         139 :     CHECK_EQ(frame->function(), frames_[0].front().GetRawValue());
    4114         139 :     Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode());
    4115             :   }
    4116         167 : }
    4117             : 
    4118     1377472 : void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
    4119             :   MaterializedObjectStore* materialized_store =
    4120     1377472 :       isolate_->materialized_object_store();
    4121             :   Handle<FixedArray> previously_materialized_objects =
    4122     1377472 :       materialized_store->Get(stack_frame_pointer_);
    4123             : 
    4124             :   // If we have no previously materialized objects, there is nothing to do.
    4125     2754944 :   if (previously_materialized_objects.is_null()) return;
    4126             : 
    4127         195 :   Handle<Object> marker = isolate_->factory()->arguments_marker();
    4128             : 
    4129         195 :   int length = static_cast<int>(object_positions_.size());
    4130         195 :   CHECK_EQ(length, previously_materialized_objects->length());
    4131             : 
    4132         528 :   for (int i = 0; i < length; i++) {
    4133             :     // For a previously materialized objects, inject their value into the
    4134             :     // translated values.
    4135         528 :     if (previously_materialized_objects->get(i) != *marker) {
    4136         493 :       TranslatedState::ObjectPosition pos = object_positions_[i];
    4137             :       TranslatedValue* value_info =
    4138         493 :           &(frames_[pos.frame_index_].values_[pos.value_index_]);
    4139         493 :       CHECK(value_info->IsMaterializedObject());
    4140             : 
    4141             :       value_info->value_ =
    4142         986 :           Handle<Object>(previously_materialized_objects->get(i), isolate_);
    4143             :     }
    4144             :   }
    4145             : }
    4146             : 
    4147             : }  // namespace internal
    4148             : }  // namespace v8

Generated by: LCOV version 1.10