mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 23:41:50 +00:00
Move remaining functionality from ClassWorld to ClosedWorld
... and rename ClassWorld to World. R=het@google.com Review URL: https://codereview.chromium.org/2366363002 .
This commit is contained in:
parent
ce596133ad
commit
a1cd695612
|
@ -1352,7 +1352,7 @@ class SimpleTypeInferrerVisitor<T>
|
|||
// In erroneous code the number of arguments in the selector might not
|
||||
// match the function element.
|
||||
// TODO(polux): return nonNullEmpty and check it doesn't break anything
|
||||
if (!selector.applies(target, compiler.backend) ||
|
||||
if (!selector.applies(target) ||
|
||||
(mask != null &&
|
||||
!mask.canHit(target, selector, compiler.closedWorld))) {
|
||||
return types.dynamicType;
|
||||
|
|
|
@ -24,7 +24,7 @@ import '../types/masks.dart'
|
|||
ValueTypeMask;
|
||||
import '../universe/selector.dart' show Selector;
|
||||
import '../util/util.dart' show ImmutableEmptySet, Setlet;
|
||||
import '../world.dart' show ClassWorld;
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'debug.dart' as debug;
|
||||
import 'inferrer_visitor.dart' show ArgumentsTypes;
|
||||
import 'type_graph_inferrer.dart'
|
||||
|
@ -867,26 +867,27 @@ class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
|
|||
*/
|
||||
TypeInformation handleIntrisifiedSelector(
|
||||
Selector selector, TypeMask mask, TypeGraphInferrerEngine inferrer) {
|
||||
ClassWorld classWorld = inferrer.closedWorld;
|
||||
if (!classWorld.backend.intImplementation.isResolved) return null;
|
||||
ClosedWorld closedWorld = inferrer.closedWorld;
|
||||
if (!closedWorld.backend.intImplementation.isResolved) return null;
|
||||
if (mask == null) return null;
|
||||
if (!mask.containsOnlyInt(classWorld)) {
|
||||
if (!mask.containsOnlyInt(closedWorld)) {
|
||||
return null;
|
||||
}
|
||||
if (!selector.isCall && !selector.isOperator) return null;
|
||||
if (!arguments.named.isEmpty) return null;
|
||||
if (arguments.positional.length > 1) return null;
|
||||
|
||||
ClassElement uint31Implementation = classWorld.backend.uint31Implementation;
|
||||
bool isInt(info) => info.type.containsOnlyInt(classWorld);
|
||||
ClassElement uint31Implementation =
|
||||
closedWorld.backend.uint31Implementation;
|
||||
bool isInt(info) => info.type.containsOnlyInt(closedWorld);
|
||||
bool isEmpty(info) => info.type.isEmpty;
|
||||
bool isUInt31(info) {
|
||||
return info.type.satisfies(uint31Implementation, classWorld);
|
||||
return info.type.satisfies(uint31Implementation, closedWorld);
|
||||
}
|
||||
|
||||
bool isPositiveInt(info) {
|
||||
return info.type
|
||||
.satisfies(classWorld.backend.positiveIntImplementation, classWorld);
|
||||
return info.type.satisfies(
|
||||
closedWorld.backend.positiveIntImplementation, closedWorld);
|
||||
}
|
||||
|
||||
TypeInformation tryLater() => inferrer.types.nonNullEmptyType;
|
||||
|
|
|
@ -925,7 +925,7 @@ class JavaScriptBackend extends Backend {
|
|||
if (elements == null) return false;
|
||||
if (elements.isEmpty) return false;
|
||||
return elements.any((element) {
|
||||
return selector.applies(element, this) &&
|
||||
return selector.applies(element) &&
|
||||
(mask == null ||
|
||||
mask.canHit(element, selector, compiler.closedWorld));
|
||||
});
|
||||
|
|
|
@ -88,7 +88,7 @@ class CodegenEnqueuer implements Enqueuer {
|
|||
|
||||
Registry get mirrorDependencies => _compiler.mirrorDependencies;
|
||||
|
||||
ClassWorld get _world => _compiler.closedWorld;
|
||||
ClosedWorld get _world => _compiler.closedWorld;
|
||||
|
||||
bool get queueIsEmpty => queue.isEmpty;
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ class ClassStubGenerator {
|
|||
Set<Selector> generatedSelectors = new Set<Selector>();
|
||||
for (Selector selector in selectors.keys) {
|
||||
if (generatedSelectors.contains(selector)) continue;
|
||||
if (!selector.appliesUnnamed(member, backend)) continue;
|
||||
if (!selector.appliesUnnamed(member)) continue;
|
||||
if (selectors[selector].applies(member, selector, compiler.closedWorld)) {
|
||||
generatedSelectors.add(selector);
|
||||
|
||||
|
|
|
@ -248,7 +248,7 @@ class ParameterStubGenerator {
|
|||
new Selector.call(member.memberName, selector.callStructure);
|
||||
renamedCallSelectors.add(renamedSelector);
|
||||
|
||||
if (!renamedSelector.appliesUnnamed(member, compiler.backend)) {
|
||||
if (!renamedSelector.appliesUnnamed(member)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ class ParameterStubGenerator {
|
|||
// call-selectors (and they are in the renamedCallSelectors set.
|
||||
for (Selector selector in selectors.keys) {
|
||||
if (renamedCallSelectors.contains(selector)) continue;
|
||||
if (!selector.appliesUnnamed(member, backend)) continue;
|
||||
if (!selector.appliesUnnamed(member)) continue;
|
||||
if (!selectors[selector]
|
||||
.applies(member, selector, compiler.closedWorld)) {
|
||||
continue;
|
||||
|
|
|
@ -332,7 +332,7 @@ class SsaBuilder extends ast.Visitor
|
|||
*/
|
||||
List<HInstruction> completeDynamicSendArgumentsList(Selector selector,
|
||||
FunctionElement function, List<HInstruction> providedArguments) {
|
||||
assert(selector.applies(function, backend));
|
||||
assert(selector.applies(function));
|
||||
FunctionSignature signature = function.functionSignature;
|
||||
List<HInstruction> compiledArguments = new List<HInstruction>(
|
||||
signature.parameterCount + 1); // Plus one for receiver.
|
||||
|
@ -426,7 +426,7 @@ class SsaBuilder extends ast.Visitor
|
|||
element.isGenerativeConstructorBody,
|
||||
message: "Missing selector for inlining of $element."));
|
||||
if (selector != null) {
|
||||
if (!selector.applies(function, backend)) return false;
|
||||
if (!selector.applies(function)) return false;
|
||||
if (mask != null &&
|
||||
!mask.canHit(function, selector, compiler.closedWorld)) {
|
||||
return false;
|
||||
|
@ -3201,7 +3201,7 @@ class SsaBuilder extends ast.Visitor
|
|||
// TODO(5347): Try to avoid the need for calling [implementation] before
|
||||
// calling [makeStaticArgumentList].
|
||||
Selector selector = elements.getSelector(node);
|
||||
assert(invariant(node, selector.applies(function.implementation, backend),
|
||||
assert(invariant(node, selector.applies(function.implementation),
|
||||
message: "$selector does not apply to ${function.implementation}"));
|
||||
List<HInstruction> inputs = makeStaticArgumentList(
|
||||
selector.callStructure, node.arguments, function.implementation);
|
||||
|
@ -4453,8 +4453,7 @@ class SsaBuilder extends ast.Visitor
|
|||
List<HInstruction> setterInputs = <HInstruction>[];
|
||||
void generateSuperSendSet() {
|
||||
Selector setterSelector = elements.getSelector(node);
|
||||
if (Elements.isUnresolved(element) ||
|
||||
!setterSelector.applies(element, compiler.backend)) {
|
||||
if (Elements.isUnresolved(element) || !setterSelector.applies(element)) {
|
||||
generateSuperNoSuchMethodSend(node, setterSelector, setterInputs);
|
||||
pop();
|
||||
} else {
|
||||
|
|
|
@ -11,7 +11,7 @@ import '../js_backend/backend_helpers.dart' show BackendHelpers;
|
|||
import '../js_backend/js_backend.dart';
|
||||
import '../types/types.dart';
|
||||
import '../universe/selector.dart' show Selector;
|
||||
import '../world.dart' show ClassWorld;
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'nodes.dart';
|
||||
import 'optimize.dart';
|
||||
|
||||
|
@ -49,7 +49,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor
|
|||
|
||||
BackendHelpers get helpers => backend.helpers;
|
||||
|
||||
ClassWorld get classWorld => compiler.closedWorld;
|
||||
ClosedWorld get closedWorld => compiler.closedWorld;
|
||||
|
||||
void visitGraph(HGraph graph) {
|
||||
this.graph = graph;
|
||||
|
@ -109,8 +109,8 @@ class SsaSimplifyInterceptors extends HBaseVisitor
|
|||
|
||||
// All intercepted classes extend `Interceptor`, so if the receiver can't be
|
||||
// a class extending `Interceptor` then it can be called directly.
|
||||
return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, classWorld)
|
||||
.isDisjoint(receiver.instructionType, classWorld);
|
||||
return new TypeMask.nonNullSubclass(helpers.jsInterceptorClass, closedWorld)
|
||||
.isDisjoint(receiver.instructionType, closedWorld);
|
||||
}
|
||||
|
||||
HInstruction tryComputeConstantInterceptor(
|
||||
|
@ -145,17 +145,17 @@ class SsaSimplifyInterceptors extends HBaseVisitor
|
|||
if (type.isNull) {
|
||||
return helpers.jsNullClass;
|
||||
}
|
||||
} else if (type.containsOnlyInt(classWorld)) {
|
||||
} else if (type.containsOnlyInt(closedWorld)) {
|
||||
return helpers.jsIntClass;
|
||||
} else if (type.containsOnlyDouble(classWorld)) {
|
||||
} else if (type.containsOnlyDouble(closedWorld)) {
|
||||
return helpers.jsDoubleClass;
|
||||
} else if (type.containsOnlyBool(classWorld)) {
|
||||
} else if (type.containsOnlyBool(closedWorld)) {
|
||||
return helpers.jsBoolClass;
|
||||
} else if (type.containsOnlyString(classWorld)) {
|
||||
} else if (type.containsOnlyString(closedWorld)) {
|
||||
return helpers.jsStringClass;
|
||||
} else if (type.satisfies(helpers.jsArrayClass, classWorld)) {
|
||||
} else if (type.satisfies(helpers.jsArrayClass, closedWorld)) {
|
||||
return helpers.jsArrayClass;
|
||||
} else if (type.containsOnlyNum(classWorld) &&
|
||||
} else if (type.containsOnlyNum(closedWorld) &&
|
||||
!interceptedClasses.contains(helpers.jsIntClass) &&
|
||||
!interceptedClasses.contains(helpers.jsDoubleClass)) {
|
||||
// If the method being intercepted is not defined in [int] or [double] we
|
||||
|
@ -174,7 +174,7 @@ class SsaSimplifyInterceptors extends HBaseVisitor
|
|||
// for a subclass or call methods defined on a subclass. Provided the
|
||||
// code is completely insensitive to the specific instance subclasses, we
|
||||
// can use the non-leaf class directly.
|
||||
ClassElement element = type.singleClass(classWorld);
|
||||
ClassElement element = type.singleClass(closedWorld);
|
||||
if (element != null && backend.isNative(element)) {
|
||||
return element;
|
||||
}
|
||||
|
|
|
@ -378,7 +378,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
|||
ClosedWorld world = compiler.closedWorld;
|
||||
|
||||
bool applies(Element element) {
|
||||
return selector.applies(element, backend) &&
|
||||
return selector.applies(element) &&
|
||||
(mask == null || mask.canHit(element, selector, world));
|
||||
}
|
||||
|
||||
|
@ -427,7 +427,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
|||
return result;
|
||||
}
|
||||
} else if (selector.isGetter) {
|
||||
if (selector.applies(helpers.jsIndexableLength, backend)) {
|
||||
if (selector.applies(helpers.jsIndexableLength)) {
|
||||
HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
|
||||
if (optimized != null) return optimized;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import '../native/native.dart' as native;
|
|||
import '../tree/tree.dart' as ast;
|
||||
import '../types/types.dart';
|
||||
import '../universe/selector.dart' show Selector;
|
||||
import '../world.dart' show ClassWorld;
|
||||
import '../world.dart' show ClosedWorld;
|
||||
|
||||
class TypeMaskFactory {
|
||||
static TypeMask inferredReturnTypeForElement(
|
||||
|
@ -34,7 +34,7 @@ class TypeMaskFactory {
|
|||
var typesReturned = nativeBehavior.typesReturned;
|
||||
if (typesReturned.isEmpty) return compiler.commonMasks.dynamicType;
|
||||
|
||||
ClassWorld world = compiler.closedWorld;
|
||||
ClosedWorld world = compiler.closedWorld;
|
||||
CommonMasks commonMasks = compiler.commonMasks;
|
||||
CoreClasses coreClasses = compiler.coreClasses;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import '../elements/elements.dart';
|
|||
import '../js_backend/js_backend.dart';
|
||||
import '../types/types.dart';
|
||||
import '../universe/selector.dart' show Selector;
|
||||
import '../world.dart' show ClassWorld;
|
||||
import '../world.dart' show ClosedWorld;
|
||||
import 'nodes.dart';
|
||||
import 'optimize.dart';
|
||||
|
||||
|
@ -18,13 +18,13 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
new Map<HInstruction, Function>();
|
||||
|
||||
final Compiler compiler;
|
||||
final ClassWorld classWorld;
|
||||
final ClosedWorld closedWorld;
|
||||
JavaScriptBackend get backend => compiler.backend;
|
||||
String get name => 'type propagator';
|
||||
|
||||
SsaTypePropagator(Compiler compiler)
|
||||
: this.compiler = compiler,
|
||||
this.classWorld = compiler.closedWorld;
|
||||
this.closedWorld = compiler.closedWorld;
|
||||
|
||||
TypeMask computeType(HInstruction instruction) {
|
||||
return instruction.accept(this);
|
||||
|
@ -160,7 +160,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
TypeMask candidateType = backend.emptyType;
|
||||
for (int i = 0, length = phi.inputs.length; i < length; i++) {
|
||||
TypeMask inputType = phi.inputs[i].instructionType;
|
||||
candidateType = candidateType.union(inputType, classWorld);
|
||||
candidateType = candidateType.union(inputType, closedWorld);
|
||||
}
|
||||
return candidateType;
|
||||
}
|
||||
|
@ -173,25 +173,25 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
// We must make sure a type conversion for receiver or argument check
|
||||
// does not try to do an int check, because an int check is not enough.
|
||||
// We only do an int check if the input is integer or null.
|
||||
if (checkedType.containsOnlyNum(classWorld) &&
|
||||
!checkedType.containsOnlyDouble(classWorld) &&
|
||||
if (checkedType.containsOnlyNum(closedWorld) &&
|
||||
!checkedType.containsOnlyDouble(closedWorld) &&
|
||||
input.isIntegerOrNull(compiler)) {
|
||||
instruction.checkedType = backend.intType;
|
||||
} else if (checkedType.containsOnlyInt(classWorld) &&
|
||||
} else if (checkedType.containsOnlyInt(closedWorld) &&
|
||||
!input.isIntegerOrNull(compiler)) {
|
||||
instruction.checkedType = backend.numType;
|
||||
}
|
||||
}
|
||||
|
||||
TypeMask outputType = checkedType.intersection(inputType, classWorld);
|
||||
TypeMask outputType = checkedType.intersection(inputType, closedWorld);
|
||||
if (outputType.isEmpty) {
|
||||
// Intersection of double and integer conflicts (is empty), but JS numbers
|
||||
// can be both int and double at the same time. For example, the input
|
||||
// can be a literal double '8.0' that is marked as an integer (because 'is
|
||||
// int' will return 'true'). What we really need to do is make the
|
||||
// overlap between int and double values explicit in the TypeMask system.
|
||||
if (inputType.containsOnlyInt(classWorld) &&
|
||||
checkedType.containsOnlyDouble(classWorld)) {
|
||||
if (inputType.containsOnlyInt(closedWorld) &&
|
||||
checkedType.containsOnlyDouble(closedWorld)) {
|
||||
if (inputType.isNullable && checkedType.isNullable) {
|
||||
outputType = backend.doubleType.nullable();
|
||||
} else {
|
||||
|
@ -221,7 +221,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
HInstruction input = instruction.checkedInput;
|
||||
TypeMask inputType = input.instructionType;
|
||||
TypeMask outputType =
|
||||
instruction.knownType.intersection(inputType, classWorld);
|
||||
instruction.knownType.intersection(inputType, closedWorld);
|
||||
if (inputType != outputType) {
|
||||
input.replaceAllUsersDominatedBy(instruction.next, instruction);
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
// In some cases, we want the receiver to be an integer,
|
||||
// but that does not mean we will get a NoSuchMethodError
|
||||
// if it's not: the receiver could be a double.
|
||||
if (type.containsOnlyInt(classWorld)) {
|
||||
if (type.containsOnlyInt(closedWorld)) {
|
||||
// If the instruction's type is integer or null, the codegen
|
||||
// will emit a null check, which is enough to know if it will
|
||||
// hit a noSuchMethod.
|
||||
|
@ -274,12 +274,12 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
Element target = targets.first;
|
||||
ClassElement cls = target.enclosingClass;
|
||||
TypeMask type =
|
||||
new TypeMask.nonNullSubclass(cls.declaration, classWorld);
|
||||
new TypeMask.nonNullSubclass(cls.declaration, closedWorld);
|
||||
// TODO(ngeoffray): We currently only optimize on primitive
|
||||
// types.
|
||||
if (!type.satisfies(backend.helpers.jsIndexableClass, classWorld) &&
|
||||
!type.containsOnlyNum(classWorld) &&
|
||||
!type.containsOnlyBool(classWorld)) {
|
||||
if (!type.satisfies(backend.helpers.jsIndexableClass, closedWorld) &&
|
||||
!type.containsOnlyNum(closedWorld) &&
|
||||
!type.containsOnlyBool(closedWorld)) {
|
||||
return false;
|
||||
}
|
||||
if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
|
||||
|
@ -373,7 +373,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
|||
TypeMask computeNewType() {
|
||||
newType = compiler.closedWorld.allFunctions
|
||||
.receiverType(instruction.selector, instruction.mask);
|
||||
newType = newType.intersection(receiverType, classWorld);
|
||||
newType = newType.intersection(receiverType, closedWorld);
|
||||
return newType;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,13 +50,13 @@ class ContainerTypeMask extends ForwardingTypeMask {
|
|||
length == other.length;
|
||||
}
|
||||
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
|
||||
TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
|
||||
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
|
||||
return forwardIntersection.isNullable ? nullable() : nonNullable();
|
||||
}
|
||||
|
||||
TypeMask union(other, ClassWorld classWorld) {
|
||||
TypeMask union(other, ClosedWorld closedWorld) {
|
||||
if (this == other) {
|
||||
return this;
|
||||
} else if (equalsDisregardNull(other)) {
|
||||
|
@ -67,9 +67,9 @@ class ContainerTypeMask extends ForwardingTypeMask {
|
|||
elementType != null &&
|
||||
other.elementType != null) {
|
||||
TypeMask newElementType =
|
||||
elementType.union(other.elementType, classWorld);
|
||||
elementType.union(other.elementType, closedWorld);
|
||||
int newLength = (length == other.length) ? length : null;
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
|
||||
return new ContainerTypeMask(
|
||||
newForwardTo,
|
||||
allocationNode == other.allocationNode ? allocationNode : null,
|
||||
|
@ -79,7 +79,7 @@ class ContainerTypeMask extends ForwardingTypeMask {
|
|||
newElementType,
|
||||
newLength);
|
||||
} else {
|
||||
return forwardTo.union(other, classWorld);
|
||||
return forwardTo.union(other, closedWorld);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,13 +47,13 @@ class DictionaryTypeMask extends MapTypeMask {
|
|||
(k) => typeMap.containsKey(k) && typeMap[k] == other.typeMap[k]);
|
||||
}
|
||||
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
|
||||
TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
|
||||
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
|
||||
return forwardIntersection.isNullable ? nullable() : nonNullable();
|
||||
}
|
||||
|
||||
TypeMask union(other, ClassWorld classWorld) {
|
||||
TypeMask union(other, ClosedWorld closedWorld) {
|
||||
if (this == other) {
|
||||
return this;
|
||||
} else if (equalsDisregardNull(other)) {
|
||||
|
@ -61,9 +61,9 @@ class DictionaryTypeMask extends MapTypeMask {
|
|||
} else if (other.isEmptyOrNull) {
|
||||
return other.isNullable ? this.nullable() : this;
|
||||
} else if (other.isDictionary) {
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, classWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, classWorld);
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, closedWorld);
|
||||
Map<String, TypeMask> mappings = <String, TypeMask>{};
|
||||
typeMap.forEach((k, v) {
|
||||
if (!other.typeMap.containsKey(k)) {
|
||||
|
@ -72,7 +72,7 @@ class DictionaryTypeMask extends MapTypeMask {
|
|||
});
|
||||
other.typeMap.forEach((k, v) {
|
||||
if (typeMap.containsKey(k)) {
|
||||
mappings[k] = v.union(typeMap[k], classWorld);
|
||||
mappings[k] = v.union(typeMap[k], closedWorld);
|
||||
} else {
|
||||
mappings[k] = v.nullable();
|
||||
}
|
||||
|
@ -82,13 +82,13 @@ class DictionaryTypeMask extends MapTypeMask {
|
|||
} else if (other.isMap &&
|
||||
(other.keyType != null) &&
|
||||
(other.valueType != null)) {
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, classWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, classWorld);
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, closedWorld);
|
||||
return new MapTypeMask(
|
||||
newForwardTo, null, null, newKeyType, newValueType);
|
||||
} else {
|
||||
return forwardTo.union(other, classWorld);
|
||||
return forwardTo.union(other, closedWorld);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -565,13 +565,11 @@ class FlatTypeMask implements TypeMask {
|
|||
} else if (isExact) {
|
||||
return hasElementIn(self, selector, element);
|
||||
} else if (isSubclass) {
|
||||
assert(closedWorld.isClosed);
|
||||
return hasElementIn(self, selector, element) ||
|
||||
other.isSubclassOf(self) ||
|
||||
closedWorld.hasAnySubclassThatMixes(self, other);
|
||||
} else {
|
||||
assert(isSubtype);
|
||||
assert(closedWorld.isClosed);
|
||||
bool result = hasElementIn(self, selector, element) ||
|
||||
other.implementsInterface(self) ||
|
||||
closedWorld.hasAnySubclassThatImplements(other, base) ||
|
||||
|
@ -602,7 +600,7 @@ class FlatTypeMask implements TypeMask {
|
|||
ClassElement enclosingClass = element.enclosingClass;
|
||||
return hasConcreteMatch(enclosingClass.superclass, selector, world);
|
||||
}
|
||||
return selector.appliesUntyped(element, world.backend);
|
||||
return selector.appliesUntyped(element);
|
||||
}
|
||||
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
|
||||
|
|
|
@ -26,55 +26,55 @@ abstract class ForwardingTypeMask implements TypeMask {
|
|||
bool get isValue => false;
|
||||
bool get isForwarding => true;
|
||||
|
||||
bool isInMask(TypeMask other, ClassWorld classWorld) {
|
||||
return forwardTo.isInMask(other, classWorld);
|
||||
bool isInMask(TypeMask other, ClosedWorld closedWorld) {
|
||||
return forwardTo.isInMask(other, closedWorld);
|
||||
}
|
||||
|
||||
bool containsMask(TypeMask other, ClassWorld classWorld) {
|
||||
return forwardTo.containsMask(other, classWorld);
|
||||
bool containsMask(TypeMask other, ClosedWorld closedWorld) {
|
||||
return forwardTo.containsMask(other, closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnlyInt(ClassWorld classWorld) {
|
||||
return forwardTo.containsOnlyInt(classWorld);
|
||||
bool containsOnlyInt(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsOnlyInt(closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnlyDouble(ClassWorld classWorld) {
|
||||
return forwardTo.containsOnlyDouble(classWorld);
|
||||
bool containsOnlyDouble(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsOnlyDouble(closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnlyNum(ClassWorld classWorld) {
|
||||
return forwardTo.containsOnlyNum(classWorld);
|
||||
bool containsOnlyNum(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsOnlyNum(closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnlyBool(ClassWorld classWorld) {
|
||||
return forwardTo.containsOnlyBool(classWorld);
|
||||
bool containsOnlyBool(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsOnlyBool(closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnlyString(ClassWorld classWorld) {
|
||||
return forwardTo.containsOnlyString(classWorld);
|
||||
bool containsOnlyString(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsOnlyString(closedWorld);
|
||||
}
|
||||
|
||||
bool containsOnly(ClassElement element) {
|
||||
return forwardTo.containsOnly(element);
|
||||
}
|
||||
|
||||
bool satisfies(ClassElement cls, ClassWorld classWorld) {
|
||||
return forwardTo.satisfies(cls, classWorld);
|
||||
bool satisfies(ClassElement cls, ClosedWorld closedWorld) {
|
||||
return forwardTo.satisfies(cls, closedWorld);
|
||||
}
|
||||
|
||||
bool contains(ClassElement type, ClassWorld classWorld) {
|
||||
return forwardTo.contains(type, classWorld);
|
||||
bool contains(ClassElement type, ClosedWorld closedWorld) {
|
||||
return forwardTo.contains(type, closedWorld);
|
||||
}
|
||||
|
||||
bool containsAll(ClassWorld classWorld) {
|
||||
return forwardTo.containsAll(classWorld);
|
||||
bool containsAll(ClosedWorld closedWorld) {
|
||||
return forwardTo.containsAll(closedWorld);
|
||||
}
|
||||
|
||||
ClassElement singleClass(ClassWorld classWorld) {
|
||||
return forwardTo.singleClass(classWorld);
|
||||
ClassElement singleClass(ClosedWorld closedWorld) {
|
||||
return forwardTo.singleClass(closedWorld);
|
||||
}
|
||||
|
||||
TypeMask union(other, ClassWorld classWorld) {
|
||||
TypeMask union(other, ClosedWorld closedWorld) {
|
||||
if (this == other) {
|
||||
return this;
|
||||
} else if (equalsDisregardNull(other)) {
|
||||
|
@ -82,23 +82,23 @@ abstract class ForwardingTypeMask implements TypeMask {
|
|||
} else if (other.isEmptyOrNull) {
|
||||
return other.isNullable ? this.nullable() : this;
|
||||
}
|
||||
return forwardTo.union(other, classWorld);
|
||||
return forwardTo.union(other, closedWorld);
|
||||
}
|
||||
|
||||
bool isDisjoint(TypeMask other, ClassWorld classWorld) {
|
||||
return forwardTo.isDisjoint(other, classWorld);
|
||||
bool isDisjoint(TypeMask other, ClosedWorld closedWorld) {
|
||||
return forwardTo.isDisjoint(other, closedWorld);
|
||||
}
|
||||
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld) {
|
||||
return forwardTo.intersection(other, classWorld);
|
||||
TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
|
||||
return forwardTo.intersection(other, closedWorld);
|
||||
}
|
||||
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
|
||||
return forwardTo.needsNoSuchMethodHandling(selector, classWorld);
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClosedWorld closedWorld) {
|
||||
return forwardTo.needsNoSuchMethodHandling(selector, closedWorld);
|
||||
}
|
||||
|
||||
bool canHit(Element element, Selector selector, ClassWorld classWorld) {
|
||||
return forwardTo.canHit(element, selector, classWorld);
|
||||
bool canHit(Element element, Selector selector, ClosedWorld closedWorld) {
|
||||
return forwardTo.canHit(element, selector, closedWorld);
|
||||
}
|
||||
|
||||
Element locateSingleElement(Selector selector, Compiler compiler) {
|
||||
|
|
|
@ -53,13 +53,13 @@ class MapTypeMask extends ForwardingTypeMask {
|
|||
valueType == other.valueType;
|
||||
}
|
||||
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
|
||||
TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
|
||||
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
|
||||
return forwardIntersection.isNullable ? nullable() : nonNullable();
|
||||
}
|
||||
|
||||
TypeMask union(other, ClassWorld classWorld) {
|
||||
TypeMask union(other, ClosedWorld closedWorld) {
|
||||
if (this == other) {
|
||||
return this;
|
||||
} else if (equalsDisregardNull(other)) {
|
||||
|
@ -71,20 +71,20 @@ class MapTypeMask extends ForwardingTypeMask {
|
|||
other.keyType != null &&
|
||||
valueType != null &&
|
||||
other.valueType != null) {
|
||||
TypeMask newKeyType = keyType.union(other.keyType, classWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, classWorld);
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
|
||||
TypeMask newValueType = valueType.union(other.valueType, closedWorld);
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
|
||||
return new MapTypeMask(
|
||||
newForwardTo, null, null, newKeyType, newValueType);
|
||||
} else if (other.isDictionary) {
|
||||
// TODO(johnniwinther): Find another way to check this invariant that
|
||||
// doesn't need the compiler.
|
||||
assert(
|
||||
other.keyType == classWorld.backend.compiler.commonMasks.stringType);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, classWorld);
|
||||
other.keyType == closedWorld.backend.compiler.commonMasks.stringType);
|
||||
TypeMask newKeyType = keyType.union(other.keyType, closedWorld);
|
||||
TypeMask newValueType =
|
||||
other.typeMap.values.fold(keyType, (p, n) => p.union(n, classWorld));
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, classWorld);
|
||||
other.typeMap.values.fold(keyType, (p, n) => p.union(n, closedWorld));
|
||||
TypeMask newForwardTo = forwardTo.union(other.forwardTo, closedWorld);
|
||||
MapTypeMask newMapTypeMask = new MapTypeMask(
|
||||
newForwardTo,
|
||||
allocationNode == other.allocationNode ? allocationNode : null,
|
||||
|
@ -95,7 +95,7 @@ class MapTypeMask extends ForwardingTypeMask {
|
|||
newValueType);
|
||||
return newMapTypeMask;
|
||||
} else {
|
||||
return forwardTo.union(other, classWorld);
|
||||
return forwardTo.union(other, closedWorld);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import '../universe/universe.dart'
|
|||
UniverseSelectorConstraints,
|
||||
SelectorConstraintsStrategy;
|
||||
import '../util/util.dart';
|
||||
import '../world.dart' show ClassWorld, ClosedWorld;
|
||||
import '../world.dart' show ClosedWorld, ClosedWorld;
|
||||
import 'abstract_value_domain.dart' show AbstractValue;
|
||||
|
||||
part 'container_type_mask.dart';
|
||||
|
@ -37,7 +37,7 @@ class CommonMasks {
|
|||
|
||||
CommonMasks(this.compiler);
|
||||
|
||||
ClassWorld get classWorld => compiler.closedWorld;
|
||||
ClosedWorld get closedWorld => compiler.closedWorld;
|
||||
|
||||
TypeMask _dynamicType;
|
||||
TypeMask _nonNullType;
|
||||
|
@ -63,72 +63,72 @@ class CommonMasks {
|
|||
TypeMask _asyncStarStreamType;
|
||||
|
||||
TypeMask get dynamicType => _dynamicType ??=
|
||||
new TypeMask.subclass(classWorld.coreClasses.objectClass, classWorld);
|
||||
new TypeMask.subclass(closedWorld.coreClasses.objectClass, closedWorld);
|
||||
|
||||
TypeMask get nonNullType => _nonNullType ??= new TypeMask.nonNullSubclass(
|
||||
classWorld.coreClasses.objectClass, classWorld);
|
||||
closedWorld.coreClasses.objectClass, closedWorld);
|
||||
|
||||
TypeMask get intType => _intType ??= new TypeMask.nonNullSubclass(
|
||||
compiler.backend.intImplementation, classWorld);
|
||||
compiler.backend.intImplementation, closedWorld);
|
||||
|
||||
TypeMask get uint32Type => _uint32Type ??= new TypeMask.nonNullSubclass(
|
||||
compiler.backend.uint32Implementation, classWorld);
|
||||
compiler.backend.uint32Implementation, closedWorld);
|
||||
|
||||
TypeMask get uint31Type => _uint31Type ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.uint31Implementation, classWorld);
|
||||
compiler.backend.uint31Implementation, closedWorld);
|
||||
|
||||
TypeMask get positiveIntType =>
|
||||
_positiveIntType ??= new TypeMask.nonNullSubclass(
|
||||
compiler.backend.positiveIntImplementation, classWorld);
|
||||
compiler.backend.positiveIntImplementation, closedWorld);
|
||||
|
||||
TypeMask get doubleType => _doubleType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.doubleImplementation, classWorld);
|
||||
compiler.backend.doubleImplementation, closedWorld);
|
||||
|
||||
TypeMask get numType => _numType ??= new TypeMask.nonNullSubclass(
|
||||
compiler.backend.numImplementation, classWorld);
|
||||
compiler.backend.numImplementation, closedWorld);
|
||||
|
||||
TypeMask get boolType => _boolType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.boolImplementation, classWorld);
|
||||
compiler.backend.boolImplementation, closedWorld);
|
||||
|
||||
TypeMask get functionType => _functionType ??= new TypeMask.nonNullSubtype(
|
||||
compiler.backend.functionImplementation, classWorld);
|
||||
compiler.backend.functionImplementation, closedWorld);
|
||||
|
||||
TypeMask get listType => _listType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.listImplementation, classWorld);
|
||||
compiler.backend.listImplementation, closedWorld);
|
||||
|
||||
TypeMask get constListType => _constListType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.constListImplementation, classWorld);
|
||||
compiler.backend.constListImplementation, closedWorld);
|
||||
|
||||
TypeMask get fixedListType => _fixedListType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.fixedListImplementation, classWorld);
|
||||
compiler.backend.fixedListImplementation, closedWorld);
|
||||
|
||||
TypeMask get growableListType =>
|
||||
_growableListType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.growableListImplementation, classWorld);
|
||||
compiler.backend.growableListImplementation, closedWorld);
|
||||
|
||||
TypeMask get mapType => _mapType ??= new TypeMask.nonNullSubtype(
|
||||
compiler.backend.mapImplementation, classWorld);
|
||||
compiler.backend.mapImplementation, closedWorld);
|
||||
|
||||
TypeMask get constMapType => _constMapType ??= new TypeMask.nonNullSubtype(
|
||||
compiler.backend.constMapImplementation, classWorld);
|
||||
compiler.backend.constMapImplementation, closedWorld);
|
||||
|
||||
TypeMask get stringType => _stringType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.stringImplementation, classWorld);
|
||||
compiler.backend.stringImplementation, closedWorld);
|
||||
|
||||
TypeMask get typeType => _typeType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.typeImplementation, classWorld);
|
||||
compiler.backend.typeImplementation, closedWorld);
|
||||
|
||||
TypeMask get syncStarIterableType =>
|
||||
_syncStarIterableType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.syncStarIterableImplementation, classWorld);
|
||||
compiler.backend.syncStarIterableImplementation, closedWorld);
|
||||
|
||||
TypeMask get asyncFutureType =>
|
||||
_asyncFutureType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.asyncFutureImplementation, classWorld);
|
||||
compiler.backend.asyncFutureImplementation, closedWorld);
|
||||
|
||||
TypeMask get asyncStarStreamType =>
|
||||
_asyncStarStreamType ??= new TypeMask.nonNullExact(
|
||||
compiler.backend.asyncStarStreamImplementation, classWorld);
|
||||
compiler.backend.asyncStarStreamImplementation, closedWorld);
|
||||
|
||||
// TODO(johnniwinther): Assert that the null type has been resolved.
|
||||
TypeMask get nullType => _nullType ??= const TypeMask.empty();
|
||||
|
|
|
@ -27,8 +27,8 @@ class ValueTypeMask extends ForwardingTypeMask {
|
|||
return super.equalsDisregardNull(other) && value == other.value;
|
||||
}
|
||||
|
||||
TypeMask intersection(TypeMask other, ClassWorld classWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, classWorld);
|
||||
TypeMask intersection(TypeMask other, ClosedWorld closedWorld) {
|
||||
TypeMask forwardIntersection = forwardTo.intersection(other, closedWorld);
|
||||
if (forwardIntersection.isEmptyOrNull) return forwardIntersection;
|
||||
return forwardIntersection.isNullable ? nullable() : nonNullable();
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ enum Instantiation {
|
|||
|
||||
/// Node for [cls] in a tree forming the subclass relation of [ClassElement]s.
|
||||
///
|
||||
/// This is used by the [ClassWorld] to perform queries on subclass and subtype
|
||||
/// This is used by the [ClosedWorld] to perform queries on subclass and subtype
|
||||
/// relations.
|
||||
///
|
||||
/// For this class hierarchy:
|
||||
|
|
|
@ -125,7 +125,7 @@ class SelectorMask {
|
|||
String get name => selector.name;
|
||||
|
||||
bool applies(Element element, ClosedWorld closedWorld) {
|
||||
if (!selector.appliesUnnamed(element, closedWorld.backend)) return false;
|
||||
if (!selector.appliesUnnamed(element)) return false;
|
||||
return constraint.canHit(element, selector, closedWorld);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,12 +217,12 @@ class Selector {
|
|||
return kind;
|
||||
}
|
||||
|
||||
bool appliesUnnamed(Element element, Target target) {
|
||||
bool appliesUnnamed(Element element) {
|
||||
assert(sameNameHack(element));
|
||||
return appliesUntyped(element, target);
|
||||
return appliesUntyped(element);
|
||||
}
|
||||
|
||||
bool appliesUntyped(Element element, Target target) {
|
||||
bool appliesUntyped(Element element) {
|
||||
assert(sameNameHack(element));
|
||||
if (Elements.isUnresolved(element)) return false;
|
||||
if (memberName.isPrivate && memberName.library != element.library) {
|
||||
|
@ -230,7 +230,6 @@ class Selector {
|
|||
// `memberName != element.memberName`.
|
||||
return false;
|
||||
}
|
||||
if (target.isForeign(element)) return true;
|
||||
if (element.isSetter) return isSetter;
|
||||
if (element.isGetter) return isGetter || isCall;
|
||||
if (element.isField) {
|
||||
|
@ -253,9 +252,9 @@ class Selector {
|
|||
return element.isConstructor || name == element.name;
|
||||
}
|
||||
|
||||
bool applies(Element element, Target target) {
|
||||
bool applies(Element element) {
|
||||
if (!sameNameHack(element)) return false;
|
||||
return appliesUnnamed(element, target);
|
||||
return appliesUnnamed(element);
|
||||
}
|
||||
|
||||
bool match(SelectorKind kind, Name memberName, CallStructure callStructure) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import '../compiler.dart' show Compiler;
|
|||
import '../dart_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../util/util.dart';
|
||||
import '../world.dart' show ClassWorld, ClosedWorld, OpenWorld;
|
||||
import '../world.dart' show World, ClosedWorld, OpenWorld;
|
||||
import 'selector.dart' show Selector;
|
||||
import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind;
|
||||
|
||||
|
@ -29,11 +29,11 @@ abstract class ReceiverConstraint {
|
|||
/// Returns whether [element] is a potential target when being
|
||||
/// invoked on a receiver with this constraint. [selector] is used to ensure
|
||||
/// library privacy is taken into account.
|
||||
bool canHit(Element element, Selector selector, ClassWorld classWorld);
|
||||
bool canHit(Element element, Selector selector, World world);
|
||||
|
||||
/// Returns whether this [TypeMask] applied to [selector] can hit a
|
||||
/// [noSuchMethod].
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld);
|
||||
bool needsNoSuchMethodHandling(Selector selector, World world);
|
||||
}
|
||||
|
||||
/// The combined constraints on receivers all the dynamic call sites of the same
|
||||
|
@ -71,7 +71,7 @@ abstract class SelectorConstraints {
|
|||
///
|
||||
/// Ideally the selector constraints for calls `foo` with two positional
|
||||
/// arguments apply to `A.foo` but `B.foo`.
|
||||
bool applies(Element element, Selector selector, ClassWorld world);
|
||||
bool applies(Element element, Selector selector, World world);
|
||||
|
||||
/// Returns `true` if at least one of the receivers matching these constraints
|
||||
/// in the closed [world] have no implementation matching [selector].
|
||||
|
@ -84,7 +84,7 @@ abstract class SelectorConstraints {
|
|||
///
|
||||
/// the potential receiver `new A()` has no implementation of `foo` and thus
|
||||
/// needs to handle the call through its `noSuchMethod` handler.
|
||||
bool needsNoSuchMethodHandling(Selector selector, ClassWorld world);
|
||||
bool needsNoSuchMethodHandling(Selector selector, World world);
|
||||
}
|
||||
|
||||
/// A mutable [SelectorConstraints] used in [Universe].
|
||||
|
@ -103,7 +103,7 @@ abstract class SelectorConstraintsStrategy {
|
|||
}
|
||||
|
||||
/// The [Universe] is an auxiliary class used in the process of computing the
|
||||
/// [ClassWorld]. The concepts here and in [ClassWorld] are very similar -- in
|
||||
/// [ClosedWorld]. The concepts here and in [ClosedWorld] are very similar -- in
|
||||
/// the same way that the "universe expands" you can think of this as a mutable
|
||||
/// world that is expanding as we visit and discover parts of the program.
|
||||
// TODO(sigmund): rename to "growing/expanding/mutable world"?
|
||||
|
@ -129,7 +129,7 @@ abstract class Universe {
|
|||
Iterable<DartType> get instantiatedTypes;
|
||||
|
||||
/// Returns `true` if [member] is invoked as a setter.
|
||||
bool hasInvokedSetter(Element member, ClassWorld world);
|
||||
bool hasInvokedSetter(Element member, World world);
|
||||
}
|
||||
|
||||
abstract class ResolutionUniverse implements Universe {
|
||||
|
@ -299,10 +299,10 @@ class ResolutionUniverseImpl implements ResolutionUniverse {
|
|||
}
|
||||
|
||||
bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
|
||||
Element member, ClassWorld world) {
|
||||
Element member, OpenWorld world) {
|
||||
if (selectors == null) return false;
|
||||
for (Selector selector in selectors.keys) {
|
||||
if (selector.appliesUnnamed(member, world.backend)) {
|
||||
if (selector.appliesUnnamed(member)) {
|
||||
SelectorConstraints masks = selectors[selector];
|
||||
if (masks.applies(member, selector, world)) {
|
||||
return true;
|
||||
|
@ -542,7 +542,7 @@ class CodegenUniverseImpl implements CodegenUniverse {
|
|||
Element member, ClosedWorld world) {
|
||||
if (selectors == null) return false;
|
||||
for (Selector selector in selectors.keys) {
|
||||
if (selector.appliesUnnamed(member, world.backend)) {
|
||||
if (selector.appliesUnnamed(member)) {
|
||||
SelectorConstraints masks = selectors[selector];
|
||||
if (masks.applies(member, selector, world)) {
|
||||
return true;
|
||||
|
|
|
@ -21,7 +21,7 @@ import '../common.dart';
|
|||
import '../dart_types.dart';
|
||||
import '../elements/elements.dart';
|
||||
import '../util/util.dart' show Hashing;
|
||||
import '../world.dart' show ClassWorld;
|
||||
import '../world.dart' show World;
|
||||
import 'call_structure.dart' show CallStructure;
|
||||
import 'selector.dart' show Selector;
|
||||
import 'universe.dart' show ReceiverConstraint;
|
||||
|
@ -37,8 +37,8 @@ class DynamicUse {
|
|||
|
||||
DynamicUse(this.selector, this.mask);
|
||||
|
||||
bool appliesUnnamed(Element element, ClassWorld world) {
|
||||
return selector.appliesUnnamed(element, world.backend) &&
|
||||
bool appliesUnnamed(Element element, World world) {
|
||||
return selector.appliesUnnamed(element) &&
|
||||
(mask == null || mask.canHit(element, selector, world));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import 'use.dart' show DynamicUse, StaticUse, TypeUse;
|
|||
///
|
||||
/// The impact object can be computed locally by inspecting just the resolution
|
||||
/// information of that element alone. The compiler uses [Universe] and
|
||||
/// [ClassWorld] to combine the information discovered in the impact objects of
|
||||
/// [World] to combine the information discovered in the impact objects of
|
||||
/// all elements reachable in an application.
|
||||
class WorldImpact {
|
||||
const WorldImpact();
|
||||
|
|
|
@ -27,7 +27,10 @@ import 'universe/selector.dart' show Selector;
|
|||
import 'universe/side_effects.dart' show SideEffects;
|
||||
import 'util/util.dart' show Link;
|
||||
|
||||
/// The [ClassWorld] represents the information known about a program when
|
||||
/// Common superinterface for [OpenWorld] and [ClosedWorld].
|
||||
abstract class World {}
|
||||
|
||||
/// The [ClosedWorld] represents the information known about a program when
|
||||
/// compiling with closed-world semantics.
|
||||
///
|
||||
/// Given the entrypoint of an application, we can track what's reachable from
|
||||
|
@ -35,49 +38,12 @@ import 'util/util.dart' show Link;
|
|||
/// JavaScript types are touched, what language features are used, and so on.
|
||||
/// This precise knowledge about what's live in the program is later used in
|
||||
/// optimizations and other compiler decisions during code generation.
|
||||
abstract class ClassWorld {
|
||||
abstract class ClosedWorld implements World {
|
||||
// TODO(johnniwinther): Refine this into a `BackendClasses` interface.
|
||||
Backend get backend;
|
||||
|
||||
CoreClasses get coreClasses;
|
||||
|
||||
/// Returns `true` if the class world is closed.
|
||||
bool get isClosed;
|
||||
|
||||
/// Returns `true` if closed-world assumptions can be made, that is,
|
||||
/// incremental compilation isn't enabled.
|
||||
bool get hasClosedWorldAssumption;
|
||||
|
||||
/// Returns a string representation of the closed world.
|
||||
///
|
||||
/// If [cls] is provided, the dump will contain only classes related to [cls].
|
||||
String dump([ClassElement cls]);
|
||||
|
||||
/// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
|
||||
/// of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClassWorld].
|
||||
ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
|
||||
|
||||
/// Returns [ClassSet] for [cls] used to model the extends and implements
|
||||
/// relations of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClassWorld].
|
||||
ClassSet getClassSet(ClassElement cls);
|
||||
|
||||
// TODO(johnniwinther): Find a better strategy for caching these.
|
||||
@deprecated
|
||||
List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
|
||||
}
|
||||
|
||||
/// The [ClosedWorld] represents the information known about a program when
|
||||
/// compiling with closed-world semantics.
|
||||
///
|
||||
/// This expands [ClassWorld] with information about live functions,
|
||||
/// side effects, and selectors with known single targets.
|
||||
abstract class ClosedWorld extends ClassWorld {
|
||||
/// Returns `true` if [cls] is either directly or indirectly instantiated.
|
||||
bool isInstantiated(ClassElement cls);
|
||||
|
||||
|
@ -189,6 +155,24 @@ abstract class ClosedWorld extends ClassWorld {
|
|||
/// Returns `true` if any subclass of [superclass] implements [type].
|
||||
bool hasAnySubclassThatImplements(ClassElement superclass, ClassElement type);
|
||||
|
||||
/// Returns [ClassHierarchyNode] for [cls] used to model the class hierarchies
|
||||
/// of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClosedWorld].
|
||||
ClassHierarchyNode getClassHierarchyNode(ClassElement cls);
|
||||
|
||||
/// Returns [ClassSet] for [cls] used to model the extends and implements
|
||||
/// relations of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClosedWorld].
|
||||
ClassSet getClassSet(ClassElement cls);
|
||||
|
||||
// TODO(johnniwinther): Find a better strategy for caching these.
|
||||
@deprecated
|
||||
List<Map<ClassElement, TypeMask>> get canonicalizedTypeMasks;
|
||||
|
||||
/// Returns the [FunctionSet] containing all live functions in the closed
|
||||
/// world.
|
||||
FunctionSet get allFunctions;
|
||||
|
@ -230,6 +214,11 @@ abstract class ClosedWorld extends ClassWorld {
|
|||
// TODO(johnniwinther): Is this 'passed invocation target` or
|
||||
// `passed as argument`?
|
||||
bool getMightBePassedToApply(Element element);
|
||||
|
||||
/// Returns a string representation of the closed world.
|
||||
///
|
||||
/// If [cls] is provided, the dump will contain only classes related to [cls].
|
||||
String dump([ClassElement cls]);
|
||||
}
|
||||
|
||||
/// Interface for computing side effects and uses of elements. This is used
|
||||
|
@ -265,7 +254,7 @@ abstract class ClosedWorldRefiner {
|
|||
void registerClosureClass(ClassElement cls);
|
||||
}
|
||||
|
||||
abstract class OpenWorld implements ClassWorld {
|
||||
abstract class OpenWorld implements World {
|
||||
/// Called to add [cls] to the set of known classes.
|
||||
///
|
||||
/// This ensures that class hierarchy queries can be performed on [cls] and
|
||||
|
@ -749,7 +738,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld {
|
|||
/// of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClassWorld].
|
||||
/// methods defined in [ClosedWorld].
|
||||
ClassHierarchyNode getClassHierarchyNode(ClassElement cls) {
|
||||
return _classHierarchyNodes[cls.declaration];
|
||||
}
|
||||
|
@ -769,7 +758,7 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld {
|
|||
/// relations of known classes.
|
||||
///
|
||||
/// This method is only provided for testing. For queries on classes, use the
|
||||
/// methods defined in [ClassWorld].
|
||||
/// methods defined in [ClosedWorld].
|
||||
ClassSet getClassSet(ClassElement cls) {
|
||||
return _classSets[cls.declaration];
|
||||
}
|
||||
|
@ -1024,6 +1013,4 @@ class WorldImpl implements ClosedWorld, ClosedWorldRefiner, OpenWorld {
|
|||
bool getCurrentlyKnownMightBePassedToApply(Element element) {
|
||||
return getMightBePassedToApply(element);
|
||||
}
|
||||
|
||||
bool get hasClosedWorldAssumption => !_compiler.options.hasIncrementalSupport;
|
||||
}
|
||||
|
|
|
@ -211,7 +211,7 @@ void doTest(String allocation, [String keyElement, String valueElement]) {
|
|||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = compilerFor(generateTest(allocation), uri,
|
||||
expectedErrors: 0, expectedWarnings: 1);
|
||||
var classWorld = compiler.openWorld.closeWorld();
|
||||
var closedWorld = compiler.openWorld.closeWorld();
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
var keyType, valueType;
|
||||
var commonMasks = compiler.commonMasks;
|
||||
|
@ -238,9 +238,9 @@ void doTest(String allocation, [String keyElement, String valueElement]) {
|
|||
}
|
||||
|
||||
K(TypeMask other) =>
|
||||
simplify(keyType.union(other, classWorld), compiler);
|
||||
simplify(keyType.union(other, closedWorld), compiler);
|
||||
V(TypeMask other) =>
|
||||
simplify(valueType.union(other, classWorld), compiler).nullable();
|
||||
simplify(valueType.union(other, closedWorld), compiler).nullable();
|
||||
|
||||
checkType('mapInField', K(aKeyType), V(commonMasks.numType));
|
||||
checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
|
||||
|
|
|
@ -942,7 +942,7 @@ Future testPatchAndSelector() async {
|
|||
TypeMask typeMask = new TypeMask.exact(cls, world);
|
||||
FunctionElement method = cls.implementation.lookupLocalMember('method');
|
||||
method.computeType(compiler.resolution);
|
||||
Expect.isTrue(selector.applies(method, world.backend));
|
||||
Expect.isTrue(selector.applies(method));
|
||||
Expect.isTrue(typeMask.canHit(method, selector, world));
|
||||
|
||||
// Check that the declaration method in the declaration class is a target
|
||||
|
@ -952,7 +952,7 @@ Future testPatchAndSelector() async {
|
|||
typeMask = new TypeMask.exact(cls, world);
|
||||
method = cls.lookupLocalMember('clear');
|
||||
method.computeType(compiler.resolution);
|
||||
Expect.isTrue(selector.applies(method, world.backend));
|
||||
Expect.isTrue(selector.applies(method));
|
||||
Expect.isTrue(typeMask.canHit(method, selector, world));
|
||||
|
||||
// Check that the declaration method in the declaration class is a target
|
||||
|
@ -960,7 +960,7 @@ Future testPatchAndSelector() async {
|
|||
cls = ensure(compiler, "B", compiler.commonElements.coreLibrary.find);
|
||||
cls.ensureResolved(compiler.resolution);
|
||||
typeMask = new TypeMask.exact(cls, world);
|
||||
Expect.isTrue(selector.applies(method, world.backend));
|
||||
Expect.isTrue(selector.applies(method));
|
||||
Expect.isTrue(typeMask.canHit(method, selector, world));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ main() {
|
|||
main() {
|
||||
Uri uri = new Uri(scheme: 'source');
|
||||
var compiler = compilerFor(CODE, uri);
|
||||
var classWorld = compiler.openWorld.closeWorld();
|
||||
var closedWorld = compiler.openWorld.closeWorld();
|
||||
|
||||
asyncTest(() => compiler.run(uri).then((_) {
|
||||
var classA = findElement(compiler, 'A');
|
||||
|
@ -29,37 +29,37 @@ main() {
|
|||
var classC = findElement(compiler, 'C');
|
||||
var classD = findElement(compiler, 'D');
|
||||
|
||||
var exactA = new TypeMask.nonNullExact(classA, classWorld);
|
||||
var exactB = new TypeMask.nonNullExact(classB, classWorld);
|
||||
var exactC = new TypeMask.nonNullExact(classC, classWorld);
|
||||
var exactD = new TypeMask.nonNullExact(classD, classWorld);
|
||||
var exactA = new TypeMask.nonNullExact(classA, closedWorld);
|
||||
var exactB = new TypeMask.nonNullExact(classB, closedWorld);
|
||||
var exactC = new TypeMask.nonNullExact(classC, closedWorld);
|
||||
var exactD = new TypeMask.nonNullExact(classD, closedWorld);
|
||||
|
||||
var subclassA = new TypeMask.nonNullSubclass(classA, classWorld);
|
||||
var subtypeA = new TypeMask.nonNullSubtype(classA, classWorld);
|
||||
var subclassA = new TypeMask.nonNullSubclass(classA, closedWorld);
|
||||
var subtypeA = new TypeMask.nonNullSubtype(classA, closedWorld);
|
||||
|
||||
var subclassObject = new TypeMask.nonNullSubclass(
|
||||
compiler.coreClasses.objectClass, classWorld);
|
||||
compiler.coreClasses.objectClass, closedWorld);
|
||||
|
||||
var unionABC =
|
||||
UnionTypeMask.unionOf([exactA, exactB, exactC], classWorld);
|
||||
UnionTypeMask.unionOf([exactA, exactB, exactC], closedWorld);
|
||||
var unionABnC = UnionTypeMask
|
||||
.unionOf([exactA, exactB.nullable(), exactC], classWorld);
|
||||
var unionAB = UnionTypeMask.unionOf([exactA, exactB], classWorld);
|
||||
.unionOf([exactA, exactB.nullable(), exactC], closedWorld);
|
||||
var unionAB = UnionTypeMask.unionOf([exactA, exactB], closedWorld);
|
||||
var unionSubtypeAC =
|
||||
UnionTypeMask.unionOf([subtypeA, exactC], classWorld);
|
||||
UnionTypeMask.unionOf([subtypeA, exactC], closedWorld);
|
||||
var unionSubclassAC =
|
||||
UnionTypeMask.unionOf([subclassA, exactC], classWorld);
|
||||
UnionTypeMask.unionOf([subclassA, exactC], closedWorld);
|
||||
var unionBCD =
|
||||
UnionTypeMask.unionOf([exactB, exactC, exactD], classWorld);
|
||||
UnionTypeMask.unionOf([exactB, exactC, exactD], closedWorld);
|
||||
var unionBCDn = UnionTypeMask
|
||||
.unionOf([exactB, exactC, exactD.nullable()], classWorld);
|
||||
.unionOf([exactB, exactC, exactD.nullable()], closedWorld);
|
||||
|
||||
Expect.isFalse(unionABC.isNullable);
|
||||
Expect.isTrue(unionABnC.isNullable);
|
||||
Expect.isFalse(unionBCD.isNullable);
|
||||
Expect.isTrue(unionBCDn.isNullable);
|
||||
|
||||
rule(a, b, c) => Expect.equals(c, a.isInMask(b, classWorld));
|
||||
rule(a, b, c) => Expect.equals(c, a.isInMask(b, closedWorld));
|
||||
|
||||
rule(exactA, exactA, true);
|
||||
rule(exactA, exactB, false);
|
||||
|
|
Loading…
Reference in a new issue