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

Generated by: LCOV version 1.10