Add TypeUse.

BUG=
R=sigurdm@google.com

Review URL: https://codereview.chromium.org/1422623014.
This commit is contained in:
Johnni Winther 2015-11-04 14:29:17 +01:00
parent 08efdd3f30
commit 3837194311
18 changed files with 272 additions and 261 deletions

View file

@ -24,7 +24,8 @@ import '../resolution/tree_elements.dart' show
TreeElements;
import '../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
import '../universe/world_impact.dart' show
WorldImpact,
WorldImpactBuilder;
@ -189,8 +190,8 @@ class CodegenRegistry extends Registry {
compiler.dumpInfoTask.elementUsesSelector(currentElement, dynamicUse);
}
void registerIsCheck(DartType type) {
worldImpact.registerIsCheck(type);
void registerTypeUse(TypeUse typeUse) {
worldImpact.registerTypeUse(typeUse);
}
void registerCompileTimeConstant(ConstantValue constant) {
@ -223,7 +224,7 @@ class CodegenRegistry extends Registry {
}
void registerInstantiation(InterfaceType type) {
worldImpact.registerInstantiatedType(type);
registerTypeUse(new TypeUse.instantiation(type));
}
void registerAsyncMarker(FunctionElement element) {

View file

@ -364,12 +364,11 @@ class DartImpactTransformer extends ImpactTransformer {
backend.usedTypeLiterals.add(typeLiteral.element);
}
}
for (InterfaceType instantiatedType in worldImpact.instantiatedTypes) {
// TODO(johnniwinther): Remove this when dependency tracking is done on
// the world impact itself.
transformed.registerInstantiatedType(instantiatedType);
backend.registerPlatformMembers(instantiatedType,
registerUse: transformed.registerDynamicUse);
for (TypeUse typeUse in worldImpact.typeUses) {
if (typeUse.kind == TypeUseKind.INSTANTIATION) {
backend.registerPlatformMembers(typeUse.type,
registerUse: transformed.registerDynamicUse);
}
}
return transformed;
}

View file

@ -48,7 +48,9 @@ import '../tree/tree.dart';
import '../universe/selector.dart' show
Selector;
import '../universe/use.dart' show
DynamicUse;
DynamicUse,
TypeUse,
TypeUseKind;
import '../universe/world_impact.dart' show
WorldImpact,
TransformedWorldImpact;

View file

@ -48,7 +48,9 @@ import 'tree/tree.dart' show
NewExpression,
Node;
import 'universe/use.dart' show
StaticUse;
StaticUse,
TypeUse,
TypeUseKind;
import 'universe/world_impact.dart' show
WorldImpact;
import 'util/setlet.dart' show
@ -318,18 +320,27 @@ class DeferredLoadTask extends CompilerTask {
elements.add(staticUse.element);
});
elements.addAll(worldImpact.closures);
for (DartType type in worldImpact.typeLiterals) {
if (type.isTypedef || type.isInterfaceType) {
elements.add(type.element);
for (TypeUse typeUse in worldImpact.typeUses) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.TYPE_LITERAL:
if (type.isTypedef || type.isInterfaceType) {
elements.add(type.element);
}
break;
case TypeUseKind.INSTANTIATION:
case TypeUseKind.IS_CHECK:
case TypeUseKind.AS_CAST:
case TypeUseKind.CATCH_TYPE:
collectTypeDependencies(type);
break;
case TypeUseKind.CHECKED_MODE_CHECK:
if (compiler.enableTypeAssertions) {
collectTypeDependencies(type);
}
break;
}
}
worldImpact.instantiatedTypes.forEach(collectTypeDependencies);
worldImpact.isChecks.forEach(collectTypeDependencies);
worldImpact.asCasts.forEach(collectTypeDependencies);
worldImpact.onCatchTypes.forEach(collectTypeDependencies);
if (compiler.enableTypeAssertions) {
worldImpact.checkedModeChecks.forEach(collectTypeDependencies);
}
TreeElements treeElements = analyzableElement.resolvedAst.elements;
assert(treeElements != null);

View file

@ -54,7 +54,9 @@ import 'universe/universe.dart';
import 'universe/use.dart' show
DynamicUse,
StaticUse,
StaticUseKind;
StaticUseKind,
TypeUse,
TypeUseKind;
import 'universe/world_impact.dart' show
WorldImpact;
import 'util/util.dart' show
@ -167,13 +169,7 @@ abstract class Enqueuer {
// TODO(johnniwinther): Optimize the application of the world impact.
worldImpact.dynamicUses.forEach(registerDynamicUse);
worldImpact.staticUses.forEach(registerStaticUse);
worldImpact.instantiatedTypes.forEach(registerInstantiatedType);
worldImpact.isChecks.forEach(registerIsCheck);
worldImpact.asCasts.forEach(registerIsCheck);
if (compiler.enableTypeAssertions) {
worldImpact.checkedModeChecks.forEach(registerIsCheck);
}
worldImpact.onCatchTypes.forEach(registerIsCheck);
worldImpact.typeUses.forEach(registerTypeUse);
worldImpact.closures.forEach(registerClosure);
}
@ -640,7 +636,29 @@ abstract class Enqueuer {
}
}
void registerIsCheck(DartType type) {
void registerTypeUse(TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
registerInstantiatedType(type);
break;
case TypeUseKind.INSTANTIATION:
case TypeUseKind.IS_CHECK:
case TypeUseKind.AS_CAST:
case TypeUseKind.CATCH_TYPE:
_registerIsCheck(type);
break;
case TypeUseKind.CHECKED_MODE_CHECK:
if (compiler.enableTypeAssertions) {
_registerIsCheck(type);
}
break;
case TypeUseKind.TYPE_LITERAL:
break;
}
}
void _registerIsCheck(DartType type) {
type = universe.registerIsCheck(type, compiler);
// Even in checked mode, type annotations for return type and argument
// types do not imply type checks, so there should never be a check

View file

@ -2770,29 +2770,52 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
}
for (InterfaceType type in worldImpact.instantiatedTypes) {
registerRequiredType(type);
}
for (DartType type in worldImpact.isChecks) {
onIsCheck(type, transformed);
}
if (worldImpact.asCasts.isNotEmpty) {
for (DartType type in worldImpact.asCasts) {
onIsCheck(type, transformed);
bool hasAsCast = false;
bool hasTypeLiteral = false;
for (TypeUse typeUse in worldImpact.typeUses) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
registerRequiredType(type);
break;
case TypeUseKind.IS_CHECK:
onIsCheck(type, transformed);
break;
case TypeUseKind.AS_CAST:
onIsCheck(type, transformed);
hasAsCast = true;
break;
case TypeUseKind.CHECKED_MODE_CHECK:
if (backend.compiler.enableTypeAssertions) {
onIsCheck(type, transformed);
}
break;
case TypeUseKind.CATCH_TYPE:
onIsCheck(type, transformed);
break;
case TypeUseKind.TYPE_LITERAL:
backend.customElementsAnalysis.registerTypeLiteral(type);
if (type.isTypedef) {
backend.compiler.world.allTypedefs.add(type.element);
}
if (type.isTypeVariable) {
ClassElement cls = type.element.enclosingClass;
backend.rti.registerClassUsingTypeVariableExpression(cls);
registerBackendImpact(transformed, impacts.typeVariableExpression);
}
hasTypeLiteral = true;
break;
}
}
if (hasAsCast) {
registerBackendImpact(transformed, impacts.asCheck);
}
if (backend.compiler.enableTypeAssertions) {
for (DartType type in worldImpact.checkedModeChecks) {
onIsCheck(type, transformed);
}
}
for (DartType type in worldImpact.onCatchTypes) {
onIsCheck(type, transformed);
if (hasTypeLiteral) {
transformed.registerTypeUse(new TypeUse.instantiation(
backend.compiler.coreTypes.typeType));
registerBackendImpact(transformed, impacts.typeLiteral);
}
for (MapLiteralUse mapLiteralUse in worldImpact.mapLiterals) {
@ -2801,7 +2824,8 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
if (mapLiteralUse.isConstant) {
registerBackendImpact(transformed, impacts.constantMapLiteral);
} else {
transformed.registerInstantiatedType(mapLiteralUse.type);
transformed.registerTypeUse(
new TypeUse.instantiation(mapLiteralUse.type));
}
registerRequiredType(mapLiteralUse.type);
}
@ -2809,26 +2833,11 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
for (ListLiteralUse listLiteralUse in worldImpact.listLiterals) {
// TODO(johnniwinther): Use the [isConstant] and [isEmpty] property when
// factory constructors are registered directly.
transformed.registerInstantiatedType(listLiteralUse.type);
transformed.registerTypeUse(
new TypeUse.instantiation(listLiteralUse.type));
registerRequiredType(listLiteralUse.type);
}
if (worldImpact.typeLiterals.isNotEmpty) {
transformed.registerInstantiatedType(backend.compiler.coreTypes.typeType);
registerBackendImpact(transformed, impacts.typeLiteral);
for (DartType typeLiteral in worldImpact.typeLiterals) {
backend.customElementsAnalysis.registerTypeLiteral(typeLiteral);
if (typeLiteral.isTypedef) {
backend.compiler.world.allTypedefs.add(typeLiteral.element);
}
if (typeLiteral.isTypeVariable) {
ClassElement cls = typeLiteral.element.enclosingClass;
backend.rti.registerClassUsingTypeVariableExpression(cls);
registerBackendImpact(transformed, impacts.typeVariableExpression);
}
}
}
if (worldImpact.constSymbolNames.isNotEmpty) {
registerBackendImpact(transformed, impacts.constSymbol);
for (String constSymbolName in worldImpact.constSymbolNames) {
@ -2861,12 +2870,14 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
for (InterfaceType instantiatedType in backendImpact.instantiatedTypes) {
backend.registerBackendUse(instantiatedType.element);
worldImpact.registerInstantiatedType(instantiatedType);
worldImpact.registerTypeUse(
new TypeUse.instantiation(instantiatedType));
}
for (ClassElement cls in backendImpact.instantiatedClasses) {
cls.ensureResolved(backend.resolution);
backend.registerBackendUse(cls);
worldImpact.registerInstantiatedType(cls.rawType);
worldImpact.registerTypeUse(
new TypeUse.instantiation(cls.rawType));
}
for (BackendImpact otherImpact in backendImpact.otherImpacts) {
registerBackendImpact(worldImpact, otherImpact);
@ -2965,12 +2976,17 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
EagerRegistry registry = impact.registry;
Enqueuer world = registry.world;
for (InterfaceType type in impact.instantiatedTypes) {
backend.lookupMapAnalysis.registerInstantiatedType(type, registry);
}
for (DartType type in impact.isChecks) {
onIsCheckForCodegen(type, transformed);
for (TypeUse typeUse in impact.typeUses) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
backend.lookupMapAnalysis.registerInstantiatedType(type, registry);
break;
case TypeUseKind.IS_CHECK:
onIsCheckForCodegen(type, transformed);
break;
default:
}
}
for (ConstantValue constant in impact.compileTimeConstants) {

View file

@ -29,7 +29,8 @@ import '../../universe/selector.dart' show
Selector;
import '../../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
import '../../util/maplet.dart';
class CodegenBailout {
@ -382,7 +383,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
List<js.Expression> typeArguments = visitExpressionList(node.typeArguments);
DartType type = node.type;
if (type is InterfaceType) {
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
//glue.registerIsCheck(type, registry);
ClassElement clazz = type.element;
@ -428,8 +429,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
function,
<js.Expression>[value, isT, typeArgumentArray, asT]);
} else if (type is TypeVariableType || type is FunctionType) {
registry.registerIsCheck(type);
//glue.registerIsCheck(type, registry);
registry.registerTypeUse(new TypeUse.isCheck(type));
Element function = node.isTypeTest
? glue.getCheckSubtypeOfRuntimeType()
@ -450,7 +450,7 @@ class CodeGenerator extends tree_ir.StatementVisitor
js.Expression object = visitExpression(node.object);
DartType dartType = node.dartType;
assert(dartType.isInterfaceType);
registry.registerIsCheck(dartType);
registry.registerTypeUse(new TypeUse.isCheck(dartType));
//glue.registerIsCheck(dartType, registry);
js.Expression property = glue.getTypeTestTag(dartType);
return js.js(r'#.#', [object, property]);

View file

@ -87,7 +87,9 @@ import '../universe/selector.dart' show
import '../universe/universe.dart';
import '../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse,
TypeUseKind;
import '../universe/world_impact.dart' show
TransformedWorldImpact,
WorldImpact;

View file

@ -39,7 +39,8 @@ import '../universe/selector.dart' show
Selector;
import '../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
import 'access_semantics.dart';
import 'class_members.dart' show MembersCreator;
@ -401,7 +402,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
TypeResult visitTypeAnnotation(TypeAnnotation node) {
DartType type = resolveTypeAnnotation(node);
if (inCheckContext) {
registry.registerCheckedModeCheck(type);
registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
}
return new TypeResult(type);
}
@ -487,7 +488,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
});
if (inCheckContext) {
functionParameters.forEachParameter((ParameterElement element) {
registry.registerCheckedModeCheck(element.type);
registry.registerTypeUse(new TypeUse.checkedModeCheck(element.type));
});
}
}
@ -1162,7 +1163,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
type = resolveTypeAnnotation(typeNode);
sendStructure = new IsStructure(type);
}
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
registry.registerSendStructure(node, sendStructure);
return const NoneResult();
}
@ -1174,7 +1175,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
Node typeNode = node.arguments.head;
DartType type = resolveTypeAnnotation(typeNode);
registry.registerAsCast(type);
registry.registerTypeUse(new TypeUse.asCast(type));
registry.registerSendStructure(node, new AsStructure(type));
return const NoneResult();
}
@ -3558,28 +3559,32 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
ConstantResult visitLiteralInt(LiteralInt node) {
registry.registerInstantiatedType(coreTypes.intType);
// TODO(johnniwinther): Make this a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.intType));
ConstantExpression constant = new IntConstantExpression(node.value);
registry.setConstant(node, constant);
return new ConstantResult(node, constant);
}
ConstantResult visitLiteralDouble(LiteralDouble node) {
registry.registerInstantiatedType(coreTypes.doubleType);
// TODO(johnniwinther): Make this a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.doubleType));
ConstantExpression constant = new DoubleConstantExpression(node.value);
registry.setConstant(node, constant);
return new ConstantResult(node, constant);
}
ConstantResult visitLiteralBool(LiteralBool node) {
registry.registerInstantiatedType(coreTypes.boolType);
// TODO(johnniwinther): Make this a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.boolType));
ConstantExpression constant = new BoolConstantExpression(node.value);
registry.setConstant(node, constant);
return new ConstantResult(node, constant);
}
ResolutionResult visitLiteralString(LiteralString node) {
registry.registerInstantiatedType(coreTypes.stringType);
// TODO(johnniwinther): Make this a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.stringType));
if (node.dartString != null) {
// [dartString] might be null on parser errors.
ConstantExpression constant =
@ -3591,13 +3596,14 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
ConstantResult visitLiteralNull(LiteralNull node) {
registry.registerInstantiatedType(coreTypes.nullType);
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.nullType));
ConstantExpression constant = new NullConstantExpression();
registry.setConstant(node, constant);
return new ConstantResult(node, constant);
}
ConstantResult visitLiteralSymbol(LiteralSymbol node) {
// TODO(johnniwinther): Make this a feature instead.
String name = node.slowNameString;
registry.registerConstSymbol(name);
if (!validateSymbol(node, name, reportError: false)) {
@ -3613,7 +3619,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
ResolutionResult visitStringJuxtaposition(StringJuxtaposition node) {
registry.registerInstantiatedType(coreTypes.stringType);
// TODO(johnniwinther): Make this a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.stringType));
ResolutionResult first = visit(node.first);
ResolutionResult second = visit(node.second);
if (first.isConstant && second.isConstant) {
@ -3747,10 +3754,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
registry.registerStaticUse(
new StaticUse.constructorRedirect(redirectionTarget));
// TODO(johnniwinther): Register the effective target type instead.
registry.registerInstantiatedType(
// TODO(johnniwinther): Register the effective target type as part of the
// static use instead.
registry.registerTypeUse(new TypeUse.instantiation(
redirectionTarget.enclosingClass.thisType
.subst(type.typeArguments, targetClass.typeVariables));
.subst(type.typeArguments, targetClass.typeVariables)));
if (isSymbolConstructor) {
registry.registerSymbolConstructor();
}
@ -3911,7 +3919,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
// TODO(johniwinther): Avoid registration of `type` in face of redirecting
// factory constructors.
registry.registerInstantiatedType(type);
registry.registerTypeUse(new TypeUse.instantiation(type));
if (constructor.isGenerativeConstructor && cls.isAbstract) {
isValidAsConstant = false;
}
@ -4064,7 +4072,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
this, node, malformedIsError: malformedIsError,
deferredIsMalformed: deferredIsMalformed);
if (inCheckContext) {
registry.registerCheckedModeCheck(type);
registry.registerTypeUse(new TypeUse.checkedModeCheck(type));
}
return type;
}
@ -4156,7 +4164,9 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
ResolutionResult visitStringInterpolation(StringInterpolation node) {
registry.registerInstantiatedType(coreTypes.stringType);
// TODO(johnniwinther): This should be a consequence of the registration
// of [registerStringInterpolation].
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.stringType));
registry.registerStringInterpolation();
registerImplicitInvocation(Selectors.toString_);
@ -4742,7 +4752,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
registry.getDefinition(exceptionVariable);
exceptionElement.variables.type = exceptionType;
}
registry.registerOnCatchType(exceptionType);
registry.registerTypeUse(new TypeUse.catchType(exceptionType));
}
if (stackTraceDefinition != null) {
Node stackTraceVariable = stackTraceDefinition.definitions.nodes.head;

View file

@ -31,7 +31,8 @@ import '../universe/selector.dart' show
Selector;
import '../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
import '../universe/world_impact.dart' show
WorldImpactBuilder;
import '../world.dart' show World;
@ -315,24 +316,9 @@ class ResolutionRegistry extends Registry {
worldImpact.registerFeature(Feature.THROW_NO_SUCH_METHOD);
}
/// Register a checked mode check against [type].
void registerCheckedModeCheck(DartType type) {
worldImpact.registerCheckedModeCheckedType(type);
}
/// Register an on-catch clause of [type].
void registerOnCatchType(DartType type) {
worldImpact.registerOnCatchType(type);
}
/// Register an is-test or is-not-test of [type].
void registerIsCheck(DartType type) {
worldImpact.registerIsCheck(type);
}
/// Register an as-cast of [type].
void registerAsCast(DartType type) {
worldImpact.registerAsCast(type);
/// Register the use of a type.
void registerTypeUse(TypeUse typeUse) {
worldImpact.registerTypeUse(typeUse);
}
void registerClosure(LocalFunctionElement element) {
@ -349,7 +335,7 @@ class ResolutionRegistry extends Registry {
void registerTypeLiteral(Send node, DartType type) {
mapping.setType(node, type);
worldImpact.registerTypeLiteral(type);
worldImpact.registerTypeUse(new TypeUse.typeLiteral(type));
}
void registerLiteralList(Node node,
@ -391,10 +377,6 @@ class ResolutionRegistry extends Registry {
worldImpact.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
}
void registerInstantiatedType(InterfaceType type) {
worldImpact.registerInstantiatedType(type);
}
void registerAbstractClassInstantiation() {
worldImpact.registerFeature(Feature.ABSTRACT_CLASS_INSTANTIATION);
}
@ -433,7 +415,7 @@ class ResolutionRegistry extends Registry {
}
void registerInstantiation(InterfaceType type) {
registerInstantiatedType(type);
worldImpact.registerTypeUse(new TypeUse.instantiation(type));
}
void registerAssert(bool hasMessage) {
@ -493,7 +475,7 @@ class ForeignResolutionResolver implements ForeignResolver {
@override
void registerInstantiatedType(InterfaceType type) {
registry.registerInstantiatedType(type);
registry.registerInstantiation(type);
}
@override

View file

@ -49,7 +49,8 @@ import '../tree/tree.dart';
import '../universe/call_structure.dart' show
CallStructure;
import '../universe/use.dart' show
StaticUse;
StaticUse,
TypeUse;
import '../universe/world_impact.dart' show
WorldImpact;
import '../util/util.dart' show
@ -377,7 +378,8 @@ class ResolverTask extends CompilerTask {
reporter.reportErrorMessage(
element, MessageKind.FINAL_WITHOUT_INITIALIZER);
} else {
registry.registerInstantiatedType(coreTypes.nullType);
// TODO(johnniwinther): Register a feature instead.
registry.registerTypeUse(new TypeUse.instantiation(coreTypes.nullType));
}
if (Elements.isStaticOrTopLevelField(element)) {

View file

@ -18,6 +18,8 @@ import '../elements/modelx.dart' show
InitializingFormalElementX,
LocalParameterElementX;
import '../tree/tree.dart';
import '../universe/use.dart' show
TypeUse;
import '../util/util.dart' show
Link,
LinkBuilder;
@ -341,7 +343,7 @@ class SignatureResolver extends MappingVisitor<FormalElementX> {
// Because there is no type annotation for the return type of
// this element, we explicitly add one.
if (compiler.enableTypeAssertions) {
registry.registerIsCheck(returnType);
registry.registerTypeUse(new TypeUse.checkedModeCheck(returnType));
}
} else {
AsyncMarker asyncMarker = AsyncMarker.SYNC;

View file

@ -11,6 +11,8 @@ import '../elements/modelx.dart' show
LocalVariableElementX,
VariableList;
import '../tree/tree.dart';
import '../universe/use.dart' show
TypeUse;
import '../util/util.dart' show
Link;
@ -54,7 +56,9 @@ class VariableDefinitionsVisitor extends CommonResolverVisitor<Identifier> {
Identifier visitIdentifier(Identifier node) {
// The variable is initialized to null.
registry.registerInstantiatedType(compiler.coreTypes.nullType);
// TODO(johnniwinther): Register a feature instead.
registry.registerTypeUse(
new TypeUse.instantiation(compiler.coreTypes.nullType));
if (definitions.modifiers.isConst) {
reporter.reportErrorMessage(
node, MessageKind.CONST_WITHOUT_INITIALIZER);

View file

@ -2590,7 +2590,7 @@ class SsaBuilder extends ast.Visitor
assert(type != null);
type = localsHandler.substInContext(type);
HInstruction other = buildTypeConversion(original, type, kind);
registry?.registerIsCheck(type);
registry?.registerTypeUse(new TypeUse.isCheck(type));
return other;
}

View file

@ -2502,7 +2502,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void checkTypeViaProperty(HInstruction input, DartType type,
SourceInformation sourceInformation,
{bool negative: false}) {
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
use(input);
@ -2523,7 +2523,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
HInstruction input, DartType type,
SourceInformation sourceInformation,
{bool negative: false}) {
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
use(input);
@ -2615,7 +2615,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
DartType type = node.typeExpression;
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
HInstruction input = node.expression;
// If this is changed to single == there are several places below that must
@ -2787,9 +2787,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
if (type.isFunctionType) {
// TODO(5022): We currently generate $isFunction checks for
// function types.
registry.registerIsCheck(compiler.coreTypes.functionType);
registry.registerTypeUse(
new TypeUse.isCheck(compiler.coreTypes.functionType));
}
registry.registerIsCheck(type);
registry.registerTypeUse(new TypeUse.isCheck(type));
CheckedModeHelper helper;
if (node.isBooleanConversionCheck) {

View file

@ -62,7 +62,8 @@ import '../universe/side_effects.dart' show
SideEffects;
import '../universe/use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
import '../util/util.dart';
import '../world.dart' show
ClassWorld,

View file

@ -10,6 +10,7 @@ library dart2js.universe.use;
import '../closure.dart' show
BoxFieldElement;
import '../common.dart';
import '../dart_types.dart';
import '../elements/elements.dart';
import '../world.dart' show
ClassWorld;
@ -247,3 +248,62 @@ class StaticUse {
String toString() => 'StaticUse($element,$kind)';
}
enum TypeUseKind {
IS_CHECK,
AS_CAST,
CHECKED_MODE_CHECK,
CATCH_TYPE,
TYPE_LITERAL,
INSTANTIATION,
}
/// Use of a [DartType].
class TypeUse {
final DartType type;
final TypeUseKind kind;
final int hashCode;
TypeUse._(DartType type, TypeUseKind kind)
: this.type = type,
this.kind = kind,
this.hashCode = Hashing.objectHash(type, Hashing.objectHash(kind));
/// [type] used in an is check, like `e is T` or `e is! T`.
factory TypeUse.isCheck(DartType type) {
return new TypeUse._(type, TypeUseKind.IS_CHECK);
}
/// [type] used in an as cast, like `e as T`.
factory TypeUse.asCast(DartType type) {
return new TypeUse._(type, TypeUseKind.AS_CAST);
}
/// [type] used as a type annotation, like `T foo;`.
factory TypeUse.checkedModeCheck(DartType type) {
return new TypeUse._(type, TypeUseKind.CHECKED_MODE_CHECK);
}
/// [type] used in a on type catch clause, like `try {} on T catch (e) {}`.
factory TypeUse.catchType(DartType type) {
return new TypeUse._(type, TypeUseKind.CATCH_TYPE);
}
/// [type] used as a type literal, like `foo() => T;`.
factory TypeUse.typeLiteral(DartType type) {
return new TypeUse._(type, TypeUseKind.TYPE_LITERAL);
}
/// [type] used in an instantiation, like `new T();`.
factory TypeUse.instantiation(InterfaceType type) {
return new TypeUse._(type, TypeUseKind.INSTANTIATION);
}
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is! TypeUse) return false;
return type == other.type &&
kind == other.kind;
}
String toString() => 'TypeUse($type,$kind)';
}

View file

@ -16,7 +16,8 @@ import '../util/util.dart' show
import 'use.dart' show
DynamicUse,
StaticUse;
StaticUse,
TypeUse;
class WorldImpact {
const WorldImpact();
@ -28,22 +29,13 @@ class WorldImpact {
// TODO(johnniwinther): Replace this by called constructors with type
// arguments.
Iterable<InterfaceType> get instantiatedTypes => const <InterfaceType>[];
// TODO(johnniwinther): Collect all checked types for checked mode separately
// to support serialization.
// TODO(johnniwinther): Collect checked types for checked mode separately to
// support serialization.
Iterable<DartType> get isChecks => const <DartType>[];
Iterable<DartType> get checkedModeChecks => const <DartType>[];
Iterable<DartType> get asCasts => const <DartType>[];
Iterable<DartType> get onCatchTypes => const <DartType>[];
Iterable<TypeUse> get typeUses => const <TypeUse>[];
Iterable<LocalFunctionElement> get closures => const <LocalFunctionElement>[];
Iterable<DartType> get typeLiterals => const <DartType>[];
String toString() => dump(this);
static String dump(WorldImpact worldImpact) {
@ -62,13 +54,8 @@ class WorldImpact {
add('dynamic uses', worldImpact.dynamicUses);
add('static uses', worldImpact.staticUses);
add('instantiated types', worldImpact.instantiatedTypes);
add('is-checks', worldImpact.isChecks);
add('checked-mode checks', worldImpact.checkedModeChecks);
add('as-casts', worldImpact.asCasts);
add('on-catch-types', worldImpact.onCatchTypes);
add('type uses', worldImpact.typeUses);
add('closures', worldImpact.closures);
add('type literals', worldImpact.typeLiterals);
}
}
@ -76,14 +63,9 @@ class WorldImpactBuilder {
// TODO(johnniwinther): Do we benefit from lazy initialization of the
// [Setlet]s?
Setlet<DynamicUse> _dynamicUses;
Setlet<InterfaceType> _instantiatedTypes;
Setlet<StaticUse> _staticUses;
Setlet<DartType> _isChecks;
Setlet<DartType> _asCasts;
Setlet<DartType> _checkedModeChecks;
Setlet<DartType> _onCatchTypes;
Setlet<TypeUse> _typeUses;
Setlet<LocalFunctionElement> _closures;
Setlet<DartType> _typeLiterals;
void registerDynamicUse(DynamicUse dynamicUse) {
assert(dynamicUse != null);
@ -98,30 +80,17 @@ class WorldImpactBuilder {
? _dynamicUses : const <DynamicUse>[];
}
void registerInstantiatedType(InterfaceType type) {
assert(type != null);
if (_instantiatedTypes == null) {
_instantiatedTypes = new Setlet<InterfaceType>();
void registerTypeUse(TypeUse typeUse) {
assert(typeUse != null);
if (_typeUses == null) {
_typeUses = new Setlet<TypeUse>();
}
_instantiatedTypes.add(type);
_typeUses.add(typeUse);
}
Iterable<InterfaceType> get instantiatedTypes {
return _instantiatedTypes != null
? _instantiatedTypes : const <InterfaceType>[];
}
void registerTypeLiteral(DartType type) {
assert(type != null);
if (_typeLiterals == null) {
_typeLiterals = new Setlet<DartType>();
}
_typeLiterals.add(type);
}
Iterable<DartType> get typeLiterals {
return _typeLiterals != null
? _typeLiterals : const <DartType>[];
Iterable<TypeUse> get typeUses {
return _typeUses != null
? _typeUses : const <TypeUse>[];
}
void registerStaticUse(StaticUse staticUse) {
@ -136,56 +105,6 @@ class WorldImpactBuilder {
return _staticUses != null ? _staticUses : const <StaticUse>[];
}
void registerIsCheck(DartType type) {
assert(type != null);
if (_isChecks == null) {
_isChecks = new Setlet<DartType>();
}
_isChecks.add(type);
}
Iterable<DartType> get isChecks {
return _isChecks != null
? _isChecks : const <DartType>[];
}
void registerAsCast(DartType type) {
if (_asCasts == null) {
_asCasts = new Setlet<DartType>();
}
_asCasts.add(type);
}
Iterable<DartType> get asCasts {
return _asCasts != null
? _asCasts : const <DartType>[];
}
void registerCheckedModeCheckedType(DartType type) {
if (_checkedModeChecks == null) {
_checkedModeChecks = new Setlet<DartType>();
}
_checkedModeChecks.add(type);
}
Iterable<DartType> get checkedModeChecks {
return _checkedModeChecks != null
? _checkedModeChecks : const <DartType>[];
}
void registerOnCatchType(DartType type) {
assert(type != null);
if (_onCatchTypes == null) {
_onCatchTypes = new Setlet<DartType>();
}
_onCatchTypes.add(type);
}
Iterable<DartType> get onCatchTypes {
return _onCatchTypes != null
? _onCatchTypes : const <DartType>[];
}
void registerClosure(LocalFunctionElement element) {
if (_closures == null) {
_closures = new Setlet<LocalFunctionElement>();
@ -205,31 +124,17 @@ class TransformedWorldImpact implements WorldImpact {
final WorldImpact worldImpact;
Setlet<StaticUse> _staticUses;
Setlet<InterfaceType> _instantiatedTypes;
Setlet<TypeUse> _typeUses;
Setlet<DynamicUse> _dynamicUses;
TransformedWorldImpact(this.worldImpact);
@override
Iterable<DartType> get asCasts => worldImpact.asCasts;
@override
Iterable<DartType> get checkedModeChecks => worldImpact.checkedModeChecks;
@override
Iterable<DynamicUse> get dynamicUses {
return _dynamicUses != null
? _dynamicUses : worldImpact.dynamicUses;
}
@override
Iterable<DartType> get isChecks => worldImpact.isChecks;
@override
Iterable<DartType> get onCatchTypes => worldImpact.onCatchTypes;
_unsupported(String message) => throw new UnsupportedError(message);
void registerDynamicUse(DynamicUse dynamicUse) {
if (_dynamicUses == null) {
_dynamicUses = new Setlet<DynamicUse>();
@ -238,23 +143,18 @@ class TransformedWorldImpact implements WorldImpact {
_dynamicUses.add(dynamicUse);
}
void registerInstantiatedType(InterfaceType type) {
if (_instantiatedTypes == null) {
_instantiatedTypes = new Setlet<InterfaceType>();
_instantiatedTypes.addAll(worldImpact.instantiatedTypes);
void registerTypeUse(TypeUse typeUse) {
if (_typeUses == null) {
_typeUses = new Setlet<TypeUse>();
_typeUses.addAll(worldImpact.typeUses);
}
_instantiatedTypes.add(type);
_typeUses.add(typeUse);
}
@override
Iterable<InterfaceType> get instantiatedTypes {
return _instantiatedTypes != null
? _instantiatedTypes : worldImpact.instantiatedTypes;
}
@override
Iterable<DartType> get typeLiterals {
return worldImpact.typeLiterals;
Iterable<TypeUse> get typeUses {
return _typeUses != null
? _typeUses : worldImpact.typeUses;
}
void registerStaticUse(StaticUse staticUse) {