OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_DEOPTIMIZER_H_ | 5 #ifndef V8_DEOPTIMIZER_H_ |
6 #define V8_DEOPTIMIZER_H_ | 6 #define V8_DEOPTIMIZER_H_ |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/allocation.h" | 10 #include "src/allocation.h" |
11 #include "src/macro-assembler.h" | 11 #include "src/macro-assembler.h" |
12 | 12 |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
| 17 |
| 18 static inline double read_double_value(Address p) { |
| 19 double d; |
| 20 memcpy(&d, p, sizeof(d)); |
| 21 return d; |
| 22 } |
| 23 |
| 24 |
17 class FrameDescription; | 25 class FrameDescription; |
18 class TranslationIterator; | 26 class TranslationIterator; |
19 class DeoptimizedFrameInfo; | 27 class DeoptimizedFrameInfo; |
20 class TranslatedState; | |
21 class RegisterValues; | |
22 | |
23 class TranslatedValue BASE_EMBEDDED { | |
24 public: | |
25 // Allocation-less getter of the value. | |
26 // Returns heap()->arguments_marker() if allocation would be | |
27 // necessary to get the value. | |
28 Object* GetRawValue() const; | |
29 Handle<Object> GetValue(); | |
30 | |
31 bool IsMaterializedObject() const; | |
32 | |
33 private: | |
34 friend class TranslatedState; | |
35 friend class TranslatedFrame; | |
36 | |
37 enum Kind { | |
38 kInvalid, | |
39 kTagged, | |
40 kInt32, | |
41 kUInt32, | |
42 kBoolBit, | |
43 kDouble, | |
44 kCapturedObject, // Object captured by the escape analysis. | |
45 // The number of nested objects can be obtained | |
46 // with the DeferredObjectLength() method | |
47 // (the values of the nested objects follow | |
48 // this value in the depth-first order.) | |
49 kDuplicatedObject, // Duplicated object of a deferred object. | |
50 kArgumentsObject // Arguments object - only used to keep indexing | |
51 // in sync, it should not be materialized. | |
52 }; | |
53 | |
54 TranslatedValue(TranslatedState* container, Kind kind) | |
55 : kind_(kind), container_(container) {} | |
56 Kind kind() const { return kind_; } | |
57 void Handlify(); | |
58 int GetChildrenCount() const; | |
59 | |
60 static TranslatedValue NewArgumentsObject(TranslatedState* container, | |
61 int length, int object_index); | |
62 static TranslatedValue NewDeferredObject(TranslatedState* container, | |
63 int length, int object_index); | |
64 static TranslatedValue NewDuplicateObject(TranslatedState* container, int id); | |
65 static TranslatedValue NewDouble(TranslatedState* container, double value); | |
66 static TranslatedValue NewInt32(TranslatedState* container, int32_t value); | |
67 static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value); | |
68 static TranslatedValue NewBool(TranslatedState* container, uint32_t value); | |
69 static TranslatedValue NewTagged(TranslatedState* container, Object* literal); | |
70 static TranslatedValue NewInvalid(); | |
71 | |
72 Isolate* isolate() const; | |
73 void MaterializeSimple(); | |
74 | |
75 Kind kind_; | |
76 TranslatedState* container_; // This is only needed for materialization of | |
77 // objects and constructing handles (to get | |
78 // to the isolate). | |
79 | |
80 MaybeHandle<Object> value_; // Before handlification, this is always null, | |
81 // after materialization it is never null, | |
82 // in between it is only null if the value needs | |
83 // to be materialized. | |
84 | |
85 struct MaterializedObjectInfo { | |
86 int id_; | |
87 int length_; // Applies only to kArgumentsObject or kCapturedObject kinds. | |
88 }; | |
89 | |
90 union { | |
91 // kind kTagged. After handlification it is always nullptr. | |
92 Object* raw_literal_; | |
93 // kind is kUInt32 or kBoolBit. | |
94 uint32_t uint32_value_; | |
95 // kind is kInt32. | |
96 int32_t int32_value_; | |
97 // kind is kDouble | |
98 double double_value_; | |
99 // kind is kDuplicatedObject or kArgumentsObject or kCapturedObject. | |
100 MaterializedObjectInfo materialization_info_; | |
101 }; | |
102 | |
103 // Checked accessors for the union members. | |
104 Object* raw_literal() const; | |
105 int32_t int32_value() const; | |
106 uint32_t uint32_value() const; | |
107 double double_value() const; | |
108 int object_length() const; | |
109 int object_index() const; | |
110 }; | |
111 | |
112 | |
113 class TranslatedFrame { | |
114 public: | |
115 enum Kind { | |
116 kFunction, | |
117 kGetter, | |
118 kSetter, | |
119 kArgumentsAdaptor, | |
120 kConstructStub, | |
121 kCompiledStub, | |
122 kInvalid | |
123 }; | |
124 | |
125 int GetValueCount(); | |
126 | |
127 Kind kind() const { return kind_; } | |
128 BailoutId node_id() { return node_id_; } | |
129 JSFunction* raw_function() { return raw_function_; } | |
130 Handle<JSFunction> function() { return function_; } | |
131 int height() { return height_; } | |
132 | |
133 class iterator { | |
134 public: | |
135 iterator& operator++() { | |
136 AdvanceIterator(&position_); | |
137 return *this; | |
138 } | |
139 | |
140 iterator operator++(int) { | |
141 iterator original(position_); | |
142 AdvanceIterator(&position_); | |
143 return original; | |
144 } | |
145 | |
146 bool operator==(const iterator& other) const { | |
147 return position_ == other.position_; | |
148 } | |
149 bool operator!=(const iterator& other) const { return !(*this == other); } | |
150 | |
151 TranslatedValue& operator*() { return (*position_); } | |
152 TranslatedValue* operator->() { return &(*position_); } | |
153 | |
154 private: | |
155 friend TranslatedFrame; | |
156 | |
157 explicit iterator(std::deque<TranslatedValue>::iterator position) | |
158 : position_(position) {} | |
159 | |
160 std::deque<TranslatedValue>::iterator position_; | |
161 }; | |
162 | |
163 iterator begin() { return iterator(values_.begin()); } | |
164 iterator end() { return iterator(values_.end()); } | |
165 | |
166 private: | |
167 friend class TranslatedState; | |
168 | |
169 // Constructor static methods. | |
170 static TranslatedFrame JSFrame(BailoutId node_id, JSFunction* function, | |
171 int height); | |
172 static TranslatedFrame AccessorFrame(Kind kind, JSFunction* function); | |
173 static TranslatedFrame ArgumentsAdaptorFrame(JSFunction* function, | |
174 int height); | |
175 static TranslatedFrame ConstructStubFrame(JSFunction* function, int height); | |
176 static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) { | |
177 return TranslatedFrame(kCompiledStub, isolate, nullptr, height); | |
178 } | |
179 static TranslatedFrame InvalidFrame() { | |
180 return TranslatedFrame(kInvalid, nullptr); | |
181 } | |
182 | |
183 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter); | |
184 | |
185 TranslatedFrame(Kind kind, Isolate* isolate, JSFunction* function = nullptr, | |
186 int height = 0) | |
187 : kind_(kind), | |
188 node_id_(BailoutId::None()), | |
189 raw_function_(function), | |
190 height_(height), | |
191 isolate_(isolate) {} | |
192 | |
193 | |
194 void Add(const TranslatedValue& value) { values_.push_back(value); } | |
195 void Handlify(Isolate* isolate); | |
196 | |
197 Kind kind_; | |
198 BailoutId node_id_; | |
199 JSFunction* raw_function_; | |
200 Handle<JSFunction> function_; | |
201 int height_; | |
202 Isolate* isolate_; | |
203 | |
204 typedef std::deque<TranslatedValue> ValuesContainer; | |
205 | |
206 ValuesContainer values_; | |
207 }; | |
208 | |
209 | |
210 // Auxiliary class for translating deoptimization values. | |
211 // Typical usage sequence: | |
212 // | |
213 // 1. Construct the instance. This will involve reading out the translations | |
214 // and resolving them to values using the supplied frame pointer and | |
215 // machine state (registers). This phase is guaranteed not to allocate | |
216 // and not to use any HandleScope. Any object pointers will be stored raw. | |
217 // | |
218 // 2. Handlify pointers. This will convert all the raw pointers to handles. | |
219 // | |
220 // 3. Reading out the frame values. | |
221 // | |
222 // Note: After the instance is constructed, it is possible to iterate over | |
223 // the values eagerly. | |
224 | |
225 class TranslatedState { | |
226 public: | |
227 TranslatedState(); | |
228 explicit TranslatedState(JavaScriptFrame* frame); | |
229 | |
230 void Prepare(bool has_adapted_arguments, Address stack_frame_pointer); | |
231 | |
232 // Store newly materialized values into the isolate. | |
233 void StoreMaterializedValuesAndDeopt(); | |
234 | |
235 std::vector<TranslatedFrame>& frames() { return frames_; } | |
236 | |
237 TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index, | |
238 int* arguments_count); | |
239 | |
240 Isolate* isolate() { return isolate_; } | |
241 | |
242 void Init(Address input_frame_pointer, JSFunction* input_frame_function, | |
243 TranslationIterator* iterator, FixedArray* literal_array, | |
244 RegisterValues* registers, FILE* trace_file); | |
245 | |
246 private: | |
247 friend TranslatedValue; | |
248 | |
249 TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator, | |
250 FixedArray* literal_array, | |
251 Address fp, | |
252 JSFunction* frame_function, | |
253 FILE* trace_file); | |
254 TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index, | |
255 TranslationIterator* iterator, | |
256 FixedArray* literal_array, | |
257 Address fp, | |
258 RegisterValues* registers, | |
259 FILE* trace_file); | |
260 | |
261 void UpdateFromPreviouslyMaterializedObjects(); | |
262 Handle<Object> MaterializeAt(int frame_index, int* value_index); | |
263 Handle<Object> MaterializeObjectAt(int object_index); | |
264 bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index); | |
265 | |
266 static int SlotOffsetFp(int slot_index); | |
267 static Address SlotAddress(Address fp, int slot_index); | |
268 static uint32_t GetUInt32Slot(Address fp, int slot_index); | |
269 | |
270 std::vector<TranslatedFrame> frames_; | |
271 Isolate* isolate_; | |
272 Address stack_frame_pointer_; | |
273 bool has_adapted_arguments_; | |
274 | |
275 struct ObjectPosition { | |
276 int frame_index_; | |
277 int value_index_; | |
278 }; | |
279 std::deque<ObjectPosition> object_positions_; | |
280 }; | |
281 | 28 |
282 template<typename T> | 29 template<typename T> |
283 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { | 30 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { |
284 public: | 31 public: |
285 HeapNumberMaterializationDescriptor(T destination, double value) | 32 HeapNumberMaterializationDescriptor(T destination, double value) |
286 : destination_(destination), value_(value) { } | 33 : destination_(destination), value_(value) { } |
287 | 34 |
288 T destination() const { return destination_; } | 35 T destination() const { return destination_; } |
289 double value() const { return value_; } | 36 double value() const { return value_; } |
290 | 37 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 Isolate* isolate, OptimizedFunctionVisitor* visitor); | 273 Isolate* isolate, OptimizedFunctionVisitor* visitor); |
527 | 274 |
528 // The size in bytes of the code required at a lazy deopt patch site. | 275 // The size in bytes of the code required at a lazy deopt patch site. |
529 static int patch_size(); | 276 static int patch_size(); |
530 | 277 |
531 ~Deoptimizer(); | 278 ~Deoptimizer(); |
532 | 279 |
533 void MaterializeHeapObjects(JavaScriptFrameIterator* it); | 280 void MaterializeHeapObjects(JavaScriptFrameIterator* it); |
534 | 281 |
535 void MaterializeHeapNumbersForDebuggerInspectableFrame( | 282 void MaterializeHeapNumbersForDebuggerInspectableFrame( |
536 int frame_index, int parameter_count, int expression_count, | 283 Address parameters_top, |
| 284 uint32_t parameters_size, |
| 285 Address expressions_top, |
| 286 uint32_t expressions_size, |
537 DeoptimizedFrameInfo* info); | 287 DeoptimizedFrameInfo* info); |
538 | 288 |
539 static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 289 static void ComputeOutputFrames(Deoptimizer* deoptimizer); |
540 | 290 |
541 | 291 |
542 enum GetEntryMode { | 292 enum GetEntryMode { |
543 CALCULATE_ENTRY_ADDRESS, | 293 CALCULATE_ENTRY_ADDRESS, |
544 ENSURE_ENTRY_CODE | 294 ENSURE_ENTRY_CODE |
545 }; | 295 }; |
546 | 296 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 375 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
626 int frame_index); | 376 int frame_index); |
627 void DoComputeConstructStubFrame(TranslationIterator* iterator, | 377 void DoComputeConstructStubFrame(TranslationIterator* iterator, |
628 int frame_index); | 378 int frame_index); |
629 void DoComputeAccessorStubFrame(TranslationIterator* iterator, | 379 void DoComputeAccessorStubFrame(TranslationIterator* iterator, |
630 int frame_index, | 380 int frame_index, |
631 bool is_setter_stub_frame); | 381 bool is_setter_stub_frame); |
632 void DoComputeCompiledStubFrame(TranslationIterator* iterator, | 382 void DoComputeCompiledStubFrame(TranslationIterator* iterator, |
633 int frame_index); | 383 int frame_index); |
634 | 384 |
635 void WriteValueToOutput(TranslatedFrame::iterator* iterator, int* input_index, | 385 // Translate object, store the result into an auxiliary array |
636 int frame_index, unsigned output_offset, | 386 // (deferred_objects_tagged_values_). |
637 Address output_address_for_materialization = nullptr); | 387 void DoTranslateObject(TranslationIterator* iterator, |
| 388 int object_index, |
| 389 int field_index); |
| 390 |
| 391 // Translate value, store the result into the given frame slot. |
| 392 void DoTranslateCommand(TranslationIterator* iterator, |
| 393 int frame_index, |
| 394 unsigned output_offset); |
| 395 |
| 396 // Translate object, do not store the result anywhere (but do update |
| 397 // the deferred materialization array). |
| 398 void DoTranslateObjectAndSkip(TranslationIterator* iterator); |
638 | 399 |
639 unsigned ComputeInputFrameSize() const; | 400 unsigned ComputeInputFrameSize() const; |
640 unsigned ComputeFixedSize(JSFunction* function) const; | 401 unsigned ComputeFixedSize(JSFunction* function) const; |
641 | 402 |
642 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; | 403 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; |
643 unsigned ComputeOutgoingArgumentSize() const; | 404 unsigned ComputeOutgoingArgumentSize() const; |
644 | 405 |
645 Object* ComputeLiteral(int index) const; | 406 Object* ComputeLiteral(int index) const; |
646 | 407 |
| 408 void AddObjectStart(intptr_t slot_address, int argc, bool is_arguments); |
| 409 void AddObjectDuplication(intptr_t slot, int object_index); |
| 410 void AddObjectTaggedValue(intptr_t value); |
| 411 void AddObjectDoubleValue(double value); |
| 412 void AddDoubleValue(intptr_t slot_address, double value); |
| 413 |
| 414 bool ArgumentsObjectIsAdapted(int object_index) { |
| 415 ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index); |
| 416 int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1; |
| 417 return jsframe_has_adapted_arguments_[reverse_jsframe_index]; |
| 418 } |
| 419 |
| 420 Handle<JSFunction> ArgumentsObjectFunction(int object_index) { |
| 421 ObjectMaterializationDescriptor desc = deferred_objects_.at(object_index); |
| 422 int reverse_jsframe_index = jsframe_count_ - desc.jsframe_index() - 1; |
| 423 return jsframe_functions_[reverse_jsframe_index]; |
| 424 } |
| 425 |
| 426 // Helper function for heap object materialization. |
| 427 Handle<Object> MaterializeNextHeapObject(); |
| 428 Handle<Object> MaterializeNextValue(); |
| 429 |
647 static void GenerateDeoptimizationEntries( | 430 static void GenerateDeoptimizationEntries( |
648 MacroAssembler* masm, int count, BailoutType type); | 431 MacroAssembler* masm, int count, BailoutType type); |
649 | 432 |
650 // Marks all the code in the given context for deoptimization. | 433 // Marks all the code in the given context for deoptimization. |
651 static void MarkAllCodeForContext(Context* native_context); | 434 static void MarkAllCodeForContext(Context* native_context); |
652 | 435 |
653 // Visit all the known optimized functions in a given context. | 436 // Visit all the known optimized functions in a given context. |
654 static void VisitAllOptimizedFunctionsForContext( | 437 static void VisitAllOptimizedFunctionsForContext( |
655 Context* context, OptimizedFunctionVisitor* visitor); | 438 Context* context, OptimizedFunctionVisitor* visitor); |
656 | 439 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 | 477 |
695 // Input frame description. | 478 // Input frame description. |
696 FrameDescription* input_; | 479 FrameDescription* input_; |
697 // Number of output frames. | 480 // Number of output frames. |
698 int output_count_; | 481 int output_count_; |
699 // Number of output js frames. | 482 // Number of output js frames. |
700 int jsframe_count_; | 483 int jsframe_count_; |
701 // Array of output frame descriptions. | 484 // Array of output frame descriptions. |
702 FrameDescription** output_; | 485 FrameDescription** output_; |
703 | 486 |
| 487 // Deferred values to be materialized. |
| 488 List<Object*> deferred_objects_tagged_values_; |
| 489 List<HeapNumberMaterializationDescriptor<int> > |
| 490 deferred_objects_double_values_; |
| 491 List<ObjectMaterializationDescriptor> deferred_objects_; |
| 492 List<HeapNumberMaterializationDescriptor<Address> > deferred_heap_numbers_; |
| 493 |
704 // Key for lookup of previously materialized objects | 494 // Key for lookup of previously materialized objects |
705 Address stack_fp_; | 495 Address stack_fp_; |
| 496 Handle<FixedArray> previously_materialized_objects_; |
| 497 int prev_materialized_count_; |
706 | 498 |
707 TranslatedState translated_state_; | 499 // Output frame information. Only used during heap object materialization. |
708 struct ValueToMaterialize { | 500 List<Handle<JSFunction> > jsframe_functions_; |
709 Address output_slot_address_; | 501 List<bool> jsframe_has_adapted_arguments_; |
710 TranslatedFrame::iterator value_; | 502 |
711 }; | 503 // Materialized objects. Only used during heap object materialization. |
712 std::vector<ValueToMaterialize> values_to_materialize_; | 504 List<Handle<Object> >* materialized_values_; |
| 505 List<Handle<Object> >* materialized_objects_; |
| 506 int materialization_value_index_; |
| 507 int materialization_object_index_; |
713 | 508 |
714 #ifdef DEBUG | 509 #ifdef DEBUG |
715 DisallowHeapAllocation* disallow_heap_allocation_; | 510 DisallowHeapAllocation* disallow_heap_allocation_; |
716 #endif // DEBUG | 511 #endif // DEBUG |
717 | 512 |
718 CodeTracer::Scope* trace_scope_; | 513 CodeTracer::Scope* trace_scope_; |
719 | 514 |
720 static const int table_entry_size_; | 515 static const int table_entry_size_; |
721 | 516 |
722 friend class FrameDescription; | 517 friend class FrameDescription; |
723 friend class DeoptimizedFrameInfo; | 518 friend class DeoptimizedFrameInfo; |
724 }; | 519 }; |
725 | 520 |
726 | 521 |
727 class RegisterValues { | 522 class FrameDescription { |
728 public: | 523 public: |
| 524 FrameDescription(uint32_t frame_size, |
| 525 JSFunction* function); |
| 526 |
| 527 void* operator new(size_t size, uint32_t frame_size) { |
| 528 // Subtracts kPointerSize, as the member frame_content_ already supplies |
| 529 // the first element of the area to store the frame. |
| 530 return malloc(size + frame_size - kPointerSize); |
| 531 } |
| 532 |
| 533 // Bug in VS2015 RC, reported fixed in RTM. Microsoft bug: 1153909. |
| 534 #if !defined(_MSC_FULL_VER) || _MSC_FULL_VER != 190022816 |
| 535 void operator delete(void* pointer, uint32_t frame_size) { |
| 536 free(pointer); |
| 537 } |
| 538 #endif // _MSC_FULL_VER |
| 539 |
| 540 void operator delete(void* description) { |
| 541 free(description); |
| 542 } |
| 543 |
| 544 uint32_t GetFrameSize() const { |
| 545 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_); |
| 546 return static_cast<uint32_t>(frame_size_); |
| 547 } |
| 548 |
| 549 JSFunction* GetFunction() const { return function_; } |
| 550 |
| 551 unsigned GetOffsetFromSlotIndex(int slot_index); |
| 552 |
| 553 intptr_t GetFrameSlot(unsigned offset) { |
| 554 return *GetFrameSlotPointer(offset); |
| 555 } |
| 556 |
| 557 double GetDoubleFrameSlot(unsigned offset) { |
| 558 intptr_t* ptr = GetFrameSlotPointer(offset); |
| 559 return read_double_value(reinterpret_cast<Address>(ptr)); |
| 560 } |
| 561 |
| 562 void SetFrameSlot(unsigned offset, intptr_t value) { |
| 563 *GetFrameSlotPointer(offset) = value; |
| 564 } |
| 565 |
| 566 void SetCallerPc(unsigned offset, intptr_t value); |
| 567 |
| 568 void SetCallerFp(unsigned offset, intptr_t value); |
| 569 |
| 570 void SetCallerConstantPool(unsigned offset, intptr_t value); |
| 571 |
729 intptr_t GetRegister(unsigned n) const { | 572 intptr_t GetRegister(unsigned n) const { |
730 #if DEBUG | 573 #if DEBUG |
731 // This convoluted DCHECK is needed to work around a gcc problem that | 574 // This convoluted DCHECK is needed to work around a gcc problem that |
732 // improperly detects an array bounds overflow in optimized debug builds | 575 // improperly detects an array bounds overflow in optimized debug builds |
733 // when using a plain DCHECK. | 576 // when using a plain DCHECK. |
734 if (n >= arraysize(registers_)) { | 577 if (n >= arraysize(registers_)) { |
735 DCHECK(false); | 578 DCHECK(false); |
736 return 0; | 579 return 0; |
737 } | 580 } |
738 #endif | 581 #endif |
739 return registers_[n]; | 582 return registers_[n]; |
740 } | 583 } |
741 | 584 |
742 double GetDoubleRegister(unsigned n) const { | 585 double GetDoubleRegister(unsigned n) const { |
743 DCHECK(n < arraysize(double_registers_)); | 586 DCHECK(n < arraysize(double_registers_)); |
744 return double_registers_[n]; | 587 return double_registers_[n]; |
745 } | 588 } |
746 | 589 |
747 void SetRegister(unsigned n, intptr_t value) { | 590 void SetRegister(unsigned n, intptr_t value) { |
748 DCHECK(n < arraysize(registers_)); | 591 DCHECK(n < arraysize(registers_)); |
749 registers_[n] = value; | 592 registers_[n] = value; |
750 } | 593 } |
751 | 594 |
752 void SetDoubleRegister(unsigned n, double value) { | 595 void SetDoubleRegister(unsigned n, double value) { |
753 DCHECK(n < arraysize(double_registers_)); | 596 DCHECK(n < arraysize(double_registers_)); |
754 double_registers_[n] = value; | 597 double_registers_[n] = value; |
755 } | 598 } |
756 | 599 |
757 intptr_t registers_[Register::kNumRegisters]; | |
758 double double_registers_[DoubleRegister::kMaxNumRegisters]; | |
759 }; | |
760 | |
761 | |
762 class FrameDescription { | |
763 public: | |
764 FrameDescription(uint32_t frame_size, | |
765 JSFunction* function); | |
766 | |
767 void* operator new(size_t size, uint32_t frame_size) { | |
768 // Subtracts kPointerSize, as the member frame_content_ already supplies | |
769 // the first element of the area to store the frame. | |
770 return malloc(size + frame_size - kPointerSize); | |
771 } | |
772 | |
773 // Bug in VS2015 RC, reported fixed in RTM. Microsoft bug: 1153909. | |
774 #if !defined(_MSC_FULL_VER) || _MSC_FULL_VER != 190022816 | |
775 void operator delete(void* pointer, uint32_t frame_size) { | |
776 free(pointer); | |
777 } | |
778 #endif // _MSC_FULL_VER | |
779 | |
780 void operator delete(void* description) { | |
781 free(description); | |
782 } | |
783 | |
784 uint32_t GetFrameSize() const { | |
785 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_); | |
786 return static_cast<uint32_t>(frame_size_); | |
787 } | |
788 | |
789 JSFunction* GetFunction() const { return function_; } | |
790 | |
791 unsigned GetOffsetFromSlotIndex(int slot_index); | |
792 | |
793 intptr_t GetFrameSlot(unsigned offset) { | |
794 return *GetFrameSlotPointer(offset); | |
795 } | |
796 | |
797 Address GetFramePointerAddress() { | |
798 int fp_offset = GetFrameSize() - | |
799 (ComputeParametersCount() + 1) * kPointerSize - | |
800 StandardFrameConstants::kCallerSPOffset; | |
801 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset)); | |
802 } | |
803 | |
804 RegisterValues* GetRegisterValues() { return ®ister_values_; } | |
805 | |
806 void SetFrameSlot(unsigned offset, intptr_t value) { | |
807 *GetFrameSlotPointer(offset) = value; | |
808 } | |
809 | |
810 void SetCallerPc(unsigned offset, intptr_t value); | |
811 | |
812 void SetCallerFp(unsigned offset, intptr_t value); | |
813 | |
814 void SetCallerConstantPool(unsigned offset, intptr_t value); | |
815 | |
816 intptr_t GetRegister(unsigned n) const { | |
817 return register_values_.GetRegister(n); | |
818 } | |
819 | |
820 double GetDoubleRegister(unsigned n) const { | |
821 return register_values_.GetDoubleRegister(n); | |
822 } | |
823 | |
824 void SetRegister(unsigned n, intptr_t value) { | |
825 register_values_.SetRegister(n, value); | |
826 } | |
827 | |
828 void SetDoubleRegister(unsigned n, double value) { | |
829 register_values_.SetDoubleRegister(n, value); | |
830 } | |
831 | |
832 intptr_t GetTop() const { return top_; } | 600 intptr_t GetTop() const { return top_; } |
833 void SetTop(intptr_t top) { top_ = top; } | 601 void SetTop(intptr_t top) { top_ = top; } |
834 | 602 |
835 intptr_t GetPc() const { return pc_; } | 603 intptr_t GetPc() const { return pc_; } |
836 void SetPc(intptr_t pc) { pc_ = pc; } | 604 void SetPc(intptr_t pc) { pc_ = pc; } |
837 | 605 |
838 intptr_t GetFp() const { return fp_; } | 606 intptr_t GetFp() const { return fp_; } |
839 void SetFp(intptr_t fp) { fp_ = fp; } | 607 void SetFp(intptr_t fp) { fp_ = fp; } |
840 | 608 |
841 intptr_t GetContext() const { return context_; } | 609 intptr_t GetContext() const { return context_; } |
(...skipping 18 matching lines...) Expand all Loading... |
860 // Get a parameter value for an unoptimized frame. | 628 // Get a parameter value for an unoptimized frame. |
861 Object* GetParameter(int index); | 629 Object* GetParameter(int index); |
862 | 630 |
863 // Get the expression stack height for a unoptimized frame. | 631 // Get the expression stack height for a unoptimized frame. |
864 unsigned GetExpressionCount(); | 632 unsigned GetExpressionCount(); |
865 | 633 |
866 // Get the expression stack value for an unoptimized frame. | 634 // Get the expression stack value for an unoptimized frame. |
867 Object* GetExpression(int index); | 635 Object* GetExpression(int index); |
868 | 636 |
869 static int registers_offset() { | 637 static int registers_offset() { |
870 return OFFSET_OF(FrameDescription, register_values_.registers_); | 638 return OFFSET_OF(FrameDescription, registers_); |
871 } | 639 } |
872 | 640 |
873 static int double_registers_offset() { | 641 static int double_registers_offset() { |
874 return OFFSET_OF(FrameDescription, register_values_.double_registers_); | 642 return OFFSET_OF(FrameDescription, double_registers_); |
875 } | 643 } |
876 | 644 |
877 static int frame_size_offset() { | 645 static int frame_size_offset() { |
878 return OFFSET_OF(FrameDescription, frame_size_); | 646 return OFFSET_OF(FrameDescription, frame_size_); |
879 } | 647 } |
880 | 648 |
881 static int pc_offset() { | 649 static int pc_offset() { |
882 return OFFSET_OF(FrameDescription, pc_); | 650 return OFFSET_OF(FrameDescription, pc_); |
883 } | 651 } |
884 | 652 |
(...skipping 10 matching lines...) Expand all Loading... |
895 } | 663 } |
896 | 664 |
897 private: | 665 private: |
898 static const uint32_t kZapUint32 = 0xbeeddead; | 666 static const uint32_t kZapUint32 = 0xbeeddead; |
899 | 667 |
900 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to | 668 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to |
901 // keep the variable-size array frame_content_ of type intptr_t at | 669 // keep the variable-size array frame_content_ of type intptr_t at |
902 // the end of the structure aligned. | 670 // the end of the structure aligned. |
903 uintptr_t frame_size_; // Number of bytes. | 671 uintptr_t frame_size_; // Number of bytes. |
904 JSFunction* function_; | 672 JSFunction* function_; |
905 RegisterValues register_values_; | 673 intptr_t registers_[Register::kNumRegisters]; |
| 674 double double_registers_[DoubleRegister::kMaxNumRegisters]; |
906 intptr_t top_; | 675 intptr_t top_; |
907 intptr_t pc_; | 676 intptr_t pc_; |
908 intptr_t fp_; | 677 intptr_t fp_; |
909 intptr_t context_; | 678 intptr_t context_; |
910 intptr_t constant_pool_; | 679 intptr_t constant_pool_; |
911 StackFrame::Type type_; | 680 StackFrame::Type type_; |
912 Smi* state_; | 681 Smi* state_; |
913 | 682 |
914 // Continuation is the PC where the execution continues after | 683 // Continuation is the PC where the execution continues after |
915 // deoptimizing. | 684 // deoptimizing. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1026 zone_(zone) { | 795 zone_(zone) { |
1027 buffer_->Add(BEGIN, zone); | 796 buffer_->Add(BEGIN, zone); |
1028 buffer_->Add(frame_count, zone); | 797 buffer_->Add(frame_count, zone); |
1029 buffer_->Add(jsframe_count, zone); | 798 buffer_->Add(jsframe_count, zone); |
1030 } | 799 } |
1031 | 800 |
1032 int index() const { return index_; } | 801 int index() const { return index_; } |
1033 | 802 |
1034 // Commands. | 803 // Commands. |
1035 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); | 804 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); |
1036 void BeginCompiledStubFrame(int height); | 805 void BeginCompiledStubFrame(); |
1037 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); | 806 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); |
1038 void BeginConstructStubFrame(int literal_id, unsigned height); | 807 void BeginConstructStubFrame(int literal_id, unsigned height); |
1039 void BeginGetterStubFrame(int literal_id); | 808 void BeginGetterStubFrame(int literal_id); |
1040 void BeginSetterStubFrame(int literal_id); | 809 void BeginSetterStubFrame(int literal_id); |
1041 void BeginArgumentsObject(int args_length); | 810 void BeginArgumentsObject(int args_length); |
1042 void BeginCapturedObject(int length); | 811 void BeginCapturedObject(int length); |
1043 void DuplicateObject(int object_index); | 812 void DuplicateObject(int object_index); |
1044 void StoreRegister(Register reg); | 813 void StoreRegister(Register reg); |
1045 void StoreInt32Register(Register reg); | 814 void StoreInt32Register(Register reg); |
1046 void StoreUint32Register(Register reg); | 815 void StoreUint32Register(Register reg); |
(...skipping 18 matching lines...) Expand all Loading... |
1065 // A literal id which refers to the JSFunction itself. | 834 // A literal id which refers to the JSFunction itself. |
1066 static const int kSelfLiteralId = -239; | 835 static const int kSelfLiteralId = -239; |
1067 | 836 |
1068 private: | 837 private: |
1069 TranslationBuffer* buffer_; | 838 TranslationBuffer* buffer_; |
1070 int index_; | 839 int index_; |
1071 Zone* zone_; | 840 Zone* zone_; |
1072 }; | 841 }; |
1073 | 842 |
1074 | 843 |
| 844 class SlotRef BASE_EMBEDDED { |
| 845 public: |
| 846 enum SlotRepresentation { |
| 847 UNKNOWN, |
| 848 TAGGED, |
| 849 INT32, |
| 850 UINT32, |
| 851 BOOLBIT, |
| 852 DOUBLE, |
| 853 LITERAL, |
| 854 DEFERRED_OBJECT, // Object captured by the escape analysis. |
| 855 // The number of nested objects can be obtained |
| 856 // with the DeferredObjectLength() method |
| 857 // (the SlotRefs of the nested objects follow |
| 858 // this SlotRef in the depth-first order.) |
| 859 DUPLICATE_OBJECT, // Duplicated object of a deferred object. |
| 860 ARGUMENTS_OBJECT // Arguments object - only used to keep indexing |
| 861 // in sync, it should not be materialized. |
| 862 }; |
| 863 |
| 864 SlotRef() |
| 865 : addr_(NULL), representation_(UNKNOWN) { } |
| 866 |
| 867 SlotRef(Address addr, SlotRepresentation representation) |
| 868 : addr_(addr), representation_(representation) { } |
| 869 |
| 870 SlotRef(Isolate* isolate, Object* literal) |
| 871 : literal_(literal, isolate), representation_(LITERAL) { } |
| 872 |
| 873 static SlotRef NewArgumentsObject(int length) { |
| 874 SlotRef slot; |
| 875 slot.representation_ = ARGUMENTS_OBJECT; |
| 876 slot.deferred_object_length_ = length; |
| 877 return slot; |
| 878 } |
| 879 |
| 880 static SlotRef NewDeferredObject(int length) { |
| 881 SlotRef slot; |
| 882 slot.representation_ = DEFERRED_OBJECT; |
| 883 slot.deferred_object_length_ = length; |
| 884 return slot; |
| 885 } |
| 886 |
| 887 SlotRepresentation Representation() { return representation_; } |
| 888 |
| 889 static SlotRef NewDuplicateObject(int id) { |
| 890 SlotRef slot; |
| 891 slot.representation_ = DUPLICATE_OBJECT; |
| 892 slot.duplicate_object_id_ = id; |
| 893 return slot; |
| 894 } |
| 895 |
| 896 int GetChildrenCount() { |
| 897 if (representation_ == DEFERRED_OBJECT || |
| 898 representation_ == ARGUMENTS_OBJECT) { |
| 899 return deferred_object_length_; |
| 900 } else { |
| 901 return 0; |
| 902 } |
| 903 } |
| 904 |
| 905 int DuplicateObjectId() { return duplicate_object_id_; } |
| 906 |
| 907 Handle<Object> GetValue(Isolate* isolate); |
| 908 |
| 909 private: |
| 910 Address addr_; |
| 911 Handle<Object> literal_; |
| 912 SlotRepresentation representation_; |
| 913 int deferred_object_length_; |
| 914 int duplicate_object_id_; |
| 915 }; |
| 916 |
| 917 class SlotRefValueBuilder BASE_EMBEDDED { |
| 918 public: |
| 919 SlotRefValueBuilder( |
| 920 JavaScriptFrame* frame, |
| 921 int inlined_frame_index, |
| 922 int formal_parameter_count); |
| 923 |
| 924 void Prepare(Isolate* isolate); |
| 925 Handle<Object> GetNext(Isolate* isolate, int level); |
| 926 void Finish(Isolate* isolate); |
| 927 |
| 928 int args_length() { return args_length_; } |
| 929 |
| 930 private: |
| 931 List<Handle<Object> > materialized_objects_; |
| 932 Handle<FixedArray> previously_materialized_objects_; |
| 933 int prev_materialized_count_; |
| 934 Address stack_frame_id_; |
| 935 List<SlotRef> slot_refs_; |
| 936 int current_slot_; |
| 937 int args_length_; |
| 938 int first_slot_index_; |
| 939 bool should_deoptimize_; |
| 940 |
| 941 static SlotRef ComputeSlotForNextArgument( |
| 942 Translation::Opcode opcode, |
| 943 TranslationIterator* iterator, |
| 944 DeoptimizationInputData* data, |
| 945 JavaScriptFrame* frame); |
| 946 |
| 947 Handle<Object> GetPreviouslyMaterialized(Isolate* isolate, int length); |
| 948 |
| 949 static Address SlotAddress(JavaScriptFrame* frame, int slot_index) { |
| 950 if (slot_index >= 0) { |
| 951 const int offset = JavaScriptFrameConstants::kLocal0Offset; |
| 952 return frame->fp() + offset - (slot_index * kPointerSize); |
| 953 } else { |
| 954 const int offset = JavaScriptFrameConstants::kLastParameterOffset; |
| 955 return frame->fp() + offset - ((slot_index + 1) * kPointerSize); |
| 956 } |
| 957 } |
| 958 |
| 959 Handle<Object> GetDeferredObject(Isolate* isolate); |
| 960 }; |
| 961 |
1075 class MaterializedObjectStore { | 962 class MaterializedObjectStore { |
1076 public: | 963 public: |
1077 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { | 964 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { |
1078 } | 965 } |
1079 | 966 |
1080 Handle<FixedArray> Get(Address fp); | 967 Handle<FixedArray> Get(Address fp); |
1081 void Set(Address fp, Handle<FixedArray> materialized_objects); | 968 void Set(Address fp, Handle<FixedArray> materialized_objects); |
1082 bool Remove(Address fp); | 969 bool Remove(Address fp); |
1083 | 970 |
1084 private: | 971 private: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 bool has_construct_stub_; | 1051 bool has_construct_stub_; |
1165 int parameters_count_; | 1052 int parameters_count_; |
1166 int expression_count_; | 1053 int expression_count_; |
1167 Object** parameters_; | 1054 Object** parameters_; |
1168 Object** expression_stack_; | 1055 Object** expression_stack_; |
1169 int source_position_; | 1056 int source_position_; |
1170 | 1057 |
1171 friend class Deoptimizer; | 1058 friend class Deoptimizer; |
1172 }; | 1059 }; |
1173 | 1060 |
1174 } // namespace internal | 1061 } } // namespace v8::internal |
1175 } // namespace v8 | |
1176 | 1062 |
1177 #endif // V8_DEOPTIMIZER_H_ | 1063 #endif // V8_DEOPTIMIZER_H_ |
OLD | NEW |