[dart2js] Add abstract value domain to distinguish uncomputed values.
Normal dart2js invocations will continue using the existing abstract
value domains with `emptyType` as the initial type for type graph nodes.
When an appropriate debug flag is passed, all abstract values will be
wrapped so that the underlying empty type is only used when a value is
known to be empty. Abstract values which have not yet been computed will
print as "[uncomputed]" in order to aid in debugging but will otherwise
behave like the empty type during type graph construction.
Change-Id: I1ec41e42e8b566a0a6bfe969c2ff96f4e53d5f4e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243844
Commit-Queue: Mayank Patke <fishythefish@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a568685..951a49e 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -38,8 +38,9 @@
import 'enqueue.dart' show Enqueuer;
import 'environment.dart';
import 'inferrer/abstract_value_strategy.dart';
-import 'inferrer/trivial.dart' show TrivialAbstractValueStrategy;
+import 'inferrer/computable.dart' show ComputableAbstractValueStrategy;
import 'inferrer/powersets/powersets.dart' show PowersetStrategy;
+import 'inferrer/trivial.dart' show TrivialAbstractValueStrategy;
import 'inferrer/typemasks/masks.dart' show TypeMaskStrategy;
import 'inferrer/types.dart'
show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
@@ -189,6 +190,10 @@
} else if (options.experimentalPowersets) {
abstractValueStrategy = PowersetStrategy(abstractValueStrategy);
}
+ if (options.debugGlobalInference) {
+ abstractValueStrategy =
+ ComputableAbstractValueStrategy(abstractValueStrategy);
+ }
CompilerTask kernelFrontEndTask;
selfTask = GenericTask('self', measurer);
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 0df88c8..d27e038 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -92,6 +92,12 @@
/// A system that implements an abstraction over runtime values.
abstract class AbstractValueDomain {
+ /// The [AbstractValue] that represents a type which has not yet been
+ /// computed. Type graph nodes may carry this type during construction of the
+ /// graph, but it should be replaced by a computed type by the time the graph
+ /// is queried.
+ AbstractValue get uncomputedType => emptyType;
+
/// The [AbstractValue] that represents an unknown runtime value. This
/// includes values internal to the implementation, such as late sentinels.
AbstractValue get internalTopType;
diff --git a/pkg/compiler/lib/src/inferrer/computable.dart b/pkg/compiler/lib/src/inferrer/computable.dart
new file mode 100644
index 0000000..b9380de
--- /dev/null
+++ b/pkg/compiler/lib/src/inferrer/computable.dart
@@ -0,0 +1,673 @@
+// Copyright (c) 2022, 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 '../constants/values.dart' show ConstantValue, PrimitiveConstantValue;
+import '../elements/entities.dart';
+import '../elements/names.dart';
+import '../elements/types.dart' show DartType;
+import '../ir/class_relation.dart';
+import '../serialization/serialization.dart';
+import '../universe/selector.dart';
+import '../universe/world_builder.dart';
+import '../universe/use.dart';
+import '../world.dart';
+import 'abstract_value_domain.dart';
+import 'abstract_value_strategy.dart';
+
+class ComputableAbstractValue implements AbstractValue {
+ final AbstractValue? _wrappedValue;
+ const ComputableAbstractValue(this._wrappedValue);
+
+ bool get isComputed => _wrappedValue != null;
+ bool get isUncomputed => _wrappedValue == null;
+
+ AbstractValue _unwrapOrThrow() => isUncomputed
+ ? throw StateError("Uncomputed abstract value")
+ : _wrappedValue!;
+
+ AbstractValue _unwrapOrEmpty(AbstractValueDomain wrappedDomain) =>
+ isUncomputed ? wrappedDomain.emptyType : _wrappedValue!;
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ if (other is ComputableAbstractValue) {
+ return _wrappedValue == other._wrappedValue;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode => _wrappedValue.hashCode;
+
+ @override
+ String toString() =>
+ isUncomputed ? "[uncomputed]" : _wrappedValue!.toString();
+}
+
+class ComputableAbstractValueDomain with AbstractValueDomain {
+ final AbstractValueDomain _wrappedDomain;
+ const ComputableAbstractValueDomain(this._wrappedDomain);
+
+ AbstractValue _unwrap(ComputableAbstractValue value) =>
+ value._unwrapOrEmpty(_wrappedDomain);
+
+ AbstractValue? _unwrapOrNull(ComputableAbstractValue? value) =>
+ value?._unwrapOrEmpty(_wrappedDomain);
+
+ @override
+ AbstractValue get uncomputedType => const ComputableAbstractValue(null);
+
+ @override
+ AbstractValue get internalTopType =>
+ ComputableAbstractValue(_wrappedDomain.internalTopType);
+
+ @override
+ AbstractValue get dynamicType =>
+ ComputableAbstractValue(_wrappedDomain.dynamicType);
+
+ @override
+ AbstractValue get typeType =>
+ ComputableAbstractValue(_wrappedDomain.typeType);
+
+ @override
+ AbstractValue get functionType =>
+ ComputableAbstractValue(_wrappedDomain.functionType);
+
+ @override
+ AbstractValue get boolType =>
+ ComputableAbstractValue(_wrappedDomain.boolType);
+
+ @override
+ AbstractValue get intType => ComputableAbstractValue(_wrappedDomain.intType);
+
+ @override
+ AbstractValue get numNotIntType =>
+ ComputableAbstractValue(_wrappedDomain.numNotIntType);
+
+ @override
+ AbstractValue get numType => ComputableAbstractValue(_wrappedDomain.numType);
+
+ @override
+ AbstractValue get stringType =>
+ ComputableAbstractValue(_wrappedDomain.stringType);
+
+ @override
+ AbstractValue get listType =>
+ ComputableAbstractValue(_wrappedDomain.listType);
+
+ @override
+ AbstractValue get setType => ComputableAbstractValue(_wrappedDomain.setType);
+
+ @override
+ AbstractValue get mapType => ComputableAbstractValue(_wrappedDomain.mapType);
+
+ @override
+ AbstractValue get nonNullType =>
+ ComputableAbstractValue(_wrappedDomain.nonNullType);
+
+ @override
+ AbstractValue get nullType =>
+ ComputableAbstractValue(_wrappedDomain.nullType);
+
+ @override
+ AbstractValue get lateSentinelType =>
+ ComputableAbstractValue(_wrappedDomain.lateSentinelType);
+
+ @override
+ AbstractValue get growableListType =>
+ ComputableAbstractValue(_wrappedDomain.growableListType);
+
+ @override
+ AbstractValue get fixedListType =>
+ ComputableAbstractValue(_wrappedDomain.fixedListType);
+
+ @override
+ AbstractValue get mutableArrayType =>
+ ComputableAbstractValue(_wrappedDomain.mutableArrayType);
+
+ @override
+ AbstractValue get uint31Type =>
+ ComputableAbstractValue(_wrappedDomain.uint31Type);
+
+ @override
+ AbstractValue get uint32Type =>
+ ComputableAbstractValue(_wrappedDomain.uint32Type);
+
+ @override
+ AbstractValue get positiveIntType =>
+ ComputableAbstractValue(_wrappedDomain.positiveIntType);
+
+ @override
+ AbstractValue get constListType =>
+ ComputableAbstractValue(_wrappedDomain.constListType);
+
+ @override
+ AbstractValue get constSetType =>
+ ComputableAbstractValue(_wrappedDomain.constSetType);
+
+ @override
+ AbstractValue get constMapType =>
+ ComputableAbstractValue(_wrappedDomain.constMapType);
+
+ @override
+ AbstractValue get emptyType =>
+ ComputableAbstractValue(_wrappedDomain.emptyType);
+
+ @override
+ AbstractValue get syncStarIterableType =>
+ ComputableAbstractValue(_wrappedDomain.syncStarIterableType);
+
+ @override
+ AbstractValue get asyncFutureType =>
+ ComputableAbstractValue(_wrappedDomain.asyncFutureType);
+
+ @override
+ AbstractValue get asyncStarStreamType =>
+ ComputableAbstractValue(_wrappedDomain.asyncStarStreamType);
+
+ @override
+ AbstractValueWithPrecision createFromStaticType(DartType type,
+ {ClassRelation classRelation = ClassRelation.subtype,
+ required bool nullable}) {
+ final unwrapped = _wrappedDomain.createFromStaticType(type,
+ classRelation: classRelation, nullable: nullable);
+ return AbstractValueWithPrecision(
+ ComputableAbstractValue(unwrapped.abstractValue), unwrapped.isPrecise);
+ }
+
+ @override
+ AbstractValue createNonNullExact(ClassEntity cls) =>
+ ComputableAbstractValue(_wrappedDomain.createNonNullExact(cls));
+
+ @override
+ AbstractValue createNullableExact(ClassEntity cls) =>
+ ComputableAbstractValue(_wrappedDomain.createNullableExact(cls));
+
+ @override
+ AbstractValue createNonNullSubclass(ClassEntity cls) =>
+ ComputableAbstractValue(_wrappedDomain.createNonNullSubclass(cls));
+
+ @override
+ AbstractValue createNonNullSubtype(ClassEntity cls) =>
+ ComputableAbstractValue(_wrappedDomain.createNonNullSubtype(cls));
+
+ @override
+ AbstractValue createNullableSubtype(ClassEntity cls) =>
+ ComputableAbstractValue(_wrappedDomain.createNullableSubtype(cls));
+
+ @override
+ AbstractBool isTypedArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isTypedArray(_unwrap(value));
+
+ @override
+ AbstractBool couldBeTypedArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.couldBeTypedArray(_unwrap(value));
+
+ @override
+ AbstractValue excludeNull(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.excludeNull(_unwrap(value)));
+
+ @override
+ AbstractValue includeNull(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.includeNull(_unwrap(value)));
+
+ @override
+ AbstractValue excludeLateSentinel(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(
+ _wrappedDomain.excludeLateSentinel(_unwrap(value)));
+
+ @override
+ AbstractValue includeLateSentinel(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(
+ _wrappedDomain.includeLateSentinel(_unwrap(value)));
+
+ @override
+ AbstractBool containsType(
+ covariant ComputableAbstractValue value, ClassEntity cls) =>
+ _wrappedDomain.containsType(_unwrap(value), cls);
+
+ @override
+ AbstractBool containsOnlyType(
+ covariant ComputableAbstractValue value, ClassEntity cls) =>
+ _wrappedDomain.containsOnlyType(_unwrap(value), cls);
+
+ @override
+ AbstractBool isInstanceOfOrNull(
+ covariant ComputableAbstractValue value, ClassEntity cls) =>
+ _wrappedDomain.isInstanceOfOrNull(_unwrap(value), cls);
+
+ @override
+ AbstractBool isInstanceOf(
+ covariant ComputableAbstractValue value, ClassEntity cls) =>
+ _wrappedDomain.isInstanceOf(_unwrap(value), cls);
+
+ @override
+ AbstractBool isEmpty(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isEmpty(_unwrap(value));
+
+ @override
+ AbstractBool isExact(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isExact(_unwrap(value));
+
+ @override
+ ClassEntity? getExactClass(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getExactClass(_unwrap(value));
+
+ @override
+ AbstractBool isNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isNull(_unwrap(value));
+
+ @override
+ AbstractBool isLateSentinel(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isLateSentinel(_unwrap(value));
+
+ @override
+ AbstractBool isPrimitive(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitive(_unwrap(value));
+
+ @override
+ AbstractBool isPrimitiveNumber(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitiveNumber(_unwrap(value));
+
+ @override
+ AbstractBool isPrimitiveBoolean(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitiveBoolean(_unwrap(value));
+
+ @override
+ AbstractBool isIndexablePrimitive(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isIndexablePrimitive(_unwrap(value));
+
+ @override
+ AbstractBool isFixedArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isFixedArray(_unwrap(value));
+
+ @override
+ AbstractBool isExtendableArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isExtendableArray(_unwrap(value));
+
+ @override
+ AbstractBool isMutableArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isMutableArray(_unwrap(value));
+
+ @override
+ AbstractBool isMutableIndexable(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isMutableIndexable(_unwrap(value));
+
+ @override
+ AbstractBool isArray(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isArray(_unwrap(value));
+
+ @override
+ AbstractBool isPrimitiveString(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitiveString(_unwrap(value));
+
+ @override
+ AbstractBool isInterceptor(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isInterceptor(_unwrap(value));
+
+ @override
+ AbstractBool isInteger(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isInteger(_unwrap(value));
+
+ @override
+ AbstractBool isUInt32(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isUInt32(_unwrap(value));
+
+ @override
+ AbstractBool isUInt31(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isUInt31(_unwrap(value));
+
+ @override
+ AbstractBool isPositiveInteger(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPositiveInteger(_unwrap(value));
+
+ @override
+ AbstractBool isPositiveIntegerOrNull(
+ covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPositiveIntegerOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isIntegerOrNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isIntegerOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isNumber(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isNumber(_unwrap(value));
+
+ @override
+ AbstractBool isNumberOrNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isNumberOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isBoolean(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isBoolean(_unwrap(value));
+
+ @override
+ AbstractBool isBooleanOrNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isBooleanOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isString(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isString(_unwrap(value));
+
+ @override
+ AbstractBool isStringOrNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isStringOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isPrimitiveOrNull(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitiveOrNull(_unwrap(value));
+
+ @override
+ AbstractBool isTruthy(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isTruthy(_unwrap(value));
+
+ @override
+ AbstractValue union(covariant ComputableAbstractValue a,
+ covariant ComputableAbstractValue b) =>
+ ComputableAbstractValue(_wrappedDomain.union(_unwrap(a), _unwrap(b)));
+
+ @override
+ AbstractValue unionOfMany(covariant Iterable<AbstractValue> values) =>
+ ComputableAbstractValue(_wrappedDomain.unionOfMany(values.map(
+ (AbstractValue value) => _unwrap(value as ComputableAbstractValue))));
+
+ @override
+ AbstractValue intersection(covariant ComputableAbstractValue a,
+ covariant ComputableAbstractValue b) =>
+ ComputableAbstractValue(
+ _wrappedDomain.intersection(_unwrap(a), _unwrap(b)));
+
+ @override
+ AbstractBool areDisjoint(covariant ComputableAbstractValue a,
+ covariant ComputableAbstractValue b) =>
+ _wrappedDomain.areDisjoint(_unwrap(a), _unwrap(b));
+
+ @override
+ AbstractBool containsAll(covariant ComputableAbstractValue a) =>
+ _wrappedDomain.containsAll(_unwrap(a));
+
+ @override
+ AbstractValue computeAbstractValueForConstant(
+ covariant ConstantValue value) =>
+ ComputableAbstractValue(
+ _wrappedDomain.computeAbstractValueForConstant(value));
+
+ @override
+ bool isContainer(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isContainer(_unwrap(value));
+
+ @override
+ AbstractValue createContainerValue(
+ covariant ComputableAbstractValue? originalValue,
+ Object? allocationNode,
+ MemberEntity? allocationElement,
+ covariant ComputableAbstractValue elementType,
+ int? length) =>
+ ComputableAbstractValue(_wrappedDomain.createContainerValue(
+ _unwrapOrNull(originalValue),
+ allocationNode,
+ allocationElement,
+ _unwrap(elementType),
+ length));
+
+ @override
+ AbstractValue getContainerElementType(
+ covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(
+ _wrappedDomain.getContainerElementType(_unwrap(value)));
+
+ @override
+ int? getContainerLength(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getContainerLength(_unwrap(value));
+
+ @override
+ bool isSet(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isSet(_unwrap(value));
+
+ @override
+ AbstractValue createSetValue(
+ covariant ComputableAbstractValue? originalValue,
+ Object? allocationNode,
+ MemberEntity? allocationElement,
+ covariant ComputableAbstractValue elementType) =>
+ ComputableAbstractValue(_wrappedDomain.createSetValue(
+ _unwrapOrNull(originalValue),
+ allocationNode,
+ allocationElement,
+ _unwrap(elementType)));
+
+ @override
+ AbstractValue getSetElementType(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.getSetElementType(_unwrap(value)));
+
+ @override
+ bool isMap(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isMap(_unwrap(value));
+
+ @override
+ AbstractValue createMapValue(
+ covariant ComputableAbstractValue? originalValue,
+ Object? allocationNode,
+ MemberEntity? allocationElement,
+ covariant ComputableAbstractValue key,
+ covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.createMapValue(
+ _unwrapOrNull(originalValue),
+ allocationNode,
+ allocationElement,
+ _unwrap(key),
+ _unwrap(value)));
+
+ @override
+ AbstractValue getMapKeyType(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.getMapKeyType(_unwrap(value)));
+
+ @override
+ AbstractValue getMapValueType(covariant ComputableAbstractValue value) =>
+ ComputableAbstractValue(_wrappedDomain.getMapValueType(_unwrap(value)));
+
+ @override
+ bool isDictionary(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isDictionary(_unwrap(value));
+
+ @override
+ AbstractValue createDictionaryValue(
+ covariant ComputableAbstractValue? originalValue,
+ Object? allocationNode,
+ MemberEntity? allocationElement,
+ covariant ComputableAbstractValue key,
+ covariant ComputableAbstractValue value,
+ covariant Map<String, AbstractValue> mappings) =>
+ ComputableAbstractValue(_wrappedDomain.createDictionaryValue(
+ _unwrapOrNull(originalValue),
+ allocationNode,
+ allocationElement,
+ _unwrap(key),
+ _unwrap(value), {
+ for (final entry in mappings.entries)
+ entry.key: _unwrap(entry.value as ComputableAbstractValue)
+ }));
+
+ @override
+ bool containsDictionaryKey(
+ covariant ComputableAbstractValue value, String key) =>
+ value.isComputed &&
+ _wrappedDomain.containsDictionaryKey(value._wrappedValue!, key);
+
+ @override
+ AbstractValue getDictionaryValueForKey(
+ covariant ComputableAbstractValue value, String key) =>
+ ComputableAbstractValue(
+ _wrappedDomain.getDictionaryValueForKey(_unwrap(value), key));
+
+ @override
+ bool isSpecializationOf(covariant ComputableAbstractValue specialization,
+ covariant ComputableAbstractValue generalization) =>
+ _wrappedDomain.isSpecializationOf(
+ _unwrap(specialization), _unwrap(generalization));
+
+ @override
+ AbstractValue? getGeneralization(covariant ComputableAbstractValue? value) {
+ final generalization =
+ _wrappedDomain.getGeneralization(_unwrapOrNull(value));
+ if (generalization == null) return null;
+ return ComputableAbstractValue(generalization);
+ }
+
+ @override
+ Object? getAllocationNode(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getAllocationNode(_unwrap(value));
+
+ @override
+ MemberEntity? getAllocationElement(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getAllocationElement(_unwrap(value));
+
+ @override
+ bool isPrimitiveValue(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isPrimitiveValue(_unwrap(value));
+
+ @override
+ AbstractValue createPrimitiveValue(
+ covariant ComputableAbstractValue originalValue,
+ PrimitiveConstantValue value) =>
+ ComputableAbstractValue(
+ _wrappedDomain.createPrimitiveValue(_unwrap(originalValue), value));
+
+ @override
+ PrimitiveConstantValue? getPrimitiveValue(
+ covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getPrimitiveValue(_unwrap(value));
+
+ @override
+ AbstractValue computeReceiver(Iterable<MemberEntity> members) =>
+ ComputableAbstractValue(_wrappedDomain.computeReceiver(members));
+
+ @override
+ AbstractBool isTargetingMember(covariant ComputableAbstractValue receiver,
+ MemberEntity member, Name name) =>
+ _wrappedDomain.isTargetingMember(_unwrap(receiver), member, name);
+
+ @override
+ AbstractBool needsNoSuchMethodHandling(
+ covariant ComputableAbstractValue receiver, Selector selector) =>
+ _wrappedDomain.needsNoSuchMethodHandling(_unwrap(receiver), selector);
+
+ @override
+ AbstractValue? getAbstractValueForNativeMethodParameterType(DartType type) {
+ final value =
+ _wrappedDomain.getAbstractValueForNativeMethodParameterType(type);
+ if (value == null) return null;
+ return ComputableAbstractValue(value);
+ }
+
+ @override
+ AbstractBool isIn(covariant ComputableAbstractValue subset,
+ covariant ComputableAbstractValue superset) =>
+ _wrappedDomain.isIn(_unwrap(subset), _unwrap(superset));
+
+ @override
+ MemberEntity? locateSingleMember(
+ covariant ComputableAbstractValue receiver, Selector selector) =>
+ _wrappedDomain.locateSingleMember(_unwrap(receiver), selector);
+
+ @override
+ AbstractBool isJsIndexable(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isJsIndexable(_unwrap(value));
+
+ @override
+ AbstractBool isJsIndexableAndIterable(
+ covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isJsIndexableAndIterable(_unwrap(value));
+
+ @override
+ AbstractBool isFixedLengthJsIndexable(
+ covariant ComputableAbstractValue value) =>
+ _wrappedDomain.isFixedLengthJsIndexable(_unwrap(value));
+
+ @override
+ String getCompactText(covariant ComputableAbstractValue value) =>
+ _wrappedDomain.getCompactText(_unwrap(value));
+
+ @override
+ AbstractValue readAbstractValueFromDataSource(DataSourceReader source) =>
+ ComputableAbstractValue(
+ _wrappedDomain.readAbstractValueFromDataSource(source));
+
+ @override
+ void writeAbstractValueToDataSink(
+ DataSinkWriter sink, covariant ComputableAbstractValue value) {
+ _wrappedDomain.writeAbstractValueToDataSink(sink, _unwrap(value));
+ }
+}
+
+class ComputableAbstractValueStrategy implements AbstractValueStrategy {
+ final AbstractValueStrategy _wrappedStrategy;
+
+ const ComputableAbstractValueStrategy(this._wrappedStrategy);
+
+ @override
+ AbstractValueDomain createDomain(JClosedWorld closedWorld) =>
+ ComputableAbstractValueDomain(_wrappedStrategy.createDomain(closedWorld));
+
+ @override
+ SelectorConstraintsStrategy createSelectorStrategy() =>
+ ComputableSelectorStrategy(_wrappedStrategy.createSelectorStrategy());
+}
+
+class ComputableSelectorStrategy implements SelectorConstraintsStrategy {
+ final SelectorConstraintsStrategy _wrappedStrategy;
+
+ const ComputableSelectorStrategy(this._wrappedStrategy);
+
+ // There should be no uncomputed values at this point, so throw instead of
+ // requiring a domain.
+ AbstractValue? _unwrap(ComputableAbstractValue? value) =>
+ value?._unwrapOrThrow();
+
+ @override
+ UniverseSelectorConstraints createSelectorConstraints(
+ Selector selector, Object? initialConstraint) =>
+ ComputableUniverseSelectorConstraints(
+ _wrappedStrategy.createSelectorConstraints(
+ selector, _unwrap(initialConstraint as ComputableAbstractValue)));
+
+ @override
+ bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member,
+ covariant JClosedWorld world) =>
+ _wrappedStrategy.appliedUnnamed(
+ dynamicUse.withReceiverConstraint(_unwrap(
+ dynamicUse.receiverConstraint as ComputableAbstractValue)),
+ member,
+ world);
+}
+
+class ComputableUniverseSelectorConstraints
+ implements UniverseSelectorConstraints {
+ final UniverseSelectorConstraints _universeSelectorConstraints;
+
+ const ComputableUniverseSelectorConstraints(
+ this._universeSelectorConstraints);
+
+ // There should be no uncomputed values at this point, so throw instead of
+ // requiring a domain.
+ AbstractValue? _unwrap(ComputableAbstractValue? value) =>
+ value?._unwrapOrThrow();
+
+ @override
+ bool addReceiverConstraint(covariant ComputableAbstractValue constraint) =>
+ _universeSelectorConstraints.addReceiverConstraint(_unwrap(constraint));
+
+ @override
+ bool needsNoSuchMethodHandling(Selector selector, World world) =>
+ _universeSelectorConstraints.needsNoSuchMethodHandling(selector, world);
+
+ @override
+ bool canHit(MemberEntity element, Name name, World world) =>
+ _universeSelectorConstraints.canHit(element, name, world);
+
+ @override
+ String toString() => 'ComputableUniverseSelectorConstraints:$hashCode';
+}
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
index 8b53761..0449df3 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
@@ -53,7 +53,7 @@
: PowersetValue(abstractValue, powersetBits);
}
-class PowersetDomain implements AbstractValueDomain {
+class PowersetDomain with AbstractValueDomain {
final AbstractValueDomain _abstractValueDomain;
final PowersetBitsDomain _powersetBitsDomain;
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index 61dbb61..2ee1e5b 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -22,7 +22,7 @@
String toString() => '?';
}
-class TrivialAbstractValueDomain implements AbstractValueDomain {
+class TrivialAbstractValueDomain with AbstractValueDomain {
const TrivialAbstractValueDomain();
@override
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index fa20fb2..a6cd6eb 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -177,7 +177,7 @@
bool reset(InferrerEngine inferrer) {
if (abandonInferencing) return false;
- type = inferrer.abstractValueDomain.emptyType;
+ type = inferrer.abstractValueDomain.uncomputedType;
refineCount = 0;
return true;
}
@@ -247,7 +247,7 @@
class PlaceholderTypeInformation extends TypeInformation {
PlaceholderTypeInformation(
AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
void accept(TypeInformationVisitor visitor) {
@@ -380,10 +380,11 @@
ElementTypeInformation._internal(
AbstractValueDomain abstractValueDomain, MemberTypeInformation? context)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
+
ElementTypeInformation._withInputs(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, ParameterInputs inputs)
- : super.withInputs(abstractValueDomain.emptyType, context, inputs);
+ : super.withInputs(abstractValueDomain.uncomputedType, context, inputs);
String getInferredSignature(TypeSystem types);
@@ -967,9 +968,8 @@
this.selector,
this.arguments,
this.inLoop)
- : super.noInputs(abstractValueDomain.emptyType, context) {
- assert(_call is ir.Node || (_call == null && selector?.name == '=='));
- }
+ : assert(_call is ir.Node || (_call == null && selector?.name == '==')),
+ super.noInputs(abstractValueDomain.uncomputedType, context);
@override
String toString() => 'Call site $debugName $type';
@@ -1603,7 +1603,7 @@
NarrowTypeInformation(AbstractValueDomain abstractValueDomain,
TypeInformation narrowedType, this.typeAnnotation)
- : super(abstractValueDomain.emptyType, narrowedType.context) {
+ : super(abstractValueDomain.uncomputedType, narrowedType.context) {
addInput(narrowedType);
}
@@ -1643,7 +1643,7 @@
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, TypeInformation? parentType)
- : super(abstractValueDomain.emptyType, context) {
+ : super(abstractValueDomain.uncomputedType, context) {
if (parentType != null) addInput(parentType);
}
@@ -2025,7 +2025,7 @@
PhiElementTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, this.branchNode, this.variable,
{required this.isTry})
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
AbstractValue computeType(InferrerEngine inferrer) {
@@ -2062,7 +2062,7 @@
ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, this._element)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
FunctionEntity get closure => _element;
@@ -2126,7 +2126,7 @@
AwaitTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, this._node)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
// TODO(22894): Compute a better type here.
@override
@@ -2148,7 +2148,7 @@
YieldTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, this._node)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index b12d9c3..bdad0fe 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -35,7 +35,7 @@
part 'union_type_mask.dart';
part 'value_type_mask.dart';
-class CommonMasks implements AbstractValueDomain {
+class CommonMasks with AbstractValueDomain {
// TODO(sigmund): once we split out the backend common elements, depend
// directly on those instead.
final JClosedWorld _closedWorld;
diff --git a/pkg/compiler/lib/src/inferrer/wrapped.dart b/pkg/compiler/lib/src/inferrer/wrapped.dart
index 455c84f..dbc1005 100644
--- a/pkg/compiler/lib/src/inferrer/wrapped.dart
+++ b/pkg/compiler/lib/src/inferrer/wrapped.dart
@@ -43,7 +43,7 @@
return abstractValue == null ? null : WrappedAbstractValue(abstractValue);
}
-class WrappedAbstractValueDomain implements AbstractValueDomain {
+class WrappedAbstractValueDomain with AbstractValueDomain {
final AbstractValueDomain _abstractValueDomain;
const WrappedAbstractValueDomain(this._abstractValueDomain);
diff --git a/pkg/compiler/lib/src/inferrer_experimental/powersets/powersets.dart b/pkg/compiler/lib/src/inferrer_experimental/powersets/powersets.dart
index 86bad4e..0b56518 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/powersets/powersets.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/powersets/powersets.dart
@@ -53,7 +53,7 @@
: PowersetValue(abstractValue, powersetBits);
}
-class PowersetDomain implements AbstractValueDomain {
+class PowersetDomain with AbstractValueDomain {
final AbstractValueDomain _abstractValueDomain;
final PowersetBitsDomain _powersetBitsDomain;
diff --git a/pkg/compiler/lib/src/inferrer_experimental/trivial.dart b/pkg/compiler/lib/src/inferrer_experimental/trivial.dart
index ba3e67e..56a01aa 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/trivial.dart
@@ -22,7 +22,7 @@
String toString() => '?';
}
-class TrivialAbstractValueDomain implements AbstractValueDomain {
+class TrivialAbstractValueDomain with AbstractValueDomain {
const TrivialAbstractValueDomain();
@override
diff --git a/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
index cfd56d8..15128e4 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
@@ -177,7 +177,7 @@
bool reset(InferrerEngine inferrer) {
if (abandonInferencing) return false;
- type = inferrer.abstractValueDomain.emptyType;
+ type = inferrer.abstractValueDomain.uncomputedType;
refineCount = 0;
return true;
}
@@ -247,7 +247,7 @@
class PlaceholderTypeInformation extends TypeInformation {
PlaceholderTypeInformation(
AbstractValueDomain abstractValueDomain, MemberTypeInformation context)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
void accept(TypeInformationVisitor visitor) {
@@ -380,10 +380,11 @@
ElementTypeInformation._internal(
AbstractValueDomain abstractValueDomain, MemberTypeInformation? context)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
+
ElementTypeInformation._withInputs(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, ParameterInputs inputs)
- : super.withInputs(abstractValueDomain.emptyType, context, inputs);
+ : super.withInputs(abstractValueDomain.uncomputedType, context, inputs);
String getInferredSignature(TypeSystem types);
@@ -967,9 +968,8 @@
this.selector,
this.arguments,
this.inLoop)
- : super.noInputs(abstractValueDomain.emptyType, context) {
- assert(_call is ir.Node || (_call == null && selector?.name == '=='));
- }
+ : assert(_call is ir.Node || (_call == null && selector?.name == '==')),
+ super.noInputs(abstractValueDomain.uncomputedType, context);
@override
String toString() => 'Call site $debugName $type';
@@ -1596,7 +1596,7 @@
NarrowTypeInformation(AbstractValueDomain abstractValueDomain,
TypeInformation narrowedType, this.typeAnnotation)
- : super(abstractValueDomain.emptyType, narrowedType.context) {
+ : super(abstractValueDomain.uncomputedType, narrowedType.context) {
addInput(narrowedType);
}
@@ -1636,7 +1636,7 @@
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, TypeInformation? parentType)
- : super(abstractValueDomain.emptyType, context) {
+ : super(abstractValueDomain.uncomputedType, context) {
if (parentType != null) addInput(parentType);
}
@@ -2018,7 +2018,7 @@
PhiElementTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, this.branchNode, this.variable,
{required this.isTry})
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
AbstractValue computeType(InferrerEngine inferrer) {
@@ -2055,7 +2055,7 @@
ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation? context, this._element)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
FunctionEntity get closure => _element;
@@ -2119,7 +2119,7 @@
AwaitTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, this._node)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
// TODO(22894): Compute a better type here.
@override
@@ -2141,7 +2141,7 @@
YieldTypeInformation(AbstractValueDomain abstractValueDomain,
MemberTypeInformation context, this._node)
- : super(abstractValueDomain.emptyType, context);
+ : super(abstractValueDomain.uncomputedType, context);
@override
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
diff --git a/pkg/compiler/lib/src/inferrer_experimental/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer_experimental/typemasks/masks.dart
index 209aa06..271bd78 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/typemasks/masks.dart
@@ -35,7 +35,7 @@
part 'union_type_mask.dart';
part 'value_type_mask.dart';
-class CommonMasks implements AbstractValueDomain {
+class CommonMasks with AbstractValueDomain {
// TODO(sigmund): once we split out the backend common elements, depend
// directly on those instead.
final JClosedWorld _closedWorld;
diff --git a/pkg/compiler/lib/src/inferrer_experimental/wrapped.dart b/pkg/compiler/lib/src/inferrer_experimental/wrapped.dart
index 2f5f04d..31188fa 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/wrapped.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/wrapped.dart
@@ -43,7 +43,7 @@
return abstractValue == null ? null : WrappedAbstractValue(abstractValue);
}
-class WrappedAbstractValueDomain implements AbstractValueDomain {
+class WrappedAbstractValueDomain with AbstractValueDomain {
final AbstractValueDomain _abstractValueDomain;
const WrappedAbstractValueDomain(this._abstractValueDomain);