Chromium Code Reviews| 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..b9be5525ae688aaf7551dc9fbad2446dbf2bc344 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); |
| + // TODO(johnniwinther): Rename this. |
| + TypeMask typeOfSend(T 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); |
| + TypeMask typeOfGetter(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`. |
|
Siggi Cherem (dart-lang)
2017/08/09 16:22:42
seems for some reason the comment here and the com
Johnni Winther
2017/08/10 09:00:50
Done.
|
| - TypeMask typeOfOperator(SendSet node); |
| + 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,17 @@ 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); |
| } |
| /// Results produced by the global type-inference algorithm. |
| @@ -243,51 +249,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 +302,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 +377,13 @@ 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 = compiler.backendStrategy |
| + .createTypesInferrerResults(typesInferrerInternal, closedWorld); |
| }); |
| } |
| } |