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 part of dart2js; | 5 part of dart2js; |
6 | 6 |
7 typedef ItemCompilationContext ItemCompilationContextCreator(); | 7 typedef ItemCompilationContext ItemCompilationContextCreator(); |
8 | 8 |
9 class EnqueueTask extends CompilerTask { | 9 class EnqueueTask extends CompilerTask { |
10 final ResolutionEnqueuer resolution; | 10 final ResolutionEnqueuer resolution; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 static final TRACE_MIRROR_ENQUEUING = | 42 static final TRACE_MIRROR_ENQUEUING = |
43 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); | 43 const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING"); |
44 | 44 |
45 bool queueIsClosed = false; | 45 bool queueIsClosed = false; |
46 EnqueueTask task; | 46 EnqueueTask task; |
47 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 47 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
48 | 48 |
49 bool hasEnqueuedReflectiveElements = false; | 49 bool hasEnqueuedReflectiveElements = false; |
50 bool hasEnqueuedReflectiveStaticFields = false; | 50 bool hasEnqueuedReflectiveStaticFields = false; |
51 | 51 |
52 CompilationInformation get compilationInfo; | |
53 | |
54 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 52 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); |
55 | 53 |
56 Queue<WorkItem> get queue; | 54 Queue<WorkItem> get queue; |
57 bool get queueIsEmpty => queue.isEmpty; | 55 bool get queueIsEmpty => queue.isEmpty; |
58 | 56 |
59 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 57 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
60 bool get isResolutionQueue => false; | 58 bool get isResolutionQueue => false; |
61 | 59 |
62 QueueFilter get filter => compiler.enqueuerFilter; | 60 QueueFilter get filter => compiler.enqueuerFilter; |
63 | 61 |
64 /// Returns [:true:] if [member] has been processed by this enqueuer. | 62 /// Returns [:true:] if [member] has been processed by this enqueuer. |
65 bool isProcessed(Element member); | 63 bool isProcessed(Element member); |
66 | 64 |
67 /** | 65 /** |
68 * Documentation wanted -- johnniwinther | 66 * Documentation wanted -- johnniwinther |
69 * | 67 * |
70 * Invariant: [element] must be a declaration element. | 68 * Invariant: [element] must be a declaration element. |
71 */ | 69 */ |
72 void addToWorkList(Element element) { | 70 void addToWorkList(Element element) { |
73 assert(invariant(element, element.isDeclaration)); | 71 assert(invariant(element, element.isDeclaration)); |
74 if (internalAddToWorkList(element)) { | 72 internalAddToWorkList(element); |
75 compilationInfo.addsToWorkList(compiler.currentElement, element); | |
76 } | |
77 } | 73 } |
78 | 74 |
79 /** | 75 /** |
80 * Adds [element] to the work list if it has not already been processed. | 76 * Adds [element] to the work list if it has not already been processed. |
81 * | 77 * |
82 * Returns [true] if the element was actually added to the queue. | 78 * Returns [true] if the element was actually added to the queue. |
83 */ | 79 */ |
84 bool internalAddToWorkList(Element element); | 80 bool internalAddToWorkList(Element element); |
85 | 81 |
86 void registerInstantiatedType(InterfaceType type, Registry registry, | 82 void registerInstantiatedType(InterfaceType type, Registry registry, |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 registerClosurizedMember(member, compiler.globalDependencies); | 178 registerClosurizedMember(member, compiler.globalDependencies); |
183 addToWorkList(member); | 179 addToWorkList(member); |
184 return; | 180 return; |
185 } | 181 } |
186 // Store the member in [instanceFunctionsByName] to catch | 182 // Store the member in [instanceFunctionsByName] to catch |
187 // getters on the function. | 183 // getters on the function. |
188 Link<Element> members = instanceFunctionsByName.putIfAbsent( | 184 Link<Element> members = instanceFunctionsByName.putIfAbsent( |
189 memberName, () => const Link<Element>()); | 185 memberName, () => const Link<Element>()); |
190 instanceFunctionsByName[memberName] = members.prepend(member); | 186 instanceFunctionsByName[memberName] = members.prepend(member); |
191 if (universe.hasInvocation(member, compiler)) { | 187 if (universe.hasInvocation(member, compiler)) { |
192 compilationInfo.enqueues(getContext(), member); | |
193 addToWorkList(member); | 188 addToWorkList(member); |
194 return; | 189 return; |
195 } | 190 } |
196 } else if (member.kind == ElementKind.GETTER) { | 191 } else if (member.kind == ElementKind.GETTER) { |
197 if (universe.hasInvokedGetter(member, compiler)) { | 192 if (universe.hasInvokedGetter(member, compiler)) { |
198 addToWorkList(member); | 193 addToWorkList(member); |
199 return; | 194 return; |
200 } | 195 } |
201 // We don't know what selectors the returned closure accepts. If | 196 // We don't know what selectors the returned closure accepts. If |
202 // the set contains any selector we have to assume that it matches. | 197 // the set contains any selector we have to assume that it matches. |
(...skipping 11 matching lines...) Expand all Loading... |
214 // The element is not yet used. Add it to the list of instance | 209 // The element is not yet used. Add it to the list of instance |
215 // members to still be processed. | 210 // members to still be processed. |
216 Link<Element> members = instanceMembersByName.putIfAbsent( | 211 Link<Element> members = instanceMembersByName.putIfAbsent( |
217 memberName, () => const Link<Element>()); | 212 memberName, () => const Link<Element>()); |
218 instanceMembersByName[memberName] = members.prepend(member); | 213 instanceMembersByName[memberName] = members.prepend(member); |
219 } | 214 } |
220 | 215 |
221 void enableNoSuchMethod(Element element) {} | 216 void enableNoSuchMethod(Element element) {} |
222 void enableIsolateSupport() {} | 217 void enableIsolateSupport() {} |
223 | 218 |
224 Element getContext() => compiler.currentElement; | |
225 | |
226 void onRegisterInstantiatedClass(ClassElement cls) { | 219 void onRegisterInstantiatedClass(ClassElement cls) { |
227 task.measure(() { | 220 task.measure(() { |
228 if (seenClasses.contains(cls)) return; | 221 if (seenClasses.contains(cls)) return; |
229 // The class must be resolved to compute the set of all | 222 // The class must be resolved to compute the set of all |
230 // supertypes. | 223 // supertypes. |
231 cls.ensureResolved(compiler); | 224 cls.ensureResolved(compiler); |
232 | 225 |
233 void processClass(ClassElement cls) { | 226 void processClass(ClassElement cls) { |
234 if (seenClasses.contains(cls)) return; | 227 if (seenClasses.contains(cls)) return; |
235 | 228 |
(...skipping 11 matching lines...) Expand all Loading... |
247 cls, this, compiler.globalDependencies); | 240 cls, this, compiler.globalDependencies); |
248 } | 241 } |
249 processClass(cls); | 242 processClass(cls); |
250 for (Link<DartType> supertypes = cls.allSupertypes; | 243 for (Link<DartType> supertypes = cls.allSupertypes; |
251 !supertypes.isEmpty; supertypes = supertypes.tail) { | 244 !supertypes.isEmpty; supertypes = supertypes.tail) { |
252 processClass(supertypes.head.element); | 245 processClass(supertypes.head.element); |
253 } | 246 } |
254 }); | 247 }); |
255 } | 248 } |
256 | 249 |
257 void registerNewSelector(Element context, | 250 void registerNewSelector(Selector selector, |
258 Selector selector, | |
259 Map<String, Set<Selector>> selectorsMap) { | 251 Map<String, Set<Selector>> selectorsMap) { |
260 String name = selector.name; | 252 String name = selector.name; |
261 Set<Selector> selectors = | 253 Set<Selector> selectors = |
262 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); | 254 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); |
263 if (!selectors.contains(selector)) { | 255 if (!selectors.contains(selector)) { |
264 selectors.add(selector); | 256 selectors.add(selector); |
265 handleUnseenSelector(context, name, selector); | 257 handleUnseenSelector(name, selector); |
266 } | 258 } |
267 } | 259 } |
268 | 260 |
269 void registerInvocation(Element context, Selector selector) { | 261 void registerInvocation(Selector selector) { |
270 task.measure(() { | 262 task.measure(() { |
271 registerNewSelector(context, selector, universe.invokedNames); | 263 registerNewSelector(selector, universe.invokedNames); |
272 }); | 264 }); |
273 } | 265 } |
274 | 266 |
275 void registerInvokedGetter(Element context, Selector selector) { | 267 void registerInvokedGetter(Selector selector) { |
276 task.measure(() { | 268 task.measure(() { |
277 registerNewSelector(context, selector, universe.invokedGetters); | 269 registerNewSelector(selector, universe.invokedGetters); |
278 }); | 270 }); |
279 } | 271 } |
280 | 272 |
281 void registerInvokedSetter(Element context, Selector selector) { | 273 void registerInvokedSetter(Selector selector) { |
282 task.measure(() { | 274 task.measure(() { |
283 registerNewSelector(context, selector, universe.invokedSetters); | 275 registerNewSelector(selector, universe.invokedSetters); |
284 }); | 276 }); |
285 } | 277 } |
286 | 278 |
287 /** | 279 /** |
288 * Decides whether an element should be included to satisfy requirements | 280 * Decides whether an element should be included to satisfy requirements |
289 * of the mirror system. [includedEnclosing] provides a hint whether the | 281 * of the mirror system. [includedEnclosing] provides a hint whether the |
290 * enclosing element was included. | 282 * enclosing element was included. |
291 * | 283 * |
292 * The actual implementation depends on the current compiler phase. | 284 * The actual implementation depends on the current compiler phase. |
293 */ | 285 */ |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 // Do not enqueue typedefs. | 318 // Do not enqueue typedefs. |
327 && !element.impliesType) { | 319 && !element.impliesType) { |
328 logEnqueueReflectiveAction(element); | 320 logEnqueueReflectiveAction(element); |
329 if (Elements.isStaticOrTopLevel(element)) { | 321 if (Elements.isStaticOrTopLevel(element)) { |
330 registerStaticUse(element.declaration); | 322 registerStaticUse(element.declaration); |
331 } else if (element.isInstanceMember) { | 323 } else if (element.isInstanceMember) { |
332 // We need to enqueue all members matching this one in subclasses, as | 324 // We need to enqueue all members matching this one in subclasses, as |
333 // well. | 325 // well. |
334 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 326 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
335 Selector selector = new Selector.fromElement(element, compiler); | 327 Selector selector = new Selector.fromElement(element, compiler); |
336 registerSelectorUse(element, selector); | 328 registerSelectorUse(selector); |
337 if (element.isField) { | 329 if (element.isField) { |
338 Selector selector = | 330 Selector selector = |
339 new Selector.setter(element.name, element.library); | 331 new Selector.setter(element.name, element.library); |
340 registerInvokedSetter(element, selector); | 332 registerInvokedSetter(selector); |
341 } | 333 } |
342 } | 334 } |
343 } | 335 } |
344 } | 336 } |
345 | 337 |
346 /// Enqeue the member [element] if it is required for reflection. | 338 /// Enqeue the member [element] if it is required for reflection. |
347 /// | 339 /// |
348 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 340 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
349 /// needed for reflection. | 341 /// needed for reflection. |
350 void enqueueReflectiveElementsInClass(ClassElement cls, | 342 void enqueueReflectiveElementsInClass(ClassElement cls, |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 } | 459 } |
468 | 460 |
469 processInstanceMembers(String n, bool f(Element e)) { | 461 processInstanceMembers(String n, bool f(Element e)) { |
470 processLink(instanceMembersByName, n, f); | 462 processLink(instanceMembersByName, n, f); |
471 } | 463 } |
472 | 464 |
473 processInstanceFunctions(String n, bool f(Element e)) { | 465 processInstanceFunctions(String n, bool f(Element e)) { |
474 processLink(instanceFunctionsByName, n, f); | 466 processLink(instanceFunctionsByName, n, f); |
475 } | 467 } |
476 | 468 |
477 void handleUnseenSelector(Element context, | 469 void handleUnseenSelector(String methodName, Selector selector) { |
478 String methodName, | |
479 Selector selector) { | |
480 processInstanceMembers(methodName, (Element member) { | 470 processInstanceMembers(methodName, (Element member) { |
481 compilationInfo.enqueues(context, member); | |
482 if (selector.appliesUnnamed(member, compiler)) { | 471 if (selector.appliesUnnamed(member, compiler)) { |
483 if (member.isFunction && selector.isGetter) { | 472 if (member.isFunction && selector.isGetter) { |
484 registerClosurizedMember(member, compiler.globalDependencies); | 473 registerClosurizedMember(member, compiler.globalDependencies); |
485 } | 474 } |
486 if (member.isField && member.enclosingClass.isNative) { | 475 if (member.isField && member.enclosingClass.isNative) { |
487 if (selector.isGetter || selector.isCall) { | 476 if (selector.isGetter || selector.isCall) { |
488 nativeEnqueuer.registerFieldLoad(member); | 477 nativeEnqueuer.registerFieldLoad(member); |
489 // We have to also handle storing to the field because we only get | 478 // We have to also handle storing to the field because we only get |
490 // one look at each member and there might be a store we have not | 479 // one look at each member and there might be a store we have not |
491 // seen yet. | 480 // seen yet. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 addToWorkList(element); | 517 addToWorkList(element); |
529 compiler.backend.registerStaticUse(element, this); | 518 compiler.backend.registerStaticUse(element, this); |
530 } | 519 } |
531 | 520 |
532 void registerGetOfStaticFunction(FunctionElement element) { | 521 void registerGetOfStaticFunction(FunctionElement element) { |
533 registerStaticUse(element); | 522 registerStaticUse(element); |
534 compiler.backend.registerGetOfStaticFunction(this); | 523 compiler.backend.registerGetOfStaticFunction(this); |
535 universe.staticFunctionsNeedingGetter.add(element); | 524 universe.staticFunctionsNeedingGetter.add(element); |
536 } | 525 } |
537 | 526 |
538 void registerDynamicInvocation(Element context, Selector selector) { | 527 void registerDynamicInvocation(Selector selector) { |
539 assert(selector != null); | 528 assert(selector != null); |
540 registerInvocation(context, selector); | 529 registerInvocation(selector); |
541 } | 530 } |
542 | 531 |
543 void registerSelectorUse(Element context, Selector selector) { | 532 void registerSelectorUse(Selector selector) { |
544 if (selector.isGetter) { | 533 if (selector.isGetter) { |
545 registerInvokedGetter(context, selector); | 534 registerInvokedGetter(selector); |
546 } else if (selector.isSetter) { | 535 } else if (selector.isSetter) { |
547 registerInvokedSetter(context, selector); | 536 registerInvokedSetter(selector); |
548 } else { | 537 } else { |
549 registerInvocation(context, selector); | 538 registerInvocation(selector); |
550 } | 539 } |
551 } | 540 } |
552 | 541 |
553 void registerDynamicGetter(Element context, Selector selector) { | 542 void registerDynamicGetter(Selector selector) { |
554 registerInvokedGetter(context, selector); | 543 registerInvokedGetter(selector); |
555 } | 544 } |
556 | 545 |
557 void registerDynamicSetter(Element context, Selector selector) { | 546 void registerDynamicSetter(Selector selector) { |
558 registerInvokedSetter(context, selector); | 547 registerInvokedSetter(selector); |
559 } | 548 } |
560 | 549 |
561 void registerGetterForSuperMethod(Element element) { | 550 void registerGetterForSuperMethod(Element element) { |
562 universe.methodsNeedingSuperGetter.add(element); | 551 universe.methodsNeedingSuperGetter.add(element); |
563 } | 552 } |
564 | 553 |
565 void registerFieldGetter(Element element) { | 554 void registerFieldGetter(Element element) { |
566 universe.fieldGetters.add(element); | 555 universe.fieldGetters.add(element); |
567 } | 556 } |
568 | 557 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 final Set<AstElement> resolvedElements; | 645 final Set<AstElement> resolvedElements; |
657 | 646 |
658 final Queue<ResolutionWorkItem> queue; | 647 final Queue<ResolutionWorkItem> queue; |
659 | 648 |
660 /** | 649 /** |
661 * A deferred task queue for the resolution phase which is processed | 650 * A deferred task queue for the resolution phase which is processed |
662 * when the resolution queue has been emptied. | 651 * when the resolution queue has been emptied. |
663 */ | 652 */ |
664 final Queue<DeferredTask> deferredTaskQueue; | 653 final Queue<DeferredTask> deferredTaskQueue; |
665 | 654 |
666 CompilationInformation compilationInfo; | |
667 | |
668 ResolutionEnqueuer(Compiler compiler, | 655 ResolutionEnqueuer(Compiler compiler, |
669 ItemCompilationContext itemCompilationContextCreator()) | 656 ItemCompilationContext itemCompilationContextCreator()) |
670 : super('resolution enqueuer', compiler, itemCompilationContextCreator), | 657 : super('resolution enqueuer', compiler, itemCompilationContextCreator), |
671 resolvedElements = new Set<AstElement>(), | 658 resolvedElements = new Set<AstElement>(), |
672 queue = new Queue<ResolutionWorkItem>(), | 659 queue = new Queue<ResolutionWorkItem>(), |
673 deferredTaskQueue = new Queue<DeferredTask>() { | 660 deferredTaskQueue = new Queue<DeferredTask>(); |
674 compilationInfo = new CompilationInformation(this, compiler.dumpInfo); | |
675 } | |
676 | 661 |
677 bool get isResolutionQueue => true; | 662 bool get isResolutionQueue => true; |
678 | 663 |
679 bool isProcessed(Element member) => resolvedElements.contains(member); | 664 bool isProcessed(Element member) => resolvedElements.contains(member); |
680 | 665 |
681 /// Returns `true` if [element] has been processed by the resolution enqueuer. | 666 /// Returns `true` if [element] has been processed by the resolution enqueuer. |
682 bool hasBeenResolved(Element element) { | 667 bool hasBeenResolved(Element element) { |
683 return resolvedElements.contains(element.analyzableElement.declaration); | 668 return resolvedElements.contains(element.analyzableElement.declaration); |
684 } | 669 } |
685 | 670 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 } | 793 } |
809 | 794 |
810 /// [Enqueuer] which is specific to code generation. | 795 /// [Enqueuer] which is specific to code generation. |
811 class CodegenEnqueuer extends Enqueuer { | 796 class CodegenEnqueuer extends Enqueuer { |
812 final Queue<CodegenWorkItem> queue; | 797 final Queue<CodegenWorkItem> queue; |
813 final Map<Element, js.Expression> generatedCode = | 798 final Map<Element, js.Expression> generatedCode = |
814 new Map<Element, js.Expression>(); | 799 new Map<Element, js.Expression>(); |
815 | 800 |
816 final Set<Element> newlyEnqueuedElements; | 801 final Set<Element> newlyEnqueuedElements; |
817 | 802 |
818 CompilationInformation compilationInfo; | |
819 | |
820 CodegenEnqueuer(Compiler compiler, | 803 CodegenEnqueuer(Compiler compiler, |
821 ItemCompilationContext itemCompilationContextCreator()) | 804 ItemCompilationContext itemCompilationContextCreator()) |
822 : queue = new Queue<CodegenWorkItem>(), | 805 : queue = new Queue<CodegenWorkItem>(), |
823 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), | 806 newlyEnqueuedElements = compiler.cacheStrategy.newSet(), |
824 super('codegen enqueuer', compiler, itemCompilationContextCreator) { | 807 super('codegen enqueuer', compiler, itemCompilationContextCreator); |
825 compilationInfo = new CompilationInformation(this, compiler.dumpInfo); | |
826 } | |
827 | 808 |
828 bool isProcessed(Element member) => | 809 bool isProcessed(Element member) => |
829 member.isAbstract || generatedCode.containsKey(member); | 810 member.isAbstract || generatedCode.containsKey(member); |
830 | 811 |
831 /** | 812 /** |
832 * Decides whether an element should be included to satisfy requirements | 813 * Decides whether an element should be included to satisfy requirements |
833 * of the mirror system. | 814 * of the mirror system. |
834 * | 815 * |
835 * For code generation, we rely on the precomputed set of elements that takes | 816 * For code generation, we rely on the precomputed set of elements that takes |
836 * subtyping constraints into account. | 817 * subtyping constraints into account. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 } | 865 } |
885 } | 866 } |
886 }); | 867 }); |
887 return true; | 868 return true; |
888 } | 869 } |
889 | 870 |
890 void processWorkItem(void f(WorkItem work), WorkItem work) { | 871 void processWorkItem(void f(WorkItem work), WorkItem work) { |
891 f(work); | 872 f(work); |
892 } | 873 } |
893 } | 874 } |
OLD | NEW |