Register type arguments on inlining

Closes #33529

Change-Id: I992552a400199490959d10de8c838e56015159e5
Reviewed-on: https://dart-review.googlesource.com/61522
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index be3be29..795ed34 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -620,8 +620,8 @@
         ConstructorBodyEntity constructorBody =
             _elementMap.getConstructorBody(body);
         if (!isCustomElement && // TODO(13836): Fix inlining.
-            _tryInlineMethod(constructorBody, null, null, bodyCallInputs, node,
-                sourceInformation)) {
+            _tryInlineMethod(constructorBody, null, null, bodyCallInputs, null,
+                node, sourceInformation)) {
           pop();
         } else {
           _invokeConstructorBody(body, bodyCallInputs,
@@ -4100,7 +4100,8 @@
       AbstractValue typeMask, List<DartType> typeArguments,
       {SourceInformation sourceInformation, InterfaceType instanceType}) {
     // TODO(redemption): Pass current node if needed.
-    if (_tryInlineMethod(target, null, null, arguments, null, sourceInformation,
+    if (_tryInlineMethod(
+        target, null, null, arguments, typeArguments, null, sourceInformation,
         instanceType: instanceType)) {
       return;
     }
@@ -4170,8 +4171,8 @@
         !(element.isGetter && selector.isCall) &&
         !(element.isFunction && selector.isGetter) &&
         !isOptimizableOperation(selector, element)) {
-      if (_tryInlineMethod(
-          element, selector, mask, arguments, node, sourceInformation)) {
+      if (_tryInlineMethod(element, selector, mask, arguments, typeArguments,
+          node, sourceInformation)) {
         return;
       }
     }
@@ -4988,6 +4989,7 @@
       Selector selector,
       AbstractValue mask,
       List<HInstruction> providedArguments,
+      List<DartType> typeArguments,
       ir.Node currentNode,
       SourceInformation sourceInformation,
       {InterfaceType instanceType}) {
@@ -5149,8 +5151,15 @@
     }
 
     void doInlining() {
-      registry
-          .registerStaticUse(new StaticUse.inlining(function, instanceType));
+      if (function.isConstructor) {
+        registry.registerStaticUse(
+            new StaticUse.constructorInlining(function, instanceType));
+      } else {
+        assert(instanceType == null,
+            "Unexpected instance type for $function: $instanceType");
+        registry.registerStaticUse(
+            new StaticUse.methodInlining(function, typeArguments));
+      }
 
       // Add an explicit null check on the receiver before doing the
       // inlining. We use [element] to get the same name in the
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index cd71861..f684d58 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -665,7 +665,7 @@
         node.typeArguments,
         node.sourceInformation);
     result.element = method;
-    _registry.registerStaticUse(new StaticUse.inlining(method, null));
+    _registry.registerStaticUse(new StaticUse.methodInlining(method, null));
     return result;
   }
 
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index b0f526e..dc49fe5 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -445,6 +445,7 @@
         }
         break;
       case StaticUseKind.INLINING:
+        registerStaticInvocation(staticUse);
         break;
     }
     if (useSet.isNotEmpty) {
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 8788342..0db511d 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -523,12 +523,18 @@
   }
 
   /// Inlining of [element].
-  factory StaticUse.inlining(
-      FunctionEntity element, InterfaceType instanceType) {
+  factory StaticUse.constructorInlining(
+      ConstructorEntity element, InterfaceType instanceType) {
     return new StaticUse.internal(element, StaticUseKind.INLINING,
         type: instanceType);
   }
 
+  /// Inlining of [element].
+  factory StaticUse.methodInlining(
+      FunctionEntity element, List<DartType> typeArguments) {
+    return new GenericStaticUse.methodInlining(element, typeArguments);
+  }
+
   bool operator ==(other) {
     if (identical(this, other)) return true;
     if (other is! StaticUse) return false;
@@ -540,7 +546,7 @@
   }
 
   String toString() =>
-      'StaticUse($element,$kind,$type,' '$typeArguments,$callStructure)';
+      'StaticUse($element,$kind,$type,$typeArguments,$callStructure)';
 }
 
 class GenericStaticUse extends StaticUse {
@@ -559,6 +565,10 @@
             "${callStructure?.typeArgumentCount ?? 0} but "
             "${typeArguments?.length ?? 0} were passed."));
   }
+
+  GenericStaticUse.methodInlining(FunctionEntity entity, this.typeArguments)
+      : super.internal(entity, StaticUseKind.INLINING,
+            typeArgumentsHash: Hashing.listHash(typeArguments));
 }
 
 enum TypeUseKind {
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index a077442..37dac4c 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -501,10 +501,12 @@
     int end = entities.length * (shardIndex + 1) ~/ shards;
     entities = entities.sublist(start, end);
   }
