| // 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. |
| |
| // @dart = 2.9 |
| |
| import "package:expect/expect.dart"; |
| |
| // A class the has a getter also provided by Object |
| // (higher in the class hierarchy) and thus also the |
| // Null class (besides X in the class hierarchy). |
| class X { |
| int hashCode; |
| X() { |
| hashCode = 1; |
| } |
| } |
| |
| // Use this getter on X receiver. |
| int hashMe(X x) { |
| int d = 0; |
| for (int i = 0; i < 10; i++) { |
| d += x.hashCode; |
| } |
| return d; |
| } |
| |
| // Use this getter on Null class receiver. |
| // Only possible value is null. |
| int hashNull(Null x) { |
| int d = 0; |
| for (int i = 0; i < 10; i++) { |
| d += x.hashCode; |
| } |
| return d; |
| } |
| |
| main() { |
| // Warm up the JIT with just an X object. Having a single receiver |
| // of type X with nothing below in the hierarchy that overrides |
| // hashCode could tempt the JIT to inline the getter with CHA |
| // that deopts when X is subclassed in the future. |
| X x = new X(); |
| for (int i = 0; i < 1000; i++) { |
| Expect.equals(10, hashMe(x)); |
| } |
| |
| // However, this is a special case that also works on null |
| // (calling Object's hashCode). So this should not throw an |
| // exception. Had we inlined, this would have hit the null |
| // check and thrown an exception. |
| Expect.notEquals(0, hashMe(null)); |
| |
| // Also warm up the JIT on a direct Null receiver. |
| int d = 0; |
| for (int i = 0; i < 1000; i++) { |
| d += hashNull(null); |
| } |
| Expect.notEquals(0, d); |
| } |