Split MemberTypeInformation by member kind

R=sigmund@google.com

Review-Url: https://codereview.chromium.org/2971693002 .
This commit is contained in:
Johnni Winther 2017-07-06 11:06:14 +02:00
parent 69580bda61
commit 83082487bb
2 changed files with 171 additions and 79 deletions

View file

@ -13,11 +13,8 @@ import '../constants/values.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/resolution_types.dart'
show
ResolutionDartType,
ResolutionFunctionType,
ResolutionInterfaceType,
ResolutionTypeKind;
show ResolutionDartType, ResolutionInterfaceType;
import '../elements/types.dart';
import '../tree/tree.dart' as ast show Node, Send;
import '../types/masks.dart'
show
@ -370,7 +367,7 @@ abstract class ElementTypeInformation extends TypeInformation {
* These should never be created directly but instead are constructed by
* the [ElementTypeInformation] factory.
*/
class MemberTypeInformation extends ElementTypeInformation
abstract class MemberTypeInformation extends ElementTypeInformation
with ApplyableTypeInformation {
MemberElement get _member => super._element;
@ -396,7 +393,8 @@ class MemberTypeInformation extends ElementTypeInformation
*/
Map<MemberElement, Setlet<Spannable>> _callers;
MemberTypeInformation(MemberElement element) : super._internal(null, element);
MemberTypeInformation._internal(MemberElement element)
: super._internal(null, element);
MemberElement get member => _element;
@ -455,59 +453,19 @@ class MemberTypeInformation extends ElementTypeInformation
// state of the [isStable] field inherited from [TypeInformation].
bool get isStable => super.isStable && !isClosurized;
TypeMask handleSpecialCases(InferrerEngine inferrer) {
if (_member.isField &&
(!inferrer.backend.canFieldBeUsedForGlobalOptimizations(
_member, inferrer.closedWorld) ||
inferrer.assumeDynamic(_member))) {
// Do not infer types for fields that have a corresponding annotation or
// are assigned by synthesized calls
TypeMask handleSpecialCases(InferrerEngine inferrer);
giveUp(inferrer);
return safeType(inferrer);
}
if (inferrer.closedWorld.nativeData.isNativeMember(_member)) {
TypeMask _handleFunctionCase(
FunctionEntity function, InferrerEngine inferrer) {
if (inferrer.closedWorld.nativeData.isNativeMember(function)) {
// 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 (_member.isField) {
FieldElement field = _member;
return inferrer
.typeOfNativeBehavior(inferrer.closedWorld.nativeData
.getNativeFieldLoadBehavior(field))
.type;
} else {
assert(_member.isFunction ||
_member.isGetter ||
_member.isSetter ||
_member.isConstructor);
MethodElement methodElement = _member;
var elementType = methodElement.type;
if (elementType.kind != ResolutionTypeKind.FUNCTION) {
return safeType(inferrer);
} else {
return inferrer
.typeOfNativeBehavior(inferrer.closedWorld.nativeData
.getNativeMethodBehavior(methodElement))
.type;
}
}
}
CommonMasks commonMasks = inferrer.commonMasks;
if (_member.isConstructor) {
ConstructorElement constructor = _member;
if (constructor.isIntFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.intType.nullable();
} else if (constructor.isBoolFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.boolType.nullable();
} else if (constructor.isStringFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.stringType.nullable();
}
return inferrer
.typeOfNativeBehavior(
inferrer.closedWorld.nativeData.getNativeMethodBehavior(function))
.type;
}
return null;
}
@ -519,19 +477,11 @@ class MemberTypeInformation extends ElementTypeInformation
!inferrer.trustTypeAnnotations(_member)) {
return mask;
}
if (_member.isGenerativeConstructor || _member.isSetter) {
return mask;
}
if (_member.isField) {
return _narrowType(inferrer.closedWorld, mask, _member.type);
}
assert(
_member.isFunction || _member.isGetter || _member.isFactoryConstructor);
ResolutionFunctionType type = _member.type;
return _narrowType(inferrer.closedWorld, mask, type.returnType);
return _potentiallyNarrowType(mask, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer);
TypeMask computeType(InferrerEngine inferrer) {
TypeMask special = handleSpecialCases(inferrer);
if (special != null) return potentiallyNarrowType(special, inferrer);
@ -549,18 +499,6 @@ class MemberTypeInformation extends ElementTypeInformation
return visitor.visitMemberTypeInformation(this);
}
bool hasStableType(InferrerEngine inferrer) {
// The number of assignments of non-final fields is
// not stable. Therefore such a field cannot be stable.
if (_member.isField && !(_member.isConst || _member.isFinal)) {
return false;
}
if (_member.isFunction) return false;
return super.hasStableType(inferrer);
}
void cleanup() {
// This node is on multiple lists so cleanup() can be called twice.
if (_isCalledOnce != null) return;
@ -575,6 +513,144 @@ class MemberTypeInformation extends ElementTypeInformation
}
}
class FieldTypeInformation extends MemberTypeInformation {
FieldElement get _field => _member;
FieldTypeInformation(FieldElement element) : super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
if (!inferrer.backend.canFieldBeUsedForGlobalOptimizations(
_field, inferrer.closedWorld) ||
inferrer.assumeDynamic(_field)) {
// Do not infer types for fields that have a corresponding annotation or
// are assigned by synthesized calls
giveUp(inferrer);
return safeType(inferrer);
}
if (inferrer.closedWorld.nativeData.isNativeMember(_field)) {
// 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);
return inferrer
.typeOfNativeBehavior(inferrer.closedWorld.nativeData
.getNativeFieldLoadBehavior(_field))
.type;
}
return null;
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
return _narrowType(inferrer.closedWorld, mask, _field.type);
}
bool hasStableType(InferrerEngine inferrer) {
// The number of assignments of non-final fields is
// not stable. Therefore such a field cannot be stable.
if (!(_field.isConst || _field.isFinal)) {
return false;
}
return super.hasStableType(inferrer);
}
}
class GetterTypeInformation extends MemberTypeInformation {
GetterElement get _getter => _member;
GetterTypeInformation(GetterElement element) : super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_getter, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
FunctionType type = _getter.type;
return _narrowType(inferrer.closedWorld, mask, type.returnType);
}
}
class SetterTypeInformation extends MemberTypeInformation {
SetterElement get _setter => _member;
SetterTypeInformation(SetterElement element) : super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_setter, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
return mask;
}
}
class MethodTypeInformation extends MemberTypeInformation {
MethodElement get _method => _member;
MethodTypeInformation(MethodElement element) : super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_method, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
FunctionType type = _method.type;
return _narrowType(inferrer.closedWorld, mask, type.returnType);
}
bool hasStableType(InferrerEngine inferrer) => false;
}
class FactoryConstructorTypeInformation extends MemberTypeInformation {
ConstructorElement get _constructor => _member;
FactoryConstructorTypeInformation(ConstructorElement element)
: super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
CommonMasks commonMasks = inferrer.commonMasks;
if (_constructor.isIntFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.intType.nullable();
} else if (_constructor.isBoolFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.boolType.nullable();
} else if (_constructor.isStringFromEnvironmentConstructor) {
giveUp(inferrer);
return commonMasks.stringType.nullable();
}
return _handleFunctionCase(_constructor, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
FunctionType type = _constructor.type;
return _narrowType(inferrer.closedWorld, mask, type.returnType);
}
bool hasStableType(InferrerEngine inferrer) {
return super.hasStableType(inferrer);
}
}
class GenerativeConstructorTypeInformation extends MemberTypeInformation {
ConstructorElement get _constructor => _member;
GenerativeConstructorTypeInformation(ConstructorElement element)
: super._internal(element);
TypeMask handleSpecialCases(InferrerEngine inferrer) {
return _handleFunctionCase(_constructor, inferrer);
}
TypeMask _potentiallyNarrowType(TypeMask mask, InferrerEngine inferrer) {
return mask;
}
bool hasStableType(InferrerEngine inferrer) {
return super.hasStableType(inferrer);
}
}
/**
* A node representing parameters:
*

View file

@ -370,7 +370,23 @@ class TypeSystem {
MemberTypeInformation getInferredTypeOfMember(MemberElement member) {
member = member.implementation;
return memberTypeInformations.putIfAbsent(member, () {
MemberTypeInformation typeInformation = new MemberTypeInformation(member);
MemberTypeInformation typeInformation;
if (member.isField) {
typeInformation = new FieldTypeInformation(member);
} else if (member.isGetter) {
typeInformation = new GetterTypeInformation(member);
} else if (member.isSetter) {
typeInformation = new SetterTypeInformation(member);
} else if (member.isFunction) {
typeInformation = new MethodTypeInformation(member);
} else {
ConstructorElement constructor = member;
if (constructor.isFactoryConstructor) {
typeInformation = new FactoryConstructorTypeInformation(member);
} else {
typeInformation = new GenerativeConstructorTypeInformation(member);
}
}
_orderedTypeInformations.add(typeInformation);
return typeInformation;
});