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.enqueue; | 5 library dart2js.enqueue; |
6 | 6 |
7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
8 | 8 |
9 import 'common/names.dart' show Identifiers; | 9 import 'common/names.dart' show Identifiers; |
10 import 'common/resolution.dart' show Resolution; | 10 import 'common/resolution.dart' show Resolution; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 220 |
221 if (member.isField) { | 221 if (member.isField) { |
222 // The obvious thing to test here would be "member.isNative", | 222 // The obvious thing to test here would be "member.isNative", |
223 // however, that only works after metadata has been parsed/analyzed, | 223 // however, that only works after metadata has been parsed/analyzed, |
224 // and that may not have happened yet. | 224 // and that may not have happened yet. |
225 // So instead we use the enclosing class, which we know have had | 225 // So instead we use the enclosing class, which we know have had |
226 // its metadata parsed and analyzed. | 226 // its metadata parsed and analyzed. |
227 // Note: this assumes that there are no non-native fields on native | 227 // Note: this assumes that there are no non-native fields on native |
228 // classes, which may not be the case when a native class is subclassed. | 228 // classes, which may not be the case when a native class is subclassed. |
229 if (compiler.backend.isNative(cls)) { | 229 if (compiler.backend.isNative(cls)) { |
230 compiler.world.registerUsedElement(member); | 230 compiler.openWorld.registerUsedElement(member); |
231 if (universe.hasInvokedGetter(member, compiler.world) || | 231 if (universe.hasInvokedGetter(member, compiler.openWorld) || |
232 universe.hasInvocation(member, compiler.world)) { | 232 universe.hasInvocation(member, compiler.openWorld)) { |
233 addToWorkList(member); | 233 addToWorkList(member); |
234 return; | 234 return; |
235 } | 235 } |
236 if (universe.hasInvokedSetter(member, compiler.world)) { | 236 if (universe.hasInvokedSetter(member, compiler.openWorld)) { |
237 addToWorkList(member); | 237 addToWorkList(member); |
238 return; | 238 return; |
239 } | 239 } |
240 // Native fields need to go into instanceMembersByName as they | 240 // Native fields need to go into instanceMembersByName as they |
241 // are virtual instantiation points and escape points. | 241 // are virtual instantiation points and escape points. |
242 } else { | 242 } else { |
243 // All field initializers must be resolved as they could | 243 // All field initializers must be resolved as they could |
244 // have an observable side-effect (and cannot be tree-shaken | 244 // have an observable side-effect (and cannot be tree-shaken |
245 // away). | 245 // away). |
246 addToWorkList(member); | 246 addToWorkList(member); |
247 return; | 247 return; |
248 } | 248 } |
249 } else if (member.isFunction) { | 249 } else if (member.isFunction) { |
250 FunctionElement function = member; | 250 FunctionElement function = member; |
251 function.computeType(resolution); | 251 function.computeType(resolution); |
252 if (function.name == Identifiers.noSuchMethod_) { | 252 if (function.name == Identifiers.noSuchMethod_) { |
253 registerNoSuchMethod(function); | 253 registerNoSuchMethod(function); |
254 } | 254 } |
255 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 255 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
256 registerCallMethodWithFreeTypeVariables(function); | 256 registerCallMethodWithFreeTypeVariables(function); |
257 } | 257 } |
258 // If there is a property access with the same name as a method we | 258 // If there is a property access with the same name as a method we |
259 // need to emit the method. | 259 // need to emit the method. |
260 if (universe.hasInvokedGetter(function, compiler.world)) { | 260 if (universe.hasInvokedGetter(function, compiler.openWorld)) { |
261 registerClosurizedMember(function); | 261 registerClosurizedMember(function); |
262 addToWorkList(function); | 262 addToWorkList(function); |
263 return; | 263 return; |
264 } | 264 } |
265 // Store the member in [instanceFunctionsByName] to catch | 265 // Store the member in [instanceFunctionsByName] to catch |
266 // getters on the function. | 266 // getters on the function. |
267 instanceFunctionsByName | 267 instanceFunctionsByName |
268 .putIfAbsent(memberName, () => new Set<Element>()) | 268 .putIfAbsent(memberName, () => new Set<Element>()) |
269 .add(member); | 269 .add(member); |
270 if (universe.hasInvocation(function, compiler.world)) { | 270 if (universe.hasInvocation(function, compiler.openWorld)) { |
271 addToWorkList(function); | 271 addToWorkList(function); |
272 return; | 272 return; |
273 } | 273 } |
274 } else if (member.isGetter) { | 274 } else if (member.isGetter) { |
275 FunctionElement getter = member; | 275 FunctionElement getter = member; |
276 getter.computeType(resolution); | 276 getter.computeType(resolution); |
277 if (universe.hasInvokedGetter(getter, compiler.world)) { | 277 if (universe.hasInvokedGetter(getter, compiler.openWorld)) { |
278 addToWorkList(getter); | 278 addToWorkList(getter); |
279 return; | 279 return; |
280 } | 280 } |
281 // We don't know what selectors the returned closure accepts. If | 281 // We don't know what selectors the returned closure accepts. If |
282 // the set contains any selector we have to assume that it matches. | 282 // the set contains any selector we have to assume that it matches. |
283 if (universe.hasInvocation(getter, compiler.world)) { | 283 if (universe.hasInvocation(getter, compiler.openWorld)) { |
284 addToWorkList(getter); | 284 addToWorkList(getter); |
285 return; | 285 return; |
286 } | 286 } |
287 } else if (member.isSetter) { | 287 } else if (member.isSetter) { |
288 FunctionElement setter = member; | 288 FunctionElement setter = member; |
289 setter.computeType(resolution); | 289 setter.computeType(resolution); |
290 if (universe.hasInvokedSetter(setter, compiler.world)) { | 290 if (universe.hasInvokedSetter(setter, compiler.openWorld)) { |
291 addToWorkList(setter); | 291 addToWorkList(setter); |
292 return; | 292 return; |
293 } | 293 } |
294 } | 294 } |
295 | 295 |
296 // The element is not yet used. Add it to the list of instance | 296 // The element is not yet used. Add it to the list of instance |
297 // members to still be processed. | 297 // members to still be processed. |
298 instanceMembersByName | 298 instanceMembersByName |
299 .putIfAbsent(memberName, () => new Set<Element>()) | 299 .putIfAbsent(memberName, () => new Set<Element>()) |
300 .add(member); | 300 .add(member); |
301 } | 301 } |
302 | 302 |
303 void processInstantiatedClass(ClassElement cls) { | 303 void processInstantiatedClass(ClassElement cls) { |
304 task.measure(() { | 304 task.measure(() { |
305 if (_processedClasses.contains(cls)) return; | 305 if (_processedClasses.contains(cls)) return; |
306 // The class must be resolved to compute the set of all | 306 // The class must be resolved to compute the set of all |
307 // supertypes. | 307 // supertypes. |
308 cls.ensureResolved(resolution); | 308 cls.ensureResolved(resolution); |
309 | 309 |
310 void processClass(ClassElement superclass) { | 310 void processClass(ClassElement superclass) { |
311 if (_processedClasses.contains(superclass)) return; | 311 if (_processedClasses.contains(superclass)) return; |
312 // TODO(johnniwinther): Re-insert this invariant when unittests don't | |
313 // fail. There is already a similar invariant on the members. | |
314 /*if (!isResolutionQueue) { | |
315 assert(invariant(superclass, | |
316 superclass.isClosure || | |
317 compiler.enqueuer.resolution.isClassProcessed(superclass), | |
318 message: "Class $superclass has not been " | |
319 "processed in resolution.")); | |
320 }*/ | |
321 | 312 |
322 _processedClasses.add(superclass); | 313 _processedClasses.add(superclass); |
323 recentClasses.add(superclass); | 314 recentClasses.add(superclass); |
324 superclass.ensureResolved(resolution); | 315 superclass.ensureResolved(resolution); |
325 superclass.implementation.forEachMember(processInstantiatedClassMember); | 316 superclass.implementation.forEachMember(processInstantiatedClassMember); |
326 if (isResolutionQueue && | 317 if (!compiler.serialization.isDeserialized(superclass)) { |
327 !compiler.serialization.isDeserialized(superclass)) { | |
328 compiler.resolver.checkClass(superclass); | 318 compiler.resolver.checkClass(superclass); |
329 } | 319 } |
330 // We only tell the backend once that [superclass] was instantiated, so | 320 // We only tell the backend once that [superclass] was instantiated, so |
331 // any additional dependencies must be treated as global | 321 // any additional dependencies must be treated as global |
332 // dependencies. | 322 // dependencies. |
333 compiler.backend.registerInstantiatedClass( | 323 compiler.backend.registerInstantiatedClass( |
334 superclass, this, compiler.globalDependencies); | 324 superclass, this, compiler.globalDependencies); |
335 } | 325 } |
336 | 326 |
337 ClassElement superclass = cls; | 327 ClassElement superclass = cls; |
338 while (superclass != null) { | 328 while (superclass != null) { |
339 processClass(superclass); | 329 processClass(superclass); |
340 superclass = superclass.superclass; | 330 superclass = superclass.superclass; |
341 } | 331 } |
342 }); | 332 }); |
343 } | 333 } |
344 | 334 |
345 void registerDynamicUse(DynamicUse dynamicUse) { | 335 void registerDynamicUse(DynamicUse dynamicUse) { |
346 task.measure(() { | 336 task.measure(() { |
347 if (universe.registerDynamicUse(dynamicUse)) { | 337 if (universe.registerDynamicUse(dynamicUse)) { |
348 handleUnseenSelector(dynamicUse); | 338 handleUnseenSelector(dynamicUse); |
349 } | 339 } |
350 }); | 340 }); |
351 } | 341 } |
352 | 342 |
353 void logEnqueueReflectiveAction(action, [msg = ""]) { | 343 void logEnqueueReflectiveAction(action, [msg = ""]) { |
354 if (TRACE_MIRROR_ENQUEUING) { | 344 if (TRACE_MIRROR_ENQUEUING) { |
355 print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); | 345 print("MIRROR_ENQUEUE (R): $action $msg"); |
356 } | 346 } |
357 } | 347 } |
358 | 348 |
359 /// Enqeue the constructor [ctor] if it is required for reflection. | 349 /// Enqeue the constructor [ctor] if it is required for reflection. |
360 /// | 350 /// |
361 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 351 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
362 /// needed for reflection. | 352 /// needed for reflection. |
363 void enqueueReflectiveConstructor( | 353 void enqueueReflectiveConstructor( |
364 ConstructorElement ctor, bool enclosingWasIncluded) { | 354 ConstructorElement ctor, bool enclosingWasIncluded) { |
365 if (shouldIncludeElementDueToMirrors(ctor, | 355 if (shouldIncludeElementDueToMirrors(ctor, |
(...skipping 11 matching lines...) Expand all Loading... |
377 /// | 367 /// |
378 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 368 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
379 /// needed for reflection. | 369 /// needed for reflection. |
380 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 370 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
381 if (shouldIncludeElementDueToMirrors(element, | 371 if (shouldIncludeElementDueToMirrors(element, |
382 includedEnclosing: enclosingWasIncluded)) { | 372 includedEnclosing: enclosingWasIncluded)) { |
383 logEnqueueReflectiveAction(element); | 373 logEnqueueReflectiveAction(element); |
384 if (element.isTypedef) { | 374 if (element.isTypedef) { |
385 TypedefElement typedef = element; | 375 TypedefElement typedef = element; |
386 typedef.ensureResolved(resolution); | 376 typedef.ensureResolved(resolution); |
387 compiler.world.allTypedefs.add(element); | |
388 } else if (Elements.isStaticOrTopLevel(element)) { | 377 } else if (Elements.isStaticOrTopLevel(element)) { |
389 registerStaticUse(new StaticUse.foreignUse(element.declaration)); | 378 registerStaticUse(new StaticUse.foreignUse(element.declaration)); |
390 } else if (element.isInstanceMember) { | 379 } else if (element.isInstanceMember) { |
391 // We need to enqueue all members matching this one in subclasses, as | 380 // We need to enqueue all members matching this one in subclasses, as |
392 // well. | 381 // well. |
393 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 382 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
394 DynamicUse dynamicUse = | 383 DynamicUse dynamicUse = |
395 new DynamicUse(new Selector.fromElement(element), null); | 384 new DynamicUse(new Selector.fromElement(element), null); |
396 registerDynamicUse(dynamicUse); | 385 registerDynamicUse(dynamicUse); |
397 if (element.isField) { | 386 if (element.isField) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 } | 530 } |
542 | 531 |
543 void handleUnseenSelector(DynamicUse universeSelector) { | 532 void handleUnseenSelector(DynamicUse universeSelector) { |
544 strategy.processDynamicUse(this, universeSelector); | 533 strategy.processDynamicUse(this, universeSelector); |
545 } | 534 } |
546 | 535 |
547 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { | 536 void handleUnseenSelectorInternal(DynamicUse dynamicUse) { |
548 Selector selector = dynamicUse.selector; | 537 Selector selector = dynamicUse.selector; |
549 String methodName = selector.name; | 538 String methodName = selector.name; |
550 processInstanceMembers(methodName, (Element member) { | 539 processInstanceMembers(methodName, (Element member) { |
551 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 540 if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { |
552 if (member.isFunction && selector.isGetter) { | 541 if (member.isFunction && selector.isGetter) { |
553 registerClosurizedMember(member); | 542 registerClosurizedMember(member); |
554 } | 543 } |
555 addToWorkList(member); | 544 addToWorkList(member); |
556 return true; | 545 return true; |
557 } | 546 } |
558 return false; | 547 return false; |
559 }); | 548 }); |
560 if (selector.isGetter) { | 549 if (selector.isGetter) { |
561 processInstanceFunctions(methodName, (Element member) { | 550 processInstanceFunctions(methodName, (Element member) { |
562 if (dynamicUse.appliesUnnamed(member, compiler.world)) { | 551 if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { |
563 registerClosurizedMember(member); | 552 registerClosurizedMember(member); |
564 return true; | 553 return true; |
565 } | 554 } |
566 return false; | 555 return false; |
567 }); | 556 }); |
568 } | 557 } |
569 } | 558 } |
570 | 559 |
571 /** | 560 /** |
572 * Documentation wanted -- johnniwinther | 561 * Documentation wanted -- johnniwinther |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 if (element.isMalformed) return false; | 715 if (element.isMalformed) return false; |
727 | 716 |
728 assert(invariant(element, element is AnalyzableElement, | 717 assert(invariant(element, element is AnalyzableElement, |
729 message: 'Element $element is not analyzable.')); | 718 message: 'Element $element is not analyzable.')); |
730 if (hasBeenProcessed(element)) return false; | 719 if (hasBeenProcessed(element)) return false; |
731 if (queueIsClosed) { | 720 if (queueIsClosed) { |
732 throw new SpannableAssertionFailure( | 721 throw new SpannableAssertionFailure( |
733 element, "Resolution work list is closed. Trying to add $element."); | 722 element, "Resolution work list is closed. Trying to add $element."); |
734 } | 723 } |
735 | 724 |
736 compiler.world.registerUsedElement(element); | 725 compiler.openWorld.registerUsedElement(element); |
737 | 726 |
738 ResolutionWorkItem workItem = compiler.resolution.createWorkItem(element); | 727 ResolutionWorkItem workItem = compiler.resolution.createWorkItem(element); |
739 queue.add(workItem); | 728 queue.add(workItem); |
740 | 729 |
741 // Enable isolate support if we start using something from the isolate | 730 // Enable isolate support if we start using something from the isolate |
742 // library, or timers for the async library. We exclude constant fields, | 731 // library, or timers for the async library. We exclude constant fields, |
743 // which are ending here because their initializing expression is compiled. | 732 // which are ending here because their initializing expression is compiled. |
744 LibraryElement library = element.library; | 733 LibraryElement library = element.library; |
745 if (!compiler.hasIsolateSupport && (!element.isField || !element.isConst)) { | 734 if (!compiler.hasIsolateSupport && (!element.isField || !element.isConst)) { |
746 String uri = library.canonicalUri.toString(); | 735 String uri = library.canonicalUri.toString(); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
912 } | 901 } |
913 | 902 |
914 typedef void _DeferredActionFunction(); | 903 typedef void _DeferredActionFunction(); |
915 | 904 |
916 class _DeferredAction { | 905 class _DeferredAction { |
917 final Element element; | 906 final Element element; |
918 final _DeferredActionFunction action; | 907 final _DeferredActionFunction action; |
919 | 908 |
920 _DeferredAction(this.element, this.action); | 909 _DeferredAction(this.element, this.action); |
921 } | 910 } |
OLD | NEW |