Skip to content

Commit 53134fc

Browse files
sigmundchcommit-bot@chromium.org
authored andcommitted
[dartdevc] Using a single cache for _typeObject and normalized types.
Change-Id: I7e3c994b7eec2cb4bc25a153fa177a39d5217b38 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/132101 Commit-Queue: Mark Zhou <[email protected]> Reviewed-by: Mark Zhou <[email protected]>
1 parent 0b4fda7 commit 53134fc

File tree

3 files changed

+33
-31
lines changed

3 files changed

+33
-31
lines changed

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

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -390,47 +390,48 @@ class _Type extends Type {
390390

391391
/// Given an internal runtime type object, wraps it in a `_Type` object
392392
/// that implements the dart:core Type interface.
393-
Type wrapType(type) {
393+
Type wrapType(type) => _wrapType(type, false);
394+
395+
/// Helper function to wrap a type.
396+
///
397+
/// When isNormalized is true, the parameter is known to be in a canonicalized
398+
/// normal form, so the algorithm can directly wrap and return the value.
399+
Type _wrapType(type, isNormalized) {
394400
// If we've already wrapped this type once, use the previous wrapper. This
395401
// way, multiple references to the same type return an identical Type.
396402
if (JS('!', '#.hasOwnProperty(#)', type, _typeObject)) {
397403
return JS('', '#[#]', type, _typeObject);
398404
}
399-
var result = JS<Type?>('', '#.get(#)', _normalizedTypeObjectMap, type) ??
400-
canonicalizeNormalizedTypeObject(type);
405+
var result = isNormalized
406+
? _Type(type)
407+
: (type is LegacyType
408+
? _wrapType(type.type, false)
409+
: _canonicalizeNormalizedTypeObject(type));
401410
JS('', '#[#] = #', type, _typeObject, result);
402411
return result;
403412
}
404413

405-
/// Constructs and caches a normalized version of a type.
414+
/// Constructs a normalized version of a type.
406415
///
407416
/// Used for type object identity. Currently only removes legacy wrappers,
408417
/// ignoring other normalization operations.
409-
Type canonicalizeNormalizedTypeObject(dartType) {
410-
// Check if a normalized type corresponding to this type has already been
411-
// generated. Search for and potentially cache both the type and its
412-
// legacy-wrapped version.
413-
var result = JS<Type?>('', '#.get(#)', _normalizedTypeObjectMap, dartType);
414-
if (result != null) {
415-
return result;
416-
}
417-
var type = dartType is LegacyType ? dartType.type : dartType;
418-
var legacyType = legacy(type);
418+
Type _canonicalizeNormalizedTypeObject(type) {
419+
assert(type is! LegacyType);
419420
var args = getGenericArgs(type);
421+
var normType;
420422
if (args == null || args.isEmpty) {
421-
var norm = _Type(type);
422-
JS('', '#.set(#, #)', _normalizedTypeObjectMap, type, norm);
423-
JS('', '#.set(#, #)', _normalizedTypeObjectMap, legacyType, norm);
424-
return norm;
425-
}
426-
var genericClass = getGenericClass(type);
427-
var normArgs = args
428-
.map((generic) => unwrapType(canonicalizeNormalizedTypeObject(generic)))
429-
.toList();
430-
var norm = _Type(constFn(JS('!', '#(...#)', genericClass, normArgs))());
431-
JS('', '#.set(#, #)', _normalizedTypeObjectMap, type, norm);
432-
JS('', '#.set(#, #)', _normalizedTypeObjectMap, legacyType, norm);
433-
return norm;
423+
normType = type;
424+
} else {
425+
var genericClass = getGenericClass(type);
426+
// We don't call _canonicalizeNormalizedTypeObject recursively but call wrap
427+
// + unwrap to handle legacy types automatically and force caching the
428+
// canonicalized type under the _typeObject cache property directly. This
429+
// way we ensure we always use the canonical normalized instance for each
430+
// type parameter.
431+
var normArgs = args.map((a) => unwrapType(wrapType(a))).toList();
432+
normType = JS('!', '#(...#)', genericClass, normArgs);
433+
}
434+
return _wrapType(normType, true);
434435
}
435436

436437
/// The symbol used to store the cached `Type` object associated with a class.
@@ -471,10 +472,6 @@ final _fnTypeTypeMap = JS('', 'new Map()');
471472
/// index path (if present) is the canonical function type.
472473
final List _fnTypeSmallMap = JS('', '[new Map(), new Map(), new Map()]');
473474

474-
/// Memo table that maps DartType objects to their type objects (`_Type`).
475-
/// Used for computing identity for runtime type objects.
476-
final _normalizedTypeObjectMap = JS('', 'new Map()');
477-
478475
@NoReifyGeneric()
479476
T _memoizeArray<T>(map, arr, T create()) => JS('', '''(() => {
480477
let len = $arr.length;

tests/language/nnbd/type_object/equality_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class B {}
1212

1313
Type type<T>() => T;
1414

15+
Type listType<T>() => <T>[].runtimeType;
16+
1517
main() {
1618
var a = new A();
1719
var b = new B();
@@ -38,4 +40,6 @@ main() {
3840
Expect.isFalse(legacyType<int>() == type<int?>());
3941
Expect.isTrue(legacyType<int>() == type<int>());
4042
Expect.isTrue(legacyType<int>() == legacyType<int>());
43+
44+
Expect.isTrue(listType<int>() == legacyListType<int>());
4145
}

tests/language/nnbd/type_object/legacy_library.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
// @dart = 2.6
77

88
Type legacyType<T>() => T;
9+
Type legacyListType<T>() => <T>[].runtimeType;

0 commit comments

Comments
 (0)