Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: src/compiler/escape-analysis-reducer.cc

Issue 1485183002: [turbofan] Deopt support for escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@ea-local
Patch Set: Improve Unittest and guard printf behind --trace-turbo-escape Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "src/compiler/escape-analysis-reducer.h" 5 #include "src/compiler/escape-analysis-reducer.h"
6 6
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/counters.h" 8 #include "src/counters.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 18 matching lines...) Expand all
29 case IrOpcode::kStoreElement: 29 case IrOpcode::kStoreElement:
30 return ReduceStore(node); 30 return ReduceStore(node);
31 case IrOpcode::kAllocate: 31 case IrOpcode::kAllocate:
32 return ReduceAllocate(node); 32 return ReduceAllocate(node);
33 case IrOpcode::kFinishRegion: 33 case IrOpcode::kFinishRegion:
34 return ReduceFinishRegion(node); 34 return ReduceFinishRegion(node);
35 case IrOpcode::kReferenceEqual: 35 case IrOpcode::kReferenceEqual:
36 return ReduceReferenceEqual(node); 36 return ReduceReferenceEqual(node);
37 case IrOpcode::kObjectIsSmi: 37 case IrOpcode::kObjectIsSmi:
38 return ReduceObjectIsSmi(node); 38 return ReduceObjectIsSmi(node);
39 case IrOpcode::kStateValues:
40 case IrOpcode::kFrameState:
41 return ReplaceWithDeoptDummy(node);
42 default: 39 default:
40 if (node->op()->EffectInputCount() > 0) {
Jarin 2016/01/05 12:51:19 As discussed offline, this serves as an over-appro
sigurds 2016/01/05 13:08:57 Done.
41 return ReduceFrameStateUses(node);
42 }
43 break; 43 break;
44 } 44 }
45 return NoChange(); 45 return NoChange();
46 } 46 }
47 47
48 48
49 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { 49 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
50 DCHECK(node->opcode() == IrOpcode::kLoadField || 50 DCHECK(node->opcode() == IrOpcode::kLoadField ||
51 node->opcode() == IrOpcode::kLoadElement); 51 node->opcode() == IrOpcode::kLoadElement);
52 if (Node* rep = escape_analysis()->GetReplacement(node)) { 52 if (Node* rep = escape_analysis()->GetReplacement(node)) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 118 }
119 return NoChange(); 119 return NoChange();
120 } 120 }
121 121
122 122
123 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) { 123 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
124 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual); 124 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual);
125 Node* left = NodeProperties::GetValueInput(node, 0); 125 Node* left = NodeProperties::GetValueInput(node, 0);
126 Node* right = NodeProperties::GetValueInput(node, 1); 126 Node* right = NodeProperties::GetValueInput(node, 1);
127 if (escape_analysis()->IsVirtual(left)) { 127 if (escape_analysis()->IsVirtual(left)) {
128 if (escape_analysis()->IsVirtual(right)) { 128 if (escape_analysis()->IsVirtual(right) &&
129 if (Node* rep = escape_analysis()->GetReplacement(left)) { 129 escape_analysis()->CompareVirtualObjects(left, right)) {
130 left = rep; 130 ReplaceWithValue(node, jsgraph()->TrueConstant());
131 } 131 if (FLAG_trace_turbo_escape) {
132 if (Node* rep = escape_analysis()->GetReplacement(right)) { 132 PrintF("Replaced ref eq #%d with true\n", node->id());
133 right = rep;
134 }
135 // TODO(sigurds): What to do if either is a PHI?
136 if (left == right) {
137 ReplaceWithValue(node, jsgraph()->TrueConstant());
138 if (FLAG_trace_turbo_escape) {
139 PrintF("Replaced ref eq #%d with true\n", node->id());
140 }
141 return Replace(node);
142 } 133 }
143 } 134 }
144 // Right-hand side is either not virtual, or a different node. 135 // Right-hand side is not a virtual object, or a different one.
145 ReplaceWithValue(node, jsgraph()->FalseConstant()); 136 ReplaceWithValue(node, jsgraph()->FalseConstant());
146 if (FLAG_trace_turbo_escape) { 137 if (FLAG_trace_turbo_escape) {
147 PrintF("Replaced ref eq #%d with false\n", node->id()); 138 PrintF("Replaced ref eq #%d with false\n", node->id());
148 } 139 }
149 return Replace(node); 140 return Replace(node);
150 } else if (escape_analysis()->IsVirtual(right)) { 141 } else if (escape_analysis()->IsVirtual(right)) {
151 // Left-hand side is not a virtual object. 142 // Left-hand side is not a virtual object.
152 ReplaceWithValue(node, jsgraph()->FalseConstant()); 143 ReplaceWithValue(node, jsgraph()->FalseConstant());
153 if (FLAG_trace_turbo_escape) { 144 if (FLAG_trace_turbo_escape) {
154 PrintF("Replaced ref eq #%d with false\n", node->id()); 145 PrintF("Replaced ref eq #%d with false\n", node->id());
(...skipping 10 matching lines...) Expand all
165 ReplaceWithValue(node, jsgraph()->FalseConstant()); 156 ReplaceWithValue(node, jsgraph()->FalseConstant());
166 if (FLAG_trace_turbo_escape) { 157 if (FLAG_trace_turbo_escape) {
167 PrintF("Replaced ObjectIsSmi #%d with false\n", node->id()); 158 PrintF("Replaced ObjectIsSmi #%d with false\n", node->id());
168 } 159 }
169 return Replace(node); 160 return Replace(node);
170 } 161 }
171 return NoChange(); 162 return NoChange();
172 } 163 }
173 164
174 165
175 // TODO(sigurds): This is a temporary solution until escape analysis 166 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) {
176 // supports deoptimization. 167 DCHECK_GE(node->op()->EffectInputCount(), 1);
177 Reduction EscapeAnalysisReducer::ReplaceWithDeoptDummy(Node* node) { 168 bool changed = false;
178 DCHECK(node->opcode() == IrOpcode::kStateValues || 169 for (int i = 0; i < node->InputCount(); ++i) {
179 node->opcode() == IrOpcode::kFrameState); 170 Node* input = node->InputAt(i);
180 Reduction r = NoChange(); 171 if (input->opcode() == IrOpcode::kFrameState) {
181 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 172 if (Node* ret = ReduceFrameState(input, node, false)) {
182 Node* input = NodeProperties::GetValueInput(node, i); 173 node->ReplaceInput(i, ret);
183 if (input->opcode() == IrOpcode::kFinishRegion || 174 changed = true;
184 input->opcode() == IrOpcode::kAllocate ||
185 input->opcode() == IrOpcode::kPhi) {
186 if (escape_analysis()->IsVirtual(input)) {
187 NodeProperties::ReplaceValueInput(node, jsgraph()->UndefinedConstant(),
188 i);
189 if (FLAG_trace_turbo_escape) {
190 PrintF("Replaced state value (#%d) input with dummy\n", node->id());
191 }
192 r = Changed(node);
193 } 175 }
194 } 176 }
195 } 177 }
196 return r; 178 if (changed) {
179 return Changed(node);
180 }
181 return NoChange();
197 } 182 }
198 183
199 184
185 Node* EscapeAnalysisReducer::ReduceFrameState(Node* node, Node* effect,
186 bool multiple_users) {
187 DCHECK(node->opcode() == IrOpcode::kFrameState);
188 if (FLAG_trace_turbo_escape) {
189 PrintF("Reducing FrameState %d\n", node->id());
190 }
191 Node* clone = nullptr;
192 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
193 Node* input = NodeProperties::GetValueInput(node, i);
194 Node* ret =
195 input->opcode() == IrOpcode::kStateValues
196 ? ReduceStateValueInputs(input, effect, node->UseCount() > 1)
197 : ReduceStateValueInput(node, i, effect, node->UseCount() > 1);
198 if (ret) {
199 if (node->UseCount() > 1 || multiple_users) {
200 if (FLAG_trace_turbo_escape) {
201 PrintF(" Cloning #%d", node->id());
202 }
203 node = clone = jsgraph()->graph()->CloneNode(node);
204 if (FLAG_trace_turbo_escape) {
205 PrintF(" to #%d\n", node->id());
206 }
207 multiple_users = false; // Don't clone anymore.
208 }
209 NodeProperties::ReplaceValueInput(node, ret, i);
210 }
211 }
212 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node, 0);
213 if (outer_frame_state->opcode() == IrOpcode::kFrameState) {
214 if (Node* ret =
215 ReduceFrameState(outer_frame_state, effect, node->UseCount() > 1)) {
216 if (node->UseCount() > 1 || multiple_users) {
217 if (FLAG_trace_turbo_escape) {
218 PrintF(" Cloning #%d", node->id());
219 }
220 node = clone = jsgraph()->graph()->CloneNode(node);
221 if (FLAG_trace_turbo_escape) {
222 PrintF(" to #%d\n", node->id());
223 }
224 multiple_users = false;
225 }
226 NodeProperties::ReplaceFrameStateInput(node, 0, ret);
227 }
228 }
229 return clone;
230 }
231
232
233 Node* EscapeAnalysisReducer::ReduceStateValueInputs(Node* node, Node* effect,
234 bool multiple_users) {
235 if (FLAG_trace_turbo_escape) {
236 PrintF("Reducing StateValue #%d\n", node->id());
237 }
238 DCHECK(node->opcode() == IrOpcode::kStateValues);
239 DCHECK_NOT_NULL(effect);
240 Node* clone = nullptr;
241 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
242 if (Node* ret = ReduceStateValueInput(node, i, effect, multiple_users)) {
243 node = ret;
244 DCHECK_NULL(clone);
245 clone = ret;
246 multiple_users = false;
247 }
248 }
249 return clone;
250 }
251
252
253 // Return the clone if it duplicated the node, and null otherwise.
Jarin 2016/01/05 12:51:19 Maybe you want to add the same comment to the meth
sigurds 2016/01/05 13:08:57 Done.
254 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index,
255 Node* effect,
256 bool multiple_users) {
257 Node* input = NodeProperties::GetValueInput(node, node_index);
258 if (FLAG_trace_turbo_escape) {
259 PrintF("Reducing State Input #%d (%s)\n", input->id(),
260 input->op()->mnemonic());
261 }
262 Node* clone = nullptr;
263 if (input->opcode() == IrOpcode::kFinishRegion ||
264 input->opcode() == IrOpcode::kAllocate) {
265 if (escape_analysis()->IsVirtual(input)) {
266 if (Node* object_state =
267 escape_analysis()->GetOrCreateObjectState(effect, input)) {
268 if (node->UseCount() > 1 || multiple_users) {
269 if (FLAG_trace_turbo_escape) {
270 PrintF("Cloning #%d", node->id());
271 }
272 node = clone = jsgraph()->graph()->CloneNode(node);
273 if (FLAG_trace_turbo_escape) {
274 PrintF(" to #%d\n", node->id());
275 }
276 }
277 NodeProperties::ReplaceValueInput(node, object_state, node_index);
278 if (FLAG_trace_turbo_escape) {
279 PrintF("Replaced state #%d input #%d with object state #%d\n",
280 node->id(), input->id(), object_state->id());
281 }
282 } else {
283 if (FLAG_trace_turbo_escape) {
284 PrintF("No object state replacement available.\n");
285 }
286 }
287 }
288 }
289 return clone;
290 }
291
200 } // namespace compiler 292 } // namespace compiler
201 } // namespace internal 293 } // namespace internal
202 } // namespace v8 294 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698