Decouple runtime type analysis from the K-world

Change-Id: I56730796de4117b6500e22b86cf3c5d6b047646c
Reviewed-on: https://dart-review.googlesource.com/c/88714
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/kernel/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
similarity index 91%
rename from pkg/compiler/lib/src/kernel/runtime_type_analysis.dart
rename to pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index b5da035..9ca94b6 100644
--- a/pkg/compiler/lib/src/kernel/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -1,18 +1,42 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2019, 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.
 
 import 'package:kernel/ast.dart' as ir;
 
 import '../common/names.dart';
-import '../elements/types.dart';
-import '../ir/util.dart';
-import '../universe/feature.dart';
-import 'element_map.dart';
+import 'util.dart';
+
+/// Enum for recognized use kinds of `Object.runtimeType`.
+enum RuntimeTypeUseKind {
+  /// Unknown use of `Object.runtimeType`. This is the fallback value if the
+  /// usage didn't match any of the recognized patterns.
+  unknown,
+
+  /// `Object.runtimeType` used in a pattern like
+  /// `a.runtimeType == b.runtimeType`.
+  equals,
+
+  /// `Object.runtimeType` used in a pattern like `'${e.runtimeType}'` or
+  /// `e.runtimeType.toString()`.
+  string,
+}
+
+class RuntimeTypeUseData {
+  /// The use kind of `Object.runtimeType`.
+  final RuntimeTypeUseKind kind;
+
+  /// The receiver expression.
+  final ir.Expression receiver;
+
+  /// The argument expression if [kind] is `RuntimeTypeUseKind.equals`.
+  final ir.Expression argument;
+
+  RuntimeTypeUseData(this.kind, this.receiver, this.argument);
+}
 
 /// Computes the [RuntimeTypeUse] corresponding to the `e.runtimeType` [node].
-RuntimeTypeUse computeRuntimeTypeUse(
-    KernelToElementMap elementMap, ir.PropertyGet node) {
+RuntimeTypeUseData computeRuntimeTypeUse(ir.PropertyGet node) {
   /// Returns `true` if [node] is of the form `e.runtimeType`.
   bool isGetRuntimeType(ir.TreeNode node) {
     return node is ir.PropertyGet && node.name.name == Identifiers.runtimeType_;
@@ -304,8 +328,5 @@
     receiver = node.receiver;
   }
 
-  DartType receiverType = elementMap.getStaticType(receiver);
-  DartType argumentType =
-      argument == null ? null : elementMap.getStaticType(argument);
-  return new RuntimeTypeUse(kind, receiverType, argumentType);
+  return new RuntimeTypeUseData(kind, receiver, argument);
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend_usage.dart b/pkg/compiler/lib/src/js_backend/backend_usage.dart
index efe00d9..39612fd 100644
--- a/pkg/compiler/lib/src/js_backend/backend_usage.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_usage.dart
@@ -7,6 +7,7 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../frontend_strategy.dart';
+import '../ir/runtime_type_analysis.dart';
 import '../serialization/serialization.dart';
 import '../universe/feature.dart';
 import '../util/util.dart' show Setlet;
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 937a205..391393b 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -15,6 +15,7 @@
 import '../elements/entities.dart';
 import '../elements/names.dart';
 import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
 import '../js/js.dart' as jsAst;
 import '../js/js.dart' show js;
 import '../js_emitter/js_emitter.dart' show Emitter;
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index a93e7e7..6a29c13 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -14,6 +14,7 @@
 import '../constants/values.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
 import '../ir/scope.dart';
 import '../ir/static_type.dart';
 import '../ir/util.dart';
@@ -27,7 +28,6 @@
 import '../universe/use.dart';
 import '../universe/world_builder.dart';
 import 'element_map.dart';
-import 'runtime_type_analysis.dart';
 
 class KernelImpactBuilder extends StaticTypeVisitor {
   final ResolutionWorldImpactBuilder impactBuilder;
@@ -604,19 +604,24 @@
         constraint, const <DartType>[]));
 
     if (node.name.name == Identifiers.runtimeType_) {
-      RuntimeTypeUse runtimeTypeUse = computeRuntimeTypeUse(elementMap, node);
+      RuntimeTypeUseData data = computeRuntimeTypeUse(node);
+      DartType receiverType = elementMap.getStaticType(data.receiver);
+      DartType argumentType = data.argument == null
+          ? null
+          : elementMap.getStaticType(data.argument);
+
       if (_options.omitImplicitChecks) {
-        switch (runtimeTypeUse.kind) {
+        switch (data.kind) {
           case RuntimeTypeUseKind.string:
             if (!_options.laxRuntimeTypeToString) {
-              if (runtimeTypeUse.receiverType == commonElements.objectType) {
+              if (receiverType == commonElements.objectType) {
                 reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
                     MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT);
               } else {
                 reporter.reportHintMessage(
                     computeSourceSpanFromTreeNode(node),
                     MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
-                    {'receiverType': '${runtimeTypeUse.receiverType}.'});
+                    {'receiverType': '${receiverType}.'});
               }
             }
             break;
@@ -625,7 +630,8 @@
             break;
         }
       }
-      impactBuilder.registerRuntimeTypeUse(runtimeTypeUse);
+      impactBuilder.registerRuntimeTypeUse(
+          new RuntimeTypeUse(data.kind, receiverType, argumentType));
     }
   }
 
@@ -696,7 +702,7 @@
 
   @override
   void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
-    if (elementMap.typeEnvironment.isSubtypeOf(operandType, node.type)) {
+    if (typeEnvironment.isSubtypeOf(operandType, node.type)) {
       // Skip unneeded casts.
       return;
     }
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index f854843..1367e6d 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -9,6 +9,7 @@
 library compiler.universe.feature;
 
 import '../elements/types.dart';
+import '../ir/runtime_type_analysis.dart';
 import '../util/util.dart';
 
 /// A language feature that may be seen in the program.
@@ -148,21 +149,6 @@
   }
 }
 
-/// Enum for recognized use kinds of `Object.runtimeType`.
-enum RuntimeTypeUseKind {
-  /// Unknown use of `Object.runtimeType`. This is the fallback value if the
-  /// usage didn't match any of the recogized patterns.
-  unknown,
-
-  /// `Object.runtimeType` used in a pattern like
-  /// `a.runtimeType == b.runtimeType`.
-  equals,
-
-  /// `Object.runtimeType` used in a pattern like `'${e.runtimeType}'` or
-  /// `e.runtimeType.toString()`.
-  string,
-}
-
 /// A use of `Object.runtimeType`.
 class RuntimeTypeUse {
   /// The use kind of `Object.runtimeType`.