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 | 17 |
18 static inline double read_double_value(Address p) { | 18 static inline double read_double_value(Address p) { |
19 double d; | 19 double d; |
20 memcpy(&d, p, sizeof(d)); | 20 memcpy(&d, p, sizeof(d)); |
21 return d; | 21 return d; |
22 } | 22 } |
23 | 23 |
24 | 24 |
25 class FrameDescription; | 25 class FrameDescription; |
26 class TranslationIterator; | 26 class TranslationIterator; |
27 class DeoptimizedFrameInfo; | 27 class DeoptimizedFrameInfo; |
28 | 28 |
29 class TranslatedState; | |
30 class RegisterValues; | |
31 | |
32 class TranslatedValue BASE_EMBEDDED { | |
33 public: | |
34 enum Kind { | |
35 UNKNOWN, | |
36 TAGGED, | |
37 INT32, | |
38 UINT32, | |
39 BOOLBIT, | |
40 DOUBLE, | |
41 DEFERRED_OBJECT, // Object captured by the escape analysis. | |
42 // The number of nested objects can be obtained | |
43 // with the DeferredObjectLength() method | |
44 // (the values of the nested objects follow | |
45 // this value in the depth-first order.) | |
46 DUPLICATE_OBJECT, // Duplicated object of a deferred object. | |
47 ARGUMENTS_OBJECT // Arguments object - only used to keep indexing | |
48 // in sync, it should not be materialized. | |
49 }; | |
50 | |
51 Kind kind() { return kind_; } | |
52 | |
53 int GetChildrenCount() { | |
54 if (kind() == DEFERRED_OBJECT || kind() == ARGUMENTS_OBJECT) { | |
55 return deferred_object_length_; | |
56 } else { | |
57 return 0; | |
58 } | |
59 } | |
60 | |
61 int ObjectIndex() { | |
62 DCHECK(DUPLICATE_OBJECT == kind() || DEFERRED_OBJECT == kind() || | |
63 ARGUMENTS_OBJECT == kind()); | |
64 return object_index_; | |
65 } | |
66 | |
67 void Handlify(); | |
68 | |
69 // Allocation-less getter of the value. | |
70 // Returns heap()->arguments_marker() if allocation would be | |
71 // necessary to get the value. | |
72 Object* GetRawValue(); | |
73 Handle<Object> GetValue(); | |
74 | |
75 bool IsMaterializedObject(); | |
76 | |
77 private: | |
78 friend class TranslatedState; | |
79 | |
80 TranslatedValue(TranslatedState* container, Kind kind) | |
81 : kind_(kind), | |
82 container_(container), | |
83 raw_literal_(nullptr), | |
84 integral_value_(0), | |
85 double_value_(0), | |
86 deferred_object_length_(-1), | |
87 object_index_(-1) {} | |
88 | |
89 static TranslatedValue NewArgumentsObject(TranslatedState* container, | |
90 int length, int object_index); | |
91 static TranslatedValue NewDeferredObject(TranslatedState* container, | |
92 int length, int object_index); | |
93 static TranslatedValue NewDuplicateObject(TranslatedState* container, int id); | |
94 static TranslatedValue NewDouble(TranslatedState* container, double value); | |
95 static TranslatedValue NewInt32(TranslatedState* container, uint32_t value); | |
96 static TranslatedValue NewUInt32(TranslatedState* container, uint32_t value); | |
97 static TranslatedValue NewBool(TranslatedState* container, uint32_t value); | |
98 static TranslatedValue NewTagged(TranslatedState* container, Object* literal); | |
99 static TranslatedValue NewInvalid(); | |
100 | |
101 Isolate* isolate(); | |
102 void MaterializeSimple(); | |
103 | |
104 Kind kind_; | |
105 TranslatedState* container_; // This is only needed for materialization of | |
106 // objects and constructing handles (to get | |
107 // to the isolate). | |
108 | |
109 MaybeHandle<Object> value_; // Before handlification, this is always null, | |
110 // after materialization it is never null, | |
111 // in between it is only null if the value needs | |
112 // to be materialized. | |
113 | |
114 // The following is supposed to be a union. | |
Benedikt Meurer
2015/06/03 04:02:17
Why not use a union here?
Jarin
2015/06/03 09:28:07
Done.
| |
115 | |
116 // - kind TAGGED. After handlification it is always nullptr. | |
117 Object* raw_literal_; | |
118 | |
119 // - kind is INT32, UINT32 or BOOLBIT. | |
120 uint32_t integral_value_; | |
121 | |
122 // - kind is DOUBLE | |
123 double double_value_; | |
124 | |
125 // - kind is ARGUMENTS_OBJECT or DEFERRED_OBJECT. | |
126 int deferred_object_length_; | |
127 // - kind is DUPLICATE_OBJECT or ARGUMENTS_OBJECT or DEFERRED_OBJECT. | |
128 int object_index_; | |
129 }; | |
130 | |
131 | |
132 class TranslatedFrame { | |
133 public: | |
134 enum Kind { | |
135 Function, | |
Benedikt Meurer
2015/06/03 04:02:17
Add k prefix to these constants.
Jarin
2015/06/03 09:28:07
Done.
| |
136 Getter, | |
137 Setter, | |
138 ArgumentsAdaptor, | |
139 ConstructStub, | |
140 CompiledStub, | |
141 Invalid | |
142 }; | |
143 | |
144 int GetValueCount(); | |
145 | |
146 Kind kind() const { return kind_; } | |
147 BailoutId node_id() { return node_id_; } | |
148 JSFunction* raw_function() { return raw_function_; } | |
149 Handle<JSFunction> function() { return function_; } | |
150 int height() { return height_; } | |
151 | |
152 class ValueIterator { | |
Benedikt Meurer
2015/06/03 04:02:17
Can we have STL naming here? I.e. rename ValueIter
Jarin
2015/06/03 09:28:07
Done.
| |
153 public: | |
154 ValueIterator& operator++() { | |
155 AdvanceIterator(&position_); | |
156 return *this; | |
157 } | |
158 | |
159 ValueIterator operator++(int) { | |
160 ValueIterator original(position_); | |
161 AdvanceIterator(&position_); | |
162 return original; | |
163 } | |
164 | |
165 bool operator==(const ValueIterator& other) const { | |
166 return position_ == other.position_; | |
167 } | |
168 bool operator!=(const ValueIterator& other) const { | |
169 return !(*this == other); | |
170 } | |
171 | |
172 TranslatedValue& operator*() { return (*position_); } | |
173 TranslatedValue* operator->() { return &(*position_); } | |
174 | |
175 private: | |
176 friend TranslatedFrame; | |
177 | |
178 explicit ValueIterator(std::deque<TranslatedValue>::iterator position) | |
179 : position_(position) {} | |
180 | |
181 std::deque<TranslatedValue>::iterator position_; | |
182 }; | |
183 | |
184 ValueIterator begin() { return ValueIterator(values_.begin()); } | |
185 ValueIterator end() { return ValueIterator(values_.end()); } | |
186 | |
187 private: | |
188 friend class TranslatedState; | |
189 | |
190 // Constructor static methods. | |
191 static TranslatedFrame JSFrame(BailoutId node_id, JSFunction* function, | |
192 int height); | |
193 static TranslatedFrame AccessorFrame(Kind kind, JSFunction* function); | |
194 static TranslatedFrame ArgumentsAdaptorFrame(JSFunction* function, | |
195 int height); | |
196 static TranslatedFrame ConstructStubFrame(JSFunction* function, int height); | |
197 static TranslatedFrame CompiledStubFrame(int height, Isolate* isolate) { | |
198 return TranslatedFrame(CompiledStub, isolate, nullptr, height); | |
199 } | |
200 static TranslatedFrame InvalidFrame() { | |
201 return TranslatedFrame(Invalid, nullptr); | |
202 } | |
203 | |
204 static void AdvanceIterator(std::deque<TranslatedValue>::iterator* iter); | |
205 | |
206 TranslatedFrame(Kind kind, Isolate* isolate, JSFunction* function = nullptr, | |
207 int height = 0) | |
208 : kind_(kind), | |
209 node_id_(BailoutId::None()), | |
210 raw_function_(function), | |
211 height_(height), | |
212 isolate_(isolate) {} | |
213 | |
214 | |
215 void Add(const TranslatedValue& value) { values_.push_back(value); } | |
216 void Handlify(Isolate* isolate); | |
217 | |
218 Kind kind_; | |
219 BailoutId node_id_; | |
220 JSFunction* raw_function_; | |
221 Handle<JSFunction> function_; | |
222 int height_; | |
223 Isolate* isolate_; | |
224 | |
225 typedef std::deque<TranslatedValue> ValuesContainer; | |
226 | |
227 ValuesContainer values_; | |
228 }; | |
229 | |
230 | |
231 // Auxiliary class for translating deoptimization values. | |
232 // Typical usage sequence: | |
233 // | |
234 // 1. Construct the instance. This will involve reading out the translations | |
235 // and resolving them to values using the supplied frame pointer and | |
236 // machine state (registers). This phase is guaranteed not to allocate | |
237 // and not to use any HandleScope. Any object pointers will be stored raw. | |
238 // | |
239 // 2. Handlify pointers. This will convert all the raw pointers to handles. | |
240 // | |
241 // 3. Reading out the frame values. | |
242 // | |
243 // Note: After the instance is constructed, it is possible to iterate over | |
244 // the values eagerly. | |
245 | |
246 class TranslatedState { | |
247 public: | |
248 TranslatedState(); | |
249 explicit TranslatedState(JavaScriptFrame* frame); | |
250 | |
251 void Prepare(bool has_adapted_arguments, Address stack_frame_pointer); | |
252 | |
253 // Store newly materialized values into the isolate. | |
254 void StoreMaterializedValuesAndDeopt(); | |
255 | |
256 std::vector<TranslatedFrame>& frames() { return frames_; } | |
257 | |
258 TranslatedFrame* GetArgumentsInfoFromJSFrameIndex(int jsframe_index, | |
259 int* arguments_count); | |
260 | |
261 Isolate* isolate() { return isolate_; } | |
262 | |
263 void Init(Address input_frame_pointer, JSFunction* input_frame_function, | |
264 TranslationIterator* iterator, FixedArray* literal_array, | |
265 RegisterValues* registers, FILE* trace_file); | |
266 | |
267 private: | |
268 friend TranslatedValue; | |
269 | |
270 TranslatedFrame CreateNextTranslatedFrame(TranslationIterator* iterator, | |
271 FixedArray* literal_array, | |
272 Address fp, | |
273 JSFunction* frame_function, | |
274 FILE* trace_file); | |
275 TranslatedValue CreateNextTranslatedValue(int frame_index, int value_index, | |
276 TranslationIterator* iterator, | |
277 FixedArray* literal_array, | |
278 Address fp, | |
279 RegisterValues* registers, | |
280 FILE* trace_file); | |
281 | |
282 void UpdateFromPreviouslyMaterializedObjects(); | |
283 Handle<Object> MaterializeAt(int frame_index, int* value_index); | |
284 Handle<Object> MaterializeObjectAt(int object_index); | |
285 bool GetAdaptedArguments(Handle<JSObject>* result, int frame_index); | |
286 | |
287 static int SlotOffsetFp(int slot_index); | |
288 static Address SlotAddress(Address fp, int slot_index); | |
289 static uint32_t GetUInt32Slot(Address fp, int slot_index); | |
290 | |
291 std::vector<TranslatedFrame> frames_; | |
292 Isolate* isolate_; | |
293 Address stack_frame_pointer_; | |
294 bool has_adapted_arguments_; | |
295 | |
296 struct ObjectPosition { | |
297 int frame_index_; | |
298 int value_index_; | |
299 }; | |
300 std::deque<ObjectPosition> object_positions_; | |
301 }; | |
302 | |
29 template<typename T> | 303 template<typename T> |
30 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { | 304 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { |
31 public: | 305 public: |
32 HeapNumberMaterializationDescriptor(T destination, double value) | 306 HeapNumberMaterializationDescriptor(T destination, double value) |
33 : destination_(destination), value_(value) { } | 307 : destination_(destination), value_(value) { } |
34 | 308 |
35 T destination() const { return destination_; } | 309 T destination() const { return destination_; } |
36 double value() const { return value_; } | 310 double value() const { return value_; } |
37 | 311 |
38 private: | 312 private: |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 Isolate* isolate, OptimizedFunctionVisitor* visitor); | 547 Isolate* isolate, OptimizedFunctionVisitor* visitor); |
274 | 548 |
275 // The size in bytes of the code required at a lazy deopt patch site. | 549 // The size in bytes of the code required at a lazy deopt patch site. |
276 static int patch_size(); | 550 static int patch_size(); |
277 | 551 |
278 ~Deoptimizer(); | 552 ~Deoptimizer(); |
279 | 553 |
280 void MaterializeHeapObjects(JavaScriptFrameIterator* it); | 554 void MaterializeHeapObjects(JavaScriptFrameIterator* it); |
281 | 555 |
282 void MaterializeHeapNumbersForDebuggerInspectableFrame( | 556 void MaterializeHeapNumbersForDebuggerInspectableFrame( |
283 Address parameters_top, | 557 int frame_index, int parameter_count, int expression_count, |
284 uint32_t parameters_size, | |
285 Address expressions_top, | |
286 uint32_t expressions_size, | |
287 DeoptimizedFrameInfo* info); | 558 DeoptimizedFrameInfo* info); |
288 | 559 |
289 static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 560 static void ComputeOutputFrames(Deoptimizer* deoptimizer); |
290 | 561 |
291 | 562 |
292 enum GetEntryMode { | 563 enum GetEntryMode { |
293 CALCULATE_ENTRY_ADDRESS, | 564 CALCULATE_ENTRY_ADDRESS, |
294 ENSURE_ENTRY_CODE | 565 ENSURE_ENTRY_CODE |
295 }; | 566 }; |
296 | 567 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 646 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
376 int frame_index); | 647 int frame_index); |
377 void DoComputeConstructStubFrame(TranslationIterator* iterator, | 648 void DoComputeConstructStubFrame(TranslationIterator* iterator, |
378 int frame_index); | 649 int frame_index); |
379 void DoComputeAccessorStubFrame(TranslationIterator* iterator, | 650 void DoComputeAccessorStubFrame(TranslationIterator* iterator, |
380 int frame_index, | 651 int frame_index, |
381 bool is_setter_stub_frame); | 652 bool is_setter_stub_frame); |
382 void DoComputeCompiledStubFrame(TranslationIterator* iterator, | 653 void DoComputeCompiledStubFrame(TranslationIterator* iterator, |
383 int frame_index); | 654 int frame_index); |
384 | 655 |
385 // Translate object, store the result into an auxiliary array | 656 void WriteValueToOutput(TranslatedFrame::ValueIterator* iterator, |
386 // (deferred_objects_tagged_values_). | 657 int* input_index, int frame_index, |
387 void DoTranslateObject(TranslationIterator* iterator, | 658 unsigned output_offset, |
388 int object_index, | 659 Address output_address_for_materialization = nullptr); |
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); | |
399 | 660 |
400 unsigned ComputeInputFrameSize() const; | 661 unsigned ComputeInputFrameSize() const; |
401 unsigned ComputeFixedSize(JSFunction* function) const; | 662 unsigned ComputeFixedSize(JSFunction* function) const; |
402 | 663 |
403 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; | 664 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; |
404 unsigned ComputeOutgoingArgumentSize() const; | 665 unsigned ComputeOutgoingArgumentSize() const; |
405 | 666 |
406 Object* ComputeLiteral(int index) const; | 667 Object* ComputeLiteral(int index) const; |
407 | 668 |
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 | |
430 static void GenerateDeoptimizationEntries( | 669 static void GenerateDeoptimizationEntries( |
431 MacroAssembler* masm, int count, BailoutType type); | 670 MacroAssembler* masm, int count, BailoutType type); |
432 | 671 |
433 // Marks all the code in the given context for deoptimization. | 672 // Marks all the code in the given context for deoptimization. |
434 static void MarkAllCodeForContext(Context* native_context); | 673 static void MarkAllCodeForContext(Context* native_context); |
435 | 674 |
436 // Visit all the known optimized functions in a given context. | 675 // Visit all the known optimized functions in a given context. |
437 static void VisitAllOptimizedFunctionsForContext( | 676 static void VisitAllOptimizedFunctionsForContext( |
438 Context* context, OptimizedFunctionVisitor* visitor); | 677 Context* context, OptimizedFunctionVisitor* visitor); |
439 | 678 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
477 | 716 |
478 // Input frame description. | 717 // Input frame description. |
479 FrameDescription* input_; | 718 FrameDescription* input_; |
480 // Number of output frames. | 719 // Number of output frames. |
481 int output_count_; | 720 int output_count_; |
482 // Number of output js frames. | 721 // Number of output js frames. |
483 int jsframe_count_; | 722 int jsframe_count_; |
484 // Array of output frame descriptions. | 723 // Array of output frame descriptions. |
485 FrameDescription** output_; | 724 FrameDescription** output_; |
486 | 725 |
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 | |
494 // Key for lookup of previously materialized objects | 726 // Key for lookup of previously materialized objects |
495 Address stack_fp_; | 727 Address stack_fp_; |
496 Handle<FixedArray> previously_materialized_objects_; | 728 Handle<FixedArray> previously_materialized_objects_; |
497 int prev_materialized_count_; | 729 int prev_materialized_count_; |
498 | 730 |
499 // Output frame information. Only used during heap object materialization. | 731 // Output frame information. Only used during heap object materialization. |
500 List<Handle<JSFunction> > jsframe_functions_; | 732 List<Handle<JSFunction> > jsframe_functions_; |
501 List<bool> jsframe_has_adapted_arguments_; | 733 List<bool> jsframe_has_adapted_arguments_; |
502 | 734 |
503 // Materialized objects. Only used during heap object materialization. | 735 TranslatedState translated_state_; |
504 List<Handle<Object> >* materialized_values_; | 736 struct ValueToMaterialize { |
505 List<Handle<Object> >* materialized_objects_; | 737 Address output_slot_address_; |
506 int materialization_value_index_; | 738 TranslatedFrame::ValueIterator value_; |
507 int materialization_object_index_; | 739 }; |
740 std::vector<ValueToMaterialize> values_to_materialize_; | |
508 | 741 |
509 #ifdef DEBUG | 742 #ifdef DEBUG |
510 DisallowHeapAllocation* disallow_heap_allocation_; | 743 DisallowHeapAllocation* disallow_heap_allocation_; |
511 #endif // DEBUG | 744 #endif // DEBUG |
512 | 745 |
513 CodeTracer::Scope* trace_scope_; | 746 CodeTracer::Scope* trace_scope_; |
514 | 747 |
515 static const int table_entry_size_; | 748 static const int table_entry_size_; |
516 | 749 |
517 friend class FrameDescription; | 750 friend class FrameDescription; |
518 friend class DeoptimizedFrameInfo; | 751 friend class DeoptimizedFrameInfo; |
519 }; | 752 }; |
520 | 753 |
521 | 754 |
755 class RegisterValues { | |
756 public: | |
757 intptr_t GetRegister(unsigned n) const { | |
758 #if DEBUG | |
759 // This convoluted DCHECK is needed to work around a gcc problem that | |
760 // improperly detects an array bounds overflow in optimized debug builds | |
761 // when using a plain DCHECK. | |
762 if (n >= arraysize(registers_)) { | |
763 DCHECK(false); | |
764 return 0; | |
765 } | |
766 #endif | |
767 return registers_[n]; | |
768 } | |
769 | |
770 double GetDoubleRegister(unsigned n) const { | |
771 DCHECK(n < arraysize(double_registers_)); | |
772 return double_registers_[n]; | |
773 } | |
774 | |
775 void SetRegister(unsigned n, intptr_t value) { | |
776 DCHECK(n < arraysize(registers_)); | |
777 registers_[n] = value; | |
778 } | |
779 | |
780 void SetDoubleRegister(unsigned n, double value) { | |
781 DCHECK(n < arraysize(double_registers_)); | |
782 double_registers_[n] = value; | |
783 } | |
784 | |
785 intptr_t registers_[Register::kNumRegisters]; | |
Benedikt Meurer
2015/06/03 04:02:17
Nit: these should be private.
Jarin
2015/06/03 09:28:07
The offset of the field is exposed to the platform
| |
786 double double_registers_[DoubleRegister::kMaxNumRegisters]; | |
787 }; | |
788 | |
789 | |
522 class FrameDescription { | 790 class FrameDescription { |
523 public: | 791 public: |
524 FrameDescription(uint32_t frame_size, | 792 FrameDescription(uint32_t frame_size, |
525 JSFunction* function); | 793 JSFunction* function); |
526 | 794 |
527 void* operator new(size_t size, uint32_t frame_size) { | 795 void* operator new(size_t size, uint32_t frame_size) { |
528 // Subtracts kPointerSize, as the member frame_content_ already supplies | 796 // Subtracts kPointerSize, as the member frame_content_ already supplies |
529 // the first element of the area to store the frame. | 797 // the first element of the area to store the frame. |
530 return malloc(size + frame_size - kPointerSize); | 798 return malloc(size + frame_size - kPointerSize); |
531 } | 799 } |
(...skipping 20 matching lines...) Expand all Loading... | |
552 | 820 |
553 intptr_t GetFrameSlot(unsigned offset) { | 821 intptr_t GetFrameSlot(unsigned offset) { |
554 return *GetFrameSlotPointer(offset); | 822 return *GetFrameSlotPointer(offset); |
555 } | 823 } |
556 | 824 |
557 double GetDoubleFrameSlot(unsigned offset) { | 825 double GetDoubleFrameSlot(unsigned offset) { |
558 intptr_t* ptr = GetFrameSlotPointer(offset); | 826 intptr_t* ptr = GetFrameSlotPointer(offset); |
559 return read_double_value(reinterpret_cast<Address>(ptr)); | 827 return read_double_value(reinterpret_cast<Address>(ptr)); |
560 } | 828 } |
561 | 829 |
830 Address GetFramePointerAddress() { | |
831 int fp_offset = GetFrameSize() - | |
832 (ComputeParametersCount() + 1) * kPointerSize - | |
833 StandardFrameConstants::kCallerSPOffset; | |
834 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset)); | |
835 } | |
836 | |
837 RegisterValues* GetRegisterValues() { return ®ister_values_; } | |
838 | |
562 void SetFrameSlot(unsigned offset, intptr_t value) { | 839 void SetFrameSlot(unsigned offset, intptr_t value) { |
563 *GetFrameSlotPointer(offset) = value; | 840 *GetFrameSlotPointer(offset) = value; |
564 } | 841 } |
565 | 842 |
566 void SetCallerPc(unsigned offset, intptr_t value); | 843 void SetCallerPc(unsigned offset, intptr_t value); |
567 | 844 |
568 void SetCallerFp(unsigned offset, intptr_t value); | 845 void SetCallerFp(unsigned offset, intptr_t value); |
569 | 846 |
570 void SetCallerConstantPool(unsigned offset, intptr_t value); | 847 void SetCallerConstantPool(unsigned offset, intptr_t value); |
571 | 848 |
572 intptr_t GetRegister(unsigned n) const { | 849 intptr_t GetRegister(unsigned n) const { |
573 #if DEBUG | 850 return register_values_.GetRegister(n); |
574 // This convoluted DCHECK is needed to work around a gcc problem that | |
575 // improperly detects an array bounds overflow in optimized debug builds | |
576 // when using a plain DCHECK. | |
577 if (n >= arraysize(registers_)) { | |
578 DCHECK(false); | |
579 return 0; | |
580 } | |
581 #endif | |
582 return registers_[n]; | |
583 } | 851 } |
584 | 852 |
585 double GetDoubleRegister(unsigned n) const { | 853 double GetDoubleRegister(unsigned n) const { |
586 DCHECK(n < arraysize(double_registers_)); | 854 return register_values_.GetDoubleRegister(n); |
587 return double_registers_[n]; | |
588 } | 855 } |
589 | 856 |
590 void SetRegister(unsigned n, intptr_t value) { | 857 void SetRegister(unsigned n, intptr_t value) { |
591 DCHECK(n < arraysize(registers_)); | 858 register_values_.SetRegister(n, value); |
592 registers_[n] = value; | |
593 } | 859 } |
594 | 860 |
595 void SetDoubleRegister(unsigned n, double value) { | 861 void SetDoubleRegister(unsigned n, double value) { |
596 DCHECK(n < arraysize(double_registers_)); | 862 register_values_.SetDoubleRegister(n, value); |
597 double_registers_[n] = value; | |
598 } | 863 } |
599 | 864 |
600 intptr_t GetTop() const { return top_; } | 865 intptr_t GetTop() const { return top_; } |
601 void SetTop(intptr_t top) { top_ = top; } | 866 void SetTop(intptr_t top) { top_ = top; } |
602 | 867 |
603 intptr_t GetPc() const { return pc_; } | 868 intptr_t GetPc() const { return pc_; } |
604 void SetPc(intptr_t pc) { pc_ = pc; } | 869 void SetPc(intptr_t pc) { pc_ = pc; } |
605 | 870 |
606 intptr_t GetFp() const { return fp_; } | 871 intptr_t GetFp() const { return fp_; } |
607 void SetFp(intptr_t fp) { fp_ = fp; } | 872 void SetFp(intptr_t fp) { fp_ = fp; } |
(...skipping 20 matching lines...) Expand all Loading... | |
628 // Get a parameter value for an unoptimized frame. | 893 // Get a parameter value for an unoptimized frame. |
629 Object* GetParameter(int index); | 894 Object* GetParameter(int index); |
630 | 895 |
631 // Get the expression stack height for a unoptimized frame. | 896 // Get the expression stack height for a unoptimized frame. |
632 unsigned GetExpressionCount(); | 897 unsigned GetExpressionCount(); |
633 | 898 |
634 // Get the expression stack value for an unoptimized frame. | 899 // Get the expression stack value for an unoptimized frame. |
635 Object* GetExpression(int index); | 900 Object* GetExpression(int index); |
636 | 901 |
637 static int registers_offset() { | 902 static int registers_offset() { |
638 return OFFSET_OF(FrameDescription, registers_); | 903 return OFFSET_OF(FrameDescription, register_values_.registers_); |
639 } | 904 } |
640 | 905 |
641 static int double_registers_offset() { | 906 static int double_registers_offset() { |
642 return OFFSET_OF(FrameDescription, double_registers_); | 907 return OFFSET_OF(FrameDescription, register_values_.double_registers_); |
643 } | 908 } |
644 | 909 |
645 static int frame_size_offset() { | 910 static int frame_size_offset() { |
646 return OFFSET_OF(FrameDescription, frame_size_); | 911 return OFFSET_OF(FrameDescription, frame_size_); |
647 } | 912 } |
648 | 913 |
649 static int pc_offset() { | 914 static int pc_offset() { |
650 return OFFSET_OF(FrameDescription, pc_); | 915 return OFFSET_OF(FrameDescription, pc_); |
651 } | 916 } |
652 | 917 |
(...skipping 10 matching lines...) Expand all Loading... | |
663 } | 928 } |
664 | 929 |
665 private: | 930 private: |
666 static const uint32_t kZapUint32 = 0xbeeddead; | 931 static const uint32_t kZapUint32 = 0xbeeddead; |
667 | 932 |
668 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to | 933 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to |
669 // keep the variable-size array frame_content_ of type intptr_t at | 934 // keep the variable-size array frame_content_ of type intptr_t at |
670 // the end of the structure aligned. | 935 // the end of the structure aligned. |
671 uintptr_t frame_size_; // Number of bytes. | 936 uintptr_t frame_size_; // Number of bytes. |
672 JSFunction* function_; | 937 JSFunction* function_; |
673 intptr_t registers_[Register::kNumRegisters]; | 938 RegisterValues register_values_; |
674 double double_registers_[DoubleRegister::kMaxNumRegisters]; | |
675 intptr_t top_; | 939 intptr_t top_; |
676 intptr_t pc_; | 940 intptr_t pc_; |
677 intptr_t fp_; | 941 intptr_t fp_; |
678 intptr_t context_; | 942 intptr_t context_; |
679 intptr_t constant_pool_; | 943 intptr_t constant_pool_; |
680 StackFrame::Type type_; | 944 StackFrame::Type type_; |
681 Smi* state_; | 945 Smi* state_; |
682 | 946 |
683 // Continuation is the PC where the execution continues after | 947 // Continuation is the PC where the execution continues after |
684 // deoptimizing. | 948 // deoptimizing. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
795 zone_(zone) { | 1059 zone_(zone) { |
796 buffer_->Add(BEGIN, zone); | 1060 buffer_->Add(BEGIN, zone); |
797 buffer_->Add(frame_count, zone); | 1061 buffer_->Add(frame_count, zone); |
798 buffer_->Add(jsframe_count, zone); | 1062 buffer_->Add(jsframe_count, zone); |
799 } | 1063 } |
800 | 1064 |
801 int index() const { return index_; } | 1065 int index() const { return index_; } |
802 | 1066 |
803 // Commands. | 1067 // Commands. |
804 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); | 1068 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); |
805 void BeginCompiledStubFrame(); | 1069 void BeginCompiledStubFrame(int height); |
806 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); | 1070 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); |
807 void BeginConstructStubFrame(int literal_id, unsigned height); | 1071 void BeginConstructStubFrame(int literal_id, unsigned height); |
808 void BeginGetterStubFrame(int literal_id); | 1072 void BeginGetterStubFrame(int literal_id); |
809 void BeginSetterStubFrame(int literal_id); | 1073 void BeginSetterStubFrame(int literal_id); |
810 void BeginArgumentsObject(int args_length); | 1074 void BeginArgumentsObject(int args_length); |
811 void BeginCapturedObject(int length); | 1075 void BeginCapturedObject(int length); |
812 void DuplicateObject(int object_index); | 1076 void DuplicateObject(int object_index); |
813 void StoreRegister(Register reg); | 1077 void StoreRegister(Register reg); |
814 void StoreInt32Register(Register reg); | 1078 void StoreInt32Register(Register reg); |
815 void StoreUint32Register(Register reg); | 1079 void StoreUint32Register(Register reg); |
(...skipping 18 matching lines...) Expand all Loading... | |
834 // A literal id which refers to the JSFunction itself. | 1098 // A literal id which refers to the JSFunction itself. |
835 static const int kSelfLiteralId = -239; | 1099 static const int kSelfLiteralId = -239; |
836 | 1100 |
837 private: | 1101 private: |
838 TranslationBuffer* buffer_; | 1102 TranslationBuffer* buffer_; |
839 int index_; | 1103 int index_; |
840 Zone* zone_; | 1104 Zone* zone_; |
841 }; | 1105 }; |
842 | 1106 |
843 | 1107 |
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 | |
962 class MaterializedObjectStore { | 1108 class MaterializedObjectStore { |
963 public: | 1109 public: |
964 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { | 1110 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { |
965 } | 1111 } |
966 | 1112 |
967 Handle<FixedArray> Get(Address fp); | 1113 Handle<FixedArray> Get(Address fp); |
968 void Set(Address fp, Handle<FixedArray> materialized_objects); | 1114 void Set(Address fp, Handle<FixedArray> materialized_objects); |
969 bool Remove(Address fp); | 1115 bool Remove(Address fp); |
970 | 1116 |
971 private: | 1117 private: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1051 bool has_construct_stub_; | 1197 bool has_construct_stub_; |
1052 int parameters_count_; | 1198 int parameters_count_; |
1053 int expression_count_; | 1199 int expression_count_; |
1054 Object** parameters_; | 1200 Object** parameters_; |
1055 Object** expression_stack_; | 1201 Object** expression_stack_; |
1056 int source_position_; | 1202 int source_position_; |
1057 | 1203 |
1058 friend class Deoptimizer; | 1204 friend class Deoptimizer; |
1059 }; | 1205 }; |
1060 | 1206 |
1061 } } // namespace v8::internal | 1207 |
Benedikt Meurer
2015/06/03 04:02:17
Nit: redundant empty line.
Jarin
2015/06/03 09:28:07
Done.
| |
1208 } // namespace internal | |
1209 } // namespace v8 | |
1062 | 1210 |
1063 #endif // V8_DEOPTIMIZER_H_ | 1211 #endif // V8_DEOPTIMIZER_H_ |
OLD | NEW |