LCOV - code coverage report
Current view: top level - src - deoptimizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1407 1576 89.3 %
Date: 2019-02-19 Functions: 127 170 74.7 %

          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/counters.h"
      14             : #include "src/disasm.h"
      15             : #include "src/frames-inl.h"
      16             : #include "src/global-handles.h"
      17             : #include "src/heap/heap-inl.h"
      18             : #include "src/interpreter/interpreter.h"
      19             : #include "src/log.h"
      20             : #include "src/macro-assembler.h"
      21             : #include "src/objects/debug-objects-inl.h"
      22             : #include "src/objects/heap-number-inl.h"
      23             : #include "src/objects/smi.h"
      24             : #include "src/register-configuration.h"
      25             : #include "src/tracing/trace-event.h"
      26             : #include "src/v8.h"
      27             : #include "src/v8threads.h"
      28             : 
      29             : // Has to be the last include (doesn't have include guards)
      30             : #include "src/objects/object-macros.h"
      31             : 
      32             : namespace v8 {
      33             : namespace internal {
      34             : 
      35             : // {FrameWriter} offers a stack writer abstraction for writing
      36             : // FrameDescriptions. The main service the class provides is managing
      37             : // {top_offset_}, i.e. the offset of the next slot to write to.
      38             : class FrameWriter {
      39             :  public:
      40             :   static const int NO_INPUT_INDEX = -1;
      41       50303 :   FrameWriter(Deoptimizer* deoptimizer, FrameDescription* frame,
      42             :               CodeTracer::Scope* trace_scope)
      43             :       : deoptimizer_(deoptimizer),
      44             :         frame_(frame),
      45             :         trace_scope_(trace_scope),
      46      100606 :         top_offset_(frame->GetFrameSize()) {}
      47             : 
      48       20767 :   void PushRawValue(intptr_t value, const char* debug_hint) {
      49             :     PushValue(value);
      50             : 
      51       20767 :     if (trace_scope_ != nullptr) {
      52           0 :       DebugPrintOutputValue(value, debug_hint);
      53             :     }
      54       20767 :   }
      55             : 
      56     1382710 :   void PushRawObject(Object obj, const char* debug_hint) {
      57      691355 :     intptr_t value = obj->ptr();
      58             :     PushValue(value);
      59      691355 :     if (trace_scope_ != nullptr) {
      60        2880 :       DebugPrintOutputObject(obj, top_offset_, debug_hint);
      61             :     }
      62      691355 :   }
      63             : 
      64       50303 :   void PushCallerPc(intptr_t pc) {
      65       50303 :     top_offset_ -= kPCOnStackSize;
      66       50303 :     frame_->SetCallerPc(top_offset_, pc);
      67       50303 :     DebugPrintOutputValue(pc, "caller's pc\n");
      68       50303 :   }
      69             : 
      70       50303 :   void PushCallerFp(intptr_t fp) {
      71       50303 :     top_offset_ -= kFPOnStackSize;
      72       50303 :     frame_->SetCallerFp(top_offset_, fp);
      73       50303 :     DebugPrintOutputValue(fp, "caller's fp\n");
      74       50303 :   }
      75             : 
      76             :   void PushCallerConstantPool(intptr_t cp) {
      77             :     top_offset_ -= kSystemPointerSize;
      78             :     frame_->SetCallerConstantPool(top_offset_, cp);
      79             :     DebugPrintOutputValue(cp, "caller's constant_pool\n");
      80             :   }
      81             : 
      82      586399 :   void PushTranslatedValue(const TranslatedFrame::iterator& iterator,
      83      583999 :                            const char* debug_hint = "") {
      84      583999 :     Object obj = iterator->GetRawValue();
      85             : 
      86      583999 :     PushRawObject(obj, debug_hint);
      87             : 
      88      583999 :     if (trace_scope_) {
      89        2400 :       PrintF(trace_scope_->file(), " (input #%d)\n", iterator.input_index());
      90             :     }
      91             : 
      92             :     deoptimizer_->QueueValueForMaterialization(output_address(top_offset_), obj,
      93     1167998 :                                                iterator);
      94      583999 :   }
      95             : 
      96             :   unsigned top_offset() const { return top_offset_; }
      97             : 
      98             :  private:
      99             :   void PushValue(intptr_t value) {
     100             :     CHECK_GE(top_offset_, 0);
     101      712122 :     top_offset_ -= kSystemPointerSize;
     102             :     frame_->SetFrameSlot(top_offset_, value);
     103             :   }
     104             : 
     105             :   Address output_address(unsigned output_offset) {
     106             :     Address output_address =
     107      587359 :         static_cast<Address>(frame_->GetTop()) + output_offset;
     108             :     return output_address;
     109             :   }
     110             : 
     111      101086 :   void DebugPrintOutputValue(intptr_t value, const char* debug_hint = "") {
     112      100606 :     if (trace_scope_ != nullptr) {
     113             :       PrintF(trace_scope_->file(),
     114             :              "    " V8PRIxPTR_FMT ": [top + %3d] <- " V8PRIxPTR_FMT " ;  %s",
     115         960 :              output_address(top_offset_), top_offset_, value, debug_hint);
     116             :     }
     117      100606 :   }
     118             : 
     119        2880 :   void DebugPrintOutputObject(Object obj, unsigned output_offset,
     120        2880 :                               const char* debug_hint = "") {
     121        2880 :     if (trace_scope_ != nullptr) {
     122             :       PrintF(trace_scope_->file(), "    " V8PRIxPTR_FMT ": [top + %3d] <- ",
     123        2880 :              output_address(output_offset), output_offset);
     124        2880 :       if (obj->IsSmi()) {
     125         312 :         PrintF(V8PRIxPTR_FMT " <Smi %d>", obj->ptr(), Smi::cast(obj)->value());
     126             :       } else {
     127        5136 :         obj->ShortPrint(trace_scope_->file());
     128             :       }
     129        5760 :       PrintF(trace_scope_->file(), " ;  %s", debug_hint);
     130             :     }
     131        2880 :   }
     132             : 
     133             :   Deoptimizer* deoptimizer_;
     134             :   FrameDescription* frame_;
     135             :   CodeTracer::Scope* trace_scope_;
     136             :   unsigned top_offset_;
     137             : };
     138             : 
     139      244196 : DeoptimizerData::DeoptimizerData(Heap* heap) : heap_(heap), current_(nullptr) {
     140             :   Code* start = &deopt_entry_code_[0];
     141             :   Code* end = &deopt_entry_code_[DeoptimizerData::kLastDeoptimizeKind + 1];
     142       61049 :   heap_->RegisterStrongRoots(FullObjectSlot(start), FullObjectSlot(end));
     143       61049 : }
     144             : 
     145             : 
     146       61034 : DeoptimizerData::~DeoptimizerData() {
     147             :   Code* start = &deopt_entry_code_[0];
     148       61034 :   heap_->UnregisterStrongRoots(FullObjectSlot(start));
     149       61034 : }
     150             : 
     151           0 : Code DeoptimizerData::deopt_entry_code(DeoptimizeKind kind) {
     152     4720990 :   return deopt_entry_code_[static_cast<int>(kind)];
     153             : }
     154             : 
     155           0 : void DeoptimizerData::set_deopt_entry_code(DeoptimizeKind kind, Code code) {
     156       43929 :   deopt_entry_code_[static_cast<int>(kind)] = code;
     157           0 : }
     158             : 
     159       45171 : Code Deoptimizer::FindDeoptimizingCode(Address addr) {
     160       90342 :   if (function_->IsHeapObject()) {
     161             :     // Search all deoptimizing code in the native context of the function.
     162       45171 :     Isolate* isolate = isolate_;
     163       45171 :     Context native_context = function_->context()->native_context();
     164       45171 :     Object element = native_context->DeoptimizedCodeListHead();
     165     7650364 :     while (!element->IsUndefined(isolate)) {
     166     7584555 :       Code code = Code::cast(element);
     167     7584555 :       CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
     168     7584555 :       if (code->contains(addr)) return code;
     169     7560022 :       element = code->next_code_link();
     170             :     }
     171             :   }
     172       20638 :   return Code();
     173             : }
     174             : 
     175             : 
     176             : // We rely on this function not causing a GC.  It is called from generated code
     177             : // without having a real stack frame in place.
     178       45171 : Deoptimizer* Deoptimizer::New(Address raw_function, DeoptimizeKind kind,
     179             :                               unsigned bailout_id, Address from,
     180       45171 :                               int fp_to_sp_delta, Isolate* isolate) {
     181             :   JSFunction function = JSFunction::cast(Object(raw_function));
     182             :   Deoptimizer* deoptimizer = new Deoptimizer(isolate, function, kind,
     183       90342 :                                              bailout_id, from, fp_to_sp_delta);
     184       45171 :   CHECK_NULL(isolate->deoptimizer_data()->current_);
     185       45171 :   isolate->deoptimizer_data()->current_ = deoptimizer;
     186       45171 :   return deoptimizer;
     187             : }
     188             : 
     189       90342 : Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
     190       45171 :   Deoptimizer* result = isolate->deoptimizer_data()->current_;
     191       45171 :   CHECK_NOT_NULL(result);
     192       45171 :   result->DeleteFrameDescriptions();
     193       45171 :   isolate->deoptimizer_data()->current_ = nullptr;
     194       45171 :   return result;
     195             : }
     196             : 
     197       24920 : DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
     198             :     JavaScriptFrame* frame,
     199             :     int jsframe_index,
     200             :     Isolate* isolate) {
     201       74760 :   CHECK(frame->is_optimized());
     202             : 
     203       24920 :   TranslatedState translated_values(frame);
     204       24920 :   translated_values.Prepare(frame->fp());
     205             : 
     206             :   TranslatedState::iterator frame_it = translated_values.end();
     207             :   int counter = jsframe_index;
     208      107942 :   for (auto it = translated_values.begin(); it != translated_values.end();
     209             :        it++) {
     210      194212 :     if (it->kind() == TranslatedFrame::kInterpretedFunction ||
     211      111162 :         it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
     212             :         it->kind() ==
     213             :             TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
     214       54882 :       if (counter == 0) {
     215             :         frame_it = it;
     216             :         break;
     217             :       }
     218       29962 :       counter--;
     219             :     }
     220             :   }
     221       24920 :   CHECK(frame_it != translated_values.end());
     222             :   // We only include kJavaScriptBuiltinContinuation frames above to get the
     223             :   // counting right.
     224       24920 :   CHECK_EQ(frame_it->kind(), TranslatedFrame::kInterpretedFunction);
     225             : 
     226             :   DeoptimizedFrameInfo* info =
     227       49840 :       new DeoptimizedFrameInfo(&translated_values, frame_it, isolate);
     228             : 
     229       24920 :   return info;
     230             : }
     231             : 
     232             : namespace {
     233       65042 : class ActivationsFinder : public ThreadVisitor {
     234             :  public:
     235             :   explicit ActivationsFinder(std::set<Code>* codes, Code topmost_optimized_code,
     236             :                              bool safe_to_deopt_topmost_optimized_code)
     237       65042 :       : codes_(codes) {
     238             : #ifdef DEBUG
     239             :     topmost_ = topmost_optimized_code;
     240             :     safe_to_deopt_ = safe_to_deopt_topmost_optimized_code;
     241             : #endif
     242             :   }
     243             : 
     244             :   // Find the frames with activations of codes marked for deoptimization, search
     245             :   // for the trampoline to the deoptimizer call respective to each code, and use
     246             :   // it to replace the current pc on the stack.
     247      128151 :   void VisitThread(Isolate* isolate, ThreadLocalTop* top) override {
     248      642819 :     for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
     249      514668 :       if (it.frame()->type() == StackFrame::OPTIMIZED) {
     250       59350 :         Code code = it.frame()->LookupCode();
     251      110376 :         if (code->kind() == Code::OPTIMIZED_FUNCTION &&
     252       51026 :             code->marked_for_deoptimization()) {
     253       26168 :           codes_->erase(code);
     254             :           // Obtain the trampoline to the deoptimizer call.
     255       52336 :           SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
     256       26168 :           int trampoline_pc = safepoint.trampoline_pc();
     257             :           DCHECK_IMPLIES(code == topmost_, safe_to_deopt_);
     258             :           // Replace the current pc on the stack with the trampoline.
     259             :           it.frame()->set_pc(code->raw_instruction_start() + trampoline_pc);
     260             :         }
     261             :       }
     262             :     }
     263      128151 :   }
     264             : 
     265             :  private:
     266             :   std::set<Code>* codes_;
     267             : 
     268             : #ifdef DEBUG
     269             :   Code topmost_;
     270             :   bool safe_to_deopt_;
     271             : #endif
     272             : };
     273             : }  // namespace
     274             : 
     275             : // Move marked code from the optimized code list to the deoptimized code list,
     276             : // and replace pc on the stack for codes marked for deoptimization.
     277       65042 : void Deoptimizer::DeoptimizeMarkedCodeForContext(Context context) {
     278             :   DisallowHeapAllocation no_allocation;
     279             : 
     280       65042 :   Isolate* isolate = context->GetIsolate();
     281             :   Code topmost_optimized_code;
     282             :   bool safe_to_deopt_topmost_optimized_code = false;
     283             : #ifdef DEBUG
     284             :   // Make sure all activations of optimized code can deopt at their current PC.
     285             :   // The topmost optimized code has special handling because it cannot be
     286             :   // deoptimized due to weak object dependency.
     287             :   for (StackFrameIterator it(isolate, isolate->thread_local_top());
     288             :        !it.done(); it.Advance()) {
     289             :     StackFrame::Type type = it.frame()->type();
     290             :     if (type == StackFrame::OPTIMIZED) {
     291             :       Code code = it.frame()->LookupCode();
     292             :       JSFunction function =
     293             :           static_cast<OptimizedFrame*>(it.frame())->function();
     294             :       if (FLAG_trace_deopt) {
     295             :         CodeTracer::Scope scope(isolate->GetCodeTracer());
     296             :         PrintF(scope.file(), "[deoptimizer found activation of function: ");
     297             :         function->PrintName(scope.file());
     298             :         PrintF(scope.file(), " / %" V8PRIxPTR "]\n", function.ptr());
     299             :       }
     300             :       SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
     301             : 
     302             :       // Turbofan deopt is checked when we are patching addresses on stack.
     303             :       bool safe_if_deopt_triggered = safepoint.has_deoptimization_index();
     304             :       bool is_builtin_code = code->kind() == Code::BUILTIN;
     305             :       DCHECK(topmost_optimized_code.is_null() || safe_if_deopt_triggered ||
     306             :              is_builtin_code);
     307             :       if (topmost_optimized_code.is_null()) {
     308             :         topmost_optimized_code = code;
     309             :         safe_to_deopt_topmost_optimized_code = safe_if_deopt_triggered;
     310             :       }
     311             :     }
     312             :   }
     313             : #endif
     314             : 
     315             :   // We will use this set to mark those Code objects that are marked for
     316             :   // deoptimization and have not been found in stack frames.
     317             :   std::set<Code> codes;
     318             : 
     319             :   // Move marked code from the optimized code list to the deoptimized code list.
     320             :   // Walk over all optimized code objects in this native context.
     321       65042 :   Code prev;
     322       65042 :   Object element = context->OptimizedCodeListHead();
     323      910232 :   while (!element->IsUndefined(isolate)) {
     324      780148 :     Code code = Code::cast(element);
     325      780148 :     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     326             :     Object next = code->next_code_link();
     327             : 
     328      780148 :     if (code->marked_for_deoptimization()) {
     329             :       codes.insert(code);
     330             : 
     331      308822 :       if (!prev.is_null()) {
     332             :         // Skip this code in the optimized code list.
     333        2213 :         prev->set_next_code_link(next);
     334             :       } else {
     335             :         // There was no previous node, the next node is the new head.
     336      306609 :         context->SetOptimizedCodeListHead(next);
     337             :       }
     338             : 
     339             :       // Move the code to the _deoptimized_ code list.
     340      308822 :       code->set_next_code_link(context->DeoptimizedCodeListHead());
     341      308822 :       context->SetDeoptimizedCodeListHead(code);
     342             :     } else {
     343             :       // Not marked; preserve this element.
     344      471326 :       prev = code;
     345             :     }
     346      780148 :     element = next;
     347             :   }
     348             : 
     349             :   ActivationsFinder visitor(&codes, topmost_optimized_code,
     350             :                             safe_to_deopt_topmost_optimized_code);
     351             :   // Iterate over the stack of this thread.
     352       65042 :   visitor.VisitThread(isolate, isolate->thread_local_top());
     353             :   // In addition to iterate over the stack of this thread, we also
     354             :   // need to consider all the other threads as they may also use
     355             :   // the code currently beings deoptimized.
     356       65042 :   isolate->thread_manager()->IterateArchivedThreads(&visitor);
     357             : 
     358             :   // If there's no activation of a code in any stack then we can remove its
     359             :   // deoptimization data. We do this to ensure that code objects that are
     360             :   // unlinked don't transitively keep objects alive unnecessarily.
     361      435983 :   for (Code code : codes) {
     362      305899 :     isolate->heap()->InvalidateCodeDeoptimizationData(code);
     363             :   }
     364       65042 : }
     365             : 
     366             : 
     367        6790 : void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
     368             :   RuntimeCallTimerScope runtimeTimer(isolate,
     369        6790 :                                      RuntimeCallCounterId::kDeoptimizeCode);
     370             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     371       20370 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     372        6790 :   if (FLAG_trace_deopt) {
     373           0 :     CodeTracer::Scope scope(isolate->GetCodeTracer());
     374           0 :     PrintF(scope.file(), "[deoptimize all code in all contexts]\n");
     375             :   }
     376        6790 :   isolate->AbortConcurrentOptimization(BlockingBehavior::kBlock);
     377             :   DisallowHeapAllocation no_allocation;
     378             :   // For all contexts, mark all code, then deoptimize.
     379        6790 :   Object context = isolate->heap()->native_contexts_list();
     380       39670 :   while (!context->IsUndefined(isolate)) {
     381       26090 :     Context native_context = Context::cast(context);
     382       26090 :     MarkAllCodeForContext(native_context);
     383       26090 :     DeoptimizeMarkedCodeForContext(native_context);
     384       26090 :     context = native_context->next_context_link();
     385             :   }
     386        6790 : }
     387             : 
     388             : 
     389        1873 : void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
     390             :   RuntimeCallTimerScope runtimeTimer(isolate,
     391        1873 :                                      RuntimeCallCounterId::kDeoptimizeCode);
     392             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     393        5619 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     394        1873 :   if (FLAG_trace_deopt) {
     395           2 :     CodeTracer::Scope scope(isolate->GetCodeTracer());
     396           2 :     PrintF(scope.file(), "[deoptimize marked code in all contexts]\n");
     397             :   }
     398             :   DisallowHeapAllocation no_allocation;
     399             :   // For all contexts, deoptimize code already marked.
     400        1873 :   Object context = isolate->heap()->native_contexts_list();
     401        7697 :   while (!context->IsUndefined(isolate)) {
     402        3951 :     Context native_context = Context::cast(context);
     403        3951 :     DeoptimizeMarkedCodeForContext(native_context);
     404        3951 :     context = native_context->next_context_link();
     405             :   }
     406        1873 : }
     407             : 
     408       26090 : void Deoptimizer::MarkAllCodeForContext(Context context) {
     409       26090 :   Object element = context->OptimizedCodeListHead();
     410             :   Isolate* isolate = context->GetIsolate();
     411      324352 :   while (!element->IsUndefined(isolate)) {
     412      272172 :     Code code = Code::cast(element);
     413      272172 :     CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     414      272172 :     code->set_marked_for_deoptimization(true);
     415      272172 :     element = code->next_code_link();
     416             :   }
     417       26090 : }
     418             : 
     419      585301 : void Deoptimizer::DeoptimizeFunction(JSFunction function, Code code) {
     420             :   Isolate* isolate = function->GetIsolate();
     421             :   RuntimeCallTimerScope runtimeTimer(isolate,
     422      585301 :                                      RuntimeCallCounterId::kDeoptimizeCode);
     423             :   TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
     424     1755903 :   TRACE_EVENT0("v8", "V8.DeoptimizeCode");
     425      585301 :   function->ResetIfBytecodeFlushed();
     426      585301 :   if (code.is_null()) code = function->code();
     427             : 
     428      585301 :   if (code->kind() == Code::OPTIMIZED_FUNCTION) {
     429             :     // Mark the code for deoptimization and unlink any functions that also
     430             :     // refer to that code. The code cannot be shared across native contexts,
     431             :     // so we only need to search one.
     432       35001 :     code->set_marked_for_deoptimization(true);
     433             :     // The code in the function's optimized code feedback vector slot might
     434             :     // be different from the code on the function - evict it if necessary.
     435             :     function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
     436       35001 :         function->shared(), "unlinking code marked for deopt");
     437       35001 :     if (!code->deopt_already_counted()) {
     438       29910 :       function->feedback_vector()->increment_deopt_count();
     439       14955 :       code->set_deopt_already_counted(true);
     440             :     }
     441       35001 :     DeoptimizeMarkedCodeForContext(function->context()->native_context());
     442             :   }
     443      585301 : }
     444             : 
     445       45171 : void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
     446       45171 :   deoptimizer->DoComputeOutputFrames();
     447       45171 : }
     448             : 
     449         487 : const char* Deoptimizer::MessageFor(DeoptimizeKind kind) {
     450         487 :   switch (kind) {
     451             :     case DeoptimizeKind::kEager:
     452             :       return "eager";
     453             :     case DeoptimizeKind::kSoft:
     454           3 :       return "soft";
     455             :     case DeoptimizeKind::kLazy:
     456           0 :       return "lazy";
     457             :   }
     458           0 :   FATAL("Unsupported deopt kind");
     459             :   return nullptr;
     460             : }
     461             : 
     462       90342 : Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction function,
     463             :                          DeoptimizeKind kind, unsigned bailout_id, Address from,
     464             :                          int fp_to_sp_delta)
     465             :     : isolate_(isolate),
     466             :       function_(function),
     467             :       bailout_id_(bailout_id),
     468             :       deopt_kind_(kind),
     469             :       from_(from),
     470             :       fp_to_sp_delta_(fp_to_sp_delta),
     471             :       deoptimizing_throw_(false),
     472             :       catch_handler_data_(-1),
     473             :       catch_handler_pc_offset_(-1),
     474             :       input_(nullptr),
     475             :       output_count_(0),
     476             :       jsframe_count_(0),
     477             :       output_(nullptr),
     478             :       caller_frame_top_(0),
     479             :       caller_fp_(0),
     480             :       caller_pc_(0),
     481             :       caller_constant_pool_(0),
     482             :       input_frame_context_(0),
     483             :       stack_fp_(0),
     484       90342 :       trace_scope_(nullptr) {
     485       45171 :   if (isolate->deoptimizer_lazy_throw()) {
     486             :     isolate->set_deoptimizer_lazy_throw(false);
     487        6113 :     deoptimizing_throw_ = true;
     488             :   }
     489             : 
     490             :   DCHECK_NE(from, kNullAddress);
     491       45171 :   compiled_code_ = FindOptimizedCode();
     492             :   DCHECK(!compiled_code_.is_null());
     493             : 
     494             :   DCHECK(function->IsJSFunction());
     495             :   trace_scope_ = FLAG_trace_deopt
     496             :                      ? new CodeTracer::Scope(isolate->GetCodeTracer())
     497       90342 :                      : nullptr;
     498             : #ifdef DEBUG
     499             :   DCHECK(AllowHeapAllocation::IsAllowed());
     500             :   disallow_heap_allocation_ = new DisallowHeapAllocation();
     501             : #endif  // DEBUG
     502       90342 :   if (compiled_code_->kind() != Code::OPTIMIZED_FUNCTION ||
     503       45171 :       !compiled_code_->deopt_already_counted()) {
     504             :     // If the function is optimized, and we haven't counted that deopt yet, then
     505             :     // increment the function's deopt count so that we can avoid optimising
     506             :     // functions that deopt too often.
     507             : 
     508       20972 :     if (deopt_kind_ == DeoptimizeKind::kSoft) {
     509             :       // Soft deopts shouldn't count against the overall deoptimization count
     510             :       // that can eventually lead to disabling optimization for a function.
     511        4529 :       isolate->counters()->soft_deopts_executed()->Increment();
     512       16443 :     } else if (!function.is_null()) {
     513       32886 :       function->feedback_vector()->increment_deopt_count();
     514             :     }
     515             :   }
     516       45171 :   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
     517       45171 :     compiled_code_->set_deopt_already_counted(true);
     518       90342 :     PROFILE(isolate_,
     519             :             CodeDeoptEvent(compiled_code_, kind, from_, fp_to_sp_delta_));
     520             :   }
     521       45171 :   unsigned size = ComputeInputFrameSize();
     522             :   int parameter_count =
     523       90342 :       function->shared()->internal_formal_parameter_count() + 1;
     524       45171 :   input_ = new (size) FrameDescription(size, parameter_count);
     525       45171 : }
     526             : 
     527       45171 : Code Deoptimizer::FindOptimizedCode() {
     528       45171 :   Code compiled_code = FindDeoptimizingCode(from_);
     529             :   return !compiled_code.is_null() ? compiled_code
     530       45171 :                                   : isolate_->FindCodeObject(from_);
     531             : }
     532             : 
     533             : 
     534         480 : void Deoptimizer::PrintFunctionName() {
     535        1440 :   if (function_->IsHeapObject() && function_->IsJSFunction()) {
     536         960 :     function_->ShortPrint(trace_scope_->file());
     537             :   } else {
     538             :     PrintF(trace_scope_->file(),
     539           0 :            "%s", Code::Kind2String(compiled_code_->kind()));
     540             :   }
     541         480 : }
     542             : 
     543       90342 : Handle<JSFunction> Deoptimizer::function() const {
     544       90342 :   return Handle<JSFunction>(function_, isolate());
     545             : }
     546           0 : Handle<Code> Deoptimizer::compiled_code() const {
     547           0 :   return Handle<Code>(compiled_code_, isolate());
     548             : }
     549             : 
     550       45171 : Deoptimizer::~Deoptimizer() {
     551             :   DCHECK(input_ == nullptr && output_ == nullptr);
     552             :   DCHECK_NULL(disallow_heap_allocation_);
     553       45411 :   delete trace_scope_;
     554       45171 : }
     555             : 
     556             : 
     557       45171 : void Deoptimizer::DeleteFrameDescriptions() {
     558       45171 :   delete input_;
     559       95474 :   for (int i = 0; i < output_count_; ++i) {
     560       50303 :     if (output_[i] != input_) delete output_[i];
     561             :   }
     562       45171 :   delete[] output_;
     563       45171 :   input_ = nullptr;
     564       45171 :   output_ = nullptr;
     565             : #ifdef DEBUG
     566             :   DCHECK(!AllowHeapAllocation::IsAllowed());
     567             :   DCHECK_NOT_NULL(disallow_heap_allocation_);
     568             :   delete disallow_heap_allocation_;
     569             :   disallow_heap_allocation_ = nullptr;
     570             : #endif  // DEBUG
     571       45171 : }
     572             : 
     573     3306868 : Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
     574             :                                             DeoptimizeKind kind) {
     575             :   DeoptimizerData* data = isolate->deoptimizer_data();
     576     3306868 :   CHECK_LE(kind, DeoptimizerData::kLastDeoptimizeKind);
     577     3306868 :   CHECK(!data->deopt_entry_code(kind).is_null());
     578     3306868 :   return data->deopt_entry_code(kind)->raw_instruction_start();
     579             : }
     580             : 
     581           0 : bool Deoptimizer::IsDeoptimizationEntry(Isolate* isolate, Address addr,
     582             :                                         DeoptimizeKind type) {
     583             :   DeoptimizerData* data = isolate->deoptimizer_data();
     584           0 :   CHECK_LE(type, DeoptimizerData::kLastDeoptimizeKind);
     585             :   Code code = data->deopt_entry_code(type);
     586           0 :   if (code.is_null()) return false;
     587           0 :   return addr == code->raw_instruction_start();
     588             : }
     589             : 
     590           0 : bool Deoptimizer::IsDeoptimizationEntry(Isolate* isolate, Address addr,
     591             :                                         DeoptimizeKind* type) {
     592           0 :   if (IsDeoptimizationEntry(isolate, addr, DeoptimizeKind::kEager)) {
     593           0 :     *type = DeoptimizeKind::kEager;
     594           0 :     return true;
     595             :   }
     596           0 :   if (IsDeoptimizationEntry(isolate, addr, DeoptimizeKind::kSoft)) {
     597           0 :     *type = DeoptimizeKind::kSoft;
     598           0 :     return true;
     599             :   }
     600           0 :   if (IsDeoptimizationEntry(isolate, addr, DeoptimizeKind::kLazy)) {
     601           0 :     *type = DeoptimizeKind::kLazy;
     602           0 :     return true;
     603             :   }
     604             :   return false;
     605             : }
     606             : 
     607          85 : int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
     608             :   int length = 0;
     609             :   // Count all entries in the deoptimizing code list of every context.
     610          85 :   Object context = isolate->heap()->native_contexts_list();
     611         255 :   while (!context->IsUndefined(isolate)) {
     612          85 :     Context native_context = Context::cast(context);
     613          85 :     Object element = native_context->DeoptimizedCodeListHead();
     614         262 :     while (!element->IsUndefined(isolate)) {
     615          92 :       Code code = Code::cast(element);
     616             :       DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
     617          92 :       if (!code->marked_for_deoptimization()) {
     618           0 :         length++;
     619             :       }
     620          92 :       element = code->next_code_link();
     621             :     }
     622          85 :     context = Context::cast(context)->next_context_link();
     623             :   }
     624          85 :   return length;
     625             : }
     626             : 
     627             : namespace {
     628             : 
     629        6180 : int LookupCatchHandler(TranslatedFrame* translated_frame, int* data_out) {
     630        6180 :   switch (translated_frame->kind()) {
     631             :     case TranslatedFrame::kInterpretedFunction: {
     632             :       int bytecode_offset = translated_frame->node_id().ToInt();
     633             :       HandlerTable table(
     634        6140 :           translated_frame->raw_shared_info()->GetBytecodeArray());
     635        6140 :       return table.LookupRange(bytecode_offset, data_out, nullptr);
     636             :     }
     637             :     case TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch: {
     638             :       return 0;
     639             :     }
     640             :     default:
     641             :       break;
     642             :   }
     643          32 :   return -1;
     644             : }
     645             : 
     646             : bool ShouldPadArguments(int arg_count) {
     647             :   return kPadArguments && (arg_count % 2 != 0);
     648             : }
     649             : 
     650             : }  // namespace
     651             : 
     652             : // We rely on this function not causing a GC.  It is called from generated code
     653             : // without having a real stack frame in place.
     654       90342 : void Deoptimizer::DoComputeOutputFrames() {
     655             :   base::ElapsedTimer timer;
     656             : 
     657             :   // Determine basic deoptimization information.  The optimized frame is
     658             :   // described by the input data.
     659             :   DeoptimizationData input_data =
     660       90342 :       DeoptimizationData::cast(compiled_code_->deoptimization_data());
     661             : 
     662             :   {
     663             :     // Read caller's PC, caller's FP and caller's constant pool values
     664             :     // from input frame. Compute caller's frame top address.
     665             : 
     666       45171 :     Register fp_reg = JavaScriptFrame::fp_register();
     667       90342 :     stack_fp_ = input_->GetRegister(fp_reg.code());
     668             : 
     669       45171 :     caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
     670             : 
     671       45171 :     Address fp_address = input_->GetFramePointerAddress();
     672       45171 :     caller_fp_ = Memory<intptr_t>(fp_address);
     673             :     caller_pc_ =
     674       90342 :         Memory<intptr_t>(fp_address + CommonFrameConstants::kCallerPCOffset);
     675             :     input_frame_context_ = Memory<intptr_t>(
     676       90342 :         fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
     677             : 
     678             :     if (FLAG_enable_embedded_constant_pool) {
     679             :       caller_constant_pool_ = Memory<intptr_t>(
     680             :           fp_address + CommonFrameConstants::kConstantPoolOffset);
     681             :     }
     682             :   }
     683             : 
     684       45171 :   if (trace_scope_ != nullptr) {
     685             :     timer.Start();
     686             :     PrintF(trace_scope_->file(), "[deoptimizing (DEOPT %s): begin ",
     687         480 :            MessageFor(deopt_kind_));
     688         240 :     PrintFunctionName();
     689             :     PrintF(trace_scope_->file(),
     690             :            " (opt #%d) @%d, FP to SP delta: %d, caller sp: " V8PRIxPTR_FMT
     691             :            "]\n",
     692             :            input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
     693         720 :            caller_frame_top_);
     694         240 :     if (deopt_kind_ == DeoptimizeKind::kEager ||
     695             :         deopt_kind_ == DeoptimizeKind::kSoft) {
     696             :       compiled_code_->PrintDeoptLocation(
     697         480 :           trace_scope_->file(), "            ;;; deoptimize at ", from_);
     698             :     }
     699             :   }
     700             : 
     701       45171 :   BailoutId node_id = input_data->BytecodeOffset(bailout_id_);
     702       45171 :   ByteArray translations = input_data->TranslationByteArray();
     703             :   unsigned translation_index =
     704       90342 :       input_data->TranslationIndex(bailout_id_)->value();
     705             : 
     706             :   TranslationIterator state_iterator(translations, translation_index);
     707             :   translated_state_.Init(
     708             :       isolate_, input_->GetFramePointerAddress(), &state_iterator,
     709             :       input_data->LiteralArray(), input_->GetRegisterValues(),
     710       45171 :       trace_scope_ == nullptr ? nullptr : trace_scope_->file(),
     711       45171 :       function_->IsHeapObject()
     712      135513 :           ? function_->shared()->internal_formal_parameter_count()
     713      225855 :           : 0);
     714             : 
     715             :   // Do the input frame to output frame(s) translation.
     716       45171 :   size_t count = translated_state_.frames().size();
     717             :   // If we are supposed to go to the catch handler, find the catching frame
     718             :   // for the catch and make sure we only deoptimize upto that frame.
     719       45171 :   if (deoptimizing_throw_) {
     720             :     size_t catch_handler_frame_index = count;
     721        6180 :     for (size_t i = count; i-- > 0;) {
     722             :       catch_handler_pc_offset_ = LookupCatchHandler(
     723       12360 :           &(translated_state_.frames()[i]), &catch_handler_data_);
     724        6180 :       if (catch_handler_pc_offset_ >= 0) {
     725             :         catch_handler_frame_index = i;
     726             :         break;
     727             :       }
     728             :     }
     729        6113 :     CHECK_LT(catch_handler_frame_index, count);
     730        6113 :     count = catch_handler_frame_index + 1;
     731             :   }
     732             : 
     733             :   DCHECK_NULL(output_);
     734       45171 :   output_ = new FrameDescription*[count];
     735       95474 :   for (size_t i = 0; i < count; ++i) {
     736       50303 :     output_[i] = nullptr;
     737             :   }
     738       45171 :   output_count_ = static_cast<int>(count);
     739             : 
     740             :   // Translate each output frame.
     741             :   int frame_index = 0;  // output_frame_index
     742       95474 :   for (size_t i = 0; i < count; ++i, ++frame_index) {
     743             :     // Read the ast node id, function, and frame height for this output frame.
     744      100606 :     TranslatedFrame* translated_frame = &(translated_state_.frames()[i]);
     745       50303 :     bool handle_exception = deoptimizing_throw_ && i == count - 1;
     746       50303 :     switch (translated_frame->kind()) {
     747             :       case TranslatedFrame::kInterpretedFunction:
     748             :         DoComputeInterpretedFrame(translated_frame, frame_index,
     749       48322 :                                   handle_exception);
     750       48322 :         jsframe_count_++;
     751       48322 :         break;
     752             :       case TranslatedFrame::kArgumentsAdaptor:
     753         834 :         DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
     754         834 :         break;
     755             :       case TranslatedFrame::kConstructStub:
     756         534 :         DoComputeConstructStubFrame(translated_frame, frame_index);
     757         534 :         break;
     758             :       case TranslatedFrame::kBuiltinContinuation:
     759             :         DoComputeBuiltinContinuation(translated_frame, frame_index,
     760          16 :                                      BuiltinContinuationMode::STUB);
     761          16 :         break;
     762             :       case TranslatedFrame::kJavaScriptBuiltinContinuation:
     763             :         DoComputeBuiltinContinuation(translated_frame, frame_index,
     764         565 :                                      BuiltinContinuationMode::JAVASCRIPT);
     765         565 :         break;
     766             :       case TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch:
     767             :         DoComputeBuiltinContinuation(
     768             :             translated_frame, frame_index,
     769             :             handle_exception
     770             :                 ? BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION
     771          32 :                 : BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH);
     772          32 :         break;
     773             :       case TranslatedFrame::kInvalid:
     774           0 :         FATAL("invalid frame");
     775             :         break;
     776             :     }
     777             :   }
     778             : 
     779       45171 :   FrameDescription* topmost = output_[count - 1];
     780             :   topmost->GetRegisterValues()->SetRegister(kRootRegister.code(),
     781       45171 :                                             isolate()->isolate_root());
     782             : 
     783             :   // Print some helpful diagnostic information.
     784       45171 :   if (trace_scope_ != nullptr) {
     785         240 :     double ms = timer.Elapsed().InMillisecondsF();
     786         240 :     int index = output_count_ - 1;  // Index of the topmost frame.
     787             :     PrintF(trace_scope_->file(), "[deoptimizing (%s): end ",
     788         480 :            MessageFor(deopt_kind_));
     789         240 :     PrintFunctionName();
     790             :     PrintF(trace_scope_->file(),
     791             :            " @%d => node=%d, pc=" V8PRIxPTR_FMT ", caller sp=" V8PRIxPTR_FMT
     792             :            ", took %0.3f ms]\n",
     793         240 :            bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
     794         720 :            caller_frame_top_, ms);
     795             :   }
     796       45171 : }
     797             : 
     798      248049 : void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
     799             :                                             int frame_index,
     800       48322 :                                             bool goto_catch_handler) {
     801       48322 :   SharedFunctionInfo shared = translated_frame->raw_shared_info();
     802             : 
     803             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
     804       48322 :   bool is_bottommost = (0 == frame_index);
     805       48322 :   bool is_topmost = (output_count_ - 1 == frame_index);
     806             : 
     807             :   int bytecode_offset = translated_frame->node_id().ToInt();
     808             :   int height = translated_frame->height();
     809       48322 :   int register_count = height - 1;  // Exclude accumulator.
     810             :   int register_stack_slot_count =
     811       48322 :       InterpreterFrameConstants::RegisterStackSlotCount(register_count);
     812       48322 :   int height_in_bytes = register_stack_slot_count * kSystemPointerSize;
     813             : 
     814             :   // The topmost frame will contain the accumulator.
     815       48322 :   if (is_topmost) {
     816       44912 :     height_in_bytes += kSystemPointerSize;
     817       44912 :     if (PadTopOfStackRegister()) height_in_bytes += kSystemPointerSize;
     818             :   }
     819             : 
     820             :   TranslatedFrame::iterator function_iterator = value_iterator++;
     821       48322 :   if (trace_scope_ != nullptr) {
     822         240 :     PrintF(trace_scope_->file(), "  translating interpreted frame ");
     823         240 :     std::unique_ptr<char[]> name = shared->DebugName()->ToCString();
     824         480 :     PrintF(trace_scope_->file(), "%s", name.get());
     825             :     PrintF(trace_scope_->file(), " => bytecode_offset=%d, height=%d%s\n",
     826             :            bytecode_offset, height_in_bytes,
     827         480 :            goto_catch_handler ? " (throw)" : "");
     828             :   }
     829       48322 :   if (goto_catch_handler) {
     830        6105 :     bytecode_offset = catch_handler_pc_offset_;
     831             :   }
     832             : 
     833             :   // The 'fixed' part of the frame consists of the incoming parameters and
     834             :   // the part described by InterpreterFrameConstants. This will include
     835             :   // argument padding, when needed.
     836             :   unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
     837       48322 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
     838             : 
     839             :   // Allocate and store the output frame description.
     840             :   int parameter_count = shared->internal_formal_parameter_count() + 1;
     841             :   FrameDescription* output_frame = new (output_frame_size)
     842       48322 :       FrameDescription(output_frame_size, parameter_count);
     843       48322 :   FrameWriter frame_writer(this, output_frame, trace_scope_);
     844             : 
     845       48322 :   CHECK(frame_index >= 0 && frame_index < output_count_);
     846       48322 :   CHECK_NULL(output_[frame_index]);
     847       48322 :   output_[frame_index] = output_frame;
     848             : 
     849             :   // The top address of the frame is computed from the previous frame's top and
     850             :   // this frame's size.
     851             :   intptr_t top_address;
     852       48322 :   if (is_bottommost) {
     853       45171 :     top_address = caller_frame_top_ - output_frame_size;
     854             :   } else {
     855        9453 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
     856             :   }
     857             :   output_frame->SetTop(top_address);
     858             : 
     859             :   // Compute the incoming parameter translation.
     860             : 
     861             :   ReadOnlyRoots roots(isolate());
     862             :   if (ShouldPadArguments(parameter_count)) {
     863             :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
     864             :   }
     865             : 
     866      286758 :   for (int i = 0; i < parameter_count; ++i, ++value_iterator) {
     867       95057 :     frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
     868             :   }
     869             : 
     870             :   DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
     871             :             frame_writer.top_offset());
     872       48322 :   if (trace_scope_ != nullptr) {
     873         240 :     PrintF(trace_scope_->file(), "    -------------------------\n");
     874             :   }
     875             : 
     876             :   // There are no translation commands for the caller's pc and fp, the
     877             :   // context, the function and the bytecode offset.  Synthesize
     878             :   // their values and set them up
     879             :   // explicitly.
     880             :   //
     881             :   // The caller's pc for the bottommost output frame is the same as in the
     882             :   // input frame.  For all subsequent output frames, it can be read from the
     883             :   // previous one.  This frame's pc can be computed from the non-optimized
     884             :   // function code and AST id of the bailout.
     885             :   const intptr_t caller_pc =
     886       48322 :       is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
     887       48322 :   frame_writer.PushCallerPc(caller_pc);
     888             : 
     889             :   // The caller's frame pointer for the bottommost output frame is the same
     890             :   // as in the input frame.  For all subsequent output frames, it can be
     891             :   // read from the previous one.  Also compute and set this frame's frame
     892             :   // pointer.
     893             :   const intptr_t caller_fp =
     894       48322 :       is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
     895       48322 :   frame_writer.PushCallerFp(caller_fp);
     896             : 
     897       48322 :   intptr_t fp_value = top_address + frame_writer.top_offset();
     898             :   output_frame->SetFp(fp_value);
     899       48322 :   if (is_topmost) {
     900       44912 :     Register fp_reg = InterpretedFrame::fp_register();
     901       44912 :     output_frame->SetRegister(fp_reg.code(), fp_value);
     902             :   }
     903             : 
     904             :   if (FLAG_enable_embedded_constant_pool) {
     905             :     // For the bottommost output frame the constant pool pointer can be gotten
     906             :     // from the input frame. For subsequent output frames, it can be read from
     907             :     // the previous frame.
     908             :     const intptr_t caller_cp =
     909             :         is_bottommost ? caller_constant_pool_
     910             :                       : output_[frame_index - 1]->GetConstantPool();
     911             :     frame_writer.PushCallerConstantPool(caller_cp);
     912             :   }
     913             : 
     914             :   // For the bottommost output frame the context can be gotten from the input
     915             :   // frame. For all subsequent output frames it can be gotten from the function
     916             :   // so long as we don't inline functions that need local contexts.
     917             : 
     918             :   // When deoptimizing into a catch block, we need to take the context
     919             :   // from a register that was specified in the handler table.
     920             :   TranslatedFrame::iterator context_pos = value_iterator++;
     921       48322 :   if (goto_catch_handler) {
     922             :     // Skip to the translated value of the register specified
     923             :     // in the handler table.
     924       75243 :     for (int i = 0; i < catch_handler_data_ + 1; ++i) {
     925       75243 :       context_pos++;
     926             :     }
     927             :   }
     928             :   // Read the context from the translations.
     929       48322 :   Object context = context_pos->GetRawValue();
     930       48322 :   output_frame->SetContext(static_cast<intptr_t>(context->ptr()));
     931       48322 :   frame_writer.PushTranslatedValue(context_pos, "context");
     932             : 
     933             :   // The function was mentioned explicitly in the BEGIN_FRAME.
     934       48322 :   frame_writer.PushTranslatedValue(function_iterator, "function");
     935             : 
     936             :   // Set the bytecode array pointer.
     937       48322 :   Object bytecode_array = shared->HasBreakInfo()
     938       48804 :                               ? shared->GetDebugInfo()->DebugBytecodeArray()
     939       96644 :                               : shared->GetBytecodeArray();
     940       48322 :   frame_writer.PushRawObject(bytecode_array, "bytecode array\n");
     941             : 
     942             :   // The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
     943             :   int raw_bytecode_offset =
     944       48322 :       BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
     945       48322 :   Smi smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
     946       48322 :   frame_writer.PushRawObject(smi_bytecode_offset, "bytecode offset\n");
     947             : 
     948       48322 :   if (trace_scope_ != nullptr) {
     949         240 :     PrintF(trace_scope_->file(), "    -------------------------\n");
     950             :   }
     951             : 
     952             :   // Translate the rest of the interpreter registers in the frame.
     953             :   // The return_value_offset is counted from the top. Here, we compute the
     954             :   // register index (counted from the start).
     955             :   int return_value_first_reg =
     956       48322 :       register_count - translated_frame->return_value_offset();
     957             :   int return_value_count = translated_frame->return_value_count();
     958      804994 :   for (int i = 0; i < register_count; ++i, ++value_iterator) {
     959             :     // Ensure we write the return value if we have one and we are returning
     960             :     // normally to a lazy deopt point.
     961      560431 :     if (is_topmost && !goto_catch_handler &&
     962      307184 :         deopt_kind_ == DeoptimizeKind::kLazy && i >= return_value_first_reg &&
     963          36 :         i < return_value_first_reg + return_value_count) {
     964          27 :       int return_index = i - return_value_first_reg;
     965          27 :       if (return_index == 0) {
     966             :         frame_writer.PushRawValue(input_->GetRegister(kReturnRegister0.code()),
     967          54 :                                   "return value 0\n");
     968             :         // We do not handle the situation when one return value should go into
     969             :         // the accumulator and another one into an ordinary register. Since
     970             :         // the interpreter should never create such situation, just assert
     971             :         // this does not happen.
     972          27 :         CHECK_LE(return_value_first_reg + return_value_count, register_count);
     973             :       } else {
     974           0 :         CHECK_EQ(return_index, 1);
     975             :         frame_writer.PushRawValue(input_->GetRegister(kReturnRegister1.code()),
     976           0 :                                   "return value 1\n");
     977             :       }
     978             :     } else {
     979             :       // This is not return value, just write the value from the translations.
     980      354148 :       frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
     981             :     }
     982             :   }
     983             : 
     984             :   int register_slots_written = register_count;
     985             :   DCHECK_LE(register_slots_written, register_stack_slot_count);
     986             :   // Some architectures must pad the stack frame with extra stack slots
     987             :   // to ensure the stack frame is aligned. Do this now.
     988       48322 :   while (register_slots_written < register_stack_slot_count) {
     989           0 :     register_slots_written++;
     990           0 :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
     991             :   }
     992             : 
     993             :   // Translate the accumulator register (depending on frame position).
     994       48322 :   if (is_topmost) {
     995       44912 :     if (PadTopOfStackRegister()) {
     996           0 :       frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
     997             :     }
     998             :     // For topmost frame, put the accumulator on the stack. The
     999             :     // {NotifyDeoptimized} builtin pops it off the topmost frame (possibly
    1000             :     // after materialization).
    1001       44912 :     if (goto_catch_handler) {
    1002             :       // If we are lazy deopting to a catch handler, we set the accumulator to
    1003             :       // the exception (which lives in the result register).
    1004             :       intptr_t accumulator_value =
    1005        6105 :           input_->GetRegister(kInterpreterAccumulatorRegister.code());
    1006       12210 :       frame_writer.PushRawObject(Object(accumulator_value), "accumulator\n");
    1007             :     } else {
    1008             :       // If we are lazily deoptimizing make sure we store the deopt
    1009             :       // return value into the appropriate slot.
    1010       95976 :       if (deopt_kind_ == DeoptimizeKind::kLazy &&
    1011       57142 :           translated_frame->return_value_offset() == 0 &&
    1012             :           translated_frame->return_value_count() > 0) {
    1013       18064 :         CHECK_EQ(translated_frame->return_value_count(), 1);
    1014             :         frame_writer.PushRawValue(input_->GetRegister(kReturnRegister0.code()),
    1015       36128 :                                   "return value 0\n");
    1016             :       } else {
    1017       20743 :         frame_writer.PushTranslatedValue(value_iterator, "accumulator");
    1018             :       }
    1019             :     }
    1020             :     ++value_iterator;  // Move over the accumulator.
    1021             :   } else {
    1022             :     // For non-topmost frames, skip the accumulator translation. For those
    1023             :     // frames, the return value from the callee will become the accumulator.
    1024             :     ++value_iterator;
    1025             :   }
    1026       48322 :   CHECK_EQ(translated_frame->end(), value_iterator);
    1027       48322 :   CHECK_EQ(0u, frame_writer.top_offset());
    1028             : 
    1029             :   // Compute this frame's PC and state. The PC will be a special builtin that
    1030             :   // continues the bytecode dispatch. Note that non-topmost and lazy-style
    1031             :   // bailout handlers also advance the bytecode offset before dispatch, hence
    1032             :   // simulating what normal handlers do upon completion of the operation.
    1033       48322 :   Builtins* builtins = isolate_->builtins();
    1034             :   Code dispatch_builtin =
    1035       44912 :       (!is_topmost || (deopt_kind_ == DeoptimizeKind::kLazy)) &&
    1036             :               !goto_catch_handler
    1037             :           ? builtins->builtin(Builtins::kInterpreterEnterBytecodeAdvance)
    1038       70094 :           : builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
    1039             :   output_frame->SetPc(
    1040       48322 :       static_cast<intptr_t>(dispatch_builtin->InstructionStart()));
    1041             : 
    1042             :   // Update constant pool.
    1043             :   if (FLAG_enable_embedded_constant_pool) {
    1044             :     intptr_t constant_pool_value =
    1045             :         static_cast<intptr_t>(dispatch_builtin->constant_pool());
    1046             :     output_frame->SetConstantPool(constant_pool_value);
    1047             :     if (is_topmost) {
    1048             :       Register constant_pool_reg =
    1049             :           InterpretedFrame::constant_pool_pointer_register();
    1050             :       output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
    1051             :     }
    1052             :   }
    1053             : 
    1054             :   // Clear the context register. The context might be a de-materialized object
    1055             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1056             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1057       48322 :   if (is_topmost) {
    1058             :     intptr_t context_value = static_cast<intptr_t>(Smi::zero().ptr());
    1059       44912 :     Register context_reg = JavaScriptFrame::context_register();
    1060       44912 :     output_frame->SetRegister(context_reg.code(), context_value);
    1061             :     // Set the continuation for the topmost frame.
    1062       44912 :     Code continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
    1063             :     output_frame->SetContinuation(
    1064       44912 :         static_cast<intptr_t>(continuation->InstructionStart()));
    1065             :   }
    1066       48322 : }
    1067             : 
    1068         834 : void Deoptimizer::DoComputeArgumentsAdaptorFrame(
    1069        1668 :     TranslatedFrame* translated_frame, int frame_index) {
    1070             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1071         834 :   bool is_bottommost = (0 == frame_index);
    1072             : 
    1073         834 :   unsigned height = translated_frame->height();
    1074         834 :   unsigned height_in_bytes = height * kSystemPointerSize;
    1075             :   int parameter_count = height;
    1076             :   if (ShouldPadArguments(parameter_count))
    1077             :     height_in_bytes += kSystemPointerSize;
    1078             : 
    1079             :   TranslatedFrame::iterator function_iterator = value_iterator++;
    1080         834 :   if (trace_scope_ != nullptr) {
    1081             :     PrintF(trace_scope_->file(),
    1082           0 :            "  translating arguments adaptor => height=%d\n", height_in_bytes);
    1083             :   }
    1084             : 
    1085             :   unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
    1086         834 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
    1087             : 
    1088             :   // Allocate and store the output frame description.
    1089             :   FrameDescription* output_frame = new (output_frame_size)
    1090         834 :       FrameDescription(output_frame_size, parameter_count);
    1091         834 :   FrameWriter frame_writer(this, output_frame, trace_scope_);
    1092             : 
    1093             :   // Arguments adaptor can not be topmost.
    1094         834 :   CHECK(frame_index < output_count_ - 1);
    1095         834 :   CHECK_NULL(output_[frame_index]);
    1096         834 :   output_[frame_index] = output_frame;
    1097             : 
    1098             :   // The top address of the frame is computed from the previous frame's top and
    1099             :   // this frame's size.
    1100             :   intptr_t top_address;
    1101         834 :   if (is_bottommost) {
    1102           0 :     top_address = caller_frame_top_ - output_frame_size;
    1103             :   } else {
    1104        2502 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1105             :   }
    1106             :   output_frame->SetTop(top_address);
    1107             : 
    1108             :   ReadOnlyRoots roots(isolate());
    1109             :   if (ShouldPadArguments(parameter_count)) {
    1110             :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1111             :   }
    1112             : 
    1113             :   // Compute the incoming parameter translation.
    1114        6590 :   for (int i = 0; i < parameter_count; ++i, ++value_iterator) {
    1115        2461 :     frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
    1116             :   }
    1117             : 
    1118             :   DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
    1119             :             frame_writer.top_offset());
    1120             : 
    1121             :   // Read caller's PC from the previous frame.
    1122             :   const intptr_t caller_pc =
    1123         834 :       is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
    1124         834 :   frame_writer.PushCallerPc(caller_pc);
    1125             : 
    1126             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1127             :   const intptr_t caller_fp =
    1128         834 :       is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
    1129         834 :   frame_writer.PushCallerFp(caller_fp);
    1130             : 
    1131         834 :   intptr_t fp_value = top_address + frame_writer.top_offset();
    1132             :   output_frame->SetFp(fp_value);
    1133             : 
    1134             :   if (FLAG_enable_embedded_constant_pool) {
    1135             :     // Read the caller's constant pool from the previous frame.
    1136             :     const intptr_t caller_cp =
    1137             :         is_bottommost ? caller_constant_pool_
    1138             :                       : output_[frame_index - 1]->GetConstantPool();
    1139             :     frame_writer.PushCallerConstantPool(caller_cp);
    1140             :   }
    1141             : 
    1142             :   // A marker value is used in place of the context.
    1143             :   intptr_t marker = StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR);
    1144         834 :   frame_writer.PushRawValue(marker, "context (adaptor sentinel)\n");
    1145             : 
    1146             :   // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
    1147         834 :   frame_writer.PushTranslatedValue(function_iterator, "function\n");
    1148             : 
    1149             :   // Number of incoming arguments.
    1150        1668 :   frame_writer.PushRawObject(Smi::FromInt(height - 1), "argc\n");
    1151             : 
    1152         834 :   frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1153             : 
    1154         834 :   CHECK_EQ(translated_frame->end(), value_iterator);
    1155             :   DCHECK_EQ(0, frame_writer.top_offset());
    1156             : 
    1157         834 :   Builtins* builtins = isolate_->builtins();
    1158             :   Code adaptor_trampoline =
    1159         834 :       builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
    1160             :   intptr_t pc_value = static_cast<intptr_t>(
    1161        1668 :       adaptor_trampoline->InstructionStart() +
    1162        1668 :       isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
    1163             :   output_frame->SetPc(pc_value);
    1164             :   if (FLAG_enable_embedded_constant_pool) {
    1165             :     intptr_t constant_pool_value =
    1166             :         static_cast<intptr_t>(adaptor_trampoline->constant_pool());
    1167             :     output_frame->SetConstantPool(constant_pool_value);
    1168             :   }
    1169         834 : }
    1170             : 
    1171        1068 : void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
    1172         534 :                                               int frame_index) {
    1173             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1174         534 :   bool is_topmost = (output_count_ - 1 == frame_index);
    1175             :   // The construct frame could become topmost only if we inlined a constructor
    1176             :   // call which does a tail call (otherwise the tail callee's frame would be
    1177             :   // the topmost one). So it could only be the DeoptimizeKind::kLazy case.
    1178         534 :   CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy);
    1179             : 
    1180         534 :   Builtins* builtins = isolate_->builtins();
    1181         534 :   Code construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
    1182             :   BailoutId bailout_id = translated_frame->node_id();
    1183         534 :   unsigned height = translated_frame->height();
    1184         534 :   unsigned parameter_count = height - 1;  // Exclude the context.
    1185         534 :   unsigned height_in_bytes = parameter_count * kSystemPointerSize;
    1186             : 
    1187             :   // If the construct frame appears to be topmost we should ensure that the
    1188             :   // value of result register is preserved during continuation execution.
    1189             :   // We do this here by "pushing" the result of the constructor function to the
    1190             :   // top of the reconstructed stack and popping it in
    1191             :   // {Builtins::kNotifyDeoptimized}.
    1192         534 :   if (is_topmost) {
    1193          40 :     height_in_bytes += kSystemPointerSize;
    1194          40 :     if (PadTopOfStackRegister()) height_in_bytes += kSystemPointerSize;
    1195             :   }
    1196             : 
    1197             :   if (ShouldPadArguments(parameter_count))
    1198             :     height_in_bytes += kSystemPointerSize;
    1199             : 
    1200             :   TranslatedFrame::iterator function_iterator = value_iterator++;
    1201         534 :   if (trace_scope_ != nullptr) {
    1202             :     PrintF(trace_scope_->file(),
    1203             :            "  translating construct stub => bailout_id=%d (%s), height=%d\n",
    1204             :            bailout_id.ToInt(),
    1205             :            bailout_id == BailoutId::ConstructStubCreate() ? "create" : "invoke",
    1206           0 :            height_in_bytes);
    1207             :   }
    1208             : 
    1209             :   unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
    1210         534 :   unsigned output_frame_size = height_in_bytes + fixed_frame_size;
    1211             : 
    1212             :   // Allocate and store the output frame description.
    1213             :   FrameDescription* output_frame = new (output_frame_size)
    1214         534 :       FrameDescription(output_frame_size, parameter_count);
    1215         534 :   FrameWriter frame_writer(this, output_frame, trace_scope_);
    1216             : 
    1217             :   // Construct stub can not be topmost.
    1218             :   DCHECK(frame_index > 0 && frame_index < output_count_);
    1219             :   DCHECK_NULL(output_[frame_index]);
    1220         534 :   output_[frame_index] = output_frame;
    1221             : 
    1222             :   // The top address of the frame is computed from the previous frame's top and
    1223             :   // this frame's size.
    1224             :   intptr_t top_address;
    1225        1602 :   top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1226             :   output_frame->SetTop(top_address);
    1227             : 
    1228             :   ReadOnlyRoots roots(isolate());
    1229             :   if (ShouldPadArguments(parameter_count)) {
    1230             :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1231             :   }
    1232             : 
    1233             :   // The allocated receiver of a construct stub frame is passed as the
    1234             :   // receiver parameter through the translation. It might be encoding
    1235             :   // a captured object, so we need save it for later.
    1236             :   TranslatedFrame::iterator receiver_iterator = value_iterator;
    1237             : 
    1238             :   // Compute the incoming parameter translation.
    1239        4322 :   for (unsigned i = 0; i < parameter_count; ++i, ++value_iterator) {
    1240        1627 :     frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
    1241             :   }
    1242             : 
    1243             :   DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
    1244             :             frame_writer.top_offset());
    1245             : 
    1246             :   // Read caller's PC from the previous frame.
    1247         534 :   const intptr_t caller_pc = output_[frame_index - 1]->GetPc();
    1248         534 :   frame_writer.PushCallerPc(caller_pc);
    1249             : 
    1250             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1251         534 :   const intptr_t caller_fp = output_[frame_index - 1]->GetFp();
    1252         534 :   frame_writer.PushCallerFp(caller_fp);
    1253             : 
    1254         534 :   intptr_t fp_value = top_address + frame_writer.top_offset();
    1255             :   output_frame->SetFp(fp_value);
    1256         534 :   if (is_topmost) {
    1257          40 :     Register fp_reg = JavaScriptFrame::fp_register();
    1258          40 :     output_frame->SetRegister(fp_reg.code(), fp_value);
    1259             :   }
    1260             : 
    1261             :   if (FLAG_enable_embedded_constant_pool) {
    1262             :     // Read the caller's constant pool from the previous frame.
    1263             :     const intptr_t caller_cp = output_[frame_index - 1]->GetConstantPool();
    1264             :     frame_writer.PushCallerConstantPool(caller_cp);
    1265             :   }
    1266             : 
    1267             :   // A marker value is used to mark the frame.
    1268             :   intptr_t marker = StackFrame::TypeToMarker(StackFrame::CONSTRUCT);
    1269         534 :   frame_writer.PushRawValue(marker, "context (construct stub sentinel)\n");
    1270             : 
    1271         534 :   frame_writer.PushTranslatedValue(value_iterator++, "context");
    1272             : 
    1273             :   // Number of incoming arguments.
    1274        1068 :   frame_writer.PushRawObject(Smi::FromInt(parameter_count - 1), "argc\n");
    1275             : 
    1276             :   // The constructor function was mentioned explicitly in the
    1277             :   // CONSTRUCT_STUB_FRAME.
    1278         534 :   frame_writer.PushTranslatedValue(function_iterator, "constructor function\n");
    1279             : 
    1280             :   // The deopt info contains the implicit receiver or the new target at the
    1281             :   // position of the receiver. Copy it to the top of stack, with the hole value
    1282             :   // as padding to maintain alignment.
    1283             : 
    1284         534 :   frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1285             : 
    1286         534 :   CHECK(bailout_id == BailoutId::ConstructStubCreate() ||
    1287             :         bailout_id == BailoutId::ConstructStubInvoke());
    1288             :   const char* debug_hint = bailout_id == BailoutId::ConstructStubCreate()
    1289             :                                ? "new target\n"
    1290         534 :                                : "allocated receiver\n";
    1291         534 :   frame_writer.PushTranslatedValue(receiver_iterator, debug_hint);
    1292             : 
    1293         534 :   if (is_topmost) {
    1294          40 :     if (PadTopOfStackRegister()) {
    1295           0 :       frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1296             :     }
    1297             :     // Ensure the result is restored back when we return to the stub.
    1298             :     Register result_reg = kReturnRegister0;
    1299          40 :     intptr_t result = input_->GetRegister(result_reg.code());
    1300          40 :     frame_writer.PushRawValue(result, "subcall result\n");
    1301             :   }
    1302             : 
    1303         534 :   CHECK_EQ(translated_frame->end(), value_iterator);
    1304         534 :   CHECK_EQ(0u, frame_writer.top_offset());
    1305             : 
    1306             :   // Compute this frame's PC.
    1307             :   DCHECK(bailout_id.IsValidForConstructStub());
    1308         534 :   Address start = construct_stub->InstructionStart();
    1309             :   int pc_offset =
    1310             :       bailout_id == BailoutId::ConstructStubCreate()
    1311         574 :           ? isolate_->heap()->construct_stub_create_deopt_pc_offset()->value()
    1312        1562 :           : isolate_->heap()->construct_stub_invoke_deopt_pc_offset()->value();
    1313         534 :   intptr_t pc_value = static_cast<intptr_t>(start + pc_offset);
    1314             :   output_frame->SetPc(pc_value);
    1315             : 
    1316             :   // Update constant pool.
    1317             :   if (FLAG_enable_embedded_constant_pool) {
    1318             :     intptr_t constant_pool_value =
    1319             :         static_cast<intptr_t>(construct_stub->constant_pool());
    1320             :     output_frame->SetConstantPool(constant_pool_value);
    1321             :     if (is_topmost) {
    1322             :       Register constant_pool_reg =
    1323             :           JavaScriptFrame::constant_pool_pointer_register();
    1324             :       output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
    1325             :     }
    1326             :   }
    1327             : 
    1328             :   // Clear the context register. The context might be a de-materialized object
    1329             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1330             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1331         534 :   if (is_topmost) {
    1332             :     intptr_t context_value = static_cast<intptr_t>(Smi::zero().ptr());
    1333          40 :     Register context_reg = JavaScriptFrame::context_register();
    1334          40 :     output_frame->SetRegister(context_reg.code(), context_value);
    1335             :   }
    1336             : 
    1337             :   // Set the continuation for the topmost frame.
    1338         534 :   if (is_topmost) {
    1339          40 :     Builtins* builtins = isolate_->builtins();
    1340             :     DCHECK_EQ(DeoptimizeKind::kLazy, deopt_kind_);
    1341          40 :     Code continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
    1342             :     output_frame->SetContinuation(
    1343          40 :         static_cast<intptr_t>(continuation->InstructionStart()));
    1344             :   }
    1345         534 : }
    1346             : 
    1347        1226 : bool Deoptimizer::BuiltinContinuationModeIsJavaScript(
    1348             :     BuiltinContinuationMode mode) {
    1349        1226 :   switch (mode) {
    1350             :     case BuiltinContinuationMode::STUB:
    1351             :       return false;
    1352             :     case BuiltinContinuationMode::JAVASCRIPT:
    1353             :     case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
    1354             :     case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
    1355        1194 :       return true;
    1356             :   }
    1357           0 :   UNREACHABLE();
    1358             : }
    1359             : 
    1360         613 : bool Deoptimizer::BuiltinContinuationModeIsWithCatch(
    1361             :     BuiltinContinuationMode mode) {
    1362         613 :   switch (mode) {
    1363             :     case BuiltinContinuationMode::STUB:
    1364             :     case BuiltinContinuationMode::JAVASCRIPT:
    1365             :       return false;
    1366             :     case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
    1367             :     case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
    1368          32 :       return true;
    1369             :   }
    1370           0 :   UNREACHABLE();
    1371             : }
    1372             : 
    1373         613 : StackFrame::Type Deoptimizer::BuiltinContinuationModeToFrameType(
    1374             :     BuiltinContinuationMode mode) {
    1375         613 :   switch (mode) {
    1376             :     case BuiltinContinuationMode::STUB:
    1377             :       return StackFrame::BUILTIN_CONTINUATION;
    1378             :     case BuiltinContinuationMode::JAVASCRIPT:
    1379         565 :       return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION;
    1380             :     case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
    1381          24 :       return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
    1382             :     case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
    1383           8 :       return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
    1384             :   }
    1385           0 :   UNREACHABLE();
    1386             : }
    1387             : 
    1388         613 : Builtins::Name Deoptimizer::TrampolineForBuiltinContinuation(
    1389             :     BuiltinContinuationMode mode, bool must_handle_result) {
    1390         613 :   switch (mode) {
    1391             :     case BuiltinContinuationMode::STUB:
    1392             :       return must_handle_result ? Builtins::kContinueToCodeStubBuiltinWithResult
    1393          16 :                                 : Builtins::kContinueToCodeStubBuiltin;
    1394             :     case BuiltinContinuationMode::JAVASCRIPT:
    1395             :     case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
    1396             :     case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
    1397             :       return must_handle_result
    1398             :                  ? Builtins::kContinueToJavaScriptBuiltinWithResult
    1399         597 :                  : Builtins::kContinueToJavaScriptBuiltin;
    1400             :   }
    1401           0 :   UNREACHABLE();
    1402             : }
    1403             : 
    1404             : // BuiltinContinuationFrames capture the machine state that is expected as input
    1405             : // to a builtin, including both input register values and stack parameters. When
    1406             : // the frame is reactivated (i.e. the frame below it returns), a
    1407             : // ContinueToBuiltin stub restores the register state from the frame and tail
    1408             : // calls to the actual target builtin, making it appear that the stub had been
    1409             : // directly called by the frame above it. The input values to populate the frame
    1410             : // are taken from the deopt's FrameState.
    1411             : //
    1412             : // Frame translation happens in two modes, EAGER and LAZY. In EAGER mode, all of
    1413             : // the parameters to the Builtin are explicitly specified in the TurboFan
    1414             : // FrameState node. In LAZY mode, there is always one fewer parameters specified
    1415             : // in the FrameState than expected by the Builtin. In that case, construction of
    1416             : // BuiltinContinuationFrame adds the final missing parameter during
    1417             : // deoptimization, and that parameter is always on the stack and contains the
    1418             : // value returned from the callee of the call site triggering the LAZY deopt
    1419             : // (e.g. rax on x64). This requires that continuation Builtins for LAZY deopts
    1420             : // must have at least one stack parameter.
    1421             : //
    1422             : //                TO
    1423             : //    |          ....           |
    1424             : //    +-------------------------+
    1425             : //    | arg padding (arch dept) |<- at most 1*kSystemPointerSize
    1426             : //    +-------------------------+
    1427             : //    |     builtin param 0     |<- FrameState input value n becomes
    1428             : //    +-------------------------+
    1429             : //    |           ...           |
    1430             : //    +-------------------------+
    1431             : //    |     builtin param m     |<- FrameState input value n+m-1, or in
    1432             : //    +-----needs-alignment-----+   the LAZY case, return LAZY result value
    1433             : //    | ContinueToBuiltin entry |
    1434             : //    +-------------------------+
    1435             : // |  |    saved frame (FP)     |
    1436             : // |  +=====needs=alignment=====+<- fpreg
    1437             : // |  |constant pool (if ool_cp)|
    1438             : // v  +-------------------------+
    1439             : //    |BUILTIN_CONTINUATION mark|
    1440             : //    +-------------------------+
    1441             : //    |  JSFunction (or zero)   |<- only if JavaScript builtin
    1442             : //    +-------------------------+
    1443             : //    |  frame height above FP  |
    1444             : //    +-------------------------+
    1445             : //    |         context         |<- this non-standard context slot contains
    1446             : //    +-------------------------+   the context, even for non-JS builtins.
    1447             : //    |     builtin address     |
    1448             : //    +-------------------------+
    1449             : //    | builtin input GPR reg0  |<- populated from deopt FrameState using
    1450             : //    +-------------------------+   the builtin's CallInterfaceDescriptor
    1451             : //    |          ...            |   to map a FrameState's 0..n-1 inputs to
    1452             : //    +-------------------------+   the builtin's n input register params.
    1453             : //    | builtin input GPR regn  |
    1454             : //    +-------------------------+
    1455             : //    | reg padding (arch dept) |
    1456             : //    +-----needs--alignment----+
    1457             : //    | res padding (arch dept) |<- only if {is_topmost}; result is pop'd by
    1458             : //    +-------------------------+<- kNotifyDeopt ASM stub and moved to acc
    1459             : //    |      result  value      |<- reg, as ContinueToBuiltin stub expects.
    1460             : //    +-----needs-alignment-----+<- spreg
    1461             : //
    1462         613 : void Deoptimizer::DoComputeBuiltinContinuation(
    1463         613 :     TranslatedFrame* translated_frame, int frame_index,
    1464        3065 :     BuiltinContinuationMode mode) {
    1465             :   TranslatedFrame::iterator value_iterator = translated_frame->begin();
    1466             : 
    1467             :   // The output frame must have room for all of the parameters that need to be
    1468             :   // passed to the builtin continuation.
    1469             :   const int height_in_words = translated_frame->height();
    1470             : 
    1471         613 :   BailoutId bailout_id = translated_frame->node_id();
    1472         613 :   Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
    1473         613 :   Code builtin = isolate()->builtins()->builtin(builtin_name);
    1474             :   Callable continuation_callable =
    1475         613 :       Builtins::CallableFor(isolate(), builtin_name);
    1476             :   CallInterfaceDescriptor continuation_descriptor =
    1477             :       continuation_callable.descriptor();
    1478             : 
    1479         613 :   const bool is_bottommost = (0 == frame_index);
    1480         613 :   const bool is_topmost = (output_count_ - 1 == frame_index);
    1481             :   const bool must_handle_result =
    1482         613 :       !is_topmost || deopt_kind_ == DeoptimizeKind::kLazy;
    1483             : 
    1484        8582 :   const RegisterConfiguration* config(RegisterConfiguration::Default());
    1485             :   const int allocatable_register_count =
    1486             :       config->num_allocatable_general_registers();
    1487             :   const int padding_slot_count =
    1488             :       BuiltinContinuationFrameConstants::PaddingSlotCount(
    1489         613 :           allocatable_register_count);
    1490             : 
    1491             :   const int register_parameter_count =
    1492             :       continuation_descriptor.GetRegisterParameterCount();
    1493             :   // Make sure to account for the context by removing it from the register
    1494             :   // parameter count.
    1495             :   const int translated_stack_parameters =
    1496         613 :       height_in_words - register_parameter_count - 1;
    1497             :   const int stack_param_count =
    1498        1226 :       translated_stack_parameters + (must_handle_result ? 1 : 0) +
    1499        1226 :       (BuiltinContinuationModeIsWithCatch(mode) ? 1 : 0);
    1500             :   const int stack_param_pad_count =
    1501             :       ShouldPadArguments(stack_param_count) ? 1 : 0;
    1502             : 
    1503             :   // If the builtins frame appears to be topmost we should ensure that the
    1504             :   // value of result register is preserved during continuation execution.
    1505             :   // We do this here by "pushing" the result of callback function to the
    1506             :   // top of the reconstructed stack and popping it in
    1507             :   // {Builtins::kNotifyDeoptimized}.
    1508             :   const int push_result_count =
    1509         613 :       is_topmost ? (PadTopOfStackRegister() ? 2 : 1) : 0;
    1510             : 
    1511             :   const unsigned output_frame_size =
    1512         613 :       kSystemPointerSize * (stack_param_count + stack_param_pad_count +
    1513         613 :                             allocatable_register_count + padding_slot_count +
    1514         613 :                             push_result_count) +
    1515         613 :       BuiltinContinuationFrameConstants::kFixedFrameSize;
    1516             : 
    1517             :   const unsigned output_frame_size_above_fp =
    1518         613 :       kSystemPointerSize * (allocatable_register_count + padding_slot_count +
    1519         613 :                             push_result_count) +
    1520             :       (BuiltinContinuationFrameConstants::kFixedFrameSize -
    1521             :        BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp);
    1522             : 
    1523             :   // Validate types of parameters. They must all be tagged except for argc for
    1524             :   // JS builtins.
    1525             :   bool has_argc = false;
    1526        2404 :   for (int i = 0; i < register_parameter_count; ++i) {
    1527             :     MachineType type = continuation_descriptor.GetParameterType(i);
    1528             :     int code = continuation_descriptor.GetRegisterParameter(i).code();
    1529             :     // Only tagged and int32 arguments are supported, and int32 only for the
    1530             :     // arguments count on JavaScript builtins.
    1531        1791 :     if (type == MachineType::Int32()) {
    1532         597 :       CHECK_EQ(code, kJavaScriptCallArgCountRegister.code());
    1533             :       has_argc = true;
    1534             :     } else {
    1535             :       // Any other argument must be a tagged value.
    1536        1194 :       CHECK(IsAnyTagged(type.representation()));
    1537             :     }
    1538             :   }
    1539         613 :   CHECK_EQ(BuiltinContinuationModeIsJavaScript(mode), has_argc);
    1540             : 
    1541         613 :   if (trace_scope_ != nullptr) {
    1542             :     PrintF(trace_scope_->file(),
    1543             :            "  translating BuiltinContinuation to %s,"
    1544             :            " register param count %d,"
    1545             :            " stack param count %d\n",
    1546             :            Builtins::name(builtin_name), register_parameter_count,
    1547           0 :            stack_param_count);
    1548             :   }
    1549             : 
    1550             :   FrameDescription* output_frame = new (output_frame_size)
    1551         613 :       FrameDescription(output_frame_size, stack_param_count);
    1552         613 :   output_[frame_index] = output_frame;
    1553         613 :   FrameWriter frame_writer(this, output_frame, trace_scope_);
    1554             : 
    1555             :   // The top address of the frame is computed from the previous frame's top and
    1556             :   // this frame's size.
    1557             :   intptr_t top_address;
    1558         613 :   if (is_bottommost) {
    1559           0 :     top_address = caller_frame_top_ - output_frame_size;
    1560             :   } else {
    1561        1839 :     top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
    1562             :   }
    1563             :   output_frame->SetTop(top_address);
    1564             : 
    1565             :   // Get the possible JSFunction for the case that this is a
    1566             :   // JavaScriptBuiltinContinuationFrame, which needs the JSFunction pointer
    1567             :   // like a normal JavaScriptFrame.
    1568        1226 :   const intptr_t maybe_function = value_iterator->GetRawValue()->ptr();
    1569             :   ++value_iterator;
    1570             : 
    1571             :   ReadOnlyRoots roots(isolate());
    1572             :   if (ShouldPadArguments(stack_param_count)) {
    1573             :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1574             :   }
    1575             : 
    1576        7054 :   for (int i = 0; i < translated_stack_parameters; ++i, ++value_iterator) {
    1577        2914 :     frame_writer.PushTranslatedValue(value_iterator, "stack parameter");
    1578             :   }
    1579             : 
    1580         613 :   switch (mode) {
    1581             :     case BuiltinContinuationMode::STUB:
    1582             :       break;
    1583             :     case BuiltinContinuationMode::JAVASCRIPT:
    1584             :       break;
    1585             :     case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH: {
    1586             :       frame_writer.PushRawObject(roots.the_hole_value(),
    1587          24 :                                  "placeholder for exception on lazy deopt\n");
    1588          24 :     } break;
    1589             :     case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION: {
    1590             :       intptr_t accumulator_value =
    1591           8 :           input_->GetRegister(kInterpreterAccumulatorRegister.code());
    1592             :       frame_writer.PushRawObject(Object(accumulator_value),
    1593          16 :                                  "exception (from accumulator)\n");
    1594           8 :     } break;
    1595             :   }
    1596             : 
    1597         613 :   if (must_handle_result) {
    1598             :     frame_writer.PushRawObject(roots.the_hole_value(),
    1599         436 :                                "placeholder for return result on lazy deopt\n");
    1600             :   }
    1601             : 
    1602             :   DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
    1603             :             frame_writer.top_offset());
    1604             : 
    1605             :   std::vector<TranslatedFrame::iterator> register_values;
    1606             :   int total_registers = config->num_general_registers();
    1607         613 :   register_values.resize(total_registers, {value_iterator});
    1608             : 
    1609        4808 :   for (int i = 0; i < register_parameter_count; ++i, ++value_iterator) {
    1610             :     int code = continuation_descriptor.GetRegisterParameter(i).code();
    1611        3582 :     register_values[code] = value_iterator;
    1612             :   }
    1613             : 
    1614             :   // The context register is always implicit in the CallInterfaceDescriptor but
    1615             :   // its register must be explicitly set when continuing to the builtin. Make
    1616             :   // sure that it's harvested from the translation and copied into the register
    1617             :   // set (it was automatically added at the end of the FrameState by the
    1618             :   // instruction selector).
    1619         613 :   Object context = value_iterator->GetRawValue();
    1620         613 :   const intptr_t value = context->ptr();
    1621             :   TranslatedFrame::iterator context_register_value = value_iterator++;
    1622         613 :   register_values[kContextRegister.code()] = context_register_value;
    1623             :   output_frame->SetContext(value);
    1624             :   output_frame->SetRegister(kContextRegister.code(), value);
    1625             : 
    1626             :   // Set caller's PC (JSFunction continuation).
    1627             :   const intptr_t caller_pc =
    1628         613 :       is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
    1629         613 :   frame_writer.PushCallerPc(caller_pc);
    1630             : 
    1631             :   // Read caller's FP from the previous frame, and set this frame's FP.
    1632             :   const intptr_t caller_fp =
    1633         613 :       is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
    1634         613 :   frame_writer.PushCallerFp(caller_fp);
    1635             : 
    1636         613 :   const intptr_t fp_value = top_address + frame_writer.top_offset();
    1637             :   output_frame->SetFp(fp_value);
    1638             : 
    1639             :   DCHECK_EQ(output_frame_size_above_fp, frame_writer.top_offset());
    1640             : 
    1641             :   if (FLAG_enable_embedded_constant_pool) {
    1642             :     // Read the caller's constant pool from the previous frame.
    1643             :     const intptr_t caller_cp =
    1644             :         is_bottommost ? caller_constant_pool_
    1645             :                       : output_[frame_index - 1]->GetConstantPool();
    1646             :     frame_writer.PushCallerConstantPool(caller_cp);
    1647             :   }
    1648             : 
    1649             :   // A marker value is used in place of the context.
    1650             :   const intptr_t marker =
    1651        1226 :       StackFrame::TypeToMarker(BuiltinContinuationModeToFrameType(mode));
    1652             :   frame_writer.PushRawValue(marker,
    1653         613 :                             "context (builtin continuation sentinel)\n");
    1654             : 
    1655         613 :   if (BuiltinContinuationModeIsJavaScript(mode)) {
    1656         597 :     frame_writer.PushRawValue(maybe_function, "JSFunction\n");
    1657             :   } else {
    1658          16 :     frame_writer.PushRawValue(0, "unused\n");
    1659             :   }
    1660             : 
    1661             :   // The delta from the SP to the FP; used to reconstruct SP in
    1662             :   // Isolate::UnwindAndFindHandler.
    1663             :   frame_writer.PushRawObject(Smi::FromInt(output_frame_size_above_fp),
    1664         613 :                              "frame height at deoptimization\n");
    1665             : 
    1666             :   // The context even if this is a stub contininuation frame. We can't use the
    1667             :   // usual context slot, because we must store the frame marker there.
    1668             :   frame_writer.PushTranslatedValue(context_register_value,
    1669         613 :                                    "builtin JavaScript context\n");
    1670             : 
    1671             :   // The builtin to continue to.
    1672         613 :   frame_writer.PushRawObject(builtin, "builtin address\n");
    1673             : 
    1674        7969 :   for (int i = 0; i < allocatable_register_count; ++i) {
    1675             :     int code = config->GetAllocatableGeneralCode(i);
    1676             :     ScopedVector<char> str(128);
    1677        7356 :     if (trace_scope_ != nullptr) {
    1678           0 :       if (BuiltinContinuationModeIsJavaScript(mode) &&
    1679             :           code == kJavaScriptCallArgCountRegister.code()) {
    1680             :         SNPrintF(
    1681             :             str,
    1682             :             "tagged argument count %s (will be untagged by continuation)\n",
    1683           0 :             RegisterName(Register::from_code(code)));
    1684             :       } else {
    1685             :         SNPrintF(str, "builtin register argument %s\n",
    1686           0 :                  RegisterName(Register::from_code(code)));
    1687             :       }
    1688             :     }
    1689             :     frame_writer.PushTranslatedValue(
    1690       14712 :         register_values[code], trace_scope_ != nullptr ? str.start() : "");
    1691             :   }
    1692             : 
    1693             :   // Some architectures must pad the stack frame with extra stack slots
    1694             :   // to ensure the stack frame is aligned.
    1695           0 :   for (int i = 0; i < padding_slot_count; ++i) {
    1696           0 :     frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1697             :   }
    1698             : 
    1699         613 :   if (is_topmost) {
    1700         219 :     if (PadTopOfStackRegister()) {
    1701           0 :       frame_writer.PushRawObject(roots.the_hole_value(), "padding\n");
    1702             :     }
    1703             :     // Ensure the result is restored back when we return to the stub.
    1704             : 
    1705         219 :     if (must_handle_result) {
    1706             :       Register result_reg = kReturnRegister0;
    1707             :       frame_writer.PushRawValue(input_->GetRegister(result_reg.code()),
    1708          84 :                                 "callback result\n");
    1709             :     } else {
    1710         177 :       frame_writer.PushRawObject(roots.undefined_value(), "callback result\n");
    1711             :     }
    1712             :   }
    1713             : 
    1714         613 :   CHECK_EQ(translated_frame->end(), value_iterator);
    1715         613 :   CHECK_EQ(0u, frame_writer.top_offset());
    1716             : 
    1717             :   // Clear the context register. The context might be a de-materialized object
    1718             :   // and will be materialized by {Runtime_NotifyDeoptimized}. For additional
    1719             :   // safety we use Smi(0) instead of the potential {arguments_marker} here.
    1720         613 :   if (is_topmost) {
    1721             :     intptr_t context_value = static_cast<intptr_t>(Smi::zero().ptr());
    1722         219 :     Register context_reg = JavaScriptFrame::context_register();
    1723         219 :     output_frame->SetRegister(context_reg.code(), context_value);
    1724             :   }
    1725             : 
    1726             :   // Ensure the frame pointer register points to the callee's frame. The builtin
    1727             :   // will build its own frame once we continue to it.
    1728         613 :   Register fp_reg = JavaScriptFrame::fp_register();
    1729         613 :   output_frame->SetRegister(fp_reg.code(), fp_value);
    1730             : 
    1731             :   Code continue_to_builtin = isolate()->builtins()->builtin(
    1732        1226 :       TrampolineForBuiltinContinuation(mode, must_handle_result));
    1733             :   output_frame->SetPc(
    1734         613 :       static_cast<intptr_t>(continue_to_builtin->InstructionStart()));
    1735             : 
    1736             :   Code continuation =
    1737         613 :       isolate()->builtins()->builtin(Builtins::kNotifyDeoptimized);
    1738             :   output_frame->SetContinuation(
    1739         613 :       static_cast<intptr_t>(continuation->InstructionStart()));
    1740         613 : }
    1741             : 
    1742       45171 : void Deoptimizer::MaterializeHeapObjects() {
    1743       45171 :   translated_state_.Prepare(static_cast<Address>(stack_fp_));
    1744       45171 :   if (FLAG_deopt_every_n_times > 0) {
    1745             :     // Doing a GC here will find problems with the deoptimized frames.
    1746             :     isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
    1747       45191 :                                         GarbageCollectionReason::kTesting);
    1748             :   }
    1749             : 
    1750      110909 :   for (auto& materialization : values_to_materialize_) {
    1751       20567 :     Handle<Object> value = materialization.value_->GetValue();
    1752             : 
    1753       20567 :     if (trace_scope_ != nullptr) {
    1754             :       PrintF("Materialization [" V8PRIxPTR_FMT "] <- " V8PRIxPTR_FMT " ;  ",
    1755             :              static_cast<intptr_t>(materialization.output_slot_address_),
    1756           0 :              value->ptr());
    1757           0 :       value->ShortPrint(trace_scope_->file());
    1758           0 :       PrintF(trace_scope_->file(), "\n");
    1759             :     }
    1760             : 
    1761             :     *(reinterpret_cast<Address*>(materialization.output_slot_address_)) =
    1762       41134 :         value->ptr();
    1763             :   }
    1764             : 
    1765             :   translated_state_.VerifyMaterializedObjects();
    1766             : 
    1767       45171 :   bool feedback_updated = translated_state_.DoUpdateFeedback();
    1768       45171 :   if (trace_scope_ != nullptr && feedback_updated) {
    1769           0 :     PrintF(trace_scope_->file(), "Feedback updated");
    1770             :     compiled_code_->PrintDeoptLocation(trace_scope_->file(),
    1771           0 :                                        " from deoptimization at ", from_);
    1772             :   }
    1773             : 
    1774             :   isolate_->materialized_object_store()->Remove(
    1775       90342 :       static_cast<Address>(stack_fp_));
    1776       45171 : }
    1777             : 
    1778      583999 : void Deoptimizer::QueueValueForMaterialization(
    1779             :     Address output_address, Object obj,
    1780             :     const TranslatedFrame::iterator& iterator) {
    1781     1167998 :   if (obj == ReadOnlyRoots(isolate_).arguments_marker()) {
    1782       61701 :     values_to_materialize_.push_back({output_address, iterator});
    1783             :   }
    1784      583999 : }
    1785             : 
    1786       90342 : unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize() const {
    1787             :   unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
    1788             :   // TODO(jkummerow): If {function_->IsSmi()} can indeed be true, then
    1789             :   // {function_} should not have type {JSFunction}.
    1790      180684 :   if (!function_->IsSmi()) {
    1791      180684 :     fixed_size += ComputeIncomingArgumentSize(function_->shared());
    1792             :   }
    1793       90342 :   return fixed_size;
    1794             : }
    1795             : 
    1796       45171 : unsigned Deoptimizer::ComputeInputFrameSize() const {
    1797             :   // The fp-to-sp delta already takes the context, constant pool pointer and the
    1798             :   // function into account so we have to avoid double counting them.
    1799       45171 :   unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
    1800       45171 :   unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
    1801       45171 :   if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
    1802             :     unsigned stack_slots = compiled_code_->stack_slots();
    1803             :     unsigned outgoing_size = 0;
    1804             :     //        ComputeOutgoingArgumentSize(compiled_code_, bailout_id_);
    1805       45171 :     CHECK_EQ(fixed_size_above_fp + (stack_slots * kSystemPointerSize) -
    1806             :                  CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
    1807             :              result);
    1808             :   }
    1809       45171 :   return result;
    1810             : }
    1811             : 
    1812             : // static
    1813           0 : unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo shared) {
    1814             :   // The fixed part of the frame consists of the return address, frame
    1815             :   // pointer, function, context, bytecode offset and all the incoming arguments.
    1816             :   return ComputeIncomingArgumentSize(shared) +
    1817       48322 :          InterpreterFrameConstants::kFixedFrameSize;
    1818             : }
    1819             : 
    1820             : // static
    1821           0 : unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo shared) {
    1822      138664 :   int parameter_slots = shared->internal_formal_parameter_count() + 1;
    1823             :   if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
    1824      138664 :   return parameter_slots * kSystemPointerSize;
    1825             : }
    1826             : 
    1827     1370193 : void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
    1828             :                                                    DeoptimizeKind kind) {
    1829     1370193 :   CHECK(kind == DeoptimizeKind::kEager || kind == DeoptimizeKind::kSoft ||
    1830             :         kind == DeoptimizeKind::kLazy);
    1831     1370193 :   DeoptimizerData* data = isolate->deoptimizer_data();
    1832     2696457 :   if (!data->deopt_entry_code(kind).is_null()) return;
    1833             : 
    1834             :   MacroAssembler masm(isolate, CodeObjectRequired::kYes,
    1835      131787 :                       NewAssemblerBuffer(16 * KB));
    1836             :   masm.set_emit_debug_code(false);
    1837       43929 :   GenerateDeoptimizationEntries(&masm, masm.isolate(), kind);
    1838       43929 :   CodeDesc desc;
    1839       43929 :   masm.GetCode(isolate, &desc);
    1840             :   DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
    1841             : 
    1842             :   // Allocate the code as immovable since the entry addresses will be used
    1843             :   // directly and there is no support for relocating them.
    1844             :   Handle<Code> code = isolate->factory()->NewCode(
    1845             :       desc, Code::STUB, Handle<Object>(), Builtins::kNoBuiltinId,
    1846       87858 :       MaybeHandle<ByteArray>(), MaybeHandle<DeoptimizationData>(), kImmovable);
    1847       43929 :   CHECK(isolate->heap()->IsImmovable(*code));
    1848             : 
    1849       43929 :   CHECK(data->deopt_entry_code(kind).is_null());
    1850             :   data->set_deopt_entry_code(kind, *code);
    1851             : }
    1852             : 
    1853      456730 : void Deoptimizer::EnsureCodeForDeoptimizationEntries(Isolate* isolate) {
    1854      456730 :   EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kEager);
    1855      456731 :   EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kLazy);
    1856      456731 :   EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kSoft);
    1857      456731 : }
    1858             : 
    1859       95474 : FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
    1860             :     : frame_size_(frame_size),
    1861             :       parameter_count_(parameter_count),
    1862             :       top_(kZapUint32),
    1863             :       pc_(kZapUint32),
    1864             :       fp_(kZapUint32),
    1865             :       context_(kZapUint32),
    1866      190948 :       constant_pool_(kZapUint32) {
    1867             :   // Zap all the registers.
    1868     1623058 :   for (int r = 0; r < Register::kNumRegisters; r++) {
    1869             :     // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
    1870             :     // isn't used before the next safepoint, the GC will try to scan it as a
    1871             :     // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
    1872             : #if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_ARM64)
    1873             :     // x18 is reserved as platform register on Windows arm64 platform
    1874             :     const int kPlatformRegister = 18;
    1875             :     if (r != kPlatformRegister) {
    1876             :       SetRegister(r, kZapUint32);
    1877             :     }
    1878             : #else
    1879     1527584 :     SetRegister(r, kZapUint32);
    1880             : #endif
    1881             :   }
    1882             : 
    1883             :   // Zap all the slots.
    1884     1254872 :   for (unsigned o = 0; o < frame_size; o += kSystemPointerSize) {
    1885             :     SetFrameSlot(o, kZapUint32);
    1886             :   }
    1887       95474 : }
    1888             : 
    1889   140119875 : void TranslationBuffer::Add(int32_t value) {
    1890             :   // This wouldn't handle kMinInt correctly if it ever encountered it.
    1891             :   DCHECK_NE(value, kMinInt);
    1892             :   // Encode the sign bit in the least significant bit.
    1893   140119875 :   bool is_negative = (value < 0);
    1894   140119875 :   uint32_t bits = (static_cast<uint32_t>(is_negative ? -value : value) << 1) |
    1895   140119875 :                   static_cast<uint32_t>(is_negative);
    1896             :   // Encode the individual bytes using the least significant bit of
    1897             :   // each byte to indicate whether or not more bytes follow.
    1898   144567209 :   do {
    1899   144567086 :     uint32_t next = bits >> 7;
    1900   144567086 :     contents_.push_back(((bits << 1) & 0xFF) | (next != 0));
    1901             :     bits = next;
    1902             :   } while (bits != 0);
    1903   140119998 : }
    1904             : 
    1905       43439 : TranslationIterator::TranslationIterator(ByteArray buffer, int index)
    1906     1439465 :     : buffer_(buffer), index_(index) {
    1907             :   DCHECK(index >= 0 && index < buffer->length());
    1908       43439 : }
    1909             : 
    1910    60225653 : int32_t TranslationIterator::Next() {
    1911             :   // Run through the bytes until we reach one with a least significant
    1912             :   // bit of zero (marks the end).
    1913             :   uint32_t bits = 0;
    1914      547559 :   for (int i = 0; true; i += 7) {
    1915             :     DCHECK(HasNext());
    1916    60773212 :     uint8_t next = buffer_->get(index_++);
    1917    60773212 :     bits |= (next >> 1) << i;
    1918    60773212 :     if ((next & 1) == 0) break;
    1919      547559 :   }
    1920             :   // The bits encode the sign in the least significant bit.
    1921    60225653 :   bool is_negative = (bits & 1) == 1;
    1922    60225653 :   int32_t result = bits >> 1;
    1923    60225653 :   return is_negative ? -result : result;
    1924             : }
    1925             : 
    1926     1396026 : bool TranslationIterator::HasNext() const { return index_ < buffer_->length(); }
    1927             : 
    1928      456571 : Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
    1929      456571 :   Handle<ByteArray> result = factory->NewByteArray(CurrentIndex(), TENURED);
    1930      456573 :   contents_.CopyTo(result->GetDataStartAddress());
    1931      456572 :   return result;
    1932             : }
    1933             : 
    1934        2100 : void Translation::BeginBuiltinContinuationFrame(BailoutId bailout_id,
    1935             :                                                 int literal_id,
    1936             :                                                 unsigned height) {
    1937        2100 :   buffer_->Add(BUILTIN_CONTINUATION_FRAME);
    1938        2100 :   buffer_->Add(bailout_id.ToInt());
    1939        2100 :   buffer_->Add(literal_id);
    1940        2100 :   buffer_->Add(height);
    1941        2100 : }
    1942             : 
    1943       11184 : void Translation::BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
    1944             :                                                           int literal_id,
    1945             :                                                           unsigned height) {
    1946       11184 :   buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME);
    1947       11184 :   buffer_->Add(bailout_id.ToInt());
    1948       11184 :   buffer_->Add(literal_id);
    1949       11184 :   buffer_->Add(height);
    1950       11184 : }
    1951             : 
    1952         267 : void Translation::BeginJavaScriptBuiltinContinuationWithCatchFrame(
    1953             :     BailoutId bailout_id, int literal_id, unsigned height) {
    1954         267 :   buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME);
    1955         267 :   buffer_->Add(bailout_id.ToInt());
    1956         267 :   buffer_->Add(literal_id);
    1957         267 :   buffer_->Add(height);
    1958         267 : }
    1959             : 
    1960       26155 : void Translation::BeginConstructStubFrame(BailoutId bailout_id, int literal_id,
    1961             :                                           unsigned height) {
    1962       26155 :   buffer_->Add(CONSTRUCT_STUB_FRAME);
    1963       26155 :   buffer_->Add(bailout_id.ToInt());
    1964       26155 :   buffer_->Add(literal_id);
    1965       26155 :   buffer_->Add(height);
    1966       26155 : }
    1967             : 
    1968             : 
    1969       83729 : void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
    1970       83729 :   buffer_->Add(ARGUMENTS_ADAPTOR_FRAME);
    1971       83729 :   buffer_->Add(literal_id);
    1972       83729 :   buffer_->Add(height);
    1973       83729 : }
    1974             : 
    1975     3823523 : void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
    1976             :                                         int literal_id, unsigned height,
    1977             :                                         int return_value_offset,
    1978             :                                         int return_value_count) {
    1979     3823523 :   buffer_->Add(INTERPRETED_FRAME);
    1980     3823528 :   buffer_->Add(bytecode_offset.ToInt());
    1981     3823532 :   buffer_->Add(literal_id);
    1982     3823533 :   buffer_->Add(height);
    1983     3823530 :   buffer_->Add(return_value_offset);
    1984     3823530 :   buffer_->Add(return_value_count);
    1985     3823532 : }
    1986             : 
    1987        6180 : void Translation::ArgumentsElements(CreateArgumentsType type) {
    1988        6180 :   buffer_->Add(ARGUMENTS_ELEMENTS);
    1989        6180 :   buffer_->Add(static_cast<uint8_t>(type));
    1990        6180 : }
    1991             : 
    1992        6500 : void Translation::ArgumentsLength(CreateArgumentsType type) {
    1993        6500 :   buffer_->Add(ARGUMENTS_LENGTH);
    1994        6500 :   buffer_->Add(static_cast<uint8_t>(type));
    1995        6500 : }
    1996             : 
    1997       98457 : void Translation::BeginCapturedObject(int length) {
    1998       98457 :   buffer_->Add(CAPTURED_OBJECT);
    1999       98457 :   buffer_->Add(length);
    2000       98457 : }
    2001             : 
    2002             : 
    2003       22779 : void Translation::DuplicateObject(int object_index) {
    2004       22779 :   buffer_->Add(DUPLICATED_OBJECT);
    2005       22779 :   buffer_->Add(object_index);
    2006       22779 : }
    2007             : 
    2008             : 
    2009      473999 : void Translation::StoreRegister(Register reg) {
    2010      473999 :   buffer_->Add(REGISTER);
    2011      474000 :   buffer_->Add(reg.code());
    2012      474002 : }
    2013             : 
    2014             : 
    2015       35569 : void Translation::StoreInt32Register(Register reg) {
    2016       35569 :   buffer_->Add(INT32_REGISTER);
    2017       35569 :   buffer_->Add(reg.code());
    2018       35569 : }
    2019             : 
    2020          14 : void Translation::StoreInt64Register(Register reg) {
    2021          14 :   buffer_->Add(INT64_REGISTER);
    2022          14 :   buffer_->Add(reg.code());
    2023          14 : }
    2024             : 
    2025        1603 : void Translation::StoreUint32Register(Register reg) {
    2026        1603 :   buffer_->Add(UINT32_REGISTER);
    2027        1603 :   buffer_->Add(reg.code());
    2028        1603 : }
    2029             : 
    2030             : 
    2031        3797 : void Translation::StoreBoolRegister(Register reg) {
    2032        3797 :   buffer_->Add(BOOL_REGISTER);
    2033        3797 :   buffer_->Add(reg.code());
    2034        3797 : }
    2035             : 
    2036         118 : void Translation::StoreFloatRegister(FloatRegister reg) {
    2037         118 :   buffer_->Add(FLOAT_REGISTER);
    2038         118 :   buffer_->Add(reg.code());
    2039         118 : }
    2040             : 
    2041       64182 : void Translation::StoreDoubleRegister(DoubleRegister reg) {
    2042       64182 :   buffer_->Add(DOUBLE_REGISTER);
    2043       64181 :   buffer_->Add(reg.code());
    2044       64183 : }
    2045             : 
    2046             : 
    2047    18829076 : void Translation::StoreStackSlot(int index) {
    2048    18829076 :   buffer_->Add(STACK_SLOT);
    2049    18829080 :   buffer_->Add(index);
    2050    18829079 : }
    2051             : 
    2052             : 
    2053      475418 : void Translation::StoreInt32StackSlot(int index) {
    2054      475418 :   buffer_->Add(INT32_STACK_SLOT);
    2055      475418 :   buffer_->Add(index);
    2056      475417 : }
    2057             : 
    2058         135 : void Translation::StoreInt64StackSlot(int index) {
    2059         135 :   buffer_->Add(INT64_STACK_SLOT);
    2060         135 :   buffer_->Add(index);
    2061         135 : }
    2062             : 
    2063       11119 : void Translation::StoreUint32StackSlot(int index) {
    2064       11119 :   buffer_->Add(UINT32_STACK_SLOT);
    2065       11119 :   buffer_->Add(index);
    2066       11119 : }
    2067             : 
    2068             : 
    2069       21554 : void Translation::StoreBoolStackSlot(int index) {
    2070       21554 :   buffer_->Add(BOOL_STACK_SLOT);
    2071       21554 :   buffer_->Add(index);
    2072       21554 : }
    2073             : 
    2074         897 : void Translation::StoreFloatStackSlot(int index) {
    2075         897 :   buffer_->Add(FLOAT_STACK_SLOT);
    2076         897 :   buffer_->Add(index);
    2077         897 : }
    2078             : 
    2079      251434 : void Translation::StoreDoubleStackSlot(int index) {
    2080      251434 :   buffer_->Add(DOUBLE_STACK_SLOT);
    2081      251435 :   buffer_->Add(index);
    2082      251434 : }
    2083             : 
    2084             : 
    2085    30886330 : void Translation::StoreLiteral(int literal_id) {
    2086    30886330 :   buffer_->Add(LITERAL);
    2087    30886311 :   buffer_->Add(literal_id);
    2088    30886331 : }
    2089             : 
    2090       38854 : void Translation::AddUpdateFeedback(int vector_literal, int slot) {
    2091       38854 :   buffer_->Add(UPDATE_FEEDBACK);
    2092       38854 :   buffer_->Add(vector_literal);
    2093       38854 :   buffer_->Add(slot);
    2094       38854 : }
    2095             : 
    2096     3597586 : void Translation::StoreJSFrameFunction() {
    2097             :   StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
    2098             :                   StandardFrameConstants::kFunctionOffset) /
    2099     3597586 :                  kSystemPointerSize);
    2100     3597591 : }
    2101             : 
    2102      211358 : int Translation::NumberOfOperandsFor(Opcode opcode) {
    2103      211358 :   switch (opcode) {
    2104             :     case DUPLICATED_OBJECT:
    2105             :     case ARGUMENTS_ELEMENTS:
    2106             :     case ARGUMENTS_LENGTH:
    2107             :     case CAPTURED_OBJECT:
    2108             :     case REGISTER:
    2109             :     case INT32_REGISTER:
    2110             :     case INT64_REGISTER:
    2111             :     case UINT32_REGISTER:
    2112             :     case BOOL_REGISTER:
    2113             :     case FLOAT_REGISTER:
    2114             :     case DOUBLE_REGISTER:
    2115             :     case STACK_SLOT:
    2116             :     case INT32_STACK_SLOT:
    2117             :     case INT64_STACK_SLOT:
    2118             :     case UINT32_STACK_SLOT:
    2119             :     case BOOL_STACK_SLOT:
    2120             :     case FLOAT_STACK_SLOT:
    2121             :     case DOUBLE_STACK_SLOT:
    2122             :     case LITERAL:
    2123             :       return 1;
    2124             :     case ARGUMENTS_ADAPTOR_FRAME:
    2125             :     case UPDATE_FEEDBACK:
    2126           0 :       return 2;
    2127             :     case BEGIN:
    2128             :     case CONSTRUCT_STUB_FRAME:
    2129             :     case BUILTIN_CONTINUATION_FRAME:
    2130             :     case JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
    2131             :     case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME:
    2132           0 :       return 3;
    2133             :     case INTERPRETED_FRAME:
    2134       55943 :       return 5;
    2135             :   }
    2136           0 :   FATAL("Unexpected translation type");
    2137             :   return -1;
    2138             : }
    2139             : 
    2140             : 
    2141             : #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
    2142             : 
    2143             : const char* Translation::StringFor(Opcode opcode) {
    2144             : #define TRANSLATION_OPCODE_CASE(item)   case item: return #item;
    2145             :   switch (opcode) {
    2146             :     TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
    2147             :   }
    2148             : #undef TRANSLATION_OPCODE_CASE
    2149             :   UNREACHABLE();
    2150             : }
    2151             : 
    2152             : #endif
    2153             : 
    2154             : 
    2155     1396420 : Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
    2156     1396195 :   int index = StackIdToIndex(fp);
    2157     1396195 :   if (index == -1) {
    2158             :     return Handle<FixedArray>::null();
    2159             :   }
    2160         225 :   Handle<FixedArray> array = GetStackEntries();
    2161         225 :   CHECK_GT(array->length(), index);
    2162         225 :   return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
    2163             : }
    2164             : 
    2165             : 
    2166         141 : void MaterializedObjectStore::Set(Address fp,
    2167             :                                   Handle<FixedArray> materialized_objects) {
    2168         141 :   int index = StackIdToIndex(fp);
    2169         141 :   if (index == -1) {
    2170         282 :     index = static_cast<int>(frame_fps_.size());
    2171         141 :     frame_fps_.push_back(fp);
    2172             :   }
    2173             : 
    2174         141 :   Handle<FixedArray> array = EnsureStackEntries(index + 1);
    2175         282 :   array->set(index, *materialized_objects);
    2176         141 : }
    2177             : 
    2178             : 
    2179     3101261 : bool MaterializedObjectStore::Remove(Address fp) {
    2180         141 :   auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
    2181     3100979 :   if (it == frame_fps_.end()) return false;
    2182         141 :   int index = static_cast<int>(std::distance(frame_fps_.begin(), it));
    2183             : 
    2184         141 :   frame_fps_.erase(it);
    2185         141 :   FixedArray array = isolate()->heap()->materialized_objects();
    2186             : 
    2187         141 :   CHECK_LT(index, array->length());
    2188         141 :   int fps_size = static_cast<int>(frame_fps_.size());
    2189         282 :   for (int i = index; i < fps_size; i++) {
    2190           0 :     array->set(i, array->get(i + 1));
    2191             :   }
    2192         141 :   array->set(fps_size, ReadOnlyRoots(isolate()).undefined_value());
    2193         141 :   return true;
    2194             : }
    2195             : 
    2196             : 
    2197     1396336 : int MaterializedObjectStore::StackIdToIndex(Address fp) {
    2198             :   auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
    2199             :   return it == frame_fps_.end()
    2200             :              ? -1
    2201     1396561 :              : static_cast<int>(std::distance(frame_fps_.begin(), it));
    2202             : }
    2203             : 
    2204             : 
    2205         366 : Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
    2206             :   return Handle<FixedArray>(isolate()->heap()->materialized_objects(),
    2207         732 :                             isolate());
    2208             : }
    2209             : 
    2210             : 
    2211         285 : Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(int length) {
    2212         141 :   Handle<FixedArray> array = GetStackEntries();
    2213         141 :   if (array->length() >= length) {
    2214          93 :     return array;
    2215             :   }
    2216             : 
    2217          48 :   int new_length = length > 10 ? length : 10;
    2218          48 :   if (new_length < 2 * array->length()) {
    2219           0 :     new_length = 2 * array->length();
    2220             :   }
    2221             : 
    2222             :   Handle<FixedArray> new_array =
    2223          48 :       isolate()->factory()->NewFixedArray(new_length, TENURED);
    2224          96 :   for (int i = 0; i < array->length(); i++) {
    2225           0 :     new_array->set(i, array->get(i));
    2226             :   }
    2227          48 :   HeapObject undefined_value = ReadOnlyRoots(isolate()).undefined_value();
    2228          96 :   for (int i = array->length(); i < length; i++) {
    2229          48 :     new_array->set(i, undefined_value);
    2230             :   }
    2231          48 :   isolate()->heap()->SetRootMaterializedObjects(*new_array);
    2232          48 :   return new_array;
    2233             : }
    2234             : 
    2235             : namespace {
    2236             : 
    2237      181399 : Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
    2238             :                                    Isolate* isolate) {
    2239      362798 :   if (it->GetRawValue() == ReadOnlyRoots(isolate).arguments_marker()) {
    2240       21261 :     if (!it->IsMaterializableByDebugger()) {
    2241         236 :       return isolate->factory()->optimized_out();
    2242             :     }
    2243             :   }
    2244      181163 :   return it->GetValue();
    2245             : }
    2246             : 
    2247             : }  // namespace
    2248             : 
    2249       24920 : DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
    2250             :                                            TranslatedState::iterator frame_it,
    2251             :                                            Isolate* isolate) {
    2252             :   int parameter_count =
    2253       24920 :       frame_it->shared_info()->internal_formal_parameter_count();
    2254             :   TranslatedFrame::iterator stack_it = frame_it->begin();
    2255             : 
    2256             :   // Get the function. Note that this might materialize the function.
    2257             :   // In case the debugger mutates this value, we should deoptimize
    2258             :   // the function and remember the value in the materialized value store.
    2259       24920 :   function_ = Handle<JSFunction>::cast(stack_it->GetValue());
    2260       24920 :   stack_it++;  // Skip the function.
    2261       24920 :   stack_it++;  // Skip the receiver.
    2262             : 
    2263             :   DCHECK_EQ(TranslatedFrame::kInterpretedFunction, frame_it->kind());
    2264             :   source_position_ = Deoptimizer::ComputeSourcePositionFromBytecodeArray(
    2265       24920 :       *frame_it->shared_info(), frame_it->node_id());
    2266             : 
    2267             :   DCHECK_EQ(parameter_count,
    2268             :             function_->shared()->internal_formal_parameter_count());
    2269             : 
    2270       24920 :   parameters_.resize(static_cast<size_t>(parameter_count));
    2271       66185 :   for (int i = 0; i < parameter_count; i++) {
    2272       41265 :     Handle<Object> parameter = GetValueForDebugger(stack_it, isolate);
    2273             :     SetParameter(i, parameter);
    2274       41265 :     stack_it++;
    2275             :   }
    2276             : 
    2277             :   // Get the context.
    2278       24920 :   context_ = GetValueForDebugger(stack_it, isolate);
    2279       24920 :   stack_it++;
    2280             : 
    2281             :   // Get the expression stack.
    2282       24920 :   int stack_height = frame_it->height();
    2283       24920 :   if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
    2284             :     // For interpreter frames, we should not count the accumulator.
    2285             :     // TODO(jarin): Clean up the indexing in translated frames.
    2286       24920 :     stack_height--;
    2287             :   }
    2288       24920 :   expression_stack_.resize(static_cast<size_t>(stack_height));
    2289      140134 :   for (int i = 0; i < stack_height; i++) {
    2290      115214 :     Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
    2291             :     SetExpression(i, expression);
    2292      115214 :     stack_it++;
    2293             :   }
    2294             : 
    2295             :   // For interpreter frame, skip the accumulator.
    2296       24920 :   if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
    2297       24920 :     stack_it++;
    2298             :   }
    2299       24920 :   CHECK(stack_it == frame_it->end());
    2300       24920 : }
    2301             : 
    2302         247 : Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code code, Address pc) {
    2303         247 :   CHECK(code->InstructionStart() <= pc && pc <= code->InstructionEnd());
    2304             :   SourcePosition last_position = SourcePosition::Unknown();
    2305             :   DeoptimizeReason last_reason = DeoptimizeReason::kUnknown;
    2306             :   int last_deopt_id = kNoDeoptimizationId;
    2307             :   int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
    2308             :              RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
    2309             :              RelocInfo::ModeMask(RelocInfo::DEOPT_SCRIPT_OFFSET) |
    2310             :              RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID);
    2311        2068 :   for (RelocIterator it(code, mask); !it.done(); it.next()) {
    2312        5710 :     RelocInfo* info = it.rinfo();
    2313        2068 :     if (info->pc() >= pc) break;
    2314        1821 :     if (info->rmode() == RelocInfo::DEOPT_SCRIPT_OFFSET) {
    2315         607 :       int script_offset = static_cast<int>(info->data());
    2316         607 :       it.next();
    2317             :       DCHECK(it.rinfo()->rmode() == RelocInfo::DEOPT_INLINING_ID);
    2318         607 :       int inlining_id = static_cast<int>(it.rinfo()->data());
    2319             :       last_position = SourcePosition(script_offset, inlining_id);
    2320        1214 :     } else if (info->rmode() == RelocInfo::DEOPT_ID) {
    2321         607 :       last_deopt_id = static_cast<int>(info->data());
    2322         607 :     } else if (info->rmode() == RelocInfo::DEOPT_REASON) {
    2323         607 :       last_reason = static_cast<DeoptimizeReason>(info->data());
    2324             :     }
    2325             :   }
    2326         247 :   return DeoptInfo(last_position, last_reason, last_deopt_id);
    2327             : }
    2328             : 
    2329             : 
    2330             : // static
    2331       24920 : int Deoptimizer::ComputeSourcePositionFromBytecodeArray(
    2332             :     SharedFunctionInfo shared, BailoutId node_id) {
    2333             :   DCHECK(shared->HasBytecodeArray());
    2334       49840 :   return AbstractCode::cast(shared->GetBytecodeArray())
    2335       49840 :       ->SourcePosition(node_id.ToInt());
    2336             : }
    2337             : 
    2338             : // static
    2339           0 : TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
    2340             :                                                    int length,
    2341             :                                                    int object_index) {
    2342             :   TranslatedValue slot(container, kCapturedObject);
    2343      152718 :   slot.materialization_info_ = {object_index, length};
    2344           0 :   return slot;
    2345             : }
    2346             : 
    2347             : 
    2348             : // static
    2349           0 : TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
    2350             :                                                     int id) {
    2351             :   TranslatedValue slot(container, kDuplicatedObject);
    2352       83150 :   slot.materialization_info_ = {id, -1};
    2353           0 :   return slot;
    2354             : }
    2355             : 
    2356             : 
    2357             : // static
    2358           0 : TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
    2359             :                                           Float32 value) {
    2360             :   TranslatedValue slot(container, kFloat);
    2361         288 :   slot.float_value_ = value;
    2362           0 :   return slot;
    2363             : }
    2364             : 
    2365             : // static
    2366           0 : TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
    2367             :                                            Float64 value) {
    2368             :   TranslatedValue slot(container, kDouble);
    2369      521488 :   slot.double_value_ = value;
    2370           0 :   return slot;
    2371             : }
    2372             : 
    2373             : 
    2374             : // static
    2375           0 : TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
    2376             :                                           int32_t value) {
    2377             :   TranslatedValue slot(container, kInt32);
    2378      316916 :   slot.int32_value_ = value;
    2379           0 :   return slot;
    2380             : }
    2381             : 
    2382             : // static
    2383           0 : TranslatedValue TranslatedValue::NewInt64(TranslatedState* container,
    2384             :                                           int64_t value) {
    2385             :   TranslatedValue slot(container, kInt64);
    2386           9 :   slot.int64_value_ = value;
    2387           0 :   return slot;
    2388             : }
    2389             : 
    2390             : // static
    2391           0 : TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
    2392             :                                            uint32_t value) {
    2393             :   TranslatedValue slot(container, kUInt32);
    2394       50145 :   slot.uint32_value_ = value;
    2395           0 :   return slot;
    2396             : }
    2397             : 
    2398             : 
    2399             : // static
    2400           0 : TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
    2401             :                                          uint32_t value) {
    2402             :   TranslatedValue slot(container, kBoolBit);
    2403         438 :   slot.uint32_value_ = value;
    2404           0 :   return slot;
    2405             : }
    2406             : 
    2407             : 
    2408             : // static
    2409           0 : TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
    2410             :                                            Object literal) {
    2411             :   TranslatedValue slot(container, kTagged);
    2412    20054528 :   slot.raw_literal_ = literal;
    2413           0 :   return slot;
    2414             : }
    2415             : 
    2416             : // static
    2417           0 : TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
    2418           0 :   return TranslatedValue(container, kInvalid);
    2419             : }
    2420             : 
    2421             : 
    2422    20196733 : Isolate* TranslatedValue::isolate() const { return container_->isolate(); }
    2423             : 
    2424           0 : Object TranslatedValue::raw_literal() const {
    2425             :   DCHECK_EQ(kTagged, kind());
    2426    20664905 :   return raw_literal_;
    2427             : }
    2428             : 
    2429           0 : int32_t TranslatedValue::int32_value() const {
    2430             :   DCHECK_EQ(kInt32, kind());
    2431       27043 :   return int32_value_;
    2432             : }
    2433             : 
    2434           0 : int64_t TranslatedValue::int64_value() const {
    2435             :   DCHECK_EQ(kInt64, kind());
    2436           9 :   return int64_value_;
    2437             : }
    2438             : 
    2439           0 : uint32_t TranslatedValue::uint32_value() const {
    2440             :   DCHECK(kind() == kUInt32 || kind() == kBoolBit);
    2441         175 :   return uint32_value_;
    2442             : }
    2443             : 
    2444           0 : Float32 TranslatedValue::float_value() const {
    2445             :   DCHECK_EQ(kFloat, kind());
    2446         280 :   return float_value_;
    2447             : }
    2448             : 
    2449           0 : Float64 TranslatedValue::double_value() const {
    2450             :   DCHECK_EQ(kDouble, kind());
    2451       23813 :   return double_value_;
    2452             : }
    2453             : 
    2454             : 
    2455           0 : int TranslatedValue::object_length() const {
    2456             :   DCHECK_EQ(kind(), kCapturedObject);
    2457     1911425 :   return materialization_info_.length_;
    2458             : }
    2459             : 
    2460             : 
    2461           0 : int TranslatedValue::object_index() const {
    2462             :   DCHECK(kind() == kCapturedObject || kind() == kDuplicatedObject);
    2463      151240 :   return materialization_info_.id_;
    2464             : }
    2465             : 
    2466     1557951 : Object TranslatedValue::GetRawValue() const {
    2467             :   // If we have a value, return it.
    2468      854070 :   if (materialization_state() == kFinished) {
    2469             :     return *storage_;
    2470             :   }
    2471             : 
    2472             :   // Otherwise, do a best effort to get the value without allocation.
    2473      703881 :   switch (kind()) {
    2474             :     case kTagged:
    2475             :       return raw_literal();
    2476             : 
    2477             :     case kInt32: {
    2478             :       bool is_smi = Smi::IsValid(int32_value());
    2479             :       if (is_smi) {
    2480       27043 :         return Smi::FromInt(int32_value());
    2481             :       }
    2482             :       break;
    2483             :     }
    2484             : 
    2485             :     case kInt64: {
    2486           9 :       bool is_smi = (int64_value() >= static_cast<int64_t>(Smi::kMinValue) &&
    2487             :                      int64_value() <= static_cast<int64_t>(Smi::kMaxValue));
    2488           9 :       if (is_smi) {
    2489           9 :         return Smi::FromIntptr(static_cast<intptr_t>(int64_value()));
    2490             :       }
    2491             :       break;
    2492             :     }
    2493             : 
    2494             :     case kUInt32: {
    2495          93 :       bool is_smi = (uint32_value() <= static_cast<uintptr_t>(Smi::kMaxValue));
    2496          93 :       if (is_smi) {
    2497          79 :         return Smi::FromInt(static_cast<int32_t>(uint32_value()));
    2498             :       }
    2499             :       break;
    2500             :     }
    2501             : 
    2502             :     case kBoolBit: {
    2503          75 :       if (uint32_value() == 0) {
    2504          58 :         return ReadOnlyRoots(isolate()).false_value();
    2505             :       } else {
    2506          17 :         CHECK_EQ(1U, uint32_value());
    2507          17 :         return ReadOnlyRoots(isolate()).true_value();
    2508             :       }
    2509             :     }
    2510             : 
    2511             :     default:
    2512             :       break;
    2513             :   }
    2514             : 
    2515             :   // If we could not get the value without allocation, return the arguments
    2516             :   // marker.
    2517       66298 :   return ReadOnlyRoots(isolate()).arguments_marker();
    2518             : }
    2519             : 
    2520           0 : void TranslatedValue::set_initialized_storage(Handle<Object> storage) {
    2521             :   DCHECK_EQ(kUninitialized, materialization_state());
    2522    20092753 :   storage_ = storage;
    2523    20092753 :   materialization_state_ = kFinished;
    2524           0 : }
    2525             : 
    2526     3649226 : Handle<Object> TranslatedValue::GetValue() {
    2527             :   // If we already have a value, then get it.
    2528     3564847 :   if (materialization_state() == kFinished) return storage_;
    2529             : 
    2530             :   // Otherwise we have to materialize.
    2531       84379 :   switch (kind()) {
    2532             :     case TranslatedValue::kTagged:
    2533             :     case TranslatedValue::kInt32:
    2534             :     case TranslatedValue::kInt64:
    2535             :     case TranslatedValue::kUInt32:
    2536             :     case TranslatedValue::kBoolBit:
    2537             :     case TranslatedValue::kFloat:
    2538             :     case TranslatedValue::kDouble: {
    2539       37338 :       MaterializeSimple();
    2540       37338 :       return storage_;
    2541             :     }
    2542             : 
    2543             :     case TranslatedValue::kCapturedObject:
    2544             :     case TranslatedValue::kDuplicatedObject: {
    2545             :       // We need to materialize the object (or possibly even object graphs).
    2546             :       // To make the object verifier happy, we materialize in two steps.
    2547             : 
    2548             :       // 1. Allocate storage for reachable objects. This makes sure that for
    2549             :       //    each object we have allocated space on heap. The space will be
    2550             :       //    a byte array that will be later initialized, or a fully
    2551             :       //    initialized object if it is safe to allocate one that will
    2552             :       //    pass the verifier.
    2553       47041 :       container_->EnsureObjectAllocatedAt(this);
    2554             : 
    2555             :       // 2. Initialize the objects. If we have allocated only byte arrays
    2556             :       //    for some objects, we now overwrite the byte arrays with the
    2557             :       //    correct object fields. Note that this phase does not allocate
    2558             :       //    any new objects, so it does not trigger the object verifier.
    2559       47041 :       return container_->InitializeObjectAt(this);
    2560             :     }
    2561             : 
    2562             :     case TranslatedValue::kInvalid:
    2563           0 :       FATAL("unexpected case");
    2564             :       return Handle<Object>::null();
    2565             :   }
    2566             : 
    2567           0 :   FATAL("internal error: value missing");
    2568             :   return Handle<Object>::null();
    2569             : }
    2570             : 
    2571      718187 : void TranslatedValue::MaterializeSimple() {
    2572             :   // If we already have materialized, return.
    2573     1388174 :   if (materialization_state() == kFinished) return;
    2574             : 
    2575       37916 :   Object raw_value = GetRawValue();
    2576       37916 :   if (raw_value != ReadOnlyRoots(isolate()).arguments_marker()) {
    2577             :     // We can get the value without allocation, just return it here.
    2578             :     set_initialized_storage(Handle<Object>(raw_value, isolate()));
    2579       13816 :     return;
    2580             :   }
    2581             : 
    2582       24100 :   switch (kind()) {
    2583             :     case kInt32:
    2584             :       set_initialized_storage(
    2585           0 :           Handle<Object>(isolate()->factory()->NewNumber(int32_value())));
    2586             :       return;
    2587             : 
    2588             :     case kInt64:
    2589             :       set_initialized_storage(Handle<Object>(
    2590           0 :           isolate()->factory()->NewNumber(static_cast<double>(int64_value()))));
    2591             :       return;
    2592             : 
    2593             :     case kUInt32:
    2594             :       set_initialized_storage(
    2595          14 :           Handle<Object>(isolate()->factory()->NewNumber(uint32_value())));
    2596             :       return;
    2597             : 
    2598             :     case kFloat: {
    2599         280 :       double scalar_value = float_value().get_scalar();
    2600             :       set_initialized_storage(
    2601         280 :           Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
    2602             :       return;
    2603             :     }
    2604             : 
    2605             :     case kDouble: {
    2606       23813 :       double scalar_value = double_value().get_scalar();
    2607             :       set_initialized_storage(
    2608       23813 :           Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
    2609             :       return;
    2610             :     }
    2611             : 
    2612             :     case kCapturedObject:
    2613             :     case kDuplicatedObject:
    2614             :     case kInvalid:
    2615             :     case kTagged:
    2616             :     case kBoolBit:
    2617           0 :       FATAL("internal error: unexpected materialization.");
    2618             :       break;
    2619             :   }
    2620             : }
    2621             : 
    2622             : 
    2623       10841 : bool TranslatedValue::IsMaterializedObject() const {
    2624       10841 :   switch (kind()) {
    2625             :     case kCapturedObject:
    2626             :     case kDuplicatedObject:
    2627             :       return true;
    2628             :     default:
    2629        9907 :       return false;
    2630             :   }
    2631             : }
    2632             : 
    2633       21261 : bool TranslatedValue::IsMaterializableByDebugger() const {
    2634             :   // At the moment, we only allow materialization of doubles.
    2635           0 :   return (kind() == kDouble);
    2636             : }
    2637             : 
    2638    27144204 : int TranslatedValue::GetChildrenCount() const {
    2639    27192291 :   if (kind() == kCapturedObject) {
    2640           0 :     return object_length();
    2641             :   } else {
    2642             :     return 0;
    2643             :   }
    2644             : }
    2645             : 
    2646           0 : uint64_t TranslatedState::GetUInt64Slot(Address fp, int slot_offset) {
    2647             : #if V8_TARGET_ARCH_32_BIT
    2648             :   return ReadUnalignedValue<uint64_t>(fp + slot_offset);
    2649             : #else
    2650     1042146 :   return Memory<uint64_t>(fp + slot_offset);
    2651             : #endif
    2652             : }
    2653             : 
    2654           0 : uint32_t TranslatedState::GetUInt32Slot(Address fp, int slot_offset) {
    2655      366241 :   Address address = fp + slot_offset;
    2656             : #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT
    2657             :   return Memory<uint32_t>(address + kIntSize);
    2658             : #else
    2659      366241 :   return Memory<uint32_t>(address);
    2660             : #endif
    2661             : }
    2662             : 
    2663           0 : Float32 TranslatedState::GetFloatSlot(Address fp, int slot_offset) {
    2664             : #if !V8_TARGET_ARCH_S390X && !V8_TARGET_ARCH_PPC64
    2665           0 :   return Float32::FromBits(GetUInt32Slot(fp, slot_offset));
    2666             : #else
    2667             :   return Float32::FromBits(Memory<uint32_t>(fp + slot_offset));
    2668             : #endif
    2669             : }
    2670             : 
    2671           0 : Float64 TranslatedState::GetDoubleSlot(Address fp, int slot_offset) {
    2672           0 :   return Float64::FromBits(GetUInt64Slot(fp, slot_offset));
    2673             : }
    2674             : 
    2675    21179680 : void TranslatedValue::Handlify() {
    2676    21179680 :   if (kind() == kTagged) {
    2677             :     set_initialized_storage(Handle<Object>(raw_literal(), isolate()));
    2678    20054528 :     raw_literal_ = Object();
    2679             :   }
    2680    21179680 : }
    2681             : 
    2682           0 : TranslatedFrame TranslatedFrame::InterpretedFrame(
    2683             :     BailoutId bytecode_offset, SharedFunctionInfo shared_info, int height,
    2684             :     int return_value_offset, int return_value_count) {
    2685             :   TranslatedFrame frame(kInterpretedFunction, shared_info, height,
    2686             :                         return_value_offset, return_value_count);
    2687     1750608 :   frame.node_id_ = bytecode_offset;
    2688           0 :   return frame;
    2689             : }
    2690             : 
    2691           0 : TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
    2692             :     SharedFunctionInfo shared_info, int height) {
    2693           0 :   return TranslatedFrame(kArgumentsAdaptor, shared_info, height);
    2694             : }
    2695             : 
    2696           0 : TranslatedFrame TranslatedFrame::ConstructStubFrame(
    2697             :     BailoutId bailout_id, SharedFunctionInfo shared_info, int height) {
    2698             :   TranslatedFrame frame(kConstructStub, shared_info, height);
    2699       40117 :   frame.node_id_ = bailout_id;
    2700           0 :   return frame;
    2701             : }
    2702             : 
    2703           0 : TranslatedFrame TranslatedFrame::BuiltinContinuationFrame(
    2704             :     BailoutId bailout_id, SharedFunctionInfo shared_info, int height) {
    2705             :   TranslatedFrame frame(kBuiltinContinuation, shared_info, height);
    2706       42231 :   frame.node_id_ = bailout_id;
    2707           0 :   return frame;
    2708             : }
    2709             : 
    2710           0 : TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationFrame(
    2711             :     BailoutId bailout_id, SharedFunctionInfo shared_info, int height) {
    2712             :   TranslatedFrame frame(kJavaScriptBuiltinContinuation, shared_info, height);
    2713        2066 :   frame.node_id_ = bailout_id;
    2714           0 :   return frame;
    2715             : }
    2716             : 
    2717           0 : TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
    2718             :     BailoutId bailout_id, SharedFunctionInfo shared_info, int height) {
    2719             :   TranslatedFrame frame(kJavaScriptBuiltinContinuationWithCatch, shared_info,
    2720             :                         height);
    2721          82 :   frame.node_id_ = bailout_id;
    2722           0 :   return frame;
    2723             : }
    2724             : 
    2725     1971282 : int TranslatedFrame::GetValueCount() {
    2726     1971282 :   switch (kind()) {
    2727             :     case kInterpretedFunction: {
    2728             :       int parameter_count =
    2729     1753008 :           raw_shared_info_->internal_formal_parameter_count() + 1;
    2730             :       // + 2 for function and context.
    2731     1753008 :       return height_ + parameter_count + 2;
    2732             :     }
    2733             : 
    2734             :     case kArgumentsAdaptor:
    2735             :     case kConstructStub:
    2736             :     case kBuiltinContinuation:
    2737             :     case kJavaScriptBuiltinContinuation:
    2738             :     case kJavaScriptBuiltinContinuationWithCatch:
    2739      218274 :       return 1 + height_;
    2740             : 
    2741             :     case kInvalid:
    2742           0 :       UNREACHABLE();
    2743             :       break;
    2744             :   }
    2745           0 :   UNREACHABLE();
    2746             : }
    2747             : 
    2748             : 
    2749     1968882 : void TranslatedFrame::Handlify() {
    2750     1968882 :   if (!raw_shared_info_.is_null()) {
    2751             :     shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_,
    2752     1968882 :                                               raw_shared_info_->GetIsolate());
    2753     1968882 :     raw_shared_info_ = SharedFunctionInfo();
    2754             :   }
    2755    23148562 :   for (auto& value : values_) {
    2756    21179680 :     value.Handlify();
    2757             :   }
    2758     1968882 : }
    2759             : 
    2760     1968882 : TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
    2761             :     TranslationIterator* iterator, FixedArray literal_array, Address fp,
    2762             :     FILE* trace_file) {
    2763             :   Translation::Opcode opcode =
    2764     1968882 :       static_cast<Translation::Opcode>(iterator->Next());
    2765     1968882 :   switch (opcode) {
    2766             :     case Translation::INTERPRETED_FRAME: {
    2767     1750608 :       BailoutId bytecode_offset = BailoutId(iterator->Next());
    2768             :       SharedFunctionInfo shared_info =
    2769     3501216 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2770     1750608 :       int height = iterator->Next();
    2771     1750608 :       int return_value_offset = iterator->Next();
    2772     1750608 :       int return_value_count = iterator->Next();
    2773     1750608 :       if (trace_file != nullptr) {
    2774         240 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2775         240 :         PrintF(trace_file, "  reading input frame %s", name.get());
    2776         240 :         int arg_count = shared_info->internal_formal_parameter_count() + 1;
    2777             :         PrintF(trace_file,
    2778             :                " => bytecode_offset=%d, args=%d, height=%d, retval=%i(#%i); "
    2779             :                "inputs:\n",
    2780             :                bytecode_offset.ToInt(), arg_count, height, return_value_offset,
    2781         240 :                return_value_count);
    2782             :       }
    2783             :       return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
    2784             :                                                height, return_value_offset,
    2785             :                                                return_value_count);
    2786             :     }
    2787             : 
    2788             :     case Translation::ARGUMENTS_ADAPTOR_FRAME: {
    2789             :       SharedFunctionInfo shared_info =
    2790      267556 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2791      133778 :       int height = iterator->Next();
    2792      133778 :       if (trace_file != nullptr) {
    2793           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2794           0 :         PrintF(trace_file, "  reading arguments adaptor frame %s", name.get());
    2795           0 :         PrintF(trace_file, " => height=%d; inputs:\n", height);
    2796             :       }
    2797             :       return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
    2798             :     }
    2799             : 
    2800             :     case Translation::CONSTRUCT_STUB_FRAME: {
    2801       40117 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2802             :       SharedFunctionInfo shared_info =
    2803       80234 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2804       40117 :       int height = iterator->Next();
    2805       40117 :       if (trace_file != nullptr) {
    2806           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2807           0 :         PrintF(trace_file, "  reading construct stub frame %s", name.get());
    2808             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2809           0 :                bailout_id.ToInt(), height);
    2810             :       }
    2811             :       return TranslatedFrame::ConstructStubFrame(bailout_id, shared_info,
    2812             :                                                  height);
    2813             :     }
    2814             : 
    2815             :     case Translation::BUILTIN_CONTINUATION_FRAME: {
    2816       42231 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2817             :       SharedFunctionInfo shared_info =
    2818       84462 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2819       42231 :       int height = iterator->Next();
    2820       42231 :       if (trace_file != nullptr) {
    2821           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2822             :         PrintF(trace_file, "  reading builtin continuation frame %s",
    2823           0 :                name.get());
    2824             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2825           0 :                bailout_id.ToInt(), height);
    2826             :       }
    2827             :       // Add one to the height to account for the context which was implicitly
    2828             :       // added to the translation during code generation.
    2829       42231 :       int height_with_context = height + 1;
    2830             :       return TranslatedFrame::BuiltinContinuationFrame(bailout_id, shared_info,
    2831             :                                                        height_with_context);
    2832             :     }
    2833             : 
    2834             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME: {
    2835        2066 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2836             :       SharedFunctionInfo shared_info =
    2837        4132 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2838        2066 :       int height = iterator->Next();
    2839        2066 :       if (trace_file != nullptr) {
    2840           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2841             :         PrintF(trace_file, "  reading JavaScript builtin continuation frame %s",
    2842           0 :                name.get());
    2843             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2844           0 :                bailout_id.ToInt(), height);
    2845             :       }
    2846             :       // Add one to the height to account for the context which was implicitly
    2847             :       // added to the translation during code generation.
    2848        2066 :       int height_with_context = height + 1;
    2849             :       return TranslatedFrame::JavaScriptBuiltinContinuationFrame(
    2850             :           bailout_id, shared_info, height_with_context);
    2851             :     }
    2852             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
    2853          82 :       BailoutId bailout_id = BailoutId(iterator->Next());
    2854             :       SharedFunctionInfo shared_info =
    2855         164 :           SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
    2856          82 :       int height = iterator->Next();
    2857          82 :       if (trace_file != nullptr) {
    2858           0 :         std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
    2859             :         PrintF(trace_file,
    2860             :                "  reading JavaScript builtin continuation frame with catch %s",
    2861           0 :                name.get());
    2862             :         PrintF(trace_file, " => bailout_id=%d, height=%d; inputs:\n",
    2863           0 :                bailout_id.ToInt(), height);
    2864             :       }
    2865             :       // Add one to the height to account for the context which was implicitly
    2866             :       // added to the translation during code generation.
    2867          82 :       int height_with_context = height + 1;
    2868             :       return TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
    2869             :           bailout_id, shared_info, height_with_context);
    2870             :     }
    2871             :     case Translation::UPDATE_FEEDBACK:
    2872             :     case Translation::BEGIN:
    2873             :     case Translation::DUPLICATED_OBJECT:
    2874             :     case Translation::ARGUMENTS_ELEMENTS:
    2875             :     case Translation::ARGUMENTS_LENGTH:
    2876             :     case Translation::CAPTURED_OBJECT:
    2877             :     case Translation::REGISTER:
    2878             :     case Translation::INT32_REGISTER:
    2879             :     case Translation::INT64_REGISTER:
    2880             :     case Translation::UINT32_REGISTER:
    2881             :     case Translation::BOOL_REGISTER:
    2882             :     case Translation::FLOAT_REGISTER:
    2883             :     case Translation::DOUBLE_REGISTER:
    2884             :     case Translation::STACK_SLOT:
    2885             :     case Translation::INT32_STACK_SLOT:
    2886             :     case Translation::INT64_STACK_SLOT:
    2887             :     case Translation::UINT32_STACK_SLOT:
    2888             :     case Translation::BOOL_STACK_SLOT:
    2889             :     case Translation::FLOAT_STACK_SLOT:
    2890             :     case Translation::DOUBLE_STACK_SLOT:
    2891             :     case Translation::LITERAL:
    2892             :       break;
    2893             :   }
    2894           0 :   FATAL("We should never get here - unexpected deopt info.");
    2895             :   return TranslatedFrame::InvalidFrame();
    2896             : }
    2897             : 
    2898             : // static
    2899     4184503 : void TranslatedFrame::AdvanceIterator(
    2900     4849998 :     std::deque<TranslatedValue>::iterator* iter) {
    2901             :   int values_to_skip = 1;
    2902    13219004 :   while (values_to_skip > 0) {
    2903             :     // Consume the current element.
    2904     4849998 :     values_to_skip--;
    2905             :     // Add all the children.
    2906     4849998 :     values_to_skip += (*iter)->GetChildrenCount();
    2907             : 
    2908     4849998 :     (*iter)++;
    2909             :   }
    2910     4184503 : }
    2911             : 
    2912         501 : Address TranslatedState::ComputeArgumentsPosition(Address input_frame_pointer,
    2913             :                                                   CreateArgumentsType type,
    2914             :                                                   int* length) {
    2915             :   Address parent_frame_pointer = *reinterpret_cast<Address*>(
    2916         501 :       input_frame_pointer + StandardFrameConstants::kCallerFPOffset);
    2917             :   intptr_t parent_frame_type = Memory<intptr_t>(
    2918        1002 :       parent_frame_pointer + CommonFrameConstants::kContextOrFrameTypeOffset);
    2919             : 
    2920             :   Address arguments_frame;
    2921         501 :   if (parent_frame_type ==
    2922             :       StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)) {
    2923         327 :     if (length)
    2924             :       *length = Smi::cast(*FullObjectSlot(
    2925             :                               parent_frame_pointer +
    2926         327 :                               ArgumentsAdaptorFrameConstants::kLengthOffset))
    2927         327 :                     ->value();
    2928             :     arguments_frame = parent_frame_pointer;
    2929             :   } else {
    2930         174 :     if (length) *length = formal_parameter_count_;
    2931             :     arguments_frame = input_frame_pointer;
    2932             :   }
    2933             : 
    2934         501 :   if (type == CreateArgumentsType::kRestParameter) {
    2935             :     // If the actual number of arguments is less than the number of formal
    2936             :     // parameters, we have zero rest parameters.
    2937          72 :     if (length) *length = std::max(0, *length - formal_parameter_count_);
    2938             :   }
    2939             : 
    2940         501 :   return arguments_frame;
    2941             : }
    2942             : 
    2943             : // Creates translated values for an arguments backing store, or the backing
    2944             : // store for rest parameters depending on the given {type}. The TranslatedValue
    2945             : // objects for the fields are not read from the TranslationIterator, but instead
    2946             : // created on-the-fly based on dynamic information in the optimized frame.
    2947         247 : void TranslatedState::CreateArgumentsElementsTranslatedValues(
    2948             :     int frame_index, Address input_frame_pointer, CreateArgumentsType type,
    2949             :     FILE* trace_file) {
    2950         247 :   TranslatedFrame& frame = frames_[frame_index];
    2951             : 
    2952             :   int length;
    2953             :   Address arguments_frame =
    2954         247 :       ComputeArgumentsPosition(input_frame_pointer, type, &length);
    2955             : 
    2956         247 :   int object_index = static_cast<int>(object_positions_.size());
    2957         247 :   int value_index = static_cast<int>(frame.values_.size());
    2958         247 :   if (trace_file != nullptr) {
    2959             :     PrintF(trace_file, "arguments elements object #%d (type = %d, length = %d)",
    2960           0 :            object_index, static_cast<uint8_t>(type), length);
    2961             :   }
    2962             : 
    2963         494 :   object_positions_.push_back({frame_index, value_index});
    2964             :   frame.Add(TranslatedValue::NewDeferredObject(
    2965         494 :       this, length + FixedArray::kHeaderSize / kTaggedSize, object_index));
    2966             : 
    2967         247 :   ReadOnlyRoots roots(isolate_);
    2968         247 :   frame.Add(TranslatedValue::NewTagged(this, roots.fixed_array_map()));
    2969         494 :   frame.Add(TranslatedValue::NewInt32(this, length));
    2970             : 
    2971             :   int number_of_holes = 0;
    2972         247 :   if (type == CreateArgumentsType::kMappedArguments) {
    2973             :     // If the actual number of arguments is less than the number of formal
    2974             :     // parameters, we have fewer holes to fill to not overshoot the length.
    2975          43 :     number_of_holes = Min(formal_parameter_count_, length);
    2976             :   }
    2977         305 :   for (int i = 0; i < number_of_holes; ++i) {
    2978          58 :     frame.Add(TranslatedValue::NewTagged(this, roots.the_hole_value()));
    2979             :   }
    2980      573940 :   for (int i = length - number_of_holes - 1; i >= 0; --i) {
    2981             :     Address argument_slot = arguments_frame +
    2982      573693 :                             CommonFrameConstants::kFixedFrameSizeAboveFp +
    2983     1147386 :                             i * kSystemPointerSize;
    2984      573693 :     frame.Add(TranslatedValue::NewTagged(this, *FullObjectSlot(argument_slot)));
    2985             :   }
    2986         247 : }
    2987             : 
    2988             : // We can't intermix stack decoding and allocations because the deoptimization
    2989             : // infrastracture is not GC safe.
    2990             : // Thus we build a temporary structure in malloced space.
    2991             : // The TranslatedValue objects created correspond to the static translation
    2992             : // instructions from the TranslationIterator, except for
    2993             : // Translation::ARGUMENTS_ELEMENTS, where the number and values of the
    2994             : // FixedArray elements depend on dynamic information from the optimized frame.
    2995             : // Returns the number of expected nested translations from the
    2996             : // TranslationIterator.
    2997    20605435 : int TranslatedState::CreateNextTranslatedValue(
    2998             :     int frame_index, TranslationIterator* iterator, FixedArray literal_array,
    2999             :     Address fp, RegisterValues* registers, FILE* trace_file) {
    3000             :   disasm::NameConverter converter;
    3001             : 
    3002    20605435 :   TranslatedFrame& frame = frames_[frame_index];
    3003    20605435 :   int value_index = static_cast<int>(frame.values_.size());
    3004             : 
    3005             :   Translation::Opcode opcode =
    3006    20605435 :       static_cast<Translation::Opcode>(iterator->Next());
    3007    20605435 :   switch (opcode) {
    3008             :     case Translation::BEGIN:
    3009             :     case Translation::INTERPRETED_FRAME:
    3010             :     case Translation::ARGUMENTS_ADAPTOR_FRAME:
    3011             :     case Translation::CONSTRUCT_STUB_FRAME:
    3012             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
    3013             :     case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME:
    3014             :     case Translation::BUILTIN_CONTINUATION_FRAME:
    3015             :     case Translation::UPDATE_FEEDBACK:
    3016             :       // Peeled off before getting here.
    3017             :       break;
    3018             : 
    3019             :     case Translation::DUPLICATED_OBJECT: {
    3020       83150 :       int object_id = iterator->Next();
    3021       83150 :       if (trace_file != nullptr) {
    3022           0 :         PrintF(trace_file, "duplicated object #%d", object_id);
    3023             :       }
    3024       83150 :       object_positions_.push_back(object_positions_[object_id]);
    3025             :       TranslatedValue translated_value =
    3026             :           TranslatedValue::NewDuplicateObject(this, object_id);
    3027             :       frame.Add(translated_value);
    3028             :       return translated_value.GetChildrenCount();
    3029             :     }
    3030             : 
    3031             :     case Translation::ARGUMENTS_ELEMENTS: {
    3032             :       CreateArgumentsType arguments_type =
    3033         247 :           static_cast<CreateArgumentsType>(iterator->Next());
    3034             :       CreateArgumentsElementsTranslatedValues(frame_index, fp, arguments_type,
    3035         247 :                                               trace_file);
    3036         247 :       return 0;
    3037             :     }
    3038             : 
    3039             :     case Translation::ARGUMENTS_LENGTH: {
    3040             :       CreateArgumentsType arguments_type =
    3041         254 :           static_cast<CreateArgumentsType>(iterator->Next());
    3042             :       int length;
    3043         254 :       ComputeArgumentsPosition(fp, arguments_type, &length);
    3044         254 :       if (trace_file != nullptr) {
    3045             :         PrintF(trace_file, "arguments length field (type = %d, length = %d)",
    3046           0 :                static_cast<uint8_t>(arguments_type), length);
    3047             :       }
    3048         508 :       frame.Add(TranslatedValue::NewInt32(this, length));
    3049             :       return 0;
    3050             :     }
    3051             : 
    3052             :     case Translation::CAPTURED_OBJECT: {
    3053      152471 :       int field_count = iterator->Next();
    3054      152471 :       int object_index = static_cast<int>(object_positions_.size());
    3055      152471 :       if (trace_file != nullptr) {
    3056             :         PrintF(trace_file, "captured object #%d (length = %d)", object_index,
    3057           0 :                field_count);
    3058             :       }
    3059      304942 :       object_positions_.push_back({frame_index, value_index});
    3060             :       TranslatedValue translated_value =
    3061             :           TranslatedValue::NewDeferredObject(this, field_count, object_index);
    3062             :       frame.Add(translated_value);
    3063             :       return translated_value.GetChildrenCount();
    3064             :     }
    3065             : 
    3066             :     case Translation::REGISTER: {
    3067       22377 :       int input_reg = iterator->Next();
    3068       22377 :       if (registers == nullptr) {
    3069             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3070             :         frame.Add(translated_value);
    3071             :         return translated_value.GetChildrenCount();
    3072             :       }
    3073       22377 :       intptr_t value = registers->GetRegister(input_reg);
    3074       22377 :       if (trace_file != nullptr) {
    3075             :         PrintF(trace_file, V8PRIxPTR_FMT " ; %s ", value,
    3076         360 :                converter.NameOfCPURegister(input_reg));
    3077         720 :         Object(value)->ShortPrint(trace_file);
    3078             :       }
    3079             :       TranslatedValue translated_value =
    3080       22377 :           TranslatedValue::NewTagged(this, Object(value));
    3081             :       frame.Add(translated_value);
    3082       22377 :       return translated_value.GetChildrenCount();
    3083             :     }
    3084             : 
    3085             :     case Translation::INT32_REGISTER: {
    3086         875 :       int input_reg = iterator->Next();
    3087         875 :       if (registers == nullptr) {
    3088             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3089             :         frame.Add(translated_value);
    3090             :         return translated_value.GetChildrenCount();
    3091             :       }
    3092         875 :       intptr_t value = registers->GetRegister(input_reg);
    3093         875 :       if (trace_file != nullptr) {
    3094             :         PrintF(trace_file, "%" V8PRIdPTR " ; %s (int32)", value,
    3095           0 :                converter.NameOfCPURegister(input_reg));
    3096             :       }
    3097             :       TranslatedValue translated_value =
    3098         875 :           TranslatedValue::NewInt32(this, static_cast<int32_t>(value));
    3099             :       frame.Add(translated_value);
    3100         875 :       return translated_value.GetChildrenCount();
    3101             :     }
    3102             : 
    3103             :     case Translation::INT64_REGISTER: {
    3104           0 :       int input_reg = iterator->Next();
    3105           0 :       if (registers == nullptr) {
    3106             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3107             :         frame.Add(translated_value);
    3108             :         return translated_value.GetChildrenCount();
    3109             :       }
    3110           0 :       intptr_t value = registers->GetRegister(input_reg);
    3111           0 :       if (trace_file != nullptr) {
    3112             :         PrintF(trace_file, "%" V8PRIdPTR " ; %s (int64)", value,
    3113           0 :                converter.NameOfCPURegister(input_reg));
    3114             :       }
    3115             :       TranslatedValue translated_value =
    3116             :           TranslatedValue::NewInt64(this, static_cast<int64_t>(value));
    3117             :       frame.Add(translated_value);
    3118           0 :       return translated_value.GetChildrenCount();
    3119             :     }
    3120             : 
    3121             :     case Translation::UINT32_REGISTER: {
    3122          14 :       int input_reg = iterator->Next();
    3123          14 :       if (registers == nullptr) {
    3124             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3125             :         frame.Add(translated_value);
    3126             :         return translated_value.GetChildrenCount();
    3127             :       }
    3128          14 :       intptr_t value = registers->GetRegister(input_reg);
    3129          14 :       if (trace_file != nullptr) {
    3130             :         PrintF(trace_file, "%" V8PRIuPTR " ; %s (uint32)", value,
    3131           0 :                converter.NameOfCPURegister(input_reg));
    3132             :       }
    3133             :       TranslatedValue translated_value =
    3134          14 :           TranslatedValue::NewUInt32(this, static_cast<uint32_t>(value));
    3135             :       frame.Add(translated_value);
    3136          14 :       return translated_value.GetChildrenCount();
    3137             :     }
    3138             : 
    3139             :     case Translation::BOOL_REGISTER: {
    3140          65 :       int input_reg = iterator->Next();
    3141          65 :       if (registers == nullptr) {
    3142             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3143             :         frame.Add(translated_value);
    3144             :         return translated_value.GetChildrenCount();
    3145             :       }
    3146          65 :       intptr_t value = registers->GetRegister(input_reg);
    3147          65 :       if (trace_file != nullptr) {
    3148             :         PrintF(trace_file, "%" V8PRIdPTR " ; %s (bool)", value,
    3149           0 :                converter.NameOfCPURegister(input_reg));
    3150             :       }
    3151             :       TranslatedValue translated_value =
    3152          65 :           TranslatedValue::NewBool(this, static_cast<uint32_t>(value));
    3153             :       frame.Add(translated_value);
    3154          65 :       return translated_value.GetChildrenCount();
    3155             :     }
    3156             : 
    3157             :     case Translation::FLOAT_REGISTER: {
    3158          91 :       int input_reg = iterator->Next();
    3159          91 :       if (registers == nullptr) {
    3160             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3161             :         frame.Add(translated_value);
    3162             :         return translated_value.GetChildrenCount();
    3163             :       }
    3164         182 :       Float32 value = registers->GetFloatRegister(input_reg);
    3165          91 :       if (trace_file != nullptr) {
    3166             :         PrintF(trace_file, "%e ; %s (float)", value.get_scalar(),
    3167           0 :                RegisterName(FloatRegister::from_code(input_reg)));
    3168             :       }
    3169             :       TranslatedValue translated_value = TranslatedValue::NewFloat(this, value);
    3170             :       frame.Add(translated_value);
    3171          91 :       return translated_value.GetChildrenCount();
    3172             :     }
    3173             : 
    3174             :     case Translation::DOUBLE_REGISTER: {
    3175         424 :       int input_reg = iterator->Next();
    3176         424 :       if (registers == nullptr) {
    3177             :         TranslatedValue translated_value = TranslatedValue::NewInvalid(this);
    3178             :         frame.Add(translated_value);
    3179             :         return translated_value.GetChildrenCount();
    3180             :       }
    3181         848 :       Float64 value = registers->GetDoubleRegister(input_reg);
    3182         424 :       if (trace_file != nullptr) {
    3183             :         PrintF(trace_file, "%e ; %s (double)", value.get_scalar(),
    3184           0 :                RegisterName(DoubleRegister::from_code(input_reg)));
    3185             :       }
    3186             :       TranslatedValue translated_value =
    3187             :           TranslatedValue::NewDouble(this, value);
    3188             :       frame.Add(translated_value);
    3189         424 :       return translated_value.GetChildrenCount();
    3190             :     }
    3191             : 
    3192             :     case Translation::STACK_SLOT: {
    3193             :       int slot_offset =
    3194     7434736 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3195     7434736 :       intptr_t value = *(reinterpret_cast<intptr_t*>(fp + slot_offset));
    3196     7434736 :       if (trace_file != nullptr) {
    3197             :         PrintF(trace_file, V8PRIxPTR_FMT " ;  [fp %c %3d]  ", value,
    3198         960 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3199        1920 :         Object(value)->ShortPrint(trace_file);
    3200             :       }
    3201             :       TranslatedValue translated_value =
    3202     7434736 :           TranslatedValue::NewTagged(this, Object(value));
    3203             :       frame.Add(translated_value);
    3204             :       return translated_value.GetChildrenCount();
    3205             :     }
    3206             : 
    3207             :     case Translation::INT32_STACK_SLOT: {
    3208             :       int slot_offset =
    3209      315540 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3210             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3211      315540 :       if (trace_file != nullptr) {
    3212             :         PrintF(trace_file, "%d ; (int32) [fp %c %3d] ",
    3213             :                static_cast<int32_t>(value), slot_offset < 0 ? '-' : '+',
    3214           0 :                std::abs(slot_offset));
    3215             :       }
    3216      315540 :       TranslatedValue translated_value = TranslatedValue::NewInt32(this, value);
    3217             :       frame.Add(translated_value);
    3218             :       return translated_value.GetChildrenCount();
    3219             :     }
    3220             : 
    3221             :     case Translation::INT64_STACK_SLOT: {
    3222             :       int slot_offset =
    3223           9 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3224             :       uint64_t value = GetUInt64Slot(fp, slot_offset);
    3225           9 :       if (trace_file != nullptr) {
    3226             :         PrintF(trace_file, "%" V8PRIdPTR " ; (int64) [fp %c %3d] ",
    3227             :                static_cast<intptr_t>(value), slot_offset < 0 ? '-' : '+',
    3228           0 :                std::abs(slot_offset));
    3229             :       }
    3230           9 :       TranslatedValue translated_value = TranslatedValue::NewInt64(this, value);
    3231             :       frame.Add(translated_value);
    3232             :       return translated_value.GetChildrenCount();
    3233             :     }
    3234             : 
    3235             :     case Translation::UINT32_STACK_SLOT: {
    3236             :       int slot_offset =
    3237       50131 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3238             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3239       50131 :       if (trace_file != nullptr) {
    3240             :         PrintF(trace_file, "%u ; (uint32) [fp %c %3d] ", value,
    3241           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3242             :       }
    3243             :       TranslatedValue translated_value =
    3244             :           TranslatedValue::NewUInt32(this, value);
    3245             :       frame.Add(translated_value);
    3246             :       return translated_value.GetChildrenCount();
    3247             :     }
    3248             : 
    3249             :     case Translation::BOOL_STACK_SLOT: {
    3250             :       int slot_offset =
    3251         373 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3252             :       uint32_t value = GetUInt32Slot(fp, slot_offset);
    3253         373 :       if (trace_file != nullptr) {
    3254             :         PrintF(trace_file, "%u ; (bool) [fp %c %3d] ", value,
    3255           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3256             :       }
    3257             :       TranslatedValue translated_value = TranslatedValue::NewBool(this, value);
    3258             :       frame.Add(translated_value);
    3259             :       return translated_value.GetChildrenCount();
    3260             :     }
    3261             : 
    3262             :     case Translation::FLOAT_STACK_SLOT: {
    3263             :       int slot_offset =
    3264         197 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3265         197 :       Float32 value = GetFloatSlot(fp, slot_offset);
    3266         197 :       if (trace_file != nullptr) {
    3267             :         PrintF(trace_file, "%e ; (float) [fp %c %3d] ", value.get_scalar(),
    3268           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3269             :       }
    3270             :       TranslatedValue translated_value = TranslatedValue::NewFloat(this, value);
    3271             :       frame.Add(translated_value);
    3272             :       return translated_value.GetChildrenCount();
    3273             :     }
    3274             : 
    3275             :     case Translation::DOUBLE_STACK_SLOT: {
    3276             :       int slot_offset =
    3277      521064 :           OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
    3278      521064 :       Float64 value = GetDoubleSlot(fp, slot_offset);
    3279      521064 :       if (trace_file != nullptr) {
    3280             :         PrintF(trace_file, "%e ; (double) [fp %c %d] ", value.get_scalar(),
    3281           0 :                slot_offset < 0 ? '-' : '+', std::abs(slot_offset));
    3282             :       }
    3283             :       TranslatedValue translated_value =
    3284             :           TranslatedValue::NewDouble(this, value);
    3285             :       frame.Add(translated_value);
    3286             :       return translated_value.GetChildrenCount();
    3287             :     }
    3288             : 
    3289             :     case Translation::LITERAL: {
    3290    12023417 :       int literal_index = iterator->Next();
    3291    12023417 :       Object value = literal_array->get(literal_index);
    3292    12023417 :       if (trace_file != nullptr) {
    3293             :         PrintF(trace_file, V8PRIxPTR_FMT " ; (literal %2d) ", value->ptr(),
    3294        1080 :                literal_index);
    3295        1080 :         value->ShortPrint(trace_file);
    3296             :       }
    3297             : 
    3298             :       TranslatedValue translated_value =
    3299             :           TranslatedValue::NewTagged(this, value);
    3300             :       frame.Add(translated_value);
    3301             :       return translated_value.GetChildrenCount();
    3302             :     }
    3303             :   }
    3304             : 
    3305           0 :   FATAL("We should never get here - unexpected deopt info.");
    3306             : }
    3307             : 
    3308     4052565 : TranslatedState::TranslatedState(const JavaScriptFrame* frame) {
    3309     1350855 :   int deopt_index = Safepoint::kNoDeoptimizationIndex;
    3310             :   DeoptimizationData data =
    3311             :       static_cast<const OptimizedFrame*>(frame)->GetDeoptimizationData(
    3312     1350855 :           &deopt_index);
    3313             :   DCHECK(!data.is_null() && deopt_index != Safepoint::kNoDeoptimizationIndex);
    3314             :   TranslationIterator it(data->TranslationByteArray(),
    3315     4052565 :                          data->TranslationIndex(deopt_index)->value());
    3316             :   Init(frame->isolate(), frame->fp(), &it, data->LiteralArray(),
    3317             :        nullptr /* registers */, nullptr /* trace file */,
    3318     2701710 :        frame->function()->shared()->internal_formal_parameter_count());
    3319     1350855 : }
    3320             : 
    3321     1396025 : void TranslatedState::Init(Isolate* isolate, Address input_frame_pointer,
    3322             :                            TranslationIterator* iterator,
    3323             :                            FixedArray literal_array, RegisterValues* registers,
    3324             :                            FILE* trace_file, int formal_parameter_count) {
    3325             :   DCHECK(frames_.empty());
    3326             : 
    3327     1396025 :   formal_parameter_count_ = formal_parameter_count;
    3328     1396025 :   isolate_ = isolate;
    3329             : 
    3330             :   // Read out the 'header' translation.
    3331             :   Translation::Opcode opcode =
    3332     1396025 :       static_cast<Translation::Opcode>(iterator->Next());
    3333     1396025 :   CHECK(opcode == Translation::BEGIN);
    3334             : 
    3335     1396025 :   int count = iterator->Next();
    3336     1396025 :   frames_.reserve(count);
    3337     1396025 :   iterator->Next();  // Drop JS frames count.
    3338     1396025 :   int update_feedback_count = iterator->Next();
    3339     1396025 :   CHECK_GE(update_feedback_count, 0);
    3340     1396025 :   CHECK_LE(update_feedback_count, 1);
    3341             : 
    3342     1396025 :   if (update_feedback_count == 1) {
    3343        1883 :     ReadUpdateFeedback(iterator, literal_array, trace_file);
    3344             :   }
    3345             : 
    3346     1396026 :   std::stack<int> nested_counts;
    3347             : 
    3348             :   // Read the frames
    3349     3364908 :   for (int frame_index = 0; frame_index < count; frame_index++) {
    3350             :     // Read the frame descriptor.
    3351             :     frames_.push_back(CreateNextTranslatedFrame(
    3352     3937764 :         iterator, literal_array, input_frame_pointer, trace_file));
    3353     1968882 :     TranslatedFrame& frame = frames_.back();
    3354             : 
    3355             :     // Read the values.
    3356     1968882 :     int values_to_process = frame.GetValueCount();
    3357    26512081 :     while (values_to_process > 0 || !nested_counts.empty()) {
    3358    20605435 :       if (trace_file != nullptr) {
    3359        2400 :         if (nested_counts.empty()) {
    3360             :           // For top level values, print the value number.
    3361             :           PrintF(trace_file, "    %3i: ",
    3362        2400 :                  frame.GetValueCount() - values_to_process);
    3363             :         } else {
    3364             :           // Take care of indenting for nested values.
    3365           0 :           PrintF(trace_file, "         ");
    3366           0 :           for (size_t j = 0; j < nested_counts.size(); j++) {
    3367           0 :             PrintF(trace_file, "  ");
    3368             :           }
    3369             :         }
    3370             :       }
    3371             : 
    3372             :       int nested_count =
    3373             :           CreateNextTranslatedValue(frame_index, iterator, literal_array,
    3374    20605435 :                                     input_frame_pointer, registers, trace_file);
    3375             : 
    3376    20605435 :       if (trace_file != nullptr) {
    3377        2400 :         PrintF(trace_file, "\n");
    3378             :       }
    3379             : 
    3380             :       // Update the value count and resolve the nesting.
    3381    20605435 :       values_to_process--;
    3382    20605435 :       if (nested_count > 0) {
    3383             :         nested_counts.push(values_to_process);
    3384      152471 :         values_to_process = nested_count;
    3385             :       } else {
    3386    22726788 :         while (values_to_process == 0 && !nested_counts.empty()) {
    3387      152471 :           values_to_process = nested_counts.top();
    3388             :           nested_counts.pop();
    3389             :         }
    3390             :       }
    3391             :     }
    3392             :   }
    3393             : 
    3394     1396026 :   CHECK(!iterator->HasNext() ||
    3395             :         static_cast<Translation::Opcode>(iterator->Next()) ==
    3396             :             Translation::BEGIN);
    3397     1396026 : }
    3398             : 
    3399     1397909 : void TranslatedState::Prepare(Address stack_frame_pointer) {
    3400     4760934 :   for (auto& frame : frames_) frame.Handlify();
    3401             : 
    3402     1396026 :   if (!feedback_vector_.is_null()) {
    3403             :     feedback_vector_handle_ =
    3404        1883 :         Handle<FeedbackVector>(feedback_vector_, isolate());
    3405        1883 :     feedback_vector_ = FeedbackVector();
    3406             :   }
    3407     1396026 :   stack_frame_pointer_ = stack_frame_pointer;
    3408             : 
    3409     1396026 :   UpdateFromPreviouslyMaterializedObjects();
    3410     1396026 : }
    3411             : 
    3412       57091 : TranslatedValue* TranslatedState::GetValueByObjectIndex(int object_index) {
    3413       57091 :   CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
    3414       57091 :   TranslatedState::ObjectPosition pos = object_positions_[object_index];
    3415      114182 :   return &(frames_[pos.frame_index_].values_[pos.value_index_]);
    3416             : }
    3417             : 
    3418       94082 : Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
    3419       47041 :   slot = ResolveCapturedObject(slot);
    3420             : 
    3421             :   DisallowHeapAllocation no_allocation;
    3422       47041 :   if (slot->materialization_state() != TranslatedValue::kFinished) {
    3423       46081 :     std::stack<int> worklist;
    3424       92162 :     worklist.push(slot->object_index());
    3425             :     slot->mark_finished();
    3426             : 
    3427       92947 :     while (!worklist.empty()) {
    3428       46866 :       int index = worklist.top();
    3429             :       worklist.pop();
    3430       46866 :       InitializeCapturedObjectAt(index, &worklist, no_allocation);
    3431             :     }
    3432             :   }
    3433       47041 :   return slot->GetStorage();
    3434             : }
    3435             : 
    3436       46866 : void TranslatedState::InitializeCapturedObjectAt(
    3437             :     int object_index, std::stack<int>* worklist,
    3438             :     const DisallowHeapAllocation& no_allocation) {
    3439       46866 :   CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
    3440       46866 :   TranslatedState::ObjectPosition pos = object_positions_[object_index];
    3441       46866 :   int value_index = pos.value_index_;
    3442             : 
    3443       46866 :   TranslatedFrame* frame = &(frames_[pos.frame_index_]);
    3444       93732 :   TranslatedValue* slot = &(frame->values_[value_index]);
    3445       46866 :   value_index++;
    3446             : 
    3447       46866 :   CHECK_EQ(TranslatedValue::kFinished, slot->materialization_state());
    3448       46866 :   CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
    3449             : 
    3450             :   // Ensure all fields are initialized.
    3451       46866 :   int children_init_index = value_index;
    3452     1595174 :   for (int i = 0; i < slot->GetChildrenCount(); i++) {
    3453             :     // If the field is an object that has not been initialized yet, queue it
    3454             :     // for initialization (and mark it as such).
    3455     1502447 :     TranslatedValue* child_slot = frame->ValueAt(children_init_index);
    3456      750721 :     if (child_slot->kind() == TranslatedValue::kCapturedObject ||
    3457             :         child_slot->kind() == TranslatedValue::kDuplicatedObject) {
    3458        1005 :       child_slot = ResolveCapturedObject(child_slot);
    3459        1005 :       if (child_slot->materialization_state() != TranslatedValue::kFinished) {
    3460             :         DCHECK_EQ(TranslatedValue::kAllocated,
    3461             :                   child_slot->materialization_state());
    3462        1570 :         worklist->push(child_slot->object_index());
    3463             :         child_slot->mark_finished();
    3464             :       }
    3465             :     }
    3466      750721 :     SkipSlots(1, frame, &children_init_index);
    3467             :   }
    3468             : 
    3469             :   // Read the map.
    3470             :   // The map should never be materialized, so let us check we already have
    3471             :   // an existing object here.
    3472       93732 :   CHECK_EQ(frame->values_[value_index].kind(), TranslatedValue::kTagged);
    3473       93732 :   Handle<Map> map = Handle<Map>::cast(frame->values_[value_index].GetValue());
    3474       93732 :   CHECK(map->IsMap());
    3475       46866 :   value_index++;
    3476             : 
    3477             :   // Handle the special cases.
    3478       46866 :   switch (map->instance_type()) {
    3479             :     case MUTABLE_HEAP_NUMBER_TYPE:
    3480             :     case FIXED_DOUBLE_ARRAY_TYPE:
    3481          39 :       return;
    3482             : 
    3483             :     case FIXED_ARRAY_TYPE:
    3484             :     case AWAIT_CONTEXT_TYPE:
    3485             :     case BLOCK_CONTEXT_TYPE:
    3486             :     case CATCH_CONTEXT_TYPE:
    3487             :     case DEBUG_EVALUATE_CONTEXT_TYPE:
    3488             :     case EVAL_CONTEXT_TYPE:
    3489             :     case FUNCTION_CONTEXT_TYPE:
    3490             :     case MODULE_CONTEXT_TYPE:
    3491             :     case NATIVE_CONTEXT_TYPE:
    3492             :     case SCRIPT_CONTEXT_TYPE:
    3493             :     case WITH_CONTEXT_TYPE:
    3494             :     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
    3495             :     case HASH_TABLE_TYPE:
    3496             :     case ORDERED_HASH_MAP_TYPE:
    3497             :     case ORDERED_HASH_SET_TYPE:
    3498             :     case NAME_DICTIONARY_TYPE:
    3499             :     case GLOBAL_DICTIONARY_TYPE:
    3500             :     case NUMBER_DICTIONARY_TYPE:
    3501             :     case SIMPLE_NUMBER_DICTIONARY_TYPE:
    3502             :     case STRING_TABLE_TYPE:
    3503             :     case PROPERTY_ARRAY_TYPE:
    3504             :     case SCRIPT_CONTEXT_TABLE_TYPE:
    3505             :       InitializeObjectWithTaggedFieldsAt(frame, &value_index, slot, map,
    3506         773 :                                          no_allocation);
    3507         773 :       break;
    3508             : 
    3509             :     default:
    3510       46054 :       CHECK(map->IsJSObjectMap());
    3511       46054 :       InitializeJSObjectAt(frame, &value_index, slot, map, no_allocation);
    3512       46054 :       break;
    3513             :   }
    3514       46827 :   CHECK_EQ(value_index, children_init_index);
    3515             : }
    3516             : 
    3517       94082 : void TranslatedState::EnsureObjectAllocatedAt(TranslatedValue* slot) {
    3518       47041 :   slot = ResolveCapturedObject(slot);
    3519             : 
    3520       47041 :   if (slot->materialization_state() == TranslatedValue::kUninitialized) {
    3521       46081 :     std::stack<int> worklist;
    3522       92162 :     worklist.push(slot->object_index());
    3523             :     slot->mark_allocated();
    3524             : 
    3525       92908 :     while (!worklist.empty()) {
    3526       46827 :       int index = worklist.top();
    3527             :       worklist.pop();
    3528       46827 :       EnsureCapturedObjectAllocatedAt(index, &worklist);
    3529             :     }
    3530             :   }
    3531       47041 : }
    3532             : 
    3533          31 : void TranslatedState::MaterializeFixedDoubleArray(TranslatedFrame* frame,
    3534             :                                                   int* value_index,
    3535             :                                                   TranslatedValue* slot,
    3536          46 :                                                   Handle<Map> map) {
    3537          62 :   int length = Smi::cast(frame->values_[*value_index].GetRawValue())->value();
    3538          31 :   (*value_index)++;
    3539             :   Handle<FixedDoubleArray> array = Handle<FixedDoubleArray>::cast(
    3540          31 :       isolate()->factory()->NewFixedDoubleArray(length));
    3541          31 :   CHECK_GT(length, 0);
    3542          86 :   for (int i = 0; i < length; i++) {
    3543         172 :     CHECK_NE(TranslatedValue::kCapturedObject,
    3544             :              frame->values_[*value_index].kind());
    3545         172 :     Handle<Object> value = frame->values_[*value_index].GetValue();
    3546         172 :     if (value->IsNumber()) {
    3547         142 :       array->set(i, value->Number());
    3548             :     } else {
    3549          15 :       CHECK(value.is_identical_to(isolate()->factory()->the_hole_value()));
    3550             :       array->set_the_hole(isolate(), i);
    3551             :     }
    3552          86 :     (*value_index)++;
    3553             :   }
    3554             :   slot->set_storage(array);
    3555          31 : }
    3556             : 
    3557           8 : void TranslatedState::MaterializeMutableHeapNumber(TranslatedFrame* frame,
    3558             :                                                    int* value_index,
    3559           8 :                                                    TranslatedValue* slot) {
    3560          16 :   CHECK_NE(TranslatedValue::kCapturedObject,
    3561             :            frame->values_[*value_index].kind());
    3562          16 :   Handle<Object> value = frame->values_[*value_index].GetValue();
    3563          16 :   CHECK(value->IsNumber());
    3564             :   Handle<MutableHeapNumber> box =
    3565          16 :       isolate()->factory()->NewMutableHeapNumber(value->Number());
    3566           8 :   (*value_index)++;
    3567             :   slot->set_storage(box);
    3568           8 : }
    3569             : 
    3570             : namespace {
    3571             : 
    3572             : enum DoubleStorageKind : uint8_t {
    3573             :   kStoreTagged,
    3574             :   kStoreUnboxedDouble,
    3575             :   kStoreMutableHeapNumber,
    3576             : };
    3577             : 
    3578             : }  // namespace
    3579             : 
    3580     2112166 : void TranslatedState::SkipSlots(int slots_to_skip, TranslatedFrame* frame,
    3581             :                                 int* value_index) {
    3582     8066431 :   while (slots_to_skip > 0) {
    3583     7684198 :     TranslatedValue* slot = &(frame->values_[*value_index]);
    3584     3842099 :     (*value_index)++;
    3585     3842099 :     slots_to_skip--;
    3586             : 
    3587     3842099 :     if (slot->kind() == TranslatedValue::kCapturedObject) {
    3588        2033 :       slots_to_skip += slot->GetChildrenCount();
    3589             :     }
    3590             :   }
    3591     2112166 : }
    3592             : 
    3593       46827 : void TranslatedState::EnsureCapturedObjectAllocatedAt(
    3594         763 :     int object_index, std::stack<int>* worklist) {
    3595       46827 :   CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
    3596       46827 :   TranslatedState::ObjectPosition pos = object_positions_[object_index];
    3597       46827 :   int value_index = pos.value_index_;
    3598             : 
    3599       46827 :   TranslatedFrame* frame = &(frames_[pos.frame_index_]);
    3600       93654 :   TranslatedValue* slot = &(frame->values_[value_index]);
    3601       46827 :   value_index++;
    3602             : 
    3603       46827 :   CHECK_EQ(TranslatedValue::kAllocated, slot->materialization_state());
    3604       46827 :   CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
    3605             : 
    3606             :   // Read the map.
    3607             :   // The map should never be materialized, so let us check we already have
    3608             :   // an existing object here.
    3609       46827 :   CHECK_EQ(frame->values_[value_index].kind(), TranslatedValue::kTagged);
    3610       93654 :   Handle<Map> map = Handle<Map>::cast(frame->values_[value_index].GetValue());
    3611       93654 :   CHECK(map->IsMap());
    3612       46827 :   value_index++;
    3613             : 
    3614             :   // Handle the special cases.
    3615       46827 :   switch (map->instance_type()) {
    3616             :     case FIXED_DOUBLE_ARRAY_TYPE:
    3617             :       // Materialize (i.e. allocate&initialize) the array and return since
    3618             :       // there is no need to process the children.
    3619          31 :       return MaterializeFixedDoubleArray(frame, &value_index, slot, map);
    3620             : 
    3621             :     case MUTABLE_HEAP_NUMBER_TYPE:
    3622             :       // Materialize (i.e. allocate&initialize) the heap number and return.
    3623             :       // There is no need to process the children.
    3624           8 :       return MaterializeMutableHeapNumber(frame, &value_index, slot);
    3625             : 
    3626             :     case FIXED_ARRAY_TYPE:
    3627             :     case SCRIPT_CONTEXT_TABLE_TYPE:
    3628             :     case AWAIT_CONTEXT_TYPE:
    3629             :     case BLOCK_CONTEXT_TYPE:
    3630             :     case CATCH_CONTEXT_TYPE:
    3631             :     case DEBUG_EVALUATE_CONTEXT_TYPE:
    3632             :     case EVAL_CONTEXT_TYPE:
    3633             :     case FUNCTION_CONTEXT_TYPE:
    3634             :     case MODULE_CONTEXT_TYPE:
    3635             :     case NATIVE_CONTEXT_TYPE:
    3636             :     case SCRIPT_CONTEXT_TYPE:
    3637             :     case WITH_CONTEXT_TYPE:
    3638             :     case HASH_TABLE_TYPE:
    3639             :     case ORDERED_HASH_MAP_TYPE:
    3640             :     case ORDERED_HASH_SET_TYPE:
    3641             :     case NAME_DICTIONARY_TYPE:
    3642             :     case GLOBAL_DICTIONARY_TYPE:
    3643             :     case NUMBER_DICTIONARY_TYPE:
    3644             :     case SIMPLE_NUMBER_DICTIONARY_TYPE:
    3645             :     case STRING_TABLE_TYPE: {
    3646             :       // Check we have the right size.
    3647             :       int array_length =
    3648        1468 :           Smi::cast(frame->values_[value_index].GetRawValue())->value();
    3649             : 
    3650             :       int instance_size = FixedArray::SizeFor(array_length);
    3651         734 :       CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
    3652             : 
    3653             :       // Canonicalize empty fixed array.
    3654         734 :       if (*map == ReadOnlyRoots(isolate()).empty_fixed_array()->map() &&
    3655             :           array_length == 0) {
    3656             :         slot->set_storage(isolate()->factory()->empty_fixed_array());
    3657             :       } else {
    3658         705 :         slot->set_storage(AllocateStorageFor(slot));
    3659             :       }
    3660             : 
    3661             :       // Make sure all the remaining children (after the map) are allocated.
    3662             :       return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
    3663         734 :                                      &value_index, worklist);
    3664             :     }
    3665             : 
    3666             :     case PROPERTY_ARRAY_TYPE: {
    3667             :       // Check we have the right size.
    3668             :       int length_or_hash =
    3669           0 :           Smi::cast(frame->values_[value_index].GetRawValue())->value();
    3670             :       int array_length = PropertyArray::LengthField::decode(length_or_hash);
    3671             :       int instance_size = PropertyArray::SizeFor(array_length);
    3672           0 :       CHECK_EQ(instance_size, slot->GetChildrenCount() * kTaggedSize);
    3673             : 
    3674           0 :       slot->set_storage(AllocateStorageFor(slot));
    3675             :       // Make sure all the remaining children (after the map) are allocated.
    3676             :       return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
    3677           0 :                                      &value_index, worklist);
    3678             :     }
    3679             : 
    3680             :     default:
    3681       46054 :       CHECK(map->IsJSObjectMap());
    3682       46054 :       EnsureJSObjectAllocated(slot, map);
    3683       92108 :       TranslatedValue* properties_slot = &(frame->values_[value_index]);
    3684       46054 :       value_index++;
    3685       46054 :       if (properties_slot->kind() == TranslatedValue::kCapturedObject) {
    3686             :         // If we are materializing the property array, make sure we put
    3687             :         // the mutable heap numbers at the right places.
    3688          39 :         EnsurePropertiesAllocatedAndMarked(properties_slot, map);
    3689             :         EnsureChildrenAllocated(properties_slot->GetChildrenCount(), frame,
    3690          39 :                                 &value_index, worklist);
    3691             :       }
    3692             :       // Make sure all the remaining children (after the map and properties) are
    3693             :       // allocated.
    3694             :       return EnsureChildrenAllocated(slot->GetChildrenCount() - 2, frame,
    3695       46054 :                                      &value_index, worklist);
    3696             :   }
    3697             :   UNREACHABLE();
    3698             : }
    3699             : 
    3700       46827 : void TranslatedState::EnsureChildrenAllocated(int count, TranslatedFrame* frame,
    3701             :                                               int* value_index,
    3702             :                                               std::stack<int>* worklist) {
    3703             :   // Ensure all children are allocated.
    3704      704542 :   for (int i = 0; i < count; i++) {
    3705             :     // If the field is an object that has not been allocated yet, queue it
    3706             :     // for initialization (and mark it as such).
    3707     1316396 :     TranslatedValue* child_slot = frame->ValueAt(*value_index);
    3708      657715 :     if (child_slot->kind() == TranslatedValue::kCapturedObject ||
    3709             :         child_slot->kind() == TranslatedValue::kDuplicatedObject) {
    3710         966 :       child_slot = ResolveCapturedObject(child_slot);
    3711         966 :       if (child_slot->materialization_state() ==
    3712             :           TranslatedValue::kUninitialized) {
    3713        1492 :         worklist->push(child_slot->object_index());
    3714             :         child_slot->mark_allocated();
    3715             :       }
    3716             :     } else {
    3717             :       // Make sure the simple values (heap numbers, etc.) are properly
    3718             :       // initialized.
    3719      656749 :       child_slot->MaterializeSimple();
    3720             :     }
    3721      657715 :     SkipSlots(1, frame, value_index);
    3722             :   }
    3723       46827 : }
    3724             : 
    3725          39 : void TranslatedState::EnsurePropertiesAllocatedAndMarked(
    3726          78 :     TranslatedValue* properties_slot, Handle<Map> map) {
    3727          39 :   CHECK_EQ(TranslatedValue::kUninitialized,
    3728             :            properties_slot->materialization_state());
    3729             : 
    3730          39 :   Handle<ByteArray> object_storage = AllocateStorageFor(properties_slot);
    3731             :   properties_slot->mark_allocated();
    3732             :   properties_slot->set_storage(object_storage);
    3733             : 
    3734             :   // Set markers for the double properties.
    3735          78 :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
    3736             :   int field_count = map->NumberOfOwnDescriptors();
    3737          86 :   for (int i = 0; i < field_count; i++) {
    3738          47 :     FieldIndex index = FieldIndex::ForDescriptor(*map, i);
    3739         102 :     if (descriptors->GetDetails(i).representation().IsDouble() &&
    3740             :         !index.is_inobject()) {
    3741           8 :       CHECK(!map->IsUnboxedDoubleField(index));
    3742             :       int outobject_index = index.outobject_array_index();
    3743           8 :       int array_index = outobject_index * kTaggedSize;
    3744             :       object_storage->set(array_index, kStoreMutableHeapNumber);
    3745             :     }
    3746             :   }
    3747          39 : }
    3748             : 
    3749       93596 : Handle<ByteArray> TranslatedState::AllocateStorageFor(TranslatedValue* slot) {
    3750             :   int allocate_size =
    3751       46798 :       ByteArray::LengthFor(slot->GetChildrenCount() * kTaggedSize);
    3752             :   // It is important to allocate all the objects tenured so that the marker
    3753             :   // does not visit them.
    3754             :   Handle<ByteArray> object_storage =
    3755       46798 :       isolate()->factory()->NewByteArray(allocate_size, TENURED);
    3756    10604044 :   for (int i = 0; i < object_storage->length(); i++) {
    3757             :     object_storage->set(i, kStoreTagged);
    3758             :   }
    3759       46798 :   return object_storage;
    3760             : }
    3761             : 
    3762       46054 : void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot,
    3763       46054 :                                               Handle<Map> map) {
    3764       92108 :   CHECK_EQ(map->instance_size(), slot->GetChildrenCount() * kTaggedSize);
    3765             : 
    3766       46054 :   Handle<ByteArray> object_storage = AllocateStorageFor(slot);
    3767             :   // Now we handle the interesting (JSObject) case.
    3768       92108 :   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
    3769             :   int field_count = map->NumberOfOwnDescriptors();
    3770             : 
    3771             :   // Set markers for the double properties.
    3772       78798 :   for (int i = 0; i < field_count; i++) {
    3773       32744 :     FieldIndex index = FieldIndex::ForDescriptor(*map, i);
    3774       65519 :     if (descriptors->GetDetails(i).representation().IsDouble() &&
    3775             :         index.is_inobject()) {
    3776          15 :       CHECK_GE(index.index(), FixedArray::kHeaderSize / kTaggedSize);
    3777          15 :       int array_index = index.index() * kTaggedSize - FixedArray::kHeaderSize;
    3778          30 :       uint8_t marker = map->IsUnboxedDoubleField(index)
    3779             :                            ? kStoreUnboxedDouble
    3780          15 :                            : kStoreMutableHeapNumber;
    3781             :       object_storage->set(array_index, marker);
    3782             :     }
    3783             :   }
    3784             :   slot->set_storage(object_storage);
    3785       46054 : }
    3786             : 
    3787      703730 : Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
    3788             :                                                    int* value_index) {
    3789     2111190 :   TranslatedValue* slot = frame->ValueAt(*value_index);
    3790      703730 :   SkipSlots(1, frame, value_index);
    3791      703730 :   if (slot->kind() == TranslatedValue::kDuplicatedObject) {
    3792         405 :     slot = ResolveCapturedObject(slot);
    3793             :   }
    3794      703730 :   CHECK_NE(TranslatedValue::kUninitialized, slot->materialization_state());
    3795      703730 :   return slot->GetStorage();
    3796             : }
    3797             : 
    3798       46054 : void TranslatedState::InitializeJSObjectAt(
    3799             :     TranslatedFrame* frame, int* value_index, TranslatedValue* slot,
    3800       46054 :     Handle<Map> map, const DisallowHeapAllocation& no_allocation) {
    3801       46054 :   Handle<HeapObject> object_storage = Handle<HeapObject>::cast(slot->storage_);
    3802             :   DCHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
    3803             : 
    3804             :   // The object should have at least a map and some payload.
    3805       46054 :   CHECK_GE(slot->GetChildrenCount(), 2);
    3806             : 
    3807             :   // Notify the concurrent marker about the layout change.
    3808             :   isolate()->heap()->NotifyObjectLayoutChange(
    3809       92108 :       *object_storage, slot->GetChildrenCount() * kTaggedSize, no_allocation);
    3810             : 
    3811             :   // Fill the property array field.
    3812             :   {
    3813       46054 :     Handle<Object> properties = GetValueAndAdvance(frame, value_index);
    3814       46054 :     WRITE_FIELD(*object_storage, JSObject::kPropertiesOrHashOffset,
    3815             :                 *properties);
    3816       92108 :     WRITE_BARRIER(*object_storage, JSObject::kPropertiesOrHashOffset,
    3817             :                   *properties);
    3818             :   }
    3819             : 
    3820             :   // For all the other fields we first look at the fixed array and check the
    3821             :   // marker to see if we store an unboxed double.
    3822             :   DCHECK_EQ(kTaggedSize, JSObject::kPropertiesOrHashOffset);
    3823      253018 :   for (int i = 2; i < slot->GetChildrenCount(); i++) {
    3824             :     // Initialize and extract the value from its slot.
    3825       80455 :     Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
    3826             : 
    3827             :     // Read out the marker and ensure the field is consistent with
    3828             :     // what the markers in the storage say (note that all heap numbers
    3829             :     // should be fully initialized by now).
    3830       80455 :     int offset = i * kTaggedSize;
    3831       80455 :     uint8_t marker = READ_UINT8_FIELD(*object_storage, offset);
    3832       80455 :     if (marker == kStoreUnboxedDouble) {
    3833             :       double double_field_value;
    3834          30 :       if (field_value->IsSmi()) {
    3835           4 :         double_field_value = Smi::cast(*field_value)->value();
    3836             :       } else {
    3837          22 :         CHECK(field_value->IsHeapNumber());
    3838             :         double_field_value = HeapNumber::cast(*field_value)->value();
    3839             :       }
    3840          15 :       WRITE_DOUBLE_FIELD(*object_storage, offset, double_field_value);
    3841       80440 :     } else if (marker == kStoreMutableHeapNumber) {
    3842           0 :       CHECK(field_value->IsMutableHeapNumber());
    3843           0 :       WRITE_FIELD(*object_storage, offset, *field_value);
    3844           0 :       WRITE_BARRIER(*object_storage, offset, *field_value);
    3845             :     } else {
    3846       80440 :       CHECK_EQ(kStoreTagged, marker);
    3847       80440 :       WRITE_FIELD(*object_storage, offset, *field_value);
    3848      160880 :       WRITE_BARRIER(*object_storage, offset, *field_value);
    3849             :     }
    3850             :   }
    3851       46054 :   object_storage->synchronized_set_map(*map);
    3852       46054 : }
    3853             : 
    3854         773 : void TranslatedState::InitializeObjectWithTaggedFieldsAt(
    3855             :     TranslatedFrame* frame, int* value_index, TranslatedValue* slot,
    3856        1517 :     Handle<Map> map, const DisallowHeapAllocation& no_allocation) {
    3857         773 :   Handle<HeapObject> object_storage = Handle<HeapObject>::cast(slot->storage_);
    3858             : 
    3859             :   // Skip the writes if we already have the canonical empty fixed array.
    3860         773 :   if (*object_storage == ReadOnlyRoots(isolate()).empty_fixed_array()) {
    3861          29 :     CHECK_EQ(2, slot->GetChildrenCount());
    3862          29 :     Handle<Object> length_value = GetValueAndAdvance(frame, value_index);
    3863          87 :     CHECK_EQ(*length_value, Smi::FromInt(0));
    3864         773 :     return;
    3865             :   }
    3866             : 
    3867             :   // Notify the concurrent marker about the layout change.
    3868             :   isolate()->heap()->NotifyObjectLayoutChange(
    3869        1488 :       *object_storage, slot->GetChildrenCount() * kTaggedSize, no_allocation);
    3870             : 
    3871             :   // Write the fields to the object.
    3872     1155872 :   for (int i = 1; i < slot->GetChildrenCount(); i++) {
    3873      577192 :     Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
    3874      577192 :     int offset = i * kTaggedSize;
    3875      577192 :     uint8_t marker = READ_UINT8_FIELD(*object_storage, offset);
    3876      577192 :     if (i > 1 && marker == kStoreMutableHeapNumber) {
    3877          16 :       CHECK(field_value->IsMutableHeapNumber());
    3878             :     } else {
    3879      577184 :       CHECK(marker == kStoreTagged || i == 1);
    3880     1154368 :       CHECK(!field_value->IsMutableHeapNumber());
    3881             :     }
    3882             : 
    3883      577192 :     WRITE_FIELD(*object_storage, offset, *field_value);
    3884     1154384 :     WRITE_BARRIER(*object_storage, offset, *field_value);
    3885             :   }
    3886             : 
    3887         744 :   object_storage->synchronized_set_map(*map);
    3888             : }
    3889             : 
    3890      250007 : TranslatedValue* TranslatedState::ResolveCapturedObject(TranslatedValue* slot) {
    3891      250007 :   while (slot->kind() == TranslatedValue::kDuplicatedObject) {
    3892       57091 :     slot = GetValueByObjectIndex(slot->object_index());
    3893             :   }
    3894       96458 :   CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
    3895       96458 :   return slot;
    3896             : }
    3897             : 
    3898          42 : TranslatedFrame* TranslatedState::GetFrameFromJSFrameIndex(int jsframe_index) {
    3899         168 :   for (size_t i = 0; i < frames_.size(); i++) {
    3900         266 :     if (frames_[i].kind() == TranslatedFrame::kInterpretedFunction ||
    3901          84 :         frames_[i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
    3902             :         frames_[i].kind() ==
    3903             :             TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
    3904          84 :       if (jsframe_index > 0) {
    3905          42 :         jsframe_index--;
    3906             :       } else {
    3907             :         return &(frames_[i]);
    3908             :       }
    3909             :     }
    3910             :   }
    3911             :   return nullptr;
    3912             : }
    3913             : 
    3914        2614 : TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
    3915             :     int jsframe_index, int* args_count) {
    3916       28026 :   for (size_t i = 0; i < frames_.size(); i++) {
    3917       50036 :     if (frames_[i].kind() == TranslatedFrame::kInterpretedFunction ||
    3918       19389 :         frames_[i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
    3919             :         frames_[i].kind() ==
    3920             :             TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
    3921        8637 :       if (jsframe_index > 0) {
    3922        6023 :         jsframe_index--;
    3923             :       } else {
    3924             :         // We have the JS function frame, now check if it has arguments
    3925             :         // adaptor.
    3926        5228 :         if (i > 0 &&
    3927        5228 :             frames_[i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
    3928        2184 :           *args_count = frames_[i - 1].height();
    3929        1092 :           return &(frames_[i - 1]);
    3930             :         }
    3931             :         *args_count =
    3932        1522 :             frames_[i].shared_info()->internal_formal_parameter_count() + 1;
    3933        1522 :         return &(frames_[i]);
    3934             :       }
    3935             :     }
    3936             :   }
    3937             :   return nullptr;
    3938             : }
    3939             : 
    3940         169 : void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
    3941             :   MaterializedObjectStore* materialized_store =
    3942         169 :       isolate_->materialized_object_store();
    3943             :   Handle<FixedArray> previously_materialized_objects =
    3944         169 :       materialized_store->Get(stack_frame_pointer_);
    3945             : 
    3946         169 :   Handle<Object> marker = isolate_->factory()->arguments_marker();
    3947             : 
    3948         169 :   int length = static_cast<int>(object_positions_.size());
    3949             :   bool new_store = false;
    3950         169 :   if (previously_materialized_objects.is_null()) {
    3951             :     previously_materialized_objects =
    3952         141 :         isolate_->factory()->NewFixedArray(length, TENURED);
    3953         527 :     for (int i = 0; i < length; i++) {
    3954         386 :       previously_materialized_objects->set(i, *marker);
    3955             :     }
    3956             :     new_store = true;
    3957             :   }
    3958             : 
    3959         169 :   CHECK_EQ(length, previously_materialized_objects->length());
    3960             : 
    3961             :   bool value_changed = false;
    3962         456 :   for (int i = 0; i < length; i++) {
    3963         456 :     TranslatedState::ObjectPosition pos = object_positions_[i];
    3964             :     TranslatedValue* value_info =
    3965         597 :         &(frames_[pos.frame_index_].values_[pos.value_index_]);
    3966             : 
    3967         456 :     CHECK(value_info->IsMaterializedObject());
    3968             : 
    3969             :     // Skip duplicate objects (i.e., those that point to some
    3970             :     // other object id).
    3971         456 :     if (value_info->object_index() != i) continue;
    3972             : 
    3973         302 :     Handle<Object> value(value_info->GetRawValue(), isolate_);
    3974             : 
    3975         302 :     if (!value.is_identical_to(marker)) {
    3976         267 :       if (previously_materialized_objects->get(i) == *marker) {
    3977         225 :         previously_materialized_objects->set(i, *value);
    3978             :         value_changed = true;
    3979             :       } else {
    3980          42 :         CHECK(previously_materialized_objects->get(i) == *value);
    3981             :       }
    3982             :     }
    3983             :   }
    3984         169 :   if (new_store && value_changed) {
    3985             :     materialized_store->Set(stack_frame_pointer_,
    3986         141 :                             previously_materialized_objects);
    3987         141 :     CHECK_EQ(frames_[0].kind(), TranslatedFrame::kInterpretedFunction);
    3988         282 :     CHECK_EQ(frame->function(), frames_[0].front().GetRawValue());
    3989         141 :     Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode());
    3990             :   }
    3991         169 : }
    3992             : 
    3993     1396026 : void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
    3994             :   MaterializedObjectStore* materialized_store =
    3995     1396026 :       isolate_->materialized_object_store();
    3996             :   Handle<FixedArray> previously_materialized_objects =
    3997     1396026 :       materialized_store->Get(stack_frame_pointer_);
    3998             : 
    3999             :   // If we have no previously materialized objects, there is nothing to do.
    4000     2792052 :   if (previously_materialized_objects.is_null()) return;
    4001             : 
    4002         197 :   Handle<Object> marker = isolate_->factory()->arguments_marker();
    4003             : 
    4004         197 :   int length = static_cast<int>(object_positions_.size());
    4005         197 :   CHECK_EQ(length, previously_materialized_objects->length());
    4006             : 
    4007         526 :   for (int i = 0; i < length; i++) {
    4008             :     // For a previously materialized objects, inject their value into the
    4009             :     // translated values.
    4010         526 :     if (previously_materialized_objects->get(i) != *marker) {
    4011         309 :       TranslatedState::ObjectPosition pos = object_positions_[i];
    4012             :       TranslatedValue* value_info =
    4013         309 :           &(frames_[pos.frame_index_].values_[pos.value_index_]);
    4014         309 :       CHECK(value_info->IsMaterializedObject());
    4015             : 
    4016         309 :       if (value_info->kind() == TranslatedValue::kCapturedObject) {
    4017             :         value_info->set_initialized_storage(
    4018         309 :             Handle<Object>(previously_materialized_objects->get(i), isolate_));
    4019             :       }
    4020             :     }
    4021             :   }
    4022             : }
    4023             : 
    4024           0 : void TranslatedState::VerifyMaterializedObjects() {
    4025             : #if VERIFY_HEAP
    4026             :   int length = static_cast<int>(object_positions_.size());
    4027             :   for (int i = 0; i < length; i++) {
    4028             :     TranslatedValue* slot = GetValueByObjectIndex(i);
    4029             :     if (slot->kind() == TranslatedValue::kCapturedObject) {
    4030             :       CHECK_EQ(slot, GetValueByObjectIndex(slot->object_index()));
    4031             :       if (slot->materialization_state() == TranslatedValue::kFinished) {
    4032             :         slot->GetStorage()->ObjectVerify(isolate());
    4033             :       } else {
    4034             :         CHECK_EQ(slot->materialization_state(),
    4035             :                  TranslatedValue::kUninitialized);
    4036             :       }
    4037             :     }
    4038             :   }
    4039             : #endif
    4040           0 : }
    4041             : 
    4042       47054 : bool TranslatedState::DoUpdateFeedback() {
    4043       45171 :   if (!feedback_vector_handle_.is_null()) {
    4044        1883 :     CHECK(!feedback_slot_.IsInvalid());
    4045        1883 :     isolate()->CountUsage(v8::Isolate::kDeoptimizerDisableSpeculation);
    4046        1883 :     FeedbackNexus nexus(feedback_vector_handle_, feedback_slot_);
    4047        1883 :     nexus.SetSpeculationMode(SpeculationMode::kDisallowSpeculation);
    4048             :     return true;
    4049             :   }
    4050             :   return false;
    4051             : }
    4052             : 
    4053        1883 : void TranslatedState::ReadUpdateFeedback(TranslationIterator* iterator,
    4054             :                                          FixedArray literal_array,
    4055             :                                          FILE* trace_file) {
    4056        3766 :   CHECK_EQ(Translation::UPDATE_FEEDBACK, iterator->Next());
    4057        3766 :   feedback_vector_ = FeedbackVector::cast(literal_array->get(iterator->Next()));
    4058        1883 :   feedback_slot_ = FeedbackSlot(iterator->Next());
    4059        1883 :   if (trace_file != nullptr) {
    4060             :     PrintF(trace_file, "  reading FeedbackVector (slot %d)\n",
    4061           0 :            feedback_slot_.ToInt());
    4062             :   }
    4063        1883 : }
    4064             : 
    4065             : }  // namespace internal
    4066      178779 : }  // namespace v8
    4067             : 
    4068             : // Undefine the heap manipulation macros.
    4069             : #include "src/objects/object-macros-undef.h"

Generated by: LCOV version 1.10