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

Unified Diff: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
deleted file mode 100644
index 8941c7bc28b0ddfdf7233193c09f88c60e833317..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
+++ /dev/null
@@ -1,1537 +0,0 @@
-// Copyright (c) 2013, 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.
-
-part of type_graph_inferrer;
-
-/**
- * Common class for all nodes in the graph. The current nodes are:
- *
- * - Concrete types
- * - Elements
- * - Call sites
- * - Narrowing instructions
- * - Phi instructions
- * - Containers (for lists)
- * - Type of the element in a container
- *
- * A node has a set of assignments and users. Assignments are used to
- * compute the type of the node ([TypeInformation.computeType]). Users are
- * added to the inferrer's work queue when the type of the node
- * changes.
- */
-abstract class TypeInformation {
- Set<TypeInformation> users;
- var /* List|ParameterAssignments */ _assignments;
-
- /// The type the inferrer has found for this [TypeInformation].
- /// Initially empty.
- TypeMask type = const TypeMask.nonNullEmpty();
-
- /// The graph node of the member this [TypeInformation] node belongs to.
- final MemberTypeInformation context;
-
- /// The element this [TypeInformation] node belongs to.
- MemberElement get contextMember => context == null ? null : context.element;
-
- Iterable<TypeInformation> get assignments => _assignments;
-
- /// We abandon inference in certain cases (complex cyclic flow, native
- /// behaviours, etc.). In some case, we might resume inference in the
- /// closure tracer, which is handled by checking whether [assignments] has
- /// been set to [STOP_TRACKING_ASSIGNMENTS_MARKER].
- bool abandonInferencing = false;
- bool get mightResume =>
- !identical(assignments, STOP_TRACKING_ASSIGNMENTS_MARKER);
-
- /// Number of times this [TypeInformation] has changed type.
- int refineCount = 0;
-
- /// Whether this [TypeInformation] is currently in the inferrer's
- /// work queue.
- bool inQueue = false;
-
- /// Used to disable enqueueing of type informations where we know that their
- /// type will not change for other reasons than being stable. For example,
- /// if inference is disabled for a type and it is hardwired to dynamic, this
- /// is set to true to spare recomputing dynamic again and again. Changing this
- /// to false should never change inference outcome, just make is slower.
- bool doNotEnqueue = false;
-
- /// Whether this [TypeInformation] has a stable [type] that will not
- /// change.
- bool isStable = false;
-
- // TypeInformations are unique.
- static int staticHashCode = 0;
- final int hashCode = staticHashCode++;
-
- bool get isConcrete => false;
-
- TypeInformation(this.context) : _assignments = <TypeInformation>[],
- users = new Setlet<TypeInformation>();
-
- TypeInformation.noAssignments(this.context)
- : _assignments = const <TypeInformation>[],
- users = new Setlet<TypeInformation>();
-
- TypeInformation.untracked()
- : _assignments = const <TypeInformation>[],
- users = const ImmutableEmptySet(),
- context = null;
-
- TypeInformation.withAssignments(this.context, this._assignments)
- : users = new Setlet<TypeInformation>();
-
- void addUser(TypeInformation user) {
- assert(!user.isConcrete);
- users.add(user);
- }
-
- void removeUser(TypeInformation user) {
- assert(!user.isConcrete);
- users.remove(user);
- }
-
- // The below is not a compile time constant to make it differentiable
- // from other empty lists of [TypeInformation].
- static final STOP_TRACKING_ASSIGNMENTS_MARKER = new List<TypeInformation>(0);
-
- bool areAssignmentsTracked() {
- return assignments != STOP_TRACKING_ASSIGNMENTS_MARKER;
- }
-
- void addAssignment(TypeInformation assignment) {
- // Cheap one-level cycle detection.
- if (assignment == this) return;
- if (areAssignmentsTracked()) {
- _assignments.add(assignment);
- }
- // Even if we abandon inferencing on this [TypeInformation] we
- // need to collect the users, so that phases that track where
- // elements flow in still work.
- assignment.addUser(this);
- }
-
- void removeAssignment(TypeInformation assignment) {
- if (!abandonInferencing || mightResume) {
- _assignments.remove(assignment);
- }
- // We can have multiple assignments of the same [TypeInformation].
- if (!assignments.contains(assignment)) {
- assignment.removeUser(this);
- }
- }
-
- TypeMask refine(TypeGraphInferrerEngine inferrer) {
- return abandonInferencing ? safeType(inferrer) : computeType(inferrer);
- }
-
- /**
- * Computes a new type for this [TypeInformation] node depending on its
- * potentially updated inputs.
- */
- TypeMask computeType(TypeGraphInferrerEngine inferrer);
-
- /**
- * Returns an approximation for this [TypeInformation] node that is always
- * safe to use. Used when abandoning inference on a node.
- */
- TypeMask safeType(TypeGraphInferrerEngine inferrer) {
- return inferrer.types.dynamicType.type;
- }
-
- void giveUp(TypeGraphInferrerEngine inferrer, {bool clearAssignments: true}) {
- abandonInferencing = true;
- // Do not remove [this] as a user of nodes in [assignments],
- // because our tracing analysis could be interested in tracing
- // this node.
- if (clearAssignments) _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
- // Do not remove users because our tracing analysis could be
- // interested in tracing the users of this node.
- }
-
- void clear() {
- _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
- users = const ImmutableEmptySet();
- }
-
- /// Reset the analysis of this node by making its type empty.
-
- bool reset(TypeGraphInferrerEngine inferrer) {
- if (abandonInferencing) return false;
- type = const TypeMask.nonNullEmpty();
- refineCount = 0;
- return true;
- }
-
- accept(TypeInformationVisitor visitor);
-
- /// The [Element] where this [TypeInformation] was created. May be
- /// for some [TypeInformation] nodes, where we do not need to store
- /// the information.
- Element get owner => null;
-
- /// Returns whether the type cannot change after it has been
- /// inferred.
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return !mightResume && assignments.every((e) => e.isStable);
- }
-
- void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
- assignments.forEach((info) { info.removeUser(this); });
- }
-
- void stabilize(TypeGraphInferrerEngine inferrer) {
- removeAndClearReferences(inferrer);
- // Do not remove users because the tracing analysis could be interested
- // in tracing the users of this node.
- _assignments = STOP_TRACKING_ASSIGNMENTS_MARKER;
- abandonInferencing = true;
- isStable = true;
- }
-
- void maybeResume() {
- if (!mightResume) return;
- abandonInferencing = false;
- doNotEnqueue = false;
- }
-}
-
-abstract class ApplyableTypeInformation implements TypeInformation {
- bool mightBePassedToFunctionApply = false;
-}
-
-/**
- * Marker node used only during tree construction but not during actual type
- * refinement.
- *
- * Currently, this is used to give a type to an optional parameter even before
- * the corresponding default expression has been analyzed. See
- * [getDefaultTypeOfParameter] and [setDefaultTypeOfParameter] for details.
- */
-class PlaceholderTypeInformation extends TypeInformation {
- PlaceholderTypeInformation(MemberTypeInformation context) : super(context);
-
- void accept(TypeInformationVisitor visitor) {
- throw new UnsupportedError("Cannot visit placeholder");
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- throw new UnsupportedError("Cannot refine placeholder");
- }
-
- toString() => "Placeholder [$hashCode]";
-}
-
-/**
- * Parameters of instance functions behave differently than other
- * elements because the inferrer may remove assignments. This happens
- * when the receiver of a dynamic call site can be refined
- * to a type where we know more about which instance method is being
- * called.
- */
-class ParameterAssignments extends IterableBase<TypeInformation> {
- final Map<TypeInformation, int> assignments =
- new Map<TypeInformation, int>();
-
- void remove(TypeInformation info) {
- int existing = assignments[info];
- if (existing == null) return;
- if (existing == 1) {
- assignments.remove(info);
- } else {
- assignments[info] = existing - 1;
- }
- }
-
- void add(TypeInformation info) {
- int existing = assignments[info];
- if (existing == null) {
- assignments[info] = 1;
- } else {
- assignments[info] = existing + 1;
- }
- }
-
- void replace(TypeInformation old, TypeInformation replacement) {
- int existing = assignments[old];
- if (existing != null) {
- int other = assignments[replacement];
- if (other != null) existing += other;
- assignments[replacement] = existing;
- assignments.remove(old);
- }
- }
-
- Iterator<TypeInformation> get iterator => assignments.keys.iterator;
- Iterable<TypeInformation> where(Function f) => assignments.keys.where(f);
-
- bool contains(TypeInformation info) => assignments.containsKey(info);
-
- String toString() => assignments.keys.toList().toString();
-}
-
-/**
- * A node representing a resolved element of the program. The kind of
- * elements that need an [ElementTypeInformation] are:
- *
- * - Functions (including getters and setters)
- * - Constructors (factory or generative)
- * - Fields
- * - Parameters
- * - Local variables mutated in closures
- *
- * The [ElementTypeInformation] of a function and a constructor is its
- * return type.
- *
- * Note that a few elements of these kinds must be treated specially,
- * and they are dealt in [ElementTypeInformation.handleSpecialCases]:
- *
- * - Parameters of closures, [noSuchMethod] and [call] instance
- * methods: we currently do not infer types for those.
- *
- * - Fields and parameters being assigned by synthesized calls done by
- * the backend: we do not know what types the backend will use.
- *
- * - Native functions and fields: because native methods contain no Dart
- * code, and native fields do not have Dart assignments, we just
- * trust their type annotation.
- *
- */
-abstract class ElementTypeInformation extends TypeInformation {
- final Element element;
-
- /// Marker to disable inference for closures in [handleSpecialCases].
- bool disableInferenceForClosures = true;
-
- factory ElementTypeInformation(Element element, TypeInformationSystem types) {
- if (element.isParameter || element.isInitializingFormal) {
- ParameterElement parameter = element;
- if (parameter.functionDeclaration.isInstanceMember) {
- return new ParameterTypeInformation._instanceMember(element, types);
- }
- return new ParameterTypeInformation._internal(element, types);
- }
- return new MemberTypeInformation._internal(element);
- }
-
- ElementTypeInformation._internal(MemberTypeInformation context, this.element)
- : super(context);
- ElementTypeInformation._withAssignments(MemberTypeInformation context,
- this.element, assignments)
- : super.withAssignments(context, assignments);
-}
-
-/**
- * A node representing members in the broadest sense:
- *
- * - Functions
- * - Constructors
- * - Fields (also synthetic ones due to closures)
- * - Local functions (closures)
- *
- * These should never be created directly but instead are constructed by
- * the [ElementTypeInformation] factory.
- */
-class MemberTypeInformation extends ElementTypeInformation
- with ApplyableTypeInformation {
- TypedElement get element => super.element;
-
- /**
- * If [element] is a function, [closurizedCount] is the number of
- * times it is closurized. The value gets updated while infering.
- */
- int closurizedCount = 0;
-
- /**
- * This map contains the callers of [element]. It stores all unique call sites
- * to enable counting the global number of call sites of [element].
- *
- * A call site is either an AST [ast.Node], a [cps_ir.Node] or in the case of
- * synthesized calls, an [Element] (see uses of [synthesizeForwardingCall]
- * in [SimpleTypeInferrerVisitor]).
- */
- final Map<Element, Setlet<Spannable>> _callers = new Map<Element, Setlet>();
-
- MemberTypeInformation._internal(Element element)
- : super._internal(null, element);
-
- void addCall(Element caller, Spannable node) {
- assert(node is ast.Node || node is cps_ir.Node || node is Element);
- _callers.putIfAbsent(caller, () => new Setlet()).add(node);
- }
-
- void removeCall(Element caller, node) {
- Setlet calls = _callers[caller];
- if (calls == null) return;
- calls.remove(node);
- if (calls.isEmpty) {
- _callers.remove(caller);
- }
- }
-
- Iterable<Element> get callers => _callers.keys;
-
- bool isCalledOnce() {
- int count = 0;
- for (var set in _callers.values) {
- count += set.length;
- if (count > 1) return false;
- }
- return count == 1;
- }
-
- bool get isClosurized => closurizedCount > 0;
-
- // Closurized methods never become stable to ensure that the information in
- // [users] is accurate. The inference stops tracking users for stable types.
- // Note that we only override the getter, the setter will still modify the
- // state of the [isStable] field inhertied from [TypeInformation].
- bool get isStable => super.isStable && !isClosurized;
-
- TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
- if (element.isField &&
- !inferrer.compiler.backend.canBeUsedForGlobalOptimizations(element)) {
- // Do not infer types for fields being assigned by synthesized calls.
- giveUp(inferrer);
- return safeType(inferrer);
- }
- if (inferrer.isNativeElement(element)) {
- // Use the type annotation as the type for native elements. We
- // also give up on inferring to make sure this element never
- // goes in the work queue.
- giveUp(inferrer);
- if (element.isField) {
- return inferrer.typeOfNativeBehavior(
- native.NativeBehavior.ofFieldLoad(element, inferrer.compiler)).type;
- } else {
- assert(element.isFunction ||
- element.isGetter ||
- element.isSetter);
- TypedElement typedElement = element;
- var elementType = typedElement.type;
- if (elementType.kind != TypeKind.FUNCTION) {
- return safeType(inferrer);
- } else {
- return inferrer.typeOfNativeBehavior(
- native.NativeBehavior.ofMethod(element, inferrer.compiler)).type;
- }
- }
- }
-
- Compiler compiler = inferrer.compiler;
- if (element.declaration == compiler.intEnvironment) {
- giveUp(inferrer);
- return compiler.typesTask.intType.nullable();
- } else if (element.declaration == compiler.boolEnvironment) {
- giveUp(inferrer);
- return compiler.typesTask.boolType.nullable();
- } else if (element.declaration == compiler.stringEnvironment) {
- giveUp(inferrer);
- return compiler.typesTask.stringType.nullable();
- }
- return null;
- }
-
- TypeMask potentiallyNarrowType(TypeMask mask,
- TypeGraphInferrerEngine inferrer) {
- Compiler compiler = inferrer.compiler;
- if (!compiler.trustTypeAnnotations && !compiler.enableTypeAssertions) {
- return mask;
- }
- if (element.isGenerativeConstructor ||
- element.isSetter) {
- return mask;
- }
- if (element.isField) {
- return new TypeMaskSystem(compiler).narrowType(mask, element.type);
- }
- assert(element.isFunction ||
- element.isGetter ||
- element.isFactoryConstructor);
-
- FunctionType type = element.type;
- return new TypeMaskSystem(compiler).narrowType(mask, type.returnType);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- TypeMask special = handleSpecialCases(inferrer);
- if (special != null) return potentiallyNarrowType(special, inferrer);
- return potentiallyNarrowType(
- inferrer.types.computeTypeMask(assignments), inferrer);
- }
-
- TypeMask safeType(TypeGraphInferrerEngine inferrer) {
- return potentiallyNarrowType(super.safeType(inferrer), inferrer);
- }
-
- String toString() => 'MemberElement $element $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitMemberTypeInformation(this);
- }
-
- Element get owner => element.outermostEnclosingMemberOrTopLevel;
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- // The number of assignments of non-final fields is
- // not stable. Therefore such a field cannot be stable.
- if (element.isField && !(element.isConst || element.isFinal)) {
- return false;
- }
-
- if (element.isFunction) return false;
-
- return super.hasStableType(inferrer);
- }
-}
-
-/**
- * A node representing parameters:
- *
- * - Parameters
- * - Initializing formals
- *
- * These should never be created directly but instead are constructed by
- * the [ElementTypeInformation] factory.
- */
-class ParameterTypeInformation extends ElementTypeInformation {
- ParameterElement get element => super.element;
-
- ParameterTypeInformation._internal(ParameterElement element,
- TypeInformationSystem types)
- : super._internal(types.getInferredTypeOf(element.functionDeclaration),
- element) {
- assert(!element.functionDeclaration.isInstanceMember);
- }
-
- ParameterTypeInformation._instanceMember(ParameterElement element,
- TypeInformationSystem types)
- : super._withAssignments(
- types.getInferredTypeOf(element.functionDeclaration),
- element,
- new ParameterAssignments()) {
- assert(element.functionDeclaration.isInstanceMember);
- }
-
- bool isTearOffClosureParameter = false;
-
- void tagAsTearOffClosureParameter(TypeGraphInferrerEngine inferrer) {
- assert(element.isParameter);
- isTearOffClosureParameter = true;
- }
-
- // TODO(herhut): Cleanup into one conditional.
- TypeMask handleSpecialCases(TypeGraphInferrerEngine inferrer) {
- if (!inferrer.compiler.backend.canBeUsedForGlobalOptimizations(element)) {
- // Do not infer types for fields and parameters being assigned
- // by synthesized calls.
- giveUp(inferrer);
- return safeType(inferrer);
- }
-
- // The below do not apply to parameters of constructors, so skip
- // initializing formals.
- if (element.isInitializingFormal) return null;
-
- FunctionElement function = element.functionDeclaration;
- if ((isTearOffClosureParameter || function.isLocal) &&
- disableInferenceForClosures) {
- // Do not infer types for parameters of closures. We do not
- // clear the assignments in case the closure is successfully
- // traced.
- giveUp(inferrer, clearAssignments: false);
- return safeType(inferrer);
- }
- if (function.isInstanceMember &&
- (function.name == Compiler.NO_SUCH_METHOD ||
- (function.name == Compiler.CALL_OPERATOR_NAME &&
- disableInferenceForClosures))) {
- // Do not infer types for parameters of [noSuchMethod] and
- // [call] instance methods.
- giveUp(inferrer);
- return safeType(inferrer);
- }
- if (function == inferrer.mainElement) {
- // The implicit call to main is not seen by the inferrer,
- // therefore we explicitly set the type of its parameters as
- // dynamic.
- // TODO(14566): synthesize a call instead to get the exact
- // types.
- giveUp(inferrer);
- return safeType(inferrer);
- }
-
- return null;
- }
-
- TypeMask potentiallyNarrowType(TypeMask mask,
- TypeGraphInferrerEngine inferrer) {
- Compiler compiler = inferrer.compiler;
- if (!compiler.trustTypeAnnotations) {
- return mask;
- }
- // When type assertions are enabled (aka checked mode), we have to always
- // ignore type annotations to ensure that the checks are actually inserted
- // into the function body and retained until runtime.
- assert(!compiler.enableTypeAssertions);
- return new TypeMaskSystem(compiler).narrowType(mask, element.type);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- TypeMask special = handleSpecialCases(inferrer);
- if (special != null) return special;
- return potentiallyNarrowType(inferrer.types.computeTypeMask(assignments),
- inferrer);
- }
-
- TypeMask safeType(TypeGraphInferrerEngine inferrer) {
- return potentiallyNarrowType(super.safeType(inferrer), inferrer);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- // The number of assignments of parameters of instance methods is
- // not stable. Therefore such a parameter cannot be stable.
- if (element.functionDeclaration.isInstanceMember) {
- return false;
- }
- return super.hasStableType(inferrer);
- }
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitParameterTypeInformation(this);
- }
-
- String toString() => 'ParameterElement $element $type';
-}
-
-/**
- * A [CallSiteTypeInformation] is a call found in the AST, or a
- * synthesized call for implicit calls in Dart (such as forwarding
- * factories). The [call] field is a [ast.Node] for the former, and an
- * [Element] for the latter.
- *
- * In the inferrer graph, [CallSiteTypeInformation] nodes do not have
- * any assignment. They rely on the [caller] field for static calls,
- * and [selector] and [receiver] fields for dynamic calls.
- */
-abstract class CallSiteTypeInformation extends TypeInformation
- with ApplyableTypeInformation {
- final Spannable call;
- final Element caller;
- final Selector selector;
- final ArgumentsTypes arguments;
- final bool inLoop;
-
- CallSiteTypeInformation(
- MemberTypeInformation context,
- this.call,
- this.caller,
- this.selector,
- this.arguments,
- this.inLoop) : super.noAssignments(context);
-
- String toString() => 'Call site $call $type';
-
- /// Add [this] to the graph being computed by [engine].
- void addToGraph(TypeGraphInferrerEngine engine);
-
- /// Return an iterable over the targets of this call.
- Iterable<Element> get callees;
-
- Element get owner => caller;
-}
-
-class StaticCallSiteTypeInformation extends CallSiteTypeInformation {
- final Element calledElement;
-
- StaticCallSiteTypeInformation(
- MemberTypeInformation context,
- Spannable call,
- Element enclosing,
- this.calledElement,
- Selector selector,
- ArgumentsTypes arguments,
- bool inLoop)
- : super(context, call, enclosing, selector, arguments, inLoop);
-
- void addToGraph(TypeGraphInferrerEngine inferrer) {
- MemberTypeInformation callee =
- inferrer.types.getInferredTypeOf(calledElement);
- callee.addCall(caller, call);
- callee.addUser(this);
- if (arguments != null) {
- arguments.forEach((info) => info.addUser(this));
- }
- inferrer.updateParameterAssignments(
- this, calledElement, arguments, selector, remove: false,
- addToQueue: false);
- }
-
- bool get isSynthesized {
- // Some calls do not have a corresponding node, for example
- // fowarding factory constructors, or synthesized super
- // constructor calls. We synthesize these calls but do
- // not create a selector for them.
- return selector == null;
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- if (isSynthesized) {
- assert(arguments != null);
- return inferrer.types.getInferredTypeOf(calledElement).type;
- } else {
- return inferrer.typeOfElementWithSelector(calledElement, selector).type;
- }
- }
-
- Iterable<Element> get callees => [calledElement.implementation];
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitStaticCallSiteTypeInformation(this);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return inferrer.types.getInferredTypeOf(calledElement).isStable &&
- (arguments == null || arguments.every((info) => info.isStable)) &&
- super.hasStableType(inferrer);
- }
-
- void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
- ElementTypeInformation callee =
- inferrer.types.getInferredTypeOf(calledElement);
- callee.removeUser(this);
- if (arguments != null) {
- arguments.forEach((info) => info.removeUser(this));
- }
- super.removeAndClearReferences(inferrer);
- }
-}
-
-class DynamicCallSiteTypeInformation extends CallSiteTypeInformation {
- final TypeInformation receiver;
- /// Cached targets of this call.
- Iterable<Element> targets;
-
- DynamicCallSiteTypeInformation(
- MemberTypeInformation context,
- Spannable call,
- Element enclosing,
- Selector selector,
- this.receiver,
- ArgumentsTypes arguments,
- bool inLoop)
- : super(context, call, enclosing, selector, arguments, inLoop);
-
- void addToGraph(TypeGraphInferrerEngine inferrer) {
- assert(receiver != null);
- Selector typedSelector = computeTypedSelector(inferrer);
- targets = inferrer.compiler.world.allFunctions.filter(typedSelector);
- receiver.addUser(this);
- if (arguments != null) {
- arguments.forEach((info) => info.addUser(this));
- }
- for (Element element in targets) {
- MemberTypeInformation callee = inferrer.types.getInferredTypeOf(element);
- callee.addCall(caller, call);
- callee.addUser(this);
- inferrer.updateParameterAssignments(
- this, element, arguments, typedSelector, remove: false,
- addToQueue: false);
- }
- }
-
- Iterable<Element> get callees => targets.map((e) => e.implementation);
-
- Selector computeTypedSelector(TypeGraphInferrerEngine inferrer) {
- TypeMask receiverType = receiver.type;
-
- if (selector.mask != receiverType) {
- return receiverType == inferrer.compiler.typesTask.dynamicType
- ? selector.asUntyped
- : new TypedSelector(receiverType, selector, inferrer.classWorld);
- } else {
- return selector;
- }
- }
-
- bool get targetsIncludeNoSuchMethod {
- return targets.any((Element e) {
- return e is FunctionElement &&
- e.isInstanceMember &&
- e.name == Compiler.NO_SUCH_METHOD;
- });
- }
-
- /**
- * We optimize certain operations on the [int] class because we know
- * more about their return type than the actual Dart code. For
- * example, we know int + int returns an int. The Dart code for
- * [int.operator+] only says it returns a [num].
- */
- TypeInformation handleIntrisifiedSelector(Selector selector,
- TypeGraphInferrerEngine inferrer) {
- ClassWorld classWorld = inferrer.classWorld;
- if (!classWorld.backend.intImplementation.isResolved) return null;
- TypeMask emptyType = const TypeMask.nonNullEmpty();
- if (selector.mask == null) return null;
- if (!selector.mask.containsOnlyInt(classWorld)) {
- 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);
- bool isEmpty(info) => info.type == emptyType;
- bool isUInt31(info) {
- return info.type.satisfies(uint31Implementation, classWorld);
- }
- bool isPositiveInt(info) {
- return info.type.satisfies(
- classWorld.backend.positiveIntImplementation, classWorld);
- }
-
- String name = selector.name;
- // We are optimizing for the cases that are not expressed in the
- // Dart code, for example:
- // int + int -> int
- // uint31 | uint31 -> uint31
- if (name == '*' || name == '+' || name == '%' || name == 'remainder' ||
- name == '~/') {
- if (isPositiveInt(receiver) &&
- arguments.hasOnePositionalArgumentThatMatches(isPositiveInt)) {
- return inferrer.types.positiveIntType;
- } else if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
- return inferrer.types.intType;
- } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
- return inferrer.types.nonNullEmptyType;
- } else {
- return null;
- }
- } else if (name == '|' || name == '^') {
- if (isUInt31(receiver) &&
- arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == '>>') {
- if (isUInt31(receiver)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == '&') {
- if (isUInt31(receiver) ||
- arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
- return inferrer.types.uint31Type;
- }
- } else if (name == 'unary-') {
- // The receiver being an int, the return value will also be an
- // int.
- return inferrer.types.intType;
- } else if (name == '-') {
- if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
- return inferrer.types.intType;
- } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
- return inferrer.types.nonNullEmptyType;
- }
- return null;
- } else if (name == 'abs') {
- return arguments.hasNoArguments() ? inferrer.types.positiveIntType : null;
- }
- return null;
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- Iterable<Element> oldTargets = targets;
- Selector typedSelector = computeTypedSelector(inferrer);
- inferrer.updateSelectorInTree(caller, call, typedSelector);
-
- Compiler compiler = inferrer.compiler;
- Selector selectorToUse = typedSelector.extendIfReachesAll(compiler);
- bool canReachAll = compiler.enabledInvokeOn &&
- (selectorToUse != typedSelector);
-
- // If this call could potentially reach all methods that satisfy
- // the untyped selector (through noSuchMethod's `Invocation`
- // and a call to `delegate`), we iterate over all these methods to
- // update their parameter types.
- targets = compiler.world.allFunctions.filter(selectorToUse);
- Iterable<Element> typedTargets = canReachAll
- ? compiler.world.allFunctions.filter(typedSelector)
- : targets;
-
- // Walk over the found targets, and compute the joined union type mask
- // for all these targets.
- TypeMask newType = inferrer.types.joinTypeMasks(targets.map((element) {
- if (!oldTargets.contains(element)) {
- MemberTypeInformation callee =
- inferrer.types.getInferredTypeOf(element);
- callee.addCall(caller, call);
- callee.addUser(this);
- inferrer.updateParameterAssignments(
- this, element, arguments, typedSelector, remove: false,
- addToQueue: true);
- }
-
- // If [canReachAll] is true, then we are iterating over all
- // targets that satisfy the untyped selector. We skip the return
- // type of the targets that can only be reached through
- // `Invocation.delegate`. Note that the `noSuchMethod` targets
- // are included in [typedTargets].
- if (canReachAll && !typedTargets.contains(element)) {
- return const TypeMask.nonNullEmpty();
- }
-
- if (inferrer.returnsListElementType(typedSelector)) {
- ContainerTypeMask mask = receiver.type;
- return mask.elementType;
- } else if (inferrer.returnsMapValueType(typedSelector)) {
- if (typedSelector.mask.isDictionary &&
- arguments.positional[0].type.isValue) {
- DictionaryTypeMask mask = typedSelector.mask;
- ValueTypeMask arg = arguments.positional[0].type;
- String key = arg.value;
- if (mask.typeMap.containsKey(key)) {
- if (_VERBOSE) {
- print("Dictionary lookup for $key yields ${mask.typeMap[key]}.");
- }
- return mask.typeMap[key];
- } else {
- // The typeMap is precise, so if we do not find the key, the lookup
- // will be [null] at runtime.
- if (_VERBOSE) {
- print("Dictionary lookup for $key yields [null].");
- }
- return inferrer.types.nullType.type;
- }
- }
- MapTypeMask mask = typedSelector.mask;
- if (_VERBOSE) {
- print("Map lookup for $typedSelector yields ${mask.valueType}.");
- }
- return mask.valueType;
- } else {
- TypeInformation info =
- handleIntrisifiedSelector(typedSelector, inferrer);
- if (info != null) return info.type;
- return inferrer.typeOfElementWithSelector(element, typedSelector).type;
- }
- }));
-
- // Walk over the old targets, and remove calls that cannot happen
- // anymore.
- oldTargets.forEach((element) {
- if (!targets.contains(element)) {
- MemberTypeInformation callee =
- inferrer.types.getInferredTypeOf(element);
- callee.removeCall(caller, call);
- callee.removeUser(this);
- inferrer.updateParameterAssignments(
- this, element, arguments, typedSelector, remove: true,
- addToQueue: true);
- }
- });
-
- return newType;
- }
-
- void giveUp(TypeGraphInferrerEngine inferrer, {bool clearAssignments: true}) {
- if (!abandonInferencing) {
- inferrer.updateSelectorInTree(caller, call, selector);
- Iterable<Element> oldTargets = targets;
- targets = inferrer.compiler.world.allFunctions.filter(selector);
- for (Element element in targets) {
- if (!oldTargets.contains(element)) {
- MemberTypeInformation callee =
- inferrer.types.getInferredTypeOf(element);
- callee.addCall(caller, call);
- inferrer.updateParameterAssignments(
- this, element, arguments, selector, remove: false,
- addToQueue: true);
- }
- }
- }
- super.giveUp(inferrer, clearAssignments: clearAssignments);
- }
-
- void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
- for (Element element in targets) {
- ElementTypeInformation callee = inferrer.types.getInferredTypeOf(element);
- callee.removeUser(this);
- }
- if (arguments != null) {
- arguments.forEach((info) => info.removeUser(this));
- }
- super.removeAndClearReferences(inferrer);
- }
-
- String toString() => 'Call site $call on ${receiver.type} $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitDynamicCallSiteTypeInformation(this);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return receiver.isStable &&
- targets.every(
- (element) => inferrer.types.getInferredTypeOf(element).isStable) &&
- (arguments == null || arguments.every((info) => info.isStable)) &&
- super.hasStableType(inferrer);
- }
-}
-
-class ClosureCallSiteTypeInformation extends CallSiteTypeInformation {
- final TypeInformation closure;
-
- ClosureCallSiteTypeInformation(
- MemberTypeInformation context,
- Spannable call,
- Element enclosing,
- Selector selector,
- this.closure,
- ArgumentsTypes arguments,
- bool inLoop)
- : super(context, call, enclosing, selector, arguments, inLoop);
-
- void addToGraph(TypeGraphInferrerEngine inferrer) {
- arguments.forEach((info) => info.addUser(this));
- closure.addUser(this);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) => safeType(inferrer);
-
- Iterable<Element> get callees {
- throw new UnsupportedError("Cannot compute callees of a closure call.");
- }
-
- String toString() => 'Closure call $call on $closure';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitClosureCallSiteTypeInformation(this);
- }
-
- void removeAndClearReferences(TypeGraphInferrerEngine inferrer) {
- // This method is a placeholder for the following comment:
- // We should maintain the information that the closure is a user
- // of its arguments because we do not check that the arguments
- // have a stable type for a closure call to be stable; our tracing
- // analysis want to know whether an (non-stable) argument is
- // passed to a closure.
- return super.removeAndClearReferences(inferrer);
- }
-}
-
-/**
- * A [ConcreteTypeInformation] represents a type that needed
- * to be materialized during the creation of the graph. For example,
- * literals, [:this:] or [:super:] need a [ConcreteTypeInformation].
- *
- * [ConcreteTypeInformation] nodes have no assignment. Also, to save
- * on memory, we do not add users to [ConcreteTypeInformation] nodes,
- * because we know such node will never be refined to a different
- * type.
- */
-class ConcreteTypeInformation extends TypeInformation {
- ConcreteTypeInformation(TypeMask type) : super.untracked() {
- this.type = type;
- this.isStable = true;
- }
-
- bool get isConcrete => true;
-
- void addUser(TypeInformation user) {
- // Nothing to do, a concrete type does not get updated so never
- // needs to notify its users.
- }
-
- void removeUser(TypeInformation user) {
- }
-
- void addAssignment(TypeInformation assignment) {
- throw "Not supported";
- }
-
- void removeAssignment(TypeInformation assignment) {
- throw "Not supported";
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) => type;
-
- bool reset(TypeGraphInferrerEngine inferrer) {
- throw "Not supported";
- }
-
- String toString() => 'Type $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitConcreteTypeInformation(this);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) => true;
-}
-
-class StringLiteralTypeInformation extends ConcreteTypeInformation {
- final ast.DartString value;
-
- StringLiteralTypeInformation(value, TypeMask mask)
- : super(new ValueTypeMask(mask, value.slowToString())),
- this.value = value;
-
- String asString() => value.slowToString();
- String toString() => 'Type $type value ${value.slowToString()}';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitStringLiteralTypeInformation(this);
- }
-}
-
-/**
- * A [NarrowTypeInformation] narrows a [TypeInformation] to a type,
- * represented in [typeAnnotation].
- *
- * A [NarrowTypeInformation] node has only one assignment: the
- * [TypeInformation] it narrows.
- *
- * [NarrowTypeInformation] nodes are created for:
- *
- * - Code after `is` and `as` checks, where we have more information
- * on the type of the right hand side of the expression.
- *
- * - Code after a dynamic call, where we have more information on the
- * type of the receiver: it can only be of a class that holds a
- * potential target of this dynamic call.
- *
- * - In checked mode, after a type annotation, we have more
- * information on the type of a local.
- */
-class NarrowTypeInformation extends TypeInformation {
- final TypeMask typeAnnotation;
-
- NarrowTypeInformation(TypeInformation narrowedType, this.typeAnnotation)
- : super(narrowedType.context) {
- addAssignment(narrowedType);
- }
-
- addAssignment(TypeInformation info) {
- super.addAssignment(info);
- assert(assignments.length == 1);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- TypeMask input = assignments.first.type;
- TypeMask intersection = input.intersection(typeAnnotation,
- inferrer.classWorld);
- if (_ANOMALY_WARN) {
- if (!input.containsMask(intersection, inferrer.classWorld) ||
- !typeAnnotation.containsMask(intersection, inferrer.classWorld)) {
- print("ANOMALY WARNING: narrowed $input to $intersection via "
- "$typeAnnotation");
- }
- }
- return intersection;
- }
-
- String toString() {
- return 'Narrow to $typeAnnotation $type';
- }
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitNarrowTypeInformation(this);
- }
-}
-
-/**
- * An [InferredTypeInformation] is a [TypeInformation] that
- * defaults to the dynamic type until it is marked as beeing
- * inferred, at which point it computes its type based on
- * its assignments.
- */
-abstract class InferredTypeInformation extends TypeInformation {
- /** Whether the element type in that container has been inferred. */
- bool inferred = false;
-
- InferredTypeInformation(MemberTypeInformation context,
- TypeInformation parentType)
- : super(context) {
- if (parentType != null) addAssignment(parentType);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- if (!inferred) return safeType(inferrer);
- return inferrer.types.computeTypeMask(assignments);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return inferred && super.hasStableType(inferrer);
- }
-}
-
-/**
- * A [ListTypeInformation] is a [TypeInformation] created
- * for each `List` instantiations.
- */
-class ListTypeInformation extends TypeInformation
- with TracedTypeInformation {
- final ElementInContainerTypeInformation elementType;
-
- /** The container type before it is inferred. */
- final ContainerTypeMask originalType;
-
- /** The length at the allocation site. */
- final int originalLength;
-
- /** The length after the container has been traced. */
- int inferredLength;
-
- /**
- * Whether this list goes through a growable check.
- * We conservatively assume it does.
- */
- bool checksGrowable = true;
-
- ListTypeInformation(MemberTypeInformation context,
- this.originalType,
- this.elementType,
- this.originalLength)
- : super(context) {
- type = originalType;
- inferredLength = originalType.length;
- elementType.addUser(this);
- }
-
- String toString() => 'List type $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitListTypeInformation(this);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return elementType.isStable && super.hasStableType(inferrer);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- var mask = type;
- if (!mask.isContainer ||
- mask.elementType != elementType.type ||
- mask.length != inferredLength) {
- return new ContainerTypeMask(originalType.forwardTo,
- originalType.allocationNode,
- originalType.allocationElement,
- elementType.type,
- inferredLength);
- }
- return mask;
- }
-
- TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType;
-}
-
-/**
- * An [ElementInContainerTypeInformation] holds the common type of the
- * elements in a [ListTypeInformation].
- */
-class ElementInContainerTypeInformation extends InferredTypeInformation {
- ElementInContainerTypeInformation(MemberTypeInformation context,
- elementType)
- : super(context, elementType);
-
- String toString() => 'Element in container $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitElementInContainerTypeInformation(this);
- }
-}
-
-/**
- * A [MapTypeInformation] is a [TypeInformation] created
- * for maps.
- */
-class MapTypeInformation extends TypeInformation
- with TracedTypeInformation {
- // When in Dictionary mode, this map tracks the type of the values that
- // have been assigned to a specific [String] key.
- final Map<String, ValueInMapTypeInformation> typeInfoMap = {};
- // These fields track the overall type of the keys/values in the map.
- final KeyInMapTypeInformation keyType;
- final ValueInMapTypeInformation valueType;
- final MapTypeMask originalType;
-
- // Set to false if a statically unknown key flows into this map.
- bool _allKeysAreStrings = true;
-
- bool get inDictionaryMode => !bailedOut && _allKeysAreStrings;
-
- MapTypeInformation(MemberTypeInformation context,
- this.originalType,
- this.keyType,
- this.valueType)
- : super(context) {
- keyType.addUser(this);
- valueType.addUser(this);
- type = originalType;
- }
-
- TypeInformation addEntryAssignment(TypeInformation key,
- TypeInformation value,
- [bool nonNull = false]) {
- TypeInformation newInfo = null;
- if (_allKeysAreStrings && key is StringLiteralTypeInformation) {
- String keyString = key.asString();
- typeInfoMap.putIfAbsent(keyString, () {
- newInfo = new ValueInMapTypeInformation(context, null, nonNull);
- return newInfo;
- });
- typeInfoMap[keyString].addAssignment(value);
- } else {
- _allKeysAreStrings = false;
- typeInfoMap.clear();
- }
- keyType.addAssignment(key);
- valueType.addAssignment(value);
- if (newInfo != null) newInfo.addUser(this);
-
- return newInfo;
- }
-
- List<TypeInformation> addMapAssignment(MapTypeInformation other) {
- List<TypeInformation> newInfos = <TypeInformation>[];
- if (_allKeysAreStrings && other.inDictionaryMode) {
- other.typeInfoMap.forEach((keyString, value) {
- typeInfoMap.putIfAbsent(keyString, () {
- TypeInformation newInfo =
- new ValueInMapTypeInformation(context, null, false);
- newInfos.add(newInfo);
- return newInfo;
- });
- typeInfoMap[keyString].addAssignment(value);
- });
- } else {
- _allKeysAreStrings = false;
- typeInfoMap.clear();
- }
- keyType.addAssignment(other.keyType);
- valueType.addAssignment(other.valueType);
-
- return newInfos;
- }
-
- markAsInferred() {
- keyType.inferred = valueType.inferred = true;
- typeInfoMap.values.forEach((v) => v.inferred = true);
- }
-
- addAssignment(TypeInformation other) {
- throw "not supported";
- }
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitMapTypeInformation(this);
- }
-
- TypeMask toTypeMask(TypeGraphInferrerEngine inferrer) {
- if (inDictionaryMode) {
- Map<String, TypeMask> mappings = new Map<String, TypeMask>();
- for (var key in typeInfoMap.keys) {
- mappings[key] = typeInfoMap[key].type;
- }
- return new DictionaryTypeMask(originalType.forwardTo,
- originalType.allocationNode,
- originalType.allocationElement,
- keyType.type,
- valueType.type,
- mappings);
- } else {
- return new MapTypeMask(originalType.forwardTo,
- originalType.allocationNode,
- originalType.allocationElement,
- keyType.type,
- valueType.type);
- }
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- if (type.isDictionary != inDictionaryMode) {
- return toTypeMask(inferrer);
- } else if (type.isDictionary) {
- assert(inDictionaryMode);
- DictionaryTypeMask mask = type;
- for (var key in typeInfoMap.keys) {
- TypeInformation value = typeInfoMap[key];
- if (!mask.typeMap.containsKey(key) &&
- !value.type.containsAll(inferrer.classWorld) &&
- !value.type.isNullable) {
- return toTypeMask(inferrer);
- }
- if (mask.typeMap[key] != typeInfoMap[key].type) {
- return toTypeMask(inferrer);
- }
- }
- } else if (type.isMap) {
- MapTypeMask mask = type;
- if (mask.keyType != keyType.type ||
- mask.valueType != valueType.type) {
- return toTypeMask(inferrer);
- }
- } else {
- return toTypeMask(inferrer);
- }
-
- return type;
- }
-
- TypeMask safeType(TypeGraphInferrerEngine inferrer) => originalType;
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return keyType.isStable &&
- valueType.isStable &&
- super.hasStableType(inferrer);
- }
-
- String toString() {
- return 'Map $type (K:$keyType, V:$valueType) contents $typeInfoMap';
- }
-}
-
-/**
- * A [KeyInMapTypeInformation] holds the common type
- * for the keys in a [MapTypeInformation]
- */
-class KeyInMapTypeInformation extends InferredTypeInformation {
- KeyInMapTypeInformation(MemberTypeInformation context,
- TypeInformation keyType)
- : super(context, keyType);
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitKeyInMapTypeInformation(this);
- }
-
- String toString() => 'Key in Map $type';
-}
-
-/**
- * A [ValueInMapTypeInformation] holds the common type
- * for the values in a [MapTypeInformation]
- */
-class ValueInMapTypeInformation extends InferredTypeInformation {
- // [nonNull] is set to true if this value is known to be part of the map.
- // Note that only values assigned to a specific key value in dictionary
- // mode can ever be marked as [nonNull].
- final bool nonNull;
-
- ValueInMapTypeInformation(MemberTypeInformation context,
- TypeInformation valueType, [this.nonNull = false])
- : super(context, valueType);
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitValueInMapTypeInformation(this);
- }
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- return nonNull ? super.computeType(inferrer)
- : super.computeType(inferrer).nullable();
- }
-
- String toString() => 'Value in Map $type';
-}
-
-/**
- * A [PhiElementTypeInformation] is an union of
- * [ElementTypeInformation], that is local to a method.
- */
-class PhiElementTypeInformation extends TypeInformation {
- final ast.Node branchNode;
- final bool isLoopPhi;
- final Local variable;
-
- PhiElementTypeInformation(MemberTypeInformation context, this.branchNode,
- this.isLoopPhi, this.variable)
- : super(context);
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) {
- return inferrer.types.computeTypeMask(assignments);
- }
-
- String toString() => 'Phi $variable $type';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitPhiElementTypeInformation(this);
- }
-}
-
-class ClosureTypeInformation extends TypeInformation
- with ApplyableTypeInformation {
- final ast.Node node;
- final Element element;
-
- ClosureTypeInformation(MemberTypeInformation context, this.node,
- this.element)
- : super(context);
-
- TypeMask computeType(TypeGraphInferrerEngine inferrer) => safeType(inferrer);
-
- TypeMask safeType(TypeGraphInferrerEngine inferrer) {
- return inferrer.types.functionType.type;
- }
-
- String toString() => 'Closure $element';
-
- accept(TypeInformationVisitor visitor) {
- return visitor.visitClosureTypeInformation(this);
- }
-
- bool hasStableType(TypeGraphInferrerEngine inferrer) {
- return false;
- }
-}
-
-/**
- * Mixin for [TypeInformation] nodes that can bail out during tracing.
- */
-abstract class TracedTypeInformation implements TypeInformation {
- /// Set to false once analysis has succeeded.
- bool bailedOut = true;
- /// Set to true once analysis is completed.
- bool analyzed = false;
-
- Set<TypeInformation> _flowsInto;
-
- /**
- * The set of [TypeInformation] nodes where values from the traced node could
- * flow in.
- */
- Set<TypeInformation> get flowsInto {
- return (_flowsInto == null) ? const ImmutableEmptySet<TypeInformation>()
- : _flowsInto;
- }
-
- /**
- * Adds [nodes] to the sets of values this [TracedTypeInformation] flows into.
- */
- void addFlowsIntoTargets(Iterable<TypeInformation> nodes) {
- if (_flowsInto == null) {
- _flowsInto = nodes.toSet();
- } else {
- _flowsInto.addAll(nodes);
- }
- }
-}
-
-abstract class TypeInformationVisitor<T> {
- T visitNarrowTypeInformation(NarrowTypeInformation info);
- T visitPhiElementTypeInformation(PhiElementTypeInformation info);
- T visitElementInContainerTypeInformation(
- ElementInContainerTypeInformation info);
- T visitKeyInMapTypeInformation(KeyInMapTypeInformation info);
- T visitValueInMapTypeInformation(ValueInMapTypeInformation info);
- T visitListTypeInformation(ListTypeInformation info);
- T visitMapTypeInformation(MapTypeInformation info);
- T visitConcreteTypeInformation(ConcreteTypeInformation info);
- T visitStringLiteralTypeInformation(StringLiteralTypeInformation info);
- T visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info);
- T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info);
- T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info);
- T visitMemberTypeInformation(MemberTypeInformation info);
- T visitParameterTypeInformation(ParameterTypeInformation info);
- T visitClosureTypeInformation(ClosureTypeInformation info);
-}

Powered by Google App Engine
This is Rietveld 408576698