dart2js: Add skeleton dart:_rti libary

- Skeleton Rti type
- Skeleton test
- Add dependency on command-line flag to get dart:_rti into platform dill

Change-Id: Idf383269c66c9951e23fd70a45ce65c54a973586
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104921
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index f0f64ff..9c0a6a5 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -377,6 +377,8 @@
         return false;
       case 'USE_CONTENT_SECURITY_POLICY':
         return options.useContentSecurityPolicy;
+      case 'USE_NEW_RTI':
+        return options.experimentNewRti;
       default:
         return null;
     }
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index 7205568..beee35b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -59,6 +59,8 @@
         unmangleGlobalNameIfPreservedAnyways,
         unmangleAllIdentifiersIfPreservedAnyways;
 
+import 'dart:_rti' as newRti show getRuntimeType;
+
 part 'annotations.dart';
 part 'constant_map.dart';
 part 'instantiation.dart';
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index e4b0f9d..6250aa0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -391,6 +391,7 @@
 }
 
 Type getRuntimeType(var object) {
+  if (JS_GET_FLAG('USE_NEW_RTI')) return newRti.getRuntimeType(object);
   return new TypeImpl(getRti(object));
 }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
new file mode 100644
index 0000000..489aef3
--- /dev/null
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -0,0 +1,140 @@
+// 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.
+
+/// This library contains support for runtime type information.
+library rti;
+
+import 'dart:_foreign_helper' show JS;
+import 'dart:_interceptors' show JSArray, JSUnmodifiableArray;
+
+/// An Rti object represents both a type (e.g `Map<int, String>`) and a type
+/// environment (`Map<int, String>` binds `Map.K=int` and `Map.V=String`).
+///
+/// There is a single [Rti] class to help reduce polymorphism in the JavaScript
+/// runtime. The class has a default constructor and no final fields so it can
+/// be created before much of the runtime exists.
+///
+/// The fields are declared in an order that gets shorter minified names for the
+/// more commonly used fields. (TODO: we should exploit the fact that an Rti
+/// instance never appears in a dynamic context, so does not need field names to
+/// be distinct from dynamic selectors).
+///
+class Rti {
+  /// JavaScript method for 'as' check. The method is called from generated code,
+  /// e.g. `o as T` generates something like `rtiForT._as(o)`.
+  dynamic _as;
+
+  /// JavaScript method for type check.  The method is called from generated
+  /// code, e.g. parameter check for `T param` generates something like
+  /// `rtiForT._check(param)`.
+  dynamic _check;
+
+  /// JavaScript method for 'is' test.  The method is called from generated
+  /// code, e.g. `o is T` generates something like `rtiForT._is(o)`.
+  dynamic _is;
+
+  /// Method called from generated code to evaluate a type environment recipe in
+  /// `this` type environment.
+  Rti _eval(String recipe) => _rtiEval(this, recipe);
+
+  /// Method called from generated code to extend `this` type environment with a
+  /// function type parameter.
+  Rti _bind1(Rti type) => _rtiBind1(this, type);
+
+  /// Method called from generated code to extend `this` type environment with a
+  /// tuple of function type parameters.
+  Rti _bind(Rti typeTuple) => _rtiBind(this, typeTuple);
+
+  // Precomputed derived types. These fields are used to hold derived types that
+  // are computed eagerly.
+  // TODO(sra): Implement precomputed type optimizations.
+  dynamic _precomputed1;
+  dynamic _precomputed2;
+  dynamic _precomputed3;
+  dynamic _precomputed4;
+
+  // The Type object corresponding to this Rti.
+  Type _typeCache;
+
+  /// The kind of Rti `this` is, one of the kindXXX constants below.
+  ///
+  /// We don't use an enum since we need to create Rti objects very early.
+  ///
+  /// The zero initializer ensures dart2js type analysis considers [_kind] is
+  /// non-nullable.
+  int _kind = 0;
+
+  // Terminal terms.
+  static const kindNever = 1;
+  static const kindDynamic = 2;
+  static const kindVoid = 3; // TODO(sra): Use `dynamic` instead?
+  static const kindAny = 4; // Dart1-style 'dynamic' for JS-interop.
+  // Unary terms.
+  static const kindStar = 5;
+  static const kindQuestion = 6;
+  static const kindFutureOr = 7;
+  // More complex terms.
+  static const kindInterface = 8;
+  // A vector of type parameters from enclosing functions and closures.
+  static const kindBinding = 9;
+  static const kindFunction = 10;
+  static const kindGenericFunction = 11;
+
+  /// Primary data associated with type.
+  ///
+  /// - Minified name of interface for interface types.
+  /// - Underlying type for unary terms.
+  /// - Class part of a type environment inside a generic class, or `null` for
+  ///   type tuple.
+  /// - Return type of function types.
+  dynamic _primary;
+
+  String get interfaceName {
+    assert(_kind == kindInterface);
+    return JS('String', '#', _primary);
+  }
+
+  /// Additional data associated with type.
+  ///
+  /// - The type arguments of an interface type.
+  /// - The type arguments from enclosing functions and closures for a
+  ///   kindBinding.
+  /// - TBD for kindFunction and kindGenericFunction.
+  dynamic _rest;
+
+  JSArray get interfaceTypeArguments {
+    // The array is a plain JavaScript Array, otherwise we would need the type
+    // `JSArray<Rti>` to exist before we could create the type `JSArray<Rti>`.
+    assert(_kind == kindInterface);
+    return JS('JSUnmodifiableArray', '#', _primary);
+  }
+
+  /// On [Rti]s that are type environments, derived types are cached on the
+  /// environment to ensure fast canonicalization. Ground-term types (i.e. not
+  /// dependent on class or function type parameters) are cached in the
+  /// universe. This field starts as `null` and the cache is created on demand.
+  dynamic _evalCache;
+}
+
+Rti _rtiEval(Rti environment, String recipe) {
+  throw UnimplementedError('_rtiEval');
+}
+
+Rti _rtiBind1(Rti environment, Rti type) {
+  throw UnimplementedError('_rtiBind1');
+}
+
+Rti _rtiBind(Rti environment, Rti typeTuple) {
+  throw UnimplementedError('_rtiBind');
+}
+
+Type getRuntimeType(object) {
+  throw UnimplementedError('getRuntimeType');
+}
+
+// Entry points for testing
+
+String testingRtiToString(dynamic rti) {
+  return 'Rti';
+}
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 58a9e90..f848a09 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -152,6 +152,8 @@
       dart2jsPatchPath: "_internal/js_runtime/lib/internal_patch.dart"),
   "_js_helper": const LibraryInfo("_internal/js_runtime/lib/js_helper.dart",
       categories: "", documented: false, platforms: DART2JS_PLATFORM),
