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

Unified Diff: pkg/compiler/lib/src/cps_ir/type_mask_system.dart

Issue 1415883005: Introduce AbstractValue and AbstractValueDomain (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comments. Created 5 years 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: pkg/compiler/lib/src/cps_ir/type_mask_system.dart
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
index 58d7330cc754175d428d52499d86a7e1c60d0ad0..a0da73e51282875c0c5004737d4d991fd609b624 100644
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
@@ -11,17 +11,13 @@ import '../dart_types.dart' as types;
import '../elements/elements.dart';
import '../js_backend/backend_helpers.dart' show BackendHelpers;
import '../js_backend/js_backend.dart' show JavaScriptBackend;
+import '../types/abstract_value_domain.dart';
import '../types/types.dart';
import '../types/constants.dart' show computeTypeMask;
import '../universe/selector.dart' show Selector;
-import '../universe/call_structure.dart' show CallStructure;
import '../world.dart' show World;
-enum AbstractBool {
- True, False, Maybe, Nothing
-}
-
-class TypeMaskSystem {
+class TypeMaskSystem implements AbstractValueDomain {
final TypesTask inferrer;
final World classWorld;
final JavaScriptBackend backend;
@@ -33,27 +29,62 @@ class TypeMaskSystem {
TypeMask __indexableTypeTest;
+ @override
TypeMask get dynamicType => inferrer.dynamicType;
+
+ @override
TypeMask get typeType => inferrer.typeType;
+
+ @override
TypeMask get functionType => inferrer.functionType;
+
+ @override
TypeMask get boolType => inferrer.boolType;
+
+ @override
TypeMask get intType => inferrer.intType;
+
+ @override
TypeMask get doubleType => inferrer.doubleType;
+
+ @override
TypeMask get numType => inferrer.numType;
+
+ @override
TypeMask get stringType => inferrer.stringType;
+
+ @override
TypeMask get listType => inferrer.listType;
+
+ @override
TypeMask get mapType => inferrer.mapType;
+
+ @override
TypeMask get nonNullType => inferrer.nonNullType;
+
+ @override
TypeMask get nullType => inferrer.nullType;
+
+ @override
TypeMask get extendableArrayType => backend.extendableArrayType;
+
+ @override
TypeMask get fixedArrayType => backend.fixedArrayType;
+
+ @override
TypeMask get arrayType =>
new TypeMask.nonNullSubclass(helpers.jsArrayClass, classWorld);
+ @override
TypeMask get uint31Type => inferrer.uint31Type;
+
+ @override
TypeMask get uint32Type => inferrer.uint32Type;
+
+ @override
TypeMask get uintType => inferrer.positiveIntType;
+ @override
TypeMask get numStringBoolType {
if (_numStringBoolType == null) {
// Build the number+string+bool type. To make containment tests more
@@ -72,6 +103,7 @@ class TypeMaskSystem {
return _numStringBoolType;
}
+ @override
TypeMask get fixedLengthType {
if (_fixedLengthType == null) {
List<TypeMask> fixedLengthTypes =
@@ -84,6 +116,7 @@ class TypeMaskSystem {
return _fixedLengthType;
}
+ @override
TypeMask get interceptorType {
if (_interceptorType == null) {
_interceptorType =
@@ -92,6 +125,7 @@ class TypeMaskSystem {
return _interceptorType;
}
+ @override
TypeMask get interceptedTypes { // Does not include null.
if (_interceptedTypes == null) {
// We redundantly include subtypes of num/string/bool as intercepted
@@ -130,6 +164,7 @@ class TypeMaskSystem {
backend = compiler.backend {
}
+ @override
bool methodUsesReceiverArgument(FunctionElement function) {
assert(backend.isInterceptedMethod(function));
ClassElement clazz = function.enclosingClass.declaration;
@@ -137,18 +172,22 @@ class TypeMaskSystem {
classWorld.isUsedAsMixin(clazz);
}
+ @override
Element locateSingleElement(TypeMask mask, Selector selector) {
return mask.locateSingleElement(selector, mask, classWorld.compiler);
}
+ @override
ClassElement singleClass(TypeMask mask) {
return mask.singleClass(classWorld);
}
+ @override
bool needsNoSuchMethodHandling(TypeMask mask, Selector selector) {
return mask.needsNoSuchMethodHandling(selector, classWorld);
}
+ @override
TypeMask getReceiverType(MethodElement method) {
assert(method.isInstanceMember);
if (classWorld.isUsedAsMixin(method.enclosingClass.declaration)) {
@@ -161,14 +200,17 @@ class TypeMaskSystem {
}
}
+ @override
TypeMask getParameterType(ParameterElement parameter) {
return inferrer.getGuaranteedTypeOfElement(parameter);
}
+ @override
TypeMask getReturnType(FunctionElement function) {
return inferrer.getGuaranteedReturnTypeOfElement(function);
}
+ @override
TypeMask getInvokeReturnType(Selector selector, TypeMask mask) {
TypeMask result = inferrer.getGuaranteedTypeOfSelector(selector, mask);
// Tearing off .call from a function returns the function itself.
@@ -180,26 +222,29 @@ class TypeMaskSystem {
return result;
}
+ @override
TypeMask getFieldType(FieldElement field) {
return inferrer.getGuaranteedTypeOfElement(field);
}
+ @override
TypeMask join(TypeMask a, TypeMask b) {
return a.union(b, classWorld);
}
+ @override
TypeMask intersection(TypeMask a, TypeMask b) {
if (a == null) return b;
if (b == null) return a;
return a.intersection(b, classWorld);
}
+ @override
TypeMask getTypeOf(ConstantValue constant) {
return computeTypeMask(inferrer.compiler, constant);
}
- // Returns the constant value if a TypeMask represents a single value.
- // Returns `null` if [mask] is not a constant.
+ @override
ConstantValue getConstantOf(TypeMask mask) {
if (!mask.isValue) return null;
if (mask.isNullable) return null; // e.g. 'true or null'.
@@ -209,7 +254,9 @@ class TypeMaskSystem {
return null;
}
+ @override
TypeMask nonNullExact(ClassElement element) {
+ // TODO(johnniwinther): I don't think the follow is valid anymore.
// The class world does not know about classes created by
// closure conversion, so just treat those as a subtypes of Function.
// TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
@@ -217,36 +264,43 @@ class TypeMaskSystem {
return new TypeMask.nonNullExact(element.declaration, classWorld);
}
+ @override
TypeMask nonNullSubclass(ClassElement element) {
if (element.isClosure) return functionType;
return new TypeMask.nonNullSubclass(element.declaration, classWorld);
}
+ @override
TypeMask nonNullSubtype(ClassElement element) {
if (element.isClosure) return functionType;
return new TypeMask.nonNullSubtype(element.declaration, classWorld);
}
+ @override
bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().containsOnlyBool(classWorld);
}
+ @override
bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().containsOnlyNum(classWorld);
}
+ @override
bool isDefinitelyString(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().containsOnlyString(classWorld);
}
+ @override
bool isDefinitelyNumStringBool(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return numStringBoolType.containsMask(t.nonNullable(), classWorld);
}
+ @override
bool isDefinitelyNotNumStringBool(TypeMask t) {
return areDisjoint(t, numStringBoolType);
}
@@ -255,6 +309,7 @@ class TypeMaskSystem {
///
/// This does not imply that the value is an integer, since most other values
/// such as null are also not a non-integer double.
+ @override
bool isDefinitelyNotNonIntegerDouble(TypeMask t) {
// Even though int is a subclass of double in the JS type system, we can
// still check this with disjointness, because [doubleType] is the *exact*
@@ -265,69 +320,82 @@ class TypeMaskSystem {
return areDisjoint(t, doubleType);
}
+ @override
bool isDefinitelyNonNegativeInt(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
// The JSPositiveInt class includes zero, despite the name.
return t.satisfies(helpers.jsPositiveIntClass, classWorld);
}
+ @override
bool isDefinitelyInt(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().containsOnlyInt(classWorld);
}
+ @override
bool isDefinitelyUint31(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.satisfies(helpers.jsUInt31Class, classWorld);
}
+ @override
bool isDefinitelyUint32(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.satisfies(helpers.jsUInt32Class, classWorld);
}
+ @override
bool isDefinitelyUint(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.satisfies(helpers.jsPositiveIntClass, classWorld);
}
+ @override
bool isDefinitelyArray(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(helpers.jsArrayClass, classWorld);
}
+ @override
bool isDefinitelyMutableArray(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(helpers.jsMutableArrayClass, classWorld);
}
+ @override
bool isDefinitelyFixedArray(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(helpers.jsFixedArrayClass, classWorld);
}
+ @override
bool isDefinitelyExtendableArray(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(helpers.jsExtendableArrayClass,
classWorld);
}
+ @override
bool isDefinitelyIndexable(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return _indexableTypeTest.containsMask(t.nonNullable(), classWorld);
}
+ @override
bool isDefinitelyMutableIndexable(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return t.nonNullable().satisfies(helpers.jsMutableIndexableClass,
classWorld);
}
+ @override
bool isDefinitelyFixedLengthIndexable(TypeMask t, {bool allowNull: false}) {
if (!allowNull && t.isNullable) return false;
return fixedLengthType.containsMask(t.nonNullable(), classWorld);
}
+ @override
bool isDefinitelyIntercepted(TypeMask t, {bool allowNull}) {
assert(allowNull != null);
if (!allowNull && t.isNullable) return false;
@@ -336,6 +404,7 @@ class TypeMaskSystem {
/// Given a class from the interceptor hierarchy, returns a [TypeMask]
/// matching all values with that interceptor (or a subtype thereof).
+ @override
TypeMask getInterceptorSubtypes(ClassElement class_) {
if (class_ == helpers.jsInterceptorClass) {
return interceptorType.nullable();
@@ -346,15 +415,18 @@ class TypeMaskSystem {
}
}
+ @override
bool areDisjoint(TypeMask leftType, TypeMask rightType) {
TypeMask intersected = intersection(leftType, rightType);
return intersected.isEmpty && !intersected.isNullable;
}
+ @override
bool isMorePreciseOrEqual(TypeMask t1, TypeMask t2) {
return t2.containsMask(t1, classWorld);
}
+ @override
AbstractBool isSubtypeOf(TypeMask value,
types.DartType type,
{bool allowNull}) {
@@ -390,6 +462,7 @@ class TypeMaskSystem {
/// Returns whether [type] is one of the falsy values: false, 0, -0, NaN,
/// the empty string, or null.
+ @override
AbstractBool boolify(TypeMask type) {
if (isDefinitelyNotNumStringBool(type) && !type.isNullable) {
return AbstractBool.True;
@@ -397,12 +470,14 @@ class TypeMaskSystem {
return AbstractBool.Maybe;
}
+ @override
AbstractBool strictBoolify(TypeMask type) {
if (areDisjoint(type, boolType)) return AbstractBool.False;
return AbstractBool.Maybe;
}
/// Create a type mask containing at least all subtypes of [type].
+ @override
TypeMask subtypesOf(types.DartType type) {
if (type is types.InterfaceType) {
ClassElement element = type.element;
@@ -435,12 +510,14 @@ class TypeMaskSystem {
/// Returns a subset of [mask] containing at least the types
/// that can respond to [selector] without throwing.
+ @override
TypeMask receiverTypeFor(Selector selector, TypeMask mask) {
return classWorld.allFunctions.receiverType(selector, mask);
}
/// The result of an index operation on something of [type], or the dynamic
/// type if unknown.
+ @override
TypeMask elementTypeOfIndexable(TypeMask type) {
if (type is UnionTypeMask) {
return new TypeMask.unionOf(
@@ -462,6 +539,7 @@ class TypeMaskSystem {
}
/// The length of something of [type], or `null` if unknown.
+ @override
int getContainerLength(TypeMask type) {
if (type is ContainerTypeMask) {
return type.length;
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/type_propagation.dart » ('j') | pkg/compiler/lib/src/cps_ir/type_propagation.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698