Chromium Code Reviews| 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 JavaScriptConstantTask constantCompilerTask; | 497 JavaScriptConstantTask constantCompilerTask; |
| 498 | 498 |
| 499 JavaScriptImpactTransformer impactTransformer; | 499 JavaScriptImpactTransformer impactTransformer; |
| 500 | 500 |
| 501 PatchResolverTask patchResolverTask; | 501 PatchResolverTask patchResolverTask; |
| 502 | 502 |
| 503 bool enabledNoSuchMethod = false; | 503 bool enabledNoSuchMethod = false; |
| 504 | 504 |
| 505 SourceInformationStrategy sourceInformationStrategy; | 505 SourceInformationStrategy sourceInformationStrategy; |
| 506 | 506 |
| 507 JavaScriptBackendSerialization serialization; | |
| 508 | |
| 509 final NativeData nativeData = new NativeData(); | |
| 510 | |
| 507 final BackendHelpers helpers; | 511 final BackendHelpers helpers; |
| 508 final BackendImpacts impacts; | 512 final BackendImpacts impacts; |
| 509 | 513 |
| 510 JavaScriptBackend(Compiler compiler, | 514 JavaScriptBackend(Compiler compiler, |
| 511 {bool generateSourceMap: true, | 515 {bool generateSourceMap: true, |
| 512 bool useStartupEmitter: false, | 516 bool useStartupEmitter: false, |
| 513 bool useNewSourceInfo: false}) | 517 bool useNewSourceInfo: false}) |
| 514 : namer = determineNamer(compiler), | 518 : namer = determineNamer(compiler), |
| 515 oneShotInterceptors = new Map<jsAst.Name, Selector>(), | 519 oneShotInterceptors = new Map<jsAst.Name, Selector>(), |
| 516 interceptedElements = new Map<String, Set<Element>>(), | 520 interceptedElements = new Map<String, Set<Element>>(), |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 535 jsInteropAnalysis = new JsInteropAnalysis(this); | 539 jsInteropAnalysis = new JsInteropAnalysis(this); |
| 536 | 540 |
| 537 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 541 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
| 538 constantCompilerTask = new JavaScriptConstantTask(compiler); | 542 constantCompilerTask = new JavaScriptConstantTask(compiler); |
| 539 impactTransformer = new JavaScriptImpactTransformer(this); | 543 impactTransformer = new JavaScriptImpactTransformer(this); |
| 540 patchResolverTask = new PatchResolverTask(compiler); | 544 patchResolverTask = new PatchResolverTask(compiler); |
| 541 functionCompiler = compiler.useCpsIr | 545 functionCompiler = compiler.useCpsIr |
| 542 ? new CpsFunctionCompiler( | 546 ? new CpsFunctionCompiler( |
| 543 compiler, this, sourceInformationStrategy) | 547 compiler, this, sourceInformationStrategy) |
| 544 : new SsaFunctionCompiler(this, sourceInformationStrategy); | 548 : new SsaFunctionCompiler(this, sourceInformationStrategy); |
| 549 serialization = new JavaScriptBackendSerialization(this); | |
| 545 } | 550 } |
| 546 | 551 |
| 547 ConstantSystem get constantSystem => constants.constantSystem; | 552 ConstantSystem get constantSystem => constants.constantSystem; |
| 548 | 553 |
| 549 DiagnosticReporter get reporter => compiler.reporter; | 554 DiagnosticReporter get reporter => compiler.reporter; |
| 550 | 555 |
| 551 CoreClasses get coreClasses => compiler.coreClasses; | 556 CoreClasses get coreClasses => compiler.coreClasses; |
| 552 | 557 |
| 553 CoreTypes get coreTypes => compiler.coreTypes; | 558 CoreTypes get coreTypes => compiler.coreTypes; |
| 554 | 559 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 } | 598 } |
| 594 | 599 |
| 595 /// The backend must *always* call this method when enqueuing an | 600 /// The backend must *always* call this method when enqueuing an |
| 596 /// element. Calls done by the backend are not seen by global | 601 /// element. Calls done by the backend are not seen by global |
| 597 /// optimizations, so they would make these optimizations unsound. | 602 /// optimizations, so they would make these optimizations unsound. |
| 598 /// Therefore we need to collect the list of helpers the backend may | 603 /// Therefore we need to collect the list of helpers the backend may |
| 599 /// use. | 604 /// use. |
| 600 // TODO(johnniwinther): Replace this with a more precise modelling; type | 605 // TODO(johnniwinther): Replace this with a more precise modelling; type |
| 601 // inference of these elements is disabled. | 606 // inference of these elements is disabled. |
| 602 Element registerBackendUse(Element element) { | 607 Element registerBackendUse(Element element) { |
| 603 if (element != null) { | 608 if (element == null) return null; |
| 604 bool registerUse = false; | 609 assert(invariant(element, _isValidBackendUse(element), |
| 605 if (element == helpers.streamIteratorConstructor || | 610 message: "Backend use of $element is not allowed.")); |
| 606 element == helpers.compiler.symbolConstructor || | 611 helpersUsed.add(element.declaration); |
| 607 element == helpers.compiler.symbolValidatedConstructor || | 612 if (element.isClass && element.isPatched) { |
| 608 element == helpers.syncCompleterConstructor || | 613 // Both declaration and implementation may declare fields, so we |
| 609 element == coreClasses.symbolClass || | 614 // add both to the list of helpers. |
| 610 element == helpers.objectNoSuchMethod) { | 615 helpersUsed.add(element.implementation); |
| 611 // TODO(johnniwinther): These are valid but we could be more precise. | |
| 612 registerUse = true; | |
| 613 } else if (element.implementationLibrary.isPatch || | |
| 614 element.library == helpers.jsHelperLibrary || | |
| 615 element.library == helpers.interceptorsLibrary || | |
| 616 element.library == helpers.isolateHelperLibrary) { | |
| 617 // TODO(johnniwinther): We should be more precise about these. | |
| 618 registerUse = true; | |
| 619 } else if (element == coreClasses.listClass || | |
| 620 element == helpers.mapLiteralClass || | |
| 621 element == coreClasses.functionClass || | |
| 622 element == coreClasses.stringClass) { | |
| 623 // TODO(johnniwinther): Avoid these. | |
| 624 registerUse = true; | |
| 625 } | |
| 626 if (!registerUse) { | |
| 627 assert(invariant(element, false, | |
| 628 message: "Backend use of $element is not allowed.")); | |
| 629 return element; | |
| 630 } | |
| 631 helpersUsed.add(element.declaration); | |
| 632 if (element.isClass && element.isPatched) { | |
| 633 // Both declaration and implementation may declare fields, so we | |
| 634 // add both to the list of helpers. | |
| 635 helpersUsed.add(element.implementation); | |
| 636 } | |
| 637 } | 616 } |
| 638 return element; | 617 return element; |
| 639 } | 618 } |
| 640 | 619 |
| 620 bool _isValidBackendUse(Element element) { | |
| 621 assert(invariant(element, element.isDeclaration, | |
| 622 message: "")); | |
| 623 if (element == helpers.streamIteratorConstructor || | |
| 624 element == helpers.compiler.symbolConstructor || | |
| 625 element == helpers.compiler.symbolValidatedConstructor || | |
| 626 element == helpers.syncCompleterConstructor || | |
| 627 element == coreClasses.symbolClass || | |
| 628 element == helpers.objectNoSuchMethod) { | |
| 629 // TODO(johnniwinther): These are valid but we could be more precise. | |
| 630 return true; | |
| 631 } else if (element.implementationLibrary.isPatch || | |
|
Siggi Cherem (dart-lang)
2016/03/17 15:33:45
nit, can be done later: any reason why not merge a
Johnni Winther
2016/03/18 08:11:32
They are grouped by the TODOs (the reasons for all
| |
| 632 // Needed to detect deserialized injected elements, that is | |
| 633 // element declared in patch files. | |
| 634 (element.library.isPlatformLibrary && | |
| 635 element.sourcePosition.uri.path.contains( | |
| 636 '_internal/js_runtime/lib/')) || | |
| 637 element.library == helpers.jsHelperLibrary || | |
| 638 element.library == helpers.interceptorsLibrary || | |
| 639 element.library == helpers.isolateHelperLibrary) { | |
| 640 // TODO(johnniwinther): We should be more precise about these. | |
| 641 return true; | |
| 642 } else if (element == coreClasses.listClass || | |
| 643 element == helpers.mapLiteralClass || | |
| 644 element == coreClasses.functionClass || | |
| 645 element == coreClasses.stringClass) { | |
| 646 // TODO(johnniwinther): Avoid these. | |
| 647 return true; | |
| 648 } | |
| 649 return false; | |
| 650 } | |
| 651 | |
| 641 bool usedByBackend(Element element) { | 652 bool usedByBackend(Element element) { |
| 642 if (element.isParameter | 653 if (element.isParameter |
| 643 || element.isInitializingFormal | 654 || element.isInitializingFormal |
| 644 || element.isField) { | 655 || element.isField) { |
| 645 if (usedByBackend(element.enclosingElement)) return true; | 656 if (usedByBackend(element.enclosingElement)) return true; |
| 646 } | 657 } |
| 647 return helpersUsed.contains(element.declaration); | 658 return helpersUsed.contains(element.declaration); |
| 648 } | 659 } |
| 649 | 660 |
| 650 bool invokedReflectively(Element element) { | 661 bool invokedReflectively(Element element) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 705 return !selector.isGetter && !compiler.hasIncrementalSupport; | 716 return !selector.isGetter && !compiler.hasIncrementalSupport; |
| 706 } | 717 } |
| 707 | 718 |
| 708 /** | 719 /** |
| 709 * Returns `true` if [member] is called from a subclass via `super`. | 720 * Returns `true` if [member] is called from a subclass via `super`. |
| 710 */ | 721 */ |
| 711 bool isAliasedSuperMember(FunctionElement member) { | 722 bool isAliasedSuperMember(FunctionElement member) { |
| 712 return aliasedSuperMembers.contains(member); | 723 return aliasedSuperMembers.contains(member); |
| 713 } | 724 } |
| 714 | 725 |
| 715 /// The JavaScript names for elements implemented via typed JavaScript | |
| 716 /// interop. | |
| 717 Map<Element, String> jsInteropNames = <Element, String>{}; | |
| 718 | |
| 719 /// The JavaScript names for native JavaScript elements implemented. | |
| 720 Map<Element, String> nativeMemberName = <Element, String>{}; | |
| 721 | |
| 722 /// Tag info for native JavaScript classes names. See | |
| 723 /// [setNativeClassTagInfo]. | |
| 724 Map<ClassElement, String> nativeClassTagInfo = <ClassElement, String>{}; | |
| 725 | |
| 726 /// Returns `true` if [element] is explicitly marked as part of JsInterop. | |
| 727 bool _isJsInterop(Element element) { | |
| 728 return jsInteropNames.containsKey(element.declaration); | |
| 729 } | |
| 730 | |
| 731 /// Returns [element] as an explicit part of JsInterop. The js interop name is | |
| 732 /// expected to be computed later. | |
| 733 void markAsJsInterop(Element element) { | |
| 734 jsInteropNames[element.declaration] = null; | |
| 735 } | |
| 736 | |
| 737 /// Sets the explicit js interop [name] for [element]. | |
| 738 void setJsInteropName(Element element, String name) { | |
| 739 assert(invariant(element, | |
| 740 isJsInterop(element), | |
| 741 message: | |
| 742 'Element $element is not js interop but given a js interop name.')); | |
| 743 jsInteropNames[element.declaration] = name; | |
| 744 } | |
| 745 | |
| 746 /// Returns the explicit js interop name for [element]. | |
| 747 String getJsInteropName(Element element) { | |
| 748 return jsInteropNames[element.declaration]; | |
| 749 } | |
| 750 | |
| 751 /// Returns `true` if [element] is part of JsInterop. | 726 /// Returns `true` if [element] is part of JsInterop. |
| 752 @override | 727 @override |
| 753 bool isJsInterop(Element element) { | 728 bool isJsInterop(Element element) => nativeData.isJsInterop(element); |
| 754 // An function is part of JsInterop in the following cases: | |
| 755 // * It has a jsInteropName annotation | |
| 756 // * It is external member of a class or library tagged as JsInterop. | |
| 757 if (element.isFunction || element.isConstructor || element.isAccessor) { | |
| 758 FunctionElement function = element; | |
| 759 if (!function.isExternal) return false; | |
| 760 | |
| 761 if (_isJsInterop(function)) return true; | |
| 762 if (function.isClassMember) return isJsInterop(function.contextClass); | |
| 763 if (function.isTopLevel) return isJsInterop(function.library); | |
| 764 return false; | |
| 765 } else { | |
| 766 return _isJsInterop(element); | |
| 767 } | |
| 768 } | |
| 769 | |
| 770 /// Returns `true` if the name of [element] is fixed for the generated | |
| 771 /// JavaScript. | |
| 772 bool hasFixedBackendName(Element element) { | |
| 773 return isJsInterop(element) || | |
| 774 nativeMemberName.containsKey(element.declaration); | |
| 775 } | |
| 776 | |
| 777 String _jsNameHelper(Element element) { | |
| 778 String jsInteropName = jsInteropNames[element.declaration]; | |
| 779 assert(invariant(element, | |
| 780 !(_isJsInterop(element) && jsInteropName == null), | |
| 781 message: | |
| 782 'Element $element is js interop but js interop name has not yet ' | |
| 783 'been computed.')); | |
| 784 if (jsInteropName != null && jsInteropName.isNotEmpty) { | |
| 785 return jsInteropName; | |
| 786 } | |
| 787 return element.isLibrary ? 'self' : element.name; | |
| 788 } | |
| 789 | |
| 790 /// Computes the name for [element] to use in the generated JavaScript. This | |
| 791 /// is either given through a native annotation or a js interop annotation. | |
| 792 String getFixedBackendName(Element element) { | |
| 793 String name = nativeMemberName[element.declaration]; | |
| 794 if (name == null && isJsInterop(element)) { | |
| 795 // If an element isJsInterop but _isJsInterop is false that means it is | |
| 796 // considered interop as the parent class is interop. | |
| 797 name = _jsNameHelper( | |
| 798 element.isConstructor ? element.enclosingClass : element); | |
| 799 nativeMemberName[element.declaration] = name; | |
| 800 } | |
| 801 return name; | |
| 802 } | |
| 803 | 729 |
| 804 /// Whether [element] corresponds to a native JavaScript construct either | 730 /// Whether [element] corresponds to a native JavaScript construct either |
| 805 /// through the native mechanism (`@Native(...)` or the `native` pseudo | 731 /// through the native mechanism (`@Native(...)` or the `native` pseudo |
| 806 /// keyword) which is only allowed for internal libraries or via the typed | 732 /// keyword) which is only allowed for internal libraries or via the typed |
| 807 /// JavaScriptInterop mechanism which is allowed for user libraries. | 733 /// JavaScriptInterop mechanism which is allowed for user libraries. |
| 808 @override | 734 @override |
| 809 bool isNative(Element element) { | 735 bool isNative(Element element) => nativeData.isNative(element); |
| 810 if (isJsInterop(element)) return true; | |
| 811 if (element.isClass) { | |
| 812 return nativeClassTagInfo.containsKey(element.declaration); | |
| 813 } else { | |
| 814 return nativeMemberName.containsKey(element.declaration); | |
| 815 } | |
| 816 } | |
| 817 | |
| 818 /// Sets the native [name] for the member [element]. This name is used for | |
| 819 /// [element] in the generated JavaScript. | |
| 820 void setNativeMemberName(MemberElement element, String name) { | |
| 821 // TODO(johnniwinther): Avoid setting this more than once. The enqueuer | |
| 822 // might enqueue [element] several times (before processing it) and computes | |
| 823 // name on each call to `internalAddToWorkList`. | |
| 824 assert(invariant(element, | |
| 825 nativeMemberName[element.declaration] == null || | |
| 826 nativeMemberName[element.declaration] == name, | |
| 827 message: | |
| 828 "Native member name set inconsistently on $element: " | |
| 829 "Existing name '${nativeMemberName[element.declaration]}', " | |
| 830 "new name '$name'.")); | |
| 831 nativeMemberName[element.declaration] = name; | |
| 832 } | |
| 833 | |
| 834 /// Sets the native tag info for [cls]. | |
| 835 /// | |
| 836 /// The tag info string contains comma-separated 'words' which are either | |
| 837 /// dispatch tags (having JavaScript identifier syntax) and directives that | |
| 838 /// begin with `!`. | |
| 839 void setNativeClassTagInfo(ClassElement cls, String tagInfo) { | |
| 840 // TODO(johnniwinther): Assert that this is only called once. The memory | |
| 841 // compiler copies pre-processed elements into a new compiler through | |
| 842 // [Compiler.onLibraryScanned] and thereby causes multiple calls to this | |
| 843 // method. | |
| 844 assert(invariant(cls, | |
| 845 nativeClassTagInfo[cls.declaration] == null || | |
| 846 nativeClassTagInfo[cls.declaration] == tagInfo, | |
| 847 message: | |
| 848 "Native tag info set inconsistently on $cls: " | |
| 849 "Existing tag info '${nativeClassTagInfo[cls.declaration]}', " | |
| 850 "new tag info '$tagInfo'.")); | |
| 851 nativeClassTagInfo[cls.declaration] = tagInfo; | |
| 852 } | |
| 853 | |
| 854 /// Returns the list of native tag words for [cls]. | |
| 855 List<String> getNativeTagsOfClassRaw(ClassElement cls) { | |
| 856 String quotedName = nativeClassTagInfo[cls.declaration]; | |
| 857 return quotedName.substring(1, quotedName.length - 1).split(','); | |
| 858 } | |
| 859 | |
| 860 /// Returns the list of non-directive native tag words for [cls]. | |
| 861 List<String> getNativeTagsOfClass(ClassElement cls) { | |
| 862 return getNativeTagsOfClassRaw(cls).where( | |
| 863 (s) => !s.startsWith('!')).toList(); | |
| 864 } | |
| 865 | |
| 866 /// Returns `true` if [cls] has a `!nonleaf` tag word. | |
| 867 bool hasNativeTagsForcedNonLeaf(ClassElement cls) { | |
| 868 return getNativeTagsOfClassRaw(cls).contains('!nonleaf'); | |
| 869 } | |
| 870 | 736 |
| 871 bool isNativeOrExtendsNative(ClassElement element) { | 737 bool isNativeOrExtendsNative(ClassElement element) { |
| 872 if (element == null) return false; | 738 if (element == null) return false; |
| 873 if (isNative(element) || isJsInterop(element)) { | 739 if (isNative(element) || isJsInterop(element)) { |
| 874 return true; | 740 return true; |
| 875 } | 741 } |
| 876 assert(element.isResolved); | 742 assert(element.isResolved); |
| 877 return isNativeOrExtendsNative(element.superclass); | 743 return isNativeOrExtendsNative(element.superclass); |
| 878 } | 744 } |
| 879 | 745 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1002 | 868 |
| 1003 void validateInterceptorImplementsAllObjectMethods( | 869 void validateInterceptorImplementsAllObjectMethods( |
| 1004 ClassElement interceptorClass) { | 870 ClassElement interceptorClass) { |
| 1005 if (interceptorClass == null) return; | 871 if (interceptorClass == null) return; |
| 1006 interceptorClass.ensureResolved(resolution); | 872 interceptorClass.ensureResolved(resolution); |
| 1007 coreClasses.objectClass.forEachMember((_, Element member) { | 873 coreClasses.objectClass.forEachMember((_, Element member) { |
| 1008 if (member.isGenerativeConstructor) return; | 874 if (member.isGenerativeConstructor) return; |
| 1009 Element interceptorMember = interceptorClass.lookupMember(member.name); | 875 Element interceptorMember = interceptorClass.lookupMember(member.name); |
| 1010 // Interceptors must override all Object methods due to calling convention | 876 // Interceptors must override all Object methods due to calling convention |
| 1011 // differences. | 877 // differences. |
| 1012 assert(interceptorMember.enclosingClass == interceptorClass); | 878 assert(invariant( |
| 879 interceptorMember, | |
| 880 interceptorMember.enclosingClass == interceptorClass, | |
| 881 message: | |
| 882 "Member ${member.name} not overridden in ${interceptorClass}. " | |
| 883 "Found $interceptorMember from " | |
| 884 "${interceptorMember.enclosingClass}.")); | |
| 1013 }); | 885 }); |
| 1014 } | 886 } |
| 1015 | 887 |
| 1016 void addInterceptorsForNativeClassMembers( | 888 void addInterceptorsForNativeClassMembers( |
| 1017 ClassElement cls, Enqueuer enqueuer) { | 889 ClassElement cls, Enqueuer enqueuer) { |
| 1018 if (enqueuer.isResolutionQueue) { | 890 if (enqueuer.isResolutionQueue) { |
| 1019 cls.ensureResolved(resolution); | 891 cls.ensureResolved(resolution); |
| 1020 cls.forEachMember((ClassElement classElement, Element member) { | 892 cls.forEachMember((ClassElement classElement, Element member) { |
| 1021 if (member.name == Identifiers.call) { | 893 if (member.name == Identifiers.call) { |
| 1022 reporter.reportErrorMessage( | 894 reporter.reportErrorMessage( |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1202 compiler.globalDependencies); | 1074 compiler.globalDependencies); |
| 1203 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); | 1075 enqueueClass(enqueuer, helpers.jsJavaScriptObjectClass, registry); |
| 1204 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); | 1076 enqueueClass(enqueuer, helpers.jsPlainJavaScriptObjectClass, registry); |
| 1205 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); | 1077 enqueueClass(enqueuer, helpers.jsJavaScriptFunctionClass, registry); |
| 1206 } else if (cls == helpers.mapLiteralClass) { | 1078 } else if (cls == helpers.mapLiteralClass) { |
| 1207 // For map literals, the dependency between the implementation class | 1079 // For map literals, the dependency between the implementation class |
| 1208 // and [Map] is not visible, so we have to add it manually. | 1080 // and [Map] is not visible, so we have to add it manually. |
| 1209 Element getFactory(String name, int arity) { | 1081 Element getFactory(String name, int arity) { |
| 1210 // The constructor is on the patch class, but dart2js unit tests don't | 1082 // The constructor is on the patch class, but dart2js unit tests don't |
| 1211 // have a patch class. | 1083 // have a patch class. |
| 1212 ClassElement implementation = cls.patch != null ? cls.patch : cls; | 1084 ClassElement implementation = cls.implementation; |
| 1213 ConstructorElement ctor = implementation.lookupConstructor(name); | 1085 ConstructorElement ctor = implementation.lookupConstructor(name); |
| 1214 if (ctor == null || | 1086 if (ctor == null || |
| 1215 (Name.isPrivateName(name) && | 1087 (Name.isPrivateName(name) && |
| 1216 ctor.library != helpers.mapLiteralClass.library)) { | 1088 ctor.library != helpers.mapLiteralClass.library)) { |
| 1217 reporter.internalError( | 1089 reporter.internalError( |
| 1218 helpers.mapLiteralClass, | 1090 helpers.mapLiteralClass, |
| 1219 "Map literal class ${helpers.mapLiteralClass} missing " | 1091 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1220 "'$name' constructor" | 1092 "'$name' constructor" |
| 1221 " ${helpers.mapLiteralClass.constructors}"); | 1093 " ${helpers.mapLiteralClass.constructors}"); |
| 1222 } | 1094 } |
| 1223 return ctor; | 1095 return ctor; |
| 1224 } | 1096 } |
| 1225 Element getMember(String name) { | 1097 Element getMember(String name) { |
| 1226 // The constructor is on the patch class, but dart2js unit tests don't | 1098 // The constructor is on the patch class, but dart2js unit tests don't |
| 1227 // have a patch class. | 1099 // have a patch class. |
| 1228 ClassElement implementation = cls.patch != null ? cls.patch : cls; | 1100 ClassElement implementation = cls.implementation; |
| 1229 Element element = implementation.lookupLocalMember(name); | 1101 Element element = implementation.lookupLocalMember(name); |
| 1230 if (element == null || !element.isFunction || !element.isStatic) { | 1102 if (element == null || !element.isFunction || !element.isStatic) { |
| 1231 reporter.internalError(helpers.mapLiteralClass, | 1103 reporter.internalError(helpers.mapLiteralClass, |
| 1232 "Map literal class ${helpers.mapLiteralClass} missing " | 1104 "Map literal class ${helpers.mapLiteralClass} missing " |
| 1233 "'$name' static member function"); | 1105 "'$name' static member function"); |
| 1234 } | 1106 } |
| 1235 return element; | 1107 return element; |
| 1236 } | 1108 } |
| 1237 helpers.mapLiteralConstructor = getFactory('_literal', 1); | 1109 helpers.mapLiteralConstructor = getFactory('_literal', 1); |
| 1238 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); | 1110 helpers.mapLiteralConstructorEmpty = getFactory('_empty', 0); |
| (...skipping 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2666 @override | 2538 @override |
| 2667 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { | 2539 Uri resolvePatchUri(String libraryName, Uri platformConfigUri) { |
| 2668 String patchLocation = _patchLocations[libraryName]; | 2540 String patchLocation = _patchLocations[libraryName]; |
| 2669 if (patchLocation == null) return null; | 2541 if (patchLocation == null) return null; |
| 2670 return platformConfigUri.resolve(patchLocation); | 2542 return platformConfigUri.resolve(patchLocation); |
| 2671 } | 2543 } |
| 2672 | 2544 |
| 2673 @override | 2545 @override |
| 2674 ImpactStrategy createImpactStrategy( | 2546 ImpactStrategy createImpactStrategy( |
| 2675 {bool supportDeferredLoad: true, | 2547 {bool supportDeferredLoad: true, |
| 2676 bool supportDumpInfo: true}) { | 2548 bool supportDumpInfo: true, |
| 2549 bool supportSerialization: true}) { | |
| 2677 return new JavaScriptImpactStrategy( | 2550 return new JavaScriptImpactStrategy( |
| 2678 resolution, | 2551 resolution, |
| 2679 compiler.dumpInfoTask, | 2552 compiler.dumpInfoTask, |
| 2680 supportDeferredLoad: supportDeferredLoad, | 2553 supportDeferredLoad: supportDeferredLoad, |
| 2681 supportDumpInfo: supportDumpInfo); | 2554 supportDumpInfo: supportDumpInfo, |
| 2555 supportSerialization: supportSerialization); | |
| 2682 } | 2556 } |
| 2683 } | 2557 } |
| 2684 | 2558 |
| 2685 /// Handling of special annotations for tests. | 2559 /// Handling of special annotations for tests. |
| 2686 class Annotations { | 2560 class Annotations { |
| 2687 static final Uri PACKAGE_EXPECT = | 2561 static final Uri PACKAGE_EXPECT = |
| 2688 new Uri(scheme: 'package', path: 'expect/expect.dart'); | 2562 new Uri(scheme: 'package', path: 'expect/expect.dart'); |
| 2689 | 2563 |
| 2690 final Compiler compiler; | 2564 final Compiler compiler; |
| 2691 | 2565 |
| (...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3147 final Element annotatedElement; | 3021 final Element annotatedElement; |
| 3148 | 3022 |
| 3149 const Dependency(this.constant, this.annotatedElement); | 3023 const Dependency(this.constant, this.annotatedElement); |
| 3150 } | 3024 } |
| 3151 | 3025 |
| 3152 class JavaScriptImpactStrategy extends ImpactStrategy { | 3026 class JavaScriptImpactStrategy extends ImpactStrategy { |
| 3153 final Resolution resolution; | 3027 final Resolution resolution; |
| 3154 final DumpInfoTask dumpInfoTask; | 3028 final DumpInfoTask dumpInfoTask; |
| 3155 final bool supportDeferredLoad; | 3029 final bool supportDeferredLoad; |
| 3156 final bool supportDumpInfo; | 3030 final bool supportDumpInfo; |
| 3031 final bool supportSerialization; | |
| 3157 | 3032 |
| 3158 JavaScriptImpactStrategy(this.resolution, | 3033 JavaScriptImpactStrategy(this.resolution, |
| 3159 this.dumpInfoTask, | 3034 this.dumpInfoTask, |
| 3160 {this.supportDeferredLoad, | 3035 {this.supportDeferredLoad, |
| 3161 this.supportDumpInfo}); | 3036 this.supportDumpInfo, |
| 3037 this.supportSerialization}); | |
| 3162 | 3038 |
| 3163 @override | 3039 @override |
| 3164 void visitImpact(Element element, | 3040 void visitImpact(Element element, |
| 3165 WorldImpact impact, | 3041 WorldImpact impact, |
| 3166 WorldImpactVisitor visitor, | 3042 WorldImpactVisitor visitor, |
| 3167 ImpactUseCase impactUse) { | 3043 ImpactUseCase impactUse) { |
| 3168 // TODO(johnniwinther): Compute the application strategy once for each use. | 3044 // TODO(johnniwinther): Compute the application strategy once for each use. |
| 3169 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { | 3045 if (impactUse == ResolutionEnqueuer.IMPACT_USE) { |
| 3170 if (supportDeferredLoad) { | 3046 if (supportDeferredLoad || supportSerialization) { |
| 3171 impact.apply(visitor); | 3047 impact.apply(visitor); |
| 3172 } else { | 3048 } else { |
| 3173 impact.apply(visitor); | 3049 impact.apply(visitor); |
| 3174 resolution.uncacheWorldImpact(element); | 3050 resolution.uncacheWorldImpact(element); |
| 3175 } | 3051 } |
| 3176 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { | 3052 } else if (impactUse == DeferredLoadTask.IMPACT_USE) { |
| 3177 impact.apply(visitor); | 3053 impact.apply(visitor); |
| 3178 // Impacts are uncached globally in [onImpactUsed]. | 3054 // Impacts are uncached globally in [onImpactUsed]. |
| 3179 } else if (impactUse == DumpInfoTask.IMPACT_USE) { | 3055 } else if (impactUse == DumpInfoTask.IMPACT_USE) { |
| 3180 impact.apply(visitor); | 3056 impact.apply(visitor); |
| 3181 dumpInfoTask.unregisterImpact(element); | 3057 dumpInfoTask.unregisterImpact(element); |
| 3182 } else { | 3058 } else { |
| 3183 impact.apply(visitor); | 3059 impact.apply(visitor); |
| 3184 } | 3060 } |
| 3185 } | 3061 } |
| 3186 | 3062 |
| 3187 @override | 3063 @override |
| 3188 void onImpactUsed(ImpactUseCase impactUse) { | 3064 void onImpactUsed(ImpactUseCase impactUse) { |
| 3189 if (impactUse == DeferredLoadTask.IMPACT_USE) { | 3065 if (impactUse == DeferredLoadTask.IMPACT_USE && |
| 3066 !supportSerialization) { | |
| 3067 // TODO(johnniwinther): Allow emptying when serialization has been | |
| 3068 // performed. | |
| 3190 resolution.emptyCache(); | 3069 resolution.emptyCache(); |
| 3191 } | 3070 } |
| 3192 } | 3071 } |
| 3193 } | 3072 } |
| OLD | NEW |