Migrate language_2/propagate to NNBD.

Change-Id: I43ab07aebe7918a1265f8dc594b759e85c08e862
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150264
Auto-Submit: Bob Nystrom <rnystrom@google.com>
Commit-Queue: Erik Ernst <eernst@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
This commit is contained in:
Robert Nystrom 2020-06-08 23:36:46 +00:00 committed by commit-bot@chromium.org
parent af4a9c8d42
commit 5fff7d61e1
8 changed files with 270 additions and 0 deletions

View file

@ -0,0 +1,27 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
main() {
Expect.equals("str", foo("str"));
}
foo(y) {
dynamic x = 3;
for (int i = 0; i < 2; i++) {
// Make sure that we don't think that the type of x is necessarily
// a number and optimize the x + y expression based on that. The
// value of x changes later...
if (i == 1) return bar(x + y);
x = new A();
}
}
bar(t) => t;
class A {
A() {}
operator +(x) => x;
}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Check that type of the AssertAssignable is recomputed correctly.
// VMOptions=--optimization-counter-threshold=10 --no-use-osr
import "package:expect/expect.dart";
class A {
final p;
final _b;
b() {
try {
return _b;
} catch (e) {}
}
A(this.p, this._b);
}
class B extends A {
B(p, b) : super(p, b);
}
bar(v) {
for (var x = v; x != null; x = x.p) {
if (x.b()) {
return x;
}
}
return null;
}
foo(v) {
A x = bar(v);
return x != null;
}
main() {
final a = new A(new B(new A("haha", true), false), false);
for (var i = 0; i < 20; i++) {
Expect.isTrue(foo(a));
}
Expect.isTrue(foo(a));
}

View file

@ -0,0 +1,28 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Check that phi type computation in the Dart2Js compiler does the
// correct thing.
import "package:expect/expect.dart";
bar() => 'foo';
main() {
Expect.throws(foo1);
Expect.throws(foo2);
}
foo1() {
var a = bar();
for (;; a = 1 + a) {
if (a != 'foo') return;
}
}
foo2() {
var a = bar();
for (;; a = 1 + a) {
if (a != 'foo') break;
}
}

View file

@ -0,0 +1,21 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:expect/expect.dart';
foo(x) => x;
check(y) {
Expect.equals('foo', y);
}
main() {
var x = foo('foo');
var y = foo(x);
x = 'constant';
check(
y); // 'y' should not propagate here unless reference to 'x' is rewritten
foo(x);
foo(x);
}

View file

@ -0,0 +1,23 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Check that phi type computation in the Dart2Js compiler does the
// correct thing.
import "package:expect/expect.dart";
bar() => 490;
bar2() => 0;
foo(b) {
var x = bar();
var x2 = x;
if (b) x2 = bar2();
var x3 = 9 + x; // Guarantees that x is a number. Dart2js propagated the
// type information back to the phi (for x2).
return x2 + x3;
}
main() {
Expect.equals(499, foo(true));
}

View file

@ -0,0 +1,24 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Regression test for dart2js that used to infinite loop on
// speculatively propagating types.
class Bar {
noSuchMethod(e) => null;
}
main() {
var d = new Bar();
while (false) {
// [input] will change from indexable to unknown: the use line 20
// changes its decision because [a2] changes its type from unknown to
// null.
var input = ((x) {})(null);
var p2 = input.keys.firstWhere(null);
var a2 = input.keys.firstWhere(null);
print(input[a2] == p2);
}
}

View file

@ -0,0 +1,57 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Regression test for dart2js that used to generate wrong code for
// it. The bug happened in the SSA type propagation.
class A {
next() => new B();
doIt() => null;
bool get isEmpty => false;
foo() => 42;
bar() => 54;
}
bool entered = false;
class B extends A {
foo() => 54;
doIt() => new A();
bool get isEmpty => true;
bar() => entered = true;
}
// (1) At initialization phase of the type propagation, [a] would be
// marked as [exact A].
// (2) Will make the loop phi [b] typed [null, exact A].
// (3) Will create a [HTypeKnown] [exact A] for [b].
// (4) Will create a [HTypeKnown] [exact A] for [b] and update users
// of [b] to use this [HTypeKnown] instead.
// (5) [a] will be updated to [subclass A].
// (6) Will change the [HTypeKnown] of [b] from [exact A] to [subclass A].
// (7) Receiver is [subclass A] and it will refine it to
// [subclass A]. We used to wrongly assume there was
// no need to update the [HTypeKnown] created in (3).
// (8) Consider that bar is called on an [exact A] (the [HTypeKnown]
// created in (3)) and remove the call because it does not have
// any side effects.
main() {
var a = new A();
for (var i in [42]) {
a = a.next();
}
// (1, 5)
var b = a;
while (b.isEmpty) {
// (4, 6)
b.foo(); // (3, 7)
b.bar(); // (8)
b = b.doIt(); // (2)
}
if (!entered) throw 'Test failed';
}

View file

@ -0,0 +1,43 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// dart2js used to have an infinite loop in its type propagation
// algorithm due to types becoming broader instead of narrower.
import "package:expect/expect.dart";
class A {
resolveSend(node) {
if (node == null) {
return [new B()][0];
} else {
return [new B(), new A()][1];
}
}
visitSend(node) {
var target = resolveSend(node);
if (false) {
if (false) {
target = target.getter;
if (false) {
target = new Object();
}
}
}
return true ? target : null;
}
}
var a = 43;
class B {
var getter = a == 42 ? new A() : null;
}
main() {
Expect.isTrue(new A().visitSend(new A()) is A);
Expect.isTrue(new A().visitSend(null) is B);
}