5 #ifndef V8_DEOPTIMIZER_H_ 6 #define V8_DEOPTIMIZER_H_ 11 #include "src/allocation.h" 12 #include "src/base/macros.h" 13 #include "src/boxed-float.h" 14 #include "src/code-tracer.h" 15 #include "src/deoptimize-reason.h" 16 #include "src/feedback-vector.h" 17 #include "src/frame-constants.h" 18 #include "src/globals.h" 19 #include "src/isolate.h" 20 #include "src/macro-assembler.h" 21 #include "src/objects/shared-function-info.h" 22 #include "src/source-position.h" 23 #include "src/zone/zone-chunk-list.h" 28 class FrameDescription;
29 class TranslationIterator;
30 class DeoptimizedFrameInfo;
31 class TranslatedState;
39 Object* GetRawValue()
const;
45 bool IsMaterializedObject()
const;
46 bool IsMaterializableByDebugger()
const;
69 enum MaterializationState : uint8_t {
78 : kind_(kind), container_(container) {}
79 Kind kind()
const {
return kind_; }
80 MaterializationState materialization_state()
const {
81 return materialization_state_;
84 int GetChildrenCount()
const;
87 int length,
int object_index);
99 void MaterializeSimple();
103 void mark_finished() { materialization_state_ = kFinished; }
104 void mark_allocated() { materialization_state_ = kAllocated; }
107 DCHECK_NE(kUninitialized, materialization_state());
112 MaterializationState materialization_state_ = kUninitialized;
121 struct MaterializedObjectInfo {
132 int32_t int32_value_;
140 MaterializedObjectInfo materialization_info_;
144 Object* raw_literal()
const;
145 int32_t int32_value()
const;
150 int object_length()
const;
151 int object_index()
const;
158 kInterpretedFunction,
161 kBuiltinContinuation,
162 kJavaScriptBuiltinContinuation,
163 kJavaScriptBuiltinContinuationWithCatch,
169 Kind kind()
const {
return kind_; }
170 BailoutId node_id()
const {
return node_id_; }
172 int height()
const {
return height_; }
173 int return_value_offset()
const {
return return_value_offset_; }
174 int return_value_count()
const {
return return_value_count_; }
177 CHECK_NOT_NULL(raw_shared_info_);
178 return raw_shared_info_;
185 AdvanceIterator(&position_);
190 iterator original(position_, input_index_);
192 AdvanceIterator(&position_);
196 bool operator==(
const iterator& other)
const {
198 return position_ == other.position_;
200 bool operator!=(
const iterator& other)
const {
return !(*
this == other); }
207 int input_index()
const {
return input_index_; }
212 explicit iterator(std::deque<TranslatedValue>::iterator position,
214 : position_(position), input_index_(input_index) {}
216 std::deque<TranslatedValue>::iterator position_;
224 iterator end() {
return iterator(values_.end()); }
226 reference front() {
return values_.front(); }
227 const_reference front()
const {
return values_.front(); }
230 friend class TranslatedState;
233 static TranslatedFrame InterpretedFrame(BailoutId bytecode_offset,
234 SharedFunctionInfo* shared_info,
235 int height,
int return_value_offset,
236 int return_value_count);
237 static TranslatedFrame AccessorFrame(Kind kind,
238 SharedFunctionInfo* shared_info);
239 static TranslatedFrame ArgumentsAdaptorFrame(SharedFunctionInfo* shared_info,
241 static TranslatedFrame ConstructStubFrame(BailoutId bailout_id,
242 SharedFunctionInfo* shared_info,
244 static TranslatedFrame BuiltinContinuationFrame(
245 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height);
246 static TranslatedFrame JavaScriptBuiltinContinuationFrame(
247 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height);
248 static TranslatedFrame JavaScriptBuiltinContinuationWithCatchFrame(
249 BailoutId bailout_id, SharedFunctionInfo* shared_info,
int height);
250 static TranslatedFrame InvalidFrame() {
251 return TranslatedFrame(kInvalid,
nullptr);
254 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter);
256 TranslatedFrame(Kind kind, SharedFunctionInfo* shared_info =
nullptr,
257 int height = 0,
int return_value_offset = 0,
258 int return_value_count = 0)
260 node_id_(BailoutId::
None()),
261 raw_shared_info_(shared_info),
263 return_value_offset_(return_value_offset),
264 return_value_count_(return_value_count) {}
266 void Add(
const TranslatedValue& value) { values_.push_back(value); }
267 TranslatedValue* ValueAt(
int index) {
return &(values_[index]); }
272 SharedFunctionInfo* raw_shared_info_;
273 Handle<SharedFunctionInfo> shared_info_;
275 int return_value_offset_;
276 int return_value_count_;
278 typedef std::deque<TranslatedValue> ValuesContainer;
280 ValuesContainer values_;
304 void Prepare(
Address stack_frame_pointer);
309 typedef std::vector<TranslatedFrame>::iterator iterator;
310 iterator begin() {
return frames_.begin(); }
311 iterator end() {
return frames_.end(); }
313 typedef std::vector<TranslatedFrame>::const_iterator const_iterator;
314 const_iterator begin()
const {
return frames_.begin(); }
315 const_iterator end()
const {
return frames_.end(); }
317 std::vector<TranslatedFrame>& frames() {
return frames_; }
321 int* arguments_count);
323 Isolate* isolate() {
return isolate_; }
327 RegisterValues* registers, FILE* trace_file,
int parameter_count);
329 void VerifyMaterializedObjects();
330 bool DoUpdateFeedback();
342 CreateArgumentsType
type,
int* length);
343 void CreateArgumentsElementsTranslatedValues(
int frame_index,
345 CreateArgumentsType
type,
348 void UpdateFromPreviouslyMaterializedObjects();
349 void MaterializeFixedDoubleArray(
TranslatedFrame* frame,
int* value_index,
351 void MaterializeMutableHeapNumber(
TranslatedFrame* frame,
int* value_index,
356 void SkipSlots(
int slots_to_skip,
TranslatedFrame* frame,
int* value_index);
360 void EnsurePropertiesAllocatedAndMarked(
TranslatedValue* properties_slot,
363 int* value_index, std::stack<int>* worklist);
364 void EnsureCapturedObjectAllocatedAt(
int object_index,
365 std::stack<int>* worklist);
367 void InitializeCapturedObjectAt(
int object_index, std::stack<int>* worklist,
372 void InitializeObjectWithTaggedFieldsAt(
384 static uint64_t GetUInt64Slot(
Address fp,
int slot_index);
388 std::vector<TranslatedFrame> frames_;
390 Address stack_frame_pointer_ = kNullAddress;
391 int formal_parameter_count_;
393 struct ObjectPosition {
397 std::deque<ObjectPosition> object_positions_;
406 virtual void VisitFunction(
JSFunction*
function) = 0;
414 : position(position), deopt_reason(deopt_reason), deopt_id(deopt_id) {}
417 DeoptimizeReason deopt_reason;
420 static const int kNoDeoptId = -1;
430 DeoptimizeKind kind,
bool frame)
433 deopt_info(deopt_info),
435 needs_frame(frame) {}
438 return address == other.address && deopt_kind == other.deopt_kind &&
439 needs_frame == other.needs_frame;
445 DeoptimizeKind deopt_kind;
449 static const char* MessageFor(DeoptimizeKind kind);
451 int output_count()
const {
return output_count_; }
455 DeoptimizeKind deopt_kind()
const {
return deopt_kind_; }
458 int jsframe_count()
const {
return jsframe_count_; }
460 static Deoptimizer* New(JSFunction*
function, DeoptimizeKind kind,
461 unsigned bailout_id, Address from,
int fp_to_sp_delta,
463 static Deoptimizer* Grab(Isolate* isolate);
467 static DeoptimizedFrameInfo* DebuggerInspectableFrame(JavaScriptFrame* frame,
475 static void DeoptimizeFunction(JSFunction*
function, Code code = Code());
478 static void DeoptimizeAll(Isolate* isolate);
483 static void DeoptimizeMarkedCode(Isolate* isolate);
487 void MaterializeHeapObjects();
489 static void ComputeOutputFrames(Deoptimizer* deoptimizer);
491 static Address GetDeoptimizationEntry(Isolate* isolate,
int id,
492 DeoptimizeKind kind);
493 static int GetDeoptimizationId(Isolate* isolate, Address addr,
494 DeoptimizeKind kind);
498 static bool IsDeoptimizationEntry(Isolate* isolate, Address addr,
499 DeoptimizeKind* type);
502 static int input_offset() {
return OFFSET_OF(Deoptimizer, input_); }
503 static int output_count_offset() {
504 return OFFSET_OF(Deoptimizer, output_count_);
506 static int output_offset() {
return OFFSET_OF(Deoptimizer, output_); }
508 static int caller_frame_top_offset() {
509 return OFFSET_OF(Deoptimizer, caller_frame_top_);
512 static int GetDeoptimizedCodeCount(Isolate* isolate);
514 static const int kNotDeoptimizationEntry = -1;
520 : masm_(masm), deopt_kind_(kind), count_(count) {}
526 DeoptimizeKind deopt_kind()
const {
return deopt_kind_; }
527 Isolate* isolate()
const {
return masm_->isolate(); }
529 void GeneratePrologue();
532 int count()
const {
return count_; }
535 DeoptimizeKind deopt_kind_;
539 static void EnsureCodeForDeoptimizationEntry(
Isolate* isolate,
540 DeoptimizeKind kind);
541 static void EnsureCodeForMaxDeoptimizationEntries(
Isolate* isolate);
543 Isolate* isolate()
const {
return isolate_; }
547 void QueueValueForMaterialization(Address output_address,
Object* obj,
550 static const int kMinNumberOfEntries = 64;
551 static const int kMaxNumberOfEntries = 16384;
554 unsigned bailout_id, Address from,
int fp_to_sp_delta);
555 Code FindOptimizedCode();
556 void PrintFunctionName();
557 void DeleteFrameDescriptions();
559 static bool IsInDeoptimizationTable(
Isolate* isolate, Address addr,
560 DeoptimizeKind
type);
562 void DoComputeOutputFrames();
564 int frame_index,
bool goto_catch_handler);
570 enum class BuiltinContinuationMode {
573 JAVASCRIPT_WITH_CATCH,
574 JAVASCRIPT_HANDLE_EXCEPTION
576 static bool BuiltinContinuationModeIsWithCatch(BuiltinContinuationMode mode);
577 static bool BuiltinContinuationModeIsJavaScript(BuiltinContinuationMode mode);
578 static StackFrame::Type BuiltinContinuationModeToFrameType(
579 BuiltinContinuationMode mode);
580 static Builtins::Name TrampolineForBuiltinContinuation(
581 BuiltinContinuationMode mode,
bool must_handle_result);
583 void DoComputeBuiltinContinuation(TranslatedFrame* translated_frame,
585 BuiltinContinuationMode mode);
587 unsigned ComputeInputFrameAboveFpFixedSize()
const;
588 unsigned ComputeInputFrameSize()
const;
589 static unsigned ComputeInterpretedFixedSize(SharedFunctionInfo* shared);
591 static unsigned ComputeIncomingArgumentSize(SharedFunctionInfo* shared);
592 static unsigned ComputeOutgoingArgumentSize(Code code,
unsigned bailout_id);
594 static void GenerateDeoptimizationEntries(MacroAssembler* masm,
int count,
595 DeoptimizeKind kind);
598 static void MarkAllCodeForContext(Context native_context);
601 static void DeoptimizeMarkedCodeForContext(Context native_context);
605 static bool PadTopOfStackRegister();
610 Code FindDeoptimizingCode(Address addr);
613 JSFunction* function_;
615 unsigned bailout_id_;
616 DeoptimizeKind deopt_kind_;
619 bool deoptimizing_throw_;
620 int catch_handler_data_;
621 int catch_handler_pc_offset_;
624 FrameDescription* input_;
630 FrameDescription** output_;
633 intptr_t caller_frame_top_;
636 intptr_t caller_constant_pool_;
637 intptr_t input_frame_context_;
642 TranslatedState translated_state_;
643 struct ValueToMaterialize {
644 Address output_slot_address_;
645 TranslatedFrame::iterator value_;
647 std::vector<ValueToMaterialize> values_to_materialize_;
650 DisallowHeapAllocation* disallow_heap_allocation_;
653 CodeTracer::Scope* trace_scope_;
655 static const int table_entry_size_;
657 friend class FrameDescription;
658 friend class DeoptimizedFrameInfo;
664 intptr_t GetRegister(
unsigned n)
const {
669 if (n >= arraysize(registers_)) {
674 return registers_[n];
677 Float32 GetFloatRegister(
unsigned n)
const {
678 DCHECK(n < arraysize(float_registers_));
679 return float_registers_[n];
682 Float64 GetDoubleRegister(
unsigned n)
const {
683 DCHECK(n < arraysize(double_registers_));
684 return double_registers_[n];
687 void SetRegister(
unsigned n, intptr_t value) {
688 DCHECK(n < arraysize(registers_));
689 registers_[n] = value;
692 void SetFloatRegister(
unsigned n,
Float32 value) {
693 DCHECK(n < arraysize(float_registers_));
694 float_registers_[n] = value;
697 void SetDoubleRegister(
unsigned n,
Float64 value) {
698 DCHECK(n < arraysize(double_registers_));
699 double_registers_[n] = value;
704 static_assert(
sizeof(
Float32) == kFloatSize,
"size mismatch");
705 static_assert(
sizeof(
Float64) == kDoubleSize,
"size mismatch");
707 intptr_t registers_[Register::kNumRegisters];
708 Float32 float_registers_[FloatRegister::kNumRegisters];
709 Float64 double_registers_[DoubleRegister::kNumRegisters];
717 void*
operator new(
size_t size,
uint32_t frame_size) {
720 return malloc(size + frame_size - kPointerSize);
723 void operator delete(
void* pointer,
uint32_t frame_size) {
727 void operator delete(
void* description) {
733 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_);
734 return static_cast<uint32_t>(frame_size_);
737 intptr_t GetFrameSlot(
unsigned offset) {
738 return *GetFrameSlotPointer(offset);
741 unsigned GetLastArgumentSlotOffset() {
742 int parameter_slots = parameter_count();
743 if (kPadArguments) parameter_slots = RoundUp(parameter_slots, 2);
744 return GetFrameSize() - parameter_slots * kPointerSize;
747 Address GetFramePointerAddress() {
749 GetLastArgumentSlotOffset() - StandardFrameConstants::kCallerSPOffset;
750 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset));
755 void SetFrameSlot(
unsigned offset, intptr_t value) {
756 *GetFrameSlotPointer(offset) = value;
759 void SetCallerPc(
unsigned offset, intptr_t value);
761 void SetCallerFp(
unsigned offset, intptr_t value);
763 void SetCallerConstantPool(
unsigned offset, intptr_t value);
765 intptr_t GetRegister(
unsigned n)
const {
766 return register_values_.GetRegister(n);
769 Float64 GetDoubleRegister(
unsigned n)
const {
770 return register_values_.GetDoubleRegister(n);
773 void SetRegister(
unsigned n, intptr_t value) {
774 register_values_.SetRegister(n, value);
777 void SetDoubleRegister(
unsigned n,
Float64 value) {
778 register_values_.SetDoubleRegister(n, value);
781 intptr_t GetTop()
const {
return top_; }
782 void SetTop(intptr_t top) { top_ = top; }
784 intptr_t GetPc()
const {
return pc_; }
785 void SetPc(intptr_t pc) { pc_ = pc; }
787 intptr_t GetFp()
const {
return fp_; }
788 void SetFp(intptr_t fp) { fp_ = fp; }
790 intptr_t GetContext()
const {
return context_; }
791 void SetContext(intptr_t context) { context_ = context; }
793 intptr_t GetConstantPool()
const {
return constant_pool_; }
794 void SetConstantPool(intptr_t constant_pool) {
795 constant_pool_ = constant_pool;
798 void SetContinuation(intptr_t pc) { continuation_ = pc; }
801 int parameter_count() {
return parameter_count_; }
803 static int registers_offset() {
807 static int double_registers_offset() {
811 static int float_registers_offset() {
815 static int frame_size_offset() {
821 static int continuation_offset() {
825 static int frame_content_offset() {
830 static const uint32_t kZapUint32 = 0xbeeddead;
836 int parameter_count_;
842 intptr_t constant_pool_;
846 intptr_t continuation_;
850 intptr_t frame_content_[1];
852 intptr_t* GetFrameSlotPointer(
unsigned offset) {
853 DCHECK(offset < frame_size_);
854 return reinterpret_cast<intptr_t*
>(
855 reinterpret_cast<Address>(
this) + frame_content_offset() + offset);
867 static const int kLastDeoptimizeKind =
868 static_cast<int>(DeoptimizeKind::kLastDeoptimizeKind);
869 Code deopt_entry_code_[kLastDeoptimizeKind + 1];
870 Code deopt_entry_code(DeoptimizeKind kind);
871 void set_deopt_entry_code(DeoptimizeKind kind,
Code code);
884 int CurrentIndex()
const {
return static_cast<int>(contents_.size()); }
885 void Add(int32_t value);
899 bool HasNext()
const;
902 for (
int i = 0;
i < n;
i++) Next();
910 #define TRANSLATION_OPCODE_LIST(V) \ 912 V(INTERPRETED_FRAME) \ 913 V(BUILTIN_CONTINUATION_FRAME) \ 914 V(JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME) \ 915 V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) \ 916 V(CONSTRUCT_STUB_FRAME) \ 917 V(ARGUMENTS_ADAPTOR_FRAME) \ 918 V(DUPLICATED_OBJECT) \ 919 V(ARGUMENTS_ELEMENTS) \ 920 V(ARGUMENTS_LENGTH) \ 930 V(INT32_STACK_SLOT) \ 931 V(INT64_STACK_SLOT) \ 932 V(UINT32_STACK_SLOT) \ 934 V(FLOAT_STACK_SLOT) \ 935 V(DOUBLE_STACK_SLOT) \ 941 #define DECLARE_TRANSLATION_OPCODE_ENUM(item) item, 943 TRANSLATION_OPCODE_LIST(DECLARE_TRANSLATION_OPCODE_ENUM)
946 #undef DECLARE_TRANSLATION_OPCODE_ENUM 949 int update_feedback_count,
Zone* zone)
950 : buffer_(buffer), index_(buffer->CurrentIndex()), zone_(zone) {
952 buffer_->Add(frame_count);
953 buffer_->Add(jsframe_count);
954 buffer_->Add(update_feedback_count);
957 int index()
const {
return index_; }
960 void BeginInterpretedFrame(
BailoutId bytecode_offset,
int literal_id,
961 unsigned height,
int return_value_offset,
962 int return_value_count);
963 void BeginArgumentsAdaptorFrame(
int literal_id,
unsigned height);
964 void BeginConstructStubFrame(
BailoutId bailout_id,
int literal_id,
966 void BeginBuiltinContinuationFrame(
BailoutId bailout_id,
int literal_id,
968 void BeginJavaScriptBuiltinContinuationFrame(
BailoutId bailout_id,
969 int literal_id,
unsigned height);
970 void BeginJavaScriptBuiltinContinuationWithCatchFrame(
BailoutId bailout_id,
973 void ArgumentsElements(CreateArgumentsType
type);
974 void ArgumentsLength(CreateArgumentsType
type);
975 void BeginCapturedObject(
int length);
976 void AddUpdateFeedback(
int vector_literal,
int slot);
977 void DuplicateObject(
int object_index);
979 void StoreInt32Register(
Register reg);
980 void StoreInt64Register(
Register reg);
981 void StoreUint32Register(
Register reg);
982 void StoreBoolRegister(
Register reg);
985 void StoreStackSlot(
int index);
986 void StoreInt32StackSlot(
int index);
987 void StoreInt64StackSlot(
int index);
988 void StoreUint32StackSlot(
int index);
989 void StoreBoolStackSlot(
int index);
990 void StoreFloatStackSlot(
int index);
991 void StoreDoubleStackSlot(
int index);
992 void StoreLiteral(
int literal_id);
993 void StoreJSFrameFunction();
995 Zone* zone()
const {
return zone_; }
997 static int NumberOfOperandsFor(Opcode opcode);
999 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 1000 static const char* StringFor(Opcode opcode);
1020 Isolate* isolate()
const {
return isolate_; }
1024 int StackIdToIndex(
Address fp);
1027 std::vector<Address> frame_fps_;
1040 TranslatedState::iterator frame_it,
Isolate* isolate);
1043 int parameters_count() {
return static_cast<int>(parameters_.size()); }
1046 int expression_count() {
return static_cast<int>(expression_stack_.size()); }
1056 DCHECK(0 <= index && index < parameters_count());
1057 return parameters_[index];
1062 DCHECK(0 <= index && index < expression_count());
1063 return expression_stack_[index];
1066 int GetSourcePosition() {
1067 return source_position_;
1073 DCHECK(0 <= index && index < parameters_count());
1074 parameters_[index] = obj;
1079 DCHECK(0 <= index && index < expression_count());
1080 expression_stack_[index] = obj;
1085 std::vector<Handle<Object> > parameters_;
1086 std::vector<Handle<Object> > expression_stack_;
1087 int source_position_;
1095 #endif // V8_DEOPTIMIZER_H_