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