[dart2js] Emit a Rti universe
Use embedded names to keep the field names consistent.
Change-Id: Ic8986b38e4a30e9457221939c6512d0446fb32f1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106203
Commit-Queue: Stephen Adams <sra@google.com>
Reviewed-by: Mayank Patke <fishythefish@google.com>
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index b33324b..2ae2052 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -1870,6 +1870,10 @@
js.string(TYPE_TO_INTERCEPTOR_MAP), js.LiteralNull()));
}
+ if (_options.experimentNewRti) {
+ globals.add(js.Property(js.string(RTI_UNIVERSE), createRtiUniverse()));
+ }
+
globals.add(emitMangledGlobalNames());
// The [MANGLED_NAMES] table must contain the mapping for const symbols.
@@ -1906,6 +1910,22 @@
return js.Block(statements);
}
+ /// Returns an expression that creates the initial Rti Universe.
+ ///
+ /// This needs to be kept in sync with `_Universe.create` in `dart:_rti`.
+ js.Expression createRtiUniverse() {
+ List<js.Property> universeFields = [];
+ void initField(String name, String value) {
+ universeFields.add(js.Property(js.string(name), js.js(value)));
+ }
+
+ initField(RtiUniverseFieldNames.evalCache, 'new Map()');
+ initField(RtiUniverseFieldNames.unprocessedRules, '[]');
+ initField(RtiUniverseFieldNames.sharedEmptyArray, '[]');
+
+ return js.ObjectInitializer(universeFields);
+ }
+
/// Emits data needed for native classes.
///
/// We don't try to reduce the size of the native data, but rather build
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 78b6164..fd8db9b 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -24,6 +24,8 @@
MANGLED_NAMES,
METADATA,
NATIVE_SUPERCLASS_TAG_NAME,
+ RTI_UNIVERSE,
+ RtiUniverseFieldNames,
TYPE_TO_INTERCEPTOR_MAP,
TYPES;
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 5039386..1a12e60 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -5,9 +5,12 @@
/// This library contains support for runtime type information.
library rti;
-import 'dart:_foreign_helper' show JS, RAW_DART_FUNCTION_REF;
+import 'dart:_foreign_helper'
+ show JS, JS_EMBEDDED_GLOBAL, RAW_DART_FUNCTION_REF;
import 'dart:_interceptors' show JSArray, JSUnmodifiableArray;
+import 'dart:_js_embedded_names' show RtiUniverseFieldNames, RTI_UNIVERSE;
+
/// 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`).
///
@@ -51,7 +54,10 @@
/// Method called from generated code to evaluate a type environment recipe in
/// `this` type environment.
- Rti _eval(String recipe) => _rtiEval(this, recipe);
+ Rti _eval(String recipe) {
+ // TODO(sra): Clone the fast-path of _Universe.evalInEnvironment to here.
+ return _rtiEval(this, recipe);
+ }
/// Method called from generated code to extend `this` type environment (an
/// interface or binding Rti) with function type arguments (a singleton
@@ -201,19 +207,24 @@
}
}
+Object _theUniverse() => JS_EMBEDDED_GLOBAL('', RTI_UNIVERSE);
+
Rti _rtiEval(Rti environment, String recipe) {
- // TODO(sra): return _Universe.eval(the-universe, environment, recipe);
- throw UnimplementedError('_rtiEval');
+ return _Universe.evalInEnvironment(_theUniverse(), environment, recipe);
}
Rti _rtiBind1(Rti environment, Rti types) {
- // TODO(sra): return _Universe.bind1(the-universe, environment, types);
- throw UnimplementedError('_rtiBind1');
+ return _Universe.bind1(_theUniverse(), environment, types);
}
-Rti _rtiBind(Rti environment, Rti typeTuple) {
- // TODO(sra): return _Universe.bind(the-universe, environment, types);
- throw UnimplementedError('_rtiBind');
+Rti _rtiBind(Rti environment, Rti types) {
+ return _Universe.bind(_theUniverse(), environment, types);
+}
+
+/// Evaluate a ground-term type.
+/// Called from generated code.
+Rti rtiTypeEval(String recipe) {
+ _Universe.eval(_theUniverse(), recipe);
}
Type getRuntimeType(object) {
@@ -322,26 +333,32 @@
@pragma('dart2js:noInline')
static Object create() {
- // TODO(sra): For consistency, this expression should be a JS_BUILTIN that
- // uses the same template as emitted by the emitter.
+ // This needs to be kept in sync with `FragmentEmitter.createRtiUniverse` in
+ // `fragment_emtter.dart`.
return JS(
'',
'{'
- 'evalCache: new Map(),'
- 'unprocessedRules:[],'
- 'a0:[],' // shared empty array.
- '}');
+ '#: new Map(),'
+ '#: [],'
+ '#: [],' // shared empty array.
+ '}',
+ RtiUniverseFieldNames.evalCache,
+ RtiUniverseFieldNames.unprocessedRules,
+ RtiUniverseFieldNames.sharedEmptyArray);
}
// Field accessors.
- static evalCache(universe) => JS('', '#.evalCache', universe);
+ static evalCache(universe) =>
+ JS('', '#.#', universe, RtiUniverseFieldNames.evalCache);
static void addRules(universe, String rules) {
- JS('', '#.unprocessedRules.push(#)', universe, rules);
+ JS('', '#.#.push(#)', universe, RtiUniverseFieldNames.unprocessedRules,
+ rules);
}
- static Object sharedEmptyArray(universe) => JS('JSArray', '#.a0', universe);
+ static Object sharedEmptyArray(universe) =>
+ JS('JSArray', '#.#', universe, RtiUniverseFieldNames.sharedEmptyArray);
/// Evaluates [recipe] in the global environment.
static Rti eval(Object universe, String recipe) {
@@ -388,6 +405,10 @@
return rti;
}
+ static Rti bind1(Object universe, Rti environment, Rti argumentsRti) {
+ throw UnimplementedError('_Universe.bind1');
+ }
+
static Rti evalTypeVariable(Object universe, Rti environment, String name) {
throw UnimplementedError('_Universe.evalTypeVariable("$name")');
}
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index bc10677..28658e4 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -192,6 +192,11 @@
/// globals don't clash with it.
const DEFERRED_INITIALIZED = 'deferredInitialized';
+/// A 'Universe' object used by 'dart:_rti'.
+///
+/// This embedded global is used for --experiment-new-rti.
+const RTI_UNIVERSE = 'typeUniverse';
+
/// Returns a function that creates all precompiled functions (in particular
/// constructors).
///
@@ -411,3 +416,10 @@
/// JsBuiltin.getType, index);
getType,
}
+
+/// Names of fields of the Rti Universe object.
+class RtiUniverseFieldNames {
+ static String evalCache = 'eC';
+ static String unprocessedRules = 'uR';
+ static String sharedEmptyArray = 'sEA';
+}