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 | 5 |
6 /** | 6 /** |
7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
8 * compiled. | 8 * compiled. |
9 */ | 9 */ |
10 const bool REPORT_EXCESS_RESOLUTION = false; | 10 const bool REPORT_EXCESS_RESOLUTION = false; |
11 | 11 |
12 /** | 12 /** |
13 * If true, trace information on pass2 optimizations. | |
14 */ | |
15 const bool REPORT_PASS2_OPTIMIZATIONS = false; | |
16 | |
17 /** | |
18 * If true, dump the inferred types after compilation. | 13 * If true, dump the inferred types after compilation. |
19 */ | 14 */ |
20 const bool DUMP_INFERRED_TYPES = false; | 15 const bool DUMP_INFERRED_TYPES = false; |
21 | 16 |
22 /** | 17 /** |
23 * A string to identify the revision or build. | 18 * A string to identify the revision or build. |
24 * | 19 * |
25 * This ID is displayed if the compiler crashes and in verbose mode, and is | 20 * This ID is displayed if the compiler crashes and in verbose mode, and is |
26 * an aid in reproducing bug reports. | 21 * an aid in reproducing bug reports. |
27 * | 22 * |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 static const SourceString START_ROOT_ISOLATE = | 164 static const SourceString START_ROOT_ISOLATE = |
170 const SourceString('startRootIsolate'); | 165 const SourceString('startRootIsolate'); |
171 bool enabledNoSuchMethod = false; | 166 bool enabledNoSuchMethod = false; |
172 bool enabledRuntimeType = false; | 167 bool enabledRuntimeType = false; |
173 | 168 |
174 Stopwatch progress; | 169 Stopwatch progress; |
175 | 170 |
176 static const int PHASE_SCANNING = 0; | 171 static const int PHASE_SCANNING = 0; |
177 static const int PHASE_RESOLVING = 1; | 172 static const int PHASE_RESOLVING = 1; |
178 static const int PHASE_COMPILING = 2; | 173 static const int PHASE_COMPILING = 2; |
179 static const int PHASE_RECOMPILING = 3; | |
180 int phase; | 174 int phase; |
181 | 175 |
182 bool compilationFailed = false; | 176 bool compilationFailed = false; |
183 | 177 |
184 bool hasCrashed = false; | 178 bool hasCrashed = false; |
185 | 179 |
186 Compiler([this.tracer = const Tracer(), | 180 Compiler([this.tracer = const Tracer(), |
187 this.enableTypeAssertions = false, | 181 this.enableTypeAssertions = false, |
188 this.enableUserAssertions = false, | 182 this.enableUserAssertions = false, |
189 this.enableMinification = false, | 183 this.enableMinification = false, |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 log('Inferring types...'); | 557 log('Inferring types...'); |
564 typesTask.onResolutionComplete(); | 558 typesTask.onResolutionComplete(); |
565 | 559 |
566 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution | 560 // TODO(ahe): Remove this line. Eventually, enqueuer.resolution |
567 // should know this. | 561 // should know this. |
568 world.populate(); | 562 world.populate(); |
569 | 563 |
570 log('Compiling...'); | 564 log('Compiling...'); |
571 phase = PHASE_COMPILING; | 565 phase = PHASE_COMPILING; |
572 processQueue(enqueuer.codegen, main); | 566 processQueue(enqueuer.codegen, main); |
573 log("Recompiling ${enqueuer.codegen.recompilationCandidates.length} " | |
574 "methods..."); | |
575 phase = PHASE_RECOMPILING; | |
576 processRecompilationQueue(enqueuer.codegen); | |
577 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 567 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
578 | 568 |
579 if (compilationFailed) return; | 569 if (compilationFailed) return; |
580 | 570 |
581 backend.assembleProgram(); | 571 backend.assembleProgram(); |
582 | 572 |
583 checkQueues(); | 573 checkQueues(); |
584 } | 574 } |
585 | 575 |
586 void processQueue(Enqueuer world, Element main) { | 576 void processQueue(Enqueuer world, Element main) { |
587 backend.processNativeClasses(world, libraries.getValues()); | 577 backend.processNativeClasses(world, libraries.getValues()); |
588 world.addToWorkList(main); | 578 world.addToWorkList(main); |
589 progress.reset(); | 579 progress.reset(); |
590 world.forEach((WorkItem work) { | 580 world.forEach((WorkItem work) { |
591 withCurrentElement(work.element, () => work.run(this, world)); | 581 withCurrentElement(work.element, () => work.run(this, world)); |
592 }); | 582 }); |
593 world.queueIsClosed = true; | 583 world.queueIsClosed = true; |
594 if (compilationFailed) return; | 584 if (compilationFailed) return; |
595 assert(world.checkNoEnqueuedInvokedInstanceMethods()); | 585 assert(world.checkNoEnqueuedInvokedInstanceMethods()); |
596 if (DUMP_INFERRED_TYPES && phase == PHASE_COMPILING) { | 586 if (DUMP_INFERRED_TYPES && phase == PHASE_COMPILING) { |
597 print("Inferred argument types:"); | 587 print("Inferred argument types:"); |
598 print("------------------------"); | 588 print("------------------------"); |
599 backend.argumentTypes.dump(); | 589 backend.argumentTypes.dump(); |
600 print(""); | 590 print(""); |
601 print("Inferred return types:"); | 591 print("Inferred return types:"); |
602 print("----------------------"); | 592 print("----------------------"); |
603 backend.dumpReturnTypes(); | 593 backend.dumpReturnTypes(); |
| 594 print("Inferred field types:"); |
| 595 print("------------------------"); |
| 596 backend.fieldTypes.dump(); |
604 } | 597 } |
605 } | 598 } |
606 | 599 |
607 void processRecompilationQueue(Enqueuer world) { | |
608 assert(phase == PHASE_RECOMPILING); | |
609 while (!world.recompilationCandidates.isEmpty()) { | |
610 WorkItem work = world.recompilationCandidates.next(); | |
611 CodeBuffer oldCode = world.universe.generatedCode[work.element]; | |
612 world.universe.generatedCode.remove(work.element); | |
613 world.universe.generatedBailoutCode.remove(work.element); | |
614 withCurrentElement(work.element, () => work.run(this, world)); | |
615 CodeBuffer newCode = world.universe.generatedCode[work.element]; | |
616 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { | |
617 log("Pass 2 optimization:"); | |
618 log("Before:\n$oldCode"); | |
619 log("After:\n$newCode"); | |
620 } | |
621 } | |
622 } | |
623 | |
624 /** | 600 /** |
625 * Perform various checks of the queues. This includes checking that | 601 * Perform various checks of the queues. This includes checking that |
626 * the queues are empty (nothing was added after we stopped | 602 * the queues are empty (nothing was added after we stopped |
627 * processing the queues). Also compute the number of methods that | 603 * processing the queues). Also compute the number of methods that |
628 * were resolved, but not compiled (aka excess resolution). | 604 * were resolved, but not compiled (aka excess resolution). |
629 */ | 605 */ |
630 checkQueues() { | 606 checkQueues() { |
631 for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) { | 607 for (Enqueuer world in [enqueuer.resolution, enqueuer.codegen]) { |
632 world.forEach((WorkItem work) { | 608 world.forEach((WorkItem work) { |
633 internalErrorOnElement(work.element, "Work list is not empty."); | 609 internalErrorOnElement(work.element, "Work list is not empty."); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
715 result = analyzeElement(element); | 691 result = analyzeElement(element); |
716 enqueuer.resolution.resolvedElements[element] = result; | 692 enqueuer.resolution.resolvedElements[element] = result; |
717 return result; | 693 return result; |
718 } | 694 } |
719 | 695 |
720 void codegen(WorkItem work, Enqueuer world) { | 696 void codegen(WorkItem work, Enqueuer world) { |
721 if (world !== enqueuer.codegen) return null; | 697 if (world !== enqueuer.codegen) return null; |
722 if (progress.elapsedInMs() > 500) { | 698 if (progress.elapsedInMs() > 500) { |
723 // TODO(ahe): Add structured diagnostics to the compiler API and | 699 // TODO(ahe): Add structured diagnostics to the compiler API and |
724 // use it to separate this from the --verbose option. | 700 // use it to separate this from the --verbose option. |
725 if (phase == PHASE_COMPILING) { | 701 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
726 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | |
727 } else { | |
728 log('Recompiled ${world.recompilationCandidates.processed} methods.'); | |
729 } | |
730 progress.reset(); | 702 progress.reset(); |
731 } | 703 } |
732 backend.codegen(work); | 704 backend.codegen(work); |
733 } | 705 } |
734 | 706 |
735 DartType resolveTypeAnnotation(Element element, | 707 DartType resolveTypeAnnotation(Element element, |
736 TypeAnnotation annotation) { | 708 TypeAnnotation annotation) { |
737 return resolver.resolveTypeAnnotation(element, annotation); | 709 return resolver.resolveTypeAnnotation(element, annotation); |
738 } | 710 } |
739 | 711 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 final endOffset = end.charOffset + end.slowCharCount; | 915 final endOffset = end.charOffset + end.slowCharCount; |
944 | 916 |
945 // [begin] and [end] might be the same for the same empty token. This | 917 // [begin] and [end] might be the same for the same empty token. This |
946 // happens for instance when scanning '$$'. | 918 // happens for instance when scanning '$$'. |
947 assert(endOffset >= beginOffset); | 919 assert(endOffset >= beginOffset); |
948 return f(beginOffset, endOffset); | 920 return f(beginOffset, endOffset); |
949 } | 921 } |
950 | 922 |
951 String toString() => 'SourceSpan($uri, $begin, $end)'; | 923 String toString() => 'SourceSpan($uri, $begin, $end)'; |
952 } | 924 } |
OLD | NEW |