| 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; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 /** | 22 /** |
| 23 * A string to identify the revision or build. | 23 * A string to identify the revision or build. |
| 24 * | 24 * |
| 25 * This ID is displayed if the compiler crashes and in verbose mode, and is | 25 * This ID is displayed if the compiler crashes and in verbose mode, and is |
| 26 * an aid in reproducing bug reports. | 26 * an aid in reproducing bug reports. |
| 27 * | 27 * |
| 28 * The actual string is rewritten during the SDK build process. | 28 * The actual string is rewritten during the SDK build process. |
| 29 */ | 29 */ |
| 30 const String BUILD_ID = 'build number could not be determined'; | 30 const String BUILD_ID = 'build number could not be determined'; |
| 31 | 31 |
| 32 | |
| 33 /** | 32 /** |
| 34 * Contains backend-specific data that is used throughout the compilation of | 33 * Contains backend-specific data that is used throughout the compilation of |
| 35 * one work item. | 34 * one work item. |
| 36 */ | 35 */ |
| 37 class ItemCompilationContext { | 36 class ItemCompilationContext { |
| 38 } | 37 } |
| 39 | 38 |
| 40 class WorkItem { | 39 class WorkItem { |
| 41 final ItemCompilationContext compilationContext; | 40 final ItemCompilationContext compilationContext; |
| 41 /** |
| 42 * Documentation wanted -- johnniwinther |
| 43 * |
| 44 * Invariant: [element] must be a declaration element. |
| 45 */ |
| 42 final Element element; | 46 final Element element; |
| 43 TreeElements resolutionTree; | 47 TreeElements resolutionTree; |
| 44 bool allowSpeculativeOptimization = true; | 48 bool allowSpeculativeOptimization = true; |
| 45 List<HTypeGuard> guards = const <HTypeGuard>[]; | 49 List<HTypeGuard> guards = const <HTypeGuard>[]; |
| 46 | 50 |
| 47 WorkItem(this.element, this.resolutionTree, this.compilationContext); | 51 WorkItem(this.element, this.resolutionTree, this.compilationContext) { |
| 52 assert(invariant(element, element.isDeclaration)); |
| 53 } |
| 48 | 54 |
| 49 bool isAnalyzed() => resolutionTree !== null; | 55 bool isAnalyzed() => resolutionTree !== null; |
| 50 | 56 |
| 51 void run(Compiler compiler, Enqueuer world) { | 57 void run(Compiler compiler, Enqueuer world) { |
| 52 CodeBuffer codeBuffer = world.universe.generatedCode[element]; | 58 CodeBuffer codeBuffer = world.universe.generatedCode[element]; |
| 53 if (codeBuffer !== null) return; | 59 if (codeBuffer !== null) return; |
| 54 resolutionTree = compiler.analyze(this, world); | 60 resolutionTree = compiler.analyze(this, world); |
| 55 compiler.codegen(this, world); | 61 compiler.codegen(this, world); |
| 56 } | 62 } |
| 57 } | 63 } |
| (...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 print("Inferred return types:"); | 607 print("Inferred return types:"); |
| 602 print("----------------------"); | 608 print("----------------------"); |
| 603 backend.dumpReturnTypes(); | 609 backend.dumpReturnTypes(); |
| 604 } | 610 } |
| 605 } | 611 } |
| 606 | 612 |
| 607 void processRecompilationQueue(Enqueuer world) { | 613 void processRecompilationQueue(Enqueuer world) { |
| 608 assert(phase == PHASE_RECOMPILING); | 614 assert(phase == PHASE_RECOMPILING); |
| 609 while (!world.recompilationCandidates.isEmpty()) { | 615 while (!world.recompilationCandidates.isEmpty()) { |
| 610 WorkItem work = world.recompilationCandidates.next(); | 616 WorkItem work = world.recompilationCandidates.next(); |
| 611 CodeBuffer oldCode = world.universe.generatedCode[work.element]; | 617 Element element = work.element; |
| 612 world.universe.generatedCode.remove(work.element); | 618 CodeBuffer oldCode = world.universe.generatedCode[element]; |
| 613 world.universe.generatedBailoutCode.remove(work.element); | 619 world.universe.generatedCode.remove(element); |
| 614 withCurrentElement(work.element, () => work.run(this, world)); | 620 world.universe.generatedBailoutCode.remove(element); |
| 615 CodeBuffer newCode = world.universe.generatedCode[work.element]; | 621 withCurrentElement(element, () => work.run(this, world)); |
| 622 CodeBuffer newCode = world.universe.generatedCode[element]; |
| 616 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { | 623 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { |
| 617 log("Pass 2 optimization:"); | 624 log("Pass 2 optimization:"); |
| 618 log("Before:\n$oldCode"); | 625 log("Before:\n$oldCode"); |
| 619 log("After:\n$newCode"); | 626 log("After:\n$newCode"); |
| 620 } | 627 } |
| 621 } | 628 } |
| 622 } | 629 } |
| 623 | 630 |
| 624 /** | 631 /** |
| 625 * Perform various checks of the queues. This includes checking that | 632 * Perform various checks of the queues. This includes checking that |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 663 log('Excess resolution work: ${resolved.length}.'); | 670 log('Excess resolution work: ${resolved.length}.'); |
| 664 if (!REPORT_EXCESS_RESOLUTION) return; | 671 if (!REPORT_EXCESS_RESOLUTION) return; |
| 665 for (Element e in resolved) { | 672 for (Element e in resolved) { |
| 666 SourceSpan span = spanFromElement(e); | 673 SourceSpan span = spanFromElement(e); |
| 667 reportDiagnostic(span, 'Warning: $e resolved but not compiled.', | 674 reportDiagnostic(span, 'Warning: $e resolved but not compiled.', |
| 668 api.Diagnostic.WARNING); | 675 api.Diagnostic.WARNING); |
| 669 } | 676 } |
| 670 } | 677 } |
| 671 | 678 |
| 672 TreeElements analyzeElement(Element element) { | 679 TreeElements analyzeElement(Element element) { |
| 680 assert(invariant(element, element.isDeclaration)); |
| 673 TreeElements elements = enqueuer.resolution.getCachedElements(element); | 681 TreeElements elements = enqueuer.resolution.getCachedElements(element); |
| 674 if (elements !== null) return elements; | 682 if (elements !== null) return elements; |
| 675 final int allowed = ElementCategory.VARIABLE | ElementCategory.FUNCTION | 683 final int allowed = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
| 676 | ElementCategory.FACTORY; | 684 | ElementCategory.FACTORY; |
| 677 ElementKind kind = element.kind; | 685 ElementKind kind = element.kind; |
| 678 if (!element.isAccessor() && | 686 if (!element.isAccessor() && |
| 679 ((kind === ElementKind.ABSTRACT_FIELD) || | 687 ((kind === ElementKind.ABSTRACT_FIELD) || |
| 680 (kind.category & allowed) == 0)) { | 688 (kind.category & allowed) == 0)) { |
| 681 return null; | 689 return null; |
| 682 } | 690 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 706 } | 714 } |
| 707 } | 715 } |
| 708 Element element = work.element; | 716 Element element = work.element; |
| 709 TreeElements result = world.getCachedElements(element); | 717 TreeElements result = world.getCachedElements(element); |
| 710 if (result !== null) return result; | 718 if (result !== null) return result; |
| 711 if (world !== enqueuer.resolution) { | 719 if (world !== enqueuer.resolution) { |
| 712 internalErrorOnElement(element, | 720 internalErrorOnElement(element, |
| 713 'Internal error: unresolved element: $element.'); | 721 'Internal error: unresolved element: $element.'); |
| 714 } | 722 } |
| 715 result = analyzeElement(element); | 723 result = analyzeElement(element); |
| 724 assert(invariant(element, element.isDeclaration)); |
| 716 enqueuer.resolution.resolvedElements[element] = result; | 725 enqueuer.resolution.resolvedElements[element] = result; |
| 717 return result; | 726 return result; |
| 718 } | 727 } |
| 719 | 728 |
| 720 void codegen(WorkItem work, Enqueuer world) { | 729 void codegen(WorkItem work, Enqueuer world) { |
| 721 if (world !== enqueuer.codegen) return null; | 730 if (world !== enqueuer.codegen) return null; |
| 722 if (progress.elapsedInMs() > 500) { | 731 if (progress.elapsedInMs() > 500) { |
| 723 // TODO(ahe): Add structured diagnostics to the compiler API and | 732 // TODO(ahe): Add structured diagnostics to the compiler API and |
| 724 // use it to separate this from the --verbose option. | 733 // use it to separate this from the --verbose option. |
| 725 if (phase == PHASE_COMPILING) { | 734 if (phase == PHASE_COMPILING) { |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 final endOffset = end.charOffset + end.slowCharCount; | 952 final endOffset = end.charOffset + end.slowCharCount; |
| 944 | 953 |
| 945 // [begin] and [end] might be the same for the same empty token. This | 954 // [begin] and [end] might be the same for the same empty token. This |
| 946 // happens for instance when scanning '$$'. | 955 // happens for instance when scanning '$$'. |
| 947 assert(endOffset >= beginOffset); | 956 assert(endOffset >= beginOffset); |
| 948 return f(beginOffset, endOffset); | 957 return f(beginOffset, endOffset); |
| 949 } | 958 } |
| 950 | 959 |
| 951 String toString() => 'SourceSpan($uri, $begin, $end)'; | 960 String toString() => 'SourceSpan($uri, $begin, $end)'; |
| 952 } | 961 } |
| 962 |
| 963 /** |
| 964 * Throws an [InvariantException] if [condition] is [:false:]. [condition] must |
| 965 * be either a [:bool:] or a no-arg function returning a [:bool:]. |
| 966 * |
| 967 * Use this method to provide better information for assertion by calling |
| 968 * [invariant] as the argument to an [:assert:] statement: |
| 969 * |
| 970 * assert(invariant(position, isValid)); |
| 971 * |
| 972 * [spannable] must be non-null and will be used to provide positional |
| 973 * information in the generated error message. |
| 974 */ |
| 975 bool invariant(Spannable spannable, var condition, {String message: null}) { |
| 976 // TODO(johnniwinther): Use [spannable] and [message] to provide better |
| 977 // information on assertion errors. |
| 978 if (condition is Function){ |
| 979 condition = condition(); |
| 980 } |
| 981 return spannable != null && condition; |
| 982 } |
| OLD | NEW |