[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::•());