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 kDanglingComputed = 1u << 4, | |
Jarin
2016/01/22 13:36:11
Could we have some comments that gives some explan
sigurds
2016/01/25 10:34:56
Done.
| |
35 kDangling = 1u << 5, | |
36 kBranchPointComputed = 1u << 6, | |
37 kBranchPoint = 1u << 7, | |
33 }; | 38 }; |
34 typedef base::Flags<EscapeStatusFlag, unsigned char> EscapeStatusFlags; | 39 typedef base::Flags<Status, unsigned char> StatusFlags; |
35 | 40 |
36 void Run(); | 41 void RunStatusAnalysis(); |
37 | 42 |
38 bool IsVirtual(Node* node); | 43 bool IsVirtual(Node* node); |
39 bool IsEscaped(Node* node); | 44 bool IsEscaped(Node* node); |
40 bool IsAllocation(Node* node); | 45 bool IsAllocation(Node* node); |
41 | |
42 void DebugPrint(); | 46 void DebugPrint(); |
43 | 47 |
44 friend class EscapeAnalysis; | 48 protected: |
49 EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, | |
50 Zone* zone); | |
51 void EnqueueForStatusAnalysis(Node* node); | |
52 bool SetEscaped(Node* node); | |
53 bool IsEffectBranchPoint(Node* node); | |
54 bool IsDanglingEffectNode(Node* node); | |
55 void ResizeStatusVector(); | |
56 size_t GetStatusVectorSize(); | |
57 bool IsVirtual(NodeId id); | |
58 | |
59 Graph* graph() const { return graph_; } | |
60 Zone* zone() const { return zone_; } | |
61 void AssignAliases(); | |
62 Alias GetAlias(NodeId id) const { return aliases_[id]; } | |
63 const ZoneVector<Alias>& GetAliasMap() const { return aliases_; } | |
64 Alias AliasCount() const { return next_free_alias_; } | |
65 static const Alias kNotReachable; | |
66 static const Alias kUntrackable; | |
67 | |
68 bool IsNotReachable(Node* node); | |
69 | |
70 ZoneVector<Node*> stack_; | |
45 | 71 |
46 private: | 72 private: |
47 EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, | |
48 Zone* zone); | |
49 void Process(Node* node); | 73 void Process(Node* node); |
50 void ProcessAllocate(Node* node); | 74 void ProcessAllocate(Node* node); |
51 void ProcessFinishRegion(Node* node); | 75 void ProcessFinishRegion(Node* node); |
52 void ProcessStoreField(Node* node); | 76 void ProcessStoreField(Node* node); |
53 void ProcessStoreElement(Node* node); | 77 void ProcessStoreElement(Node* node); |
54 bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { | 78 bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { |
55 return CheckUsesForEscape(node, node, phi_escaping); | 79 return CheckUsesForEscape(node, node, phi_escaping); |
56 } | 80 } |
57 bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); | 81 bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); |
58 void RevisitUses(Node* node); | 82 void RevisitUses(Node* node); |
59 void RevisitInputs(Node* node); | 83 void RevisitInputs(Node* node); |
60 bool SetEscaped(Node* node); | 84 |
61 bool IsVirtual(NodeId id); | 85 Alias NextAlias() { return next_free_alias_++; } |
86 | |
62 bool HasEntry(Node* node); | 87 bool HasEntry(Node* node); |
63 void Resize(); | 88 |
64 size_t size(); | |
65 bool IsAllocationPhi(Node* node); | 89 bool IsAllocationPhi(Node* node); |
66 | 90 |
67 Graph* graph() const { return graph_; } | |
68 Zone* zone() const { return zone_; } | |
69 | |
70 EscapeAnalysis* object_analysis_; | 91 EscapeAnalysis* object_analysis_; |
71 Graph* const graph_; | 92 Graph* const graph_; |
72 Zone* const zone_; | 93 Zone* const zone_; |
73 ZoneVector<EscapeStatusFlags> status_; | 94 ZoneVector<StatusFlags> status_; |
74 ZoneDeque<Node*> queue_; | 95 Alias next_free_alias_; |
96 ZoneVector<Node*> status_stack_; | |
97 ZoneVector<Alias> aliases_; | |
75 | 98 |
76 DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); | 99 DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); |
77 }; | 100 }; |
78 | 101 |
79 | 102 |
80 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags) | 103 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags) |
81 | 104 |
82 | 105 |
83 // Forward Declaration. | 106 // Forward Declaration. |
84 class MergeCache; | 107 class MergeCache; |
85 | 108 |
86 | 109 |
87 // EscapeObjectAnalysis simulates stores to determine values of loads if | 110 // EscapeObjectAnalysis simulates stores to determine values of loads if |
88 // an object is virtual and eliminated. | 111 // an object is virtual and eliminated. |
89 class EscapeAnalysis { | 112 class EscapeAnalysis : private EscapeStatusAnalysis { |
Jarin
2016/01/22 13:36:11
Is there a good reason to inherit? Is it just to s
sigurds
2016/01/25 10:34:56
Done.
| |
90 public: | 113 public: |
91 typedef NodeId Alias; | |
92 | |
93 EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); | 114 EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone); |
94 ~EscapeAnalysis(); | 115 ~EscapeAnalysis(); |
95 | 116 |
96 void Run(); | 117 void Run(); |
97 | 118 |
98 Node* GetReplacement(Node* node); | 119 Node* GetReplacement(Node* node); |
99 bool IsVirtual(Node* node); | 120 bool IsVirtual(Node* node); |
100 bool IsEscaped(Node* node); | 121 bool IsEscaped(Node* node); |
101 bool CompareVirtualObjects(Node* left, Node* right); | 122 bool CompareVirtualObjects(Node* left, Node* right); |
102 Node* GetOrCreateObjectState(Node* effect, Node* node); | 123 Node* GetOrCreateObjectState(Node* effect, Node* node); |
103 bool ExistsVirtualAllocate(); | 124 bool ExistsVirtualAllocate(); |
104 | 125 |
105 private: | 126 private: |
106 void RunObjectAnalysis(); | 127 void RunObjectAnalysis(); |
107 void AssignAliases(); | |
108 bool Process(Node* node); | 128 bool Process(Node* node); |
109 void ProcessLoadField(Node* node); | 129 void ProcessLoadField(Node* node); |
110 void ProcessStoreField(Node* node); | 130 void ProcessStoreField(Node* node); |
111 void ProcessLoadElement(Node* node); | 131 void ProcessLoadElement(Node* node); |
112 void ProcessStoreElement(Node* node); | 132 void ProcessStoreElement(Node* node); |
113 void ProcessAllocationUsers(Node* node); | 133 void ProcessAllocationUsers(Node* node); |
114 void ProcessAllocation(Node* node); | 134 void ProcessAllocation(Node* node); |
115 void ProcessFinishRegion(Node* node); | 135 void ProcessFinishRegion(Node* node); |
116 void ProcessCall(Node* node); | 136 void ProcessCall(Node* node); |
117 void ProcessStart(Node* node); | 137 void ProcessStart(Node* node); |
118 bool ProcessEffectPhi(Node* node); | 138 bool ProcessEffectPhi(Node* node); |
119 void ProcessLoadFromPhi(int offset, Node* from, Node* node, | 139 void ProcessLoadFromPhi(int offset, Node* from, Node* node, |
120 VirtualState* states); | 140 VirtualState* states); |
121 | 141 |
122 void ForwardVirtualState(Node* node); | 142 void ForwardVirtualState(Node* node); |
123 bool IsEffectBranchPoint(Node* node); | |
124 bool IsDanglingEffectNode(Node* node); | |
125 int OffsetFromAccess(Node* node); | 143 int OffsetFromAccess(Node* node); |
126 | 144 VirtualState* CopyForModificationAt(VirtualState* state, Node* node); |
145 VirtualObject* CopyForModificationAt(VirtualObject* obj, VirtualState* state, | |
146 Node* node); | |
127 VirtualObject* GetVirtualObject(Node* at, NodeId id); | 147 VirtualObject* GetVirtualObject(Node* at, NodeId id); |
128 VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); | 148 VirtualObject* ResolveVirtualObject(VirtualState* state, Node* node); |
129 Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); | 149 Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs); |
130 | 150 |
131 bool SetEscaped(Node* node); | 151 bool SetEscaped(Node* node); |
132 Node* replacement(NodeId id); | 152 Node* replacement(NodeId id); |
133 Node* replacement(Node* node); | 153 Node* replacement(Node* node); |
134 Node* ResolveReplacement(Node* node); | 154 Node* ResolveReplacement(Node* node); |
135 Node* GetReplacement(NodeId id); | 155 Node* GetReplacement(NodeId id); |
136 bool SetReplacement(Node* node, Node* rep); | 156 bool SetReplacement(Node* node, Node* rep); |
137 bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); | 157 bool UpdateReplacement(VirtualState* state, Node* node, Node* rep); |
138 | 158 |
139 VirtualObject* GetVirtualObject(VirtualState* state, Node* node); | 159 VirtualObject* GetVirtualObject(VirtualState* state, Node* node); |
140 | 160 |
141 void DebugPrint(); | 161 void DebugPrint(); |
142 void DebugPrintState(VirtualState* state); | 162 void DebugPrintState(VirtualState* state); |
143 void DebugPrintObject(VirtualObject* state, Alias id); | 163 void DebugPrintObject(VirtualObject* state, Alias id); |
144 | 164 |
145 Alias NextAlias() { return next_free_alias_++; } | 165 CommonOperatorBuilder* common() const { return common_; } |
146 Alias AliasCount() const { return next_free_alias_; } | |
147 | 166 |
148 Graph* graph() const { return graph_; } | |
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_; | 167 CommonOperatorBuilder* const common_; |
156 Zone* const zone_; | |
157 ZoneVector<VirtualState*> virtual_states_; | 168 ZoneVector<VirtualState*> virtual_states_; |
158 ZoneVector<Node*> replacements_; | 169 ZoneVector<Node*> replacements_; |
159 EscapeStatusAnalysis escape_status_; | |
160 MergeCache* cache_; | 170 MergeCache* cache_; |
161 ZoneVector<Alias> aliases_; | |
162 Alias next_free_alias_; | |
163 | 171 |
164 DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); | 172 DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); |
165 }; | 173 }; |
166 | 174 |
167 } // namespace compiler | 175 } // namespace compiler |
168 } // namespace internal | 176 } // namespace internal |
169 } // namespace v8 | 177 } // namespace v8 |
170 | 178 |
171 #endif // V8_COMPILER_ESCAPE_ANALYSIS_H_ | 179 #endif // V8_COMPILER_ESCAPE_ANALYSIS_H_ |
OLD | NEW |