| // 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"; |
| |
| // We want to run each test with and without inlining of the target functions. |
| // We accomplish this by using VM options in the yes-inlining variant to set the |
| // "enable_inlining" constant variable to true. This maximizes code sharing |
| // between the two variants, which are otherwise identical. |
| const pragma NeverInline = const bool.fromEnvironment("enable_inlining") |
| ? null |
| : pragma('vm:never-inline'); |
| |
| // In AOT we need to force some functions to be inlined since we only build the |
| // unchecked entry-point when inlining. |
| const pragma AlwaysInline = const bool.fromEnvironment("enable_inlining") |
| ? pragma('vm:prefer-inline') |
| : null; |
| |
| // All these tests can be run in test mode or in benchmark mode. In benchmark |
| // mode, there is introspection is omitted and the tests runs for many more |
| // iterations. |
| const bool benchmarkMode = const bool.fromEnvironment("benchmark_mode"); |
| |
| class TargetCalls { |
| int checked = 0; |
| int unchecked = 0; |
| |
| // Leave a little room for some cases which always use the checked entry, like |
| // lazy compile stub. |
| static const int wiggle = 10; |
| |
| void expectChecked(int iterations) { |
| print("$checked, $unchecked"); |
| Expect.isTrue(checked >= iterations - wiggle && unchecked == 0); |
| } |
| |
| void expectUnchecked(int iterations) { |
| print("$checked, $unchecked"); |
| Expect.isTrue(checked <= wiggle && unchecked >= iterations - wiggle); |
| } |
| } |
| |
| TargetCalls entryPoint = TargetCalls(); |
| TargetCalls tearoffEntryPoint = TargetCalls(); |
| |
| _validateHelper(int ep, TargetCalls calls) { |
| calls ??= entryPoint; |
| |
| if (ep < 0 || ep > 2) { |
| Expect.fail("ERROR: invalid entry-point ($ep) passed by VM."); |
| } |
| if (ep == 0) { |
| calls.checked++; |
| } else { |
| calls.unchecked++; |
| } |
| } |
| |
| void _validateFn(String _, int ep) => _validateHelper(ep, null); |
| |
| // Invocation of tearoffs go through a tearoff wrapper. We want to independently |
| // test which entrypoint was used for the tearoff wrapper vs. which was used for |
| // actual target. |
| _validateTearoffFn(String name, int ep) { |
| _validateHelper( |
| ep, name.endsWith("#tearoff") ? tearoffEntryPoint : entryPoint); |
| } |
| |
| @pragma("vm:entry-point", "get") |
| const validate = benchmarkMode ? null : _validateFn; |
| |
| @pragma("vm:entry-point", "get") |
| const validateTearoff = benchmarkMode ? null : _validateTearoffFn; |