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