| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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_COMPILER_ESCAPE_ANALYSIS_H_ | 5 #ifndef V8_COMPILER_ESCAPE_ANALYSIS_H_ |
| 6 #define V8_COMPILER_ESCAPE_ANALYSIS_H_ | 6 #define V8_COMPILER_ESCAPE_ANALYSIS_H_ |
| 7 | 7 |
| 8 #include "src/base/flags.h" | 8 #include "src/base/flags.h" |
| 9 #include "src/compiler/graph.h" | 9 #include "src/compiler/graph.h" |
| 10 | 10 |
| 11 namespace v8 { | 11 namespace v8 { |
| 12 namespace internal { | 12 namespace internal { |
| 13 namespace compiler { | 13 namespace compiler { |
| 14 | 14 |
| 15 // Forward declarations. | 15 // Forward declarations. |
| 16 class CommonOperatorBuilder; | 16 class CommonOperatorBuilder; |
| 17 class EscapeAnalysis; | 17 class EscapeAnalysis; |
| 18 class VirtualState; | 18 class VirtualState; |
| 19 class VirtualObject; | 19 class VirtualObject; |
| 20 | 20 |
| 21 | 21 |
| 22 // EscapeStatusAnalysis determines for each allocation whether it escapes. | 22 // EscapeStatusAnalysis determines for each allocation whether it escapes. |
| 23 class EscapeStatusAnalysis { | 23 class EscapeStatusAnalysis { |
| 24 public: | 24 public: |
| 25 typedef NodeId Alias; |
| 25 ~EscapeStatusAnalysis(); | 26 ~EscapeStatusAnalysis(); |
| 26 | 27 |
| 27 enum EscapeStatusFlag { | 28 enum Status { |
| 28 kUnknown = 0u, | 29 kUnknown = 0u, |
| 29 kTracked = 1u << 0, | 30 kTracked = 1u << 0, |
| 30 kEscaped = 1u << 1, | 31 kEscaped = 1u << 1, |
| 31 kOnStack = 1u << 2, | 32 kOnStack = 1u << 2, |
| 32 kVisited = 1u << 3, | 33 kVisited = 1u << 3, |
| 34 // A node is dangling, if it is a load of some kind, and does not have |
| 35 // an effect successor. |
| 36 kDanglingComputed = 1u << 4, |
| 37 kDangling = 1u << 5, |
| 38 // A node is is an effect branch point, if it has more than 2 non-dangling |
| 39 // effect successors. |
| 40 kBranchPointComputed = 1u << 6, |
| 41 kBranchPoint = 1u << 7, |
| 33 }; | 42 }; |
| 34 typedef base::Flags<EscapeStatusFlag, unsigned char> EscapeStatusFlags; | 43 typedef base::Flags<Status, unsigned char> StatusFlags; |
| 35 | 44 |
| 36 void Run(); | 45 void RunStatusAnalysis(); |
| 37 | 46 |
| 38 bool IsVirtual(Node* node); | 47 bool IsVirtual(Node* node); |
| 39 bool IsEscaped(Node* node); | 48 bool IsEscaped(Node* node); |
| 40 bool IsAllocation(Node* node); | 49 bool IsAllocation(Node* node); |
| 41 | |
| 42 void DebugPrint(); | 50 void DebugPrint(); |
| 43 | 51 |
| 44 friend class EscapeAnalysis; | 52 EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, |
| 53 Zone* zone); |
| 54 void EnqueueForStatusAnalysis(Node* node); |
| 55 bool SetEscaped(Node* node); |
| 56 bool IsEffectBranchPoint(Node* node); |
| 57 bool IsDanglingEffectNode(Node* node); |
| 58 void ResizeStatusVector(); |
| 59 size_t GetStatusVectorSize(); |
| 60 bool IsVirtual(NodeId id); |
| 61 |
| 62 Graph* graph() const { return graph_; } |
| 63 Zone* zone() const { return zone_; } |
| 64 void AssignAliases(); |
| 65 Alias GetAlias(NodeId id) const { return aliases_[id]; } |
| 66 const ZoneVector<Alias>& GetAliasMap() const { return aliases_; } |
| 67 Alias AliasCount() const { return next_free_alias_; } |
| 68 static const Alias kNotReachable; |
| 69 static const Alias kUntrackable; |
| 70 |
| 71 bool IsNotReachable(Node* node); |
| 72 ZoneVector<Node*>& stack() { return stack_; } |
| 45 | 73 |
| 46 private: | 74 private: |
| 47 EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, | |
| 48 Zone* zone); | |
| 49 void Process(Node* node); | 75 void Process(Node* node); |
| 50 void ProcessAllocate(Node* node); | 76 void ProcessAllocate(Node* node); |
| 51 void ProcessFinishRegion(Node* node); | 77 void ProcessFinishRegion(Node* node); |
| 52 void ProcessStoreField(Node* node); | 78 void ProcessStoreField(Node* node); |
| 53 void ProcessStoreElement(Node* node); | 79 void ProcessStoreElement(Node* node); |
| 54 bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { | 80 bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { |
| 55 return CheckUsesForEscape(node, node, phi_escaping); | 81 return CheckUsesForEscape(node, node, phi_escaping); |
| 56 } | 82 } |
| 57 bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); | 83 bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); |
| 58 void RevisitUses(Node* node); | 84 void RevisitUses(Node* node); |
| 59 void RevisitInputs(Node* node); | 85 void RevisitInputs(Node* node); |
| 60 bool SetEscaped(Node* node); | 86 |
| 61 bool IsVirtual(NodeId id); | 87 Alias NextAlias() { return next_free_alias_++; } |
| 88 |
| 62 bool HasEntry(Node* node); | 89 bool HasEntry(Node* node); |
| 63 void Resize(); | 90 |
| 64 size_t size(); | |
| 65 bool IsAllocationPhi(Node* node); | 91 bool IsAllocationPhi(Node* node); |
| 66 | 92 |
| 67 Graph* graph() const { return graph_; } | 93 ZoneVector<Node*> stack_; |
| 68 Zone* zone() const { return zone_; } | |
| 69 | |
| 70 EscapeAnalysis* object_analysis_; | 94 EscapeAnalysis* object_analysis_; |
| 71 Graph* const graph_; | 95 Graph* const graph_; |
| 72 Zone* const zone_; | 96 Zone* const zone_; |
| 73 ZoneVector<EscapeStatusFlags> status_; | 97 ZoneVector<StatusFlags> status_; |
| 74 ZoneDeque<Node*> queue_; | 98 Alias next_free_alias_; |
| 99 ZoneVector<Node*> status_stack_; |
| 100 ZoneVector<Alias> aliases_; |
| 75 | 101 |
| 76 DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); | 102 DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); |
| 77 }; | 103 }; |
| 78 | 104 |
| 79 | 105 |
| 80 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags) | 106 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags) |
| 81 | 107 |
| 82 | 108 |
| 83 // Forward Declaration. | 109 // Forward Declaration. |
| 84 class MergeCache; | 110 class MergeCache; |
| 85 | 111 |
| 86 | 112 |
| 87 // EscapeObjectAnalysis simulates stores to determine values of loads if | 113 // EscapeObjectAnalysis simulates stores to determine values of loads if |
| 88 // an object is virtual and eliminated. | 114 // an object is virtual and eliminated. |
| 89 class EscapeAnalysis { | 115 class EscapeAnalysis { |
| 90 public: | 116 public: |
| 91 typedef NodeId Alias; | 117 using Alias = EscapeStatusAnalysis::Alias; |
| 92 | |
| 93 EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); | 118 EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); |
| 94 ~EscapeAnalysis(); | 119 ~EscapeAnalysis(); |
| 95 | 120 |
| 96 void Run(); | 121 void Run(); |
| 97 | 122 |
| 98 Node* GetReplacement(Node* node); | 123 Node* GetReplacement(Node* node); |
| 99 bool IsVirtual(Node* node); | 124 bool IsVirtual(Node* node); |
| 100 bool IsEscaped(Node* node); | 125 bool IsEscaped(Node* node); |
| 101 bool CompareVirtualObjects(Node* left, Node* right); | 126 bool CompareVirtualObjects(Node* left, Node* right); |
| 102 Node* GetOrCreateObjectState(Node* effect, Node* node); | 127 Node* GetOrCreateObjectState(Node* effect, Node* node); |
| 103 bool ExistsVirtualAllocate(); | 128 bool ExistsVirtualAllocate(); |
| 104 | 129 |
| 105 private: | 130 private: |
| 106 void RunObjectAnalysis(); | 131 void RunObjectAnalysis(); |
| 107 void AssignAliases(); | |
| 108 bool Process(Node* node); | 132 bool Process(Node* node); |
| 109 void ProcessLoadField(Node* node); | 133 void ProcessLoadField(Node* node); |
| 110 void ProcessStoreField(Node* node); | 134 void ProcessStoreField(Node* node); |
| 111 void ProcessLoadElement(Node* node); | 135 void ProcessLoadElement(Node* node); |
| 112 void ProcessStoreElement(Node* node); | 136 void ProcessStoreElement(Node* node); |
| 113 void ProcessAllocationUsers(Node* node); | 137 void ProcessAllocationUsers(Node* node); |
| 114 void ProcessAllocation(Node* node); | 138 void ProcessAllocation(Node* node); |
| 115 void ProcessFinishRegion(Node* node); | 139 void ProcessFinishRegion(Node* node); |
| 116 void ProcessCall(Node* node); | 140 void ProcessCall(Node* node); |
| 117 void ProcessStart(Node* node); | 141 void ProcessStart(Node* node); |
| 118 bool ProcessEffectPhi(Node* node); | 142 bool ProcessEffectPhi(Node* node); |
| 119 void ProcessLoadFromPhi(int offset, Node* from, Node* node, | 143 void ProcessLoadFromPhi(int offset, Node* from, Node* node, |
| 120 VirtualState* states); | 144 VirtualState* states); |
| 121 | 145 |
| 122 void ForwardVirtualState(Node* node); | 146 void ForwardVirtualState(Node* node); |
| 123 bool IsEffectBranchPoint(Node* node); | |
| 124 bool IsDanglingEffectNode(Node* node); | |
| 125 int OffsetFromAccess(Node* node); | 147 int OffsetFromAccess(Node* node); |
| 126 | 148 VirtualState* CopyForModificationAt(VirtualState* state, Node* node); |
| 149 VirtualObject* CopyForModificationAt(VirtualObject* obj, VirtualState* state, |
| 150 Node* node); |
| 127 VirtualObject* GetVirtualObject(Node* at, NodeId id); | 151 VirtualObject* GetVirtualObject(Node* at, NodeId id); |
| 128 VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); | 152 VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); |
| 129 Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); | 153 Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); |
| 130 | 154 |
| 131 bool SetEscaped(Node* node); | 155 bool SetEscaped(Node* node); |
| 132 Node* replacement(NodeId id); | 156 Node* replacement(NodeId id); |
| 133 Node* replacement(Node* node); | 157 Node* replacement(Node* node); |
| 134 Node* ResolveReplacement(Node* node); | 158 Node* ResolveReplacement(Node* node); |
| 135 Node* GetReplacement(NodeId id); | 159 Node* GetReplacement(NodeId id); |
| 136 bool SetReplacement(Node* node, Node* rep); | 160 bool SetReplacement(Node* node, Node* rep); |
| 137 bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); | 161 bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); |
| 138 | 162 |
| 139 VirtualObject* GetVirtualObject(VirtualState* state, Node* node); | 163 VirtualObject* GetVirtualObject(VirtualState* state, Node* node); |
| 140 | 164 |
| 141 void DebugPrint(); | 165 void DebugPrint(); |
| 142 void DebugPrintState(VirtualState* state); | 166 void DebugPrintState(VirtualState* state); |
| 143 void DebugPrintObject(VirtualObject* state, Alias id); | 167 void DebugPrintObject(VirtualObject* state, Alias id); |
| 144 | 168 |
| 145 Alias NextAlias() { return next_free_alias_++; } | 169 Graph* graph() const { return status_analysis_.graph(); } |
| 146 Alias AliasCount() const { return next_free_alias_; } | 170 Zone* zone() const { return status_analysis_.zone(); } |
| 171 CommonOperatorBuilder* common() const { return common_; } |
| 172 ZoneVector<Node*>& stack() { return status_analysis_.stack(); } |
| 173 bool IsEffectBranchPoint(Node* node) { |
| 174 return status_analysis_.IsEffectBranchPoint(node); |
| 175 } |
| 176 bool IsDanglingEffectNode(Node* node) { |
| 177 return status_analysis_.IsDanglingEffectNode(node); |
| 178 } |
| 179 bool IsNotReachable(Node* node) { |
| 180 return status_analysis_.IsNotReachable(node); |
| 181 } |
| 182 Alias GetAlias(NodeId id) const { return status_analysis_.GetAlias(id); } |
| 183 Alias AliasCount() const { return status_analysis_.AliasCount(); } |
| 147 | 184 |
| 148 Graph* graph() const { return graph_; } | 185 EscapeStatusAnalysis status_analysis_; |
| 149 CommonOperatorBuilder* common() const { return common_; } | |
| 150 Zone* zone() const { return zone_; } | |
| 151 | |
| 152 static const Alias kNotReachable; | |
| 153 static const Alias kUntrackable; | |
| 154 Graph* const graph_; | |
| 155 CommonOperatorBuilder* const common_; | 186 CommonOperatorBuilder* const common_; |
| 156 Zone* const zone_; | |
| 157 ZoneVector<VirtualState*> virtual_states_; | 187 ZoneVector<VirtualState*> virtual_states_; |
| 158 ZoneVector<Node*> replacements_; | 188 ZoneVector<Node*> replacements_; |
| 159 EscapeStatusAnalysis escape_status_; | |
| 160 MergeCache* cache_; | 189 MergeCache* cache_; |
| 161 ZoneVector<Alias> aliases_; | |
| 162 Alias next_free_alias_; | |
| 163 | 190 |
| 164 DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); | 191 DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); |
| 165 }; | 192 }; |
| 166 | 193 |
| 167 } // namespace compiler | 194 } // namespace compiler |
| 168 } // namespace internal | 195 } // namespace internal |
| 169 } // namespace v8 | 196 } // namespace v8 |
| 170 | 197 |
| 171 #endif // V8_COMPILER_ESCAPE_ANALYSIS_H_ | 198 #endif // V8_COMPILER_ESCAPE_ANALYSIS_H_ |
| OLD | NEW |