| 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 2a132f12b7e6a509f2283f2508455994da95f6c6..03d72ea2d9cea02f5e298014689d732a726f68c1 100644
|
| --- a/pkg/compiler/lib/src/types/types.dart
|
| +++ b/pkg/compiler/lib/src/types/types.dart
|
| @@ -28,7 +28,7 @@ export 'masks.dart';
|
| /// implementation would return false on all boolean properties (giving no
|
| /// guarantees) and the `subclass of Object or null` type mask for the type
|
| /// based queries (the runtime value could be anything).
|
| -abstract class GlobalTypeInferenceElementResult {
|
| +abstract class GlobalTypeInferenceElementResult<T> {
|
| /// Whether the method element associated with this result always throws.
|
| bool get throwsAlways;
|
|
|
| @@ -40,54 +40,55 @@ abstract class GlobalTypeInferenceElementResult {
|
| TypeMask get returnType;
|
|
|
| /// Returns the type of a list new expression [node].
|
| - TypeMask typeOfNewList(Send node);
|
| + TypeMask typeOfNewList(T node);
|
|
|
| /// Returns the type of a list literal [node].
|
| - TypeMask typeOfListLiteral(LiteralList node);
|
| + TypeMask typeOfListLiteral(T node);
|
|
|
| /// Returns the type of a send [node].
|
| - TypeMask typeOfSend(Send node);
|
| -
|
| - /// Returns the type of the operator of a complex send-set [node], for
|
| - /// example, the type of `+` in `a += b`.
|
| - TypeMask typeOfGetter(SendSet node);
|
| + // TODO(johnniwinther): Rename this.
|
| + TypeMask typeOfSend(T 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 typeOfOperator(SendSet node);
|
| + TypeMask typeOfGetter(T node);
|
| +
|
| + /// Returns the type of the operator of a complex send-set [node], for
|
| + /// example, the type of `+` in `a += b`.
|
| + TypeMask typeOfOperator(T node);
|
|
|
| /// Returns the type of the iterator in a [loop].
|
| - TypeMask typeOfIterator(ForIn node);
|
| + TypeMask typeOfIterator(T node);
|
|
|
| /// Returns the type of the `moveNext` call of an iterator in a [loop].
|
| - TypeMask typeOfIteratorMoveNext(ForIn node);
|
| + TypeMask typeOfIteratorMoveNext(T node);
|
|
|
| /// Returns the type of the `current` getter of an iterator in a [loop].
|
| - TypeMask typeOfIteratorCurrent(ForIn node);
|
| + TypeMask typeOfIteratorCurrent(T node);
|
| }
|
|
|
| -abstract class GlobalTypeInferenceMemberResult
|
| - extends GlobalTypeInferenceElementResult {
|
| +abstract class GlobalTypeInferenceMemberResult<T>
|
| + extends GlobalTypeInferenceElementResult<T> {
|
| /// Whether the member associated with this result is only called once in one
|
| /// location in the entire program.
|
| bool get isCalledOnce;
|
| }
|
|
|
| -abstract class GlobalTypeInferenceElementResultImpl
|
| - implements GlobalTypeInferenceElementResult {
|
| - // TODO(sigmund): delete, store data directly here.
|
| - final Element _owner;
|
| +abstract class GlobalTypeInferenceParameterResult<T>
|
| + extends GlobalTypeInferenceElementResult<T> {}
|
|
|
| +abstract class GlobalTypeInferenceElementResultImpl<T>
|
| + implements GlobalTypeInferenceElementResult<T> {
|
| // TODO(sigmund): split - stop using _data after inference is done.
|
| - final GlobalTypeInferenceElementData _data;
|
| + final GlobalTypeInferenceElementData<T> _data;
|
|
|
| // TODO(sigmund): store relevant data & drop reference to inference engine.
|
| - final TypesInferrer _inferrer;
|
| + final TypesInferrer<T> _inferrer;
|
| final bool _isJsInterop;
|
| final TypeMask _dynamic;
|
|
|
| - GlobalTypeInferenceElementResultImpl.internal(this._owner, this._data,
|
| - this._inferrer, this._isJsInterop, this._dynamic);
|
| + GlobalTypeInferenceElementResultImpl(
|
| + this._data, this._inferrer, this._isJsInterop, this._dynamic);
|
|
|
| bool get throwsAlways {
|
| TypeMask mask = this.returnType;
|
| @@ -95,31 +96,32 @@ abstract class GlobalTypeInferenceElementResultImpl
|
| return mask != null && mask.isEmpty;
|
| }
|
|
|
| - TypeMask typeOfNewList(Send node) => _inferrer.getTypeForNewList(node);
|
| + TypeMask typeOfNewList(T node) => _inferrer.getTypeForNewList(node);
|
|
|
| - TypeMask typeOfListLiteral(LiteralList node) =>
|
| - _inferrer.getTypeForNewList(node);
|
| + TypeMask typeOfListLiteral(T node) => _inferrer.getTypeForNewList(node);
|
|
|
| - TypeMask typeOfSend(Send node) => _data?.typeOfSend(node);
|
| - TypeMask typeOfGetter(SendSet node) => _data?.typeOfGetter(node);
|
| - TypeMask typeOfOperator(SendSet node) => _data?.typeOfOperator(node);
|
| - TypeMask typeOfIterator(ForIn node) => _data?.typeOfIterator(node);
|
| - TypeMask typeOfIteratorMoveNext(ForIn node) =>
|
| + TypeMask typeOfSend(T node) => _data?.typeOfSend(node);
|
| + TypeMask typeOfGetter(T node) => _data?.typeOfGetter(node);
|
| + TypeMask typeOfOperator(T node) => _data?.typeOfOperator(node);
|
| + TypeMask typeOfIterator(T node) => _data?.typeOfIterator(node);
|
| + TypeMask typeOfIteratorMoveNext(T node) =>
|
| _data?.typeOfIteratorMoveNext(node);
|
| - TypeMask typeOfIteratorCurrent(ForIn node) =>
|
| - _data?.typeOfIteratorCurrent(node);
|
| + TypeMask typeOfIteratorCurrent(T node) => _data?.typeOfIteratorCurrent(node);
|
| }
|
|
|
| -class GlobalTypeInferenceMemberResultImpl
|
| - extends GlobalTypeInferenceElementResultImpl
|
| - implements GlobalTypeInferenceMemberResult {
|
| +class GlobalTypeInferenceMemberResultImpl<T>
|
| + extends GlobalTypeInferenceElementResultImpl<T>
|
| + implements GlobalTypeInferenceMemberResult<T> {
|
| + // TODO(sigmund): delete, store data directly here.
|
| + final MemberEntity _owner;
|
| +
|
| GlobalTypeInferenceMemberResultImpl(
|
| - MemberElement owner,
|
| + this._owner,
|
| GlobalTypeInferenceElementData data,
|
| TypesInferrer inferrer,
|
| bool isJsInterop,
|
| TypeMask _dynamic)
|
| - : super.internal(owner, data, inferrer, isJsInterop, _dynamic);
|
| + : super(data, inferrer, isJsInterop, _dynamic);
|
|
|
| bool get isCalledOnce => _inferrer.isMemberCalledOnce(_owner);
|
|
|
| @@ -130,11 +132,15 @@ class GlobalTypeInferenceMemberResultImpl
|
| _isJsInterop ? _dynamic : _inferrer.getTypeOfMember(_owner);
|
| }
|
|
|
| -class GlobalTypeInferenceParameterResult
|
| - extends GlobalTypeInferenceElementResultImpl {
|
| - GlobalTypeInferenceParameterResult(
|
| - ParameterElement owner, TypesInferrer inferrer, TypeMask _dynamic)
|
| - : super.internal(owner, null, inferrer, false, _dynamic);
|
| +class GlobalTypeInferenceParameterResultImpl<T>
|
| + extends GlobalTypeInferenceElementResultImpl<T>
|
| + implements GlobalTypeInferenceParameterResult<T> {
|
| + // TODO(sigmund): delete, store data directly here.
|
| + final Local _owner;
|
| +
|
| + GlobalTypeInferenceParameterResultImpl(
|
| + this._owner, TypesInferrer inferrer, TypeMask _dynamic)
|
| + : super(null, inferrer, false, _dynamic);
|
|
|
| TypeMask get returnType =>
|
| _isJsInterop ? _dynamic : _inferrer.getReturnTypeOfParameter(_owner);
|
| @@ -224,17 +230,18 @@ class AstGlobalTypeInferenceElementData
|
| }
|
|
|
| /// API to interact with the global type-inference engine.
|
| -abstract class TypesInferrer {
|
| +abstract class TypesInferrer<T> {
|
| void analyzeMain(FunctionEntity element);
|
| - TypeMask getReturnTypeOfMember(MemberElement element);
|
| - TypeMask getReturnTypeOfParameter(ParameterElement element);
|
| - TypeMask getTypeOfMember(MemberElement element);
|
| - TypeMask getTypeOfParameter(ParameterElement element);
|
| - TypeMask getTypeForNewList(Node node);
|
| + TypeMask getReturnTypeOfMember(MemberEntity element);
|
| + TypeMask getReturnTypeOfParameter(Local element);
|
| + TypeMask getTypeOfMember(MemberEntity element);
|
| + TypeMask getTypeOfParameter(Local element);
|
| + TypeMask getTypeForNewList(T node);
|
| TypeMask getTypeOfSelector(Selector selector, TypeMask mask);
|
| void clear();
|
| - bool isMemberCalledOnce(MemberElement element);
|
| - bool isFixedArrayCheckedForGrowable(Node node);
|
| + bool isMemberCalledOnce(MemberEntity element);
|
| + bool isFixedArrayCheckedForGrowable(T node);
|
| + GlobalTypeInferenceResults createResults();
|
| }
|
|
|
| /// Results produced by the global type-inference algorithm.
|
| @@ -243,51 +250,48 @@ abstract class TypesInferrer {
|
| /// 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 {
|
| +abstract class GlobalTypeInferenceResults<T> {
|
| // TODO(sigmund): store relevant data & drop reference to inference engine.
|
| - final TypeGraphInferrer _inferrer;
|
| + final TypeGraphInferrer<T> _inferrer;
|
| final ClosedWorld closedWorld;
|
| - final Map<MemberElement, GlobalTypeInferenceMemberResult> _memberResults =
|
| - <MemberElement, GlobalTypeInferenceMemberResult>{};
|
| - final Map<ParameterElement, GlobalTypeInferenceParameterResult>
|
| - _parameterResults =
|
| - <ParameterElement, GlobalTypeInferenceParameterResult>{};
|
| + final Map<MemberEntity, GlobalTypeInferenceMemberResult<T>> _memberResults =
|
| + <MemberEntity, GlobalTypeInferenceMemberResult<T>>{};
|
| + final Map<Local, GlobalTypeInferenceParameterResult<T>> _parameterResults =
|
| + <Local, GlobalTypeInferenceParameterResult<T>>{};
|
| +
|
| + GlobalTypeInferenceResults(this._inferrer, this.closedWorld);
|
| +
|
| + /// Create the [GlobalTypeInferenceMemberResult] object for [member].
|
| + GlobalTypeInferenceMemberResult<T> createMemberResult(
|
| + TypeGraphInferrer<T> inferrer, MemberEntity member,
|
| + {bool isJsInterop: false});
|
| +
|
| + /// Create the [GlobalTypeInferenceParameterResult] object for [parameter].
|
| + GlobalTypeInferenceParameterResult<T> createParameterResult(
|
| + TypeGraphInferrer<T> inferrer, Local parameter);
|
|
|
| // TODO(sigmund,johnniwinther): compute result objects eagerly and make it an
|
| // error to query for results that don't exist.
|
| - GlobalTypeInferenceMemberResult resultOfMember(MemberElement member) {
|
| + GlobalTypeInferenceMemberResult<T> resultOfMember(MemberEntity member) {
|
| assert(
|
| - !member.isGenerativeConstructorBody,
|
| + member is! ConstructorBodyEntity,
|
| failedAt(
|
| member,
|
| "unexpected input: ConstructorBodyElements are created"
|
| " after global type inference, no data is avaiable for them."));
|
|
|
| bool isJsInterop = closedWorld.nativeData.isJsInteropMember(member);
|
| - return _memberResults.putIfAbsent(
|
| - member,
|
| - () => new GlobalTypeInferenceMemberResultImpl(
|
| - member,
|
| - // We store data in the context of the enclosing method, even
|
| - // for closure elements.
|
| - _inferrer.inferrer.lookupDataOfMember(member.memberContext),
|
| - _inferrer,
|
| - isJsInterop,
|
| - dynamicType));
|
| + return _memberResults.putIfAbsent(member,
|
| + () => createMemberResult(_inferrer, member, isJsInterop: isJsInterop));
|
| }
|
|
|
| // TODO(sigmund,johnniwinther): compute result objects eagerly and make it an
|
| // error to query for results that don't exist.
|
| - GlobalTypeInferenceElementResult resultOfParameter(
|
| - ParameterElement parameter) {
|
| + GlobalTypeInferenceElementResult<T> resultOfParameter(Local parameter) {
|
| return _parameterResults.putIfAbsent(
|
| - parameter,
|
| - () => new GlobalTypeInferenceParameterResult(
|
| - parameter, _inferrer, dynamicType));
|
| + parameter, () => createParameterResult(_inferrer, parameter));
|
| }
|
|
|
| - GlobalTypeInferenceResults(this._inferrer, this.closedWorld);
|
| -
|
| TypeMask get dynamicType => closedWorld.commonMasks.dynamicType;
|
|
|
| /// Returns the type of a [selector] when applied to a receiver with the given
|
| @@ -299,10 +303,60 @@ class GlobalTypeInferenceResults {
|
| /// check.
|
| // TODO(sigmund): move into the result of the element containing such
|
| // constructor call.
|
| - bool isFixedArrayCheckedForGrowable(Node ctorCall) =>
|
| + bool isFixedArrayCheckedForGrowable(T ctorCall) =>
|
| _inferrer.isFixedArrayCheckedForGrowable(ctorCall);
|
| }
|
|
|
| +/// Mixin that assert the types of the nodes used for querying type masks.
|
| +abstract class AstGlobalTypeInferenceElementResultMixin
|
| + implements GlobalTypeInferenceElementResultImpl<Node> {
|
| + TypeMask typeOfNewList(covariant Send node) =>
|
| + _inferrer.getTypeForNewList(node);
|
| +
|
| + TypeMask typeOfListLiteral(covariant LiteralList node) =>
|
| + _inferrer.getTypeForNewList(node);
|
| +
|
| + TypeMask typeOfSend(covariant Send node) => _data?.typeOfSend(node);
|
| + TypeMask typeOfGetter(covariant SendSet node) => _data?.typeOfGetter(node);
|
| + TypeMask typeOfOperator(covariant SendSet node) =>
|
| + _data?.typeOfOperator(node);
|
| + TypeMask typeOfIterator(covariant ForIn node) => _data?.typeOfIterator(node);
|
| + TypeMask typeOfIteratorMoveNext(covariant ForIn node) =>
|
| + _data?.typeOfIteratorMoveNext(node);
|
| + TypeMask typeOfIteratorCurrent(covariant ForIn node) =>
|
| + _data?.typeOfIteratorCurrent(node);
|
| +}
|
| +
|
| +class AstMemberResult = GlobalTypeInferenceMemberResultImpl<Node>
|
| + with AstGlobalTypeInferenceElementResultMixin;
|
| +
|
| +class AstParameterResult = GlobalTypeInferenceParameterResultImpl<Node>
|
| + with AstGlobalTypeInferenceElementResultMixin;
|
| +
|
| +class AstGlobalTypeInferenceResults extends GlobalTypeInferenceResults<Node> {
|
| + AstGlobalTypeInferenceResults(
|
| + TypesInferrer<Node> inferrer, ClosedWorld closedWorld)
|
| + : super(inferrer, closedWorld);
|
| +
|
| + GlobalTypeInferenceMemberResult<Node> createMemberResult(
|
| + TypeGraphInferrer<Node> inferrer, covariant MemberElement member,
|
| + {bool isJsInterop: false}) {
|
| + return new AstMemberResult(
|
| + member,
|
| + // We store data in the context of the enclosing method, even
|
| + // for closure elements.
|
| + inferrer.inferrer.lookupDataOfMember(member.memberContext),
|
| + inferrer,
|
| + isJsInterop,
|
| + dynamicType);
|
| + }
|
| +
|
| + GlobalTypeInferenceParameterResult<Node> createParameterResult(
|
| + TypeGraphInferrer<Node> inferrer, Local parameter) {
|
| + return new AstParameterResult(parameter, inferrer, dynamicType);
|
| + }
|
| +}
|
| +
|
| /// Global analysis that infers concrete types.
|
| class GlobalTypeInferenceTask extends CompilerTask {
|
| // TODO(sigmund): rename at the same time as our benchmarking tools.
|
| @@ -324,12 +378,12 @@ class GlobalTypeInferenceTask extends CompilerTask {
|
| void runGlobalTypeInference(FunctionEntity mainElement,
|
| ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {
|
| measure(() {
|
| - typesInferrerInternal ??=
|
| - new TypeGraphInferrer(compiler, closedWorld, closedWorldRefiner);
|
| + typesInferrerInternal ??= compiler.backendStrategy.createTypesInferrer(
|
| + closedWorldRefiner,
|
| + disableTypeInference: compiler.disableTypeInference);
|
| typesInferrerInternal.analyzeMain(mainElement);
|
| typesInferrerInternal.clear();
|
| - results =
|
| - new GlobalTypeInferenceResults(typesInferrerInternal, closedWorld);
|
| + results = typesInferrerInternal.createResults();
|
| });
|
| }
|
| }
|
|
|