| Index: pkg/compiler/lib/src/types/types.dart
|
| diff --git a/pkg/compiler/lib/src/types/types.dart b/pkg/compiler/lib/src/types/types.dart
|
| index 28dc608cb384ef9bfd2da203f58f908c24909ea9..ad890dc6c79f6aaaee44a7880f2eb00d1abbeba8 100644
|
| --- a/pkg/compiler/lib/src/types/types.dart
|
| +++ b/pkg/compiler/lib/src/types/types.dart
|
| @@ -9,6 +9,7 @@ import '../compiler.dart' show Compiler;
|
| import '../elements/elements.dart';
|
| import '../inferrer/type_graph_inferrer.dart' show TypeGraphInferrer;
|
| import '../tree/tree.dart';
|
| +import '../resolution/tree_elements.dart';
|
| import '../universe/selector.dart' show Selector;
|
|
|
| import 'masks.dart';
|
| @@ -19,13 +20,108 @@ abstract class TypesInferrer {
|
| void analyzeMain(Element element);
|
| TypeMask getReturnTypeOfElement(Element element);
|
| TypeMask getTypeOfElement(Element element);
|
| - TypeMask getTypeOfNode(Element owner, Node node);
|
| + TypeMask getTypeForNewList(Element owner, Node node);
|
| TypeMask getTypeOfSelector(Selector selector, TypeMask mask);
|
| void clear();
|
| bool isCalledOnce(Element element);
|
| bool isFixedArrayCheckedForGrowable(Node node);
|
| }
|
|
|
| +/// Results produced by the global type-inference algorithm.
|
| +///
|
| +/// All queries in this class may contain results that assume whole-program
|
| +/// closed-world semantics. Any [TypeMask] for an element or node that we return
|
| +/// was inferred to be a "guaranteed type", that means, it is a type that we
|
| +/// can prove to be correct for all executions of the program.
|
| +class GlobalTypeInferenceResults {
|
| + // TODO(sigmund): store relevant data & drop reference to inference engine.
|
| + final TypesInferrer _inferrer;
|
| + final Compiler compiler;
|
| + final TypeMask dynamicType;
|
| +
|
| + GlobalTypeInferenceResults(this._inferrer, this.compiler, CommonMasks masks)
|
| + : dynamicType = masks.dynamicType;
|
| +
|
| + /// Returns the type of a parameter or field [element], if any.
|
| + TypeMask typeOf(Element element) {
|
| + // TODO(24489): trust some JsInterop types.
|
| + if (compiler.backend.isJsInterop(element)) return dynamicType;
|
| + return _inferrer.getTypeOfElement(element);
|
| + }
|
| +
|
| + /// Returns the return type of a method or function [element].
|
| + TypeMask returnTypeOf(Element element) {
|
| + // TODO(24489): trust some JsInterop types.
|
| + if (compiler.backend.isJsInterop(element)) return dynamicType;
|
| + return _inferrer.getReturnTypeOfElement(element);
|
| + }
|
| +
|
| + /// Returns the type of a [selector] when applied to a receiver with the given
|
| + /// type [mask].
|
| + TypeMask typeOfSelector(Selector selector, TypeMask mask) =>
|
| + _inferrer.getTypeOfSelector(selector, mask);
|
| +
|
| + /// Returns whether the method [element] always throws.
|
| + bool throwsAlways(Element element) {
|
| + // We know the element always throws if the return type was inferred to be
|
| + // non-null empty.
|
| + TypeMask returnType = returnTypeOf(element);
|
| + return returnType != null && returnType.isEmpty;
|
| + }
|
| +
|
| + /// Returns whether [element] is only called once in the entire program.
|
| + bool isCalledOnce(Element element) => _inferrer.isCalledOnce(element);
|
| +
|
| + // TODO(sigmund): introduce a new class [ElementInferenceResult] that can be
|
| + // used to collect any information that is specific about the body within a
|
| + // single element (basically everything below this line). We could consider
|
| + // moving some of the functions above too, for example:
|
| + // results.throwsAlways(element)
|
| + // could become:
|
| + // results[element].alwaysThrows;
|
| + //
|
| +
|
| + /// Returns the type of a list allocation [node] occuring within [owner].
|
| + ///
|
| + /// [node] can be a list literal or a list new expression.
|
| + TypeMask typeOfNewList(Element owner, Node node) =>
|
| + _inferrer.getTypeForNewList(owner, node);
|
| +
|
| + /// Returns whether a fixed-length constructor call goes through a growable
|
| + /// check.
|
| + bool isFixedArrayCheckedForGrowable(Node ctorCall) =>
|
| + _inferrer.isFixedArrayCheckedForGrowable(ctorCall);
|
| +
|
| + /// Returns the type of a send [node].
|
| + TypeMask typeOfSend(
|
| + Node node,
|
| + // TODO(sigmund): move inference data out of TreeElements
|
| + TreeElements elements) =>
|
| + elements.getTypeMask(node);
|
| +
|
| + /// Returns the type of the operator of a complex send-set [node], for
|
| + /// example, the type of `+` in `a += b`.
|
| + TypeMask typeOfOperator(Send node, TreeElements elements) =>
|
| + elements.getOperatorTypeMaskInComplexSendSet(node);
|
| +
|
| + /// Returns the type of the getter in a complex send-set [node], for example,
|
| + /// the type of the `a.f` getter in `a.f += b`.
|
| + TypeMask typeOfGetter(node, elements) =>
|
| + elements.getGetterTypeMaskInComplexSendSet(node);
|
| +
|
| + /// Returns the type of the iterator in a [loop].
|
| + TypeMask typeOfIterator(ForIn loop, elements) =>
|
| + elements.getIteratorTypeMask(loop);
|
| +
|
| + /// Returns the type of the `moveNext` call of an iterator in a [loop].
|
| + TypeMask typeOfIteratorMoveNext(ForIn loop, elements) =>
|
| + elements.getMoveNextTypeMask(loop);
|
| +
|
| + /// Returns the type of the `current` getter of an iterator in a [loop].
|
| + TypeMask typeOfIteratorCurrent(ForIn node, elements) =>
|
| + elements.getCurrentTypeMask(node);
|
| +}
|
| +
|
| /// Global analysis that infers concrete types.
|
| class GlobalTypeInferenceTask extends CompilerTask {
|
| // TODO(sigmund): rename at the same time as our benchmarking tools.
|
| @@ -34,6 +130,7 @@ class GlobalTypeInferenceTask extends CompilerTask {
|
| final Compiler compiler;
|
| TypesInferrer typesInferrer;
|
| CommonMasks masks;
|
| + GlobalTypeInferenceResults results;
|
|
|
| GlobalTypeInferenceTask(Compiler compiler)
|
| : masks = new CommonMasks(compiler),
|
| @@ -47,59 +144,7 @@ class GlobalTypeInferenceTask extends CompilerTask {
|
| measure(() {
|
| typesInferrer.analyzeMain(mainElement);
|
| typesInferrer.clear();
|
| + results = new GlobalTypeInferenceResults(typesInferrer, compiler, masks);
|
| });
|
| }
|
| -
|
| - /**
|
| - * Return the (inferred) guaranteed type of [element] or null.
|
| - */
|
| - TypeMask getGuaranteedTypeOfElement(Element element) {
|
| - // TODO(24489): trust some JsInterop types.
|
| - if (compiler.backend.isJsInterop(element)) {
|
| - return masks.dynamicType;
|
| - }
|
| - TypeMask guaranteedType = typesInferrer.getTypeOfElement(element);
|
| - return guaranteedType;
|
| - }
|
| -
|
| - TypeMask getGuaranteedReturnTypeOfElement(Element element) {
|
| - // TODO(24489): trust some JsInterop types.
|
| - if (compiler.backend.isJsInterop(element)) {
|
| - return masks.dynamicType;
|
| - }
|
| -
|
| - TypeMask guaranteedType = typesInferrer.getReturnTypeOfElement(element);
|
| - return guaranteedType;
|
| - }
|
| -
|
| - /// Return whether the global inference algorithm determined that [element]
|
| - /// always throws.
|
| - bool throwsAlways(Element element) {
|
| - // We know the element always throws if the return type was inferred to be
|
| - // non-null empty.
|
| - TypeMask returnType = getGuaranteedReturnTypeOfElement(element);
|
| - return returnType != null && returnType.isEmpty;
|
| - }
|
| -
|
| - bool isFixedArrayCheckedForGrowable(Node send) =>
|
| - typesInferrer.isFixedArrayCheckedForGrowable(send);
|
| -
|
| - bool isCalledOnce(Element element) => typesInferrer.isCalledOnce(element);
|
| -
|
| - /**
|
| - * Return the (inferred) guaranteed type of [node] or null.
|
| - * [node] must be an AST node of [owner].
|
| - */
|
| - TypeMask getGuaranteedTypeOfNode(owner, node) {
|
| - TypeMask guaranteedType = typesInferrer.getTypeOfNode(owner, node);
|
| - return guaranteedType;
|
| - }
|
| -
|
| - /**
|
| - * Return the (inferred) guaranteed type of [selector] or null.
|
| - */
|
| - TypeMask getGuaranteedTypeOfSelector(Selector selector, TypeMask mask) {
|
| - TypeMask guaranteedType = typesInferrer.getTypeOfSelector(selector, mask);
|
| - return guaranteedType;
|
| - }
|
| }
|
|
|