Files
sdk/pkg/vm/lib/kernel_front_end.dart
T
Vyacheslav Egorov d117760ba6 [vm/kernel/aot] Skip unnecessary type checks on parameters of instance methods.
This relands 75a9579ea0.

The approach works as follows:

Step 1: Kernel transform. Under the closed world assumption compute the
set of selectors dispatched dynamically, then mark all procedures that don't
match any of those selectors as 'not-dispatched-dynamically'.

Step 2: VM backend. When building IR for a function if this function was
marked as not-dispatched-dynamically then omit type checks for any parameter
that is not marked as generic-covariant-impl, as such arguments are guaranteed
to be checked on the caller side (by front-end).


+------------------------+------------+----------+-----------+--------------+
|       benchmark        |  baseline  |  current |  with opt |  improved by |
+------------------------+------------+----------+-----------+--------------+
| stock_layout_iteration |  2366.3786 |   2724.3 |   2562.75 |  -5.93%      |
| stock_build_iteration  |     3824.3 |   4914.8 |      4681 |  -4.76%      |
+------------------------+------------+----------+-----------+--------------+

* Flutter gallery Instructions size is reduced by 11% (8748720 bytes to 7846368 bytes).
Baseline is at 6196496 bytes.


Alternatively to annotating individual procedures, I considered annotating Program node
with a set of dynamically dispatched selectors. Decoding and passing this information
around proved to be quite cumbersome in the "streaming" world, so I opted for a simpler
approach where all individual procedures are annotated.

Bug: https://github.com/dart-lang/sdk/issues/3179
Change-Id: I2f32a609e3872c74d5ae7bbd97555453aaedf15f
Reviewed-on: https://dart-review.googlesource.com/38125
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Samir Jindel <sjindel@google.com>
2018-02-02 11:43:55 +00:00

83 lines
2.9 KiB
Dart

// Copyright (c) 2017, 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.
/// Defines the VM-specific translation of Dart source code to kernel binaries.
library vm.kernel_front_end;
import 'dart:async';
import 'package:front_end/src/api_prototype/compiler_options.dart'
show CompilerOptions, ErrorHandler;
import 'package:front_end/src/api_prototype/kernel_generator.dart'
show kernelForProgram;
import 'package:front_end/src/api_prototype/compilation_message.dart'
show CompilationMessage, Severity;
import 'package:front_end/src/fasta/severity.dart' show Severity;
import 'package:kernel/ast.dart' show Program;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'transformations/devirtualization.dart' as devirtualization
show transformProgram;
import 'transformations/no_dynamic_invocations_annotator.dart'
as no_dynamic_invocations_annotator show transformProgram;
import 'transformations/type_flow/transformer.dart' as globalTypeFlow
show transformProgram;
// Flag to enable global type flow analysis and related transformations.
const kUseGlobalTypeFlow = const bool.fromEnvironment('use.global.type.flow');
/// Generates a kernel representation of the program whose main library is in
/// the given [source]. Intended for whole program (non-modular) compilation.
///
/// VM-specific replacement of [kernelForProgram].
///
Future<Program> compileToKernel(Uri source, CompilerOptions options,
{bool aot: false}) async {
// Replace error handler to detect if there are compilation errors.
final errorDetector =
new ErrorDetector(previousErrorHandler: options.onError);
options.onError = errorDetector;
final program = await kernelForProgram(source, options);
// Restore error handler (in case 'options' are reused).
options.onError = errorDetector.previousErrorHandler;
// Run global transformations only if program is correct.
if (aot && (program != null) && !errorDetector.hasCompilationErrors) {
_runGlobalTransformations(program, options.strongMode);
}
return program;
}
_runGlobalTransformations(Program program, bool strongMode) {
if (strongMode) {
final coreTypes = new CoreTypes(program);
if (kUseGlobalTypeFlow) {
globalTypeFlow.transformProgram(coreTypes, program);
} else {
devirtualization.transformProgram(coreTypes, program);
no_dynamic_invocations_annotator.transformProgram(coreTypes, program);
}
}
}
class ErrorDetector {
final ErrorHandler previousErrorHandler;
bool hasCompilationErrors = false;
ErrorDetector({this.previousErrorHandler});
void call(CompilationMessage message) {
if ((message.severity != Severity.nit) &&
(message.severity != Severity.warning)) {
hasCompilationErrors = true;
}
previousErrorHandler?.call(message);
}
}