Chromium Code Reviews| 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 6650db7073f640499f6ff8f9ff370efa784db55b..0aac614d313ebb5a3c1773309173abb1ca2d4b40 100644 |
| --- a/pkg/compiler/lib/src/js_backend/backend.dart |
| +++ b/pkg/compiler/lib/src/js_backend/backend.dart |
| @@ -55,7 +55,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'; |
| @@ -576,6 +578,12 @@ class JavaScriptBackend extends Backend { |
| JavaScriptBackendSerialization serialization; |
| + StagedWorldImpactBuilder constantImpactsForResolution = |
| + new StagedWorldImpactBuilder(); |
| + |
| + StagedWorldImpactBuilder constantImpactsForCodegen = |
| + new StagedWorldImpactBuilder(); |
| + |
| final NativeData nativeData = new NativeData(); |
| final BackendHelpers helpers; |
| @@ -1060,17 +1068,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); |
| } |
| } |
| @@ -1078,32 +1089,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 (!type.treatAsRaw && classNeedsRti(type.element)) { |
| - registry.registerStaticUse(new StaticUse.staticInvoke( |
| + impactBuilder.registerStaticUse(new StaticUse.staticInvoke( |
| // TODO(johnniwinther): Find the right [CallStructure]. |
| helpers.setRuntimeTypeInfo, |
| null)); |
| @@ -1112,7 +1134,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)); |
| @@ -1281,23 +1303,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 |
| @@ -1590,7 +1600,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 |
| @@ -2337,15 +2348,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(); |
| @@ -2385,6 +2396,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) { |
| @@ -2393,8 +2407,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); |
|
Harry Terkelsen
2016/09/19 21:17:52
enqueuer.isResolutionQueue -> true?
|
| } |
| // TODO(johnniwinther): We should have access to all recently processed |
| @@ -2403,11 +2417,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); |
|
Harry Terkelsen
2016/09/19 21:17:52
enqueuer.isResolutionQueue -> false?
|
| } |
| metadataConstants.clear(); |
| } |
| + enqueuer.applyImpact(null, impactBuilder.flush()); |
| } |
| return true; |
| } |
| @@ -3080,14 +3095,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); |
| @@ -3097,7 +3110,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer { |
| } |
| for (ConstantValue constant in impact.compileTimeConstants) { |
| - backend.registerCompileTimeConstant(constant, registry); |
| + backend.computeImpactForCompileTimeConstant(constant, transformed, false); |
| backend.addCompileTimeConstantForEmission(constant); |
| } |
| @@ -3124,7 +3137,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) { |
| @@ -3182,7 +3197,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); |