+  int testCount = 0;
   for (FileSystemEntity entity in entities) {
     String name = entity.uri.pathSegments.last;
     if (args.isNotEmpty && !args.contains(name) && !continued) continue;
     if (shouldContinue) continued = true;
+    testCount++;
     List<String> testOptions = options.toList();
     bool strongModeOnlyTest = false;
     bool trustTypeAnnotations = false;
@@ -652,6 +654,7 @@
     }
   }
   Expect.isFalse(hasFailures, 'Errors found.');
+  Expect.isTrue(testCount > 0, "No files were tested.");
 }
 
 final Set<String> userFiles = new Set<String>();
diff --git a/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart
new file mode 100644
index 0000000..ccc9db9
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/generic_methods_dynamic_02_strong.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// Based on language/generic_methods_dynamic_test/02
+
+library generic_methods_dynamic_test;
+
+/*class: A:checkedInstance,checks=[],typeArgument*/
+class A {}
+
+/*class: B:checks=[],instance*/
+class B {}
+
+/*class: C:*/
+class C {
+  T foo<T>(T t) => t;
+  List<T> bar<T>(Iterable<T> t) => <T>[t.first];
+}
+
+main() {
+  B b = new B();
+  C c = new C();
+  dynamic obj = c;
+  obj.foo<A>(b);
+}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index d09fc30..e46be42 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -212,7 +212,6 @@
 symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
 
 [ $compiler == dart2js && $fast_startup && $fasta && $strong ]
-cast_test: RuntimeError
 error_stack_trace1_test: RuntimeError
 growable_list_test: RuntimeError
 integer_to_radix_string_test/01: RuntimeError
@@ -231,7 +230,6 @@
 int_parse_radix_test/01: RuntimeError
 
 [ $compiler == dart2js && $fasta && $host_checked && $strong ]
-cast_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
 growable_list_test: RuntimeError # Concurrent modifications test always runs
 integer_to_radix_string_test/01: RuntimeError
@@ -248,7 +246,6 @@
 uri_base_test: RuntimeError
 
 [ $compiler == dart2js && $fasta && $minified && $strong ]
-cast_test: RuntimeError
 dynamic_nosuchmethod_test: RuntimeError
 error_stack_trace1_test: RuntimeError # Issue 12399
 growable_list_test: RuntimeError # Concurrent modifications test always runs
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index c151979..ff637f7 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -635,8 +635,6 @@
 generic_is_check_test: RuntimeError
 generic_method_types_test/02: RuntimeError
 generic_methods_bounds_test/02: MissingRuntimeError
-generic_methods_dynamic_test/02: MissingRuntimeError
-generic_methods_dynamic_test/04: MissingRuntimeError
 generic_methods_generic_class_tearoff_test: RuntimeError
 generic_methods_generic_function_result_test/01: MissingCompileTimeError
 generic_methods_unused_parameter_test: RuntimeError
@@ -759,7 +757,6 @@
 nested_generic_closure_test: RuntimeError
 no_main_test/01: CompileTimeError
 no_such_method_mock_test: RuntimeError
-nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 null_no_such_method_test: CompileTimeError
 number_identity2_test: RuntimeError
 numbers_test: RuntimeError, OK # non JS number semantics
@@ -1014,8 +1011,6 @@
 generic_method_types_test/02: RuntimeError
 generic_methods_bounds_test/01: MissingCompileTimeError
 generic_methods_bounds_test/02: MissingRuntimeError
-generic_methods_dynamic_test/02: MissingRuntimeError
-generic_methods_dynamic_test/04: MissingRuntimeError
 generic_methods_generic_class_tearoff_test: RuntimeError
 generic_methods_generic_function_result_test/01: MissingCompileTimeError
 generic_methods_overriding_test/01: MissingCompileTimeError
@@ -1198,7 +1193,6 @@
 nested_generic_closure_test: RuntimeError
 no_main_test/01: CompileTimeError
 no_such_method_mock_test: RuntimeError
-nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 null_no_such_method_test: CompileTimeError
 number_identity2_test: RuntimeError
 numbers_test: RuntimeError, OK # non JS number semantics
@@ -1514,8 +1508,6 @@
 generic_method_types_test/02: RuntimeError
 generic_methods_bounds_test/01: MissingCompileTimeError
 generic_methods_bounds_test/02: MissingRuntimeError
-generic_methods_dynamic_test/02: MissingRuntimeError
-generic_methods_dynamic_test/04: MissingRuntimeError
 generic_methods_generic_class_tearoff_test: RuntimeError
 generic_methods_generic_function_result_test/01: MissingCompileTimeError
 generic_methods_overriding_test/01: MissingCompileTimeError
@@ -1706,7 +1698,6 @@
 no_such_method_mock_test: RuntimeError
 no_such_method_native_test: RuntimeError
 no_such_method_test: RuntimeError
-nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
 null_no_such_method_test: CompileTimeError
 number_identity2_test: RuntimeError
 numbers_test: RuntimeError, OK # non JS number semantics