| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.cps_ir.bounds_checker; | 5 library dart2js.cps_ir.bounds_checker; |
| 6 | 6 |
| 7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
| 8 import 'optimizers.dart' show Pass; | 8 import 'optimizers.dart' show Pass; |
| 9 import 'octagon.dart'; | 9 import 'octagon.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 Continuation cont = node.continuation.definition; | 391 Continuation cont = node.continuation.definition; |
| 392 if (isStrongLoopPass) { | 392 if (isStrongLoopPass) { |
| 393 for (int i = 0; i < node.arguments.length; ++i) { | 393 for (int i = 0; i < node.arguments.length; ++i) { |
| 394 Parameter param = cont.parameters[i]; | 394 Parameter param = cont.parameters[i]; |
| 395 if (!isInt(param)) continue; | 395 if (!isInt(param)) continue; |
| 396 Primitive initialValue = node.arguments[i].definition; | 396 Primitive initialValue = node.arguments[i].definition; |
| 397 SignedVariable initialVariable = getValue(initialValue); | 397 SignedVariable initialVariable = getValue(initialValue); |
| 398 Monotonicity mono = monotonicity[param]; | 398 Monotonicity mono = monotonicity[param]; |
| 399 if (mono == null) { | 399 if (mono == null) { |
| 400 // Value never changes. This is extremely uncommon. | 400 // Value never changes. This is extremely uncommon. |
| 401 initialValue.substituteFor(param); | 401 param.replaceUsesWith(initialValue); |
| 402 } else if (mono == Monotonicity.Increasing) { | 402 } else if (mono == Monotonicity.Increasing) { |
| 403 makeGreaterThanOrEqual(getValue(param), initialVariable); | 403 makeGreaterThanOrEqual(getValue(param), initialVariable); |
| 404 } else if (mono == Monotonicity.Decreasing) { | 404 } else if (mono == Monotonicity.Decreasing) { |
| 405 makeLessThanOrEqual(getValue(param), initialVariable); | 405 makeLessThanOrEqual(getValue(param), initialVariable); |
| 406 } | 406 } |
| 407 } | 407 } |
| 408 } | 408 } |
| 409 if (loopEffects.loopChangesLength(cont)) { | 409 if (loopEffects.loopChangesLength(cont)) { |
| 410 currentEffectNumber = effectNumberAt[cont] = makeNewEffect(); | 410 currentEffectNumber = effectNumberAt[cont] = makeNewEffect(); |
| 411 } | 411 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 int effect = effectNumberAt[cont]; | 461 int effect = effectNumberAt[cont]; |
| 462 if (effect == null) { | 462 if (effect == null) { |
| 463 effectNumberAt[cont] = currentEffectNumber; | 463 effectNumberAt[cont] = currentEffectNumber; |
| 464 } else if (effect != currentEffectNumber && effect != NEW_EFFECT) { | 464 } else if (effect != currentEffectNumber && effect != NEW_EFFECT) { |
| 465 effectNumberAt[cont] = NEW_EFFECT; | 465 effectNumberAt[cont] = NEW_EFFECT; |
| 466 } | 466 } |
| 467 // TODO(asgerf): Compute join for parameters to increase precision? | 467 // TODO(asgerf): Compute join for parameters to increase precision? |
| 468 } | 468 } |
| 469 } | 469 } |
| 470 | 470 |
| 471 // ---------------- CALL EXPRESSIONS -------------------- | 471 // ---------------- PRIMITIVES -------------------- |
| 472 | 472 |
| 473 @override | 473 @override |
| 474 void visitInvokeMethod(InvokeMethod node) { | 474 void visitInvokeMethod(InvokeMethod node) { |
| 475 // TODO(asgerf): What we really need is a "changes length" side effect flag. | 475 // TODO(asgerf): What we really need is a "changes length" side effect flag. |
| 476 if (world | 476 if (world |
| 477 .getSideEffectsOfSelector(node.selector, node.mask) | 477 .getSideEffectsOfSelector(node.selector, node.mask) |
| 478 .changesIndex()) { | 478 .changesIndex()) { |
| 479 currentEffectNumber = makeNewEffect(); | 479 currentEffectNumber = makeNewEffect(); |
| 480 } | 480 } |
| 481 push(node.continuation.definition); | |
| 482 } | 481 } |
| 483 | 482 |
| 484 @override | 483 @override |
| 485 void visitInvokeStatic(InvokeStatic node) { | 484 void visitInvokeStatic(InvokeStatic node) { |
| 486 if (world.getSideEffectsOfElement(node.target).changesIndex()) { | 485 if (world.getSideEffectsOfElement(node.target).changesIndex()) { |
| 487 currentEffectNumber = makeNewEffect(); | 486 currentEffectNumber = makeNewEffect(); |
| 488 } | 487 } |
| 489 push(node.continuation.definition); | |
| 490 } | 488 } |
| 491 | 489 |
| 492 @override | 490 @override |
| 493 void visitInvokeMethodDirectly(InvokeMethodDirectly node) { | 491 void visitInvokeMethodDirectly(InvokeMethodDirectly node) { |
| 494 FunctionElement target = node.target; | 492 FunctionElement target = node.target; |
| 495 if (target is ConstructorBodyElement) { | 493 if (target is ConstructorBodyElement) { |
| 496 ConstructorBodyElement body = target; | 494 ConstructorBodyElement body = target; |
| 497 target = body.constructor; | 495 target = body.constructor; |
| 498 } | 496 } |
| 499 if (world.getSideEffectsOfElement(target).changesIndex()) { | 497 if (world.getSideEffectsOfElement(target).changesIndex()) { |
| 500 currentEffectNumber = makeNewEffect(); | 498 currentEffectNumber = makeNewEffect(); |
| 501 } | 499 } |
| 502 push(node.continuation.definition); | |
| 503 } | 500 } |
| 504 | 501 |
| 505 @override | 502 @override |
| 506 void visitInvokeConstructor(InvokeConstructor node) { | 503 void visitInvokeConstructor(InvokeConstructor node) { |
| 507 if (world.getSideEffectsOfElement(node.target).changesIndex()) { | 504 if (world.getSideEffectsOfElement(node.target).changesIndex()) { |
| 508 currentEffectNumber = makeNewEffect(); | 505 currentEffectNumber = makeNewEffect(); |
| 509 } | 506 } |
| 510 push(node.continuation.definition); | |
| 511 } | 507 } |
| 512 | 508 |
| 513 @override | 509 @override |
| 514 void visitTypeCast(TypeCast node) { | 510 void visitTypeCast(TypeCast node) { |
| 515 push(node.continuation.definition); | |
| 516 } | 511 } |
| 517 | 512 |
| 518 @override | 513 @override |
| 519 void visitGetLazyStatic(GetLazyStatic node) { | 514 void visitGetLazyStatic(GetLazyStatic node) { |
| 520 // TODO(asgerf): How do we get the side effects of a lazy field initializer? | 515 // TODO(asgerf): How do we get the side effects of a lazy field initializer? |
| 521 currentEffectNumber = makeNewEffect(); | 516 currentEffectNumber = makeNewEffect(); |
| 522 push(node.continuation.definition); | |
| 523 } | 517 } |
| 524 | 518 |
| 525 @override | 519 @override |
| 526 void visitForeignCode(ForeignCode node) { | 520 void visitForeignCode(ForeignCode node) { |
| 527 if (node.nativeBehavior.sideEffects.changesIndex()) { | 521 if (node.nativeBehavior.sideEffects.changesIndex()) { |
| 528 currentEffectNumber = makeNewEffect(); | 522 currentEffectNumber = makeNewEffect(); |
| 529 } | 523 } |
| 530 push(node.continuation.definition); | |
| 531 } | 524 } |
| 532 | 525 |
| 533 @override | 526 @override |
| 534 void visitAwait(Await node) { | 527 void visitAwait(Await node) { |
| 535 currentEffectNumber = makeNewEffect(); | 528 currentEffectNumber = makeNewEffect(); |
| 536 push(node.continuation.definition); | |
| 537 } | 529 } |
| 538 | 530 |
| 539 @override | 531 @override |
| 540 void visitYield(Yield node) { | 532 void visitYield(Yield node) { |
| 541 currentEffectNumber = makeNewEffect(); | 533 currentEffectNumber = makeNewEffect(); |
| 542 push(node.continuation.definition); | |
| 543 } | 534 } |
| 544 | 535 |
| 545 // ---------------- PRIMITIVES -------------------- | |
| 546 | |
| 547 @override | 536 @override |
| 548 void visitApplyBuiltinMethod(ApplyBuiltinMethod node) { | 537 void visitApplyBuiltinMethod(ApplyBuiltinMethod node) { |
| 549 Primitive receiver = node.receiver.definition; | 538 Primitive receiver = node.receiver.definition; |
| 550 int effectBefore = currentEffectNumber; | 539 int effectBefore = currentEffectNumber; |
| 551 currentEffectNumber = makeNewEffect(); | 540 currentEffectNumber = makeNewEffect(); |
| 552 int effectAfter = currentEffectNumber; | 541 int effectAfter = currentEffectNumber; |
| 553 SignedVariable lengthBefore = getLength(receiver, effectBefore); | 542 SignedVariable lengthBefore = getLength(receiver, effectBefore); |
| 554 SignedVariable lengthAfter = getLength(receiver, effectAfter); | 543 SignedVariable lengthAfter = getLength(receiver, effectAfter); |
| 555 switch (node.method) { | 544 switch (node.method) { |
| 556 case BuiltinMethod.Push: | 545 case BuiltinMethod.Push: |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 } | 589 } |
| 601 return node.body; | 590 return node.body; |
| 602 } | 591 } |
| 603 } | 592 } |
| 604 | 593 |
| 605 /// Lattice representing the known (weak) monotonicity of a loop variable. | 594 /// Lattice representing the known (weak) monotonicity of a loop variable. |
| 606 /// | 595 /// |
| 607 /// The lattice bottom is represented by `null` and represents the case where | 596 /// The lattice bottom is represented by `null` and represents the case where |
| 608 /// the loop variable never changes value during the loop. | 597 /// the loop variable never changes value during the loop. |
| 609 enum Monotonicity { NotMonotone, Increasing, Decreasing, } | 598 enum Monotonicity { NotMonotone, Increasing, Decreasing, } |
| OLD | NEW |