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 |