mirror of
https://github.com/dart-lang/sdk
synced 2024-09-04 16:03:44 +00:00
[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>
This commit is contained in:
parent
053c633d0b
commit
278815b192
|
@ -38,8 +38,9 @@ import 'elements/entities.dart';
|
|||
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 @@ class Compiler
|
|||
} else if (options.experimentalPowersets) {
|
||||
abstractValueStrategy = PowersetStrategy(abstractValueStrategy);
|
||||
}
|
||||
if (options.debugGlobalInference) {
|
||||
abstractValueStrategy =
|
||||
ComputableAbstractValueStrategy(abstractValueStrategy);
|
||||
}
|
||||
|
||||
CompilerTask kernelFrontEndTask;
|
||||
selfTask = GenericTask('self', measurer);
|
||||
|
|
|
@ -92,6 +92,12 @@ class AbstractValueWithPrecision {
|
|||
|
||||
/// 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;
|
||||
|
|
673
pkg/compiler/lib/src/inferrer/computable.dart
Normal file
673
pkg/compiler/lib/src/inferrer/computable.dart
Normal file
|
@ -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';
|
||||
}
|
|
@ -53,7 +53,7 @@ PowersetValue? wrapOrNull(AbstractValue? abstractValue, int powersetBits) {
|
|||
: PowersetValue(abstractValue, powersetBits);
|
||||
}
|
||||
|
||||
class PowersetDomain implements AbstractValueDomain {
|
||||
class PowersetDomain with AbstractValueDomain {
|
||||
final AbstractValueDomain _abstractValueDomain;
|
||||
final PowersetBitsDomain _powersetBitsDomain;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class TrivialAbstractValue implements AbstractValue {
|
|||
String toString() => '?';
|
||||
}
|
||||
|
||||
class TrivialAbstractValueDomain implements AbstractValueDomain {
|
||||
class TrivialAbstractValueDomain with AbstractValueDomain {
|
||||
const TrivialAbstractValueDomain();
|
||||
|
||||
@override
|
||||
|
|
|
@ -177,7 +177,7 @@ abstract class TypeInformation {
|
|||
|
||||
bool reset(InferrerEngine inferrer) {
|
||||
if (abandonInferencing) return false;
|
||||
type = inferrer.abstractValueDomain.emptyType;
|
||||
type = inferrer.abstractValueDomain.uncomputedType;
|
||||
refineCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ abstract class ApplyableTypeInformation implements TypeInformation {
|
|||
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 @@ abstract class ElementTypeInformation extends TypeInformation {
|
|||
|
||||
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 @@ abstract class CallSiteTypeInformation extends TypeInformation
|
|||
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 @@ class NarrowTypeInformation extends TypeInformation {
|
|||
|
||||
NarrowTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
TypeInformation narrowedType, this.typeAnnotation)
|
||||
: super(abstractValueDomain.emptyType, narrowedType.context) {
|
||||
: super(abstractValueDomain.uncomputedType, narrowedType.context) {
|
||||
addInput(narrowedType);
|
||||
}
|
||||
|
||||
|
@ -1643,7 +1643,7 @@ abstract class InferredTypeInformation extends TypeInformation {
|
|||
|
||||
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation? context, TypeInformation? parentType)
|
||||
: super(abstractValueDomain.emptyType, context) {
|
||||
: super(abstractValueDomain.uncomputedType, context) {
|
||||
if (parentType != null) addInput(parentType);
|
||||
}
|
||||
|
||||
|
@ -2025,7 +2025,7 @@ class PhiElementTypeInformation extends TypeInformation {
|
|||
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 @@ class ClosureTypeInformation extends TypeInformation
|
|||
|
||||
ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation? context, this._element)
|
||||
: super(abstractValueDomain.emptyType, context);
|
||||
: super(abstractValueDomain.uncomputedType, context);
|
||||
|
||||
FunctionEntity get closure => _element;
|
||||
|
||||
|
@ -2126,7 +2126,7 @@ class AwaitTypeInformation extends TypeInformation {
|
|||
|
||||
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 @@ class YieldTypeInformation extends TypeInformation {
|
|||
|
||||
YieldTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation context, this._node)
|
||||
: super(abstractValueDomain.emptyType, context);
|
||||
: super(abstractValueDomain.uncomputedType, context);
|
||||
|
||||
@override
|
||||
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
|
||||
|
|
|
@ -35,7 +35,7 @@ part 'type_mask.dart';
|
|||
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;
|
||||
|
|
|
@ -43,7 +43,7 @@ WrappedAbstractValue? wrapOrNull(AbstractValue? abstractValue) {
|
|||
return abstractValue == null ? null : WrappedAbstractValue(abstractValue);
|
||||
}
|
||||
|
||||
class WrappedAbstractValueDomain implements AbstractValueDomain {
|
||||
class WrappedAbstractValueDomain with AbstractValueDomain {
|
||||
final AbstractValueDomain _abstractValueDomain;
|
||||
const WrappedAbstractValueDomain(this._abstractValueDomain);
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ PowersetValue? wrapOrNull(AbstractValue? abstractValue, int powersetBits) {
|
|||
: PowersetValue(abstractValue, powersetBits);
|
||||
}
|
||||
|
||||
class PowersetDomain implements AbstractValueDomain {
|
||||
class PowersetDomain with AbstractValueDomain {
|
||||
final AbstractValueDomain _abstractValueDomain;
|
||||
final PowersetBitsDomain _powersetBitsDomain;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ class TrivialAbstractValue implements AbstractValue {
|
|||
String toString() => '?';
|
||||
}
|
||||
|
||||
class TrivialAbstractValueDomain implements AbstractValueDomain {
|
||||
class TrivialAbstractValueDomain with AbstractValueDomain {
|
||||
const TrivialAbstractValueDomain();
|
||||
|
||||
@override
|
||||
|
|
|
@ -177,7 +177,7 @@ abstract class TypeInformation {
|
|||
|
||||
bool reset(InferrerEngine inferrer) {
|
||||
if (abandonInferencing) return false;
|
||||
type = inferrer.abstractValueDomain.emptyType;
|
||||
type = inferrer.abstractValueDomain.uncomputedType;
|
||||
refineCount = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ abstract class ApplyableTypeInformation implements TypeInformation {
|
|||
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 @@ abstract class ElementTypeInformation extends TypeInformation {
|
|||
|
||||
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 @@ abstract class CallSiteTypeInformation extends TypeInformation
|
|||
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 @@ class NarrowTypeInformation extends TypeInformation {
|
|||
|
||||
NarrowTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
TypeInformation narrowedType, this.typeAnnotation)
|
||||
: super(abstractValueDomain.emptyType, narrowedType.context) {
|
||||
: super(abstractValueDomain.uncomputedType, narrowedType.context) {
|
||||
addInput(narrowedType);
|
||||
}
|
||||
|
||||
|
@ -1636,7 +1636,7 @@ abstract class InferredTypeInformation extends TypeInformation {
|
|||
|
||||
InferredTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation? context, TypeInformation? parentType)
|
||||
: super(abstractValueDomain.emptyType, context) {
|
||||
: super(abstractValueDomain.uncomputedType, context) {
|
||||
if (parentType != null) addInput(parentType);
|
||||
}
|
||||
|
||||
|
@ -2018,7 +2018,7 @@ class PhiElementTypeInformation extends TypeInformation {
|
|||
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 @@ class ClosureTypeInformation extends TypeInformation
|
|||
|
||||
ClosureTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation? context, this._element)
|
||||
: super(abstractValueDomain.emptyType, context);
|
||||
: super(abstractValueDomain.uncomputedType, context);
|
||||
|
||||
FunctionEntity get closure => _element;
|
||||
|
||||
|
@ -2119,7 +2119,7 @@ class AwaitTypeInformation extends TypeInformation {
|
|||
|
||||
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 @@ class YieldTypeInformation extends TypeInformation {
|
|||
|
||||
YieldTypeInformation(AbstractValueDomain abstractValueDomain,
|
||||
MemberTypeInformation context, this._node)
|
||||
: super(abstractValueDomain.emptyType, context);
|
||||
: super(abstractValueDomain.uncomputedType, context);
|
||||
|
||||
@override
|
||||
AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
|
||||
|
|
|
@ -35,7 +35,7 @@ part 'type_mask.dart';
|
|||
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;
|
||||
|
|
|
@ -43,7 +43,7 @@ WrappedAbstractValue? wrapOrNull(AbstractValue? abstractValue) {
|
|||
return abstractValue == null ? null : WrappedAbstractValue(abstractValue);
|
||||
}
|
||||
|
||||
class WrappedAbstractValueDomain implements AbstractValueDomain {
|
||||
class WrappedAbstractValueDomain with AbstractValueDomain {
|
||||
final AbstractValueDomain _abstractValueDomain;
|
||||
const WrappedAbstractValueDomain(this._abstractValueDomain);
|
||||
|
||||
|
|
Loading…
Reference in a new issue