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