Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/enqueuer.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart |
| index c0b028c951ed01490cd7bf6f8e475e9f657e9650..decfea41b19c7dac1a2232abb39617137975ce87 100644 |
| --- a/pkg/compiler/lib/src/js_backend/enqueuer.dart |
| +++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart |
| @@ -48,12 +48,12 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| @deprecated |
| final Compiler _compiler; // TODO(ahe): Remove this dependency. |
| final EnqueuerStrategy strategy; |
| - final Map<String, Set<Element>> instanceMembersByName = |
| + final Map<String, Set<Element>> _instanceMembersByName = |
| new Map<String, Set<Element>>(); |
| - final Map<String, Set<Element>> instanceFunctionsByName = |
| + final Map<String, Set<Element>> _instanceFunctionsByName = |
| new Map<String, Set<Element>>(); |
| final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
| - Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
| + Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); |
| final CodegenWorldBuilderImpl _universe = |
| new CodegenWorldBuilderImpl(const TypeMaskStrategy()); |
| @@ -61,23 +61,34 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| final CompilerTask task; |
| final native.NativeEnqueuer nativeEnqueuer; |
| - WorldImpactVisitor impactVisitor; |
| + WorldImpactVisitor _impactVisitor; |
| + |
| + final Queue<WorkItem> queue = new Queue<WorkItem>(); |
| + final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
| + |
| + final Set<Element> newlyEnqueuedElements; |
| + |
| + final Set<DynamicUse> newlySeenSelectors; |
| + |
| + bool _enabledNoSuchMethod = false; |
| + |
| + static const ImpactUseCase IMPACT_USE = |
| + const ImpactUseCase('CodegenEnqueuer'); |
| CodegenEnqueuer(this.task, Compiler compiler, this.strategy) |
| - : queue = new Queue<CodegenWorkItem>(), |
| - newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| + : newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| newlySeenSelectors = compiler.cacheStrategy.newSet(), |
| nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(), |
| this.name = 'codegen enqueuer', |
| this._compiler = compiler { |
| - impactVisitor = new EnqueuerImplImpactVisitor(this); |
| + _impactVisitor = new EnqueuerImplImpactVisitor(this); |
| } |
| CodegenWorldBuilder get universe => _universe; |
| - Backend get backend => _compiler.backend; |
| + Backend get _backend => _compiler.backend; |
| - CompilerOptions get options => _compiler.options; |
| + CompilerOptions get _options => _compiler.options; |
| ClosedWorld get _world => _compiler.closedWorld; |
| @@ -86,27 +97,26 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| bool get isResolutionQueue => false; |
| - DiagnosticReporter get reporter => _compiler.reporter; |
| - |
| /** |
| * Documentation wanted -- johnniwinther |
| * |
| * Invariant: [element] must be a declaration element. |
| */ |
| - void addToWorkList(Element element) { |
| + void _addToWorkList(Element element) { |
| assert(invariant(element, element.isDeclaration)); |
| // Don't generate code for foreign elements. |
| - if (backend.isForeign(element)) return; |
| + if (_backend.isForeign(element)) return; |
| // Codegen inlines field initializers. It only needs to generate |
| // code for checked setters. |
| if (element.isField && element.isInstanceMember) { |
| - if (!options.enableTypeAssertions || element.enclosingElement.isClosure) { |
| + if (!_options.enableTypeAssertions || |
| + element.enclosingElement.isClosure) { |
| return; |
| } |
| } |
| - if (options.hasIncrementalSupport && !isProcessed(element)) { |
| + if (_options.hasIncrementalSupport && !isProcessed(element)) { |
| newlyEnqueuedElements.add(element); |
| } |
| @@ -114,7 +124,7 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| throw new SpannableAssertionFailure( |
| element, "Codegen work list is closed. Trying to add $element"); |
| } |
| - queue.add(new CodegenWorkItem(backend, element)); |
| + queue.add(new CodegenWorkItem(_backend, element)); |
| // TODO(sigmund): add other missing dependencies (internals, selectors |
| // enqueued after allocations). |
| _compiler.dumpInfoTask |
| @@ -124,31 +134,27 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
| if (worldImpact.isEmpty) return; |
| impactStrategy.visitImpact( |
| - impactSource, worldImpact, impactVisitor, impactUse); |
| - } |
| - |
| - void registerInstantiatedType(InterfaceType type) { |
| - _registerInstantiatedType(type); |
| + impactSource, worldImpact, _impactVisitor, impactUse); |
| } |
| void _registerInstantiatedType(InterfaceType type, |
| {bool mirrorUsage: false, bool nativeUsage: false}) { |
| task.measure(() { |
| ClassElement cls = type.element; |
| - bool isNative = backend.isNative(cls); |
| + bool isNative = _backend.isNative(cls); |
| _universe.registerTypeInstantiation(type, |
| isNative: isNative, |
| byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
| applyImpact( |
| - backend.registerImplementedClass(cls, forResolution: false)); |
| + _backend.registerImplementedClass(cls, forResolution: false)); |
| }); |
| if (nativeUsage) { |
| nativeEnqueuer.onInstantiatedType(type); |
| } |
| - backend.registerInstantiatedType(type); |
| + _backend.registerInstantiatedType(type); |
| // TODO(johnniwinther): Share this reasoning with [Universe]. |
| if (!cls.isAbstract || isNative || mirrorUsage) { |
| - processInstantiatedClass(cls); |
| + _processInstantiatedClass(cls); |
| } |
| }); |
| } |
| @@ -175,13 +181,13 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| // its metadata parsed and analyzed. |
| // Note: this assumes that there are no non-native fields on native |
| // classes, which may not be the case when a native class is subclassed. |
| - if (backend.isNative(cls)) { |
| + if (_backend.isNative(cls)) { |
| if (_universe.hasInvokedGetter(member, _world) || |
| _universe.hasInvocation(member, _world)) { |
| - addToWorkList(member); |
| + _addToWorkList(member); |
| return; |
| } else if (universe.hasInvokedSetter(member, _world)) { |
| - addToWorkList(member); |
| + _addToWorkList(member); |
| return; |
| } |
| // Native fields need to go into instanceMembersByName as they |
| @@ -190,52 +196,52 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| // All field initializers must be resolved as they could |
| // have an observable side-effect (and cannot be tree-shaken |
| // away). |
| - addToWorkList(member); |
| + _addToWorkList(member); |
| return; |
| } |
| } else if (member.isFunction) { |
| FunctionElement function = member; |
| if (function.name == Identifiers.noSuchMethod_) { |
| - registerNoSuchMethod(function); |
| + _registerNoSuchMethod(function); |
| } |
| if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
| - registerCallMethodWithFreeTypeVariables(function); |
| + _registerCallMethodWithFreeTypeVariables(function); |
| } |
| // If there is a property access with the same name as a method we |
| // need to emit the method. |
| if (_universe.hasInvokedGetter(function, _world)) { |
| - registerClosurizedMember(function); |
| - addToWorkList(function); |
| + _registerClosurizedMember(function); |
| + _addToWorkList(function); |
| return; |
| } |
| _registerInstanceMethod(function); |
| if (_universe.hasInvocation(function, _world)) { |
| - addToWorkList(function); |
| + _addToWorkList(function); |
| return; |
| } |
| } else if (member.isGetter) { |
| FunctionElement getter = member; |
| if (_universe.hasInvokedGetter(getter, _world)) { |
| - addToWorkList(getter); |
| + _addToWorkList(getter); |
| return; |
| } |
| // We don't know what selectors the returned closure accepts. If |
| // the set contains any selector we have to assume that it matches. |
| if (_universe.hasInvocation(getter, _world)) { |
| - addToWorkList(getter); |
| + _addToWorkList(getter); |
| return; |
| } |
| } else if (member.isSetter) { |
| FunctionElement setter = member; |
| if (_universe.hasInvokedSetter(setter, _world)) { |
| - addToWorkList(setter); |
| + _addToWorkList(setter); |
| return; |
| } |
| } |
| // The element is not yet used. Add it to the list of instance |
| // members to still be processed. |
| - instanceMembersByName |
| + _instanceMembersByName |
| .putIfAbsent(memberName, () => new Set<Element>()) |
| .add(member); |
| } |
| @@ -243,14 +249,12 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| // Store the member in [instanceFunctionsByName] to catch |
| // getters on the function. |
| void _registerInstanceMethod(MethodElement element) { |
| - instanceFunctionsByName |
| + _instanceFunctionsByName |
| .putIfAbsent(element.name, () => new Set<Element>()) |
| .add(element); |
| } |
| - void enableIsolateSupport() {} |
|
Harry Terkelsen
2016/11/29 22:25:03
can we remove all enableIsolateSupport calls?
Johnni Winther
2016/11/30 08:05:23
This is only for the codegen enqueuer. The resolut
|
| - |
| - void processInstantiatedClass(ClassElement cls) { |
| + void _processInstantiatedClass(ClassElement cls) { |
| task.measure(() { |
| if (_processedClasses.contains(cls)) return; |
| @@ -266,12 +270,12 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| */ |
| _processedClasses.add(superclass); |
| - recentClasses.add(superclass); |
| + _recentClasses.add(superclass); |
| superclass.implementation.forEachMember(processInstantiatedClassMember); |
| // We only tell the backend once that [superclass] was instantiated, so |
| // any additional dependencies must be treated as global |
| // dependencies. |
| - applyImpact(backend.registerInstantiatedClass(superclass, |
| + applyImpact(_backend.registerInstantiatedClass(superclass, |
| forResolution: false)); |
| } |
| @@ -283,15 +287,15 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| }); |
| } |
| - void registerDynamicUse(DynamicUse dynamicUse) { |
| + void processDynamicUse(DynamicUse dynamicUse) { |
| task.measure(() { |
| if (_universe.registerDynamicUse(dynamicUse)) { |
| - handleUnseenSelector(dynamicUse); |
| + _handleUnseenSelector(dynamicUse); |
| } |
| }); |
| } |
| - void processSet( |
| + void _processSet( |
| Map<String, Set<Element>> map, String memberName, bool f(Element e)) { |
| Set<Element> members = map[memberName]; |
| if (members == null) return; |
| @@ -306,35 +310,34 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| map[memberName].addAll(remaining); |
| } |
| - processInstanceMembers(String n, bool f(Element e)) { |
| - processSet(instanceMembersByName, n, f); |
| - } |
| - |
| - processInstanceFunctions(String n, bool f(Element e)) { |
| - processSet(instanceFunctionsByName, n, f); |
| + void _processInstanceMembers(String n, bool f(Element e)) { |
| + _processSet(_instanceMembersByName, n, f); |
| } |
| - void _handleUnseenSelector(DynamicUse universeSelector) { |
| - strategy.processDynamicUse(this, universeSelector); |
| + void _processInstanceFunctions(String n, bool f(Element e)) { |
| + _processSet(_instanceFunctionsByName, n, f); |
| } |
| - void handleUnseenSelectorInternal(DynamicUse dynamicUse) { |
| + void _handleUnseenSelector(DynamicUse dynamicUse) { |
| + if (_options.hasIncrementalSupport) { |
| + newlySeenSelectors.add(dynamicUse); |
| + } |
| Selector selector = dynamicUse.selector; |
| String methodName = selector.name; |
| - processInstanceMembers(methodName, (Element member) { |
| + _processInstanceMembers(methodName, (Element member) { |
| if (dynamicUse.appliesUnnamed(member, _world)) { |
| if (member.isFunction && selector.isGetter) { |
| - registerClosurizedMember(member); |
| + _registerClosurizedMember(member); |
| } |
| - addToWorkList(member); |
| + _addToWorkList(member); |
| return true; |
| } |
| return false; |
| }); |
| if (selector.isGetter) { |
| - processInstanceFunctions(methodName, (Element member) { |
| + _processInstanceFunctions(methodName, (Element member) { |
| if (dynamicUse.appliesUnnamed(member, _world)) { |
| - registerClosurizedMember(member); |
| + _registerClosurizedMember(member); |
| return true; |
| } |
| return false; |
| @@ -342,25 +345,16 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| } |
| } |
| - /** |
| - * Documentation wanted -- johnniwinther |
| - * |
| - * Invariant: [element] must be a declaration element. |
| - */ |
| - void registerStaticUse(StaticUse staticUse) { |
| - strategy.processStaticUse(this, staticUse); |
| - } |
| - |
| - void registerStaticUseInternal(StaticUse staticUse) { |
| + void processStaticUse(StaticUse staticUse) { |
| Element element = staticUse.element; |
| assert(invariant(element, element.isDeclaration, |
| message: "Element ${element} is not the declaration.")); |
| _universe.registerStaticUse(staticUse); |
| - applyImpact(backend.registerStaticUse(element, forResolution: false)); |
| + applyImpact(_backend.registerStaticUse(element, forResolution: false)); |
| bool addElement = true; |
| switch (staticUse.kind) { |
| case StaticUseKind.STATIC_TEAR_OFF: |
| - applyImpact(backend.registerGetOfStaticFunction()); |
| + applyImpact(_backend.registerGetOfStaticFunction()); |
| break; |
| case StaticUseKind.FIELD_GET: |
| case StaticUseKind.FIELD_SET: |
| @@ -379,22 +373,18 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| case StaticUseKind.CONSTRUCTOR_INVOKE: |
| case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| case StaticUseKind.REDIRECTION: |
| - registerTypeUseInternal(new TypeUse.instantiation(staticUse.type)); |
| + processTypeUse(new TypeUse.instantiation(staticUse.type)); |
| break; |
| case StaticUseKind.DIRECT_INVOKE: |
| _registerInstanceMethod(staticUse.element); |
| break; |
| } |
| if (addElement) { |
| - addToWorkList(element); |
| + _addToWorkList(element); |
| } |
| } |
| - void registerTypeUse(TypeUse typeUse) { |
| - strategy.processTypeUse(this, typeUse); |
| - } |
| - |
| - void registerTypeUseInternal(TypeUse typeUse) { |
| + void processTypeUse(TypeUse typeUse) { |
| DartType type = typeUse.type; |
| switch (typeUse.kind) { |
| case TypeUseKind.INSTANTIATION: |
| @@ -412,7 +402,7 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| _registerIsCheck(type); |
| break; |
| case TypeUseKind.CHECKED_MODE_CHECK: |
| - if (options.enableTypeAssertions) { |
| + if (_options.enableTypeAssertions) { |
| _registerIsCheck(type); |
| } |
| break; |
| @@ -429,18 +419,18 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
| } |
| - void registerCallMethodWithFreeTypeVariables(Element element) { |
| - applyImpact(backend.registerCallMethodWithFreeTypeVariables(element, |
| + void _registerCallMethodWithFreeTypeVariables(Element element) { |
| + applyImpact(_backend.registerCallMethodWithFreeTypeVariables(element, |
| forResolution: false)); |
| } |
| - void registerClosurizedMember(TypedElement element) { |
| + void _registerClosurizedMember(TypedElement element) { |
| assert(element.isInstanceMember); |
| if (element.type.containsTypeVariables) { |
| - applyImpact(backend.registerClosureWithFreeTypeVariables(element, |
| + applyImpact(_backend.registerClosureWithFreeTypeVariables(element, |
| forResolution: false)); |
| } |
| - applyImpact(backend.registerBoundClosure()); |
| + applyImpact(_backend.registerBoundClosure()); |
| } |
| void forEach(void f(WorkItem work)) { |
| @@ -454,24 +444,24 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| // is currently a side-effect of calling `work.run`. |
| } |
| } |
| - List recents = recentClasses.toList(growable: false); |
| - recentClasses.clear(); |
| - if (!onQueueEmpty(recents)) recentClasses.addAll(recents); |
| - } while (queue.isNotEmpty || recentClasses.isNotEmpty); |
| + List recents = _recentClasses.toList(growable: false); |
| + _recentClasses.clear(); |
| + if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents); |
| + } while (queue.isNotEmpty || _recentClasses.isNotEmpty); |
| } |
| - /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| + /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| /// contains the set of all classes seen for the first time since |
| - /// [onQueueEmpty] was called last. A return value of [true] indicates that |
| + /// [_onQueueEmpty] was called last. A return value of [true] indicates that |
| /// the [recentClasses] have been processed and may be cleared. If [false] is |
| - /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
| + /// returned, [_onQueueEmpty] will be called once the queue is empty again (or |
| /// still empty) and [recentClasses] will be a superset of the current value. |
| - bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
| - return backend.onQueueEmpty(this, recentClasses); |
| + bool _onQueueEmpty(Iterable<ClassElement> recentClasses) { |
| + return _backend.onQueueEmpty(this, recentClasses); |
| } |
| void logSummary(log(message)) { |
| - _logSpecificSummary(log); |
| + log('Compiled ${generatedCode.length} methods.'); |
| nativeEnqueuer.logSummary(log); |
| } |
| @@ -480,57 +470,34 @@ class CodegenEnqueuer extends EnqueuerImpl { |
| void _forgetElement(Element element) { |
| _universe.forgetElement(element, _compiler); |
| _processedClasses.remove(element); |
| - instanceMembersByName[element.name]?.remove(element); |
| - instanceFunctionsByName[element.name]?.remove(element); |
| + _instanceMembersByName[element.name]?.remove(element); |
| + _instanceFunctionsByName[element.name]?.remove(element); |
| } |
| - final Queue<CodegenWorkItem> queue; |
| - final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
| - |
| - final Set<Element> newlyEnqueuedElements; |
| - |
| - final Set<DynamicUse> newlySeenSelectors; |
| - |
| - bool enabledNoSuchMethod = false; |
| - |
| - static const ImpactUseCase IMPACT_USE = |
| - const ImpactUseCase('CodegenEnqueuer'); |
| - |
| ImpactUseCase get impactUse => IMPACT_USE; |
| bool isProcessed(Element member) => |
| member.isAbstract || generatedCode.containsKey(member); |
| - void registerNoSuchMethod(Element element) { |
| - if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) { |
| - applyImpact(backend.enableNoSuchMethod()); |
| - enabledNoSuchMethod = true; |
| + void _registerNoSuchMethod(Element element) { |
| + if (!_enabledNoSuchMethod && _backend.enabledNoSuchMethod) { |
| + applyImpact(_backend.enableNoSuchMethod()); |
| + _enabledNoSuchMethod = true; |
| } |
| } |
| - void _logSpecificSummary(log(message)) { |
| - log('Compiled ${generatedCode.length} methods.'); |
| - } |
| - |
| void forgetElement(Element element, Compiler compiler) { |
| _forgetElement(element); |
| generatedCode.remove(element); |
| if (element is MemberElement) { |
| for (Element closure in element.nestedClosures) { |
| generatedCode.remove(closure); |
| - removeFromSet(instanceMembersByName, closure); |
| - removeFromSet(instanceFunctionsByName, closure); |
| + removeFromSet(_instanceMembersByName, closure); |
| + removeFromSet(_instanceFunctionsByName, closure); |
| } |
| } |
| } |
| - void handleUnseenSelector(DynamicUse dynamicUse) { |
| - if (options.hasIncrementalSupport) { |
| - newlySeenSelectors.add(dynamicUse); |
| - } |
| - _handleUnseenSelector(dynamicUse); |
| - } |
| - |
| @override |
| Iterable<Entity> get processedEntities => generatedCode.keys; |