LCOV - code coverage report
Current view: top level - src - deoptimizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1368 1567 87.3 %
Date: 2019-04-19 Functions: 123 169 72.8 %

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

Generated by: LCOV version 1.10