Chromium Code Reviews| 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 |