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 | |
25 class FrameDescription; | 17 class FrameDescription; |
26 class TranslationIterator; | 18 class TranslationIterator; |
27 class DeoptimizedFrameInfo; | 19 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 }; |
28 | 281 |
29 template<typename T> | 282 template<typename T> |
30 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { | 283 class HeapNumberMaterializationDescriptor BASE_EMBEDDED { |
31 public: | 284 public: |
32 HeapNumberMaterializationDescriptor(T destination, double value) | 285 HeapNumberMaterializationDescriptor(T destination, double value) |
33 : destination_(destination), value_(value) { } | 286 : destination_(destination), value_(value) { } |
34 | 287 |
35 T destination() const { return destination_; } | 288 T destination() const { return destination_; } |
36 double value() const { return value_; } | 289 double value() const { return value_; } |
37 | 290 |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 Isolate* isolate, OptimizedFunctionVisitor* visitor); | 526 Isolate* isolate, OptimizedFunctionVisitor* visitor); |
274 | 527 |
275 // The size in bytes of the code required at a lazy deopt patch site. | 528 // The size in bytes of the code required at a lazy deopt patch site. |
276 static int patch_size(); | 529 static int patch_size(); |
277 | 530 |
278 ~Deoptimizer(); | 531 ~Deoptimizer(); |
279 | 532 |
280 void MaterializeHeapObjects(JavaScriptFrameIterator* it); | 533 void MaterializeHeapObjects(JavaScriptFrameIterator* it); |
281 | 534 |
282 void MaterializeHeapNumbersForDebuggerInspectableFrame( | 535 void MaterializeHeapNumbersForDebuggerInspectableFrame( |
283 Address parameters_top, | 536 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); | 537 DeoptimizedFrameInfo* info); |
288 | 538 |
289 static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 539 static void ComputeOutputFrames(Deoptimizer* deoptimizer); |
290 | 540 |
291 | 541 |
292 enum GetEntryMode { | 542 enum GetEntryMode { |
293 CALCULATE_ENTRY_ADDRESS, | 543 CALCULATE_ENTRY_ADDRESS, |
294 ENSURE_ENTRY_CODE | 544 ENSURE_ENTRY_CODE |
295 }; | 545 }; |
296 | 546 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, | 625 void DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
376 int frame_index); | 626 int frame_index); |
377 void DoComputeConstructStubFrame(TranslationIterator* iterator, | 627 void DoComputeConstructStubFrame(TranslationIterator* iterator, |
378 int frame_index); | 628 int frame_index); |
379 void DoComputeAccessorStubFrame(TranslationIterator* iterator, | 629 void DoComputeAccessorStubFrame(TranslationIterator* iterator, |
380 int frame_index, | 630 int frame_index, |
381 bool is_setter_stub_frame); | 631 bool is_setter_stub_frame); |
382 void DoComputeCompiledStubFrame(TranslationIterator* iterator, | 632 void DoComputeCompiledStubFrame(TranslationIterator* iterator, |
383 int frame_index); | 633 int frame_index); |
384 | 634 |
385 // Translate object, store the result into an auxiliary array | 635 void WriteValueToOutput(TranslatedFrame::iterator* iterator, int* input_index, |
386 // (deferred_objects_tagged_values_). | 636 int frame_index, unsigned output_offset, |
387 void DoTranslateObject(TranslationIterator* iterator, | 637 Address output_address_for_materialization = nullptr); |
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); | |
399 | 638 |
400 unsigned ComputeInputFrameSize() const; | 639 unsigned ComputeInputFrameSize() const; |
401 unsigned ComputeFixedSize(JSFunction* function) const; | 640 unsigned ComputeFixedSize(JSFunction* function) const; |
402 | 641 |
403 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; | 642 unsigned ComputeIncomingArgumentSize(JSFunction* function) const; |
404 unsigned ComputeOutgoingArgumentSize() const; | 643 unsigned ComputeOutgoingArgumentSize() const; |
405 | 644 |
406 Object* ComputeLiteral(int index) const; | 645 Object* ComputeLiteral(int index) const; |
407 | 646 |
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( | 647 static void GenerateDeoptimizationEntries( |
431 MacroAssembler* masm, int count, BailoutType type); | 648 MacroAssembler* masm, int count, BailoutType type); |
432 | 649 |
433 // Marks all the code in the given context for deoptimization. | 650 // Marks all the code in the given context for deoptimization. |
434 static void MarkAllCodeForContext(Context* native_context); | 651 static void MarkAllCodeForContext(Context* native_context); |
435 | 652 |
436 // Visit all the known optimized functions in a given context. | 653 // Visit all the known optimized functions in a given context. |
437 static void VisitAllOptimizedFunctionsForContext( | 654 static void VisitAllOptimizedFunctionsForContext( |
438 Context* context, OptimizedFunctionVisitor* visitor); | 655 Context* context, OptimizedFunctionVisitor* visitor); |
439 | 656 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 | 694 |
478 // Input frame description. | 695 // Input frame description. |
479 FrameDescription* input_; | 696 FrameDescription* input_; |
480 // Number of output frames. | 697 // Number of output frames. |
481 int output_count_; | 698 int output_count_; |
482 // Number of output js frames. | 699 // Number of output js frames. |
483 int jsframe_count_; | 700 int jsframe_count_; |
484 // Array of output frame descriptions. | 701 // Array of output frame descriptions. |
485 FrameDescription** output_; | 702 FrameDescription** output_; |
486 | 703 |
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 | 704 // Key for lookup of previously materialized objects |
495 Address stack_fp_; | 705 Address stack_fp_; |
496 Handle<FixedArray> previously_materialized_objects_; | |
497 int prev_materialized_count_; | |
498 | 706 |
499 // Output frame information. Only used during heap object materialization. | 707 TranslatedState translated_state_; |
500 List<Handle<JSFunction> > jsframe_functions_; | 708 struct ValueToMaterialize { |
501 List<bool> jsframe_has_adapted_arguments_; | 709 Address output_slot_address_; |
502 | 710 TranslatedFrame::iterator value_; |
503 // Materialized objects. Only used during heap object materialization. | 711 }; |
504 List<Handle<Object> >* materialized_values_; | 712 std::vector<ValueToMaterialize> values_to_materialize_; |
505 List<Handle<Object> >* materialized_objects_; | |
506 int materialization_value_index_; | |
507 int materialization_object_index_; | |
508 | 713 |
509 #ifdef DEBUG | 714 #ifdef DEBUG |
510 DisallowHeapAllocation* disallow_heap_allocation_; | 715 DisallowHeapAllocation* disallow_heap_allocation_; |
511 #endif // DEBUG | 716 #endif // DEBUG |
512 | 717 |
513 CodeTracer::Scope* trace_scope_; | 718 CodeTracer::Scope* trace_scope_; |
514 | 719 |
515 static const int table_entry_size_; | 720 static const int table_entry_size_; |
516 | 721 |
517 friend class FrameDescription; | 722 friend class FrameDescription; |
518 friend class DeoptimizedFrameInfo; | 723 friend class DeoptimizedFrameInfo; |
519 }; | 724 }; |
520 | 725 |
521 | 726 |
| 727 class RegisterValues { |
| 728 public: |
| 729 intptr_t GetRegister(unsigned n) const { |
| 730 #if DEBUG |
| 731 // This convoluted DCHECK is needed to work around a gcc problem that |
| 732 // improperly detects an array bounds overflow in optimized debug builds |
| 733 // when using a plain DCHECK. |
| 734 if (n >= arraysize(registers_)) { |
| 735 DCHECK(false); |
| 736 return 0; |
| 737 } |
| 738 #endif |
| 739 return registers_[n]; |
| 740 } |
| 741 |
| 742 double GetDoubleRegister(unsigned n) const { |
| 743 DCHECK(n < arraysize(double_registers_)); |
| 744 return double_registers_[n]; |
| 745 } |
| 746 |
| 747 void SetRegister(unsigned n, intptr_t value) { |
| 748 DCHECK(n < arraysize(registers_)); |
| 749 registers_[n] = value; |
| 750 } |
| 751 |
| 752 void SetDoubleRegister(unsigned n, double value) { |
| 753 DCHECK(n < arraysize(double_registers_)); |
| 754 double_registers_[n] = value; |
| 755 } |
| 756 |
| 757 intptr_t registers_[Register::kNumRegisters]; |
| 758 double double_registers_[DoubleRegister::kMaxNumRegisters]; |
| 759 }; |
| 760 |
| 761 |
522 class FrameDescription { | 762 class FrameDescription { |
523 public: | 763 public: |
524 FrameDescription(uint32_t frame_size, | 764 FrameDescription(uint32_t frame_size, |
525 JSFunction* function); | 765 JSFunction* function); |
526 | 766 |
527 void* operator new(size_t size, uint32_t frame_size) { | 767 void* operator new(size_t size, uint32_t frame_size) { |
528 // Subtracts kPointerSize, as the member frame_content_ already supplies | 768 // Subtracts kPointerSize, as the member frame_content_ already supplies |
529 // the first element of the area to store the frame. | 769 // the first element of the area to store the frame. |
530 return malloc(size + frame_size - kPointerSize); | 770 return malloc(size + frame_size - kPointerSize); |
531 } | 771 } |
(...skipping 15 matching lines...) Expand all Loading... |
547 } | 787 } |
548 | 788 |
549 JSFunction* GetFunction() const { return function_; } | 789 JSFunction* GetFunction() const { return function_; } |
550 | 790 |
551 unsigned GetOffsetFromSlotIndex(int slot_index); | 791 unsigned GetOffsetFromSlotIndex(int slot_index); |
552 | 792 |
553 intptr_t GetFrameSlot(unsigned offset) { | 793 intptr_t GetFrameSlot(unsigned offset) { |
554 return *GetFrameSlotPointer(offset); | 794 return *GetFrameSlotPointer(offset); |
555 } | 795 } |
556 | 796 |
557 double GetDoubleFrameSlot(unsigned offset) { | 797 Address GetFramePointerAddress() { |
558 intptr_t* ptr = GetFrameSlotPointer(offset); | 798 int fp_offset = GetFrameSize() - |
559 return read_double_value(reinterpret_cast<Address>(ptr)); | 799 (ComputeParametersCount() + 1) * kPointerSize - |
| 800 StandardFrameConstants::kCallerSPOffset; |
| 801 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset)); |
560 } | 802 } |
561 | 803 |
| 804 RegisterValues* GetRegisterValues() { return ®ister_values_; } |
| 805 |
562 void SetFrameSlot(unsigned offset, intptr_t value) { | 806 void SetFrameSlot(unsigned offset, intptr_t value) { |
563 *GetFrameSlotPointer(offset) = value; | 807 *GetFrameSlotPointer(offset) = value; |
564 } | 808 } |
565 | 809 |
566 void SetCallerPc(unsigned offset, intptr_t value); | 810 void SetCallerPc(unsigned offset, intptr_t value); |
567 | 811 |
568 void SetCallerFp(unsigned offset, intptr_t value); | 812 void SetCallerFp(unsigned offset, intptr_t value); |
569 | 813 |
570 void SetCallerConstantPool(unsigned offset, intptr_t value); | 814 void SetCallerConstantPool(unsigned offset, intptr_t value); |
571 | 815 |
572 intptr_t GetRegister(unsigned n) const { | 816 intptr_t GetRegister(unsigned n) const { |
573 #if DEBUG | 817 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 } | 818 } |
584 | 819 |
585 double GetDoubleRegister(unsigned n) const { | 820 double GetDoubleRegister(unsigned n) const { |
586 DCHECK(n < arraysize(double_registers_)); | 821 return register_values_.GetDoubleRegister(n); |
587 return double_registers_[n]; | |
588 } | 822 } |
589 | 823 |
590 void SetRegister(unsigned n, intptr_t value) { | 824 void SetRegister(unsigned n, intptr_t value) { |
591 DCHECK(n < arraysize(registers_)); | 825 register_values_.SetRegister(n, value); |
592 registers_[n] = value; | |
593 } | 826 } |
594 | 827 |
595 void SetDoubleRegister(unsigned n, double value) { | 828 void SetDoubleRegister(unsigned n, double value) { |
596 DCHECK(n < arraysize(double_registers_)); | 829 register_values_.SetDoubleRegister(n, value); |
597 double_registers_[n] = value; | |
598 } | 830 } |
599 | 831 |
600 intptr_t GetTop() const { return top_; } | 832 intptr_t GetTop() const { return top_; } |
601 void SetTop(intptr_t top) { top_ = top; } | 833 void SetTop(intptr_t top) { top_ = top; } |
602 | 834 |
603 intptr_t GetPc() const { return pc_; } | 835 intptr_t GetPc() const { return pc_; } |
604 void SetPc(intptr_t pc) { pc_ = pc; } | 836 void SetPc(intptr_t pc) { pc_ = pc; } |
605 | 837 |
606 intptr_t GetFp() const { return fp_; } | 838 intptr_t GetFp() const { return fp_; } |
607 void SetFp(intptr_t fp) { fp_ = fp; } | 839 void SetFp(intptr_t fp) { fp_ = fp; } |
(...skipping 20 matching lines...) Expand all Loading... |
628 // Get a parameter value for an unoptimized frame. | 860 // Get a parameter value for an unoptimized frame. |
629 Object* GetParameter(int index); | 861 Object* GetParameter(int index); |
630 | 862 |
631 // Get the expression stack height for a unoptimized frame. | 863 // Get the expression stack height for a unoptimized frame. |
632 unsigned GetExpressionCount(); | 864 unsigned GetExpressionCount(); |
633 | 865 |
634 // Get the expression stack value for an unoptimized frame. | 866 // Get the expression stack value for an unoptimized frame. |
635 Object* GetExpression(int index); | 867 Object* GetExpression(int index); |
636 | 868 |
637 static int registers_offset() { | 869 static int registers_offset() { |
638 return OFFSET_OF(FrameDescription, registers_); | 870 return OFFSET_OF(FrameDescription, register_values_.registers_); |
639 } | 871 } |
640 | 872 |
641 static int double_registers_offset() { | 873 static int double_registers_offset() { |
642 return OFFSET_OF(FrameDescription, double_registers_); | 874 return OFFSET_OF(FrameDescription, register_values_.double_registers_); |
643 } | 875 } |
644 | 876 |
645 static int frame_size_offset() { | 877 static int frame_size_offset() { |
646 return OFFSET_OF(FrameDescription, frame_size_); | 878 return OFFSET_OF(FrameDescription, frame_size_); |
647 } | 879 } |
648 | 880 |
649 static int pc_offset() { | 881 static int pc_offset() { |
650 return OFFSET_OF(FrameDescription, pc_); | 882 return OFFSET_OF(FrameDescription, pc_); |
651 } | 883 } |
652 | 884 |
(...skipping 10 matching lines...) Expand all Loading... |
663 } | 895 } |
664 | 896 |
665 private: | 897 private: |
666 static const uint32_t kZapUint32 = 0xbeeddead; | 898 static const uint32_t kZapUint32 = 0xbeeddead; |
667 | 899 |
668 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to | 900 // 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 | 901 // keep the variable-size array frame_content_ of type intptr_t at |
670 // the end of the structure aligned. | 902 // the end of the structure aligned. |
671 uintptr_t frame_size_; // Number of bytes. | 903 uintptr_t frame_size_; // Number of bytes. |
672 JSFunction* function_; | 904 JSFunction* function_; |
673 intptr_t registers_[Register::kNumRegisters]; | 905 RegisterValues register_values_; |
674 double double_registers_[DoubleRegister::kMaxNumRegisters]; | |
675 intptr_t top_; | 906 intptr_t top_; |
676 intptr_t pc_; | 907 intptr_t pc_; |
677 intptr_t fp_; | 908 intptr_t fp_; |
678 intptr_t context_; | 909 intptr_t context_; |
679 intptr_t constant_pool_; | 910 intptr_t constant_pool_; |
680 StackFrame::Type type_; | 911 StackFrame::Type type_; |
681 Smi* state_; | 912 Smi* state_; |
682 | 913 |
683 // Continuation is the PC where the execution continues after | 914 // Continuation is the PC where the execution continues after |
684 // deoptimizing. | 915 // deoptimizing. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
795 zone_(zone) { | 1026 zone_(zone) { |
796 buffer_->Add(BEGIN, zone); | 1027 buffer_->Add(BEGIN, zone); |
797 buffer_->Add(frame_count, zone); | 1028 buffer_->Add(frame_count, zone); |
798 buffer_->Add(jsframe_count, zone); | 1029 buffer_->Add(jsframe_count, zone); |
799 } | 1030 } |
800 | 1031 |
801 int index() const { return index_; } | 1032 int index() const { return index_; } |
802 | 1033 |
803 // Commands. | 1034 // Commands. |
804 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); | 1035 void BeginJSFrame(BailoutId node_id, int literal_id, unsigned height); |
805 void BeginCompiledStubFrame(); | 1036 void BeginCompiledStubFrame(int height); |
806 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); | 1037 void BeginArgumentsAdaptorFrame(int literal_id, unsigned height); |
807 void BeginConstructStubFrame(int literal_id, unsigned height); | 1038 void BeginConstructStubFrame(int literal_id, unsigned height); |
808 void BeginGetterStubFrame(int literal_id); | 1039 void BeginGetterStubFrame(int literal_id); |
809 void BeginSetterStubFrame(int literal_id); | 1040 void BeginSetterStubFrame(int literal_id); |
810 void BeginArgumentsObject(int args_length); | 1041 void BeginArgumentsObject(int args_length); |
811 void BeginCapturedObject(int length); | 1042 void BeginCapturedObject(int length); |
812 void DuplicateObject(int object_index); | 1043 void DuplicateObject(int object_index); |
813 void StoreRegister(Register reg); | 1044 void StoreRegister(Register reg); |
814 void StoreInt32Register(Register reg); | 1045 void StoreInt32Register(Register reg); |
815 void StoreUint32Register(Register reg); | 1046 void StoreUint32Register(Register reg); |
(...skipping 18 matching lines...) Expand all Loading... |
834 // A literal id which refers to the JSFunction itself. | 1065 // A literal id which refers to the JSFunction itself. |
835 static const int kSelfLiteralId = -239; | 1066 static const int kSelfLiteralId = -239; |
836 | 1067 |
837 private: | 1068 private: |
838 TranslationBuffer* buffer_; | 1069 TranslationBuffer* buffer_; |
839 int index_; | 1070 int index_; |
840 Zone* zone_; | 1071 Zone* zone_; |
841 }; | 1072 }; |
842 | 1073 |
843 | 1074 |
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 { | 1075 class MaterializedObjectStore { |
963 public: | 1076 public: |
964 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { | 1077 explicit MaterializedObjectStore(Isolate* isolate) : isolate_(isolate) { |
965 } | 1078 } |
966 | 1079 |
967 Handle<FixedArray> Get(Address fp); | 1080 Handle<FixedArray> Get(Address fp); |
968 void Set(Address fp, Handle<FixedArray> materialized_objects); | 1081 void Set(Address fp, Handle<FixedArray> materialized_objects); |
969 bool Remove(Address fp); | 1082 bool Remove(Address fp); |
970 | 1083 |
971 private: | 1084 private: |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 bool has_construct_stub_; | 1164 bool has_construct_stub_; |
1052 int parameters_count_; | 1165 int parameters_count_; |
1053 int expression_count_; | 1166 int expression_count_; |
1054 Object** parameters_; | 1167 Object** parameters_; |
1055 Object** expression_stack_; | 1168 Object** expression_stack_; |
1056 int source_position_; | 1169 int source_position_; |
1057 | 1170 |
1058 friend class Deoptimizer; | 1171 friend class Deoptimizer; |
1059 }; | 1172 }; |
1060 | 1173 |
1061 } } // namespace v8::internal | 1174 } // namespace internal |
| 1175 } // namespace v8 |
1062 | 1176 |
1063 #endif // V8_DEOPTIMIZER_H_ | 1177 #endif // V8_DEOPTIMIZER_H_ |
OLD | NEW |