|  | // Copyright (c) 2018, 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"; | 
|  |  | 
|  | // Class hierarchy on an abstract class | 
|  | // that defines a "next" structure. | 
|  |  | 
|  | abstract class A { | 
|  | A? next; | 
|  | } | 
|  |  | 
|  | class B extends A { | 
|  | B(A? n) { | 
|  | this.next = n; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Method that counts length of list. | 
|  | // With only Bs, the getter can be | 
|  | // inlined without check class. | 
|  | int countMe(A? i) { | 
|  | int x = 0; | 
|  | while (i != null) { | 
|  | A? next = i.next; | 
|  | x++; | 
|  | i = next; | 
|  | } | 
|  | return x; | 
|  | } | 
|  |  | 
|  | int doitHot(A? a) { | 
|  | // Warm up the JIT. | 
|  | int d = 0; | 
|  | for (int i = 0; i < 1000; i++) { | 
|  | d += countMe(a); | 
|  | } | 
|  | return d; | 
|  | } | 
|  |  | 
|  | // Nasty class that overrides the getter. | 
|  | class C extends A { | 
|  | C(A? n) { | 
|  | this.next = n; | 
|  | } | 
|  | // New override. | 
|  | A? get next => null; | 
|  | } | 
|  |  | 
|  | int bringInC(A? a) { | 
|  | // Introduce C to compiler. | 
|  | a = new C(a); | 
|  | return doitHot(a); | 
|  | } | 
|  |  | 
|  | main() { | 
|  | // Make a list with just Bs. | 
|  | A? a = null; | 
|  | for (int i = 0; i < 1000; i++) { | 
|  | a = new B(a); | 
|  | } | 
|  |  | 
|  | Expect.equals(1000 * 1000, doitHot(a)); | 
|  | Expect.equals(1000, bringInC(a)); | 
|  | } |