|  | // Copyright (c) 2011, 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. | 
|  |  | 
|  | // @dart = 2.7 | 
|  |  | 
|  | import 'package:expect/expect.dart'; | 
|  | import 'package:async_helper/async_helper.dart'; | 
|  | import '../helpers/compiler_helper.dart'; | 
|  |  | 
|  | const String TEST_ONE = r""" | 
|  | void foo(bar) { | 
|  | for (int i = 0; i < 1; i++) { | 
|  | print(1 + bar); | 
|  | print(1 + bar); | 
|  | } | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that modulo does not have any side effect and we are | 
|  | // GVN'ing the length of [:list:]. | 
|  | const String TEST_TWO = r""" | 
|  | void foo(a) { | 
|  | var list = new List<int>(); | 
|  | list[0] = list[0 % a]; | 
|  | list[1] = list[1 % a]; | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that is checks get GVN'ed. | 
|  | const String TEST_THREE = r""" | 
|  | void foo(a) { | 
|  | print(42);  // Make sure numbers are used. | 
|  | print(a is num); | 
|  | print(a is num); | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that instructions that don't have a builtin equivalent can | 
|  | // still be GVN'ed. | 
|  | const String TEST_FOUR = r""" | 
|  | void foo(a) { | 
|  | print(1 >> a); | 
|  | print(1 >> a); | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that [HCheck] instructions do not prevent GVN. | 
|  | const String TEST_FIVE = r""" | 
|  | class A { | 
|  | final int foo; | 
|  | A(this.foo); | 
|  | } | 
|  |  | 
|  | class B {} | 
|  |  | 
|  | main() { | 
|  | helper([new A(32), new A(21), new B(), null][0]); | 
|  | } | 
|  |  | 
|  | helper(A a) { | 
|  | var b = a.foo; | 
|  | var c = a.foo; | 
|  | if (a is B) { | 
|  | c = (a as dynamic).foo; | 
|  | } | 
|  | return b + c; | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that a gvn'able instruction in the loop header gets hoisted. | 
|  | const String TEST_SIX = r""" | 
|  | class A { | 
|  | @pragma('dart2js:noElision') | 
|  | final field = 54; | 
|  | } | 
|  |  | 
|  | main() { | 
|  | dynamic a = new A(); | 
|  | while (a.field == 54) { a.field = 42; } | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that a gvn'able instruction that may throw in the loop header | 
|  | // gets hoisted. | 
|  | const String TEST_SEVEN = r""" | 
|  | class A { | 
|  | final field; | 
|  | A() : field = null; | 
|  | A.bar() : field = 42; | 
|  | } | 
|  |  | 
|  | main() { | 
|  | dynamic a = new A(); | 
|  | dynamic b = new A.bar(); | 
|  | while (a.field == 54) { a.field = 42; b.field = 42; } | 
|  | } | 
|  | """; | 
|  |  | 
|  | // Check that a check in a loop header gets hoisted. | 
|  | const String TEST_EIGHT = r""" | 
|  | class A { | 
|  | final field; | 
|  | A() : field = null; | 
|  | A.bar() : field = 42; | 
|  | } | 
|  |  | 
|  | main() { | 
|  | dynamic a = new A(); | 
|  | dynamic b = new A.bar(); | 
|  | for (int i = 0; i < a.field; i++) { a.field = 42; b.field = 42; } | 
|  | } | 
|  | """; | 
|  |  | 
|  | main() { | 
|  | asyncTest(() async { | 
|  | await compile(TEST_ONE, entry: 'foo', check: (String generated) { | 
|  | RegExp regexp = RegExp(r"1 \+ [a-z]+"); | 
|  | checkNumberOfMatches(regexp.allMatches(generated).iterator, 1); | 
|  | }); | 
|  | await compile(TEST_TWO, entry: 'foo', check: (String generated) { | 
|  | checkNumberOfMatches(RegExp("length").allMatches(generated).iterator, 1); | 
|  | }); | 
|  | await compile(TEST_THREE, entry: 'foo', check: (String generated) { | 
|  | checkNumberOfMatches(RegExp("number").allMatches(generated).iterator, 1); | 
|  | }); | 
|  | await compile(TEST_FOUR, entry: 'foo', check: (String generated) { | 
|  | checkNumberOfMatches(RegExp("shr").allMatches(generated).iterator, 1); | 
|  | }); | 
|  |  | 
|  | await compileAll(TEST_FIVE).then((generated) { | 
|  | checkNumberOfMatches(RegExp(r"\.foo;").allMatches(generated).iterator, 1); | 
|  | checkNumberOfMatches( | 
|  | RegExp(r"get\$foo\(").allMatches(generated).iterator, 0); | 
|  | }); | 
|  | await compileAll(TEST_SIX).then((generated) { | 
|  | Expect.isTrue(generated.contains('for (t1 = a.field === 54; t1;)')); | 
|  | }); | 
|  | await compileAll(TEST_SEVEN).then((generated) { | 
|  | Expect.isTrue(generated.contains('for (t1 = a.field === 54; t1;)')); | 
|  | }); | 
|  | await compileAll(TEST_EIGHT).then((generated) { | 
|  | Expect.isTrue(generated.contains('for (; i < t1; ++i)')); | 
|  | }); | 
|  | }); | 
|  | } |