| 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 '../cache_strategy.dart' show CacheStrategy; | 9 import '../cache_strategy.dart' show CacheStrategy; |
| 10 import '../common/backend_api.dart' show Backend; | 10 import '../common/backend_api.dart' show Backend; |
| 11 import '../common/codegen.dart' show CodegenWorkItem; | 11 import '../common/codegen.dart' show CodegenWorkItem; |
| 12 import '../common/names.dart' show Identifiers; | |
| 13 import '../common/tasks.dart' show CompilerTask; | 12 import '../common/tasks.dart' show CompilerTask; |
| 14 import '../common/work.dart' show WorkItem; | 13 import '../common/work.dart' show WorkItem; |
| 15 import '../common.dart'; | 14 import '../common.dart'; |
| 16 import '../compiler.dart' show Compiler; | 15 import '../compiler.dart' show Compiler; |
| 17 import '../dart_types.dart' show DartType, InterfaceType; | 16 import '../dart_types.dart' show DartType, InterfaceType; |
| 18 import '../dump_info.dart'; | |
| 19 import '../elements/elements.dart' | 17 import '../elements/elements.dart' |
| 20 show | 18 show ClassElement, Element, Entity, MemberElement, TypedElement; |
| 21 ClassElement, | |
| 22 Element, | |
| 23 Entity, | |
| 24 FunctionElement, | |
| 25 MemberElement, | |
| 26 MethodElement, | |
| 27 TypedElement; | |
| 28 import '../elements/entities.dart'; | 19 import '../elements/entities.dart'; |
| 29 import '../enqueue.dart'; | 20 import '../enqueue.dart'; |
| 30 import '../js/js.dart' as js; | 21 import '../js/js.dart' as js; |
| 31 import '../native/native.dart' as native; | 22 import '../native/native.dart' as native; |
| 32 import '../options.dart'; | 23 import '../options.dart'; |
| 33 import '../types/types.dart' show TypeMaskStrategy; | 24 import '../types/types.dart' show TypeMaskStrategy; |
| 34 import '../universe/selector.dart' show Selector; | |
| 35 import '../universe/world_builder.dart'; | 25 import '../universe/world_builder.dart'; |
| 36 import '../universe/use.dart' | 26 import '../universe/use.dart' |
| 37 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; | 27 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
| 38 import '../universe/world_impact.dart' | 28 import '../universe/world_impact.dart' |
| 39 show ImpactUseCase, WorldImpact, WorldImpactVisitor; | 29 show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
| 30 import '../util/enumset.dart'; |
| 40 import '../util/util.dart' show Setlet; | 31 import '../util/util.dart' show Setlet; |
| 41 import '../world.dart'; | |
| 42 | 32 |
| 43 /// [Enqueuer] which is specific to code generation. | 33 /// [Enqueuer] which is specific to code generation. |
| 44 class CodegenEnqueuer extends EnqueuerImpl { | 34 class CodegenEnqueuer extends EnqueuerImpl { |
| 45 final String name; | 35 final String name; |
| 46 final EnqueuerStrategy strategy; | 36 final EnqueuerStrategy strategy; |
| 47 final Map<String, Set<Element>> _instanceMembersByName = | 37 |
| 48 new Map<String, Set<Element>>(); | |
| 49 final Map<String, Set<Element>> _instanceFunctionsByName = | |
| 50 new Map<String, Set<Element>>(); | |
| 51 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | |
| 52 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); | 38 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); |
| 53 final CodegenWorldBuilderImpl _universe = | 39 final CodegenWorldBuilderImpl _universe; |
| 54 new CodegenWorldBuilderImpl(const TypeMaskStrategy()); | |
| 55 | 40 |
| 56 bool queueIsClosed = false; | 41 bool queueIsClosed = false; |
| 57 final CompilerTask task; | 42 final CompilerTask task; |
| 58 final native.NativeEnqueuer nativeEnqueuer; | 43 final native.NativeEnqueuer nativeEnqueuer; |
| 59 final Backend _backend; | 44 final Backend _backend; |
| 60 final CompilerOptions _options; | 45 final CompilerOptions _options; |
| 61 | 46 |
| 62 WorldImpactVisitor _impactVisitor; | 47 WorldImpactVisitor _impactVisitor; |
| 63 | 48 |
| 64 final Queue<WorkItem> _queue = new Queue<WorkItem>(); | 49 final Queue<WorkItem> _queue = new Queue<WorkItem>(); |
| 65 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; | 50 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{}; |
| 66 | 51 |
| 67 final Set<Element> newlyEnqueuedElements; | 52 final Set<Element> newlyEnqueuedElements; |
| 68 | 53 |
| 69 final Set<DynamicUse> newlySeenSelectors; | 54 final Set<DynamicUse> newlySeenSelectors; |
| 70 | 55 |
| 71 bool _enabledNoSuchMethod = false; | |
| 72 | |
| 73 static const ImpactUseCase IMPACT_USE = | 56 static const ImpactUseCase IMPACT_USE = |
| 74 const ImpactUseCase('CodegenEnqueuer'); | 57 const ImpactUseCase('CodegenEnqueuer'); |
| 75 | 58 |
| 76 CodegenEnqueuer(this.task, CacheStrategy cacheStrategy, Backend backend, | 59 CodegenEnqueuer(this.task, CacheStrategy cacheStrategy, Backend backend, |
| 77 this._options, this.strategy) | 60 this._options, this.strategy) |
| 78 : newlyEnqueuedElements = cacheStrategy.newSet(), | 61 : _universe = |
| 62 new CodegenWorldBuilderImpl(backend, const TypeMaskStrategy()), |
| 63 newlyEnqueuedElements = cacheStrategy.newSet(), |
| 79 newlySeenSelectors = cacheStrategy.newSet(), | 64 newlySeenSelectors = cacheStrategy.newSet(), |
| 80 nativeEnqueuer = backend.nativeCodegenEnqueuer(), | 65 nativeEnqueuer = backend.nativeCodegenEnqueuer(), |
| 81 this._backend = backend, | 66 this._backend = backend, |
| 82 this.name = 'codegen enqueuer' { | 67 this.name = 'codegen enqueuer' { |
| 83 _impactVisitor = new EnqueuerImplImpactVisitor(this); | 68 _impactVisitor = new EnqueuerImplImpactVisitor(this); |
| 84 } | 69 } |
| 85 | 70 |
| 86 CodegenWorldBuilder get universe => _universe; | 71 CodegenWorldBuilder get universe => _universe; |
| 87 | 72 |
| 88 // TODO(johnniwinther): Remove these hacks: | |
| 89 ClosedWorld get _world => _backend.compiler.closedWorld; | |
| 90 DumpInfoTask get _dumpInfoTask => _backend.compiler.dumpInfoTask; | |
| 91 | |
| 92 bool get queueIsEmpty => _queue.isEmpty; | 73 bool get queueIsEmpty => _queue.isEmpty; |
| 93 | 74 |
| 94 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 75 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 95 bool get isResolutionQueue => false; | 76 bool get isResolutionQueue => false; |
| 96 | 77 |
| 97 /** | 78 /** |
| 98 * Documentation wanted -- johnniwinther | 79 * Documentation wanted -- johnniwinther |
| 99 * | 80 * |
| 100 * Invariant: [element] must be a declaration element. | 81 * Invariant: [element] must be a declaration element. |
| 101 */ | 82 */ |
| (...skipping 13 matching lines...) Expand all Loading... |
| 115 | 96 |
| 116 if (_options.hasIncrementalSupport && !isProcessed(element)) { | 97 if (_options.hasIncrementalSupport && !isProcessed(element)) { |
| 117 newlyEnqueuedElements.add(element); | 98 newlyEnqueuedElements.add(element); |
| 118 } | 99 } |
| 119 | 100 |
| 120 if (queueIsClosed) { | 101 if (queueIsClosed) { |
| 121 throw new SpannableAssertionFailure( | 102 throw new SpannableAssertionFailure( |
| 122 element, "Codegen work list is closed. Trying to add $element"); | 103 element, "Codegen work list is closed. Trying to add $element"); |
| 123 } | 104 } |
| 124 _queue.add(new CodegenWorkItem(_backend, element)); | 105 _queue.add(new CodegenWorkItem(_backend, element)); |
| 125 // TODO(sigmund): add other missing dependencies (internals, selectors | 106 applyImpact(_backend.registerUsedElement(element, forResolution: false)); |
| 126 // enqueued after allocations). | |
| 127 _dumpInfoTask.registerDependency(element); | |
| 128 } | 107 } |
| 129 | 108 |
| 130 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { | 109 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
| 131 if (worldImpact.isEmpty) return; | 110 if (worldImpact.isEmpty) return; |
| 132 impactStrategy.visitImpact( | 111 impactStrategy.visitImpact( |
| 133 impactSource, worldImpact, _impactVisitor, impactUse); | 112 impactSource, worldImpact, _impactVisitor, impactUse); |
| 134 } | 113 } |
| 135 | 114 |
| 136 void _registerInstantiatedType(InterfaceType type, | 115 void _registerInstantiatedType(InterfaceType type, |
| 137 {bool mirrorUsage: false, bool nativeUsage: false}) { | 116 {bool mirrorUsage: false, bool nativeUsage: false}) { |
| 138 task.measure(() { | 117 task.measure(() { |
| 139 ClassElement cls = type.element; | 118 _universe.registerTypeInstantiation(type, _applyClassUse, |
| 140 bool isNative = _backend.isNative(cls); | 119 byMirrors: mirrorUsage); |
| 141 _universe.registerTypeInstantiation(type, | |
| 142 isNative: isNative, | |
| 143 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { | |
| 144 applyImpact( | |
| 145 _backend.registerImplementedClass(cls, forResolution: false)); | |
| 146 }); | |
| 147 if (nativeUsage) { | 120 if (nativeUsage) { |
| 148 nativeEnqueuer.onInstantiatedType(type); | 121 nativeEnqueuer.onInstantiatedType(type); |
| 149 } | 122 } |
| 150 _backend.registerInstantiatedType(type); | 123 _backend.registerInstantiatedType(type); |
| 151 // TODO(johnniwinther): Share this reasoning with [Universe]. | |
| 152 if (!cls.isAbstract || isNative || mirrorUsage) { | |
| 153 _processInstantiatedClass(cls); | |
| 154 } | |
| 155 }); | 124 }); |
| 156 } | 125 } |
| 157 | 126 |
| 158 bool checkNoEnqueuedInvokedInstanceMethods() { | 127 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 159 return strategy.checkEnqueuerConsistency(this); | 128 return strategy.checkEnqueuerConsistency(this); |
| 160 } | 129 } |
| 161 | 130 |
| 162 void checkClass(ClassElement cls) { | 131 void checkClass(ClassElement cls) { |
| 163 cls.implementation.forEachMember(processInstantiatedClassMember); | 132 _universe.processClassMembers(cls, (MemberElement member, useSet) { |
| 164 } | 133 if (useSet.isNotEmpty) { |
| 165 | 134 _backend.compiler.reporter.internalError(member, |
| 166 void processInstantiatedClassMember(ClassElement cls, Element member) { | 135 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); |
| 167 assert(invariant(member, member.isDeclaration)); | |
| 168 if (isProcessed(member)) return; | |
| 169 if (!member.isInstanceMember) return; | |
| 170 String memberName = member.name; | |
| 171 | |
| 172 if (member.isField) { | |
| 173 // The obvious thing to test here would be "member.isNative", | |
| 174 // however, that only works after metadata has been parsed/analyzed, | |
| 175 // and that may not have happened yet. | |
| 176 // So instead we use the enclosing class, which we know have had | |
| 177 // its metadata parsed and analyzed. | |
| 178 // Note: this assumes that there are no non-native fields on native | |
| 179 // classes, which may not be the case when a native class is subclassed. | |
| 180 if (_backend.isNative(cls)) { | |
| 181 if (_universe.hasInvokedGetter(member, _world) || | |
| 182 _universe.hasInvocation(member, _world)) { | |
| 183 _addToWorkList(member); | |
| 184 return; | |
| 185 } else if (universe.hasInvokedSetter(member, _world)) { | |
| 186 _addToWorkList(member); | |
| 187 return; | |
| 188 } | |
| 189 // Native fields need to go into instanceMembersByName as they | |
| 190 // are virtual instantiation points and escape points. | |
| 191 } else { | |
| 192 // All field initializers must be resolved as they could | |
| 193 // have an observable side-effect (and cannot be tree-shaken | |
| 194 // away). | |
| 195 _addToWorkList(member); | |
| 196 return; | |
| 197 } | |
| 198 } else if (member.isFunction) { | |
| 199 FunctionElement function = member; | |
| 200 if (function.name == Identifiers.noSuchMethod_) { | |
| 201 _registerNoSuchMethod(function); | |
| 202 } | |
| 203 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | |
| 204 _registerCallMethodWithFreeTypeVariables(function); | |
| 205 } | |
| 206 // If there is a property access with the same name as a method we | |
| 207 // need to emit the method. | |
| 208 if (_universe.hasInvokedGetter(function, _world)) { | |
| 209 _registerClosurizedMember(function); | |
| 210 _addToWorkList(function); | |
| 211 return; | |
| 212 } | |
| 213 _registerInstanceMethod(function); | |
| 214 if (_universe.hasInvocation(function, _world)) { | |
| 215 _addToWorkList(function); | |
| 216 return; | |
| 217 } | |
| 218 } else if (member.isGetter) { | |
| 219 FunctionElement getter = member; | |
| 220 if (_universe.hasInvokedGetter(getter, _world)) { | |
| 221 _addToWorkList(getter); | |
| 222 return; | |
| 223 } | |
| 224 // We don't know what selectors the returned closure accepts. If | |
| 225 // the set contains any selector we have to assume that it matches. | |
| 226 if (_universe.hasInvocation(getter, _world)) { | |
| 227 _addToWorkList(getter); | |
| 228 return; | |
| 229 } | |
| 230 } else if (member.isSetter) { | |
| 231 FunctionElement setter = member; | |
| 232 if (_universe.hasInvokedSetter(setter, _world)) { | |
| 233 _addToWorkList(setter); | |
| 234 return; | |
| 235 } | |
| 236 } | |
| 237 | |
| 238 // The element is not yet used. Add it to the list of instance | |
| 239 // members to still be processed. | |
| 240 _instanceMembersByName | |
| 241 .putIfAbsent(memberName, () => new Set<Element>()) | |
| 242 .add(member); | |
| 243 } | |
| 244 | |
| 245 // Store the member in [instanceFunctionsByName] to catch | |
| 246 // getters on the function. | |
| 247 void _registerInstanceMethod(MethodElement element) { | |
| 248 _instanceFunctionsByName | |
| 249 .putIfAbsent(element.name, () => new Set<Element>()) | |
| 250 .add(element); | |
| 251 } | |
| 252 | |
| 253 void _processInstantiatedClass(ClassElement cls) { | |
| 254 task.measure(() { | |
| 255 if (_processedClasses.contains(cls)) return; | |
| 256 | |
| 257 void processClass(ClassElement superclass) { | |
| 258 if (_processedClasses.contains(superclass)) return; | |
| 259 // TODO(johnniwinther): Re-insert this invariant when unittests don't | |
| 260 // fail. There is already a similar invariant on the members. | |
| 261 /*assert(invariant(superclass, | |
| 262 superclass.isClosure || | |
| 263 _compiler.enqueuer.resolution.isClassProcessed(superclass), | |
| 264 message: "Class $superclass has not been " | |
| 265 "processed in resolution.")); | |
| 266 */ | |
| 267 | |
| 268 _processedClasses.add(superclass); | |
| 269 _recentClasses.add(superclass); | |
| 270 superclass.implementation.forEachMember(processInstantiatedClassMember); | |
| 271 // We only tell the backend once that [superclass] was instantiated, so | |
| 272 // any additional dependencies must be treated as global | |
| 273 // dependencies. | |
| 274 applyImpact(_backend.registerInstantiatedClass(superclass, | |
| 275 forResolution: false)); | |
| 276 } | |
| 277 | |
| 278 ClassElement superclass = cls; | |
| 279 while (superclass != null) { | |
| 280 processClass(superclass); | |
| 281 superclass = superclass.superclass; | |
| 282 } | 136 } |
| 283 }); | 137 }); |
| 284 } | 138 } |
| 285 | 139 |
| 140 /// Callback for applying the use of a [cls]. |
| 141 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { |
| 142 if (useSet.contains(ClassUse.INSTANTIATED)) { |
| 143 _recentClasses.add(cls); |
| 144 _universe.processClassMembers(cls, _applyMemberUse); |
| 145 // We only tell the backend once that [cls] was instantiated, so |
| 146 // any additional dependencies must be treated as global |
| 147 // dependencies. |
| 148 applyImpact( |
| 149 _backend.registerInstantiatedClass(cls, forResolution: false)); |
| 150 } |
| 151 if (useSet.contains(ClassUse.IMPLEMENTED)) { |
| 152 applyImpact(_backend.registerImplementedClass(cls, forResolution: false)); |
| 153 } |
| 154 } |
| 155 |
| 156 /// Callback for applying the use of a [member]. |
| 157 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { |
| 158 if (useSet.contains(MemberUse.NORMAL)) { |
| 159 _addToWorkList(member); |
| 160 } |
| 161 if (useSet.contains(MemberUse.CLOSURIZE_INSTANCE)) { |
| 162 _registerClosurizedMember(member); |
| 163 } |
| 164 if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) { |
| 165 applyImpact(_backend.registerGetOfStaticFunction()); |
| 166 } |
| 167 } |
| 168 |
| 286 void processDynamicUse(DynamicUse dynamicUse) { | 169 void processDynamicUse(DynamicUse dynamicUse) { |
| 287 task.measure(() { | 170 task.measure(() { |
| 288 if (_universe.registerDynamicUse(dynamicUse)) { | 171 if (_universe.registerDynamicUse(dynamicUse, _applyMemberUse)) { |
| 289 _handleUnseenSelector(dynamicUse); | 172 if (_options.hasIncrementalSupport) { |
| 173 newlySeenSelectors.add(dynamicUse); |
| 174 } |
| 290 } | 175 } |
| 291 }); | 176 }); |
| 292 } | 177 } |
| 293 | 178 |
| 294 void _processSet( | |
| 295 Map<String, Set<Element>> map, String memberName, bool f(Element e)) { | |
| 296 Set<Element> members = map[memberName]; | |
| 297 if (members == null) return; | |
| 298 // [f] might add elements to [: map[memberName] :] during the loop below | |
| 299 // so we create a new list for [: map[memberName] :] and prepend the | |
| 300 // [remaining] members after the loop. | |
| 301 map[memberName] = new Set<Element>(); | |
| 302 Set<Element> remaining = new Set<Element>(); | |
| 303 for (Element member in members) { | |
| 304 if (!f(member)) remaining.add(member); | |
| 305 } | |
| 306 map[memberName].addAll(remaining); | |
| 307 } | |
| 308 | |
| 309 void _processInstanceMembers(String n, bool f(Element e)) { | |
| 310 _processSet(_instanceMembersByName, n, f); | |
| 311 } | |
| 312 | |
| 313 void _processInstanceFunctions(String n, bool f(Element e)) { | |
| 314 _processSet(_instanceFunctionsByName, n, f); | |
| 315 } | |
| 316 | |
| 317 void _handleUnseenSelector(DynamicUse dynamicUse) { | |
| 318 if (_options.hasIncrementalSupport) { | |
| 319 newlySeenSelectors.add(dynamicUse); | |
| 320 } | |
| 321 Selector selector = dynamicUse.selector; | |
| 322 String methodName = selector.name; | |
| 323 _processInstanceMembers(methodName, (Element member) { | |
| 324 if (dynamicUse.appliesUnnamed(member, _world)) { | |
| 325 if (member.isFunction && selector.isGetter) { | |
| 326 _registerClosurizedMember(member); | |
| 327 } | |
| 328 _addToWorkList(member); | |
| 329 return true; | |
| 330 } | |
| 331 return false; | |
| 332 }); | |
| 333 if (selector.isGetter) { | |
| 334 _processInstanceFunctions(methodName, (Element member) { | |
| 335 if (dynamicUse.appliesUnnamed(member, _world)) { | |
| 336 _registerClosurizedMember(member); | |
| 337 return true; | |
| 338 } | |
| 339 return false; | |
| 340 }); | |
| 341 } | |
| 342 } | |
| 343 | |
| 344 void processStaticUse(StaticUse staticUse) { | 179 void processStaticUse(StaticUse staticUse) { |
| 345 Element element = staticUse.element; | 180 Element element = staticUse.element; |
| 346 assert(invariant(element, element.isDeclaration, | 181 assert(invariant(element, element.isDeclaration, |
| 347 message: "Element ${element} is not the declaration.")); | 182 message: "Element ${element} is not the declaration.")); |
| 348 _universe.registerStaticUse(staticUse); | 183 _universe.registerStaticUse(staticUse, _applyMemberUse); |
| 349 applyImpact(_backend.registerUsedElement(element, forResolution: false)); | |
| 350 bool addElement = true; | |
| 351 switch (staticUse.kind) { | 184 switch (staticUse.kind) { |
| 352 case StaticUseKind.STATIC_TEAR_OFF: | |
| 353 applyImpact(_backend.registerGetOfStaticFunction()); | |
| 354 break; | |
| 355 case StaticUseKind.FIELD_GET: | |
| 356 case StaticUseKind.FIELD_SET: | |
| 357 case StaticUseKind.CLOSURE: | |
| 358 // TODO(johnniwinther): Avoid this. Currently [FIELD_GET] and | |
| 359 // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue. | |
| 360 // Also [CLOSURE] contains [LocalFunctionElement] which we cannot | |
| 361 // enqueue. | |
| 362 addElement = false; | |
| 363 break; | |
| 364 case StaticUseKind.SUPER_FIELD_SET: | |
| 365 case StaticUseKind.SUPER_TEAR_OFF: | |
| 366 case StaticUseKind.GENERAL: | |
| 367 case StaticUseKind.DIRECT_USE: | |
| 368 break; | |
| 369 case StaticUseKind.CONSTRUCTOR_INVOKE: | 185 case StaticUseKind.CONSTRUCTOR_INVOKE: |
| 370 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: | 186 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: |
| 371 case StaticUseKind.REDIRECTION: | 187 case StaticUseKind.REDIRECTION: |
| 372 processTypeUse(new TypeUse.instantiation(staticUse.type)); | 188 processTypeUse(new TypeUse.instantiation(staticUse.type)); |
| 373 break; | 189 break; |
| 374 case StaticUseKind.DIRECT_INVOKE: | 190 default: |
| 375 _registerInstanceMethod(staticUse.element); | |
| 376 break; | 191 break; |
| 377 } | 192 } |
| 378 if (addElement) { | |
| 379 _addToWorkList(element); | |
| 380 } | |
| 381 } | 193 } |
| 382 | 194 |
| 383 void processTypeUse(TypeUse typeUse) { | 195 void processTypeUse(TypeUse typeUse) { |
| 384 DartType type = typeUse.type; | 196 DartType type = typeUse.type; |
| 385 switch (typeUse.kind) { | 197 switch (typeUse.kind) { |
| 386 case TypeUseKind.INSTANTIATION: | 198 case TypeUseKind.INSTANTIATION: |
| 387 _registerInstantiatedType(type); | 199 _registerInstantiatedType(type); |
| 388 break; | 200 break; |
| 389 case TypeUseKind.MIRROR_INSTANTIATION: | 201 case TypeUseKind.MIRROR_INSTANTIATION: |
| 390 _registerInstantiatedType(type, mirrorUsage: true); | 202 _registerInstantiatedType(type, mirrorUsage: true); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 408 } | 220 } |
| 409 | 221 |
| 410 void _registerIsCheck(DartType type) { | 222 void _registerIsCheck(DartType type) { |
| 411 type = _universe.registerIsCheck(type); | 223 type = _universe.registerIsCheck(type); |
| 412 // Even in checked mode, type annotations for return type and argument | 224 // Even in checked mode, type annotations for return type and argument |
| 413 // types do not imply type checks, so there should never be a check | 225 // types do not imply type checks, so there should never be a check |
| 414 // against the type variable of a typedef. | 226 // against the type variable of a typedef. |
| 415 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); | 227 assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef); |
| 416 } | 228 } |
| 417 | 229 |
| 418 void _registerCallMethodWithFreeTypeVariables(Element element) { | |
| 419 applyImpact(_backend.registerCallMethodWithFreeTypeVariables(element, | |
| 420 forResolution: false)); | |
| 421 } | |
| 422 | |
| 423 void _registerClosurizedMember(TypedElement element) { | 230 void _registerClosurizedMember(TypedElement element) { |
| 424 assert(element.isInstanceMember); | 231 assert(element.isInstanceMember); |
| 425 if (element.type.containsTypeVariables) { | 232 if (element.type.containsTypeVariables) { |
| 426 applyImpact(_backend.registerClosureWithFreeTypeVariables(element, | 233 applyImpact(_backend.registerClosureWithFreeTypeVariables(element, |
| 427 forResolution: false)); | 234 forResolution: false)); |
| 428 } | 235 } |
| 429 applyImpact(_backend.registerBoundClosure()); | 236 applyImpact(_backend.registerBoundClosure()); |
| 430 } | 237 } |
| 431 | 238 |
| 432 void forEach(void f(WorkItem work)) { | 239 void forEach(void f(WorkItem work)) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 461 nativeEnqueuer.logSummary(log); | 268 nativeEnqueuer.logSummary(log); |
| 462 } | 269 } |
| 463 | 270 |
| 464 String toString() => 'Enqueuer($name)'; | 271 String toString() => 'Enqueuer($name)'; |
| 465 | 272 |
| 466 ImpactUseCase get impactUse => IMPACT_USE; | 273 ImpactUseCase get impactUse => IMPACT_USE; |
| 467 | 274 |
| 468 bool isProcessed(Element member) => | 275 bool isProcessed(Element member) => |
| 469 member.isAbstract || generatedCode.containsKey(member); | 276 member.isAbstract || generatedCode.containsKey(member); |
| 470 | 277 |
| 471 void _registerNoSuchMethod(Element element) { | |
| 472 if (!_enabledNoSuchMethod && _backend.enabledNoSuchMethod) { | |
| 473 applyImpact(_backend.enableNoSuchMethod()); | |
| 474 _enabledNoSuchMethod = true; | |
| 475 } | |
| 476 } | |
| 477 | |
| 478 void forgetEntity(Element element, Compiler compiler) { | 278 void forgetEntity(Element element, Compiler compiler) { |
| 479 _universe.forgetElement(element, compiler); | 279 _universe.forgetElement(element, compiler); |
| 480 _processedClasses.remove(element); | |
| 481 _instanceMembersByName[element.name]?.remove(element); | |
| 482 _instanceFunctionsByName[element.name]?.remove(element); | |
| 483 generatedCode.remove(element); | 280 generatedCode.remove(element); |
| 484 if (element is MemberElement) { | 281 if (element is MemberElement) { |
| 485 for (Element closure in element.nestedClosures) { | 282 for (Element closure in element.nestedClosures) { |
| 486 generatedCode.remove(closure); | 283 generatedCode.remove(closure); |
| 487 removeFromSet(_instanceMembersByName, closure); | |
| 488 removeFromSet(_instanceFunctionsByName, closure); | |
| 489 } | 284 } |
| 490 } | 285 } |
| 491 } | 286 } |
| 492 | 287 |
| 493 @override | 288 @override |
| 494 Iterable<Entity> get processedEntities => generatedCode.keys; | 289 Iterable<Entity> get processedEntities => generatedCode.keys; |
| 495 | 290 |
| 496 @override | 291 @override |
| 497 Iterable<ClassEntity> get processedClasses => _processedClasses; | 292 Iterable<ClassEntity> get processedClasses => _universe.processedClasses; |
| 498 } | 293 } |
| 499 | |
| 500 void removeFromSet(Map<String, Set<Element>> map, Element element) { | |
| 501 Set<Element> set = map[element.name]; | |
| 502 if (set == null) return; | |
| 503 set.remove(element); | |
| 504 } | |
| OLD | NEW |