| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.js.enqueue; | 5 library dart2js.js.enqueue; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import '../common/backend_api.dart' show Backend; |
| 9 import '../common/codegen.dart' show CodegenWorkItem; | 10 import '../common/codegen.dart' show CodegenWorkItem; |
| 11 import '../common/registry.dart' show Registry; |
| 10 import '../common/names.dart' show Identifiers; | 12 import '../common/names.dart' show Identifiers; |
| 11 import '../common/resolution.dart' show Resolution; | |
| 12 import '../common/work.dart' show WorkItem; | 13 import '../common/work.dart' show WorkItem; |
| 13 import '../common.dart'; | 14 import '../common.dart'; |
| 14 import '../compiler.dart' show Compiler; | 15 import '../compiler.dart' show Compiler; |
| 15 import '../dart_types.dart' show DartType, InterfaceType; | 16 import '../dart_types.dart' show DartType, InterfaceType; |
| 16 import '../elements/elements.dart' | 17 import '../elements/elements.dart' |
| 17 show | 18 show |
| 18 ClassElement, | 19 ClassElement, |
| 19 ConstructorElement, | 20 ConstructorElement, |
| 20 Element, | 21 Element, |
| 21 Elements, | 22 Elements, |
| 22 Entity, | 23 Entity, |
| 23 FunctionElement, | 24 FunctionElement, |
| 24 LibraryElement, | 25 LibraryElement, |
| 25 Member, | 26 Member, |
| 26 MemberElement, | 27 MemberElement, |
| 27 Name, | 28 Name, |
| 28 TypedElement, | 29 TypedElement, |
| 29 TypedefElement; | 30 TypedefElement; |
| 30 import '../enqueue.dart'; | 31 import '../enqueue.dart'; |
| 31 import '../js/js.dart' as js; | 32 import '../js/js.dart' as js; |
| 32 import '../native/native.dart' as native; | 33 import '../native/native.dart' as native; |
| 34 import '../options.dart'; |
| 33 import '../types/types.dart' show TypeMaskStrategy; | 35 import '../types/types.dart' show TypeMaskStrategy; |
| 34 import '../universe/selector.dart' show Selector; | 36 import '../universe/selector.dart' show Selector; |
| 35 import '../universe/universe.dart'; | 37 import '../universe/universe.dart'; |
| 36 import '../universe/use.dart' | 38 import '../universe/use.dart' |
| 37 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 39 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 38 import '../universe/world_impact.dart' | 40 import '../universe/world_impact.dart' |
| 39 show ImpactUseCase, WorldImpact, WorldImpactVisitor; | 41 show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 40 import '../util/util.dart' show Setlet; | 42 import '../util/util.dart' show Setlet; |
| 43 import '../world.dart'; |
| 41 | 44 |
| 42 /// [Enqueuer] which is specific to code generation. | 45 /// [Enqueuer] which is specific to code generation. |
| 43 class CodegenEnqueuer implements Enqueuer { | 46 class CodegenEnqueuer implements Enqueuer { |
| 44 final String name; | 47 final String name; |
| 45 final Compiler compiler; // TODO(ahe): Remove this dependency. | 48 @deprecated |
| 49 final Compiler _compiler; // TODO(ahe): Remove this dependency. |
| 46 final EnqueuerStrategy strategy; | 50 final EnqueuerStrategy strategy; |
| 47 final Map<String, Set<Element>> instanceMembersByName = | 51 final Map<String, Set<Element>> instanceMembersByName = |
| 48 new Map<String, Set<Element>>(); | 52 new Map<String, Set<Element>>(); |
| 49 final Map<String, Set<Element>> instanceFunctionsByName = | 53 final Map<String, Set<Element>> instanceFunctionsByName = |
| 50 new Map<String, Set<Element>>(); | 54 new Map<String, Set<Element>>(); |
| 51 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | 55 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
| 52 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); | 56 Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
| 53 final Universe universe = new Universe(const TypeMaskStrategy()); | 57 final Universe universe = new Universe(const TypeMaskStrategy()); |
| 54 | 58 |
| 55 static final TRACE_MIRROR_ENQUEUING = | 59 static final TRACE_MIRROR_ENQUEUING = |
| 56 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 60 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
| 57 | 61 |
| 58 bool queueIsClosed = false; | 62 bool queueIsClosed = false; |
| 59 EnqueueTask task; | 63 EnqueueTask task; |
| 60 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 64 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 61 | 65 |
| 62 bool hasEnqueuedReflectiveElements = false; | 66 bool hasEnqueuedReflectiveElements = false; |
| 63 bool hasEnqueuedReflectiveStaticFields = false; | 67 bool hasEnqueuedReflectiveStaticFields = false; |
| 64 | 68 |
| 65 WorldImpactVisitor impactVisitor; | 69 WorldImpactVisitor impactVisitor; |
| 66 | 70 |
| 67 CodegenEnqueuer(Compiler compiler, this.strategy) | 71 CodegenEnqueuer(Compiler compiler, this.strategy) |
| 68 : queue = new Queue<CodegenWorkItem>(), | 72 : queue = new Queue<CodegenWorkItem>(), |
| 69 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 73 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
| 70 newlySeenSelectors = compiler.cacheStrategy.newSet(), | 74 newlySeenSelectors = compiler.cacheStrategy.newSet(), |
| 71 this.name = 'codegen enqueuer', | 75 this.name = 'codegen enqueuer', |
| 72 this.compiler = compiler { | 76 this._compiler = compiler { |
| 73 impactVisitor = new _EnqueuerImpactVisitor(this); | 77 impactVisitor = new _EnqueuerImpactVisitor(this); |
| 74 } | 78 } |
| 75 | 79 |
| 76 // TODO(johnniwinther): Move this to [ResolutionEnqueuer]. | 80 Backend get backend => _compiler.backend; |
| 77 Resolution get resolution => compiler.resolution; | 81 |
| 82 CompilerOptions get options => _compiler.options; |
| 83 |
| 84 Registry get globalDependencies => _compiler.globalDependencies; |
| 85 |
| 86 Registry get mirrorDependencies => _compiler.mirrorDependencies; |
| 87 |
| 88 ClassWorld get _world => _compiler.world; |
| 78 | 89 |
| 79 bool get queueIsEmpty => queue.isEmpty; | 90 bool get queueIsEmpty => queue.isEmpty; |
| 80 | 91 |
| 81 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 92 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 82 bool get isResolutionQueue => false; | 93 bool get isResolutionQueue => false; |
| 83 | 94 |
| 84 QueueFilter get filter => compiler.enqueuerFilter; | 95 QueueFilter get filter => _compiler.enqueuerFilter; |
| 85 | 96 |
| 86 DiagnosticReporter get reporter => compiler.reporter; | 97 DiagnosticReporter get reporter => _compiler.reporter; |
| 87 | |
| 88 bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); | |
| 89 | |
| 90 Iterable<ClassElement> get processedClasses => _processedClasses; | |
| 91 | 98 |
| 92 /** | 99 /** |
| 93 * Documentation wanted -- johnniwinther | 100 * Documentation wanted -- johnniwinther |
| 94 * | 101 * |
| 95 * Invariant: [element] must be a declaration element. | 102 * Invariant: [element] must be a declaration element. |
| 96 */ | 103 */ |
| 97 void addToWorkList(Element element) { | 104 void addToWorkList(Element element) { |
| 98 assert(invariant(element, element.isDeclaration)); | 105 assert(invariant(element, element.isDeclaration)); |
| 99 if (internalAddToWorkList(element) && compiler.options.dumpInfo) { | 106 // Don't generate code for foreign elements. |
| 107 if (backend.isForeign(element)) return; |
| 108 |
| 109 // Codegen inlines field initializers. It only needs to generate |
| 110 // code for checked setters. |
| 111 if (element.isField && element.isInstanceMember) { |
| 112 if (!options.enableTypeAssertions || |
| 113 element.enclosingElement.isClosure) { |
| 114 return; |
| 115 } |
| 116 } |
| 117 |
| 118 if (options.hasIncrementalSupport && !isProcessed(element)) { |
| 119 newlyEnqueuedElements.add(element); |
| 120 } |
| 121 |
| 122 if (queueIsClosed) { |
| 123 throw new SpannableAssertionFailure( |
| 124 element, "Codegen work list is closed. Trying to add $element"); |
| 125 } |
| 126 queue.add(new CodegenWorkItem(_compiler, element)); |
| 127 if (options.dumpInfo) { |
| 100 // TODO(sigmund): add other missing dependencies (internals, selectors | 128 // TODO(sigmund): add other missing dependencies (internals, selectors |
| 101 // enqueued after allocations), also enable only for the codegen enqueuer. | 129 // enqueued after allocations), also enable only for the codegen enqueuer. |
| 102 compiler.dumpInfoTask | 130 _compiler.dumpInfoTask |
| 103 .registerDependency(compiler.currentElement, element); | 131 .registerDependency(_compiler.currentElement, element); |
| 104 } | 132 } |
| 105 } | 133 } |
| 106 | 134 |
| 107 /// Apply the [worldImpact] of processing [element] to this enqueuer. | 135 /// Apply the [worldImpact] of processing [element] to this enqueuer. |
| 108 void applyImpact(Element element, WorldImpact worldImpact) { | 136 void applyImpact(Element element, WorldImpact worldImpact) { |
| 109 compiler.impactStrategy | 137 _compiler.impactStrategy |
| 110 .visitImpact(element, worldImpact, impactVisitor, impactUse); | 138 .visitImpact(element, worldImpact, impactVisitor, impactUse); |
| 111 } | 139 } |
| 112 | 140 |
| 113 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { | 141 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { |
| 114 task.measure(() { | 142 task.measure(() { |
| 115 ClassElement cls = type.element; | 143 ClassElement cls = type.element; |
| 116 cls.ensureResolved(resolution); | 144 bool isNative = backend.isNative(cls); |
| 117 bool isNative = compiler.backend.isNative(cls); | |
| 118 universe.registerTypeInstantiation(type, | 145 universe.registerTypeInstantiation(type, |
| 119 isNative: isNative, | 146 isNative: isNative, |
| 120 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { | 147 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
| 121 compiler.backend | 148 backend |
| 122 .registerImplementedClass(cls, this, compiler.globalDependencies); | 149 .registerImplementedClass(cls, this, globalDependencies); |
| 123 }); | 150 }); |
| 124 // TODO(johnniwinther): Share this reasoning with [Universe]. | 151 // TODO(johnniwinther): Share this reasoning with [Universe]. |
| 125 if (!cls.isAbstract || isNative || mirrorUsage) { | 152 if (!cls.isAbstract || isNative || mirrorUsage) { |
| 126 processInstantiatedClass(cls); | 153 processInstantiatedClass(cls); |
| 127 } | 154 } |
| 128 }); | 155 }); |
| 129 } | 156 } |
| 130 | 157 |
| 131 bool checkNoEnqueuedInvokedInstanceMethods() { | 158 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 132 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 159 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 143 String memberName = member.name; | 170 String memberName = member.name; |
| 144 | 171 |
| 145 if (member.isField) { | 172 if (member.isField) { |
| 146 // The obvious thing to test here would be "member.isNative", | 173 // The obvious thing to test here would be "member.isNative", |
| 147 // however, that only works after metadata has been parsed/analyzed, | 174 // however, that only works after metadata has been parsed/analyzed, |
| 148 // and that may not have happened yet. | 175 // and that may not have happened yet. |
| 149 // So instead we use the enclosing class, which we know have had | 176 // So instead we use the enclosing class, which we know have had |
| 150 // its metadata parsed and analyzed. | 177 // its metadata parsed and analyzed. |
| 151 // Note: this assumes that there are no non-native fields on native | 178 // Note: this assumes that there are no non-native fields on native |
| 152 // classes, which may not be the case when a native class is subclassed. | 179 // classes, which may not be the case when a native class is subclassed. |
| 153 if (compiler.backend.isNative(cls)) { | 180 if (backend.isNative(cls)) { |
| 154 compiler.world.registerUsedElement(member); | 181 _compiler.world.registerUsedElement(member); |
| 155 if (universe.hasInvokedGetter(member, compiler.world) || | 182 if (universe.hasInvokedGetter(member, _world) || |
| 156 universe.hasInvocation(member, compiler.world)) { | 183 universe.hasInvocation(member, _world)) { |
| 157 addToWorkList(member); | 184 addToWorkList(member); |
| 158 return; | 185 return; |
| 159 } | 186 } |
| 160 if (universe.hasInvokedSetter(member, compiler.world)) { | 187 if (universe.hasInvokedSetter(member, _world)) { |
| 161 addToWorkList(member); | 188 addToWorkList(member); |
| 162 return; | 189 return; |
| 163 } | 190 } |
| 164 // Native fields need to go into instanceMembersByName as they | 191 // Native fields need to go into instanceMembersByName as they |
| 165 // are virtual instantiation points and escape points. | 192 // are virtual instantiation points and escape points. |
| 166 } else { | 193 } else { |
| 167 // All field initializers must be resolved as they could | 194 // All field initializers must be resolved as they could |
| 168 // have an observable side-effect (and cannot be tree-shaken | 195 // have an observable side-effect (and cannot be tree-shaken |
| 169 // away). | 196 // away). |
| 170 addToWorkList(member); | 197 addToWorkList(member); |
| 171 return; | 198 return; |
| 172 } | 199 } |
| 173 } else if (member.isFunction) { | 200 } else if (member.isFunction) { |
| 174 FunctionElement function = member; | 201 FunctionElement function = member; |
| 175 function.computeType(resolution); | |
| 176 if (function.name == Identifiers.noSuchMethod_) { | 202 if (function.name == Identifiers.noSuchMethod_) { |
| 177 registerNoSuchMethod(function); | 203 registerNoSuchMethod(function); |
| 178 } | 204 } |
| 179 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 205 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
| 180 registerCallMethodWithFreeTypeVariables(function); | 206 registerCallMethodWithFreeTypeVariables(function); |
| 181 } | 207 } |
| 182 // If there is a property access with the same name as a method we | 208 // If there is a property access with the same name as a method we |
| 183 // need to emit the method. | 209 // need to emit the method. |
| 184 if (universe.hasInvokedGetter(function, compiler.world)) { | 210 if (universe.hasInvokedGetter(function, _world)) { |
| 185 registerClosurizedMember(function); | 211 registerClosurizedMember(function); |
| 186 addToWorkList(function); | 212 addToWorkList(function); |
| 187 return; | 213 return; |
| 188 } | 214 } |
| 189 // Store the member in [instanceFunctionsByName] to catch | 215 // Store the member in [instanceFunctionsByName] to catch |
| 190 // getters on the function. | 216 // getters on the function. |
| 191 instanceFunctionsByName | 217 instanceFunctionsByName |
| 192 .putIfAbsent(memberName, () => new Set<Element>()) | 218 .putIfAbsent(memberName, () => new Set<Element>()) |
| 193 .add(member); | 219 .add(member); |
| 194 if (universe.hasInvocation(function, compiler.world)) { | 220 if (universe.hasInvocation(function, _world)) { |
| 195 addToWorkList(function); | 221 addToWorkList(function); |
| 196 return; | 222 return; |
| 197 } | 223 } |
| 198 } else if (member.isGetter) { | 224 } else if (member.isGetter) { |
| 199 FunctionElement getter = member; | 225 FunctionElement getter = member; |
| 200 getter.computeType(resolution); | 226 if (universe.hasInvokedGetter(getter, _world)) { |
| 201 if (universe.hasInvokedGetter(getter, compiler.world)) { | |
| 202 addToWorkList(getter); | 227 addToWorkList(getter); |
| 203 return; | 228 return; |
| 204 } | 229 } |
| 205 // We don't know what selectors the returned closure accepts. If | 230 // We don't know what selectors the returned closure accepts. If |
| 206 // the set contains any selector we have to assume that it matches. | 231 // the set contains any selector we have to assume that it matches. |
| 207 if (universe.hasInvocation(getter, compiler.world)) { | 232 if (universe.hasInvocation(getter, _world)) { |
| 208 addToWorkList(getter); | 233 addToWorkList(getter); |
| 209 return; | 234 return; |
| 210 } | 235 } |
| 211 } else if (member.isSetter) { | 236 } else if (member.isSetter) { |
| 212 FunctionElement setter = member; | 237 FunctionElement setter = member; |
| 213 setter.computeType(resolution); | 238 if (universe.hasInvokedSetter(setter, _world)) { |
| 214 if (universe.hasInvokedSetter(setter, compiler.world)) { | |
| 215 addToWorkList(setter); | 239 addToWorkList(setter); |
| 216 return; | 240 return; |
| 217 } | 241 } |
| 218 } | 242 } |
| 219 | 243 |
| 220 // The element is not yet used. Add it to the list of instance | 244 // The element is not yet used. Add it to the list of instance |
| 221 // members to still be processed. | 245 // members to still be processed. |
| 222 instanceMembersByName | 246 instanceMembersByName |
| 223 .putIfAbsent(memberName, () => new Set<Element>()) | 247 .putIfAbsent(memberName, () => new Set<Element>()) |
| 224 .add(member); | 248 .add(member); |
| 225 } | 249 } |
| 226 | 250 |
| 227 void enableIsolateSupport() {} | 251 void enableIsolateSupport() {} |
| 228 | 252 |
| 229 void processInstantiatedClass(ClassElement cls) { | 253 void processInstantiatedClass(ClassElement cls) { |
| 230 task.measure(() { | 254 task.measure(() { |
| 231 if (_processedClasses.contains(cls)) return; | 255 if (_processedClasses.contains(cls)) return; |
| 232 // The class must be resolved to compute the set of all | |
| 233 // supertypes. | |
| 234 cls.ensureResolved(resolution); | |
| 235 | 256 |
| 236 void processClass(ClassElement superclass) { | 257 void processClass(ClassElement superclass) { |
| 237 if (_processedClasses.contains(superclass)) return; | 258 if (_processedClasses.contains(superclass)) return; |
| 238 // TODO(johnniwinther): Re-insert this invariant when unittests don't | 259 // TODO(johnniwinther): Re-insert this invariant when unittests don't |
| 239 // fail. There is already a similar invariant on the members. | 260 // fail. There is already a similar invariant on the members. |
| 240 /*if (!isResolutionQueue) { | 261 /*assert(invariant(superclass, |
| 241 assert(invariant(superclass, | |
| 242 superclass.isClosure || | 262 superclass.isClosure || |
| 243 compiler.enqueuer.resolution.isClassProcessed(superclass), | 263 _compiler.enqueuer.resolution.isClassProcessed(superclass), |
| 244 message: "Class $superclass has not been " | 264 message: "Class $superclass has not been " |
| 245 "processed in resolution.")); | 265 "processed in resolution.")); |
| 246 }*/ | 266 */ |
| 247 | 267 |
| 248 _processedClasses.add(superclass); | 268 _processedClasses.add(superclass); |
| 249 recentClasses.add(superclass); | 269 recentClasses.add(superclass); |
| 250 superclass.ensureResolved(resolution); | |
| 251 superclass.implementation.forEachMember(processInstantiatedClassMember); | 270 superclass.implementation.forEachMember(processInstantiatedClassMember); |
| 252 if (isResolutionQueue && | |
| 253 !compiler.serialization.isDeserialized(superclass)) { | |
| 254 compiler.resolver.checkClass(superclass); | |
| 255 } | |
| 256 // We only tell the backend once that [superclass] was instantiated, so | 271 // We only tell the backend once that [superclass] was instantiated, so |
| 257 // any additional dependencies must be treated as global | 272 // any additional dependencies must be treated as global |
| 258 // dependencies. | 273 // dependencies. |
| 259 compiler.backend.registerInstantiatedClass( | 274 backend.registerInstantiatedClass( |
| 260 superclass, this, compiler.globalDependencies); | 275 superclass, this, globalDependencies); |
| 261 } | 276 } |
| 262 | 277 |
| 263 ClassElement superclass = cls; | 278 ClassElement superclass = cls; |
| 264 while (superclass != null) { | 279 while (superclass != null) { |
| 265 processClass(superclass); | 280 processClass(superclass); |
| 266 superclass = superclass.superclass; | 281 superclass = superclass.superclass; |
| 267 } | 282 } |
| 268 }); | 283 }); |
| 269 } | 284 } |
| 270 | 285 |
| 271 void registerDynamicUse(DynamicUse dynamicUse) { | 286 void registerDynamicUse(DynamicUse dynamicUse) { |
| 272 task.measure(() { | 287 task.measure(() { |
| 273 if (universe.registerDynamicUse(dynamicUse)) { | 288 if (universe.registerDynamicUse(dynamicUse)) { |
| 274 handleUnseenSelector(dynamicUse); | 289 handleUnseenSelector(dynamicUse); |
| 275 } | 290 } |
| 276 }); | 291 }); |
| 277 } | 292 } |
| 278 | 293 |
| 279 void logEnqueueReflectiveAction(action, [msg = ""]) { | 294 void logEnqueueReflectiveAction(action, [msg = ""]) { |
| 280 if (TRACE_MIRROR_ENQUEUING) { | 295 if (TRACE_MIRROR_ENQUEUING) { |
| 281 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); | 296 print("MIRROR_ENQUEUE (C): $action $msg"); |
| 282 } | 297 } |
| 283 } | 298 } |
| 284 | 299 |
| 285 /// Enqeue the constructor [ctor] if it is required for reflection. | 300 /// Enqeue the constructor [ctor] if it is required for reflection. |
| 286 /// | 301 /// |
| 287 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 302 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 288 /// needed for reflection. | 303 /// needed for reflection. |
| 289 void enqueueReflectiveConstructor( | 304 void enqueueReflectiveConstructor( |
| 290 ConstructorElement ctor, bool enclosingWasIncluded) { | 305 ConstructorElement ctor, bool enclosingWasIncluded) { |
| 291 if (shouldIncludeElementDueToMirrors(ctor, | 306 if (shouldIncludeElementDueToMirrors(ctor, |
| 292 includedEnclosing: enclosingWasIncluded)) { | 307 includedEnclosing: enclosingWasIncluded)) { |
| 293 logEnqueueReflectiveAction(ctor); | 308 logEnqueueReflectiveAction(ctor); |
| 294 ClassElement cls = ctor.declaration.enclosingClass; | 309 ClassElement cls = ctor.declaration.enclosingClass; |
| 295 compiler.backend.registerInstantiatedType( | 310 backend.registerInstantiatedType( |
| 296 cls.rawType, this, compiler.mirrorDependencies, | 311 cls.rawType, this, mirrorDependencies, |
| 297 mirrorUsage: true); | 312 mirrorUsage: true); |
| 298 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); | 313 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); |
| 299 } | 314 } |
| 300 } | 315 } |
| 301 | 316 |
| 302 /// Enqeue the member [element] if it is required for reflection. | 317 /// Enqeue the member [element] if it is required for reflection. |
| 303 /// | 318 /// |
| 304 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 319 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 305 /// needed for reflection. | 320 /// needed for reflection. |
| 306 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 321 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
| 307 if (shouldIncludeElementDueToMirrors(element, | 322 if (shouldIncludeElementDueToMirrors(element, |
| 308 includedEnclosing: enclosingWasIncluded)) { | 323 includedEnclosing: enclosingWasIncluded)) { |
| 309 logEnqueueReflectiveAction(element); | 324 logEnqueueReflectiveAction(element); |
| 310 if (element.isTypedef) { | 325 if (element.isTypedef) { |
| 311 TypedefElement typedef = element; | 326 // Do nothing. |
| 312 typedef.ensureResolved(resolution); | |
| 313 compiler.world.allTypedefs.add(element); | |
| 314 } else if (Elements.isStaticOrTopLevel(element)) { | 327 } else if (Elements.isStaticOrTopLevel(element)) { |
| 315 registerStaticUse(new StaticUse.foreignUse(element.declaration)); | 328 registerStaticUse(new StaticUse.foreignUse(element.declaration)); |
| 316 } else if (element.isInstanceMember) { | 329 } else if (element.isInstanceMember) { |
| 317 // We need to enqueue all members matching this one in subclasses, as | 330 // We need to enqueue all members matching this one in subclasses, as |
| 318 // well. | 331 // well. |
| 319 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 332 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
| 320 DynamicUse dynamicUse = | 333 DynamicUse dynamicUse = |
| 321 new DynamicUse(new Selector.fromElement(element), null); | 334 new DynamicUse(new Selector.fromElement(element), null); |
| 322 registerDynamicUse(dynamicUse); | 335 registerDynamicUse(dynamicUse); |
| 323 if (element.isField) { | 336 if (element.isField) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 336 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 349 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 337 /// needed for reflection. | 350 /// needed for reflection. |
| 338 void enqueueReflectiveElementsInClass(ClassElement cls, | 351 void enqueueReflectiveElementsInClass(ClassElement cls, |
| 339 Iterable<ClassElement> recents, bool enclosingWasIncluded) { | 352 Iterable<ClassElement> recents, bool enclosingWasIncluded) { |
| 340 if (cls.library.isInternalLibrary || cls.isInjected) return; | 353 if (cls.library.isInternalLibrary || cls.isInjected) return; |
| 341 bool includeClass = shouldIncludeElementDueToMirrors(cls, | 354 bool includeClass = shouldIncludeElementDueToMirrors(cls, |
| 342 includedEnclosing: enclosingWasIncluded); | 355 includedEnclosing: enclosingWasIncluded); |
| 343 if (includeClass) { | 356 if (includeClass) { |
| 344 logEnqueueReflectiveAction(cls, "register"); | 357 logEnqueueReflectiveAction(cls, "register"); |
| 345 ClassElement decl = cls.declaration; | 358 ClassElement decl = cls.declaration; |
| 346 decl.ensureResolved(resolution); | 359 backend.registerInstantiatedType( |
| 347 compiler.backend.registerInstantiatedType( | 360 decl.rawType, this, mirrorDependencies, |
| 348 decl.rawType, this, compiler.mirrorDependencies, | |
| 349 mirrorUsage: true); | 361 mirrorUsage: true); |
| 350 } | 362 } |
| 351 // If the class is never instantiated, we know nothing of it can possibly | 363 // If the class is never instantiated, we know nothing of it can possibly |
| 352 // be reflected upon. | 364 // be reflected upon. |
| 353 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | 365 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. |
| 354 if (recents.contains(cls.declaration)) { | 366 if (recents.contains(cls.declaration)) { |
| 355 logEnqueueReflectiveAction(cls, "members"); | 367 logEnqueueReflectiveAction(cls, "members"); |
| 356 cls.constructors.forEach((Element element) { | 368 cls.constructors.forEach((Element element) { |
| 357 enqueueReflectiveConstructor(element, includeClass); | 369 enqueueReflectiveConstructor(element, includeClass); |
| 358 }); | 370 }); |
| 359 cls.forEachClassMember((Member member) { | 371 cls.forEachClassMember((Member member) { |
| 360 enqueueReflectiveMember(member.element, includeClass); | 372 enqueueReflectiveMember(member.element, includeClass); |
| 361 }); | 373 }); |
| 362 } | 374 } |
| 363 } | 375 } |
| 364 | 376 |
| 365 /// Enqeue special classes that might not be visible by normal means or that | 377 /// Enqeue special classes that might not be visible by normal means or that |
| 366 /// would not normally be enqueued: | 378 /// would not normally be enqueued: |
| 367 /// | 379 /// |
| 368 /// [Closure] is treated specially as it is the superclass of all closures. | 380 /// [Closure] is treated specially as it is the superclass of all closures. |
| 369 /// Although it is in an internal library, we mark it as reflectable. Note | 381 /// Although it is in an internal library, we mark it as reflectable. Note |
| 370 /// that none of its methods are reflectable, unless reflectable by | 382 /// that none of its methods are reflectable, unless reflectable by |
| 371 /// inheritance. | 383 /// inheritance. |
| 372 void enqueueReflectiveSpecialClasses() { | 384 void enqueueReflectiveSpecialClasses() { |
| 373 Iterable<ClassElement> classes = | 385 Iterable<ClassElement> classes = |
| 374 compiler.backend.classesRequiredForReflection; | 386 backend.classesRequiredForReflection; |
| 375 for (ClassElement cls in classes) { | 387 for (ClassElement cls in classes) { |
| 376 if (compiler.backend.referencedFromMirrorSystem(cls)) { | 388 if (backend.referencedFromMirrorSystem(cls)) { |
| 377 logEnqueueReflectiveAction(cls); | 389 logEnqueueReflectiveAction(cls); |
| 378 cls.ensureResolved(resolution); | 390 backend.registerInstantiatedType( |
| 379 compiler.backend.registerInstantiatedType( | 391 cls.rawType, this, mirrorDependencies, |
| 380 cls.rawType, this, compiler.mirrorDependencies, | |
| 381 mirrorUsage: true); | 392 mirrorUsage: true); |
| 382 } | 393 } |
| 383 } | 394 } |
| 384 } | 395 } |
| 385 | 396 |
| 386 /// Enqeue all local members of the library [lib] if they are required for | 397 /// Enqeue all local members of the library [lib] if they are required for |
| 387 /// reflection. | 398 /// reflection. |
| 388 void enqueueReflectiveElementsInLibrary( | 399 void enqueueReflectiveElementsInLibrary( |
| 389 LibraryElement lib, Iterable<ClassElement> recents) { | 400 LibraryElement lib, Iterable<ClassElement> recents) { |
| 390 bool includeLibrary = | 401 bool includeLibrary = |
| (...skipping 14 matching lines...) Expand all Loading... |
| 405 if (!hasEnqueuedReflectiveElements) { | 416 if (!hasEnqueuedReflectiveElements) { |
| 406 logEnqueueReflectiveAction("!START enqueueAll"); | 417 logEnqueueReflectiveAction("!START enqueueAll"); |
| 407 // First round of enqueuing, visit everything that is visible to | 418 // First round of enqueuing, visit everything that is visible to |
| 408 // also pick up static top levels, etc. | 419 // also pick up static top levels, etc. |
| 409 // Also, during the first round, consider all classes that have been seen | 420 // Also, during the first round, consider all classes that have been seen |
| 410 // as recently seen, as we do not know how many rounds of resolution might | 421 // as recently seen, as we do not know how many rounds of resolution might |
| 411 // have run before tree shaking is disabled and thus everything is | 422 // have run before tree shaking is disabled and thus everything is |
| 412 // enqueued. | 423 // enqueued. |
| 413 recents = _processedClasses.toSet(); | 424 recents = _processedClasses.toSet(); |
| 414 reporter.log('Enqueuing everything'); | 425 reporter.log('Enqueuing everything'); |
| 415 for (LibraryElement lib in compiler.libraryLoader.libraries) { | 426 for (LibraryElement lib in _compiler.libraryLoader.libraries) { |
| 416 enqueueReflectiveElementsInLibrary(lib, recents); | 427 enqueueReflectiveElementsInLibrary(lib, recents); |
| 417 } | 428 } |
| 418 enqueueReflectiveSpecialClasses(); | 429 enqueueReflectiveSpecialClasses(); |
| 419 hasEnqueuedReflectiveElements = true; | 430 hasEnqueuedReflectiveElements = true; |
| 420 hasEnqueuedReflectiveStaticFields = true; | 431 hasEnqueuedReflectiveStaticFields = true; |
| 421 logEnqueueReflectiveAction("!DONE enqueueAll"); | 432 logEnqueueReflectiveAction("!DONE enqueueAll"); |
| 422 } else if (recents.isNotEmpty) { | 433 } else if (recents.isNotEmpty) { |
| 423 // Keep looking at new classes until fixpoint is reached. | 434 // Keep looking at new classes until fixpoint is reached. |
| 424 logEnqueueReflectiveAction("!START enqueueRecents"); | 435 logEnqueueReflectiveAction("!START enqueueRecents"); |
| 425 recents.forEach((ClassElement cls) { | 436 recents.forEach((ClassElement cls) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 } | 478 } |
| 468 | 479 |
| 469 void _handleUnseenSelector(DynamicUse universeSelector) { | 480 void _handleUnseenSelector(DynamicUse universeSelector) { |
| 470 strategy.processDynamicUse(this, universeSelector); | 481 strategy.processDynamicUse(this, universeSelector); |
| 471 } | 482 } |
| 472 | 483 |
| 473 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { | 484 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { |
| 474 Selector selector = dynamicUse.selector; | 485 Selector selector = dynamicUse.selector; |
| 475 String methodName = selector.name; | 486 String methodName = selector.name; |
| 476 processInstanceMembers(methodName, (Element member) { | 487 processInstanceMembers(methodName, (Element member) { |
| 477 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 488 if (dynamicUse.appliesUnnamed(member, _world)) { |
| 478 if (member.isFunction && selector.isGetter) { | 489 if (member.isFunction && selector.isGetter) { |
| 479 registerClosurizedMember(member); | 490 registerClosurizedMember(member); |
| 480 } | 491 } |
| 481 addToWorkList(member); | 492 addToWorkList(member); |
| 482 return true; | 493 return true; |
| 483 } | 494 } |
| 484 return false; | 495 return false; |
| 485 }); | 496 }); |
| 486 if (selector.isGetter) { | 497 if (selector.isGetter) { |
| 487 processInstanceFunctions(methodName, (Element member) { | 498 processInstanceFunctions(methodName, (Element member) { |
| 488 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 499 if (dynamicUse.appliesUnnamed(member, _world)) { |
| 489 registerClosurizedMember(member); | 500 registerClosurizedMember(member); |
| 490 return true; | 501 return true; |
| 491 } | 502 } |
| 492 return false; | 503 return false; |
| 493 }); | 504 }); |
| 494 } | 505 } |
| 495 } | 506 } |
| 496 | 507 |
| 497 /** | 508 /** |
| 498 * Documentation wanted -- johnniwinther | 509 * Documentation wanted -- johnniwinther |
| 499 * | 510 * |
| 500 * Invariant: [element] must be a declaration element. | 511 * Invariant: [element] must be a declaration element. |
| 501 */ | 512 */ |
| 502 void registerStaticUse(StaticUse staticUse) { | 513 void registerStaticUse(StaticUse staticUse) { |
| 503 strategy.processStaticUse(this, staticUse); | 514 strategy.processStaticUse(this, staticUse); |
| 504 } | 515 } |
| 505 | 516 |
| 506 void registerStaticUseInternal(StaticUse staticUse) { | 517 void registerStaticUseInternal(StaticUse staticUse) { |
| 507 Element element = staticUse.element; | 518 Element element = staticUse.element; |
| 508 assert(invariant(element, element.isDeclaration, | 519 assert(invariant(element, element.isDeclaration, |
| 509 message: "Element ${element} is not the declaration.")); | 520 message: "Element ${element} is not the declaration.")); |
| 510 universe.registerStaticUse(staticUse); | 521 universe.registerStaticUse(staticUse); |
| 511 compiler.backend.registerStaticUse(element, this); | 522 backend.registerStaticUse(element, this); |
| 512 bool addElement = true; | 523 bool addElement = true; |
| 513 switch (staticUse.kind) { | 524 switch (staticUse.kind) { |
| 514 case StaticUseKind.STATIC_TEAR_OFF: | 525 case StaticUseKind.STATIC_TEAR_OFF: |
| 515 compiler.backend.registerGetOfStaticFunction(this); | 526 backend.registerGetOfStaticFunction(this); |
| 516 break; | 527 break; |
| 517 case StaticUseKind.FIELD_GET: | 528 case StaticUseKind.FIELD_GET: |
| 518 case StaticUseKind.FIELD_SET: | 529 case StaticUseKind.FIELD_SET: |
| 519 case StaticUseKind.CLOSURE: | 530 case StaticUseKind.CLOSURE: |
| 520 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and | 531 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and |
| 521 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | 532 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. |
| 522 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | 533 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot |
| 523 // enqueue. | 534 // enqueue. |
| 524 addElement = false; | 535 addElement = false; |
| 525 break; | 536 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 539 case TypeUseKind.INSTANTIATION: | 550 case TypeUseKind.INSTANTIATION: |
| 540 registerInstantiatedType(type); | 551 registerInstantiatedType(type); |
| 541 break; | 552 break; |
| 542 case TypeUseKind.INSTANTIATION: | 553 case TypeUseKind.INSTANTIATION: |
| 543 case TypeUseKind.IS_CHECK: | 554 case TypeUseKind.IS_CHECK: |
| 544 case TypeUseKind.AS_CAST: | 555 case TypeUseKind.AS_CAST: |
| 545 case TypeUseKind.CATCH_TYPE: | 556 case TypeUseKind.CATCH_TYPE: |
| 546 _registerIsCheck(type); | 557 _registerIsCheck(type); |
| 547 break; | 558 break; |
| 548 case TypeUseKind.CHECKED_MODE_CHECK: | 559 case TypeUseKind.CHECKED_MODE_CHECK: |
| 549 if (compiler.options.enableTypeAssertions) { | 560 if (options.enableTypeAssertions) { |
| 550 _registerIsCheck(type); | 561 _registerIsCheck(type); |
| 551 } | 562 } |
| 552 break; | 563 break; |
| 553 case TypeUseKind.TYPE_LITERAL: | 564 case TypeUseKind.TYPE_LITERAL: |
| 554 break; | 565 break; |
| 555 } | 566 } |
| 556 } | 567 } |
| 557 | 568 |
| 558 void _registerIsCheck(DartType type) { | 569 void _registerIsCheck(DartType type) { |
| 559 type = universe.registerIsCheck(type, compiler); | 570 type = universe.registerIsCheck(type, _compiler); |
| 560 // Even in checked mode, type annotations for return type and argument | 571 // Even in checked mode, type annotations for return type and argument |
| 561 // types do not imply type checks, so there should never be a check | 572 // types do not imply type checks, so there should never be a check |
| 562 // against the type variable of a typedef. | 573 // against the type variable of a typedef. |
| 563 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 574 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
| 564 } | 575 } |
| 565 | 576 |
| 566 void registerCallMethodWithFreeTypeVariables(Element element) { | 577 void registerCallMethodWithFreeTypeVariables(Element element) { |
| 567 compiler.backend.registerCallMethodWithFreeTypeVariables( | 578 backend.registerCallMethodWithFreeTypeVariables( |
| 568 element, this, compiler.globalDependencies); | 579 element, this, globalDependencies); |
| 569 universe.callMethodsWithFreeTypeVariables.add(element); | 580 universe.callMethodsWithFreeTypeVariables.add(element); |
| 570 } | 581 } |
| 571 | 582 |
| 572 void registerClosurizedMember(TypedElement element) { | 583 void registerClosurizedMember(TypedElement element) { |
| 573 assert(element.isInstanceMember); | 584 assert(element.isInstanceMember); |
| 574 if (element.computeType(resolution).containsTypeVariables) { | 585 if (element.type.containsTypeVariables) { |
| 575 compiler.backend.registerClosureWithFreeTypeVariables( | 586 backend.registerClosureWithFreeTypeVariables( |
| 576 element, this, compiler.globalDependencies); | 587 element, this, globalDependencies); |
| 577 } | 588 } |
| 578 compiler.backend.registerBoundClosure(this); | 589 backend.registerBoundClosure(this); |
| 579 universe.closurizedMembers.add(element); | 590 universe.closurizedMembers.add(element); |
| 580 } | 591 } |
| 581 | 592 |
| 582 void forEach(void f(WorkItem work)) { | 593 void forEach(void f(WorkItem work)) { |
| 583 do { | 594 do { |
| 584 while (queue.isNotEmpty) { | 595 while (queue.isNotEmpty) { |
| 585 // TODO(johnniwinther): Find an optimal process order. | 596 // TODO(johnniwinther): Find an optimal process order. |
| 586 filter.processWorkItem(f, queue.removeLast()); | 597 filter.processWorkItem(f, queue.removeLast()); |
| 587 } | 598 } |
| 588 List recents = recentClasses.toList(growable: false); | 599 List recents = recentClasses.toList(growable: false); |
| 589 recentClasses.clear(); | 600 recentClasses.clear(); |
| 590 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); | 601 if (!onQueueEmpty(recents)) recentClasses.addAll(recents); |
| 591 } while (queue.isNotEmpty || recentClasses.isNotEmpty); | 602 } while (queue.isNotEmpty || recentClasses.isNotEmpty); |
| 592 } | 603 } |
| 593 | 604 |
| 594 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] | 605 /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
| 595 /// contains the set of all classes seen for the first time since | 606 /// contains the set of all classes seen for the first time since |
| 596 /// [onQueueEmpty] was called last. A return value of [true] indicates that | 607 /// [onQueueEmpty] was called last. A return value of [true] indicates that |
| 597 /// the [recentClasses] have been processed and may be cleared. If [false] is | 608 /// the [recentClasses] have been processed and may be cleared. If [false] is |
| 598 /// returned, [onQueueEmpty] will be called once the queue is empty again (or | 609 /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
| 599 /// still empty) and [recentClasses] will be a superset of the current value. | 610 /// still empty) and [recentClasses] will be a superset of the current value. |
| 600 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { | 611 bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
| 601 return compiler.backend.onQueueEmpty(this, recentClasses); | 612 return backend.onQueueEmpty(this, recentClasses); |
| 602 } | 613 } |
| 603 | 614 |
| 604 void logSummary(log(message)) { | 615 void logSummary(log(message)) { |
| 605 _logSpecificSummary(log); | 616 _logSpecificSummary(log); |
| 606 nativeEnqueuer.logSummary(log); | 617 nativeEnqueuer.logSummary(log); |
| 607 } | 618 } |
| 608 | 619 |
| 609 String toString() => 'Enqueuer($name)'; | 620 String toString() => 'Enqueuer($name)'; |
| 610 | 621 |
| 611 void _forgetElement(Element element) { | 622 void _forgetElement(Element element) { |
| 612 universe.forgetElement(element, compiler); | 623 universe.forgetElement(element, _compiler); |
| 613 _processedClasses.remove(element); | 624 _processedClasses.remove(element); |
| 614 instanceMembersByName[element.name]?.remove(element); | 625 instanceMembersByName[element.name]?.remove(element); |
| 615 instanceFunctionsByName[element.name]?.remove(element); | 626 instanceFunctionsByName[element.name]?.remove(element); |
| 616 } | 627 } |
| 617 | 628 |
| 618 final Queue<CodegenWorkItem> queue; | 629 final Queue<CodegenWorkItem> queue; |
| 619 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; | 630 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
| 620 | 631 |
| 621 final Set<Element> newlyEnqueuedElements; | 632 final Set<Element> newlyEnqueuedElements; |
| 622 | 633 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 634 | 645 |
| 635 /** | 646 /** |
| 636 * Decides whether an element should be included to satisfy requirements | 647 * Decides whether an element should be included to satisfy requirements |
| 637 * of the mirror system. | 648 * of the mirror system. |
| 638 * | 649 * |
| 639 * For code generation, we rely on the precomputed set of elements that takes | 650 * For code generation, we rely on the precomputed set of elements that takes |
| 640 * subtyping constraints into account. | 651 * subtyping constraints into account. |
| 641 */ | 652 */ |
| 642 bool shouldIncludeElementDueToMirrors(Element element, | 653 bool shouldIncludeElementDueToMirrors(Element element, |
| 643 {bool includedEnclosing}) { | 654 {bool includedEnclosing}) { |
| 644 return compiler.backend.isAccessibleByReflection(element); | 655 return backend.isAccessibleByReflection(element); |
| 645 } | |
| 646 | |
| 647 /** | |
| 648 * Adds [element] to the work list if it has not already been processed. | |
| 649 * | |
| 650 * Returns [true] if the element was actually added to the queue. | |
| 651 */ | |
| 652 bool internalAddToWorkList(Element element) { | |
| 653 // Don't generate code for foreign elements. | |
| 654 if (compiler.backend.isForeign(element)) return false; | |
| 655 | |
| 656 // Codegen inlines field initializers. It only needs to generate | |
| 657 // code for checked setters. | |
| 658 if (element.isField && element.isInstanceMember) { | |
| 659 if (!compiler.options.enableTypeAssertions || | |
| 660 element.enclosingElement.isClosure) { | |
| 661 return false; | |
| 662 } | |
| 663 } | |
| 664 | |
| 665 if (compiler.options.hasIncrementalSupport && !isProcessed(element)) { | |
| 666 newlyEnqueuedElements.add(element); | |
| 667 } | |
| 668 | |
| 669 if (queueIsClosed) { | |
| 670 throw new SpannableAssertionFailure( | |
| 671 element, "Codegen work list is closed. Trying to add $element"); | |
| 672 } | |
| 673 queue.add(new CodegenWorkItem(compiler, element)); | |
| 674 return true; | |
| 675 } | 656 } |
| 676 | 657 |
| 677 void registerNoSuchMethod(Element element) { | 658 void registerNoSuchMethod(Element element) { |
| 678 if (!enabledNoSuchMethod && compiler.backend.enabledNoSuchMethod) { | 659 if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) { |
| 679 compiler.backend.enableNoSuchMethod(this); | 660 backend.enableNoSuchMethod(this); |
| 680 enabledNoSuchMethod = true; | 661 enabledNoSuchMethod = true; |
| 681 } | 662 } |
| 682 } | 663 } |
| 683 | 664 |
| 684 void _logSpecificSummary(log(message)) { | 665 void _logSpecificSummary(log(message)) { |
| 685 log('Compiled ${generatedCode.length} methods.'); | 666 log('Compiled ${generatedCode.length} methods.'); |
| 686 } | 667 } |
| 687 | 668 |
| 688 void forgetElement(Element element) { | 669 void forgetElement(Element element) { |
| 689 _forgetElement(element); | 670 _forgetElement(element); |
| 690 generatedCode.remove(element); | 671 generatedCode.remove(element); |
| 691 if (element is MemberElement) { | 672 if (element is MemberElement) { |
| 692 for (Element closure in element.nestedClosures) { | 673 for (Element closure in element.nestedClosures) { |
| 693 generatedCode.remove(closure); | 674 generatedCode.remove(closure); |
| 694 removeFromSet(instanceMembersByName, closure); | 675 removeFromSet(instanceMembersByName, closure); |
| 695 removeFromSet(instanceFunctionsByName, closure); | 676 removeFromSet(instanceFunctionsByName, closure); |
| 696 } | 677 } |
| 697 } | 678 } |
| 698 } | 679 } |
| 699 | 680 |
| 700 void handleUnseenSelector(DynamicUse dynamicUse) { | 681 void handleUnseenSelector(DynamicUse dynamicUse) { |
| 701 if (compiler.options.hasIncrementalSupport) { | 682 if (options.hasIncrementalSupport) { |
| 702 newlySeenSelectors.add(dynamicUse); | 683 newlySeenSelectors.add(dynamicUse); |
| 703 } | 684 } |
| 704 _handleUnseenSelector(dynamicUse); | 685 _handleUnseenSelector(dynamicUse); |
| 705 } | 686 } |
| 706 | 687 |
| 707 @override | 688 @override |
| 708 Iterable<Entity> get processedEntities => generatedCode.keys; | 689 Iterable<Entity> get processedEntities => generatedCode.keys; |
| 709 } | 690 } |
| 710 | 691 |
| 711 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 692 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 727 @override | 708 @override |
| 728 void visitStaticUse(StaticUse staticUse) { | 709 void visitStaticUse(StaticUse staticUse) { |
| 729 enqueuer.registerStaticUse(staticUse); | 710 enqueuer.registerStaticUse(staticUse); |
| 730 } | 711 } |
| 731 | 712 |
| 732 @override | 713 @override |
| 733 void visitTypeUse(TypeUse typeUse) { | 714 void visitTypeUse(TypeUse typeUse) { |
| 734 enqueuer.registerTypeUse(typeUse); | 715 enqueuer.registerTypeUse(typeUse); |
| 735 } | 716 } |
| 736 } | 717 } |
| OLD | NEW |