Index: pkg/compiler/lib/src/js_backend/backend.dart |
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart |
index fd9efa19d9adfc5a6212a839148c1834d63927c5..91b8b5b8521d73ce593925762d592c67c7fd1c2f 100644 |
--- a/pkg/compiler/lib/src/js_backend/backend.dart |
+++ b/pkg/compiler/lib/src/js_backend/backend.dart |
@@ -14,7 +14,7 @@ import '../common/backend_api.dart' |
show Backend, ImpactTransformer, ForeignResolver, NativeRegistry; |
import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; |
import '../common/names.dart' show Identifiers, Selectors, Uris; |
-import '../common/registry.dart' show EagerRegistry, Registry; |
+import '../common/registry.dart' show Registry; |
import '../common/resolution.dart' show Frontend, Resolution, ResolutionImpact; |
import '../common/tasks.dart' show CompilerTask; |
import '../compiler.dart' show Compiler; |
@@ -54,7 +54,9 @@ import '../universe/world_impact.dart' |
ImpactUseCase, |
TransformedWorldImpact, |
WorldImpact, |
- WorldImpactVisitor; |
+ WorldImpactBuilder, |
+ WorldImpactVisitor, |
+ StagedWorldImpactBuilder; |
import '../util/util.dart'; |
import '../world.dart' show ClassWorld; |
import 'backend_helpers.dart'; |
@@ -579,6 +581,12 @@ class JavaScriptBackend extends Backend { |
JavaScriptBackendSerialization serialization; |
+ StagedWorldImpactBuilder constantImpactsForResolution = |
+ new StagedWorldImpactBuilder(); |
+ |
+ StagedWorldImpactBuilder constantImpactsForCodegen = |
+ new StagedWorldImpactBuilder(); |
+ |
final NativeData nativeData = new NativeData(); |
final BackendHelpers helpers; |
@@ -1069,17 +1077,20 @@ class JavaScriptBackend extends Backend { |
} |
} |
- void registerCompileTimeConstant(ConstantValue constant, Registry registry) { |
- registerCompileTimeConstantInternal(constant, registry); |
+ void computeImpactForCompileTimeConstant(ConstantValue constant, |
+ WorldImpactBuilder impactBuilder, bool isForResolution) { |
+ computeImpactForCompileTimeConstantInternal( |
+ constant, impactBuilder, isForResolution); |
- if (!registry.isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
+ if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { |
// Note: internally, this registration will temporarily remove the |
// constant dependencies and add them later on-demand. |
lookupMapAnalysis.registerLookupMapReference(constant); |
} |
for (ConstantValue dependency in constant.getDependencies()) { |
- registerCompileTimeConstant(dependency, registry); |
+ computeImpactForCompileTimeConstant( |
+ dependency, impactBuilder, isForResolution); |
} |
} |
@@ -1087,32 +1098,43 @@ class JavaScriptBackend extends Backend { |
constants.addCompileTimeConstantForEmission(constant); |
} |
- void registerCompileTimeConstantInternal( |
- ConstantValue constant, Registry registry) { |
+ void computeImpactForCompileTimeConstantInternal(ConstantValue constant, |
+ WorldImpactBuilder impactBuilder, bool isForResolution) { |
DartType type = constant.getType(compiler.coreTypes); |
- registerInstantiatedConstantType(type, registry); |
+ computeImpactForInstantiatedConstantType(type, impactBuilder); |
if (constant.isFunction) { |
FunctionConstantValue function = constant; |
- registry.registerStaticUse(new StaticUse.staticTearOff(function.element)); |
+ impactBuilder |
+ .registerStaticUse(new StaticUse.staticTearOff(function.element)); |
} else if (constant.isInterceptor) { |
// An interceptor constant references the class's prototype chain. |
InterceptorConstantValue interceptor = constant; |
- registerInstantiatedConstantType(interceptor.dispatchedType, registry); |
+ computeImpactForInstantiatedConstantType( |
+ interceptor.dispatchedType, impactBuilder); |
} else if (constant.isType) { |
- enqueueInResolution(helpers.createRuntimeType, registry); |
- registry.registerInstantiation(typeImplementation.rawType); |
+ if (isForResolution) { |
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
+ // TODO(johnniwinther): Find the right [CallStructure]. |
+ helpers.createRuntimeType, |
+ null)); |
+ registerBackendUse(helpers.createRuntimeType); |
+ } |
+ impactBuilder.registerTypeUse( |
+ new TypeUse.instantiation(typeImplementation.rawType)); |
} |
lookupMapAnalysis.registerConstantKey(constant); |
} |
- void registerInstantiatedConstantType(DartType type, Registry registry) { |
+ void computeImpactForInstantiatedConstantType( |
+ DartType type, WorldImpactBuilder impactBuilder) { |
DartType instantiatedType = |
type.isFunctionType ? coreTypes.functionType : type; |
if (type is InterfaceType) { |
- registry.registerInstantiation(instantiatedType); |
+ impactBuilder |
+ .registerTypeUse(new TypeUse.instantiation(instantiatedType)); |
if (classNeedsRtiField(type.element)) { |
- registry.registerStaticUse(new StaticUse.staticInvoke( |
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
// TODO(johnniwinther): Find the right [CallStructure]. |
helpers.setRuntimeTypeInfo, |
null)); |
@@ -1121,7 +1143,7 @@ class JavaScriptBackend extends Backend { |
// If we use a type literal in a constant, the compile time |
// constant emitter will generate a call to the createRuntimeType |
// helper so we register a use of that. |
- registry.registerStaticUse(new StaticUse.staticInvoke( |
+ impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
// TODO(johnniwinther): Find the right [CallStructure]. |
helpers.createRuntimeType, |
null)); |
@@ -1290,23 +1312,11 @@ class JavaScriptBackend extends Backend { |
void registerInstantiatedType( |
InterfaceType type, Enqueuer enqueuer, Registry registry, |
{bool mirrorUsage: false}) { |
- lookupMapAnalysis.registerInstantiatedType(type, registry); |
+ lookupMapAnalysis.registerInstantiatedType(type); |
super.registerInstantiatedType(type, enqueuer, registry, |
mirrorUsage: mirrorUsage); |
} |
- void registerUseInterceptor(Enqueuer enqueuer) { |
- assert(!enqueuer.isResolutionQueue); |
- if (!enqueuer.nativeEnqueuer.hasInstantiatedNativeClasses()) return; |
- Registry registry = compiler.globalDependencies; |
- enqueue(enqueuer, helpers.getNativeInterceptorMethod, registry); |
- enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
- enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
- enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
- needToInitializeIsolateAffinityTag = true; |
- needToInitializeDispatchProperty = true; |
- } |
- |
void enqueueHelpers(ResolutionEnqueuer world, Registry registry) { |
assert(helpers.interceptorsLibrary != null); |
// TODO(ngeoffray): Not enqueuing those two classes currently make |
@@ -1605,7 +1615,8 @@ class JavaScriptBackend extends Backend { |
if (constant != null) { |
ConstantValue initialValue = constants.getConstantValue(constant); |
if (initialValue != null) { |
- registerCompileTimeConstant(initialValue, work.registry); |
+ computeImpactForCompileTimeConstant( |
+ initialValue, work.registry.worldImpact, false); |
addCompileTimeConstantForEmission(initialValue); |
// We don't need to generate code for static or top-level |
// variables. For instance variables, we may need to generate |
@@ -2352,15 +2363,15 @@ class JavaScriptBackend extends Backend { |
/// Called when [enqueuer] is empty, but before it is closed. |
bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
- if (!compiler.options.resolveOnly) { |
- // TODO(johnniwinther): The custom element analysis eagerly enqueues |
- // elements on the codegen queue. Change to compute the data needed |
- // instead. |
+ // Add elements used synthetically, that is, through features rather than |
+ // syntax, for instance custom elements. |
+ // |
+ // Return early if any elements are added to avoid counting the elements as |
+ // due to mirrors. |
+ customElementsAnalysis.onQueueEmpty(enqueuer); |
+ lookupMapAnalysis.onQueueEmpty(enqueuer); |
+ typeVariableHandler.onQueueEmpty(enqueuer); |
- // Add elements referenced only via custom elements. Return early if any |
- // elements are added to avoid counting the elements as due to mirrors. |
- customElementsAnalysis.onQueueEmpty(enqueuer); |
- } |
if (!enqueuer.queueIsEmpty) return false; |
noSuchMethodRegistry.onQueueEmpty(); |
@@ -2404,6 +2415,9 @@ class JavaScriptBackend extends Backend { |
compiler.libraryLoader.libraries.forEach(retainMetadataOf); |
+ StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue |
+ ? constantImpactsForResolution |
+ : constantImpactsForResolution; |
if (enqueuer.isResolutionQueue && !enqueuer.queueIsClosed) { |
/// Register the constant value of [metadata] as live in resolution. |
void registerMetadataConstant(MetadataAnnotation metadata) { |
@@ -2412,8 +2426,8 @@ class JavaScriptBackend extends Backend { |
Dependency dependency = |
new Dependency(constant, metadata.annotatedElement); |
metadataConstants.add(dependency); |
- registerCompileTimeConstant(dependency.constant, |
- new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
+ computeImpactForCompileTimeConstant( |
+ dependency.constant, impactBuilder, enqueuer.isResolutionQueue); |
} |
// TODO(johnniwinther): We should have access to all recently processed |
@@ -2422,11 +2436,12 @@ class JavaScriptBackend extends Backend { |
registerMetadataConstant); |
} else { |
for (Dependency dependency in metadataConstants) { |
- registerCompileTimeConstant(dependency.constant, |
- new EagerRegistry('EagerRegistry for ${dependency}', enqueuer)); |
+ computeImpactForCompileTimeConstant( |
+ dependency.constant, impactBuilder, enqueuer.isResolutionQueue); |
} |
metadataConstants.clear(); |
} |
+ enqueuer.applyImpact(null, impactBuilder.flush()); |
} |
return true; |
} |
@@ -3014,6 +3029,16 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
for (BackendImpact otherImpact in backendImpact.otherImpacts) { |
registerBackendImpact(worldImpact, otherImpact); |
} |
+ for (BackendFeature feature in backendImpact.features) { |
+ switch (feature) { |
+ case BackendFeature.needToInitializeDispatchProperty: |
+ backend.needToInitializeDispatchProperty = true; |
+ break; |
+ case BackendFeature.needToInitializeIsolateAffinityTag: |
+ backend.needToInitializeIsolateAffinityTag = true; |
+ break; |
+ } |
+ } |
} |
/// Register [type] as required for the runtime type information system. |
@@ -3105,14 +3130,12 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
@override |
WorldImpact transformCodegenImpact(CodegenImpact impact) { |
TransformedWorldImpact transformed = new TransformedWorldImpact(impact); |
- EagerRegistry registry = impact.registry; |
- Enqueuer world = registry.world; |
for (TypeUse typeUse in impact.typeUses) { |
DartType type = typeUse.type; |
switch (typeUse.kind) { |
case TypeUseKind.INSTANTIATION: |
- backend.lookupMapAnalysis.registerInstantiatedType(type, registry); |
+ backend.lookupMapAnalysis.registerInstantiatedType(type); |
break; |
case TypeUseKind.IS_CHECK: |
onIsCheckForCodegen(type, transformed); |
@@ -3122,7 +3145,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
for (ConstantValue constant in impact.compileTimeConstants) { |
- backend.registerCompileTimeConstant(constant, registry); |
+ backend.computeImpactForCompileTimeConstant(constant, transformed, false); |
backend.addCompileTimeConstantForEmission(constant); |
} |
@@ -3149,7 +3172,9 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
} |
if (impact.usesInterceptor) { |
- backend.registerUseInterceptor(world); |
+ if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { |
+ registerBackendImpact(transformed, impacts.interceptorUse); |
+ } |
} |
for (ClassElement element in impact.typeConstants) { |
@@ -3207,7 +3232,9 @@ class JavaScriptImpactStrategy extends ImpactStrategy { |
impact.apply(visitor); |
} else { |
impact.apply(visitor); |
- resolution.uncacheWorldImpact(element); |
+ if (element != null) { |
+ resolution.uncacheWorldImpact(element); |
+ } |
} |
} else if (impactUse == DeferredLoadTask.IMPACT_USE) { |
impact.apply(visitor); |