| 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/allocation.h" | 8 #include "src/allocation.h" |
| 9 #include "src/macro-assembler.h" | 9 #include "src/macro-assembler.h" |
| 10 | 10 |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 class FrameDescription; | 15 class FrameDescription; |
| 16 class TranslationIterator; | 16 class TranslationIterator; |
| 17 class DeoptimizedFrameInfo; | 17 class DeoptimizedFrameInfo; |
| 18 class TranslatedState; | 18 class TranslatedState; |
| 19 class RegisterValues; | 19 class RegisterValues; |
| 20 | 20 |
| 21 class TranslatedValue { | 21 class TranslatedValue { |
| 22 public: | 22 public: |
| 23 // Allocation-less getter of the value. | 23 // Allocation-less getter of the value. |
| 24 // Returns heap()->arguments_marker() if allocation would be | 24 // Returns heap()->arguments_marker() if allocation would be |
| 25 // necessary to get the value. | 25 // necessary to get the value. |
| 26 Object* GetRawValue() const; | 26 Object* GetRawValue() const; |
| 27 Handle<Object> GetValue(); | 27 Handle<Object> GetValue(); |
| 28 | 28 |
| 29 bool IsMaterializedObject() const; | 29 bool IsMaterializedObject() const; |
| 30 bool IsMaterializableByDebugger() const; |
| 30 | 31 |
| 31 private: | 32 private: |
| 32 friend class TranslatedState; | 33 friend class TranslatedState; |
| 33 friend class TranslatedFrame; | 34 friend class TranslatedFrame; |
| 34 | 35 |
| 35 enum Kind { | 36 enum Kind { |
| 36 kInvalid, | 37 kInvalid, |
| 37 kTagged, | 38 kTagged, |
| 38 kInt32, | 39 kInt32, |
| 39 kUInt32, | 40 kUInt32, |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 static void VisitAllOptimizedFunctions( | 502 static void VisitAllOptimizedFunctions( |
| 502 Isolate* isolate, OptimizedFunctionVisitor* visitor); | 503 Isolate* isolate, OptimizedFunctionVisitor* visitor); |
| 503 | 504 |
| 504 // The size in bytes of the code required at a lazy deopt patch site. | 505 // The size in bytes of the code required at a lazy deopt patch site. |
| 505 static int patch_size(); | 506 static int patch_size(); |
| 506 | 507 |
| 507 ~Deoptimizer(); | 508 ~Deoptimizer(); |
| 508 | 509 |
| 509 void MaterializeHeapObjects(JavaScriptFrameIterator* it); | 510 void MaterializeHeapObjects(JavaScriptFrameIterator* it); |
| 510 | 511 |
| 511 void MaterializeHeapNumbersForDebuggerInspectableFrame( | |
| 512 int frame_index, int parameter_count, int expression_count, | |
| 513 DeoptimizedFrameInfo* info); | |
| 514 | |
| 515 static void ComputeOutputFrames(Deoptimizer* deoptimizer); | 512 static void ComputeOutputFrames(Deoptimizer* deoptimizer); |
| 516 | 513 |
| 517 | 514 |
| 518 enum GetEntryMode { | 515 enum GetEntryMode { |
| 519 CALCULATE_ENTRY_ADDRESS, | 516 CALCULATE_ENTRY_ADDRESS, |
| 520 ENSURE_ENTRY_CODE | 517 ENSURE_ENTRY_CODE |
| 521 }; | 518 }; |
| 522 | 519 |
| 523 | 520 |
| 524 static Address GetDeoptimizationEntry( | 521 static Address GetDeoptimizationEntry( |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 static void DeoptimizeMarkedCodeForContext(Context* native_context); | 635 static void DeoptimizeMarkedCodeForContext(Context* native_context); |
| 639 | 636 |
| 640 // Patch the given code so that it will deoptimize itself. | 637 // Patch the given code so that it will deoptimize itself. |
| 641 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code); | 638 static void PatchCodeForDeoptimization(Isolate* isolate, Code* code); |
| 642 | 639 |
| 643 // Searches the list of known deoptimizing code for a Code object | 640 // Searches the list of known deoptimizing code for a Code object |
| 644 // containing the given address (which is supposedly faster than | 641 // containing the given address (which is supposedly faster than |
| 645 // searching all code objects). | 642 // searching all code objects). |
| 646 Code* FindDeoptimizingCode(Address addr); | 643 Code* FindDeoptimizingCode(Address addr); |
| 647 | 644 |
| 648 // Fill the input from from a JavaScript frame. This is used when | |
| 649 // the debugger needs to inspect an optimized frame. For normal | |
| 650 // deoptimizations the input frame is filled in generated code. | |
| 651 void FillInputFrame(Address tos, JavaScriptFrame* frame); | |
| 652 | |
| 653 // Fill the given output frame's registers to contain the failure handler | 645 // Fill the given output frame's registers to contain the failure handler |
| 654 // address and the number of parameters for a stub failure trampoline. | 646 // address and the number of parameters for a stub failure trampoline. |
| 655 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame, | 647 void SetPlatformCompiledStubRegisters(FrameDescription* output_frame, |
| 656 CodeStubDescriptor* desc); | 648 CodeStubDescriptor* desc); |
| 657 | 649 |
| 658 // Fill the given output frame's double registers with the original values | 650 // Fill the given output frame's double registers with the original values |
| 659 // from the input frame's double registers. | 651 // from the input frame's double registers. |
| 660 void CopyDoubleRegisters(FrameDescription* output_frame); | 652 void CopyDoubleRegisters(FrameDescription* output_frame); |
| 661 | 653 |
| 662 // Determines whether the input frame contains alignment padding by looking | 654 // Determines whether the input frame contains alignment padding by looking |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 double_registers_[n] = value; | 729 double_registers_[n] = value; |
| 738 } | 730 } |
| 739 | 731 |
| 740 intptr_t registers_[Register::kNumRegisters]; | 732 intptr_t registers_[Register::kNumRegisters]; |
| 741 double double_registers_[DoubleRegister::kMaxNumRegisters]; | 733 double double_registers_[DoubleRegister::kMaxNumRegisters]; |
| 742 }; | 734 }; |
| 743 | 735 |
| 744 | 736 |
| 745 class FrameDescription { | 737 class FrameDescription { |
| 746 public: | 738 public: |
| 747 FrameDescription(uint32_t frame_size, | 739 explicit FrameDescription(uint32_t frame_size, int parameter_count = 0); |
| 748 JSFunction* function); | |
| 749 | 740 |
| 750 void* operator new(size_t size, uint32_t frame_size) { | 741 void* operator new(size_t size, uint32_t frame_size) { |
| 751 // Subtracts kPointerSize, as the member frame_content_ already supplies | 742 // Subtracts kPointerSize, as the member frame_content_ already supplies |
| 752 // the first element of the area to store the frame. | 743 // the first element of the area to store the frame. |
| 753 return malloc(size + frame_size - kPointerSize); | 744 return malloc(size + frame_size - kPointerSize); |
| 754 } | 745 } |
| 755 | 746 |
| 756 void operator delete(void* pointer, uint32_t frame_size) { | 747 void operator delete(void* pointer, uint32_t frame_size) { |
| 757 free(pointer); | 748 free(pointer); |
| 758 } | 749 } |
| 759 | 750 |
| 760 void operator delete(void* description) { | 751 void operator delete(void* description) { |
| 761 free(description); | 752 free(description); |
| 762 } | 753 } |
| 763 | 754 |
| 764 uint32_t GetFrameSize() const { | 755 uint32_t GetFrameSize() const { |
| 765 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_); | 756 DCHECK(static_cast<uint32_t>(frame_size_) == frame_size_); |
| 766 return static_cast<uint32_t>(frame_size_); | 757 return static_cast<uint32_t>(frame_size_); |
| 767 } | 758 } |
| 768 | 759 |
| 769 JSFunction* GetFunction() const { return function_; } | |
| 770 | |
| 771 unsigned GetOffsetFromSlotIndex(int slot_index); | 760 unsigned GetOffsetFromSlotIndex(int slot_index); |
| 772 | 761 |
| 773 intptr_t GetFrameSlot(unsigned offset) { | 762 intptr_t GetFrameSlot(unsigned offset) { |
| 774 return *GetFrameSlotPointer(offset); | 763 return *GetFrameSlotPointer(offset); |
| 775 } | 764 } |
| 776 | 765 |
| 777 Address GetFramePointerAddress() { | 766 Address GetFramePointerAddress() { |
| 778 int fp_offset = GetFrameSize() - | 767 int fp_offset = GetFrameSize() - parameter_count() * kPointerSize - |
| 779 (ComputeParametersCount() + 1) * kPointerSize - | |
| 780 StandardFrameConstants::kCallerSPOffset; | 768 StandardFrameConstants::kCallerSPOffset; |
| 781 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset)); | 769 return reinterpret_cast<Address>(GetFrameSlotPointer(fp_offset)); |
| 782 } | 770 } |
| 783 | 771 |
| 784 RegisterValues* GetRegisterValues() { return ®ister_values_; } | 772 RegisterValues* GetRegisterValues() { return ®ister_values_; } |
| 785 | 773 |
| 786 void SetFrameSlot(unsigned offset, intptr_t value) { | 774 void SetFrameSlot(unsigned offset, intptr_t value) { |
| 787 *GetFrameSlotPointer(offset) = value; | 775 *GetFrameSlotPointer(offset) = value; |
| 788 } | 776 } |
| 789 | 777 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 } | 815 } |
| 828 | 816 |
| 829 Smi* GetState() const { return state_; } | 817 Smi* GetState() const { return state_; } |
| 830 void SetState(Smi* state) { state_ = state; } | 818 void SetState(Smi* state) { state_ = state; } |
| 831 | 819 |
| 832 void SetContinuation(intptr_t pc) { continuation_ = pc; } | 820 void SetContinuation(intptr_t pc) { continuation_ = pc; } |
| 833 | 821 |
| 834 StackFrame::Type GetFrameType() const { return type_; } | 822 StackFrame::Type GetFrameType() const { return type_; } |
| 835 void SetFrameType(StackFrame::Type type) { type_ = type; } | 823 void SetFrameType(StackFrame::Type type) { type_ = type; } |
| 836 | 824 |
| 837 // Get the incoming arguments count. | 825 // Argument count, including receiver. |
| 838 int ComputeParametersCount(); | 826 int parameter_count() { return parameter_count_; } |
| 839 | |
| 840 // Get a parameter value for an unoptimized frame. | |
| 841 Object* GetParameter(int index); | |
| 842 | |
| 843 // Get the expression stack height for a unoptimized frame. | |
| 844 unsigned GetExpressionCount(); | |
| 845 | |
| 846 // Get the expression stack value for an unoptimized frame. | |
| 847 Object* GetExpression(int index); | |
| 848 | 827 |
| 849 static int registers_offset() { | 828 static int registers_offset() { |
| 850 return OFFSET_OF(FrameDescription, register_values_.registers_); | 829 return OFFSET_OF(FrameDescription, register_values_.registers_); |
| 851 } | 830 } |
| 852 | 831 |
| 853 static int double_registers_offset() { | 832 static int double_registers_offset() { |
| 854 return OFFSET_OF(FrameDescription, register_values_.double_registers_); | 833 return OFFSET_OF(FrameDescription, register_values_.double_registers_); |
| 855 } | 834 } |
| 856 | 835 |
| 857 static int frame_size_offset() { | 836 static int frame_size_offset() { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 870 return offsetof(FrameDescription, frame_content_); | 849 return offsetof(FrameDescription, frame_content_); |
| 871 } | 850 } |
| 872 | 851 |
| 873 private: | 852 private: |
| 874 static const uint32_t kZapUint32 = 0xbeeddead; | 853 static const uint32_t kZapUint32 = 0xbeeddead; |
| 875 | 854 |
| 876 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to | 855 // Frame_size_ must hold a uint32_t value. It is only a uintptr_t to |
| 877 // keep the variable-size array frame_content_ of type intptr_t at | 856 // keep the variable-size array frame_content_ of type intptr_t at |
| 878 // the end of the structure aligned. | 857 // the end of the structure aligned. |
| 879 uintptr_t frame_size_; // Number of bytes. | 858 uintptr_t frame_size_; // Number of bytes. |
| 880 JSFunction* function_; | 859 int parameter_count_; |
| 881 RegisterValues register_values_; | 860 RegisterValues register_values_; |
| 882 intptr_t top_; | 861 intptr_t top_; |
| 883 intptr_t pc_; | 862 intptr_t pc_; |
| 884 intptr_t fp_; | 863 intptr_t fp_; |
| 885 intptr_t context_; | 864 intptr_t context_; |
| 886 intptr_t constant_pool_; | 865 intptr_t constant_pool_; |
| 887 StackFrame::Type type_; | 866 StackFrame::Type type_; |
| 888 Smi* state_; | 867 Smi* state_; |
| 889 | 868 |
| 890 // Continuation is the PC where the execution continues after | 869 // Continuation is the PC where the execution continues after |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1065 | 1044 |
| 1066 | 1045 |
| 1067 // Class used to represent an unoptimized frame when the debugger | 1046 // Class used to represent an unoptimized frame when the debugger |
| 1068 // needs to inspect a frame that is part of an optimized frame. The | 1047 // needs to inspect a frame that is part of an optimized frame. The |
| 1069 // internally used FrameDescription objects are not GC safe so for use | 1048 // internally used FrameDescription objects are not GC safe so for use |
| 1070 // by the debugger frame information is copied to an object of this type. | 1049 // by the debugger frame information is copied to an object of this type. |
| 1071 // Represents parameters in unadapted form so their number might mismatch | 1050 // Represents parameters in unadapted form so their number might mismatch |
| 1072 // formal parameter count. | 1051 // formal parameter count. |
| 1073 class DeoptimizedFrameInfo : public Malloced { | 1052 class DeoptimizedFrameInfo : public Malloced { |
| 1074 public: | 1053 public: |
| 1075 DeoptimizedFrameInfo(Deoptimizer* deoptimizer, | 1054 DeoptimizedFrameInfo(TranslatedState* state, |
| 1076 int frame_index, | 1055 TranslatedState::iterator frame_it, Isolate* isolate); |
| 1077 bool has_arguments_adaptor, | 1056 |
| 1078 bool has_construct_stub); | |
| 1079 // Return the number of incoming arguments. | 1057 // Return the number of incoming arguments. |
| 1080 int parameters_count() { return static_cast<int>(parameters_.size()); } | 1058 int parameters_count() { return static_cast<int>(parameters_.size()); } |
| 1081 | 1059 |
| 1082 // Return the height of the expression stack. | 1060 // Return the height of the expression stack. |
| 1083 int expression_count() { return static_cast<int>(expression_stack_.size()); } | 1061 int expression_count() { return static_cast<int>(expression_stack_.size()); } |
| 1084 | 1062 |
| 1085 // Get the frame function. | 1063 // Get the frame function. |
| 1086 Handle<JSFunction> GetFunction() { return function_; } | 1064 Handle<JSFunction> GetFunction() { return function_; } |
| 1087 | 1065 |
| 1088 // Get the frame context. | 1066 // Get the frame context. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1130 std::vector<Handle<Object> > expression_stack_; | 1108 std::vector<Handle<Object> > expression_stack_; |
| 1131 int source_position_; | 1109 int source_position_; |
| 1132 | 1110 |
| 1133 friend class Deoptimizer; | 1111 friend class Deoptimizer; |
| 1134 }; | 1112 }; |
| 1135 | 1113 |
| 1136 } // namespace internal | 1114 } // namespace internal |
| 1137 } // namespace v8 | 1115 } // namespace v8 |
| 1138 | 1116 |
| 1139 #endif // V8_DEOPTIMIZER_H_ | 1117 #endif // V8_DEOPTIMIZER_H_ |
| OLD | NEW |