| 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 |