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 #include "src/compiler/escape-analysis.h" | 5 #include "src/compiler/escape-analysis.h" |
6 #include "src/bit-vector.h" | 6 #include "src/bit-vector.h" |
7 #include "src/compiler/escape-analysis-reducer.h" | 7 #include "src/compiler/escape-analysis-reducer.h" |
8 #include "src/compiler/graph-visualizer.h" | 8 #include "src/compiler/graph-visualizer.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 control); | 112 control); |
113 } | 113 } |
114 | 114 |
115 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) { | 115 Node* Return(Node* value, Node* effect = nullptr, Node* control = nullptr) { |
116 if (!effect) { | 116 if (!effect) { |
117 effect = effect_; | 117 effect = effect_; |
118 } | 118 } |
119 if (!control) { | 119 if (!control) { |
120 control = control_; | 120 control = control_; |
121 } | 121 } |
122 Node* zero = graph()->NewNode(common()->Int32Constant(0)); | 122 return control_ = |
123 return control_ = graph()->NewNode(common()->Return(), zero, value, effect, | 123 graph()->NewNode(common()->Return(), value, effect, control); |
124 control); | |
125 } | 124 } |
126 | 125 |
127 void EndGraph() { | 126 void EndGraph() { |
128 for (Edge edge : graph()->end()->input_edges()) { | 127 for (Edge edge : graph()->end()->input_edges()) { |
129 if (NodeProperties::IsControlEdge(edge)) { | 128 if (NodeProperties::IsControlEdge(edge)) { |
130 edge.UpdateTo(control_); | 129 edge.UpdateTo(control_); |
131 } | 130 } |
132 } | 131 } |
133 } | 132 } |
134 | 133 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 Node* result = Return(load); | 217 Node* result = Return(load); |
219 EndGraph(); | 218 EndGraph(); |
220 | 219 |
221 Analysis(); | 220 Analysis(); |
222 | 221 |
223 ExpectVirtual(allocation); | 222 ExpectVirtual(allocation); |
224 ExpectReplacement(load, object1); | 223 ExpectReplacement(load, object1); |
225 | 224 |
226 Transformation(); | 225 Transformation(); |
227 | 226 |
228 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 227 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
229 } | 228 } |
230 | 229 |
231 | 230 |
232 TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) { | 231 TEST_F(EscapeAnalysisTest, StraightNonEscapeNonConstStore) { |
233 Node* object1 = Constant(1); | 232 Node* object1 = Constant(1); |
234 Node* object2 = Constant(2); | 233 Node* object2 = Constant(2); |
235 BeginRegion(); | 234 BeginRegion(); |
236 Node* allocation = Allocate(Constant(kPointerSize)); | 235 Node* allocation = Allocate(Constant(kPointerSize)); |
237 Store(FieldAccessAtIndex(0), allocation, object1); | 236 Store(FieldAccessAtIndex(0), allocation, object1); |
238 Node* index = | 237 Node* index = |
239 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), | 238 graph()->NewNode(common()->Select(MachineRepresentation::kTagged), |
240 object1, object2, control()); | 239 object1, object2, control()); |
241 StoreElement(MakeElementAccess(0), allocation, index, object1); | 240 StoreElement(MakeElementAccess(0), allocation, index, object1); |
242 Node* finish = FinishRegion(allocation); | 241 Node* finish = FinishRegion(allocation); |
243 Node* load = Load(FieldAccessAtIndex(0), finish); | 242 Node* load = Load(FieldAccessAtIndex(0), finish); |
244 Node* result = Return(load); | 243 Node* result = Return(load); |
245 EndGraph(); | 244 EndGraph(); |
246 | 245 |
247 Analysis(); | 246 Analysis(); |
248 | 247 |
249 ExpectEscaped(allocation); | 248 ExpectEscaped(allocation); |
250 ExpectReplacement(load, nullptr); | 249 ExpectReplacement(load, nullptr); |
251 | 250 |
252 Transformation(); | 251 Transformation(); |
253 | 252 |
254 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 1)); | 253 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0)); |
255 } | 254 } |
256 | 255 |
257 | 256 |
258 TEST_F(EscapeAnalysisTest, StraightEscape) { | 257 TEST_F(EscapeAnalysisTest, StraightEscape) { |
259 Node* object1 = Constant(1); | 258 Node* object1 = Constant(1); |
260 BeginRegion(); | 259 BeginRegion(); |
261 Node* allocation = Allocate(Constant(kPointerSize)); | 260 Node* allocation = Allocate(Constant(kPointerSize)); |
262 Store(FieldAccessAtIndex(0), allocation, object1); | 261 Store(FieldAccessAtIndex(0), allocation, object1); |
263 Node* finish = FinishRegion(allocation); | 262 Node* finish = FinishRegion(allocation); |
264 Node* load = Load(FieldAccessAtIndex(0), finish); | 263 Node* load = Load(FieldAccessAtIndex(0), finish); |
265 Node* result = Return(allocation); | 264 Node* result = Return(allocation); |
266 EndGraph(); | 265 EndGraph(); |
267 graph()->end()->AppendInput(zone(), load); | 266 graph()->end()->AppendInput(zone(), load); |
268 | 267 |
269 Analysis(); | 268 Analysis(); |
270 | 269 |
271 ExpectEscaped(allocation); | 270 ExpectEscaped(allocation); |
272 ExpectReplacement(load, object1); | 271 ExpectReplacement(load, object1); |
273 | 272 |
274 Transformation(); | 273 Transformation(); |
275 | 274 |
276 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 1)); | 275 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); |
277 } | 276 } |
278 | 277 |
279 | 278 |
280 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { | 279 TEST_F(EscapeAnalysisTest, StoreLoadEscape) { |
281 Node* object1 = Constant(1); | 280 Node* object1 = Constant(1); |
282 | 281 |
283 BeginRegion(); | 282 BeginRegion(); |
284 Node* allocation1 = Allocate(Constant(kPointerSize)); | 283 Node* allocation1 = Allocate(Constant(kPointerSize)); |
285 Store(FieldAccessAtIndex(0), allocation1, object1); | 284 Store(FieldAccessAtIndex(0), allocation1, object1); |
286 Node* finish1 = FinishRegion(allocation1); | 285 Node* finish1 = FinishRegion(allocation1); |
287 | 286 |
288 BeginRegion(); | 287 BeginRegion(); |
289 Node* allocation2 = Allocate(Constant(kPointerSize)); | 288 Node* allocation2 = Allocate(Constant(kPointerSize)); |
290 Store(FieldAccessAtIndex(0), allocation2, finish1); | 289 Store(FieldAccessAtIndex(0), allocation2, finish1); |
291 Node* finish2 = FinishRegion(allocation2); | 290 Node* finish2 = FinishRegion(allocation2); |
292 | 291 |
293 Node* load = Load(FieldAccessAtIndex(0), finish2); | 292 Node* load = Load(FieldAccessAtIndex(0), finish2); |
294 Node* result = Return(load); | 293 Node* result = Return(load); |
295 EndGraph(); | 294 EndGraph(); |
296 Analysis(); | 295 Analysis(); |
297 | 296 |
298 ExpectEscaped(allocation1); | 297 ExpectEscaped(allocation1); |
299 ExpectVirtual(allocation2); | 298 ExpectVirtual(allocation2); |
300 ExpectReplacement(load, finish1); | 299 ExpectReplacement(load, finish1); |
301 | 300 |
302 Transformation(); | 301 Transformation(); |
303 | 302 |
304 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 1)); | 303 ASSERT_EQ(finish1, NodeProperties::GetValueInput(result, 0)); |
305 } | 304 } |
306 | 305 |
307 | 306 |
308 TEST_F(EscapeAnalysisTest, BranchNonEscape) { | 307 TEST_F(EscapeAnalysisTest, BranchNonEscape) { |
309 Node* object1 = Constant(1); | 308 Node* object1 = Constant(1); |
310 Node* object2 = Constant(2); | 309 Node* object2 = Constant(2); |
311 BeginRegion(); | 310 BeginRegion(); |
312 Node* allocation = Allocate(Constant(kPointerSize)); | 311 Node* allocation = Allocate(Constant(kPointerSize)); |
313 Store(FieldAccessAtIndex(0), allocation, object1); | 312 Store(FieldAccessAtIndex(0), allocation, object1); |
314 Node* finish = FinishRegion(allocation); | 313 Node* finish = FinishRegion(allocation); |
(...skipping 12 matching lines...) Expand all Loading... |
327 graph()->end()->AppendInput(zone(), result); | 326 graph()->end()->AppendInput(zone(), result); |
328 | 327 |
329 Analysis(); | 328 Analysis(); |
330 | 329 |
331 ExpectVirtual(allocation); | 330 ExpectVirtual(allocation); |
332 ExpectReplacementPhi(load, object1, object2); | 331 ExpectReplacementPhi(load, object1, object2); |
333 Node* replacement_phi = escape_analysis()->GetReplacement(load); | 332 Node* replacement_phi = escape_analysis()->GetReplacement(load); |
334 | 333 |
335 Transformation(); | 334 Transformation(); |
336 | 335 |
337 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 1)); | 336 ASSERT_EQ(replacement_phi, NodeProperties::GetValueInput(result, 0)); |
338 } | 337 } |
339 | 338 |
340 | 339 |
341 TEST_F(EscapeAnalysisTest, BranchEscapeOne) { | 340 TEST_F(EscapeAnalysisTest, BranchEscapeOne) { |
342 Node* object1 = Constant(1); | 341 Node* object1 = Constant(1); |
343 Node* object2 = Constant(2); | 342 Node* object2 = Constant(2); |
344 Node* index = graph()->NewNode(common()->Parameter(0), start()); | 343 Node* index = graph()->NewNode(common()->Parameter(0), start()); |
345 BeginRegion(); | 344 BeginRegion(); |
346 Node* allocation = Allocate(Constant(kPointerSize)); | 345 Node* allocation = Allocate(Constant(kPointerSize)); |
347 Store(FieldAccessAtIndex(0), allocation, object1); | 346 Store(FieldAccessAtIndex(0), allocation, object1); |
(...skipping 11 matching lines...) Expand all Loading... |
359 Node* result = Return(load, phi); | 358 Node* result = Return(load, phi); |
360 EndGraph(); | 359 EndGraph(); |
361 | 360 |
362 Analysis(); | 361 Analysis(); |
363 | 362 |
364 ExpectEscaped(allocation); | 363 ExpectEscaped(allocation); |
365 ExpectReplacement(load, nullptr); | 364 ExpectReplacement(load, nullptr); |
366 | 365 |
367 Transformation(); | 366 Transformation(); |
368 | 367 |
369 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 1)); | 368 ASSERT_EQ(load, NodeProperties::GetValueInput(result, 0)); |
370 } | 369 } |
371 | 370 |
372 | 371 |
373 TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) { | 372 TEST_F(EscapeAnalysisTest, BranchEscapeThroughStore) { |
374 Node* object1 = Constant(1); | 373 Node* object1 = Constant(1); |
375 Node* object2 = Constant(2); | 374 Node* object2 = Constant(2); |
376 BeginRegion(); | 375 BeginRegion(); |
377 Node* allocation = Allocate(Constant(kPointerSize)); | 376 Node* allocation = Allocate(Constant(kPointerSize)); |
378 Store(FieldAccessAtIndex(0), allocation, object1); | 377 Store(FieldAccessAtIndex(0), allocation, object1); |
379 FinishRegion(allocation); | 378 FinishRegion(allocation); |
(...skipping 14 matching lines...) Expand all Loading... |
394 graph()->end()->AppendInput(zone(), load); | 393 graph()->end()->AppendInput(zone(), load); |
395 | 394 |
396 Analysis(); | 395 Analysis(); |
397 | 396 |
398 ExpectEscaped(allocation); | 397 ExpectEscaped(allocation); |
399 ExpectEscaped(allocation2); | 398 ExpectEscaped(allocation2); |
400 ExpectReplacement(load, nullptr); | 399 ExpectReplacement(load, nullptr); |
401 | 400 |
402 Transformation(); | 401 Transformation(); |
403 | 402 |
404 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 1)); | 403 ASSERT_EQ(allocation, NodeProperties::GetValueInput(result, 0)); |
405 } | 404 } |
406 | 405 |
407 | 406 |
408 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { | 407 TEST_F(EscapeAnalysisTest, DanglingLoadOrder) { |
409 Node* object1 = Constant(1); | 408 Node* object1 = Constant(1); |
410 Node* object2 = Constant(2); | 409 Node* object2 = Constant(2); |
411 Node* allocation = Allocate(Constant(kPointerSize)); | 410 Node* allocation = Allocate(Constant(kPointerSize)); |
412 Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1); | 411 Node* store1 = Store(FieldAccessAtIndex(0), allocation, object1); |
413 Node* load1 = Load(FieldAccessAtIndex(0), allocation); | 412 Node* load1 = Load(FieldAccessAtIndex(0), allocation); |
414 Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2); | 413 Node* store2 = Store(FieldAccessAtIndex(0), allocation, object2); |
415 Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1); | 414 Node* load2 = Load(FieldAccessAtIndex(0), allocation, store1); |
416 Node* result = Return(load2); | 415 Node* result = Return(load2); |
417 EndGraph(); | 416 EndGraph(); |
418 graph()->end()->AppendInput(zone(), store2); | 417 graph()->end()->AppendInput(zone(), store2); |
419 graph()->end()->AppendInput(zone(), load1); | 418 graph()->end()->AppendInput(zone(), load1); |
420 | 419 |
421 Analysis(); | 420 Analysis(); |
422 | 421 |
423 ExpectVirtual(allocation); | 422 ExpectVirtual(allocation); |
424 ExpectReplacement(load1, object1); | 423 ExpectReplacement(load1, object1); |
425 ExpectReplacement(load2, object1); | 424 ExpectReplacement(load2, object1); |
426 | 425 |
427 Transformation(); | 426 Transformation(); |
428 | 427 |
429 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 428 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
430 } | 429 } |
431 | 430 |
432 | 431 |
433 TEST_F(EscapeAnalysisTest, DeoptReplacement) { | 432 TEST_F(EscapeAnalysisTest, DeoptReplacement) { |
434 Node* object1 = Constant(1); | 433 Node* object1 = Constant(1); |
435 BeginRegion(); | 434 BeginRegion(); |
436 Node* allocation = Allocate(Constant(kPointerSize)); | 435 Node* allocation = Allocate(Constant(kPointerSize)); |
437 Store(FieldAccessAtIndex(0), allocation, object1); | 436 Store(FieldAccessAtIndex(0), allocation, object1); |
438 Node* finish = FinishRegion(allocation); | 437 Node* finish = FinishRegion(allocation); |
439 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); | 438 Node* effect1 = Store(FieldAccessAtIndex(0), allocation, object1, finish); |
(...skipping 15 matching lines...) Expand all Loading... |
455 Node* result = Return(load, effect1, ifTrue); | 454 Node* result = Return(load, effect1, ifTrue); |
456 EndGraph(); | 455 EndGraph(); |
457 graph()->end()->AppendInput(zone(), deopt); | 456 graph()->end()->AppendInput(zone(), deopt); |
458 Analysis(); | 457 Analysis(); |
459 | 458 |
460 ExpectVirtual(allocation); | 459 ExpectVirtual(allocation); |
461 ExpectReplacement(load, object1); | 460 ExpectReplacement(load, object1); |
462 | 461 |
463 Transformation(); | 462 Transformation(); |
464 | 463 |
465 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 464 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
466 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 465 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
467 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 466 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
468 ASSERT_EQ(1, object_state->op()->ValueInputCount()); | 467 ASSERT_EQ(1, object_state->op()->ValueInputCount()); |
469 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 468 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
470 } | 469 } |
471 | 470 |
472 TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) { | 471 TEST_F(EscapeAnalysisTest, DISABLED_DeoptReplacementIdentity) { |
473 Node* object1 = Constant(1); | 472 Node* object1 = Constant(1); |
474 BeginRegion(); | 473 BeginRegion(); |
475 Node* allocation = Allocate(Constant(kPointerSize * 2)); | 474 Node* allocation = Allocate(Constant(kPointerSize * 2)); |
(...skipping 19 matching lines...) Expand all Loading... |
495 Node* result = Return(load, effect1, ifTrue); | 494 Node* result = Return(load, effect1, ifTrue); |
496 EndGraph(); | 495 EndGraph(); |
497 graph()->end()->AppendInput(zone(), deopt); | 496 graph()->end()->AppendInput(zone(), deopt); |
498 Analysis(); | 497 Analysis(); |
499 | 498 |
500 ExpectVirtual(allocation); | 499 ExpectVirtual(allocation); |
501 ExpectReplacement(load, object1); | 500 ExpectReplacement(load, object1); |
502 | 501 |
503 Transformation(); | 502 Transformation(); |
504 | 503 |
505 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 1)); | 504 ASSERT_EQ(object1, NodeProperties::GetValueInput(result, 0)); |
506 | 505 |
507 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); | 506 Node* object_state = NodeProperties::GetValueInput(state_values1, 0); |
508 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); | 507 ASSERT_EQ(object_state->opcode(), IrOpcode::kObjectState); |
509 ASSERT_EQ(2, object_state->op()->ValueInputCount()); | 508 ASSERT_EQ(2, object_state->op()->ValueInputCount()); |
510 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); | 509 ASSERT_EQ(object1, NodeProperties::GetValueInput(object_state, 0)); |
511 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); | 510 ASSERT_EQ(object_state, NodeProperties::GetValueInput(object_state, 1)); |
512 | 511 |
513 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); | 512 Node* object_state2 = NodeProperties::GetValueInput(state_values1, 0); |
514 ASSERT_EQ(object_state, object_state2); | 513 ASSERT_EQ(object_state, object_state2); |
515 } | 514 } |
516 | 515 |
517 } // namespace compiler | 516 } // namespace compiler |
518 } // namespace internal | 517 } // namespace internal |
519 } // namespace v8 | 518 } // namespace v8 |
OLD | NEW |