5 #include "src/deoptimizer.h" 9 #include "src/accessors.h" 10 #include "src/assembler-inl.h" 11 #include "src/ast/prettyprinter.h" 12 #include "src/callable.h" 13 #include "src/counters.h" 14 #include "src/disasm.h" 15 #include "src/frames-inl.h" 16 #include "src/global-handles.h" 17 #include "src/interpreter/interpreter.h" 18 #include "src/macro-assembler.h" 19 #include "src/objects/debug-objects-inl.h" 20 #include "src/objects/smi.h" 21 #include "src/register-configuration.h" 22 #include "src/tracing/trace-event.h" 26 #include "src/objects/object-macros.h" 36 static const int NO_INPUT_INDEX = -1;
39 : deoptimizer_(deoptimizer),
41 trace_scope_(trace_scope),
42 top_offset_(frame->GetFrameSize()) {}
44 void PushRawValue(intptr_t value,
const char* debug_hint) {
47 if (trace_scope_ !=
nullptr) {
48 DebugPrintOutputValue(value, debug_hint);
52 void PushRawObject(
Object* obj,
const char* debug_hint) {
53 intptr_t value =
reinterpret_cast<intptr_t
>(obj);
55 if (trace_scope_ !=
nullptr) {
56 DebugPrintOutputObject(obj, top_offset_, debug_hint);
60 void PushCallerPc(intptr_t pc) {
61 top_offset_ -= kPCOnStackSize;
62 frame_->SetCallerPc(top_offset_, pc);
63 DebugPrintOutputValue(pc,
"caller's pc\n");
66 void PushCallerFp(intptr_t fp) {
67 top_offset_ -= kFPOnStackSize;
68 frame_->SetCallerFp(top_offset_, fp);
69 DebugPrintOutputValue(fp,
"caller's fp\n");
72 void PushCallerConstantPool(intptr_t cp) {
73 top_offset_ -= kPointerSize;
74 frame_->SetCallerConstantPool(top_offset_, cp);
75 DebugPrintOutputValue(cp,
"caller's constant_pool\n");
79 const char* debug_hint =
"") {
80 Object* obj = iterator->GetRawValue();
82 PushRawObject(obj, debug_hint);
85 PrintF(trace_scope_->file(),
" (input #%d)\n", iterator.input_index());
88 deoptimizer_->QueueValueForMaterialization(output_address(top_offset_), obj,
92 unsigned top_offset()
const {
return top_offset_; }
95 void PushValue(intptr_t value) {
96 CHECK_GE(top_offset_, 0);
97 top_offset_ -= kPointerSize;
98 frame_->SetFrameSlot(top_offset_, value);
101 Address output_address(
unsigned output_offset) {
103 static_cast<Address>(frame_->GetTop()) + output_offset;
104 return output_address;
107 void DebugPrintOutputValue(intptr_t value,
const char* debug_hint =
"") {
108 if (trace_scope_ !=
nullptr) {
109 PrintF(trace_scope_->file(),
110 " " V8PRIxPTR_FMT
": [top + %3d] <- " V8PRIxPTR_FMT
" ; %s",
111 output_address(top_offset_), top_offset_, value, debug_hint);
115 void DebugPrintOutputObject(
Object* obj,
unsigned output_offset,
116 const char* debug_hint =
"") {
117 if (trace_scope_ !=
nullptr) {
118 PrintF(trace_scope_->file(),
" " V8PRIxPTR_FMT
": [top + %3d] <- ",
119 output_address(output_offset), output_offset);
121 PrintF(V8PRIxPTR_FMT
" <Smi %d>", reinterpret_cast<Address>(obj),
122 Smi::cast(obj)->value());
124 obj->ShortPrint(trace_scope_->file());
126 PrintF(trace_scope_->file(),
" ; %s", debug_hint);
133 unsigned top_offset_;
136 DeoptimizerData::DeoptimizerData(
Heap* heap) : heap_(heap), current_(nullptr) {
137 Code* start = &deopt_entry_code_[0];
138 Code* end = &deopt_entry_code_[DeoptimizerData::kLastDeoptimizeKind + 1];
143 DeoptimizerData::~DeoptimizerData() {
144 Code* start = &deopt_entry_code_[0];
145 heap_->UnregisterStrongRoots(ObjectSlot(start));
148 Code DeoptimizerData::deopt_entry_code(DeoptimizeKind kind) {
149 return deopt_entry_code_[
static_cast<int>(kind)];
152 void DeoptimizerData::set_deopt_entry_code(DeoptimizeKind kind, Code code) {
153 deopt_entry_code_[
static_cast<int>(kind)] = code;
156 Code Deoptimizer::FindDeoptimizingCode(Address addr) {
157 if (function_->IsHeapObject()) {
159 Isolate* isolate = isolate_;
160 Context native_context = function_->context()->native_context();
161 Object* element = native_context->DeoptimizedCodeListHead();
162 while (!element->IsUndefined(isolate)) {
163 Code code = Code::cast(element);
164 CHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
165 if (code->contains(addr))
return code;
166 element = code->next_code_link();
175 Deoptimizer* Deoptimizer::New(JSFunction*
function, DeoptimizeKind kind,
176 unsigned bailout_id, Address from,
177 int fp_to_sp_delta, Isolate* isolate) {
178 Deoptimizer* deoptimizer =
new Deoptimizer(isolate,
function, kind,
179 bailout_id, from, fp_to_sp_delta);
180 CHECK_NULL(isolate->deoptimizer_data()->current_);
181 isolate->deoptimizer_data()->current_ = deoptimizer;
186 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
187 Deoptimizer* result = isolate->deoptimizer_data()->current_;
188 CHECK_NOT_NULL(result);
189 result->DeleteFrameDescriptions();
190 isolate->deoptimizer_data()->current_ =
nullptr;
194 DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
195 JavaScriptFrame* frame,
198 CHECK(frame->is_optimized());
200 TranslatedState translated_values(frame);
201 translated_values.Prepare(frame->fp());
203 TranslatedState::iterator frame_it = translated_values.end();
204 int counter = jsframe_index;
205 for (
auto it = translated_values.begin(); it != translated_values.end();
207 if (it->kind() == TranslatedFrame::kInterpretedFunction ||
208 it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
210 TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
218 CHECK(frame_it != translated_values.end());
221 CHECK_EQ(frame_it->kind(), TranslatedFrame::kInterpretedFunction);
223 DeoptimizedFrameInfo* info =
224 new DeoptimizedFrameInfo(&translated_values, frame_it, isolate);
229 void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
int count,
230 DeoptimizeKind kind) {
231 NoRootArrayScope no_root_array(masm);
232 TableEntryGenerator generator(masm, kind, count);
233 generator.Generate();
237 class ActivationsFinder :
public ThreadVisitor {
239 explicit ActivationsFinder(std::set<Code>* codes, Code topmost_optimized_code,
240 bool safe_to_deopt_topmost_optimized_code)
243 topmost_ = topmost_optimized_code;
244 safe_to_deopt_ = safe_to_deopt_topmost_optimized_code;
251 void VisitThread(Isolate* isolate, ThreadLocalTop* top)
override {
252 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
253 if (it.frame()->type() == StackFrame::OPTIMIZED) {
254 Code code = it.frame()->LookupCode();
255 if (code->kind() == Code::OPTIMIZED_FUNCTION &&
256 code->marked_for_deoptimization()) {
259 SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
260 int trampoline_pc = safepoint.trampoline_pc();
261 DCHECK_IMPLIES(code == topmost_, safe_to_deopt_);
263 it.frame()->set_pc(code->raw_instruction_start() + trampoline_pc);
270 std::set<Code>* codes_;
281 void Deoptimizer::DeoptimizeMarkedCodeForContext(Context context) {
282 DisallowHeapAllocation no_allocation;
284 Isolate* isolate = context->GetHeap()->isolate();
285 Code topmost_optimized_code;
286 bool safe_to_deopt_topmost_optimized_code =
false;
291 for (StackFrameIterator it(isolate, isolate->thread_local_top());
292 !it.done(); it.Advance()) {
293 StackFrame::Type type = it.frame()->type();
294 if (type == StackFrame::OPTIMIZED) {
295 Code code = it.frame()->LookupCode();
296 JSFunction*
function =
297 static_cast<OptimizedFrame*
>(it.frame())->
function();
298 if (FLAG_trace_deopt) {
299 CodeTracer::Scope scope(isolate->GetCodeTracer());
300 PrintF(scope.file(),
"[deoptimizer found activation of function: ");
301 function->PrintName(scope.file());
303 " / %" V8PRIxPTR
"]\n",
reinterpret_cast<intptr_t
>(
function));
305 SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
306 int deopt_index = safepoint.deoptimization_index();
309 bool safe_if_deopt_triggered =
310 deopt_index != Safepoint::kNoDeoptimizationIndex;
311 bool is_builtin_code = code->kind() == Code::BUILTIN;
312 DCHECK(topmost_optimized_code.is_null() || safe_if_deopt_triggered ||
314 if (topmost_optimized_code.is_null()) {
315 topmost_optimized_code = code;
316 safe_to_deopt_topmost_optimized_code = safe_if_deopt_triggered;
324 std::set<Code> codes;
329 Object* element = context->OptimizedCodeListHead();
330 while (!element->IsUndefined(isolate)) {
331 Code code = Code::cast(element);
332 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
333 Object* next = code->next_code_link();
335 if (code->marked_for_deoptimization()) {
338 if (!prev.is_null()) {
340 prev->set_next_code_link(next);
343 context->SetOptimizedCodeListHead(next);
347 code->set_next_code_link(context->DeoptimizedCodeListHead());
348 context->SetDeoptimizedCodeListHead(code);
356 ActivationsFinder visitor(&codes, topmost_optimized_code,
357 safe_to_deopt_topmost_optimized_code);
359 visitor.VisitThread(isolate, isolate->thread_local_top());
363 isolate->thread_manager()->IterateArchivedThreads(&visitor);
368 for (Code code : codes) {
369 isolate->heap()->InvalidateCodeDeoptimizationData(code);
374 void Deoptimizer::DeoptimizeAll(Isolate* isolate) {
375 RuntimeCallTimerScope runtimeTimer(isolate,
376 RuntimeCallCounterId::kDeoptimizeCode);
377 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
378 TRACE_EVENT0(
"v8",
"V8.DeoptimizeCode");
379 if (FLAG_trace_deopt) {
380 CodeTracer::Scope scope(isolate->GetCodeTracer());
381 PrintF(scope.file(),
"[deoptimize all code in all contexts]\n");
383 isolate->AbortConcurrentOptimization(BlockingBehavior::kBlock);
384 DisallowHeapAllocation no_allocation;
386 Object* context = isolate->heap()->native_contexts_list();
387 while (!context->IsUndefined(isolate)) {
388 Context native_context = Context::cast(context);
389 MarkAllCodeForContext(native_context);
390 DeoptimizeMarkedCodeForContext(native_context);
391 context = native_context->next_context_link();
396 void Deoptimizer::DeoptimizeMarkedCode(Isolate* isolate) {
397 RuntimeCallTimerScope runtimeTimer(isolate,
398 RuntimeCallCounterId::kDeoptimizeCode);
399 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
400 TRACE_EVENT0(
"v8",
"V8.DeoptimizeCode");
401 if (FLAG_trace_deopt) {
402 CodeTracer::Scope scope(isolate->GetCodeTracer());
403 PrintF(scope.file(),
"[deoptimize marked code in all contexts]\n");
405 DisallowHeapAllocation no_allocation;
407 Object* context = isolate->heap()->native_contexts_list();
408 while (!context->IsUndefined(isolate)) {
409 Context native_context = Context::cast(context);
410 DeoptimizeMarkedCodeForContext(native_context);
411 context = native_context->next_context_link();
415 void Deoptimizer::MarkAllCodeForContext(Context context) {
416 Object* element = context->OptimizedCodeListHead();
417 Isolate* isolate = context->GetIsolate();
418 while (!element->IsUndefined(isolate)) {
419 Code code = Code::cast(element);
420 CHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
421 code->set_marked_for_deoptimization(
true);
422 element = code->next_code_link();
426 void Deoptimizer::DeoptimizeFunction(JSFunction*
function, Code code) {
427 Isolate* isolate =
function->GetIsolate();
428 RuntimeCallTimerScope runtimeTimer(isolate,
429 RuntimeCallCounterId::kDeoptimizeCode);
430 TimerEventScope<TimerEventDeoptimizeCode> timer(isolate);
431 TRACE_EVENT0(
"v8",
"V8.DeoptimizeCode");
432 if (code.is_null()) code = function->code();
434 if (code->kind() == Code::OPTIMIZED_FUNCTION) {
438 code->set_marked_for_deoptimization(
true);
441 function->feedback_vector()->EvictOptimizedCodeMarkedForDeoptimization(
442 function->shared(),
"unlinking code marked for deopt");
443 if (!code->deopt_already_counted()) {
444 function->feedback_vector()->increment_deopt_count();
445 code->set_deopt_already_counted(
true);
447 DeoptimizeMarkedCodeForContext(function->context()->native_context());
452 void Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
453 deoptimizer->DoComputeOutputFrames();
456 const char* Deoptimizer::MessageFor(DeoptimizeKind kind) {
458 case DeoptimizeKind::kEager:
460 case DeoptimizeKind::kSoft:
462 case DeoptimizeKind::kLazy:
465 FATAL(
"Unsupported deopt kind");
469 Deoptimizer::Deoptimizer(Isolate* isolate, JSFunction*
function,
470 DeoptimizeKind kind,
unsigned bailout_id, Address from,
474 bailout_id_(bailout_id),
477 fp_to_sp_delta_(fp_to_sp_delta),
478 deoptimizing_throw_(false),
479 catch_handler_data_(-1),
480 catch_handler_pc_offset_(-1),
485 caller_frame_top_(0),
488 caller_constant_pool_(0),
489 input_frame_context_(0),
491 trace_scope_(nullptr) {
492 if (isolate->deoptimizer_lazy_throw()) {
493 isolate->set_deoptimizer_lazy_throw(
false);
494 deoptimizing_throw_ =
true;
497 DCHECK_NE(from, kNullAddress);
498 compiled_code_ = FindOptimizedCode();
499 DCHECK(!compiled_code_.is_null());
501 DCHECK(function->IsJSFunction());
502 trace_scope_ = FLAG_trace_deopt
503 ?
new CodeTracer::Scope(isolate->GetCodeTracer())
506 DCHECK(AllowHeapAllocation::IsAllowed());
507 disallow_heap_allocation_ =
new DisallowHeapAllocation();
509 if (compiled_code_->kind() != Code::OPTIMIZED_FUNCTION ||
510 !compiled_code_->deopt_already_counted()) {
515 if (deopt_kind_ == DeoptimizeKind::kSoft) {
518 isolate->counters()->soft_deopts_executed()->Increment();
519 }
else if (
function !=
nullptr) {
520 function->feedback_vector()->increment_deopt_count();
523 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
524 compiled_code_->set_deopt_already_counted(
true);
526 CodeDeoptEvent(compiled_code_, kind, from_, fp_to_sp_delta_));
528 unsigned size = ComputeInputFrameSize();
529 int parameter_count =
530 function->shared()->internal_formal_parameter_count() + 1;
531 input_ =
new (size) FrameDescription(size, parameter_count);
534 Code Deoptimizer::FindOptimizedCode() {
535 Code compiled_code = FindDeoptimizingCode(from_);
536 return !compiled_code.is_null() ? compiled_code
537 : isolate_->FindCodeObject(from_);
541 void Deoptimizer::PrintFunctionName() {
542 if (function_->IsHeapObject() && function_->IsJSFunction()) {
543 function_->ShortPrint(trace_scope_->file());
545 PrintF(trace_scope_->file(),
546 "%s", Code::Kind2String(compiled_code_->kind()));
550 Handle<JSFunction> Deoptimizer::function()
const {
551 return Handle<JSFunction>(function_, isolate());
553 Handle<Code> Deoptimizer::compiled_code()
const {
554 return Handle<Code>(compiled_code_, isolate());
557 Deoptimizer::~Deoptimizer() {
558 DCHECK(input_ ==
nullptr && output_ ==
nullptr);
559 DCHECK_NULL(disallow_heap_allocation_);
564 void Deoptimizer::DeleteFrameDescriptions() {
566 for (
int i = 0;
i < output_count_; ++
i) {
567 if (output_[
i] != input_)
delete output_[
i];
573 DCHECK(!AllowHeapAllocation::IsAllowed());
574 DCHECK_NOT_NULL(disallow_heap_allocation_);
575 delete disallow_heap_allocation_;
576 disallow_heap_allocation_ =
nullptr;
580 Address Deoptimizer::GetDeoptimizationEntry(Isolate* isolate,
int id,
581 DeoptimizeKind kind) {
583 if (
id >= kMaxNumberOfEntries)
return kNullAddress;
584 DeoptimizerData* data = isolate->deoptimizer_data();
585 CHECK_LE(kind, DeoptimizerData::kLastDeoptimizeKind);
586 CHECK(!data->deopt_entry_code(kind).is_null());
587 Code code = data->deopt_entry_code(kind);
588 return code->raw_instruction_start() + (
id * table_entry_size_);
591 int Deoptimizer::GetDeoptimizationId(Isolate* isolate, Address addr,
592 DeoptimizeKind kind) {
593 DeoptimizerData* data = isolate->deoptimizer_data();
594 CHECK_LE(kind, DeoptimizerData::kLastDeoptimizeKind);
595 DCHECK(IsInDeoptimizationTable(isolate, addr, kind));
596 Code code = data->deopt_entry_code(kind);
597 Address start = code->raw_instruction_start();
599 static_cast<int>(addr - start) % table_entry_size_);
600 return static_cast<int>(addr - start) / table_entry_size_;
603 bool Deoptimizer::IsInDeoptimizationTable(Isolate* isolate, Address addr,
604 DeoptimizeKind type) {
605 DeoptimizerData* data = isolate->deoptimizer_data();
606 CHECK_LE(type, DeoptimizerData::kLastDeoptimizeKind);
607 Code code = data->deopt_entry_code(type);
608 if (code.is_null())
return false;
609 Address start = code->raw_instruction_start();
610 return ((table_entry_size_ == 0 && addr == start) ||
612 addr < start + (kMaxNumberOfEntries * table_entry_size_)));
615 bool Deoptimizer::IsDeoptimizationEntry(Isolate* isolate, Address addr,
616 DeoptimizeKind* type) {
617 if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kEager)) {
618 *type = DeoptimizeKind::kEager;
621 if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kSoft)) {
622 *type = DeoptimizeKind::kSoft;
625 if (IsInDeoptimizationTable(isolate, addr, DeoptimizeKind::kLazy)) {
626 *type = DeoptimizeKind::kLazy;
632 int Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
635 Object* context = isolate->heap()->native_contexts_list();
636 while (!context->IsUndefined(isolate)) {
637 Context native_context = Context::cast(context);
638 Object* element = native_context->DeoptimizedCodeListHead();
639 while (!element->IsUndefined(isolate)) {
640 Code code = Code::cast(element);
641 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
642 if (!code->marked_for_deoptimization()) {
645 element = code->next_code_link();
647 context = Context::cast(context)->next_context_link();
654 int LookupCatchHandler(TranslatedFrame* translated_frame,
int* data_out) {
655 switch (translated_frame->kind()) {
656 case TranslatedFrame::kInterpretedFunction: {
657 int bytecode_offset = translated_frame->node_id().ToInt();
659 translated_frame->raw_shared_info()->GetBytecodeArray());
660 return table.LookupRange(bytecode_offset, data_out,
nullptr);
662 case TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch: {
671 bool ShouldPadArguments(
int arg_count) {
672 return kPadArguments && (arg_count % 2 != 0);
679 void Deoptimizer::DoComputeOutputFrames() {
680 base::ElapsedTimer timer;
684 DeoptimizationData input_data =
685 DeoptimizationData::cast(compiled_code_->deoptimization_data());
691 Register fp_reg = JavaScriptFrame::fp_register();
692 stack_fp_ = input_->GetRegister(fp_reg.code());
694 caller_frame_top_ = stack_fp_ + ComputeInputFrameAboveFpFixedSize();
696 Address fp_address = input_->GetFramePointerAddress();
697 caller_fp_ = Memory<intptr_t>(fp_address);
699 Memory<intptr_t>(fp_address + CommonFrameConstants::kCallerPCOffset);
700 input_frame_context_ = Memory<intptr_t>(
701 fp_address + CommonFrameConstants::kContextOrFrameTypeOffset);
703 if (FLAG_enable_embedded_constant_pool) {
704 caller_constant_pool_ = Memory<intptr_t>(
705 fp_address + CommonFrameConstants::kConstantPoolOffset);
709 if (trace_scope_ !=
nullptr) {
711 PrintF(trace_scope_->file(),
"[deoptimizing (DEOPT %s): begin ",
712 MessageFor(deopt_kind_));
714 PrintF(trace_scope_->file(),
715 " (opt #%d) @%d, FP to SP delta: %d, caller sp: " V8PRIxPTR_FMT
717 input_data->OptimizationId()->value(), bailout_id_, fp_to_sp_delta_,
719 if (deopt_kind_ == DeoptimizeKind::kEager ||
720 deopt_kind_ == DeoptimizeKind::kSoft) {
721 compiled_code_->PrintDeoptLocation(
722 trace_scope_->file(),
" ;;; deoptimize at ", from_);
726 BailoutId node_id = input_data->BytecodeOffset(bailout_id_);
727 ByteArray translations = input_data->TranslationByteArray();
728 unsigned translation_index =
729 input_data->TranslationIndex(bailout_id_)->value();
731 TranslationIterator state_iterator(translations, translation_index);
732 translated_state_.Init(
733 isolate_, input_->GetFramePointerAddress(), &state_iterator,
734 input_data->LiteralArray(), input_->GetRegisterValues(),
735 trace_scope_ ==
nullptr ? nullptr : trace_scope_->file(),
736 function_->IsHeapObject()
737 ? function_->shared()->internal_formal_parameter_count()
741 size_t count = translated_state_.frames().size();
744 if (deoptimizing_throw_) {
745 size_t catch_handler_frame_index = count;
746 for (
size_t i = count;
i-- > 0;) {
747 catch_handler_pc_offset_ = LookupCatchHandler(
748 &(translated_state_.frames()[
i]), &catch_handler_data_);
749 if (catch_handler_pc_offset_ >= 0) {
750 catch_handler_frame_index =
i;
754 CHECK_LT(catch_handler_frame_index, count);
755 count = catch_handler_frame_index + 1;
758 DCHECK_NULL(output_);
759 output_ =
new FrameDescription*[count];
760 for (
size_t i = 0;
i < count; ++
i) {
761 output_[
i] =
nullptr;
763 output_count_ =
static_cast<int>(count);
767 for (
size_t i = 0;
i < count; ++
i, ++frame_index) {
769 TranslatedFrame* translated_frame = &(translated_state_.frames()[
i]);
770 bool handle_exception = deoptimizing_throw_ &&
i == count - 1;
771 switch (translated_frame->kind()) {
772 case TranslatedFrame::kInterpretedFunction:
773 DoComputeInterpretedFrame(translated_frame, frame_index,
777 case TranslatedFrame::kArgumentsAdaptor:
778 DoComputeArgumentsAdaptorFrame(translated_frame, frame_index);
780 case TranslatedFrame::kConstructStub:
781 DoComputeConstructStubFrame(translated_frame, frame_index);
783 case TranslatedFrame::kBuiltinContinuation:
784 DoComputeBuiltinContinuation(translated_frame, frame_index,
785 BuiltinContinuationMode::STUB);
787 case TranslatedFrame::kJavaScriptBuiltinContinuation:
788 DoComputeBuiltinContinuation(translated_frame, frame_index,
789 BuiltinContinuationMode::JAVASCRIPT);
791 case TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch:
792 DoComputeBuiltinContinuation(
793 translated_frame, frame_index,
795 ? BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION
796 : BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH);
798 case TranslatedFrame::kInvalid:
799 FATAL(
"invalid frame");
804 FrameDescription* topmost = output_[count - 1];
805 topmost->GetRegisterValues()->SetRegister(kRootRegister.code(),
806 isolate()->isolate_root());
809 if (trace_scope_ !=
nullptr) {
810 double ms = timer.Elapsed().InMillisecondsF();
811 int index = output_count_ - 1;
812 PrintF(trace_scope_->file(),
"[deoptimizing (%s): end ",
813 MessageFor(deopt_kind_));
815 PrintF(trace_scope_->file(),
816 " @%d => node=%d, pc=" V8PRIxPTR_FMT
", caller sp=" V8PRIxPTR_FMT
817 ", took %0.3f ms]\n",
818 bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
819 caller_frame_top_, ms);
823 void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
825 bool goto_catch_handler) {
826 SharedFunctionInfo* shared = translated_frame->raw_shared_info();
828 TranslatedFrame::iterator value_iterator = translated_frame->begin();
829 bool is_bottommost = (0 == frame_index);
830 bool is_topmost = (output_count_ - 1 == frame_index);
832 int bytecode_offset = translated_frame->node_id().ToInt();
833 int height = translated_frame->height();
834 int register_count = height - 1;
835 int register_stack_slot_count =
836 InterpreterFrameConstants::RegisterStackSlotCount(register_count);
837 int height_in_bytes = register_stack_slot_count * kPointerSize;
841 height_in_bytes += kPointerSize;
842 if (PadTopOfStackRegister()) height_in_bytes += kPointerSize;
845 TranslatedFrame::iterator function_iterator = value_iterator++;
846 if (trace_scope_ !=
nullptr) {
847 PrintF(trace_scope_->file(),
" translating interpreted frame ");
848 std::unique_ptr<char[]> name = shared->DebugName()->ToCString();
849 PrintF(trace_scope_->file(),
"%s", name.get());
850 PrintF(trace_scope_->file(),
" => bytecode_offset=%d, height=%d%s\n",
851 bytecode_offset, height_in_bytes,
852 goto_catch_handler ?
" (throw)" :
"");
854 if (goto_catch_handler) {
855 bytecode_offset = catch_handler_pc_offset_;
861 unsigned fixed_frame_size = ComputeInterpretedFixedSize(shared);
862 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
865 int parameter_count = shared->internal_formal_parameter_count() + 1;
866 FrameDescription* output_frame =
new (output_frame_size)
867 FrameDescription(output_frame_size, parameter_count);
868 FrameWriter frame_writer(
this, output_frame, trace_scope_);
870 CHECK(frame_index >= 0 && frame_index < output_count_);
871 CHECK_NULL(output_[frame_index]);
872 output_[frame_index] = output_frame;
876 intptr_t top_address;
878 top_address = caller_frame_top_ - output_frame_size;
880 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
882 output_frame->SetTop(top_address);
886 ReadOnlyRoots roots(isolate());
887 if (ShouldPadArguments(parameter_count)) {
888 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
891 for (
int i = 0;
i < parameter_count; ++
i, ++value_iterator) {
892 frame_writer.PushTranslatedValue(value_iterator,
"stack parameter");
895 DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
896 frame_writer.top_offset());
897 if (trace_scope_ !=
nullptr) {
898 PrintF(trace_scope_->file(),
" -------------------------\n");
910 const intptr_t caller_pc =
911 is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
912 frame_writer.PushCallerPc(caller_pc);
918 const intptr_t caller_fp =
919 is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
920 frame_writer.PushCallerFp(caller_fp);
922 intptr_t fp_value = top_address + frame_writer.top_offset();
923 output_frame->SetFp(fp_value);
925 Register fp_reg = InterpretedFrame::fp_register();
926 output_frame->SetRegister(fp_reg.code(), fp_value);
929 if (FLAG_enable_embedded_constant_pool) {
933 const intptr_t caller_cp =
934 is_bottommost ? caller_constant_pool_
935 : output_[frame_index - 1]->GetConstantPool();
936 frame_writer.PushCallerConstantPool(caller_cp);
945 TranslatedFrame::iterator context_pos = value_iterator++;
946 if (goto_catch_handler) {
949 for (
int i = 0;
i < catch_handler_data_ + 1; ++
i) {
954 Object* context = context_pos->GetRawValue();
955 output_frame->SetContext(reinterpret_cast<intptr_t>(context));
956 frame_writer.PushTranslatedValue(context_pos,
"context");
959 frame_writer.PushTranslatedValue(function_iterator,
"function");
962 Object* bytecode_array = shared->HasBreakInfo()
963 ? shared->GetDebugInfo()->DebugBytecodeArray()
964 : shared->GetBytecodeArray();
965 frame_writer.PushRawObject(bytecode_array,
"bytecode array\n");
968 int raw_bytecode_offset =
969 BytecodeArray::kHeaderSize - kHeapObjectTag + bytecode_offset;
970 Smi smi_bytecode_offset = Smi::FromInt(raw_bytecode_offset);
971 frame_writer.PushRawObject(smi_bytecode_offset,
"bytecode offset\n");
973 if (trace_scope_ !=
nullptr) {
974 PrintF(trace_scope_->file(),
" -------------------------\n");
980 int return_value_first_reg =
981 register_count - translated_frame->return_value_offset();
982 int return_value_count = translated_frame->return_value_count();
983 for (
int i = 0;
i < register_count; ++
i, ++value_iterator) {
986 if (is_topmost && !goto_catch_handler &&
987 deopt_kind_ == DeoptimizeKind::kLazy &&
i >= return_value_first_reg &&
988 i < return_value_first_reg + return_value_count) {
989 int return_index =
i - return_value_first_reg;
990 if (return_index == 0) {
991 frame_writer.PushRawValue(input_->GetRegister(kReturnRegister0.code()),
997 CHECK_LE(return_value_first_reg + return_value_count, register_count);
999 CHECK_EQ(return_index, 1);
1000 frame_writer.PushRawValue(input_->GetRegister(kReturnRegister1.code()),
1001 "return value 1\n");
1005 frame_writer.PushTranslatedValue(value_iterator,
"stack parameter");
1009 int register_slots_written = register_count;
1010 DCHECK_LE(register_slots_written, register_stack_slot_count);
1013 while (register_slots_written < register_stack_slot_count) {
1014 register_slots_written++;
1015 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1020 if (PadTopOfStackRegister()) {
1021 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1026 if (goto_catch_handler) {
1029 intptr_t accumulator_value =
1030 input_->GetRegister(kInterpreterAccumulatorRegister.code());
1031 frame_writer.PushRawObject(reinterpret_cast<Object*>(accumulator_value),
1036 if (deopt_kind_ == DeoptimizeKind::kLazy &&
1037 translated_frame->return_value_offset() == 0 &&
1038 translated_frame->return_value_count() > 0) {
1039 CHECK_EQ(translated_frame->return_value_count(), 1);
1040 frame_writer.PushRawValue(input_->GetRegister(kReturnRegister0.code()),
1041 "return value 0\n");
1043 frame_writer.PushTranslatedValue(value_iterator,
"accumulator");
1052 CHECK_EQ(translated_frame->end(), value_iterator);
1053 CHECK_EQ(0u, frame_writer.top_offset());
1059 Builtins* builtins = isolate_->builtins();
1060 Code dispatch_builtin =
1061 (!is_topmost || (deopt_kind_ == DeoptimizeKind::kLazy)) &&
1063 ? builtins->builtin(Builtins::kInterpreterEnterBytecodeAdvance)
1064 : builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
1065 output_frame->SetPc(
1066 static_cast<intptr_t>(dispatch_builtin->InstructionStart()));
1069 if (FLAG_enable_embedded_constant_pool) {
1070 intptr_t constant_pool_value =
1071 static_cast<intptr_t
>(dispatch_builtin->constant_pool());
1072 output_frame->SetConstantPool(constant_pool_value);
1074 Register constant_pool_reg =
1075 InterpretedFrame::constant_pool_pointer_register();
1076 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1084 intptr_t context_value =
static_cast<intptr_t
>(Smi::zero().ptr());
1085 Register context_reg = JavaScriptFrame::context_register();
1086 output_frame->SetRegister(context_reg.code(), context_value);
1088 Code continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1089 output_frame->SetContinuation(
1090 static_cast<intptr_t>(continuation->InstructionStart()));
1094 void Deoptimizer::DoComputeArgumentsAdaptorFrame(
1095 TranslatedFrame* translated_frame,
int frame_index) {
1096 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1097 bool is_bottommost = (0 == frame_index);
1099 unsigned height = translated_frame->height();
1100 unsigned height_in_bytes = height * kPointerSize;
1101 int parameter_count = height;
1102 if (ShouldPadArguments(parameter_count)) height_in_bytes += kPointerSize;
1104 TranslatedFrame::iterator function_iterator = value_iterator++;
1105 if (trace_scope_ !=
nullptr) {
1106 PrintF(trace_scope_->file(),
1107 " translating arguments adaptor => height=%d\n", height_in_bytes);
1110 unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFixedFrameSize;
1111 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1114 FrameDescription* output_frame =
new (output_frame_size)
1115 FrameDescription(output_frame_size, parameter_count);
1116 FrameWriter frame_writer(
this, output_frame, trace_scope_);
1119 CHECK(frame_index < output_count_ - 1);
1120 CHECK_NULL(output_[frame_index]);
1121 output_[frame_index] = output_frame;
1125 intptr_t top_address;
1126 if (is_bottommost) {
1127 top_address = caller_frame_top_ - output_frame_size;
1129 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1131 output_frame->SetTop(top_address);
1133 ReadOnlyRoots roots(isolate());
1134 if (ShouldPadArguments(parameter_count)) {
1135 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1139 for (
int i = 0;
i < parameter_count; ++
i, ++value_iterator) {
1140 frame_writer.PushTranslatedValue(value_iterator,
"stack parameter");
1143 DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
1144 frame_writer.top_offset());
1147 const intptr_t caller_pc =
1148 is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
1149 frame_writer.PushCallerPc(caller_pc);
1152 const intptr_t caller_fp =
1153 is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
1154 frame_writer.PushCallerFp(caller_fp);
1156 intptr_t fp_value = top_address + frame_writer.top_offset();
1157 output_frame->SetFp(fp_value);
1159 if (FLAG_enable_embedded_constant_pool) {
1161 const intptr_t caller_cp =
1162 is_bottommost ? caller_constant_pool_
1163 : output_[frame_index - 1]->GetConstantPool();
1164 frame_writer.PushCallerConstantPool(caller_cp);
1168 intptr_t marker = StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR);
1169 frame_writer.PushRawValue(marker,
"context (adaptor sentinel)\n");
1172 frame_writer.PushTranslatedValue(function_iterator,
"function\n");
1175 frame_writer.PushRawObject(Smi::FromInt(height - 1),
"argc\n");
1177 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1179 CHECK_EQ(translated_frame->end(), value_iterator);
1180 DCHECK_EQ(0, frame_writer.top_offset());
1182 Builtins* builtins = isolate_->builtins();
1183 Code adaptor_trampoline =
1184 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
1185 intptr_t pc_value =
static_cast<intptr_t
>(
1186 adaptor_trampoline->InstructionStart() +
1187 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
1188 output_frame->SetPc(pc_value);
1189 if (FLAG_enable_embedded_constant_pool) {
1190 intptr_t constant_pool_value =
1191 static_cast<intptr_t
>(adaptor_trampoline->constant_pool());
1192 output_frame->SetConstantPool(constant_pool_value);
1196 void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
1198 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1199 bool is_topmost = (output_count_ - 1 == frame_index);
1203 CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy);
1205 Builtins* builtins = isolate_->builtins();
1206 Code construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
1207 BailoutId bailout_id = translated_frame->node_id();
1208 unsigned height = translated_frame->height();
1209 unsigned parameter_count = height - 1;
1210 unsigned height_in_bytes = parameter_count * kPointerSize;
1218 height_in_bytes += kPointerSize;
1219 if (PadTopOfStackRegister()) height_in_bytes += kPointerSize;
1222 if (ShouldPadArguments(parameter_count)) height_in_bytes += kPointerSize;
1224 TranslatedFrame::iterator function_iterator = value_iterator++;
1225 if (trace_scope_ !=
nullptr) {
1226 PrintF(trace_scope_->file(),
1227 " translating construct stub => bailout_id=%d (%s), height=%d\n",
1229 bailout_id == BailoutId::ConstructStubCreate() ?
"create" :
"invoke",
1233 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize;
1234 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
1237 FrameDescription* output_frame =
new (output_frame_size)
1238 FrameDescription(output_frame_size, parameter_count);
1239 FrameWriter frame_writer(
this, output_frame, trace_scope_);
1242 DCHECK(frame_index > 0 && frame_index < output_count_);
1243 DCHECK_NULL(output_[frame_index]);
1244 output_[frame_index] = output_frame;
1248 intptr_t top_address;
1249 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1250 output_frame->SetTop(top_address);
1252 ReadOnlyRoots roots(isolate());
1253 if (ShouldPadArguments(parameter_count)) {
1254 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1260 TranslatedFrame::iterator receiver_iterator = value_iterator;
1263 for (
unsigned i = 0;
i < parameter_count; ++
i, ++value_iterator) {
1264 frame_writer.PushTranslatedValue(value_iterator,
"stack parameter");
1267 DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
1268 frame_writer.top_offset());
1271 const intptr_t caller_pc = output_[frame_index - 1]->GetPc();
1272 frame_writer.PushCallerPc(caller_pc);
1275 const intptr_t caller_fp = output_[frame_index - 1]->GetFp();
1276 frame_writer.PushCallerFp(caller_fp);
1278 intptr_t fp_value = top_address + frame_writer.top_offset();
1279 output_frame->SetFp(fp_value);
1281 Register fp_reg = JavaScriptFrame::fp_register();
1282 output_frame->SetRegister(fp_reg.code(), fp_value);
1285 if (FLAG_enable_embedded_constant_pool) {
1287 const intptr_t caller_cp = output_[frame_index - 1]->GetConstantPool();
1288 frame_writer.PushCallerConstantPool(caller_cp);
1292 intptr_t marker = StackFrame::TypeToMarker(StackFrame::CONSTRUCT);
1293 frame_writer.PushRawValue(marker,
"context (construct stub sentinel)\n");
1295 frame_writer.PushTranslatedValue(value_iterator++,
"context");
1298 frame_writer.PushRawObject(Smi::FromInt(parameter_count - 1),
"argc\n");
1302 frame_writer.PushTranslatedValue(function_iterator,
"constuctor function\n");
1308 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1310 CHECK(bailout_id == BailoutId::ConstructStubCreate() ||
1311 bailout_id == BailoutId::ConstructStubInvoke());
1312 const char* debug_hint = bailout_id == BailoutId::ConstructStubCreate()
1314 :
"allocated receiver\n";
1315 frame_writer.PushTranslatedValue(receiver_iterator, debug_hint);
1318 if (PadTopOfStackRegister()) {
1319 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1322 Register result_reg = kReturnRegister0;
1323 intptr_t result = input_->GetRegister(result_reg.code());
1324 frame_writer.PushRawValue(result,
"subcall result\n");
1327 CHECK_EQ(translated_frame->end(), value_iterator);
1328 CHECK_EQ(0u, frame_writer.top_offset());
1331 DCHECK(bailout_id.IsValidForConstructStub());
1332 Address start = construct_stub->InstructionStart();
1334 bailout_id == BailoutId::ConstructStubCreate()
1335 ? isolate_->heap()->construct_stub_create_deopt_pc_offset()->value()
1336 : isolate_->heap()->construct_stub_invoke_deopt_pc_offset()->value();
1337 intptr_t pc_value =
static_cast<intptr_t
>(start + pc_offset);
1338 output_frame->SetPc(pc_value);
1341 if (FLAG_enable_embedded_constant_pool) {
1342 intptr_t constant_pool_value =
1343 static_cast<intptr_t
>(construct_stub->constant_pool());
1344 output_frame->SetConstantPool(constant_pool_value);
1346 Register constant_pool_reg =
1347 JavaScriptFrame::constant_pool_pointer_register();
1348 output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
1356 intptr_t context_value =
static_cast<intptr_t
>(Smi::zero().ptr());
1357 Register context_reg = JavaScriptFrame::context_register();
1358 output_frame->SetRegister(context_reg.code(), context_value);
1363 Builtins* builtins = isolate_->builtins();
1364 DCHECK_EQ(DeoptimizeKind::kLazy, deopt_kind_);
1365 Code continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
1366 output_frame->SetContinuation(
1367 static_cast<intptr_t>(continuation->InstructionStart()));
1371 bool Deoptimizer::BuiltinContinuationModeIsJavaScript(
1372 BuiltinContinuationMode mode) {
1374 case BuiltinContinuationMode::STUB:
1376 case BuiltinContinuationMode::JAVASCRIPT:
1377 case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
1378 case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
1384 bool Deoptimizer::BuiltinContinuationModeIsWithCatch(
1385 BuiltinContinuationMode mode) {
1387 case BuiltinContinuationMode::STUB:
1388 case BuiltinContinuationMode::JAVASCRIPT:
1390 case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
1391 case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
1397 StackFrame::Type Deoptimizer::BuiltinContinuationModeToFrameType(
1398 BuiltinContinuationMode mode) {
1400 case BuiltinContinuationMode::STUB:
1401 return StackFrame::BUILTIN_CONTINUATION;
1402 case BuiltinContinuationMode::JAVASCRIPT:
1403 return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION;
1404 case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
1405 return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1406 case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
1407 return StackFrame::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1412 Builtins::Name Deoptimizer::TrampolineForBuiltinContinuation(
1413 BuiltinContinuationMode mode,
bool must_handle_result) {
1415 case BuiltinContinuationMode::STUB:
1416 return must_handle_result ? Builtins::kContinueToCodeStubBuiltinWithResult
1417 : Builtins::kContinueToCodeStubBuiltin;
1418 case BuiltinContinuationMode::JAVASCRIPT:
1419 case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH:
1420 case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION:
1421 return must_handle_result
1422 ? Builtins::kContinueToJavaScriptBuiltinWithResult
1423 : Builtins::kContinueToJavaScriptBuiltin;
1486 void Deoptimizer::DoComputeBuiltinContinuation(
1487 TranslatedFrame* translated_frame,
int frame_index,
1488 BuiltinContinuationMode mode) {
1489 TranslatedFrame::iterator value_iterator = translated_frame->begin();
1493 const int height_in_words = translated_frame->height();
1495 BailoutId bailout_id = translated_frame->node_id();
1496 Builtins::Name builtin_name = Builtins::GetBuiltinFromBailoutId(bailout_id);
1497 Code builtin = isolate()->builtins()->builtin(builtin_name);
1498 Callable continuation_callable =
1499 Builtins::CallableFor(isolate(), builtin_name);
1500 CallInterfaceDescriptor continuation_descriptor =
1501 continuation_callable.descriptor();
1503 const bool is_bottommost = (0 == frame_index);
1504 const bool is_topmost = (output_count_ - 1 == frame_index);
1505 const bool must_handle_result =
1506 !is_topmost || deopt_kind_ == DeoptimizeKind::kLazy;
1508 const RegisterConfiguration* config(RegisterConfiguration::Default());
1509 const int allocatable_register_count =
1510 config->num_allocatable_general_registers();
1511 const int padding_slot_count =
1512 BuiltinContinuationFrameConstants::PaddingSlotCount(
1513 allocatable_register_count);
1515 const int register_parameter_count =
1516 continuation_descriptor.GetRegisterParameterCount();
1519 const int translated_stack_parameters =
1520 height_in_words - register_parameter_count - 1;
1521 const int stack_param_count =
1522 translated_stack_parameters + (must_handle_result ? 1 : 0) +
1523 (BuiltinContinuationModeIsWithCatch(mode) ? 1 : 0);
1524 const int stack_param_pad_count =
1525 ShouldPadArguments(stack_param_count) ? 1 : 0;
1532 const int push_result_count =
1533 is_topmost ? (PadTopOfStackRegister() ? 2 : 1) : 0;
1535 const unsigned output_frame_size =
1536 kPointerSize * (stack_param_count + stack_param_pad_count +
1537 allocatable_register_count + padding_slot_count +
1538 push_result_count) +
1539 BuiltinContinuationFrameConstants::kFixedFrameSize;
1541 const unsigned output_frame_size_above_fp =
1542 kPointerSize * (allocatable_register_count + padding_slot_count +
1543 push_result_count) +
1544 (BuiltinContinuationFrameConstants::kFixedFrameSize -
1545 BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp);
1549 bool has_argc =
false;
1550 for (
int i = 0;
i < register_parameter_count; ++
i) {
1551 MachineType type = continuation_descriptor.GetParameterType(
i);
1552 int code = continuation_descriptor.GetRegisterParameter(
i).code();
1555 if (type == MachineType::Int32()) {
1556 CHECK_EQ(code, kJavaScriptCallArgCountRegister.code());
1560 CHECK(IsAnyTagged(type.representation()));
1563 CHECK_EQ(BuiltinContinuationModeIsJavaScript(mode), has_argc);
1565 if (trace_scope_ !=
nullptr) {
1566 PrintF(trace_scope_->file(),
1567 " translating BuiltinContinuation to %s," 1568 " register param count %d," 1569 " stack param count %d\n",
1570 Builtins::name(builtin_name), register_parameter_count,
1574 FrameDescription* output_frame =
new (output_frame_size)
1575 FrameDescription(output_frame_size, stack_param_count);
1576 output_[frame_index] = output_frame;
1577 FrameWriter frame_writer(
this, output_frame, trace_scope_);
1581 intptr_t top_address;
1582 if (is_bottommost) {
1583 top_address = caller_frame_top_ - output_frame_size;
1585 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
1587 output_frame->SetTop(top_address);
1592 const intptr_t maybe_function =
1593 reinterpret_cast<intptr_t
>(value_iterator->GetRawValue());
1596 ReadOnlyRoots roots(isolate());
1597 if (ShouldPadArguments(stack_param_count)) {
1598 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1601 for (
int i = 0;
i < translated_stack_parameters; ++
i, ++value_iterator) {
1602 frame_writer.PushTranslatedValue(value_iterator,
"stack parameter");
1606 case BuiltinContinuationMode::STUB:
1608 case BuiltinContinuationMode::JAVASCRIPT:
1610 case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH: {
1611 frame_writer.PushRawObject(roots.the_hole_value(),
1612 "placeholder for exception on lazy deopt\n");
1614 case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION: {
1615 intptr_t accumulator_value =
1616 input_->GetRegister(kInterpreterAccumulatorRegister.code());
1617 frame_writer.PushRawObject(reinterpret_cast<Object*>(accumulator_value),
1618 "exception (from accumulator)\n");
1622 if (must_handle_result) {
1623 frame_writer.PushRawObject(roots.the_hole_value(),
1624 "placeholder for return result on lazy deopt\n");
1627 DCHECK_EQ(output_frame->GetLastArgumentSlotOffset(),
1628 frame_writer.top_offset());
1630 std::vector<TranslatedFrame::iterator> register_values;
1631 int total_registers = config->num_general_registers();
1632 register_values.resize(total_registers, {value_iterator});
1634 for (
int i = 0;
i < register_parameter_count; ++
i, ++value_iterator) {
1635 int code = continuation_descriptor.GetRegisterParameter(
i).code();
1636 register_values[code] = value_iterator;
1644 Object* context = value_iterator->GetRawValue();
1645 const intptr_t value =
reinterpret_cast<intptr_t
>(context);
1646 TranslatedFrame::iterator context_register_value = value_iterator++;
1647 register_values[kContextRegister.code()] = context_register_value;
1648 output_frame->SetContext(value);
1649 output_frame->SetRegister(kContextRegister.code(), value);
1652 const intptr_t caller_pc =
1653 is_bottommost ? caller_pc_ : output_[frame_index - 1]->GetPc();
1654 frame_writer.PushCallerPc(caller_pc);
1657 const intptr_t caller_fp =
1658 is_bottommost ? caller_fp_ : output_[frame_index - 1]->GetFp();
1659 frame_writer.PushCallerFp(caller_fp);
1661 const intptr_t fp_value = top_address + frame_writer.top_offset();
1662 output_frame->SetFp(fp_value);
1664 DCHECK_EQ(output_frame_size_above_fp, frame_writer.top_offset());
1666 if (FLAG_enable_embedded_constant_pool) {
1668 const intptr_t caller_cp =
1669 is_bottommost ? caller_constant_pool_
1670 : output_[frame_index - 1]->GetConstantPool();
1671 frame_writer.PushCallerConstantPool(caller_cp);
1675 const intptr_t marker =
1676 StackFrame::TypeToMarker(BuiltinContinuationModeToFrameType(mode));
1677 frame_writer.PushRawValue(marker,
1678 "context (builtin continuation sentinel)\n");
1680 if (BuiltinContinuationModeIsJavaScript(mode)) {
1681 frame_writer.PushRawValue(maybe_function,
"JSFunction\n");
1683 frame_writer.PushRawValue(0,
"unused\n");
1688 frame_writer.PushRawObject(Smi::FromInt(output_frame_size_above_fp),
1689 "frame height at deoptimization\n");
1693 frame_writer.PushTranslatedValue(context_register_value,
1694 "builtin JavaScript context\n");
1697 frame_writer.PushRawObject(builtin,
"builtin address\n");
1699 for (
int i = 0;
i < allocatable_register_count; ++
i) {
1700 int code = config->GetAllocatableGeneralCode(
i);
1701 ScopedVector<char> str(128);
1702 if (trace_scope_ !=
nullptr) {
1703 if (BuiltinContinuationModeIsJavaScript(mode) &&
1704 code == kJavaScriptCallArgCountRegister.code()) {
1707 "tagged argument count %s (will be untagged by continuation)\n",
1708 RegisterName(Register::from_code(code)));
1710 SNPrintF(str,
"builtin register argument %s\n",
1711 RegisterName(Register::from_code(code)));
1714 frame_writer.PushTranslatedValue(
1715 register_values[code], trace_scope_ !=
nullptr ? str.start() :
"");
1720 for (
int i = 0;
i < padding_slot_count; ++
i) {
1721 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1725 if (PadTopOfStackRegister()) {
1726 frame_writer.PushRawObject(roots.the_hole_value(),
"padding\n");
1730 if (must_handle_result) {
1731 Register result_reg = kReturnRegister0;
1732 frame_writer.PushRawValue(input_->GetRegister(result_reg.code()),
1733 "callback result\n");
1735 frame_writer.PushRawObject(roots.undefined_value(),
"callback result\n");
1739 CHECK_EQ(translated_frame->end(), value_iterator);
1740 CHECK_EQ(0u, frame_writer.top_offset());
1746 intptr_t context_value =
static_cast<intptr_t
>(Smi::zero().ptr());
1747 Register context_reg = JavaScriptFrame::context_register();
1748 output_frame->SetRegister(context_reg.code(), context_value);
1753 Register fp_reg = JavaScriptFrame::fp_register();
1754 output_frame->SetRegister(fp_reg.code(), fp_value);
1756 Code continue_to_builtin = isolate()->builtins()->builtin(
1757 TrampolineForBuiltinContinuation(mode, must_handle_result));
1758 output_frame->SetPc(
1759 static_cast<intptr_t>(continue_to_builtin->InstructionStart()));
1762 isolate()->builtins()->builtin(Builtins::kNotifyDeoptimized);
1763 output_frame->SetContinuation(
1764 static_cast<intptr_t>(continuation->InstructionStart()));
1767 void Deoptimizer::MaterializeHeapObjects() {
1768 translated_state_.Prepare(static_cast<Address>(stack_fp_));
1769 if (FLAG_deopt_every_n_times > 0) {
1771 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
1772 GarbageCollectionReason::kTesting);
1775 for (
auto& materialization : values_to_materialize_) {
1776 Handle<Object> value = materialization.value_->GetValue();
1778 if (trace_scope_ !=
nullptr) {
1779 PrintF(
"Materialization [" V8PRIxPTR_FMT
"] <- " V8PRIxPTR_FMT
" ; ",
1780 static_cast<intptr_t>(materialization.output_slot_address_),
1781 reinterpret_cast<intptr_t>(*value));
1782 value->ShortPrint(trace_scope_->file());
1783 PrintF(trace_scope_->file(),
"\n");
1786 *(
reinterpret_cast<intptr_t*
>(materialization.output_slot_address_)) =
1787 reinterpret_cast<intptr_t
>(*value);
1790 translated_state_.VerifyMaterializedObjects();
1792 bool feedback_updated = translated_state_.DoUpdateFeedback();
1793 if (trace_scope_ !=
nullptr && feedback_updated) {
1794 PrintF(trace_scope_->file(),
"Feedback updated");
1795 compiled_code_->PrintDeoptLocation(trace_scope_->file(),
1796 " from deoptimization at ", from_);
1799 isolate_->materialized_object_store()->Remove(
1800 static_cast<Address>(stack_fp_));
1803 void Deoptimizer::QueueValueForMaterialization(
1804 Address output_address, Object* obj,
1805 const TranslatedFrame::iterator& iterator) {
1806 if (obj == ReadOnlyRoots(isolate_).arguments_marker()) {
1807 values_to_materialize_.push_back({output_address, iterator});
1811 unsigned Deoptimizer::ComputeInputFrameAboveFpFixedSize()
const {
1812 unsigned fixed_size = CommonFrameConstants::kFixedFrameSizeAboveFp;
1813 if (!function_->IsSmi()) {
1814 fixed_size += ComputeIncomingArgumentSize(function_->shared());
1819 unsigned Deoptimizer::ComputeInputFrameSize()
const {
1822 unsigned fixed_size_above_fp = ComputeInputFrameAboveFpFixedSize();
1823 unsigned result = fixed_size_above_fp + fp_to_sp_delta_;
1824 if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
1825 unsigned stack_slots = compiled_code_->stack_slots();
1826 unsigned outgoing_size = 0;
1828 CHECK_EQ(fixed_size_above_fp + (stack_slots * kPointerSize) -
1829 CommonFrameConstants::kFixedFrameSizeAboveFp + outgoing_size,
1836 unsigned Deoptimizer::ComputeInterpretedFixedSize(SharedFunctionInfo* shared) {
1839 return ComputeIncomingArgumentSize(shared) +
1840 InterpreterFrameConstants::kFixedFrameSize;
1844 unsigned Deoptimizer::ComputeIncomingArgumentSize(SharedFunctionInfo* shared) {
1845 int parameter_slots = shared->internal_formal_parameter_count() + 1;
1846 if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
1847 return parameter_slots * kPointerSize;
1850 void Deoptimizer::EnsureCodeForDeoptimizationEntry(Isolate* isolate,
1851 DeoptimizeKind kind) {
1852 CHECK(kind == DeoptimizeKind::kEager || kind == DeoptimizeKind::kSoft ||
1853 kind == DeoptimizeKind::kLazy);
1854 DeoptimizerData* data = isolate->deoptimizer_data();
1855 if (!data->deopt_entry_code(kind).is_null())
return;
1857 MacroAssembler masm(isolate,
nullptr, 16 * KB, CodeObjectRequired::kYes);
1858 masm.set_emit_debug_code(
false);
1859 GenerateDeoptimizationEntries(&masm, kMaxNumberOfEntries, kind);
1861 masm.GetCode(isolate, &desc);
1862 DCHECK(!RelocInfo::RequiresRelocationAfterCodegen(desc));
1866 Handle<Code> code = isolate->factory()->NewCode(
1867 desc, Code::STUB, Handle<Object>(), Builtins::kNoBuiltinId,
1868 MaybeHandle<ByteArray>(), MaybeHandle<DeoptimizationData>(), kImmovable);
1869 CHECK(isolate->heap()->IsImmovable(*code));
1871 CHECK(data->deopt_entry_code(kind).is_null());
1872 data->set_deopt_entry_code(kind, *code);
1875 void Deoptimizer::EnsureCodeForMaxDeoptimizationEntries(Isolate* isolate) {
1876 EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kEager);
1877 EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kLazy);
1878 EnsureCodeForDeoptimizationEntry(isolate, DeoptimizeKind::kSoft);
1881 FrameDescription::FrameDescription(
uint32_t frame_size,
int parameter_count)
1882 : frame_size_(frame_size),
1883 parameter_count_(parameter_count),
1887 context_(kZapUint32),
1888 constant_pool_(kZapUint32) {
1890 for (
int r = 0; r < Register::kNumRegisters; r++) {
1894 #if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_ARM64) 1896 const int kPlatformRegister = 18;
1897 if (r != kPlatformRegister) {
1898 SetRegister(r, kZapUint32);
1901 SetRegister(r, kZapUint32);
1906 for (
unsigned o = 0; o < frame_size; o += kPointerSize) {
1907 SetFrameSlot(o, kZapUint32);
1911 void TranslationBuffer::Add(int32_t value) {
1913 DCHECK_NE(value, kMinInt);
1915 bool is_negative = (value < 0);
1916 uint32_t bits = (
static_cast<uint32_t>(is_negative ? -value : value) << 1) |
1917 static_cast<uint32_t>(is_negative);
1922 contents_.push_back(((bits << 1) & 0xFF) | (next != 0));
1924 }
while (bits != 0);
1927 TranslationIterator::TranslationIterator(ByteArray buffer,
int index)
1928 : buffer_(buffer), index_(index) {
1929 DCHECK(index >= 0 && index < buffer->length());
1932 int32_t TranslationIterator::Next() {
1936 for (
int i = 0;
true;
i += 7) {
1938 uint8_t next = buffer_->get(index_++);
1939 bits |= (next >> 1) <<
i;
1940 if ((next & 1) == 0)
break;
1943 bool is_negative = (bits & 1) == 1;
1944 int32_t result = bits >> 1;
1945 return is_negative ? -result : result;
1948 bool TranslationIterator::HasNext()
const {
return index_ < buffer_->length(); }
1950 Handle<ByteArray> TranslationBuffer::CreateByteArray(Factory* factory) {
1951 Handle<ByteArray> result = factory->NewByteArray(CurrentIndex(), TENURED);
1952 contents_.CopyTo(result->GetDataStartAddress());
1956 void Translation::BeginBuiltinContinuationFrame(BailoutId bailout_id,
1959 buffer_->Add(BUILTIN_CONTINUATION_FRAME);
1960 buffer_->Add(bailout_id.ToInt());
1961 buffer_->Add(literal_id);
1962 buffer_->Add(height);
1965 void Translation::BeginJavaScriptBuiltinContinuationFrame(BailoutId bailout_id,
1968 buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME);
1969 buffer_->Add(bailout_id.ToInt());
1970 buffer_->Add(literal_id);
1971 buffer_->Add(height);
1974 void Translation::BeginJavaScriptBuiltinContinuationWithCatchFrame(
1975 BailoutId bailout_id,
int literal_id,
unsigned height) {
1976 buffer_->Add(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME);
1977 buffer_->Add(bailout_id.ToInt());
1978 buffer_->Add(literal_id);
1979 buffer_->Add(height);
1982 void Translation::BeginConstructStubFrame(BailoutId bailout_id,
int literal_id,
1984 buffer_->Add(CONSTRUCT_STUB_FRAME);
1985 buffer_->Add(bailout_id.ToInt());
1986 buffer_->Add(literal_id);
1987 buffer_->Add(height);
1991 void Translation::BeginArgumentsAdaptorFrame(
int literal_id,
unsigned height) {
1992 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME);
1993 buffer_->Add(literal_id);
1994 buffer_->Add(height);
1997 void Translation::BeginInterpretedFrame(BailoutId bytecode_offset,
1998 int literal_id,
unsigned height,
1999 int return_value_offset,
2000 int return_value_count) {
2001 buffer_->Add(INTERPRETED_FRAME);
2002 buffer_->Add(bytecode_offset.ToInt());
2003 buffer_->Add(literal_id);
2004 buffer_->Add(height);
2005 buffer_->Add(return_value_offset);
2006 buffer_->Add(return_value_count);
2009 void Translation::ArgumentsElements(CreateArgumentsType type) {
2010 buffer_->Add(ARGUMENTS_ELEMENTS);
2011 buffer_->Add(static_cast<uint8_t>(type));
2014 void Translation::ArgumentsLength(CreateArgumentsType type) {
2015 buffer_->Add(ARGUMENTS_LENGTH);
2016 buffer_->Add(static_cast<uint8_t>(type));
2019 void Translation::BeginCapturedObject(
int length) {
2020 buffer_->Add(CAPTURED_OBJECT);
2021 buffer_->Add(length);
2025 void Translation::DuplicateObject(
int object_index) {
2026 buffer_->Add(DUPLICATED_OBJECT);
2027 buffer_->Add(object_index);
2031 void Translation::StoreRegister(Register reg) {
2032 buffer_->Add(REGISTER);
2033 buffer_->Add(reg.code());
2037 void Translation::StoreInt32Register(Register reg) {
2038 buffer_->Add(INT32_REGISTER);
2039 buffer_->Add(reg.code());
2042 void Translation::StoreInt64Register(Register reg) {
2043 buffer_->Add(INT64_REGISTER);
2044 buffer_->Add(reg.code());
2047 void Translation::StoreUint32Register(Register reg) {
2048 buffer_->Add(UINT32_REGISTER);
2049 buffer_->Add(reg.code());
2053 void Translation::StoreBoolRegister(Register reg) {
2054 buffer_->Add(BOOL_REGISTER);
2055 buffer_->Add(reg.code());
2058 void Translation::StoreFloatRegister(FloatRegister reg) {
2059 buffer_->Add(FLOAT_REGISTER);
2060 buffer_->Add(reg.code());
2063 void Translation::StoreDoubleRegister(DoubleRegister reg) {
2064 buffer_->Add(DOUBLE_REGISTER);
2065 buffer_->Add(reg.code());
2069 void Translation::StoreStackSlot(
int index) {
2070 buffer_->Add(STACK_SLOT);
2071 buffer_->Add(index);
2075 void Translation::StoreInt32StackSlot(
int index) {
2076 buffer_->Add(INT32_STACK_SLOT);
2077 buffer_->Add(index);
2080 void Translation::StoreInt64StackSlot(
int index) {
2081 buffer_->Add(INT64_STACK_SLOT);
2082 buffer_->Add(index);
2085 void Translation::StoreUint32StackSlot(
int index) {
2086 buffer_->Add(UINT32_STACK_SLOT);
2087 buffer_->Add(index);
2091 void Translation::StoreBoolStackSlot(
int index) {
2092 buffer_->Add(BOOL_STACK_SLOT);
2093 buffer_->Add(index);
2096 void Translation::StoreFloatStackSlot(
int index) {
2097 buffer_->Add(FLOAT_STACK_SLOT);
2098 buffer_->Add(index);
2101 void Translation::StoreDoubleStackSlot(
int index) {
2102 buffer_->Add(DOUBLE_STACK_SLOT);
2103 buffer_->Add(index);
2107 void Translation::StoreLiteral(
int literal_id) {
2108 buffer_->Add(LITERAL);
2109 buffer_->Add(literal_id);
2112 void Translation::AddUpdateFeedback(
int vector_literal,
int slot) {
2113 buffer_->Add(UPDATE_FEEDBACK);
2114 buffer_->Add(vector_literal);
2118 void Translation::StoreJSFrameFunction() {
2119 StoreStackSlot((StandardFrameConstants::kCallerPCOffset -
2120 StandardFrameConstants::kFunctionOffset) /
2124 int Translation::NumberOfOperandsFor(Opcode opcode) {
2126 case DUPLICATED_OBJECT:
2127 case ARGUMENTS_ELEMENTS:
2128 case ARGUMENTS_LENGTH:
2129 case CAPTURED_OBJECT:
2131 case INT32_REGISTER:
2132 case INT64_REGISTER:
2133 case UINT32_REGISTER:
2135 case FLOAT_REGISTER:
2136 case DOUBLE_REGISTER:
2138 case INT32_STACK_SLOT:
2139 case INT64_STACK_SLOT:
2140 case UINT32_STACK_SLOT:
2141 case BOOL_STACK_SLOT:
2142 case FLOAT_STACK_SLOT:
2143 case DOUBLE_STACK_SLOT:
2146 case ARGUMENTS_ADAPTOR_FRAME:
2147 case UPDATE_FEEDBACK:
2150 case CONSTRUCT_STUB_FRAME:
2151 case BUILTIN_CONTINUATION_FRAME:
2152 case JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
2153 case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME:
2155 case INTERPRETED_FRAME:
2158 FATAL(
"Unexpected translation type");
2163 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 2165 const char* Translation::StringFor(Opcode opcode) {
2166 #define TRANSLATION_OPCODE_CASE(item) case item: return #item; 2168 TRANSLATION_OPCODE_LIST(TRANSLATION_OPCODE_CASE)
2170 #undef TRANSLATION_OPCODE_CASE 2177 Handle<FixedArray> MaterializedObjectStore::Get(Address fp) {
2178 int index = StackIdToIndex(fp);
2180 return Handle<FixedArray>::null();
2182 Handle<FixedArray> array = GetStackEntries();
2183 CHECK_GT(array->length(), index);
2184 return Handle<FixedArray>::cast(Handle<Object>(array->get(index), isolate()));
2188 void MaterializedObjectStore::Set(Address fp,
2189 Handle<FixedArray> materialized_objects) {
2190 int index = StackIdToIndex(fp);
2192 index =
static_cast<int>(frame_fps_.size());
2193 frame_fps_.push_back(fp);
2196 Handle<FixedArray> array = EnsureStackEntries(index + 1);
2197 array->set(index, *materialized_objects);
2201 bool MaterializedObjectStore::Remove(Address fp) {
2202 auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
2203 if (it == frame_fps_.end())
return false;
2204 int index =
static_cast<int>(std::distance(frame_fps_.begin(), it));
2206 frame_fps_.erase(it);
2207 FixedArray array = isolate()->heap()->materialized_objects();
2209 CHECK_LT(index, array->length());
2210 int fps_size =
static_cast<int>(frame_fps_.size());
2211 for (
int i = index;
i < fps_size;
i++) {
2212 array->set(
i, array->get(
i + 1));
2214 array->set(fps_size, ReadOnlyRoots(isolate()).undefined_value());
2219 int MaterializedObjectStore::StackIdToIndex(Address fp) {
2220 auto it = std::find(frame_fps_.begin(), frame_fps_.end(), fp);
2221 return it == frame_fps_.end()
2223 :
static_cast<int>(std::distance(frame_fps_.begin(), it));
2227 Handle<FixedArray> MaterializedObjectStore::GetStackEntries() {
2228 return Handle<FixedArray>(isolate()->heap()->materialized_objects(),
2233 Handle<FixedArray> MaterializedObjectStore::EnsureStackEntries(
int length) {
2234 Handle<FixedArray> array = GetStackEntries();
2235 if (array->length() >= length) {
2239 int new_length = length > 10 ? length : 10;
2240 if (new_length < 2 * array->length()) {
2241 new_length = 2 * array->length();
2244 Handle<FixedArray> new_array =
2245 isolate()->factory()->NewFixedArray(new_length, TENURED);
2246 for (
int i = 0;
i < array->length();
i++) {
2247 new_array->set(
i, array->get(
i));
2249 HeapObject* undefined_value = ReadOnlyRoots(isolate()).undefined_value();
2250 for (
int i = array->length();
i < length;
i++) {
2251 new_array->set(
i, undefined_value);
2253 isolate()->heap()->SetRootMaterializedObjects(*new_array);
2259 Handle<Object> GetValueForDebugger(TranslatedFrame::iterator it,
2261 if (it->GetRawValue() == ReadOnlyRoots(isolate).arguments_marker()) {
2262 if (!it->IsMaterializableByDebugger()) {
2263 return isolate->factory()->optimized_out();
2266 return it->GetValue();
2271 DeoptimizedFrameInfo::DeoptimizedFrameInfo(TranslatedState* state,
2272 TranslatedState::iterator frame_it,
2274 int parameter_count =
2275 frame_it->shared_info()->internal_formal_parameter_count();
2276 TranslatedFrame::iterator stack_it = frame_it->begin();
2281 function_ = Handle<JSFunction>::cast(stack_it->GetValue());
2285 DCHECK_EQ(TranslatedFrame::kInterpretedFunction, frame_it->kind());
2286 source_position_ = Deoptimizer::ComputeSourcePositionFromBytecodeArray(
2287 *frame_it->shared_info(), frame_it->node_id());
2289 DCHECK_EQ(parameter_count,
2290 function_->shared()->internal_formal_parameter_count());
2292 parameters_.resize(static_cast<size_t>(parameter_count));
2293 for (
int i = 0;
i < parameter_count;
i++) {
2294 Handle<Object> parameter = GetValueForDebugger(stack_it, isolate);
2295 SetParameter(
i, parameter);
2300 context_ = GetValueForDebugger(stack_it, isolate);
2304 int stack_height = frame_it->height();
2305 if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2310 expression_stack_.resize(static_cast<size_t>(stack_height));
2311 for (
int i = 0;
i < stack_height;
i++) {
2312 Handle<Object> expression = GetValueForDebugger(stack_it, isolate);
2313 SetExpression(
i, expression);
2318 if (frame_it->kind() == TranslatedFrame::kInterpretedFunction) {
2321 CHECK(stack_it == frame_it->end());
2324 Deoptimizer::DeoptInfo Deoptimizer::GetDeoptInfo(Code code, Address pc) {
2325 CHECK(code->InstructionStart() <= pc && pc <= code->InstructionEnd());
2326 SourcePosition last_position = SourcePosition::Unknown();
2327 DeoptimizeReason last_reason = DeoptimizeReason::kUnknown;
2328 int last_deopt_id = kNoDeoptimizationId;
2329 int mask = RelocInfo::ModeMask(RelocInfo::DEOPT_REASON) |
2330 RelocInfo::ModeMask(RelocInfo::DEOPT_ID) |
2331 RelocInfo::ModeMask(RelocInfo::DEOPT_SCRIPT_OFFSET) |
2332 RelocInfo::ModeMask(RelocInfo::DEOPT_INLINING_ID);
2333 for (RelocIterator it(code, mask); !it.done(); it.next()) {
2334 RelocInfo* info = it.rinfo();
2335 if (info->pc() >= pc)
break;
2336 if (info->rmode() == RelocInfo::DEOPT_SCRIPT_OFFSET) {
2337 int script_offset =
static_cast<int>(info->data());
2339 DCHECK(it.rinfo()->rmode() == RelocInfo::DEOPT_INLINING_ID);
2340 int inlining_id =
static_cast<int>(it.rinfo()->data());
2341 last_position = SourcePosition(script_offset, inlining_id);
2342 }
else if (info->rmode() == RelocInfo::DEOPT_ID) {
2343 last_deopt_id =
static_cast<int>(info->data());
2344 }
else if (info->rmode() == RelocInfo::DEOPT_REASON) {
2345 last_reason =
static_cast<DeoptimizeReason
>(info->data());
2348 return DeoptInfo(last_position, last_reason, last_deopt_id);
2353 int Deoptimizer::ComputeSourcePositionFromBytecodeArray(
2354 SharedFunctionInfo* shared, BailoutId node_id) {
2355 DCHECK(shared->HasBytecodeArray());
2356 return AbstractCode::cast(shared->GetBytecodeArray())
2357 ->SourcePosition(node_id.ToInt());
2361 TranslatedValue TranslatedValue::NewDeferredObject(TranslatedState* container,
2364 TranslatedValue slot(container, kCapturedObject);
2365 slot.materialization_info_ = {object_index, length};
2371 TranslatedValue TranslatedValue::NewDuplicateObject(TranslatedState* container,
2373 TranslatedValue slot(container, kDuplicatedObject);
2374 slot.materialization_info_ = {id, -1};
2380 TranslatedValue TranslatedValue::NewFloat(TranslatedState* container,
2382 TranslatedValue slot(container, kFloat);
2383 slot.float_value_ = value;
2388 TranslatedValue TranslatedValue::NewDouble(TranslatedState* container,
2390 TranslatedValue slot(container, kDouble);
2391 slot.double_value_ = value;
2397 TranslatedValue TranslatedValue::NewInt32(TranslatedState* container,
2399 TranslatedValue slot(container, kInt32);
2400 slot.int32_value_ = value;
2405 TranslatedValue TranslatedValue::NewInt64(TranslatedState* container,
2407 TranslatedValue slot(container, kInt64);
2408 slot.int64_value_ = value;
2413 TranslatedValue TranslatedValue::NewUInt32(TranslatedState* container,
2415 TranslatedValue slot(container, kUInt32);
2416 slot.uint32_value_ = value;
2422 TranslatedValue TranslatedValue::NewBool(TranslatedState* container,
2424 TranslatedValue slot(container, kBoolBit);
2425 slot.uint32_value_ = value;
2431 TranslatedValue TranslatedValue::NewTagged(TranslatedState* container,
2433 TranslatedValue slot(container, kTagged);
2434 slot.raw_literal_ = literal;
2440 TranslatedValue TranslatedValue::NewInvalid(TranslatedState* container) {
2441 return TranslatedValue(container, kInvalid);
2445 Isolate* TranslatedValue::isolate()
const {
return container_->isolate(); }
2448 Object* TranslatedValue::raw_literal()
const {
2449 DCHECK_EQ(kTagged, kind());
2450 return raw_literal_;
2454 int32_t TranslatedValue::int32_value()
const {
2455 DCHECK_EQ(kInt32, kind());
2456 return int32_value_;
2459 int64_t TranslatedValue::int64_value()
const {
2460 DCHECK_EQ(kInt64, kind());
2461 return int64_value_;
2464 uint32_t TranslatedValue::uint32_value()
const {
2465 DCHECK(kind() == kUInt32 || kind() == kBoolBit);
2466 return uint32_value_;
2469 Float32 TranslatedValue::float_value()
const {
2470 DCHECK_EQ(kFloat, kind());
2471 return float_value_;
2474 Float64 TranslatedValue::double_value()
const {
2475 DCHECK_EQ(kDouble, kind());
2476 return double_value_;
2480 int TranslatedValue::object_length()
const {
2481 DCHECK_EQ(kind(), kCapturedObject);
2482 return materialization_info_.length_;
2486 int TranslatedValue::object_index()
const {
2487 DCHECK(kind() == kCapturedObject || kind() == kDuplicatedObject);
2488 return materialization_info_.id_;
2492 Object* TranslatedValue::GetRawValue()
const {
2494 if (materialization_state() == kFinished) {
2501 return raw_literal();
2504 bool is_smi = Smi::IsValid(int32_value());
2506 return Smi::FromInt(int32_value());
2512 bool is_smi = (int64_value() >=
static_cast<int64_t>(Smi::kMinValue) &&
2513 int64_value() <=
static_cast<int64_t>(Smi::kMaxValue));
2515 return Smi::FromIntptr(static_cast<intptr_t>(int64_value()));
2521 bool is_smi = (uint32_value() <=
static_cast<uintptr_t>(Smi::kMaxValue));
2523 return Smi::FromInt(static_cast<int32_t>(uint32_value()));
2529 if (uint32_value() == 0) {
2530 return ReadOnlyRoots(isolate()).false_value();
2532 CHECK_EQ(1U, uint32_value());
2533 return ReadOnlyRoots(isolate()).true_value();
2543 return ReadOnlyRoots(isolate()).arguments_marker();
2546 void TranslatedValue::set_initialized_storage(Handle<Object> storage) {
2547 DCHECK_EQ(kUninitialized, materialization_state());
2549 materialization_state_ = kFinished;
2552 Handle<Object> TranslatedValue::GetValue() {
2554 if (materialization_state() == kFinished)
return storage_;
2558 case TranslatedValue::kTagged:
2559 case TranslatedValue::kInt32:
2560 case TranslatedValue::kInt64:
2561 case TranslatedValue::kUInt32:
2562 case TranslatedValue::kBoolBit:
2563 case TranslatedValue::kFloat:
2564 case TranslatedValue::kDouble: {
2565 MaterializeSimple();
2569 case TranslatedValue::kCapturedObject:
2570 case TranslatedValue::kDuplicatedObject: {
2579 container_->EnsureObjectAllocatedAt(
this);
2585 return container_->InitializeObjectAt(
this);
2588 case TranslatedValue::kInvalid:
2589 FATAL(
"unexpected case");
2590 return Handle<Object>::null();
2593 FATAL(
"internal error: value missing");
2594 return Handle<Object>::null();
2597 void TranslatedValue::MaterializeSimple() {
2599 if (materialization_state() == kFinished)
return;
2601 Object* raw_value = GetRawValue();
2602 if (raw_value != ReadOnlyRoots(isolate()).arguments_marker()) {
2604 set_initialized_storage(Handle<Object>(raw_value, isolate()));
2610 set_initialized_storage(
2611 Handle<Object>(isolate()->factory()->NewNumber(int32_value())));
2615 set_initialized_storage(Handle<Object>(
2616 isolate()->factory()->NewNumber(static_cast<double>(int64_value()))));
2620 set_initialized_storage(
2621 Handle<Object>(isolate()->factory()->NewNumber(uint32_value())));
2625 double scalar_value = float_value().get_scalar();
2626 set_initialized_storage(
2627 Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
2632 double scalar_value = double_value().get_scalar();
2633 set_initialized_storage(
2634 Handle<Object>(isolate()->factory()->NewNumber(scalar_value)));
2638 case kCapturedObject:
2639 case kDuplicatedObject:
2643 FATAL(
"internal error: unexpected materialization.");
2649 bool TranslatedValue::IsMaterializedObject()
const {
2651 case kCapturedObject:
2652 case kDuplicatedObject:
2659 bool TranslatedValue::IsMaterializableByDebugger()
const {
2661 return (kind() == kDouble);
2664 int TranslatedValue::GetChildrenCount()
const {
2665 if (kind() == kCapturedObject) {
2666 return object_length();
2672 uint64_t TranslatedState::GetUInt64Slot(Address fp,
int slot_offset) {
2673 return Memory<uint64_t>(fp + slot_offset);
2676 uint32_t TranslatedState::GetUInt32Slot(Address fp,
int slot_offset) {
2677 Address address = fp + slot_offset;
2678 #if V8_TARGET_BIG_ENDIAN && V8_HOST_ARCH_64_BIT 2679 return Memory<uint32_t>(address + kIntSize);
2681 return Memory<uint32_t>(address);
2685 Float32 TranslatedState::GetFloatSlot(Address fp,
int slot_offset) {
2686 #if !V8_TARGET_ARCH_S390X && !V8_TARGET_ARCH_PPC64 2687 return Float32::FromBits(GetUInt32Slot(fp, slot_offset));
2689 return Float32::FromBits(Memory<uint32_t>(fp + slot_offset));
2693 Float64 TranslatedState::GetDoubleSlot(Address fp,
int slot_offset) {
2694 return Float64::FromBits(GetUInt64Slot(fp, slot_offset));
2697 void TranslatedValue::Handlify() {
2698 if (kind() == kTagged) {
2699 set_initialized_storage(Handle<Object>(raw_literal(), isolate()));
2700 raw_literal_ =
nullptr;
2704 TranslatedFrame TranslatedFrame::InterpretedFrame(
2705 BailoutId bytecode_offset, SharedFunctionInfo* shared_info,
int height,
2706 int return_value_offset,
int return_value_count) {
2707 TranslatedFrame frame(kInterpretedFunction, shared_info, height,
2708 return_value_offset, return_value_count);
2709 frame.node_id_ = bytecode_offset;
2714 TranslatedFrame TranslatedFrame::ArgumentsAdaptorFrame(
2715 SharedFunctionInfo* shared_info,
int height) {
2716 return TranslatedFrame(kArgumentsAdaptor, shared_info, height);
2719 TranslatedFrame TranslatedFrame::ConstructStubFrame(
2720 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height) {
2721 TranslatedFrame frame(kConstructStub, shared_info, height);
2722 frame.node_id_ = bailout_id;
2726 TranslatedFrame TranslatedFrame::BuiltinContinuationFrame(
2727 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height) {
2728 TranslatedFrame frame(kBuiltinContinuation, shared_info, height);
2729 frame.node_id_ = bailout_id;
2733 TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationFrame(
2734 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height) {
2735 TranslatedFrame frame(kJavaScriptBuiltinContinuation, shared_info, height);
2736 frame.node_id_ = bailout_id;
2740 TranslatedFrame TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
2741 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height) {
2742 TranslatedFrame frame(kJavaScriptBuiltinContinuationWithCatch, shared_info,
2744 frame.node_id_ = bailout_id;
2748 int TranslatedFrame::GetValueCount() {
2750 case kInterpretedFunction: {
2751 int parameter_count =
2752 raw_shared_info_->internal_formal_parameter_count() + 1;
2754 return height_ + parameter_count + 2;
2757 case kArgumentsAdaptor:
2758 case kConstructStub:
2759 case kBuiltinContinuation:
2760 case kJavaScriptBuiltinContinuation:
2761 case kJavaScriptBuiltinContinuationWithCatch:
2772 void TranslatedFrame::Handlify() {
2773 if (raw_shared_info_ !=
nullptr) {
2774 shared_info_ = Handle<SharedFunctionInfo>(raw_shared_info_,
2775 raw_shared_info_->GetIsolate());
2776 raw_shared_info_ =
nullptr;
2778 for (
auto& value : values_) {
2783 TranslatedFrame TranslatedState::CreateNextTranslatedFrame(
2784 TranslationIterator* iterator, FixedArray literal_array, Address fp,
2786 Translation::Opcode opcode =
2787 static_cast<Translation::Opcode
>(iterator->Next());
2789 case Translation::INTERPRETED_FRAME: {
2790 BailoutId bytecode_offset = BailoutId(iterator->Next());
2791 SharedFunctionInfo* shared_info =
2792 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2793 int height = iterator->Next();
2794 int return_value_offset = iterator->Next();
2795 int return_value_count = iterator->Next();
2796 if (trace_file !=
nullptr) {
2797 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2798 PrintF(trace_file,
" reading input frame %s", name.get());
2799 int arg_count = shared_info->internal_formal_parameter_count() + 1;
2801 " => bytecode_offset=%d, args=%d, height=%d, retval=%i(#%i); " 2803 bytecode_offset.ToInt(), arg_count, height, return_value_offset,
2804 return_value_count);
2806 return TranslatedFrame::InterpretedFrame(bytecode_offset, shared_info,
2807 height, return_value_offset,
2808 return_value_count);
2811 case Translation::ARGUMENTS_ADAPTOR_FRAME: {
2812 SharedFunctionInfo* shared_info =
2813 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2814 int height = iterator->Next();
2815 if (trace_file !=
nullptr) {
2816 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2817 PrintF(trace_file,
" reading arguments adaptor frame %s", name.get());
2818 PrintF(trace_file,
" => height=%d; inputs:\n", height);
2820 return TranslatedFrame::ArgumentsAdaptorFrame(shared_info, height);
2823 case Translation::CONSTRUCT_STUB_FRAME: {
2824 BailoutId bailout_id = BailoutId(iterator->Next());
2825 SharedFunctionInfo* shared_info =
2826 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2827 int height = iterator->Next();
2828 if (trace_file !=
nullptr) {
2829 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2830 PrintF(trace_file,
" reading construct stub frame %s", name.get());
2831 PrintF(trace_file,
" => bailout_id=%d, height=%d; inputs:\n",
2832 bailout_id.ToInt(), height);
2834 return TranslatedFrame::ConstructStubFrame(bailout_id, shared_info,
2838 case Translation::BUILTIN_CONTINUATION_FRAME: {
2839 BailoutId bailout_id = BailoutId(iterator->Next());
2840 SharedFunctionInfo* shared_info =
2841 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2842 int height = iterator->Next();
2843 if (trace_file !=
nullptr) {
2844 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2845 PrintF(trace_file,
" reading builtin continuation frame %s",
2847 PrintF(trace_file,
" => bailout_id=%d, height=%d; inputs:\n",
2848 bailout_id.ToInt(), height);
2852 int height_with_context = height + 1;
2853 return TranslatedFrame::BuiltinContinuationFrame(bailout_id, shared_info,
2854 height_with_context);
2857 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME: {
2858 BailoutId bailout_id = BailoutId(iterator->Next());
2859 SharedFunctionInfo* shared_info =
2860 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2861 int height = iterator->Next();
2862 if (trace_file !=
nullptr) {
2863 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2864 PrintF(trace_file,
" reading JavaScript builtin continuation frame %s",
2866 PrintF(trace_file,
" => bailout_id=%d, height=%d; inputs:\n",
2867 bailout_id.ToInt(), height);
2871 int height_with_context = height + 1;
2872 return TranslatedFrame::JavaScriptBuiltinContinuationFrame(
2873 bailout_id, shared_info, height_with_context);
2875 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
2876 BailoutId bailout_id = BailoutId(iterator->Next());
2877 SharedFunctionInfo* shared_info =
2878 SharedFunctionInfo::cast(literal_array->get(iterator->Next()));
2879 int height = iterator->Next();
2880 if (trace_file !=
nullptr) {
2881 std::unique_ptr<char[]> name = shared_info->DebugName()->ToCString();
2883 " reading JavaScript builtin continuation frame with catch %s",
2885 PrintF(trace_file,
" => bailout_id=%d, height=%d; inputs:\n",
2886 bailout_id.ToInt(), height);
2890 int height_with_context = height + 1;
2891 return TranslatedFrame::JavaScriptBuiltinContinuationWithCatchFrame(
2892 bailout_id, shared_info, height_with_context);
2894 case Translation::UPDATE_FEEDBACK:
2895 case Translation::BEGIN:
2896 case Translation::DUPLICATED_OBJECT:
2897 case Translation::ARGUMENTS_ELEMENTS:
2898 case Translation::ARGUMENTS_LENGTH:
2899 case Translation::CAPTURED_OBJECT:
2900 case Translation::REGISTER:
2901 case Translation::INT32_REGISTER:
2902 case Translation::INT64_REGISTER:
2903 case Translation::UINT32_REGISTER:
2904 case Translation::BOOL_REGISTER:
2905 case Translation::FLOAT_REGISTER:
2906 case Translation::DOUBLE_REGISTER:
2907 case Translation::STACK_SLOT:
2908 case Translation::INT32_STACK_SLOT:
2909 case Translation::INT64_STACK_SLOT:
2910 case Translation::UINT32_STACK_SLOT:
2911 case Translation::BOOL_STACK_SLOT:
2912 case Translation::FLOAT_STACK_SLOT:
2913 case Translation::DOUBLE_STACK_SLOT:
2914 case Translation::LITERAL:
2917 FATAL(
"We should never get here - unexpected deopt info.");
2918 return TranslatedFrame::InvalidFrame();
2922 void TranslatedFrame::AdvanceIterator(
2923 std::deque<TranslatedValue>::iterator* iter) {
2924 int values_to_skip = 1;
2925 while (values_to_skip > 0) {
2929 values_to_skip += (*iter)->GetChildrenCount();
2935 Address TranslatedState::ComputeArgumentsPosition(Address input_frame_pointer,
2936 CreateArgumentsType type,
2938 Address parent_frame_pointer = *
reinterpret_cast<Address*
>(
2939 input_frame_pointer + StandardFrameConstants::kCallerFPOffset);
2940 intptr_t parent_frame_type = Memory<intptr_t>(
2941 parent_frame_pointer + CommonFrameConstants::kContextOrFrameTypeOffset);
2943 Address arguments_frame;
2944 if (parent_frame_type ==
2945 StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)) {
2947 *length = Smi::cast(*reinterpret_cast<Object**>(
2948 parent_frame_pointer +
2949 ArgumentsAdaptorFrameConstants::kLengthOffset))
2951 arguments_frame = parent_frame_pointer;
2953 if (length) *length = formal_parameter_count_;
2954 arguments_frame = input_frame_pointer;
2957 if (type == CreateArgumentsType::kRestParameter) {
2960 if (length) *length = std::max(0, *length - formal_parameter_count_);
2963 return arguments_frame;
2970 void TranslatedState::CreateArgumentsElementsTranslatedValues(
2971 int frame_index, Address input_frame_pointer, CreateArgumentsType type,
2973 TranslatedFrame& frame = frames_[frame_index];
2976 Address arguments_frame =
2977 ComputeArgumentsPosition(input_frame_pointer, type, &length);
2979 int object_index =
static_cast<int>(object_positions_.size());
2980 int value_index =
static_cast<int>(frame.values_.size());
2981 if (trace_file !=
nullptr) {
2982 PrintF(trace_file,
"arguments elements object #%d (type = %d, length = %d)",
2983 object_index, static_cast<uint8_t>(type), length);
2986 object_positions_.push_back({frame_index, value_index});
2987 frame.Add(TranslatedValue::NewDeferredObject(
2988 this, length + FixedArray::kHeaderSize / kPointerSize, object_index));
2990 ReadOnlyRoots roots(isolate_);
2991 frame.Add(TranslatedValue::NewTagged(
this, roots.fixed_array_map()));
2992 frame.Add(TranslatedValue::NewInt32(
this, length));
2994 int number_of_holes = 0;
2995 if (type == CreateArgumentsType::kMappedArguments) {
2998 number_of_holes = Min(formal_parameter_count_, length);
3000 for (
int i = 0;
i < number_of_holes; ++
i) {
3001 frame.Add(TranslatedValue::NewTagged(
this, roots.the_hole_value()));
3003 for (
int i = length - number_of_holes - 1;
i >= 0; --
i) {
3004 Address argument_slot = arguments_frame +
3005 CommonFrameConstants::kFixedFrameSizeAboveFp +
3007 frame.Add(TranslatedValue::NewTagged(
3008 this, *reinterpret_cast<Object**>(argument_slot)));
3021 int TranslatedState::CreateNextTranslatedValue(
3022 int frame_index, TranslationIterator* iterator, FixedArray literal_array,
3023 Address fp, RegisterValues* registers, FILE* trace_file) {
3026 TranslatedFrame& frame = frames_[frame_index];
3027 int value_index =
static_cast<int>(frame.values_.size());
3029 Translation::Opcode opcode =
3030 static_cast<Translation::Opcode
>(iterator->Next());
3032 case Translation::BEGIN:
3033 case Translation::INTERPRETED_FRAME:
3034 case Translation::ARGUMENTS_ADAPTOR_FRAME:
3035 case Translation::CONSTRUCT_STUB_FRAME:
3036 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
3037 case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME:
3038 case Translation::BUILTIN_CONTINUATION_FRAME:
3039 case Translation::UPDATE_FEEDBACK:
3043 case Translation::DUPLICATED_OBJECT: {
3044 int object_id = iterator->Next();
3045 if (trace_file !=
nullptr) {
3046 PrintF(trace_file,
"duplicated object #%d", object_id);
3048 object_positions_.push_back(object_positions_[object_id]);
3049 TranslatedValue translated_value =
3050 TranslatedValue::NewDuplicateObject(
this, object_id);
3051 frame.Add(translated_value);
3052 return translated_value.GetChildrenCount();
3055 case Translation::ARGUMENTS_ELEMENTS: {
3056 CreateArgumentsType arguments_type =
3057 static_cast<CreateArgumentsType
>(iterator->Next());
3058 CreateArgumentsElementsTranslatedValues(frame_index, fp, arguments_type,
3063 case Translation::ARGUMENTS_LENGTH: {
3064 CreateArgumentsType arguments_type =
3065 static_cast<CreateArgumentsType
>(iterator->Next());
3067 ComputeArgumentsPosition(fp, arguments_type, &length);
3068 if (trace_file !=
nullptr) {
3069 PrintF(trace_file,
"arguments length field (type = %d, length = %d)",
3070 static_cast<uint8_t>(arguments_type), length);
3072 frame.Add(TranslatedValue::NewInt32(
this, length));
3076 case Translation::CAPTURED_OBJECT: {
3077 int field_count = iterator->Next();
3078 int object_index =
static_cast<int>(object_positions_.size());
3079 if (trace_file !=
nullptr) {
3080 PrintF(trace_file,
"captured object #%d (length = %d)", object_index,
3083 object_positions_.push_back({frame_index, value_index});
3084 TranslatedValue translated_value =
3085 TranslatedValue::NewDeferredObject(
this, field_count, object_index);
3086 frame.Add(translated_value);
3087 return translated_value.GetChildrenCount();
3090 case Translation::REGISTER: {
3091 int input_reg = iterator->Next();
3092 if (registers ==
nullptr) {
3093 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3094 frame.Add(translated_value);
3095 return translated_value.GetChildrenCount();
3097 intptr_t value = registers->GetRegister(input_reg);
3098 if (trace_file !=
nullptr) {
3099 PrintF(trace_file, V8PRIxPTR_FMT
" ; %s ", value,
3100 converter.NameOfCPURegister(input_reg));
3101 reinterpret_cast<Object*
>(value)->ShortPrint(trace_file);
3103 TranslatedValue translated_value =
3104 TranslatedValue::NewTagged(
this, reinterpret_cast<Object*>(value));
3105 frame.Add(translated_value);
3106 return translated_value.GetChildrenCount();
3109 case Translation::INT32_REGISTER: {
3110 int input_reg = iterator->Next();
3111 if (registers ==
nullptr) {
3112 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3113 frame.Add(translated_value);
3114 return translated_value.GetChildrenCount();
3116 intptr_t value = registers->GetRegister(input_reg);
3117 if (trace_file !=
nullptr) {
3118 PrintF(trace_file,
"%" V8PRIdPTR
" ; %s (int32)", value,
3119 converter.NameOfCPURegister(input_reg));
3121 TranslatedValue translated_value =
3122 TranslatedValue::NewInt32(
this, static_cast<int32_t>(value));
3123 frame.Add(translated_value);
3124 return translated_value.GetChildrenCount();
3127 case Translation::INT64_REGISTER: {
3128 int input_reg = iterator->Next();
3129 if (registers ==
nullptr) {
3130 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3131 frame.Add(translated_value);
3132 return translated_value.GetChildrenCount();
3134 intptr_t value = registers->GetRegister(input_reg);
3135 if (trace_file !=
nullptr) {
3136 PrintF(trace_file,
"%" V8PRIdPTR
" ; %s (int64)", value,
3137 converter.NameOfCPURegister(input_reg));
3139 TranslatedValue translated_value =
3140 TranslatedValue::NewInt64(
this, static_cast<int64_t>(value));
3141 frame.Add(translated_value);
3142 return translated_value.GetChildrenCount();
3145 case Translation::UINT32_REGISTER: {
3146 int input_reg = iterator->Next();
3147 if (registers ==
nullptr) {
3148 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3149 frame.Add(translated_value);
3150 return translated_value.GetChildrenCount();
3152 intptr_t value = registers->GetRegister(input_reg);
3153 if (trace_file !=
nullptr) {
3154 PrintF(trace_file,
"%" V8PRIuPTR
" ; %s (uint32)", value,
3155 converter.NameOfCPURegister(input_reg));
3157 TranslatedValue translated_value =
3158 TranslatedValue::NewUInt32(
this, static_cast<uint32_t>(value));
3159 frame.Add(translated_value);
3160 return translated_value.GetChildrenCount();
3163 case Translation::BOOL_REGISTER: {
3164 int input_reg = iterator->Next();
3165 if (registers ==
nullptr) {
3166 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3167 frame.Add(translated_value);
3168 return translated_value.GetChildrenCount();
3170 intptr_t value = registers->GetRegister(input_reg);
3171 if (trace_file !=
nullptr) {
3172 PrintF(trace_file,
"%" V8PRIdPTR
" ; %s (bool)", value,
3173 converter.NameOfCPURegister(input_reg));
3175 TranslatedValue translated_value =
3176 TranslatedValue::NewBool(
this, static_cast<uint32_t>(value));
3177 frame.Add(translated_value);
3178 return translated_value.GetChildrenCount();
3181 case Translation::FLOAT_REGISTER: {
3182 int input_reg = iterator->Next();
3183 if (registers ==
nullptr) {
3184 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3185 frame.Add(translated_value);
3186 return translated_value.GetChildrenCount();
3188 Float32 value = registers->GetFloatRegister(input_reg);
3189 if (trace_file !=
nullptr) {
3190 PrintF(trace_file,
"%e ; %s (float)", value.get_scalar(),
3191 RegisterName(FloatRegister::from_code(input_reg)));
3193 TranslatedValue translated_value = TranslatedValue::NewFloat(
this, value);
3194 frame.Add(translated_value);
3195 return translated_value.GetChildrenCount();
3198 case Translation::DOUBLE_REGISTER: {
3199 int input_reg = iterator->Next();
3200 if (registers ==
nullptr) {
3201 TranslatedValue translated_value = TranslatedValue::NewInvalid(
this);
3202 frame.Add(translated_value);
3203 return translated_value.GetChildrenCount();
3205 Float64 value = registers->GetDoubleRegister(input_reg);
3206 if (trace_file !=
nullptr) {
3207 PrintF(trace_file,
"%e ; %s (double)", value.get_scalar(),
3208 RegisterName(DoubleRegister::from_code(input_reg)));
3210 TranslatedValue translated_value =
3211 TranslatedValue::NewDouble(
this, value);
3212 frame.Add(translated_value);
3213 return translated_value.GetChildrenCount();
3216 case Translation::STACK_SLOT: {
3218 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3219 intptr_t value = *(
reinterpret_cast<intptr_t*
>(fp + slot_offset));
3220 if (trace_file !=
nullptr) {
3221 PrintF(trace_file, V8PRIxPTR_FMT
" ; [fp %c %3d] ", value,
3222 slot_offset < 0 ?
'-' :
'+', std::abs(slot_offset));
3223 reinterpret_cast<Object*
>(value)->ShortPrint(trace_file);
3225 TranslatedValue translated_value =
3226 TranslatedValue::NewTagged(
this, reinterpret_cast<Object*>(value));
3227 frame.Add(translated_value);
3228 return translated_value.GetChildrenCount();
3231 case Translation::INT32_STACK_SLOT: {
3233 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3234 uint32_t value = GetUInt32Slot(fp, slot_offset);
3235 if (trace_file !=
nullptr) {
3236 PrintF(trace_file,
"%d ; (int32) [fp %c %3d] ",
3237 static_cast<int32_t>(value), slot_offset < 0 ?
'-' :
'+',
3238 std::abs(slot_offset));
3240 TranslatedValue translated_value = TranslatedValue::NewInt32(
this, value);
3241 frame.Add(translated_value);
3242 return translated_value.GetChildrenCount();
3245 case Translation::INT64_STACK_SLOT: {
3247 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3248 uint64_t value = GetUInt64Slot(fp, slot_offset);
3249 if (trace_file !=
nullptr) {
3250 PrintF(trace_file,
"%" V8PRIdPTR
" ; (int64) [fp %c %3d] ",
3251 static_cast<intptr_t>(value), slot_offset < 0 ?
'-' :
'+',
3252 std::abs(slot_offset));
3254 TranslatedValue translated_value = TranslatedValue::NewInt64(
this, value);
3255 frame.Add(translated_value);
3256 return translated_value.GetChildrenCount();
3259 case Translation::UINT32_STACK_SLOT: {
3261 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3262 uint32_t value = GetUInt32Slot(fp, slot_offset);
3263 if (trace_file !=
nullptr) {
3264 PrintF(trace_file,
"%u ; (uint32) [fp %c %3d] ", value,
3265 slot_offset < 0 ?
'-' :
'+', std::abs(slot_offset));
3267 TranslatedValue translated_value =
3268 TranslatedValue::NewUInt32(
this, value);
3269 frame.Add(translated_value);
3270 return translated_value.GetChildrenCount();
3273 case Translation::BOOL_STACK_SLOT: {
3275 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3276 uint32_t value = GetUInt32Slot(fp, slot_offset);
3277 if (trace_file !=
nullptr) {
3278 PrintF(trace_file,
"%u ; (bool) [fp %c %3d] ", value,
3279 slot_offset < 0 ?
'-' :
'+', std::abs(slot_offset));
3281 TranslatedValue translated_value = TranslatedValue::NewBool(
this, value);
3282 frame.Add(translated_value);
3283 return translated_value.GetChildrenCount();
3286 case Translation::FLOAT_STACK_SLOT: {
3288 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3289 Float32 value = GetFloatSlot(fp, slot_offset);
3290 if (trace_file !=
nullptr) {
3291 PrintF(trace_file,
"%e ; (float) [fp %c %3d] ", value.get_scalar(),
3292 slot_offset < 0 ?
'-' :
'+', std::abs(slot_offset));
3294 TranslatedValue translated_value = TranslatedValue::NewFloat(
this, value);
3295 frame.Add(translated_value);
3296 return translated_value.GetChildrenCount();
3299 case Translation::DOUBLE_STACK_SLOT: {
3301 OptimizedFrame::StackSlotOffsetRelativeToFp(iterator->Next());
3302 Float64 value = GetDoubleSlot(fp, slot_offset);
3303 if (trace_file !=
nullptr) {
3304 PrintF(trace_file,
"%e ; (double) [fp %c %d] ", value.get_scalar(),
3305 slot_offset < 0 ?
'-' :
'+', std::abs(slot_offset));
3307 TranslatedValue translated_value =
3308 TranslatedValue::NewDouble(
this, value);
3309 frame.Add(translated_value);
3310 return translated_value.GetChildrenCount();
3313 case Translation::LITERAL: {
3314 int literal_index = iterator->Next();
3315 Object* value = literal_array->get(literal_index);
3316 if (trace_file !=
nullptr) {
3317 PrintF(trace_file, V8PRIxPTR_FMT
" ; (literal %2d) ",
3318 reinterpret_cast<intptr_t>(value), literal_index);
3319 reinterpret_cast<Object*
>(value)->ShortPrint(trace_file);
3322 TranslatedValue translated_value =
3323 TranslatedValue::NewTagged(
this, value);
3324 frame.Add(translated_value);
3325 return translated_value.GetChildrenCount();
3329 FATAL(
"We should never get here - unexpected deopt info.");
3332 TranslatedState::TranslatedState(
const JavaScriptFrame* frame) {
3333 int deopt_index = Safepoint::kNoDeoptimizationIndex;
3334 DeoptimizationData data =
3335 static_cast<const OptimizedFrame*
>(frame)->GetDeoptimizationData(
3337 DCHECK(!data.is_null() && deopt_index != Safepoint::kNoDeoptimizationIndex);
3338 TranslationIterator it(data->TranslationByteArray(),
3339 data->TranslationIndex(deopt_index)->value());
3340 Init(frame->isolate(), frame->fp(), &it, data->LiteralArray(),
3342 frame->function()->shared()->internal_formal_parameter_count());
3345 void TranslatedState::Init(Isolate* isolate, Address input_frame_pointer,
3346 TranslationIterator* iterator,
3347 FixedArray literal_array, RegisterValues* registers,
3348 FILE* trace_file,
int formal_parameter_count) {
3349 DCHECK(frames_.empty());
3351 formal_parameter_count_ = formal_parameter_count;
3355 Translation::Opcode opcode =
3356 static_cast<Translation::Opcode
>(iterator->Next());
3357 CHECK(opcode == Translation::BEGIN);
3359 int count = iterator->Next();
3360 frames_.reserve(count);
3362 int update_feedback_count = iterator->Next();
3363 CHECK_GE(update_feedback_count, 0);
3364 CHECK_LE(update_feedback_count, 1);
3366 if (update_feedback_count == 1) {
3367 ReadUpdateFeedback(iterator, literal_array, trace_file);
3370 std::stack<int> nested_counts;
3373 for (
int frame_index = 0; frame_index < count; frame_index++) {
3375 frames_.push_back(CreateNextTranslatedFrame(
3376 iterator, literal_array, input_frame_pointer, trace_file));
3377 TranslatedFrame& frame = frames_.back();
3380 int values_to_process = frame.GetValueCount();
3381 while (values_to_process > 0 || !nested_counts.empty()) {
3382 if (trace_file !=
nullptr) {
3383 if (nested_counts.empty()) {
3385 PrintF(trace_file,
" %3i: ",
3386 frame.GetValueCount() - values_to_process);
3389 PrintF(trace_file,
" ");
3390 for (
size_t j = 0; j < nested_counts.size(); j++) {
3391 PrintF(trace_file,
" ");
3397 CreateNextTranslatedValue(frame_index, iterator, literal_array,
3398 input_frame_pointer, registers, trace_file);
3400 if (trace_file !=
nullptr) {
3401 PrintF(trace_file,
"\n");
3405 values_to_process--;
3406 if (nested_count > 0) {
3407 nested_counts.push(values_to_process);
3408 values_to_process = nested_count;
3410 while (values_to_process == 0 && !nested_counts.empty()) {
3411 values_to_process = nested_counts.top();
3412 nested_counts.pop();
3418 CHECK(!iterator->HasNext() ||
3419 static_cast<Translation::Opcode
>(iterator->Next()) ==
3420 Translation::BEGIN);
3423 void TranslatedState::Prepare(Address stack_frame_pointer) {
3424 for (
auto& frame : frames_) frame.Handlify();
3426 if (feedback_vector_ !=
nullptr) {
3427 feedback_vector_handle_ =
3428 Handle<FeedbackVector>(feedback_vector_, isolate());
3429 feedback_vector_ =
nullptr;
3431 stack_frame_pointer_ = stack_frame_pointer;
3433 UpdateFromPreviouslyMaterializedObjects();
3436 TranslatedValue* TranslatedState::GetValueByObjectIndex(
int object_index) {
3437 CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
3438 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3439 return &(frames_[pos.frame_index_].values_[pos.value_index_]);
3442 Handle<Object> TranslatedState::InitializeObjectAt(TranslatedValue* slot) {
3443 slot = ResolveCapturedObject(slot);
3445 DisallowHeapAllocation no_allocation;
3446 if (slot->materialization_state() != TranslatedValue::kFinished) {
3447 std::stack<int> worklist;
3448 worklist.push(slot->object_index());
3449 slot->mark_finished();
3451 while (!worklist.empty()) {
3452 int index = worklist.top();
3454 InitializeCapturedObjectAt(index, &worklist, no_allocation);
3457 return slot->GetStorage();
3460 void TranslatedState::InitializeCapturedObjectAt(
3461 int object_index, std::stack<int>* worklist,
3462 const DisallowHeapAllocation& no_allocation) {
3463 CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
3464 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3465 int value_index = pos.value_index_;
3467 TranslatedFrame* frame = &(frames_[pos.frame_index_]);
3468 TranslatedValue* slot = &(frame->values_[value_index]);
3471 CHECK_EQ(TranslatedValue::kFinished, slot->materialization_state());
3472 CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
3475 int children_init_index = value_index;
3476 for (
int i = 0;
i < slot->GetChildrenCount();
i++) {
3479 TranslatedValue* child_slot = frame->ValueAt(children_init_index);
3480 if (child_slot->kind() == TranslatedValue::kCapturedObject ||
3481 child_slot->kind() == TranslatedValue::kDuplicatedObject) {
3482 child_slot = ResolveCapturedObject(child_slot);
3483 if (child_slot->materialization_state() != TranslatedValue::kFinished) {
3484 DCHECK_EQ(TranslatedValue::kAllocated,
3485 child_slot->materialization_state());
3486 worklist->push(child_slot->object_index());
3487 child_slot->mark_finished();
3490 SkipSlots(1, frame, &children_init_index);
3496 CHECK_EQ(frame->values_[value_index].kind(), TranslatedValue::kTagged);
3497 Handle<Map> map = Handle<Map>::cast(frame->values_[value_index].GetValue());
3498 CHECK(map->IsMap());
3502 switch (map->instance_type()) {
3503 case MUTABLE_HEAP_NUMBER_TYPE:
3504 case FIXED_DOUBLE_ARRAY_TYPE:
3507 case FIXED_ARRAY_TYPE:
3508 case AWAIT_CONTEXT_TYPE:
3509 case BLOCK_CONTEXT_TYPE:
3510 case CATCH_CONTEXT_TYPE:
3511 case DEBUG_EVALUATE_CONTEXT_TYPE:
3512 case EVAL_CONTEXT_TYPE:
3513 case FUNCTION_CONTEXT_TYPE:
3514 case MODULE_CONTEXT_TYPE:
3515 case NATIVE_CONTEXT_TYPE:
3516 case SCRIPT_CONTEXT_TYPE:
3517 case WITH_CONTEXT_TYPE:
3518 case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
3519 case HASH_TABLE_TYPE:
3520 case ORDERED_HASH_MAP_TYPE:
3521 case ORDERED_HASH_SET_TYPE:
3522 case NAME_DICTIONARY_TYPE:
3523 case GLOBAL_DICTIONARY_TYPE:
3524 case NUMBER_DICTIONARY_TYPE:
3525 case SIMPLE_NUMBER_DICTIONARY_TYPE:
3526 case STRING_TABLE_TYPE:
3527 case PROPERTY_ARRAY_TYPE:
3528 case SCRIPT_CONTEXT_TABLE_TYPE:
3529 InitializeObjectWithTaggedFieldsAt(frame, &value_index, slot, map,
3534 CHECK(map->IsJSObjectMap());
3535 InitializeJSObjectAt(frame, &value_index, slot, map, no_allocation);
3538 CHECK_EQ(value_index, children_init_index);
3541 void TranslatedState::EnsureObjectAllocatedAt(TranslatedValue* slot) {
3542 slot = ResolveCapturedObject(slot);
3544 if (slot->materialization_state() == TranslatedValue::kUninitialized) {
3545 std::stack<int> worklist;
3546 worklist.push(slot->object_index());
3547 slot->mark_allocated();
3549 while (!worklist.empty()) {
3550 int index = worklist.top();
3552 EnsureCapturedObjectAllocatedAt(index, &worklist);
3557 void TranslatedState::MaterializeFixedDoubleArray(TranslatedFrame* frame,
3559 TranslatedValue* slot,
3561 int length = Smi::cast(frame->values_[*value_index].GetRawValue())->value();
3563 Handle<FixedDoubleArray> array = Handle<FixedDoubleArray>::cast(
3564 isolate()->factory()->NewFixedDoubleArray(length));
3565 CHECK_GT(length, 0);
3566 for (
int i = 0;
i < length;
i++) {
3567 CHECK_NE(TranslatedValue::kCapturedObject,
3568 frame->values_[*value_index].kind());
3569 Handle<Object> value = frame->values_[*value_index].GetValue();
3570 if (value->IsNumber()) {
3571 array->set(
i, value->Number());
3573 CHECK(value.is_identical_to(isolate()->factory()->the_hole_value()));
3574 array->set_the_hole(isolate(),
i);
3578 slot->set_storage(array);
3581 void TranslatedState::MaterializeMutableHeapNumber(TranslatedFrame* frame,
3583 TranslatedValue* slot) {
3584 CHECK_NE(TranslatedValue::kCapturedObject,
3585 frame->values_[*value_index].kind());
3586 Handle<Object> value = frame->values_[*value_index].GetValue();
3587 CHECK(value->IsNumber());
3588 Handle<MutableHeapNumber> box =
3589 isolate()->factory()->NewMutableHeapNumber(value->Number());
3591 slot->set_storage(box);
3596 enum DoubleStorageKind : uint8_t {
3598 kStoreUnboxedDouble,
3599 kStoreMutableHeapNumber,
3604 void TranslatedState::SkipSlots(
int slots_to_skip, TranslatedFrame* frame,
3606 while (slots_to_skip > 0) {
3607 TranslatedValue* slot = &(frame->values_[*value_index]);
3611 if (slot->kind() == TranslatedValue::kCapturedObject) {
3612 slots_to_skip += slot->GetChildrenCount();
3617 void TranslatedState::EnsureCapturedObjectAllocatedAt(
3618 int object_index, std::stack<int>* worklist) {
3619 CHECK_LT(static_cast<size_t>(object_index), object_positions_.size());
3620 TranslatedState::ObjectPosition pos = object_positions_[object_index];
3621 int value_index = pos.value_index_;
3623 TranslatedFrame* frame = &(frames_[pos.frame_index_]);
3624 TranslatedValue* slot = &(frame->values_[value_index]);
3627 CHECK_EQ(TranslatedValue::kAllocated, slot->materialization_state());
3628 CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
3633 CHECK_EQ(frame->values_[value_index].kind(), TranslatedValue::kTagged);
3634 Handle<Map> map = Handle<Map>::cast(frame->values_[value_index].GetValue());
3635 CHECK(map->IsMap());
3639 switch (map->instance_type()) {
3640 case FIXED_DOUBLE_ARRAY_TYPE:
3643 return MaterializeFixedDoubleArray(frame, &value_index, slot, map);
3645 case MUTABLE_HEAP_NUMBER_TYPE:
3648 return MaterializeMutableHeapNumber(frame, &value_index, slot);
3650 case FIXED_ARRAY_TYPE:
3651 case SCRIPT_CONTEXT_TABLE_TYPE:
3652 case AWAIT_CONTEXT_TYPE:
3653 case BLOCK_CONTEXT_TYPE:
3654 case CATCH_CONTEXT_TYPE:
3655 case DEBUG_EVALUATE_CONTEXT_TYPE:
3656 case EVAL_CONTEXT_TYPE:
3657 case FUNCTION_CONTEXT_TYPE:
3658 case MODULE_CONTEXT_TYPE:
3659 case NATIVE_CONTEXT_TYPE:
3660 case SCRIPT_CONTEXT_TYPE:
3661 case WITH_CONTEXT_TYPE:
3662 case HASH_TABLE_TYPE:
3663 case ORDERED_HASH_MAP_TYPE:
3664 case ORDERED_HASH_SET_TYPE:
3665 case NAME_DICTIONARY_TYPE:
3666 case GLOBAL_DICTIONARY_TYPE:
3667 case NUMBER_DICTIONARY_TYPE:
3668 case SIMPLE_NUMBER_DICTIONARY_TYPE:
3669 case STRING_TABLE_TYPE: {
3672 Smi::cast(frame->values_[value_index].GetRawValue())->value();
3674 int instance_size = FixedArray::SizeFor(array_length);
3675 CHECK_EQ(instance_size, slot->GetChildrenCount() * kPointerSize);
3678 if (*map == ReadOnlyRoots(isolate()).empty_fixed_array()->map() &&
3679 array_length == 0) {
3680 slot->set_storage(isolate()->factory()->empty_fixed_array());
3682 slot->set_storage(AllocateStorageFor(slot));
3686 return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
3687 &value_index, worklist);
3690 case PROPERTY_ARRAY_TYPE: {
3692 int length_or_hash =
3693 Smi::cast(frame->values_[value_index].GetRawValue())->value();
3694 int array_length = PropertyArray::LengthField::decode(length_or_hash);
3695 int instance_size = PropertyArray::SizeFor(array_length);
3696 CHECK_EQ(instance_size, slot->GetChildrenCount() * kPointerSize);
3698 slot->set_storage(AllocateStorageFor(slot));
3700 return EnsureChildrenAllocated(slot->GetChildrenCount() - 1, frame,
3701 &value_index, worklist);
3705 CHECK(map->IsJSObjectMap());
3706 EnsureJSObjectAllocated(slot, map);
3707 TranslatedValue* properties_slot = &(frame->values_[value_index]);
3709 if (properties_slot->kind() == TranslatedValue::kCapturedObject) {
3712 EnsurePropertiesAllocatedAndMarked(properties_slot, map);
3713 EnsureChildrenAllocated(properties_slot->GetChildrenCount(), frame,
3714 &value_index, worklist);
3718 return EnsureChildrenAllocated(slot->GetChildrenCount() - 2, frame,
3719 &value_index, worklist);
3724 void TranslatedState::EnsureChildrenAllocated(
int count, TranslatedFrame* frame,
3726 std::stack<int>* worklist) {
3728 for (
int i = 0;
i < count;
i++) {
3731 TranslatedValue* child_slot = frame->ValueAt(*value_index);
3732 if (child_slot->kind() == TranslatedValue::kCapturedObject ||
3733 child_slot->kind() == TranslatedValue::kDuplicatedObject) {
3734 child_slot = ResolveCapturedObject(child_slot);
3735 if (child_slot->materialization_state() ==
3736 TranslatedValue::kUninitialized) {
3737 worklist->push(child_slot->object_index());
3738 child_slot->mark_allocated();
3743 child_slot->MaterializeSimple();
3745 SkipSlots(1, frame, value_index);
3749 void TranslatedState::EnsurePropertiesAllocatedAndMarked(
3750 TranslatedValue* properties_slot, Handle<Map> map) {
3751 CHECK_EQ(TranslatedValue::kUninitialized,
3752 properties_slot->materialization_state());
3754 Handle<ByteArray> object_storage = AllocateStorageFor(properties_slot);
3755 properties_slot->mark_allocated();
3756 properties_slot->set_storage(object_storage);
3759 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
3760 int field_count = map->NumberOfOwnDescriptors();
3761 for (
int i = 0;
i < field_count;
i++) {
3762 FieldIndex index = FieldIndex::ForDescriptor(*map,
i);
3763 if (descriptors->GetDetails(
i).representation().IsDouble() &&
3764 !index.is_inobject()) {
3765 CHECK(!map->IsUnboxedDoubleField(index));
3766 int outobject_index = index.outobject_array_index();
3767 int array_index = outobject_index * kPointerSize;
3768 object_storage->set(array_index, kStoreMutableHeapNumber);
3773 Handle<ByteArray> TranslatedState::AllocateStorageFor(TranslatedValue* slot) {
3775 ByteArray::LengthFor(slot->GetChildrenCount() * kPointerSize);
3778 Handle<ByteArray> object_storage =
3779 isolate()->factory()->NewByteArray(allocate_size, TENURED);
3780 for (
int i = 0;
i < object_storage->length();
i++) {
3781 object_storage->set(
i, kStoreTagged);
3783 return object_storage;
3786 void TranslatedState::EnsureJSObjectAllocated(TranslatedValue* slot,
3788 CHECK_EQ(map->instance_size(), slot->GetChildrenCount() * kPointerSize);
3790 Handle<ByteArray> object_storage = AllocateStorageFor(slot);
3792 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate());
3793 int field_count = map->NumberOfOwnDescriptors();
3796 for (
int i = 0;
i < field_count;
i++) {
3797 FieldIndex index = FieldIndex::ForDescriptor(*map,
i);
3798 if (descriptors->GetDetails(
i).representation().IsDouble() &&
3799 index.is_inobject()) {
3800 CHECK_GE(index.index(), FixedArray::kHeaderSize / kPointerSize);
3801 int array_index = index.index() * kPointerSize - FixedArray::kHeaderSize;
3802 uint8_t marker = map->IsUnboxedDoubleField(index)
3803 ? kStoreUnboxedDouble
3804 : kStoreMutableHeapNumber;
3805 object_storage->set(array_index, marker);
3808 slot->set_storage(object_storage);
3811 Handle<Object> TranslatedState::GetValueAndAdvance(TranslatedFrame* frame,
3813 TranslatedValue* slot = frame->ValueAt(*value_index);
3814 SkipSlots(1, frame, value_index);
3815 if (slot->kind() == TranslatedValue::kDuplicatedObject) {
3816 slot = ResolveCapturedObject(slot);
3818 CHECK_NE(TranslatedValue::kUninitialized, slot->materialization_state());
3819 return slot->GetStorage();
3822 void TranslatedState::InitializeJSObjectAt(
3823 TranslatedFrame* frame,
int* value_index, TranslatedValue* slot,
3824 Handle<Map> map,
const DisallowHeapAllocation& no_allocation) {
3825 Handle<HeapObject> object_storage = Handle<HeapObject>::cast(slot->storage_);
3826 DCHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
3829 CHECK_GE(slot->GetChildrenCount(), 2);
3832 isolate()->heap()->NotifyObjectLayoutChange(
3833 *object_storage, slot->GetChildrenCount() * kPointerSize, no_allocation);
3837 Handle<Object> properties = GetValueAndAdvance(frame, value_index);
3838 WRITE_FIELD(*object_storage, JSObject::kPropertiesOrHashOffset,
3840 WRITE_BARRIER(*object_storage, JSObject::kPropertiesOrHashOffset,
3846 DCHECK_EQ(kPointerSize, JSObject::kPropertiesOrHashOffset);
3847 for (
int i = 2;
i < slot->GetChildrenCount();
i++) {
3849 Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
3854 int offset =
i * kPointerSize;
3855 uint8_t marker = READ_UINT8_FIELD(*object_storage, offset);
3856 if (marker == kStoreUnboxedDouble) {
3857 double double_field_value;
3858 if (field_value->IsSmi()) {
3859 double_field_value = Smi::cast(*field_value)->value();
3861 CHECK(field_value->IsHeapNumber());
3862 double_field_value = HeapNumber::cast(*field_value)->value();
3864 WRITE_DOUBLE_FIELD(*object_storage, offset, double_field_value);
3865 }
else if (marker == kStoreMutableHeapNumber) {
3866 CHECK(field_value->IsMutableHeapNumber());
3867 WRITE_FIELD(*object_storage, offset, *field_value);
3868 WRITE_BARRIER(*object_storage, offset, *field_value);
3870 CHECK_EQ(kStoreTagged, marker);
3871 WRITE_FIELD(*object_storage, offset, *field_value);
3872 WRITE_BARRIER(*object_storage, offset, *field_value);
3875 object_storage->synchronized_set_map(*map);
3878 void TranslatedState::InitializeObjectWithTaggedFieldsAt(
3879 TranslatedFrame* frame,
int* value_index, TranslatedValue* slot,
3880 Handle<Map> map,
const DisallowHeapAllocation& no_allocation) {
3881 Handle<HeapObject> object_storage = Handle<HeapObject>::cast(slot->storage_);
3884 if (*object_storage == ReadOnlyRoots(isolate()).empty_fixed_array()) {
3885 CHECK_EQ(2, slot->GetChildrenCount());
3886 Handle<Object> length_value = GetValueAndAdvance(frame, value_index);
3887 CHECK_EQ(*length_value, Smi::FromInt(0));
3892 isolate()->heap()->NotifyObjectLayoutChange(
3893 *object_storage, slot->GetChildrenCount() * kPointerSize, no_allocation);
3896 for (
int i = 1;
i < slot->GetChildrenCount();
i++) {
3897 Handle<Object> field_value = GetValueAndAdvance(frame, value_index);
3898 int offset =
i * kPointerSize;
3899 uint8_t marker = READ_UINT8_FIELD(*object_storage, offset);
3900 if (
i > 1 && marker == kStoreMutableHeapNumber) {
3901 CHECK(field_value->IsMutableHeapNumber());
3903 CHECK(marker == kStoreTagged ||
i == 1);
3904 CHECK(!field_value->IsMutableHeapNumber());
3907 WRITE_FIELD(*object_storage, offset, *field_value);
3908 WRITE_BARRIER(*object_storage, offset, *field_value);
3911 object_storage->synchronized_set_map(*map);
3914 TranslatedValue* TranslatedState::ResolveCapturedObject(TranslatedValue* slot) {
3915 while (slot->kind() == TranslatedValue::kDuplicatedObject) {
3916 slot = GetValueByObjectIndex(slot->object_index());
3918 CHECK_EQ(TranslatedValue::kCapturedObject, slot->kind());
3922 TranslatedFrame* TranslatedState::GetFrameFromJSFrameIndex(
int jsframe_index) {
3923 for (
size_t i = 0;
i < frames_.size();
i++) {
3924 if (frames_[
i].kind() == TranslatedFrame::kInterpretedFunction ||
3925 frames_[
i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
3926 frames_[
i].kind() ==
3927 TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
3928 if (jsframe_index > 0) {
3931 return &(frames_[
i]);
3938 TranslatedFrame* TranslatedState::GetArgumentsInfoFromJSFrameIndex(
3939 int jsframe_index,
int* args_count) {
3940 for (
size_t i = 0;
i < frames_.size();
i++) {
3941 if (frames_[
i].kind() == TranslatedFrame::kInterpretedFunction ||
3942 frames_[
i].kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
3943 frames_[
i].kind() ==
3944 TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
3945 if (jsframe_index > 0) {
3951 frames_[
i - 1].kind() == TranslatedFrame::kArgumentsAdaptor) {
3952 *args_count = frames_[
i - 1].height();
3953 return &(frames_[
i - 1]);
3956 frames_[
i].shared_info()->internal_formal_parameter_count() + 1;
3957 return &(frames_[
i]);
3964 void TranslatedState::StoreMaterializedValuesAndDeopt(JavaScriptFrame* frame) {
3965 MaterializedObjectStore* materialized_store =
3966 isolate_->materialized_object_store();
3967 Handle<FixedArray> previously_materialized_objects =
3968 materialized_store->Get(stack_frame_pointer_);
3970 Handle<Object> marker = isolate_->factory()->arguments_marker();
3972 int length =
static_cast<int>(object_positions_.size());
3973 bool new_store =
false;
3974 if (previously_materialized_objects.is_null()) {
3975 previously_materialized_objects =
3976 isolate_->factory()->NewFixedArray(length, TENURED);
3977 for (
int i = 0;
i < length;
i++) {
3978 previously_materialized_objects->set(
i, *marker);
3983 CHECK_EQ(length, previously_materialized_objects->length());
3985 bool value_changed =
false;
3986 for (
int i = 0;
i < length;
i++) {
3987 TranslatedState::ObjectPosition pos = object_positions_[
i];
3988 TranslatedValue* value_info =
3989 &(frames_[pos.frame_index_].values_[pos.value_index_]);
3991 CHECK(value_info->IsMaterializedObject());
3995 if (value_info->object_index() !=
i)
continue;
3997 Handle<Object> value(value_info->GetRawValue(), isolate_);
3999 if (!value.is_identical_to(marker)) {
4000 if (previously_materialized_objects->get(
i) == *marker) {
4001 previously_materialized_objects->set(
i, *value);
4002 value_changed =
true;
4004 CHECK(previously_materialized_objects->get(
i) == *value);
4008 if (new_store && value_changed) {
4009 materialized_store->Set(stack_frame_pointer_,
4010 previously_materialized_objects);
4011 CHECK_EQ(frames_[0].kind(), TranslatedFrame::kInterpretedFunction);
4012 CHECK_EQ(frame->function(), frames_[0].front().GetRawValue());
4013 Deoptimizer::DeoptimizeFunction(frame->function(), frame->LookupCode());
4017 void TranslatedState::UpdateFromPreviouslyMaterializedObjects() {
4018 MaterializedObjectStore* materialized_store =
4019 isolate_->materialized_object_store();
4020 Handle<FixedArray> previously_materialized_objects =
4021 materialized_store->Get(stack_frame_pointer_);
4024 if (previously_materialized_objects.is_null())
return;
4026 Handle<Object> marker = isolate_->factory()->arguments_marker();
4028 int length =
static_cast<int>(object_positions_.size());
4029 CHECK_EQ(length, previously_materialized_objects->length());
4031 for (
int i = 0;
i < length;
i++) {
4034 if (previously_materialized_objects->get(
i) != *marker) {
4035 TranslatedState::ObjectPosition pos = object_positions_[
i];
4036 TranslatedValue* value_info =
4037 &(frames_[pos.frame_index_].values_[pos.value_index_]);
4038 CHECK(value_info->IsMaterializedObject());
4040 if (value_info->kind() == TranslatedValue::kCapturedObject) {
4041 value_info->set_initialized_storage(
4042 Handle<Object>(previously_materialized_objects->get(
i), isolate_));
4048 void TranslatedState::VerifyMaterializedObjects() {
4050 int length =
static_cast<int>(object_positions_.size());
4051 for (
int i = 0;
i < length;
i++) {
4052 TranslatedValue* slot = GetValueByObjectIndex(
i);
4053 if (slot->kind() == TranslatedValue::kCapturedObject) {
4054 CHECK_EQ(slot, GetValueByObjectIndex(slot->object_index()));
4055 if (slot->materialization_state() == TranslatedValue::kFinished) {
4056 slot->GetStorage()->ObjectVerify(isolate());
4058 CHECK_EQ(slot->materialization_state(),
4059 TranslatedValue::kUninitialized);
4066 bool TranslatedState::DoUpdateFeedback() {
4067 if (!feedback_vector_handle_.is_null()) {
4068 CHECK(!feedback_slot_.IsInvalid());
4069 isolate()->CountUsage(v8::Isolate::kDeoptimizerDisableSpeculation);
4070 FeedbackNexus nexus(feedback_vector_handle_, feedback_slot_);
4071 nexus.SetSpeculationMode(SpeculationMode::kDisallowSpeculation);
4077 void TranslatedState::ReadUpdateFeedback(TranslationIterator* iterator,
4078 FixedArray literal_array,
4080 CHECK_EQ(Translation::UPDATE_FEEDBACK, iterator->Next());
4081 feedback_vector_ = FeedbackVector::cast(literal_array->get(iterator->Next()));
4082 feedback_slot_ = FeedbackSlot(iterator->Next());
4083 if (trace_file !=
nullptr) {
4084 PrintF(trace_file,
" reading FeedbackVector (slot %d)\n",
4085 feedback_slot_.ToInt());
4093 #include "src/objects/object-macros-undef.h"