Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/enqueue.dart

Issue 430913002: Better dependency tracking (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fixed final critiques Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698