Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Unified Diff: sdk/lib/_internal/compiler/js_lib/js_names.dart

Issue 974803002: Defer addStubs to class instantiation time. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased and fixes. Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/js_lib/js_names.dart
diff --git a/sdk/lib/_internal/compiler/js_lib/js_names.dart b/sdk/lib/_internal/compiler/js_lib/js_names.dart
index 7058b07bde504a7d5ba656ddd41d6984a89da047..1c50eb4d42ff55a7ec7fce4f6dd08fd433bcee68 100644
--- a/sdk/lib/_internal/compiler/js_lib/js_names.dart
+++ b/sdk/lib/_internal/compiler/js_lib/js_names.dart
@@ -27,55 +27,118 @@ preserveNames() {}
/// A map from mangled names to "reflective" names, that is, unmangled names
/// with some additional information, such as, number of required arguments.
/// This map is for mangled names used as instance members.
-final Map<String, String> mangledNames =
- computeMangledNames(
- JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES),
- false);
+final _LazyMangledNamesMap mangledNames = new _LazyMangledInstanceNamesMap(
+ JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES));
/// A map from "reflective" names to mangled names (the reverse of
/// [mangledNames]).
-final Map<String, String> reflectiveNames =
- computeReflectiveNames(mangledNames);
+final _LazyReflectiveNamesMap reflectiveNames =
+ new _LazyReflectiveNamesMap(JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES),
+ true);
/// A map from mangled names to "reflective" names (see [mangledNames]). This
/// map is for globals, that is, static and top-level members.
-final Map<String, String> mangledGlobalNames = computeMangledNames(
- JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES),
- true);
+final _LazyMangledNamesMap mangledGlobalNames = new _LazyMangledNamesMap(
+ JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES));
/// A map from "reflective" names to mangled names (the reverse of
/// [mangledGlobalNames]).
-final Map<String, String> reflectiveGlobalNames =
- computeReflectiveNames(mangledGlobalNames);
-
-/// [jsMangledNames] is a JavaScript object literal. The keys are the mangled
-/// names, and the values are the "reflective" names.
-Map<String, String> computeMangledNames(jsMangledNames, bool isGlobal) {
- preserveNames();
- var keys = extractKeys(jsMangledNames);
- var result = <String, String>{};
- String getterPrefix = JS_GET_NAME(JsGetName.GETTER_PREFIX);
- int getterPrefixLength = getterPrefix.length;
- String setterPrefix = JS_GET_NAME(JsGetName.SETTER_PREFIX);
- for (String key in keys) {
- String value = JS('String', '#[#]', jsMangledNames, key);
- result[key] = value;
- if (!isGlobal) {
- if (key.startsWith(getterPrefix)) {
- result['$setterPrefix${key.substring(getterPrefixLength)}'] = '$value=';
- }
+final _LazyReflectiveNamesMap reflectiveGlobalNames =
+ new _LazyReflectiveNamesMap(
+ JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES), false);
+
+/// Implements a mapping from mangled names to their reflective counterparts.
+/// The propertiy names of [_jsMangledNames] are the mangled names, and the
+/// values are the "reflective" names.
+class _LazyMangledNamesMap {
+ /// [_jsMangledNames] is a JavaScript object literal.
+ var _jsMangledNames;
+
+ _LazyMangledNamesMap(this._jsMangledNames);
+
+ String operator[](String key) {
+ String result = JS('var', '#[#]', _jsMangledNames, key);
+ // Filter out all non-string values to protect against polution from
+ // anciliary fields in [_jsMangledNames].
+ bool filter =
+ JS('bool', 'typeof # !== "string"', result);
+ // To ensure that the inferrer sees that result is a String, we explicitly
+ // give it a better type here.
+ return filter ? null : JS('String', '#', result);
+ }
+}
+
+/// Extends [_LazyMangledNamesMap] with additional support for adding mappings
+/// from mangled setter names to their reflective counterpart by rewriting a
+/// corresponding entry for a getter name, if it exists.
+class _LazyMangledInstanceNamesMap extends _LazyMangledNamesMap {
+ _LazyMangledInstanceNamesMap(_jsMangledNames) : super(_jsMangledNames);
+
+ String operator[](String key) {
+ String result = super[key];
+ String setterPrefix = JS_GET_NAME(JsGetName.SETTER_PREFIX);
+ if (result == null && key.startsWith(setterPrefix)) {
+ String getterPrefix = JS_GET_NAME(JsGetName.GETTER_PREFIX);
+ int setterPrefixLength = setterPrefix.length;
+
+ // Generate the setter name from the getter name.
+ key = '$getterPrefix${key.substring(setterPrefixLength)}';
+ result = super[key];
+ return (result != null) ? "${result}=" : null;
}
+ return result;
}
- return result;
}
-Map<String, String> computeReflectiveNames(Map<String, String> map) {
- preserveNames();
- var result = <String, String>{};
- map.forEach((String mangledName, String reflectiveName) {
- result[reflectiveName] = mangledName;
- });
- return result;
+/// Implements the inverse of [_LazyMangledNamesMap]. As it would be too
+/// expensive to seach the mangled names map for a value that corresponds to
+/// the lookup key on each invocation, we compute the full mapping in demand
+/// and cache it. The cache is invalidated when the underlying [_jsMangledNames]
+/// object changes its length. This condition is sufficient as the name mapping
+/// can only grow over time.
+/// When [_isInstance] is true, we also apply the inverse of the setter/getter
+/// name conversion implemented by [_LazyMangledInstanceNamesMap].
+class _LazyReflectiveNamesMap {
+ /// [_jsMangledNames] is a JavaScript object literal.
+ final _jsMangledNames;
+ final bool _isInstance;
+ int _cacheLength = 0;
+ Map<String, String> _cache;
+
+ _LazyReflectiveNamesMap(this._jsMangledNames, this._isInstance);
+
+ Map<String, String> _updateReflectiveNames() {
+ preserveNames();
+ Map<String, String> result = <String, String>{};
+ List keys = JS('List', 'Object.keys(#)', _jsMangledNames);
+ for (String key in keys) {
+ var reflectiveName = JS('var', '#[#]', _jsMangledNames, key);
+ // Filter out all non-string values to protect against polution from
+ // anciliary fields in [_jsMangledNames].
+ bool filter = JS('bool', 'typeof # !== "string"', reflectiveName);
+ if (filter) continue;
+ result[reflectiveName] = JS('String', '#', key);
+
+ String getterPrefix = JS_GET_NAME(JsGetName.GETTER_PREFIX);
+ if (_isInstance && key.startsWith(getterPrefix)) {
+ int getterPrefixLength = getterPrefix.length;
+ String setterPrefix = JS_GET_NAME(JsGetName.SETTER_PREFIX);
+ result['$reflectiveName='] =
+ '$setterPrefix${key.substring(getterPrefixLength)}';
+ }
+ }
+ return result;
+ }
+
+ int get _jsMangledNamesLength => JS('int', '#.length', _jsMangledNames);
+
+ String operator[](String key) {
+ if (_cache == null || _jsMangledNamesLength != _cacheLength) {
+ _cache = _updateReflectiveNames();
+ _cacheLength = _jsMangledNamesLength;
+ }
+ return _cache[key];
+ }
}
@NoInline()
« no previous file with comments | « sdk/lib/_internal/compiler/js_lib/js_mirrors.dart ('k') | sdk/lib/_internal/compiler/js_lib/shared/embedded_names.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698