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 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 ConstantEmitter constantEmitter; | 70 ConstantEmitter constantEmitter; |
| 71 NativeEmitter nativeEmitter; | 71 NativeEmitter nativeEmitter; |
| 72 CodeBuffer mainBuffer; | 72 CodeBuffer mainBuffer; |
| 73 final CodeBuffer deferredLibraries = new CodeBuffer(); | 73 final CodeBuffer deferredLibraries = new CodeBuffer(); |
| 74 final CodeBuffer deferredConstants = new CodeBuffer(); | 74 final CodeBuffer deferredConstants = new CodeBuffer(); |
| 75 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 75 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 76 well as in the generated code. */ | 76 well as in the generated code. */ |
| 77 String isolateProperties; | 77 String isolateProperties; |
| 78 String classesCollector; | 78 String classesCollector; |
| 79 final Set<ClassElement> neededClasses = new Set<ClassElement>(); | 79 final Set<ClassElement> neededClasses = new Set<ClassElement>(); |
| 80 final Set<ClassElement> rtiNeededClasses = new Set<ClassElement>(); | |
| 80 final List<ClassElement> regularClasses = <ClassElement>[]; | 81 final List<ClassElement> regularClasses = <ClassElement>[]; |
| 81 final List<ClassElement> deferredClasses = <ClassElement>[]; | 82 final List<ClassElement> deferredClasses = <ClassElement>[]; |
| 82 final List<ClassElement> nativeClasses = <ClassElement>[]; | 83 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 83 final List<Selector> trivialNsmHandlers = <Selector>[]; | 84 final List<Selector> trivialNsmHandlers = <Selector>[]; |
| 84 final Map<String, String> mangledFieldNames = <String, String>{}; | 85 final Map<String, String> mangledFieldNames = <String, String>{}; |
| 85 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; | 86 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
| 86 final Set<String> recordedMangledNames = new Set<String>(); | 87 final Set<String> recordedMangledNames = new Set<String>(); |
| 87 final Set<String> interceptorInvocationNames = new Set<String>(); | 88 final Set<String> interceptorInvocationNames = new Set<String>(); |
| 88 | 89 |
| 89 /// A list of JS expressions that represent metadata, parameter names and | 90 /// A list of JS expressions that represent metadata, parameter names and |
| (...skipping 1581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1671 } | 1672 } |
| 1672 assert(invariant(member, previousName == memberName, | 1673 assert(invariant(member, previousName == memberName, |
| 1673 message: '$previousName != ${memberName}')); | 1674 message: '$previousName != ${memberName}')); |
| 1674 } | 1675 } |
| 1675 | 1676 |
| 1676 /// Returns `true` if fields added. | 1677 /// Returns `true` if fields added. |
| 1677 bool emitClassFields(ClassElement classElement, | 1678 bool emitClassFields(ClassElement classElement, |
| 1678 ClassBuilder builder, | 1679 ClassBuilder builder, |
| 1679 String superName, | 1680 String superName, |
| 1680 { bool classIsNative: false, | 1681 { bool classIsNative: false, |
| 1681 bool emitStatics: false }) { | 1682 bool emitStatics: false, |
| 1683 bool onlyForRti: false }) { | |
| 1684 assert(!emitStatics || !onlyForRti); | |
| 1682 StringBuffer buffer = new StringBuffer(); | 1685 StringBuffer buffer = new StringBuffer(); |
| 1683 if (emitStatics) { | 1686 if (emitStatics) { |
| 1684 assert(invariant(classElement, superName == null, message: superName)); | 1687 assert(invariant(classElement, superName == null, message: superName)); |
| 1685 } else { | 1688 } else { |
| 1686 assert(invariant(classElement, superName != null)); | 1689 assert(invariant(classElement, superName != null)); |
| 1687 String nativeName = | 1690 String nativeName = |
| 1688 namer.getPrimitiveInterceptorRuntimeName(classElement); | 1691 namer.getPrimitiveInterceptorRuntimeName(classElement); |
| 1689 if (nativeName != null) { | 1692 if (nativeName != null) { |
| 1690 buffer.write('$nativeName/'); | 1693 buffer.write('$nativeName/'); |
| 1691 } | 1694 } |
| 1692 buffer.write('$superName;'); | 1695 buffer.write('$superName;'); |
| 1693 } | 1696 } |
| 1694 int bufferClassLength = buffer.length; | 1697 int bufferClassLength = buffer.length; |
| 1695 | 1698 |
| 1696 String separator = ''; | 1699 String separator = ''; |
| 1697 | 1700 |
| 1698 var fieldMetadata = []; | 1701 var fieldMetadata = []; |
| 1699 bool hasMetadata = false; | 1702 bool hasMetadata = false; |
| 1700 | 1703 |
| 1701 visitClassFields(classElement, emitStatics, | 1704 if (!onlyForRti) { |
| 1702 (Element member, | 1705 visitClassFields(classElement, emitStatics, |
|
ngeoffray
2013/07/22 12:04:03
MAke the following anonymous function a function i
ahe
2013/07/22 12:32:05
I thought of that, but it would require more param
| |
| 1703 String name, | 1706 (Element member, |
| 1704 String accessorName, | 1707 String name, |
| 1705 bool needsGetter, | 1708 String accessorName, |
| 1706 bool needsSetter, | 1709 bool needsGetter, |
| 1707 bool needsCheckedSetter) { | 1710 bool needsSetter, |
| 1708 // Ignore needsCheckedSetter - that is handled below. | 1711 bool needsCheckedSetter) { |
| 1709 bool needsAccessor = (needsGetter || needsSetter); | 1712 // Ignore needsCheckedSetter - that is handled below. |
| 1710 // We need to output the fields for non-native classes so we can auto- | 1713 bool needsAccessor = (needsGetter || needsSetter); |
| 1711 // generate the constructor. For native classes there are no | 1714 // We need to output the fields for non-native classes so we can auto- |
| 1712 // constructors, so we don't need the fields unless we are generating | 1715 // generate the constructor. For native classes there are no |
| 1713 // accessors at runtime. | 1716 // constructors, so we don't need the fields unless we are generating |
| 1714 if (!classIsNative || needsAccessor) { | 1717 // accessors at runtime. |
| 1715 buffer.write(separator); | 1718 if (!classIsNative || needsAccessor) { |
| 1716 separator = ','; | 1719 buffer.write(separator); |
| 1717 var metadata = buildMetadataFunction(member); | 1720 separator = ','; |
| 1718 if (metadata != null) { | 1721 var metadata = buildMetadataFunction(member); |
| 1719 hasMetadata = true; | 1722 if (metadata != null) { |
| 1720 } else { | 1723 hasMetadata = true; |
| 1721 metadata = new jsAst.LiteralNull(); | 1724 } else { |
| 1722 } | 1725 metadata = new jsAst.LiteralNull(); |
| 1723 fieldMetadata.add(metadata); | |
| 1724 recordMangledField(member, accessorName, member.name.slowToString()); | |
| 1725 if (!needsAccessor) { | |
| 1726 // Emit field for constructor generation. | |
| 1727 assert(!classIsNative); | |
| 1728 buffer.write(name); | |
| 1729 } else { | |
| 1730 // Emit (possibly renaming) field name so we can add accessors at | |
| 1731 // runtime. | |
| 1732 buffer.write(accessorName); | |
| 1733 if (name != accessorName) { | |
| 1734 buffer.write(':$name'); | |
| 1735 // Only the native classes can have renaming accessors. | |
| 1736 assert(classIsNative); | |
| 1737 } | 1726 } |
| 1727 fieldMetadata.add(metadata); | |
| 1728 recordMangledField(member, accessorName, member.name.slowToString()); | |
| 1729 if (!needsAccessor) { | |
| 1730 // Emit field for constructor generation. | |
| 1731 assert(!classIsNative); | |
| 1732 buffer.write(name); | |
| 1733 } else { | |
| 1734 // Emit (possibly renaming) field name so we can add accessors at | |
| 1735 // runtime. | |
| 1736 buffer.write(accessorName); | |
| 1737 if (name != accessorName) { | |
| 1738 buffer.write(':$name'); | |
| 1739 // Only the native classes can have renaming accessors. | |
| 1740 assert(classIsNative); | |
| 1741 } | |
| 1738 | 1742 |
| 1739 int getterCode = 0; | 1743 int getterCode = 0; |
| 1740 if (needsGetter) { | 1744 if (needsGetter) { |
| 1741 // 01: function() { return this.field; } | 1745 // 01: function() { return this.field; } |
| 1742 // 10: function(receiver) { return receiver.field; } | 1746 // 10: function(receiver) { return receiver.field; } |
| 1743 // 11: function(receiver) { return this.field; } | 1747 // 11: function(receiver) { return this.field; } |
| 1744 getterCode += backend.fieldHasInterceptedGetter(member) ? 2 : 0; | 1748 if (member.isInstanceMember()) { |
|
sra1
2013/07/19 22:07:57
When is this false?
My understanding is that memb
ahe
2013/07/20 12:16:52
For static fields.
ahe
2013/07/22 12:32:05
This is documented in CL 19676002.
| |
| 1745 getterCode += backend.isInterceptorClass(classElement) ? 0 : 1; | 1749 getterCode += backend.fieldHasInterceptedGetter(member) ? 2 : 0; |
| 1746 // TODO(sra): 'isInterceptorClass' might not be the correct test for | 1750 getterCode += backend.isInterceptorClass(classElement) ? 0 : 1; |
| 1747 // methods forced to use the interceptor convention because the | 1751 // TODO(sra): 'isInterceptorClass' might not be the correct |
| 1748 // method's class was elsewhere mixed-in to an interceptor. | 1752 // test for methods forced to use the interceptor convention |
| 1749 assert(!member.isInstanceMember() || getterCode != 0); | 1753 // because the method's class was elsewhere mixed-in to an |
| 1750 } | 1754 // interceptor. |
| 1751 int setterCode = 0; | 1755 assert(getterCode != 0); |
| 1752 if (needsSetter) { | 1756 } else { |
| 1753 // 01: function(value) { this.field = value; } | 1757 getterCode = 1; |
| 1754 // 10: function(receiver, value) { receiver.field = value; } | 1758 } |
| 1755 // 11: function(receiver, value) { this.field = value; } | 1759 } |
| 1756 setterCode += backend.fieldHasInterceptedSetter(member) ? 2 : 0; | 1760 int setterCode = 0; |
| 1757 setterCode += backend.isInterceptorClass(classElement) ? 0 : 1; | 1761 if (needsSetter) { |
| 1758 assert(!member.isInstanceMember() || setterCode != 0); | 1762 // 01: function(value) { this.field = value; } |
| 1759 } | 1763 // 10: function(receiver, value) { receiver.field = value; } |
| 1760 int code = getterCode + (setterCode << 2); | 1764 // 11: function(receiver, value) { this.field = value; } |
| 1761 if (code == 0) { | 1765 if (member.isInstanceMember()) { |
| 1762 compiler.reportInternalError( | 1766 setterCode += backend.fieldHasInterceptedSetter(member) ? 2 : 0; |
| 1763 member, 'Internal error: code is 0 ($classElement/$member)'); | 1767 setterCode += backend.isInterceptorClass(classElement) ? 0 : 1; |
| 1764 } else { | 1768 assert(setterCode != 0); |
| 1765 buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]); | 1769 } else { |
| 1770 setterCode = 1; | |
| 1771 } | |
| 1772 } | |
| 1773 int code = getterCode + (setterCode << 2); | |
| 1774 if (code == 0) { | |
|
sra1
2013/07/19 22:07:57
This function is getting a bit long.
Maybe break o
ahe
2013/07/20 12:16:52
Good idea.
ahe
2013/07/22 12:32:05
I'll do that in another CL to reduce conflicts wit
| |
| 1775 compiler.reportInternalError( | |
| 1776 member, 'Internal error: code is 0 ($classElement/$member)'); | |
| 1777 } else { | |
| 1778 buffer.write(FIELD_CODE_CHARACTERS[code - FIRST_FIELD_CODE]); | |
| 1779 } | |
| 1766 } | 1780 } |
| 1767 } | 1781 } |
| 1768 } | 1782 }); |
| 1769 }); | 1783 } |
| 1770 | 1784 |
| 1771 bool fieldsAdded = buffer.length > bufferClassLength; | 1785 bool fieldsAdded = buffer.length > bufferClassLength; |
| 1772 String compactClassData = buffer.toString(); | 1786 String compactClassData = buffer.toString(); |
| 1773 jsAst.Expression classDataNode = js.string(compactClassData); | 1787 jsAst.Expression classDataNode = js.string(compactClassData); |
| 1774 if (hasMetadata) { | 1788 if (hasMetadata) { |
| 1775 fieldMetadata.insert(0, classDataNode); | 1789 fieldMetadata.insert(0, classDataNode); |
| 1776 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata); | 1790 classDataNode = new jsAst.ArrayInitializer.from(fieldMetadata); |
| 1777 } | 1791 } |
| 1778 builder.addProperty('', classDataNode); | 1792 builder.addProperty('', classDataNode); |
| 1779 return fieldsAdded; | 1793 return fieldsAdded; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1805 }); | 1819 }); |
| 1806 }); | 1820 }); |
| 1807 } | 1821 } |
| 1808 | 1822 |
| 1809 /** | 1823 /** |
| 1810 * Documentation wanted -- johnniwinther | 1824 * Documentation wanted -- johnniwinther |
| 1811 * | 1825 * |
| 1812 * Invariant: [classElement] must be a declaration element. | 1826 * Invariant: [classElement] must be a declaration element. |
| 1813 */ | 1827 */ |
| 1814 void generateClass(ClassElement classElement, CodeBuffer buffer) { | 1828 void generateClass(ClassElement classElement, CodeBuffer buffer) { |
| 1829 final onlyForRti = rtiNeededClasses.contains(classElement); | |
| 1830 | |
| 1815 assert(invariant(classElement, classElement.isDeclaration)); | 1831 assert(invariant(classElement, classElement.isDeclaration)); |
| 1816 assert(invariant(classElement, !classElement.isNative())); | 1832 assert(invariant(classElement, !classElement.isNative() || onlyForRti)); |
| 1817 | 1833 |
| 1818 needsDefineClass = true; | 1834 needsDefineClass = true; |
| 1819 String className = namer.getName(classElement); | 1835 String className = namer.getName(classElement); |
| 1820 | 1836 |
| 1821 ClassElement superclass = classElement.superclass; | 1837 ClassElement superclass = classElement.superclass; |
| 1822 String superName = ""; | 1838 String superName = ""; |
| 1823 if (superclass != null) { | 1839 if (superclass != null) { |
| 1824 superName = namer.getName(superclass); | 1840 superName = namer.getName(superclass); |
| 1825 } | 1841 } |
| 1826 String runtimeName = | 1842 String runtimeName = |
| 1827 namer.getPrimitiveInterceptorRuntimeName(classElement); | 1843 namer.getPrimitiveInterceptorRuntimeName(classElement); |
| 1828 | 1844 |
| 1829 if (classElement.isMixinApplication) { | 1845 if (classElement.isMixinApplication) { |
| 1830 String mixinName = namer.getName(computeMixinClass(classElement)); | 1846 String mixinName = namer.getName(computeMixinClass(classElement)); |
| 1831 superName = '$superName+$mixinName'; | 1847 superName = '$superName+$mixinName'; |
| 1832 needsMixinSupport = true; | 1848 needsMixinSupport = true; |
| 1833 } | 1849 } |
| 1834 | 1850 |
| 1835 ClassBuilder builder = new ClassBuilder(); | 1851 ClassBuilder builder = new ClassBuilder(); |
| 1836 emitClassConstructor(classElement, builder); | 1852 emitClassConstructor(classElement, builder); |
| 1837 emitSuper(superName, builder); | 1853 emitSuper(superName, builder); |
| 1838 emitRuntimeName(runtimeName, builder); | 1854 emitRuntimeName(runtimeName, builder); |
| 1839 emitClassFields(classElement, builder, superName); | 1855 emitClassFields(classElement, builder, superName, onlyForRti: onlyForRti); |
| 1840 emitClassGettersSetters(classElement, builder); | 1856 emitClassGettersSetters(classElement, builder); |
| 1841 if (!classElement.isMixinApplication) { | 1857 if (!classElement.isMixinApplication) { |
| 1842 emitInstanceMembers(classElement, builder); | 1858 emitInstanceMembers(classElement, builder); |
| 1843 } | 1859 } |
| 1844 emitIsTests(classElement, builder); | 1860 emitIsTests(classElement, builder); |
| 1845 | 1861 |
| 1846 emitClassBuilderWithReflectionData( | 1862 emitClassBuilderWithReflectionData( |
| 1847 className, classElement, builder, buffer); | 1863 className, classElement, builder, buffer); |
| 1848 } | 1864 } |
| 1849 | 1865 |
| (...skipping 1236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3086 // 1. We need to generate all classes that are instantiated. | 3102 // 1. We need to generate all classes that are instantiated. |
| 3087 addClassesWithSuperclasses(instantiatedClasses); | 3103 addClassesWithSuperclasses(instantiatedClasses); |
| 3088 | 3104 |
| 3089 // 2. Add all classes used as mixins. | 3105 // 2. Add all classes used as mixins. |
| 3090 Set<ClassElement> mixinClasses = neededClasses | 3106 Set<ClassElement> mixinClasses = neededClasses |
| 3091 .where((ClassElement element) => element.isMixinApplication) | 3107 .where((ClassElement element) => element.isMixinApplication) |
| 3092 .map(computeMixinClass) | 3108 .map(computeMixinClass) |
| 3093 .toSet(); | 3109 .toSet(); |
| 3094 neededClasses.addAll(mixinClasses); | 3110 neededClasses.addAll(mixinClasses); |
| 3095 | 3111 |
| 3096 // 3a. Add classes that are referenced by type arguments or substitutions in | 3112 // 3. If we need noSuchMethod support, we run through all needed |
| 3097 // argument checks. | |
| 3098 // TODO(karlklose): merge this case with 3b when unifying argument and | |
| 3099 // object checks. | |
| 3100 RuntimeTypes rti = backend.rti; | |
| 3101 backend.rti.getRequiredArgumentClasses(backend).forEach((ClassElement c) { | |
| 3102 // Types that we represent with JS native types (like int and String) do | |
| 3103 // not need a class definition as we use the interceptor classes instead. | |
| 3104 if (!rti.isJsNative(c)) { | |
| 3105 addClassWithSuperclasses(c); | |
| 3106 } | |
| 3107 }); | |
| 3108 | |
| 3109 // 3b. Add classes that are referenced by substitutions in object checks and | |
| 3110 // their superclasses. | |
| 3111 TypeChecks requiredChecks = | |
| 3112 backend.rti.computeChecks(neededClasses, checkedClasses); | |
| 3113 Set<ClassElement> classesUsedInSubstitutions = | |
| 3114 rti.getClassesUsedInSubstitutions(backend, requiredChecks); | |
| 3115 addClassesWithSuperclasses(classesUsedInSubstitutions); | |
| 3116 | |
| 3117 // 3c. Add classes that contain checked generic function types. These are | |
| 3118 // needed to store the signature encoding. | |
| 3119 for (FunctionType type in checkedFunctionTypes) { | |
| 3120 ClassElement contextClass = Types.getClassContext(type); | |
| 3121 if (contextClass != null) { | |
| 3122 neededClasses.add(contextClass); | |
| 3123 } | |
| 3124 } | |
| 3125 | |
| 3126 // 4. Finally, sort the classes. | |
| 3127 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | |
| 3128 | |
| 3129 // If we need noSuchMethod support, we run through all needed | |
| 3130 // classes to figure out if we need the support on any native | 3113 // classes to figure out if we need the support on any native |
| 3131 // class. If so, we let the native emitter deal with it. | 3114 // class. If so, we let the native emitter deal with it. |
| 3132 if (compiler.enabledNoSuchMethod) { | 3115 if (compiler.enabledNoSuchMethod) { |
| 3133 SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD; | 3116 SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD; |
| 3134 Selector noSuchMethodSelector = compiler.noSuchMethodSelector; | 3117 Selector noSuchMethodSelector = compiler.noSuchMethodSelector; |
| 3135 for (ClassElement element in sortedClasses) { | 3118 for (ClassElement element in neededClasses) { |
| 3136 if (!element.isNative()) continue; | 3119 if (!element.isNative()) continue; |
| 3137 Element member = element.lookupLocalMember(noSuchMethodName); | 3120 Element member = element.lookupLocalMember(noSuchMethodName); |
| 3138 if (member == null) continue; | 3121 if (member == null) continue; |
| 3139 if (noSuchMethodSelector.applies(member, compiler)) { | 3122 if (noSuchMethodSelector.applies(member, compiler)) { |
| 3140 nativeEmitter.handleNoSuchMethod = true; | 3123 nativeEmitter.handleNoSuchMethod = true; |
| 3141 break; | 3124 break; |
| 3142 } | 3125 } |
| 3143 } | 3126 } |
| 3144 } | 3127 } |
| 3145 | 3128 |
| 3129 // 4. Find all classes needed for rti. | |
|
sra1
2013/07/19 22:07:57
Start at 4?
ahe
2013/07/20 12:16:52
I'm not sure what you mean by that. If this step w
| |
| 3130 computeRtiNeededClasses(); | |
| 3131 rtiNeededClasses.removeAll(neededClasses); | |
| 3132 neededClasses.addAll(rtiNeededClasses); | |
| 3133 | |
| 3134 // 5. Finally, sort the classes. | |
| 3135 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | |
| 3136 | |
| 3146 for (ClassElement element in sortedClasses) { | 3137 for (ClassElement element in sortedClasses) { |
| 3147 if (element.isNative()) { | 3138 if (rtiNeededClasses.contains(element)) { |
| 3139 regularClasses.add(element); | |
| 3140 } else if (element.isNative()) { | |
| 3148 // For now, native classes cannot be deferred. | 3141 // For now, native classes cannot be deferred. |
| 3149 nativeClasses.add(element); | 3142 nativeClasses.add(element); |
| 3150 } else if (isDeferred(element)) { | 3143 } else if (isDeferred(element)) { |
| 3151 deferredClasses.add(element); | 3144 deferredClasses.add(element); |
| 3152 } else { | 3145 } else { |
| 3153 regularClasses.add(element); | 3146 regularClasses.add(element); |
| 3154 } | 3147 } |
| 3155 } | 3148 } |
| 3156 } | 3149 } |
| 3157 | 3150 |
| 3151 Set<ClassElement> computeRtiNeededClasses() { | |
| 3152 void addClassWithSuperclasses(ClassElement cls) { | |
| 3153 if (cls.name == const SourceString('CssStyleDeclaration')) { | |
| 3154 throw 'hest'; | |
| 3155 } | |
| 3156 rtiNeededClasses.add(cls); | |
| 3157 for (ClassElement superclass = cls.superclass; | |
| 3158 superclass != null; | |
| 3159 superclass = superclass.superclass) { | |
| 3160 if (superclass.name == const SourceString('CssStyleDeclaration')) { | |
| 3161 throw 'fisk'; | |
|
ngeoffray
2013/07/22 12:04:03
fisk -> fish. Or you could just get rid of this co
ahe
2013/07/22 12:32:05
This is debug code I overlooked.
| |
| 3162 } | |
| 3163 rtiNeededClasses.add(superclass); | |
| 3164 } | |
| 3165 } | |
| 3166 | |
| 3167 void addClassesWithSuperclasses(Iterable<ClassElement> classes) { | |
| 3168 for (ClassElement cls in classes) { | |
| 3169 addClassWithSuperclasses(cls); | |
| 3170 } | |
| 3171 } | |
| 3172 | |
| 3173 // 1. Add classes that are referenced by type arguments or substitutions in | |
| 3174 // argument checks. | |
| 3175 // TODO(karlklose): merge this case with 2 when unifying argument and | |
| 3176 // object checks. | |
| 3177 RuntimeTypes rti = backend.rti; | |
| 3178 rti.getRequiredArgumentClasses(backend).forEach((ClassElement c) { | |
| 3179 // Types that we represent with JS native types (like int and String) do | |
| 3180 // not need a class definition as we use the interceptor classes instead. | |
| 3181 if (!rti.isJsNative(c)) { | |
| 3182 addClassWithSuperclasses(c); | |
| 3183 } | |
| 3184 }); | |
| 3185 | |
| 3186 // 2. Add classes that are referenced by substitutions in object checks and | |
| 3187 // their superclasses. | |
| 3188 TypeChecks requiredChecks = | |
| 3189 rti.computeChecks(rtiNeededClasses, checkedClasses); | |
| 3190 Set<ClassElement> classesUsedInSubstitutions = | |
| 3191 rti.getClassesUsedInSubstitutions(backend, requiredChecks); | |
| 3192 addClassesWithSuperclasses(classesUsedInSubstitutions); | |
| 3193 | |
| 3194 // 3. Add classes that contain checked generic function types. These are | |
| 3195 // needed to store the signature encoding. | |
| 3196 for (FunctionType type in checkedFunctionTypes) { | |
| 3197 ClassElement contextClass = Types.getClassContext(type); | |
| 3198 if (contextClass != null) { | |
| 3199 rtiNeededClasses.add(contextClass); | |
| 3200 } | |
| 3201 } | |
| 3202 | |
| 3203 return rtiNeededClasses; | |
| 3204 } | |
| 3205 | |
| 3158 // Optimize performance critical one shot interceptors. | 3206 // Optimize performance critical one shot interceptors. |
| 3159 jsAst.Statement tryOptimizeOneShotInterceptor(Selector selector, | 3207 jsAst.Statement tryOptimizeOneShotInterceptor(Selector selector, |
| 3160 Set<ClassElement> classes) { | 3208 Set<ClassElement> classes) { |
| 3161 jsAst.Expression isNumber(String variable) { | 3209 jsAst.Expression isNumber(String variable) { |
| 3162 return js('typeof $variable == "number"'); | 3210 return js('typeof $variable == "number"'); |
| 3163 } | 3211 } |
| 3164 | 3212 |
| 3165 jsAst.Expression isNotObject(String variable) { | 3213 jsAst.Expression isNotObject(String variable) { |
| 3166 return js('typeof $variable != "object"'); | 3214 return js('typeof $variable != "object"'); |
| 3167 } | 3215 } |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3907 | 3955 |
| 3908 const String HOOKS_API_USAGE = """ | 3956 const String HOOKS_API_USAGE = """ |
| 3909 // The code supports the following hooks: | 3957 // The code supports the following hooks: |
| 3910 // dartPrint(message) - if this function is defined it is called | 3958 // dartPrint(message) - if this function is defined it is called |
| 3911 // instead of the Dart [print] method. | 3959 // instead of the Dart [print] method. |
| 3912 // dartMainRunner(main) - if this function is defined, the Dart [main] | 3960 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 3913 // method will not be invoked directly. | 3961 // method will not be invoked directly. |
| 3914 // Instead, a closure that will invoke [main] is | 3962 // Instead, a closure that will invoke [main] is |
| 3915 // passed to [dartMainRunner]. | 3963 // passed to [dartMainRunner]. |
| 3916 """; | 3964 """; |
| OLD | NEW |