+  "_rti": const LibraryInfo("_internal/js_runtime/lib/rti.dart",
+      categories: "", documented: false, platforms: DART2JS_PLATFORM),
   "_interceptors": const LibraryInfo(
       "_internal/js_runtime/lib/interceptors.dart",
       categories: "",
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 41a30a2..4a0f788 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -265,6 +265,9 @@
       "web_sql": {
         "uri": "web_sql/dart2js/web_sql_dart2js.dart"
       },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      },
       "svg": {
         "uri": "svg/dart2js/svg_dart2js.dart"
       }
@@ -464,6 +467,9 @@
       "_js_helper": {
         "uri": "_internal/js_runtime/lib/js_helper.dart"
       },
+      "_rti": {
+        "uri": "_internal/js_runtime/lib/rti.dart"
+      },
       "js": {
         "uri": "js/dart2js/js_dart2js.dart"
       }
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index ccd601d..7a5520c 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -245,6 +245,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _rti:
+      uri: "_internal/js_runtime/lib/rti.dart"
+
     _interceptors:
       uri: "_internal/js_runtime/lib/interceptors.dart"
 
@@ -334,6 +337,9 @@
     _js_helper:
       uri: "_internal/js_runtime/lib/js_helper.dart"
 
+    _rti:
+      uri: "_internal/js_runtime/lib/rti.dart"
+
     _interceptors:
       uri: "_internal/js_runtime/lib/interceptors.dart"
 
@@ -351,6 +357,7 @@
 
     _async_await_error_codes:
       uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+
 dartdevc:
     libraries:
       _runtime:
diff --git a/tests/compiler/dart2js_extra/rti/simple_test.dart b/tests/compiler/dart2js_extra/rti/simple_test.dart
new file mode 100644
index 0000000..636a457
--- /dev/null
+++ b/tests/compiler/dart2js_extra/rti/simple_test.dart
@@ -0,0 +1,10 @@
+// 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 'dart:_rti' as rti;
+import "package:expect/expect.dart";
+
+main() {
+  Expect.equals('Rti', rti.testingRtiToString(null));
+}