Skip to content

Commit ec8941b

Browse files
committed
[dartdevc] Hoisting subtype caches to addTypeCaches.
This lets us avoid some runtime polymorphicity of JS objects. Contains a subset of optimizations in https://dart-review.googlesource.com/c/sdk/+/136845 Change-Id: I6cdcf6c58a51074ad860ea225db512f28fff5436 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138564 Reviewed-by: Sigmund Cherem <[email protected]> Reviewed-by: Nicholas Shahan <[email protected]>
1 parent f5a6554 commit ec8941b

File tree

2 files changed

+9
-13
lines changed

2 files changed

+9
-13
lines changed

sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ addTypeTests(ctor, isClass) {
573573
addTypeCaches(type) {
574574
JS('', '#[#] = void 0', type, _cachedLegacy);
575575
JS('', '#[#] = void 0', type, _cachedNullable);
576+
var subtypeCacheMap = JS<Object>('!', 'new Map()');
577+
JS('', '#[#] = #', type, _subtypeCache, subtypeCacheMap);
578+
JS('', '#.push(#)', _cacheMaps, subtypeCacheMap);
576579
}
577580

578581
// TODO(jmesserly): should we do this for all interfaces?

sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ final _cachedNullable = JS('', 'Symbol("cachedNullable")');
273273
/// A javascript Symbol used to store a canonical version of T* on T.
274274
final _cachedLegacy = JS('', 'Symbol("cachedLegacy")');
275275

276+
/// A javascript Symbol used to store prior subtype checks and their results.
277+
final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
278+
276279
/// Returns a nullable (question, ?) version of [type].
277280
///
278281
/// The resulting type returned in a normalized form based on the rules from the
@@ -1235,17 +1238,9 @@ _isFunctionSubtype(ft1, ft2, bool strictMode) => JS('', '''(() => {
12351238
bool isSubtypeOf(Object t1, Object t2) {
12361239
// TODO(jmesserly): we've optimized `is`/`as`/implicit type checks, so they're
12371240
// dispatched on the type. Can we optimize the subtype relation too?
1238-
// TODO: Find a way to eagerly attach this cache to the Null object at
1239-
// compile-time so we can remove the top-level null comparison cache entirely.
1240-
Object map;
1241-
if (JS('!', '!#.hasOwnProperty(#)', t1, _subtypeCache)) {
1242-
JS('', '#[#] = #', t1, _subtypeCache, map = JS<Object>('!', 'new Map()'));
1243-
_cacheMaps.add(map);
1244-
} else {
1245-
map = JS<Object>('!', '#[#]', t1, _subtypeCache);
1246-
bool result = JS('', '#.get(#)', map, t2);
1247-
if (JS('!', '# !== void 0', result)) return result;
1248-
}
1241+
var map = JS<Object>('!', '#[#]', t1, _subtypeCache);
1242+
bool result = JS('', '#.get(#)', map, t2);
1243+
if (JS('!', '# !== void 0', result)) return result;
12491244

12501245
var validSubtype = _isSubtype(t1, t2, true);
12511246
if (!validSubtype && !_strictSubtypeChecks) {
@@ -1261,8 +1256,6 @@ bool isSubtypeOf(Object t1, Object t2) {
12611256
return validSubtype;
12621257
}
12631258

1264-
final _subtypeCache = JS('', 'Symbol("_subtypeCache")');
1265-
12661259
@notNull
12671260
bool _isBottom(type, @notNull bool strictMode) =>
12681261
_equalType(type, Never) || (!strictMode && _equalType(type, Null));

0 commit comments

Comments
 (0)