[vm/tfa] Use concrete types for list and map literals and constants.
Change-Id: Ieaeb64501c78e31a38c1aa350a7f112f51bcc7f0
Cq-Include-Trybots: luci.dart.try:vm-kernel-win-release-x64-try, vm-kernel-optcounter-threshold-linux-release-x64-try, vm-kernel-precomp-linux-debug-x64-try, vm-kernel-precomp-linux-release-simarm-try, vm-kernel-precomp-linux-release-simarm64-try, vm-kernel-precomp-linux-release-x64-try, vm-kernel-precomp-win-release-x64-try
Reviewed-on: https://dart-review.googlesource.com/74881
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 38e7c2e..7d2f6bd 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -194,6 +194,12 @@
Component configureComponent(Component component) => component;
String toString() => 'Target($name)';
+
+ Class concreteListLiteralClass(CoreTypes coreTypes) => null;
+ Class concreteConstListLiteralClass(CoreTypes coreTypes) => null;
+
+ Class concreteMapLiteralClass(CoreTypes coreTypes) => null;
+ Class concreteConstMapLiteralClass(CoreTypes coreTypes) => null;
}
class NoneTarget extends Target {
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index ac3dd10..3b86390 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -121,7 +121,8 @@
}
if (useGlobalTypeFlowAnalysis) {
- globalTypeFlow.transformComponent(coreTypes, component, entryPoints);
+ globalTypeFlow.transformComponent(
+ compilerOptions.target, coreTypes, component, entryPoints);
} else {
devirtualization.transformComponent(coreTypes, component);
}
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 0889b46..8b75174 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -20,6 +20,11 @@
class VmTarget extends Target {
final TargetFlags flags;
+ Class _growableList;
+ Class _immutableList;
+ Class _internalLinkedHashMap;
+ Class _immutableMap;
+
VmTarget(this.flags);
@override
@@ -292,4 +297,28 @@
callSiteAnnotator.addRepositoryTo(component);
return super.configureComponent(component);
}
+
+ @override
+ Class concreteListLiteralClass(CoreTypes coreTypes) {
+ return _growableList ??=
+ coreTypes.index.getClass('dart:core', '_GrowableList');
+ }
+
+ @override
+ Class concreteConstListLiteralClass(CoreTypes coreTypes) {
+ return _immutableList ??=
+ coreTypes.index.getClass('dart:core', '_ImmutableList');
+ }
+
+ @override
+ Class concreteMapLiteralClass(CoreTypes coreTypes) {
+ return _internalLinkedHashMap ??=
+ coreTypes.index.getClass('dart:collection', '_InternalLinkedHashMap');
+ }
+
+ @override
+ Class concreteConstMapLiteralClass(CoreTypes coreTypes) {
+ return _immutableMap ??=
+ coreTypes.index.getClass('dart:core', '_ImmutableMap');
+ }
}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index b59c80c..d11f83c 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -9,6 +9,7 @@
import 'dart:core' hide Type;
import 'dart:math' show max;
+import 'package:kernel/target/targets.dart' show Target;
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
import 'package:kernel/class_hierarchy.dart' show ClosedWorldClassHierarchy;
import 'package:kernel/library_index.dart' show LibraryIndex;
@@ -1175,6 +1176,7 @@
}
class TypeFlowAnalysis implements EntryPointsListener, CallHandler {
+ final Target target;
final TypeEnvironment environment;
final LibraryIndex libraryIndex;
final PragmaAnnotationParser annotationMatcher;
@@ -1187,7 +1189,7 @@
final Map<Member, Summary> _summaries = <Member, Summary>{};
final Map<Field, _FieldValue> _fieldValues = <Field, _FieldValue>{};
- TypeFlowAnalysis(Component component, CoreTypes coreTypes,
+ TypeFlowAnalysis(this.target, Component component, CoreTypes coreTypes,
ClosedWorldClassHierarchy hierarchy, this.environment, this.libraryIndex,
{List<String> entryPointsJSONFiles, PragmaAnnotationParser matcher})
: annotationMatcher =
@@ -1195,7 +1197,7 @@
nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
hierarchyCache = new _ClassHierarchyCache(this, hierarchy);
summaryCollector =
- new SummaryCollector(environment, this, nativeCodeOracle);
+ new SummaryCollector(target, environment, this, nativeCodeOracle);
_invocationsCache = new _InvocationsCache(this);
workList = new _WorkList(this);
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 57cbe89..4aaa33d 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -7,6 +7,7 @@
import 'dart:core' hide Type;
+import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
@@ -242,6 +243,7 @@
/// Create a type flow summary for a member from the kernel AST.
class SummaryCollector extends RecursiveVisitor<TypeExpr> {
+ final Target target;
final TypeEnvironment _environment;
final EntryPointsListener _entryPointsListener;
final NativeCodeOracle _nativeCodeOracle;
@@ -255,8 +257,8 @@
Parameter _receiver;
ConstantAllocationCollector constantAllocationCollector;
- SummaryCollector(
- this._environment, this._entryPointsListener, this._nativeCodeOracle) {
+ SummaryCollector(this.target, this._environment, this._entryPointsListener,
+ this._nativeCodeOracle) {
constantAllocationCollector = new ConstantAllocationCollector(this);
}
@@ -690,8 +692,11 @@
@override
TypeExpr visitListLiteral(ListLiteral node) {
node.expressions.forEach(_visit);
- // TODO(alexmarkov): concrete type
- return _staticType(node);
+ Class concreteClass =
+ target.concreteListLiteralClass(_environment.coreTypes);
+ return concreteClass != null
+ ? _entryPointsListener.addAllocatedClass(concreteClass)
+ : _staticType(node);
}
@override
@@ -707,8 +712,11 @@
_visit(entry.key);
_visit(entry.value);
}
- // TODO(alexmarkov): concrete type
- return _staticType(node);
+ Class concreteClass =
+ target.concreteMapLiteralClass(_environment.coreTypes);
+ return concreteClass != null
+ ? _entryPointsListener.addAllocatedClass(concreteClass)
+ : _staticType(node);
}
@override
@@ -1215,8 +1223,8 @@
final TypeEnvironment _environment;
final SummaryCollector _summaryColector;
- CreateAllSummariesVisitor(this._environment)
- : _summaryColector = new SummaryCollector(_environment,
+ CreateAllSummariesVisitor(Target target, this._environment)
+ : _summaryColector = new SummaryCollector(target, _environment,
new EmptyEntryPointsListener(), new NativeCodeOracle(null, null));
@override
@@ -1285,7 +1293,11 @@
for (final Constant entry in constant.entries) {
typeFor(entry);
}
- return new Type.cone(constant.getType(summaryCollector._environment));
+ Class concreteClass = summaryCollector.target
+ .concreteConstListLiteralClass(summaryCollector._environment.coreTypes);
+ return concreteClass != null
+ ? summaryCollector._entryPointsListener.addAllocatedClass(concreteClass)
+ : new Type.cone(constant.getType(summaryCollector._environment));
}
@override
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 6b7f51c..849de1d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -7,6 +7,7 @@
import 'dart:core' hide Type;
+import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -31,8 +32,8 @@
/// Whole-program type flow analysis and transformation.
/// Assumes strong mode and closed world.
-Component transformComponent(
- CoreTypes coreTypes, Component component, List<String> entryPoints,
+Component transformComponent(Target target, CoreTypes coreTypes,
+ Component component, List<String> entryPoints,
[PragmaAnnotationParser matcher]) {
if ((entryPoints == null) || entryPoints.isEmpty) {
throw 'Error: unable to perform global type flow analysis without entry points.';
@@ -46,7 +47,7 @@
if (kDumpAllSummaries) {
Statistics.reset();
- new CreateAllSummariesVisitor(types).visitComponent(component);
+ new CreateAllSummariesVisitor(target, types).visitComponent(component);
Statistics.print("All summaries statistics");
}
@@ -54,7 +55,7 @@
final analysisStopWatch = new Stopwatch()..start();
final typeFlowAnalysis = new TypeFlowAnalysis(
- component, coreTypes, hierarchy, types, libraryIndex,
+ target, component, coreTypes, hierarchy, types, libraryIndex,
entryPointsJSONFiles: entryPoints, matcher: matcher);
Procedure main = component.mainMethod;
diff --git a/pkg/vm/test/common_test_utils.dart b/pkg/vm/test/common_test_utils.dart
index 5960361..0ed04c7 100644
--- a/pkg/vm/test/common_test_utils.dart
+++ b/pkg/vm/test/common_test_utils.dart
@@ -22,14 +22,14 @@
TestingVmTarget(TargetFlags flags) : super(flags);
@override
- bool enableSuperMixins;
+ bool enableSuperMixins = false;
}
Future<Component> compileTestCaseToKernelProgram(Uri sourceUri,
- {bool enableSuperMixins: false}) async {
+ {Target target, bool enableSuperMixins: false}) async {
final platformKernel =
computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
- final target = new TestingVmTarget(new TargetFlags(strongMode: true))
+ target ??= new TestingVmTarget(new TargetFlags(strongMode: true))
..enableSuperMixins = enableSuperMixins;
final options = new CompilerOptions()
..strongMode = true
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index f605342..34c54015 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -12,6 +12,7 @@
import 'package:vm/transformations/type_flow/native_code.dart';
import 'package:vm/transformations/type_flow/summary_collector.dart';
import 'annotation_matcher.dart';
+import 'package:kernel/target/targets.dart';
import '../../common_test_utils.dart';
@@ -21,8 +22,10 @@
final SummaryCollector _summaryCollector;
final StringBuffer _buf = new StringBuffer();
- PrintSummaries(TypeEnvironment environment, CoreTypes coreTypes)
+ PrintSummaries(
+ Target target, TypeEnvironment environment, CoreTypes coreTypes)
: _summaryCollector = new SummaryCollector(
+ target,
environment,
new EmptyEntryPointsListener(),
new NativeCodeOracle(
@@ -44,6 +47,7 @@
}
runTestCase(Uri source) async {
+ final Target target = new TestingVmTarget(new TargetFlags(strongMode: true));
final Component component = await compileTestCaseToKernelProgram(source);
final Library library = component.mainMethod.enclosingLibrary;
final CoreTypes coreTypes = new CoreTypes(component);
@@ -51,7 +55,8 @@
final typeEnvironment =
new TypeEnvironment(coreTypes, new ClassHierarchy(component));
- final actual = new PrintSummaries(typeEnvironment, coreTypes).print(library);
+ final actual =
+ new PrintSummaries(target, typeEnvironment, coreTypes).print(library);
compareResultWithExpectationsFile(source, actual);
}
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index df929f8..887c97a 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -4,6 +4,7 @@
import 'dart:io';
+import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
@@ -17,7 +18,9 @@
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
runTestCase(Uri source) async {
- Component component = await compileTestCaseToKernelProgram(source);
+ final target = new TestingVmTarget(new TargetFlags(strongMode: true));
+ Component component =
+ await compileTestCaseToKernelProgram(source, target: target);
final coreTypes = new CoreTypes(component);
@@ -26,7 +29,7 @@
pkgVmDir + '/lib/transformations/type_flow/entry_points_extra.json',
];
- component = transformComponent(coreTypes, component, entryPoints,
+ component = transformComponent(target, coreTypes, component, entryPoints,
new ExpressionPragmaAnnotationParser(coreTypes));
final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
index ac18742..88d3aa8 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field2.dart.expect
@@ -28,8 +28,8 @@
: self::Q::result = result, super core::Object::•()
;
}
-static method foo1(core::List<self::T1> list) → dynamic {
- [@vm.direct-call.metadata=#lib::T3::run] [@vm.direct-call.metadata=#lib::T1::go??] [@vm.inferred-type.metadata=#lib::T3] [@vm.direct-call.metadata=#lib::Q::result??] [@vm.inferred-type.metadata=!] list.{core::Iterable::map}<self::Q<self::T1>>((self::T1 t1) → self::Q<self::T1> => new self::Q::•<self::T1>(t1)).{core::Iterable::first}.{self::Q::result}.{self::T1::go}().{self::T3::run}();
+static method foo1([@vm.inferred-type.metadata=dart.core::_GrowableList] core::List<self::T1> list) → dynamic {
+ [@vm.direct-call.metadata=#lib::T3::run] [@vm.direct-call.metadata=#lib::T1::go??] [@vm.inferred-type.metadata=#lib::T3] [@vm.direct-call.metadata=#lib::Q::result??] [@vm.direct-call.metadata=dart._internal::ListIterable::first] [@vm.direct-call.metadata=dart.collection::_ListBase&Object&ListMixin::map] [@vm.inferred-type.metadata=dart._internal::MappedListIterable] list.{core::Iterable::map}<self::Q<self::T1>>((self::T1 t1) → self::Q<self::T1> => new self::Q::•<self::T1>(t1)).{core::Iterable::first}.{self::Q::result}.{self::T1::go}().{self::T3::run}();
}
static method foo2NewValue() → self::Q<dynamic>
return new self::Q::•<self::T2>(new self::T2::•());