1989edb06e
This CL adds a new target for kernel front-end, vm_precompiler. This is an experimental target for new Dart VM precompiler pipeline which will fully exploit strong mode type system and perform whole-program optimizations. As an example of such whole-program optimization, this CL adds draft implementation of devirtualization of method invocations, which uses single target computed by closed-world class hierarchy analysis. Corresponding null checks (required for correctness) are not generated yet. Issue: https://github.com/dart-lang/sdk/issues/30480 Change-Id: I704cd16843a08f036a188b1188c80ee4dfbeab3b Reviewed-on: https://dart-review.googlesource.com/3402 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
116 lines
3.5 KiB
Dart
116 lines
3.5 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.
|
|
|
|
library kernel.transformations.precompiler;
|
|
|
|
import '../ast.dart'
|
|
show
|
|
DirectMethodInvocation,
|
|
DirectPropertyGet,
|
|
DirectPropertySet,
|
|
Field,
|
|
Library,
|
|
Member,
|
|
MethodInvocation,
|
|
Procedure,
|
|
Program,
|
|
PropertyGet,
|
|
PropertySet,
|
|
TreeNode;
|
|
|
|
import '../core_types.dart' show CoreTypes;
|
|
|
|
import '../class_hierarchy.dart' show ClosedWorldClassHierarchy;
|
|
|
|
import '../visitor.dart' show Transformer;
|
|
|
|
/// Performs whole-program transformations for Dart VM precompiler.
|
|
/// Assumes strong mode and closed world.
|
|
Program transformProgram(CoreTypes coreTypes, Program program) {
|
|
new _DevirtualizationTransformer(program).visitProgram(program);
|
|
return program;
|
|
}
|
|
|
|
/// Transforms instance method invocations into direct using strong mode
|
|
/// types / interface targets and closed-world class hierarchy analysis.
|
|
class _DevirtualizationTransformer extends Transformer {
|
|
/// Toggles tracing (useful for debugging).
|
|
static const _trace = const bool.fromEnvironment('trace.devirtualization');
|
|
|
|
ClosedWorldClassHierarchy _hierarchy;
|
|
|
|
_DevirtualizationTransformer(Program program)
|
|
: _hierarchy = new ClosedWorldClassHierarchy(program) {}
|
|
|
|
@override
|
|
TreeNode visitLibrary(Library node) {
|
|
if (_trace) {
|
|
String external = node.isExternal ? " (external)" : "";
|
|
print("[devirt] Processing library ${node.name}${external}");
|
|
}
|
|
return super.visitLibrary(node);
|
|
}
|
|
|
|
@override
|
|
TreeNode visitMethodInvocation(MethodInvocation node) {
|
|
node = super.visitMethodInvocation(node);
|
|
|
|
Member target = node.interfaceTarget;
|
|
if ((target != null) && (target is! Field)) {
|
|
Member singleTarget =
|
|
_hierarchy.getSingleTargetForInterfaceInvocation(target);
|
|
if (singleTarget != null) {
|
|
if (_trace) {
|
|
print("[devirt] Replacing ${target} with ${singleTarget}");
|
|
}
|
|
// TODO(dartbug.com/30480): add annotation to check for null
|
|
return new DirectMethodInvocation(
|
|
node.receiver, singleTarget as Procedure, node.arguments);
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
TreeNode visitPropertyGet(PropertyGet node) {
|
|
node = super.visitPropertyGet(node);
|
|
|
|
Member target = node.interfaceTarget;
|
|
if (target != null) {
|
|
Member singleTarget =
|
|
_hierarchy.getSingleTargetForInterfaceInvocation(target);
|
|
if (singleTarget != null) {
|
|
if (_trace) {
|
|
print("[devirt] Replacing ${target} with ${singleTarget}");
|
|
}
|
|
// TODO(dartbug.com/30480): add annotation to check for null
|
|
return new DirectPropertyGet(node.receiver, singleTarget);
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
@override
|
|
TreeNode visitPropertySet(PropertySet node) {
|
|
node = super.visitPropertySet(node);
|
|
|
|
Member target = node.interfaceTarget;
|
|
if (target != null) {
|
|
Member singleTarget = _hierarchy
|
|
.getSingleTargetForInterfaceInvocation(target, setter: true);
|
|
if (singleTarget != null) {
|
|
if (_trace) {
|
|
print("[devirt] Replacing ${target} with ${singleTarget}");
|
|
}
|
|
// TODO(dartbug.com/30480): add annotation to check for null
|
|
return new DirectPropertySet(node.receiver, singleTarget, node.value);
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
}
|