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

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

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 months 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
deleted file mode 100644
index 773b96f5c75e4fb3f5ef10e1456501f0a5ffc962..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart
+++ /dev/null
@@ -1,616 +0,0 @@
-// Copyright (c) 2015, 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.
-
-library dart2js.type_mask_system;
-
-import '../closure.dart' show ClosureFieldElement, BoxLocal, TypeVariableLocal;
-import '../common/names.dart' show Identifiers;
-import '../compiler.dart' as dart2js show Compiler;
-import '../constants/values.dart';
-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/constants.dart' show computeTypeMask;
-import '../types/types.dart';
-import '../universe/selector.dart' show Selector;
-import '../world.dart' show World;
-
-class TypeMaskSystem implements AbstractValueDomain {
- final TypesTask inferrer;
- final World classWorld;
- final JavaScriptBackend backend;
-
- TypeMask _numStringBoolType;
- TypeMask _fixedLengthType;
- TypeMask _interceptorType;
- TypeMask _interceptedTypes; // Does not include null.
-
- TypeMask __indexableTypeTest;
-
- // The full type of a constant (e.g. a ContainerTypeMask) is not available on
- // the constant. Type inference flows the type to some place where it is used,
- // e.g. a parameter. For constant values that are the value of static const
- // fields we need to remember the association.
- final Map<ConstantValue, TypeMask> _constantMasks =
- <ConstantValue, TypeMask>{};
-
- @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
- // inclusive, we use the num, String, bool types for this, not
- // the JSNumber, JSString, JSBool subclasses.
- TypeMask anyNum =
- new TypeMask.nonNullSubtype(classWorld.numClass, classWorld);
- TypeMask anyString =
- new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
- TypeMask anyBool =
- new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld);
- _numStringBoolType = new TypeMask.unionOf(
- <TypeMask>[anyNum, anyString, anyBool], classWorld);
- }
- return _numStringBoolType;
- }
-
- @override
- TypeMask get fixedLengthType {
- if (_fixedLengthType == null) {
- List<TypeMask> fixedLengthTypes = <TypeMask>[
- stringType,
- backend.fixedArrayType
- ];
- if (classWorld.isInstantiated(helpers.typedArrayClass)) {
- fixedLengthTypes.add(nonNullSubclass(helpers.typedArrayClass));
- }
- _fixedLengthType = new TypeMask.unionOf(fixedLengthTypes, classWorld);
- }
- return _fixedLengthType;
- }
-
- @override
- TypeMask get interceptorType {
- if (_interceptorType == null) {
- _interceptorType =
- new TypeMask.nonNullSubtype(helpers.jsInterceptorClass, classWorld);
- }
- return _interceptorType;
- }
-
- @override
- TypeMask get interceptedTypes {
- // Does not include null.
- if (_interceptedTypes == null) {
- // We redundantly include subtypes of num/string/bool as intercepted
- // types, because the type system does not infer that their
- // implementations are all subclasses of Interceptor.
- _interceptedTypes = new TypeMask.unionOf(
- <TypeMask>[interceptorType, numStringBoolType], classWorld);
- }
- return _interceptedTypes;
- }
-
- TypeMask get _indexableTypeTest {
- if (__indexableTypeTest == null) {
- // Make a TypeMask containing Indexable and (redundantly) subtypes of
- // string because the type inference does not infer that all strings are
- // indexables.
- TypeMask indexable =
- new TypeMask.nonNullSubtype(helpers.jsIndexableClass, classWorld);
- TypeMask anyString =
- new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
- __indexableTypeTest =
- new TypeMask.unionOf(<TypeMask>[indexable, anyString], classWorld);
- }
- return __indexableTypeTest;
- }
-
- ClassElement get jsNullClass => helpers.jsNullClass;
-
- BackendHelpers get helpers => backend.helpers;
-
- // TODO(karlklose): remove compiler here.
- TypeMaskSystem(dart2js.Compiler compiler)
- : inferrer = compiler.typesTask,
- classWorld = compiler.world,
- backend = compiler.backend {}
-
- @override
- bool methodIgnoresReceiverArgument(FunctionElement function) {
- assert(backend.isInterceptedMethod(function));
- ClassElement clazz = function.enclosingClass.declaration;
- return !clazz.isSubclassOf(helpers.jsInterceptorClass) &&
- !classWorld.isUsedAsMixin(clazz);
- }
-
- @override
- bool targetIgnoresReceiverArgument(TypeMask type, Selector selector) {
- // Check if any of the possible targets depend on the extra receiver
- // argument. Mixins do this, and tear-offs always needs the extra receiver
- // argument because BoundClosure uses it for equality and hash code.
- // TODO(15933): Make automatically generated property extraction
- // closures work with the dummy receiver optimization.
- bool needsReceiver(Element target) {
- if (target is! FunctionElement) return false;
- FunctionElement function = target;
- return selector.isGetter && !function.isGetter ||
- !methodIgnoresReceiverArgument(function);
- }
-
- return !classWorld.allFunctions.filter(selector, type).any(needsReceiver);
- }
-
- @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)) {
- // If used as a mixin, the receiver could be any of the classes that mix
- // in the class, and these are not considered subclasses.
- // TODO(asgerf): Exclude the subtypes that only `implement` the class.
- return nonNullSubtype(method.enclosingClass);
- } else {
- return nonNullSubclass(method.enclosingClass);
- }
- }
-
- @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.
- if (selector.isGetter &&
- selector.name == Identifiers.call &&
- !areDisjoint(functionType, mask)) {
- result = join(result, functionType);
- }
- return result;
- }
-
- @override
- TypeMask getFieldType(FieldElement field) {
- if (field is ClosureFieldElement) {
- // The type inference does not report types for all closure fields.
- // Box fields are never null.
- if (field.local is BoxLocal) return nonNullType;
- // Closure fields for type variables contain the internal representation
- // of the type (which can be null), not the Type object.
- if (field.local is TypeVariableLocal) return dynamicType;
- }
- 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);
- }
-
- void associateConstantValueWithElement(
- ConstantValue constant, Element element) {
- // TODO(25093): Replace this code with an approach that works for anonymous
- // constants and non-constant literals.
- if (constant is ListConstantValue || constant is MapConstantValue) {
- // Inferred type is usually better (e.g. a ContainerTypeMask) but is
- // occasionally less general.
- TypeMask computed = computeTypeMask(inferrer.compiler, constant);
- TypeMask inferred = inferrer.getGuaranteedTypeOfElement(element);
- TypeMask best = intersection(inferred, computed);
- assert(!best.isEmptyOrNull);
- _constantMasks[constant] = best;
- }
- }
-
- @override
- TypeMask getTypeOf(ConstantValue constant) {
- return _constantMasks[constant] ??
- computeTypeMask(inferrer.compiler, constant);
- }
-
- @override
- ConstantValue getConstantOf(TypeMask mask) {
- if (!mask.isValue) return null;
- if (mask.isNullable) return null; // e.g. 'true or null'.
- ValueTypeMask valueMask = mask;
- if (valueMask.value.isBool) return valueMask.value;
- // TODO(sra): Consider other values. Be careful with large strings.
- 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?
- if (element.isClosure) return functionType;
- 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);
- }
-
- /// True if all values of [t] are either integers or not numbers at all.
- ///
- /// 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*
- // double class, so this excludes things that are known to be instances of a
- // more specific class.
- // We currently exploit that there are no subclasses of double that are
- // not integers (e.g. there is no UnsignedDouble class or whatever).
- 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;
- return interceptedTypes.containsMask(t.nonNullable(), classWorld);
- }
-
- @override
- bool isDefinitelySelfInterceptor(TypeMask t, {bool allowNull: false}) {
- assert(allowNull != null);
- if (!allowNull && t.isNullable) return false;
- return areDisjoint(t, interceptorType);
- }
-
- /// 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();
- } else if (class_ == helpers.jsNullClass) {
- return nullType;
- } else {
- return nonNullSubclass(class_);
- }
- }
-
- @override
- bool areDisjoint(TypeMask leftType, TypeMask rightType) =>
- leftType.isDisjoint(rightType, classWorld);
-
- @override
- bool isMorePreciseOrEqual(TypeMask t1, TypeMask t2) {
- return t2.containsMask(t1, classWorld);
- }
-
- @override
- AbstractBool isSubtypeOf(TypeMask value, types.DartType type,
- {bool allowNull}) {
- assert(allowNull != null);
- if (type is types.DynamicType) {
- return AbstractBool.True;
- }
- if (type is types.InterfaceType) {
- TypeMask typeAsMask = allowNull
- ? new TypeMask.subtype(type.element, classWorld)
- : new TypeMask.nonNullSubtype(type.element, classWorld);
- if (areDisjoint(value, typeAsMask)) {
- // Disprove the subtype relation based on the class alone.
- return AbstractBool.False;
- }
- if (!type.treatAsRaw) {
- // If there are type arguments, we cannot prove the subtype relation,
- // because the type arguments are unknown on both the value and type.
- return AbstractBool.Maybe;
- }
- if (typeAsMask.containsMask(value, classWorld)) {
- // All possible values are contained in the set of allowed values.
- // Note that we exploit the fact that [typeAsMask] is an exact
- // representation of [type], not an approximation.
- return AbstractBool.True;
- }
- // The value is neither contained in the type, nor disjoint from the type.
- return AbstractBool.Maybe;
- }
- // TODO(asgerf): Support function types, and what else might be missing.
- return AbstractBool.Maybe;
- }
-
- /// 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;
- }
- 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;
- if (element.isObject) {
- return dynamicType;
- }
- if (element == classWorld.nullClass) {
- return nullType;
- }
- if (element == classWorld.stringClass) {
- return stringType;
- }
- if (element == classWorld.numClass || element == classWorld.doubleClass) {
- return numType;
- }
- if (element == classWorld.intClass) {
- return intType;
- }
- if (element == classWorld.boolClass) {
- return boolType;
- }
- return new TypeMask.nonNullSubtype(element, classWorld);
- }
- if (type is types.FunctionType) {
- return functionType;
- }
- return dynamicType;
- }
-
- /// 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(
- type.disjointMasks.map(elementTypeOfIndexable), classWorld);
- }
- if (type is ContainerTypeMask) {
- return type.elementType;
- }
- if (isDefinitelyString(type)) {
- return stringType;
- }
- if (type.satisfies(helpers.jsIndexingBehaviorInterface, classWorld)) {
- return getInvokeReturnType(new Selector.index(), type);
- }
- return dynamicType;
- }
-
- /// The length of something of [type], or `null` if unknown.
- @override
- int getContainerLength(TypeMask type) {
- if (type is ContainerTypeMask) {
- return type.length;
- } else {
- return null;
- }
- }
-
- /// Returns the type of the entry at a given index, `null` if unknown.
- TypeMask indexWithConstant(TypeMask container, ConstantValue indexValue) {
- if (container is DictionaryTypeMask) {
- if (indexValue is StringConstantValue) {
- String key = indexValue.primitiveValue.slowToString();
- TypeMask result = container.typeMap[key];
- if (result != null) return result;
- }
- }
- if (container is ContainerTypeMask) {
- return container.elementType;
- }
- return null;
- }
-}
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart ('k') | pkg/compiler/lib/src/cps_ir/type_propagation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698