| 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 30 matching lines...) Expand all Loading... |
| 41 // Has the same signature as [DefineStubFunction]. | 41 // Has the same signature as [DefineStubFunction]. |
| 42 void addProperty(String name, jsAst.Expression value) { | 42 void addProperty(String name, jsAst.Expression value) { |
| 43 properties.add(new jsAst.Property(js.string(name), value)); | 43 properties.add(new jsAst.Property(js.string(name), value)); |
| 44 } | 44 } |
| 45 | 45 |
| 46 jsAst.Expression toObjectInitializer() { | 46 jsAst.Expression toObjectInitializer() { |
| 47 return new jsAst.ObjectInitializer(properties); | 47 return new jsAst.ObjectInitializer(properties); |
| 48 } | 48 } |
| 49 } | 49 } |
| 50 | 50 |
| 51 // Function signatures used in the generation of runtime type information. |
| 52 typedef void FunctionTypeSignatureEmitter(Element method, |
| 53 FunctionType methodType); |
| 54 // TODO(johnniwinther): Clean up terminology for rti in the emitter. |
| 55 typedef void FunctionTypeTestEmitter(FunctionType functionType); |
| 56 typedef void SubstitutionEmitter(Element element, {bool emitNull}); |
| 57 |
| 51 /** | 58 /** |
| 52 * Generates the code for all used classes in the program. Static fields (even | 59 * Generates the code for all used classes in the program. Static fields (even |
| 53 * in classes) are ignored, since they can be treated as non-class elements. | 60 * in classes) are ignored, since they can be treated as non-class elements. |
| 54 * | 61 * |
| 55 * The code for the containing (used) methods must exist in the [:universe:]. | 62 * The code for the containing (used) methods must exist in the [:universe:]. |
| 56 */ | 63 */ |
| 57 class CodeEmitterTask extends CompilerTask { | 64 class CodeEmitterTask extends CompilerTask { |
| 58 bool needsInheritFunction = false; | 65 bool needsInheritFunction = false; |
| 59 bool needsDefineClass = false; | 66 bool needsDefineClass = false; |
| 60 bool needsMixinSupport = false; | 67 bool needsMixinSupport = false; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 112 |
| 106 /** | 113 /** |
| 107 * Raw ClassElement symbols occuring in is-checks and type assertions. If the | 114 * Raw ClassElement symbols occuring in is-checks and type assertions. If the |
| 108 * program contains parameterized checks `x is Set<int>` and | 115 * program contains parameterized checks `x is Set<int>` and |
| 109 * `x is Set<String>` then the ClassElement `Set` will occur once in | 116 * `x is Set<String>` then the ClassElement `Set` will occur once in |
| 110 * [checkedClasses]. | 117 * [checkedClasses]. |
| 111 */ | 118 */ |
| 112 Set<ClassElement> checkedClasses; | 119 Set<ClassElement> checkedClasses; |
| 113 | 120 |
| 114 /** | 121 /** |
| 115 * Raw Typedef symbols occuring in is-checks and type assertions. If the | 122 * The set of function types that checked, both explicity through tests of |
| 116 * program contains `x is F<int>` and `x is F<bool>` then the TypedefElement | 123 * typedefs and implicitly through type annotations in checked mode. |
| 117 * `F` will occur once in [checkedTypedefs]. | |
| 118 */ | 124 */ |
| 119 Set<TypedefElement> checkedTypedefs; | 125 Set<FunctionType> checkedFunctionTypes; |
| 126 |
| 127 Map<ClassElement, Set<FunctionType>> checkedGenericFunctionTypes = |
| 128 new Map<ClassElement, Set<FunctionType>>(); |
| 129 |
| 130 Set<FunctionType> checkedNonGenericFunctionTypes = |
| 131 new Set<FunctionType>(); |
| 132 |
| 133 void registerDynamicFunctionTypeCheck(FunctionType functionType) { |
| 134 ClassElement classElement = Types.getClassContext(functionType); |
| 135 if (classElement != null) { |
| 136 checkedGenericFunctionTypes.putIfAbsent(classElement, |
| 137 () => new Set<FunctionType>()).add(functionType); |
| 138 } else { |
| 139 checkedNonGenericFunctionTypes.add(functionType); |
| 140 } |
| 141 } |
| 120 | 142 |
| 121 final bool generateSourceMap; | 143 final bool generateSourceMap; |
| 122 | 144 |
| 123 Iterable<ClassElement> cachedClassesUsingTypeVariableTests; | 145 Iterable<ClassElement> cachedClassesUsingTypeVariableTests; |
| 124 | 146 |
| 125 Iterable<ClassElement> get classesUsingTypeVariableTests { | 147 Iterable<ClassElement> get classesUsingTypeVariableTests { |
| 126 if (cachedClassesUsingTypeVariableTests == null) { | 148 if (cachedClassesUsingTypeVariableTests == null) { |
| 127 cachedClassesUsingTypeVariableTests = compiler.codegenWorld.isChecks | 149 cachedClassesUsingTypeVariableTests = compiler.codegenWorld.isChecks |
| 128 .where((DartType t) => t is TypeVariableType) | 150 .where((DartType t) => t is TypeVariableType) |
| 129 .map((TypeVariableType v) => v.element.getEnclosingClass()) | 151 .map((TypeVariableType v) => v.element.getEnclosingClass()) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 140 constantEmitter = new ConstantEmitter(compiler, namer), | 162 constantEmitter = new ConstantEmitter(compiler, namer), |
| 141 super(compiler) { | 163 super(compiler) { |
| 142 nativeEmitter = new NativeEmitter(this); | 164 nativeEmitter = new NativeEmitter(this); |
| 143 } | 165 } |
| 144 | 166 |
| 145 void addComment(String comment, CodeBuffer buffer) { | 167 void addComment(String comment, CodeBuffer buffer) { |
| 146 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); | 168 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); |
| 147 } | 169 } |
| 148 | 170 |
| 149 void computeRequiredTypeChecks() { | 171 void computeRequiredTypeChecks() { |
| 150 assert(checkedClasses == null && checkedTypedefs == null); | 172 assert(checkedClasses == null && checkedFunctionTypes == null); |
| 151 | 173 |
| 152 backend.rti.addImplicitChecks(compiler.codegenWorld, | 174 backend.rti.addImplicitChecks(compiler.codegenWorld, |
| 153 classesUsingTypeVariableTests); | 175 classesUsingTypeVariableTests); |
| 154 | 176 |
| 155 checkedClasses = new Set<ClassElement>(); | 177 checkedClasses = new Set<ClassElement>(); |
| 156 checkedTypedefs = new Set<TypedefElement>(); | 178 checkedFunctionTypes = new Set<FunctionType>(); |
| 157 compiler.codegenWorld.isChecks.forEach((DartType t) { | 179 compiler.codegenWorld.isChecks.forEach((DartType t) { |
| 158 if (t is InterfaceType) { | 180 if (!t.isMalformed) { |
| 159 checkedClasses.add(t.element); | 181 if (t is InterfaceType) { |
| 160 } else if (t is TypedefType) { | 182 checkedClasses.add(t.element); |
| 161 checkedTypedefs.add(t.element); | 183 } else if (t is FunctionType) { |
| 184 checkedFunctionTypes.add(t); |
| 185 } |
| 162 } | 186 } |
| 163 }); | 187 }); |
| 164 } | 188 } |
| 165 | 189 |
| 166 ClassElement computeMixinClass(MixinApplicationElement mixinApplication) { | 190 ClassElement computeMixinClass(MixinApplicationElement mixinApplication) { |
| 167 ClassElement mixin = mixinApplication.mixin; | 191 ClassElement mixin = mixinApplication.mixin; |
| 168 while (mixin.isMixinApplication) { | 192 while (mixin.isMixinApplication) { |
| 169 mixinApplication = mixin; | 193 mixinApplication = mixin; |
| 170 mixin = mixinApplication.mixin; | 194 mixin = mixinApplication.mixin; |
| 171 } | 195 } |
| (...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1312 | 1336 |
| 1313 void generateIsTest(Element other) { | 1337 void generateIsTest(Element other) { |
| 1314 if (other == compiler.objectClass && other != classElement) { | 1338 if (other == compiler.objectClass && other != classElement) { |
| 1315 // Avoid emitting [:$isObject:] on all classes but [Object]. | 1339 // Avoid emitting [:$isObject:] on all classes but [Object]. |
| 1316 return; | 1340 return; |
| 1317 } | 1341 } |
| 1318 other = backend.getImplementationClass(other); | 1342 other = backend.getImplementationClass(other); |
| 1319 builder.addProperty(namer.operatorIs(other), js('true')); | 1343 builder.addProperty(namer.operatorIs(other), js('true')); |
| 1320 } | 1344 } |
| 1321 | 1345 |
| 1346 void generateIsFunctionTypeTest(FunctionType type) { |
| 1347 String operator = namer.operatorIsType(type); |
| 1348 builder.addProperty(operator, new jsAst.LiteralBool(true)); |
| 1349 } |
| 1350 |
| 1351 void generateFunctionTypeSignature(Element method, FunctionType type) { |
| 1352 assert(method.isImplementation); |
| 1353 String thisAccess = 'this'; |
| 1354 Node node = method.parseNode(compiler); |
| 1355 ClosureClassMap closureData = |
| 1356 compiler.closureToClassMapper.closureMappingCache[node]; |
| 1357 if (closureData != null) { |
| 1358 Element thisElement = |
| 1359 closureData.freeVariableMapping[closureData.thisElement]; |
| 1360 if (thisElement != null) { |
| 1361 String thisName = backend.namer.getName(thisElement); |
| 1362 thisAccess = 'this.$thisName'; |
| 1363 } |
| 1364 } |
| 1365 RuntimeTypes rti = backend.rti; |
| 1366 String encoding = rti.getSignatureEncoding(type, () => '$thisAccess'); |
| 1367 String operatorSignature = namer.operatorSignature(); |
| 1368 builder.addProperty(operatorSignature, |
| 1369 new jsAst.LiteralExpression(encoding)); |
| 1370 } |
| 1371 |
| 1322 void generateSubstitution(Element other, {bool emitNull: false}) { | 1372 void generateSubstitution(Element other, {bool emitNull: false}) { |
| 1323 RuntimeTypes rti = backend.rti; | 1373 RuntimeTypes rti = backend.rti; |
| 1324 // TODO(karlklose): support typedefs with variables. | |
| 1325 jsAst.Expression expression; | 1374 jsAst.Expression expression; |
| 1326 bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other); | 1375 bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other); |
| 1327 if (other.kind == ElementKind.CLASS) { | 1376 if (other.kind == ElementKind.CLASS) { |
| 1328 String substitution = rti.getSupertypeSubstitution(classElement, other, | 1377 String substitution = rti.getSupertypeSubstitution(classElement, other, |
| 1329 alwaysGenerateFunction: true); | 1378 alwaysGenerateFunction: true); |
| 1330 if (substitution != null) { | 1379 if (substitution != null) { |
| 1331 expression = new jsAst.LiteralExpression(substitution); | 1380 expression = new jsAst.LiteralExpression(substitution); |
| 1332 } else if (emitNull || needsNativeCheck) { | 1381 } else if (emitNull || needsNativeCheck) { |
| 1333 expression = new jsAst.LiteralNull(); | 1382 expression = new jsAst.LiteralNull(); |
| 1334 } | 1383 } |
| 1335 } | 1384 } |
| 1336 if (expression != null) { | 1385 if (expression != null) { |
| 1337 builder.addProperty(namer.substitutionName(other), expression); | 1386 builder.addProperty(namer.substitutionName(other), expression); |
| 1338 } | 1387 } |
| 1339 } | 1388 } |
| 1340 | 1389 |
| 1341 generateIsTestsOn(classElement, generateIsTest, generateSubstitution); | 1390 generateIsTestsOn(classElement, generateIsTest, |
| 1391 generateIsFunctionTypeTest, generateFunctionTypeSignature, |
| 1392 generateSubstitution); |
| 1342 } | 1393 } |
| 1343 | 1394 |
| 1344 void emitRuntimeTypeSupport(CodeBuffer buffer) { | 1395 void emitRuntimeTypeSupport(CodeBuffer buffer) { |
| 1345 RuntimeTypes rti = backend.rti; | 1396 RuntimeTypes rti = backend.rti; |
| 1346 TypeChecks typeChecks = rti.requiredChecks; | 1397 TypeChecks typeChecks = rti.requiredChecks; |
| 1347 | 1398 |
| 1348 // Add checks to the constructors of instantiated classes. | 1399 // Add checks to the constructors of instantiated classes. |
| 1349 for (ClassElement cls in typeChecks) { | 1400 for (ClassElement cls in typeChecks) { |
| 1350 String holder = namer.isolateAccess(backend.getImplementationClass(cls)); | 1401 String holder = namer.isolateAccess(backend.getImplementationClass(cls)); |
| 1351 for (TypeCheck check in typeChecks[cls]) { | 1402 for (TypeCheck check in typeChecks[cls]) { |
| 1352 ClassElement cls = check.cls; | 1403 ClassElement cls = check.cls; |
| 1353 buffer.write('$holder.${namer.operatorIs(cls)}$_=${_}true$N'); | 1404 buffer.write('$holder.${namer.operatorIs(cls)}$_=${_}true$N'); |
| 1354 Substitution substitution = check.substitution; | 1405 Substitution substitution = check.substitution; |
| 1355 if (substitution != null) { | 1406 if (substitution != null) { |
| 1356 String body = substitution.getCode(rti, false); | 1407 String body = substitution.getCode(rti, false); |
| 1357 buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}$body$N'); | 1408 buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}$body$N'); |
| 1358 } | 1409 } |
| 1359 }; | 1410 }; |
| 1360 } | 1411 } |
| 1412 |
| 1413 void addSignature(FunctionType type) { |
| 1414 String encoding = rti.getTypeEncoding(type); |
| 1415 buffer.add('${namer.signatureName(type)}$_=${_}$encoding$N'); |
| 1416 } |
| 1417 |
| 1418 checkedNonGenericFunctionTypes.forEach(addSignature); |
| 1419 |
| 1420 checkedGenericFunctionTypes.forEach((_, Set<FunctionType> functionTypes) { |
| 1421 functionTypes.forEach(addSignature); |
| 1422 }); |
| 1361 } | 1423 } |
| 1362 | 1424 |
| 1363 /** | 1425 /** |
| 1364 * Documentation wanted -- johnniwinther | 1426 * Documentation wanted -- johnniwinther |
| 1365 * | 1427 * |
| 1366 * Invariant: [classElement] must be a declaration element. | 1428 * Invariant: [classElement] must be a declaration element. |
| 1367 */ | 1429 */ |
| 1368 void visitClassFields(ClassElement classElement, | 1430 void visitClassFields(ClassElement classElement, |
| 1369 void addField(Element member, | 1431 void addField(Element member, |
| 1370 String name, | 1432 String name, |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } | 1544 } |
| 1483 | 1545 |
| 1484 void generateCheckedSetter(Element member, | 1546 void generateCheckedSetter(Element member, |
| 1485 String fieldName, | 1547 String fieldName, |
| 1486 String accessorName, | 1548 String accessorName, |
| 1487 ClassBuilder builder) { | 1549 ClassBuilder builder) { |
| 1488 assert(canGenerateCheckedSetter(member)); | 1550 assert(canGenerateCheckedSetter(member)); |
| 1489 DartType type = member.computeType(compiler); | 1551 DartType type = member.computeType(compiler); |
| 1490 // TODO(ahe): Generate a dynamic type error here. | 1552 // TODO(ahe): Generate a dynamic type error here. |
| 1491 if (type.element.isErroneous()) return; | 1553 if (type.element.isErroneous()) return; |
| 1492 FunctionElement helperElement | 1554 type = type.unalias(compiler); |
| 1493 = backend.getCheckedModeHelper(type, typeCast: false); | 1555 CheckedModeHelper helper = |
| 1556 backend.getCheckedModeHelper(type, typeCast: false); |
| 1557 FunctionElement helperElement = helper.getElement(compiler); |
| 1494 String helperName = namer.isolateAccess(helperElement); | 1558 String helperName = namer.isolateAccess(helperElement); |
| 1495 List<jsAst.Expression> arguments = <jsAst.Expression>[js('v')]; | 1559 List<jsAst.Expression> arguments = <jsAst.Expression>[js('v')]; |
| 1496 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 1560 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 1497 arguments.add(js.string(namer.operatorIs(type.element))); | 1561 arguments.add(js.string(namer.operatorIsType(type))); |
| 1498 } | 1562 } |
| 1499 | 1563 |
| 1500 String setterName = namer.setterNameFromAccessorName(accessorName); | 1564 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1501 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) | 1565 String receiver = backend.isInterceptorClass(member.getEnclosingClass()) |
| 1502 ? 'receiver' : 'this'; | 1566 ? 'receiver' : 'this'; |
| 1503 List<String> args = backend.isInterceptedMethod(member) | 1567 List<String> args = backend.isInterceptedMethod(member) |
| 1504 ? ['receiver', 'v'] | 1568 ? ['receiver', 'v'] |
| 1505 : ['v']; | 1569 : ['v']; |
| 1506 builder.addProperty(setterName, | 1570 builder.addProperty(setterName, |
| 1507 js.fun(args, | 1571 js.fun(args, |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 return arity; | 1792 return arity; |
| 1729 } | 1793 } |
| 1730 | 1794 |
| 1731 int _compareSelectorNames(Selector selector1, Selector selector2) { | 1795 int _compareSelectorNames(Selector selector1, Selector selector2) { |
| 1732 String name1 = selector1.name.toString(); | 1796 String name1 = selector1.name.toString(); |
| 1733 String name2 = selector2.name.toString(); | 1797 String name2 = selector2.name.toString(); |
| 1734 if (name1 != name2) return Comparable.compare(name1, name2); | 1798 if (name1 != name2) return Comparable.compare(name1, name2); |
| 1735 return _selectorRank(selector1) - _selectorRank(selector2); | 1799 return _selectorRank(selector1) - _selectorRank(selector2); |
| 1736 } | 1800 } |
| 1737 | 1801 |
| 1738 Iterable<Element> getTypedefChecksOn(DartType type) { | 1802 /** |
| 1739 bool isSubtype(TypedefElement typedef) { | 1803 * Returns a mapping containing all checked function types for which [type] |
| 1740 FunctionType typedefType = | 1804 * can be a subtype. A function type is mapped to [:true:] if [type] is |
| 1741 typedef.computeType(compiler).unalias(compiler); | 1805 * statically known to be a subtype of it and to [:false:] if [type] might |
| 1742 return compiler.types.isSubtype(type, typedefType); | 1806 * be a subtype, provided with the right type arguments. |
| 1807 */ |
| 1808 // TODO(johnniwinther): Change to return a mapping from function types to |
| 1809 // a set of variable points and use this to detect statically/dynamically |
| 1810 // known subtype relations. |
| 1811 Map<FunctionType, bool> getFunctionTypeChecksOn(DartType type) { |
| 1812 Map<FunctionType, bool> functionTypeMap = |
| 1813 new LinkedHashMap<FunctionType, bool>(); |
| 1814 for (FunctionType functionType in checkedFunctionTypes) { |
| 1815 if (compiler.types.isSubtype(type, functionType)) { |
| 1816 functionTypeMap[functionType] = true; |
| 1817 } else if (compiler.types.isPotentialSubtype(type, functionType)) { |
| 1818 functionTypeMap[functionType] = false; |
| 1819 } |
| 1743 } | 1820 } |
| 1744 return checkedTypedefs.where(isSubtype).toList() | 1821 // TODO(johnniwinther): Ensure stable ordering of the keys. |
| 1745 ..sort(Elements.compareByPosition); | 1822 return functionTypeMap; |
| 1746 } | 1823 } |
| 1747 | 1824 |
| 1748 /** | 1825 /** |
| 1749 * Generate "is tests" for [cls]: itself, and the "is tests" for the | 1826 * Generate "is tests" for [cls]: itself, and the "is tests" for the |
| 1750 * classes it implements and type argument substitution functions for these | 1827 * classes it implements and type argument substitution functions for these |
| 1751 * tests. We don't need to add the "is tests" of the super class because | 1828 * tests. We don't need to add the "is tests" of the super class because |
| 1752 * they will be inherited at runtime, but we may need to generate the | 1829 * they will be inherited at runtime, but we may need to generate the |
| 1753 * substitutions, because they may have changed. | 1830 * substitutions, because they may have changed. |
| 1754 */ | 1831 */ |
| 1755 void generateIsTestsOn(ClassElement cls, | 1832 void generateIsTestsOn(ClassElement cls, |
| 1756 void emitIsTest(Element element), | 1833 void emitIsTest(Element element), |
| 1757 void emitSubstitution(Element element, {emitNull})) { | 1834 FunctionTypeTestEmitter emitIsFunctionTypeTest, |
| 1835 FunctionTypeSignatureEmitter emitFunctionTypeSignature, |
| 1836 SubstitutionEmitter emitSubstitution) { |
| 1758 if (checkedClasses.contains(cls)) { | 1837 if (checkedClasses.contains(cls)) { |
| 1759 emitIsTest(cls); | 1838 emitIsTest(cls); |
| 1760 emitSubstitution(cls); | 1839 emitSubstitution(cls); |
| 1761 } | 1840 } |
| 1762 | 1841 |
| 1763 RuntimeTypes rti = backend.rti; | 1842 RuntimeTypes rti = backend.rti; |
| 1764 ClassElement superclass = cls.superclass; | 1843 ClassElement superclass = cls.superclass; |
| 1765 | 1844 |
| 1766 bool haveSameTypeVariables(ClassElement a, ClassElement b) { | 1845 bool haveSameTypeVariables(ClassElement a, ClassElement b) { |
| 1767 if (a.isClosure()) return true; | 1846 if (a.isClosure()) return true; |
| 1768 return a.typeVariables == b.typeVariables; | 1847 return a.typeVariables == b.typeVariables; |
| 1769 } | 1848 } |
| 1770 | 1849 |
| 1771 if (superclass != null && superclass != compiler.objectClass && | 1850 if (superclass != null && superclass != compiler.objectClass && |
| 1772 !haveSameTypeVariables(cls, superclass)) { | 1851 !haveSameTypeVariables(cls, superclass)) { |
| 1773 // We cannot inherit the generated substitutions, because the type | 1852 // We cannot inherit the generated substitutions, because the type |
| 1774 // variable layout for this class is different. Instead we generate | 1853 // variable layout for this class is different. Instead we generate |
| 1775 // substitutions for all checks and make emitSubstitution a NOP for the | 1854 // substitutions for all checks and make emitSubstitution a NOP for the |
| 1776 // rest of this function. | 1855 // rest of this function. |
| 1777 Set<ClassElement> emitted = new Set<ClassElement>(); | 1856 Set<ClassElement> emitted = new Set<ClassElement>(); |
| 1778 // TODO(karlklose): move the computation of these checks to | 1857 // TODO(karlklose): move the computation of these checks to |
| 1779 // RuntimeTypeInformation. | 1858 // RuntimeTypeInformation. |
| 1780 if (backend.needsRti(cls)) { | 1859 if (backend.classNeedsRti(cls)) { |
| 1781 emitSubstitution(superclass, emitNull: true); | 1860 emitSubstitution(superclass, emitNull: true); |
| 1782 emitted.add(superclass); | 1861 emitted.add(superclass); |
| 1783 } | 1862 } |
| 1784 for (DartType supertype in cls.allSupertypes) { | 1863 for (DartType supertype in cls.allSupertypes) { |
| 1785 ClassElement superclass = supertype.element; | 1864 ClassElement superclass = supertype.element; |
| 1786 if (classesUsingTypeVariableTests.contains(superclass)) { | 1865 if (classesUsingTypeVariableTests.contains(superclass)) { |
| 1787 emitSubstitution(superclass, emitNull: true); | 1866 emitSubstitution(superclass, emitNull: true); |
| 1788 emitted.add(superclass); | 1867 emitted.add(superclass); |
| 1789 } | 1868 } |
| 1790 for (ClassElement check in checkedClasses) { | 1869 for (ClassElement check in checkedClasses) { |
| 1791 if (supertype.element == check && !emitted.contains(check)) { | 1870 if (supertype.element == check && !emitted.contains(check)) { |
| 1792 // Generate substitution. If no substitution is necessary, emit | 1871 // Generate substitution. If no substitution is necessary, emit |
| 1793 // [:null:] to overwrite a (possibly) existing substitution from the | 1872 // [:null:] to overwrite a (possibly) existing substitution from the |
| 1794 // super classes. | 1873 // super classes. |
| 1795 emitSubstitution(check, emitNull: true); | 1874 emitSubstitution(check, emitNull: true); |
| 1796 emitted.add(check); | 1875 emitted.add(check); |
| 1797 } | 1876 } |
| 1798 } | 1877 } |
| 1799 } | 1878 } |
| 1800 void emitNothing(_, {emitNull}) {}; | 1879 void emitNothing(_, {emitNull}) {}; |
| 1801 emitSubstitution = emitNothing; | 1880 emitSubstitution = emitNothing; |
| 1802 } | 1881 } |
| 1803 | 1882 |
| 1804 Set<Element> generated = new Set<Element>(); | 1883 Set<Element> generated = new Set<Element>(); |
| 1805 // A class that defines a [:call:] method implicitly implements | 1884 // A class that defines a [:call:] method implicitly implements |
| 1806 // [Function] and needs checks for all typedefs that are used in is-checks. | 1885 // [Function] and needs checks for all typedefs that are used in is-checks. |
| 1807 if (checkedClasses.contains(compiler.functionClass) || | 1886 if (checkedClasses.contains(compiler.functionClass) || |
| 1808 !checkedTypedefs.isEmpty) { | 1887 !checkedFunctionTypes.isEmpty) { |
| 1809 Element call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); | 1888 Element call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); |
| 1810 if (call == null) { | 1889 if (call == null) { |
| 1811 // If [cls] is a closure, it has a synthetic call operator method. | 1890 // If [cls] is a closure, it has a synthetic call operator method. |
| 1812 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); | 1891 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); |
| 1813 } | 1892 } |
| 1814 if (call != null && call.isFunction()) { | 1893 if (call != null && call.isFunction()) { |
| 1815 generateInterfacesIsTests(compiler.functionClass, | 1894 generateInterfacesIsTests(compiler.functionClass, |
| 1816 emitIsTest, | 1895 emitIsTest, |
| 1817 emitSubstitution, | 1896 emitSubstitution, |
| 1818 generated); | 1897 generated); |
| 1819 getTypedefChecksOn(call.computeType(compiler)).forEach(emitIsTest); | 1898 FunctionType callType = call.computeType(compiler); |
| 1820 } | 1899 Map<FunctionType, bool> functionTypeChecks = |
| 1900 getFunctionTypeChecksOn(callType); |
| 1901 generateFunctionTypeTests(call, callType, functionTypeChecks, |
| 1902 emitFunctionTypeSignature, emitIsFunctionTypeTest); |
| 1903 } |
| 1821 } | 1904 } |
| 1822 | 1905 |
| 1823 for (DartType interfaceType in cls.interfaces) { | 1906 for (DartType interfaceType in cls.interfaces) { |
| 1824 generateInterfacesIsTests(interfaceType.element, emitIsTest, | 1907 generateInterfacesIsTests(interfaceType.element, emitIsTest, |
| 1825 emitSubstitution, generated); | 1908 emitSubstitution, generated); |
| 1826 } | 1909 } |
| 1827 } | 1910 } |
| 1828 | 1911 |
| 1829 /** | 1912 /** |
| 1830 * Generate "is tests" where [cls] is being implemented. | 1913 * Generate "is tests" where [cls] is being implemented. |
| 1831 */ | 1914 */ |
| 1832 void generateInterfacesIsTests(ClassElement cls, | 1915 void generateInterfacesIsTests(ClassElement cls, |
| 1833 void emitIsTest(ClassElement element), | 1916 void emitIsTest(ClassElement element), |
| 1834 void emitSubstitution(ClassElement element), | 1917 SubstitutionEmitter emitSubstitution, |
| 1835 Set<Element> alreadyGenerated) { | 1918 Set<Element> alreadyGenerated) { |
| 1836 void tryEmitTest(ClassElement check) { | 1919 void tryEmitTest(ClassElement check) { |
| 1837 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) { | 1920 if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) { |
| 1838 alreadyGenerated.add(check); | 1921 alreadyGenerated.add(check); |
| 1839 emitIsTest(check); | 1922 emitIsTest(check); |
| 1840 emitSubstitution(check); | 1923 emitSubstitution(check); |
| 1841 } | 1924 } |
| 1842 }; | 1925 }; |
| 1843 | 1926 |
| 1844 tryEmitTest(cls); | 1927 tryEmitTest(cls); |
| 1845 | 1928 |
| 1846 for (DartType interfaceType in cls.interfaces) { | 1929 for (DartType interfaceType in cls.interfaces) { |
| 1847 Element element = interfaceType.element; | 1930 Element element = interfaceType.element; |
| 1848 tryEmitTest(element); | 1931 tryEmitTest(element); |
| 1849 generateInterfacesIsTests(element, emitIsTest, emitSubstitution, | 1932 generateInterfacesIsTests(element, emitIsTest, emitSubstitution, |
| 1850 alreadyGenerated); | 1933 alreadyGenerated); |
| 1851 } | 1934 } |
| 1852 | 1935 |
| 1853 // We need to also emit "is checks" for the superclass and its supertypes. | 1936 // We need to also emit "is checks" for the superclass and its supertypes. |
| 1854 ClassElement superclass = cls.superclass; | 1937 ClassElement superclass = cls.superclass; |
| 1855 if (superclass != null) { | 1938 if (superclass != null) { |
| 1856 tryEmitTest(superclass); | 1939 tryEmitTest(superclass); |
| 1857 generateInterfacesIsTests(superclass, emitIsTest, emitSubstitution, | 1940 generateInterfacesIsTests(superclass, emitIsTest, emitSubstitution, |
| 1858 alreadyGenerated); | 1941 alreadyGenerated); |
| 1859 } | 1942 } |
| 1860 } | 1943 } |
| 1861 | 1944 |
| 1945 static const int MAX_FUNCTION_TYPE_PREDICATES = 10; |
| 1946 |
| 1947 /** |
| 1948 * Generates function type checks on [method] with type [methodType] against |
| 1949 * the function type checks in [functionTypeChecks]. |
| 1950 */ |
| 1951 void generateFunctionTypeTests( |
| 1952 Element method, |
| 1953 FunctionType methodType, |
| 1954 Map<FunctionType, bool> functionTypeChecks, |
| 1955 FunctionTypeSignatureEmitter emitFunctionTypeSignature, |
| 1956 FunctionTypeTestEmitter emitIsFunctionTypeTest) { |
| 1957 bool hasDynamicFunctionTypeCheck = false; |
| 1958 int neededPredicates = 0; |
| 1959 functionTypeChecks.forEach((FunctionType functionType, bool knownSubtype) { |
| 1960 if (!knownSubtype) { |
| 1961 registerDynamicFunctionTypeCheck(functionType); |
| 1962 hasDynamicFunctionTypeCheck = true; |
| 1963 } else { |
| 1964 neededPredicates++; |
| 1965 } |
| 1966 }); |
| 1967 bool alwaysUseSignature = false; |
| 1968 if (hasDynamicFunctionTypeCheck || |
| 1969 neededPredicates > MAX_FUNCTION_TYPE_PREDICATES) { |
| 1970 emitFunctionTypeSignature(method, methodType); |
| 1971 alwaysUseSignature = true; |
| 1972 } |
| 1973 functionTypeChecks.forEach((FunctionType functionType, bool knownSubtype) { |
| 1974 if (knownSubtype) { |
| 1975 if (alwaysUseSignature) { |
| 1976 registerDynamicFunctionTypeCheck(functionType); |
| 1977 } else { |
| 1978 emitIsFunctionTypeTest(functionType); |
| 1979 } |
| 1980 } |
| 1981 }); |
| 1982 } |
| 1983 |
| 1862 /** | 1984 /** |
| 1863 * Return a function that returns true if its argument is a class | 1985 * Return a function that returns true if its argument is a class |
| 1864 * that needs to be emitted. | 1986 * that needs to be emitted. |
| 1865 */ | 1987 */ |
| 1866 Function computeClassFilter() { | 1988 Function computeClassFilter() { |
| 1867 Set<ClassElement> unneededClasses = new Set<ClassElement>(); | 1989 Set<ClassElement> unneededClasses = new Set<ClassElement>(); |
| 1868 // The [Bool] class is not marked as abstract, but has a factory | 1990 // The [Bool] class is not marked as abstract, but has a factory |
| 1869 // constructor that always throws. We never need to emit it. | 1991 // constructor that always throws. We never need to emit it. |
| 1870 unneededClasses.add(compiler.boolClass); | 1992 unneededClasses.add(compiler.boolClass); |
| 1871 | 1993 |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2014 ClassBuilder closureBuilder = new ClassBuilder(); | 2136 ClassBuilder closureBuilder = new ClassBuilder(); |
| 2015 // If a static function is used as a closure we need to add its name | 2137 // If a static function is used as a closure we need to add its name |
| 2016 // in case it is used in spawnFunction. | 2138 // in case it is used in spawnFunction. |
| 2017 String methodName = namer.STATIC_CLOSURE_NAME_NAME; | 2139 String methodName = namer.STATIC_CLOSURE_NAME_NAME; |
| 2018 emitClosureClassHeader( | 2140 emitClosureClassHeader( |
| 2019 mangledName, superName, <String>[invocationName, methodName], | 2141 mangledName, superName, <String>[invocationName, methodName], |
| 2020 closureBuilder); | 2142 closureBuilder); |
| 2021 | 2143 |
| 2022 addParameterStubs(callElement, closureBuilder.addProperty); | 2144 addParameterStubs(callElement, closureBuilder.addProperty); |
| 2023 | 2145 |
| 2024 DartType type = element.computeType(compiler); | |
| 2025 getTypedefChecksOn(type).forEach((Element typedef) { | |
| 2026 String operator = namer.operatorIs(typedef); | |
| 2027 closureBuilder.addProperty(operator, js('true')); | |
| 2028 }); | |
| 2029 | |
| 2030 // TODO(ngeoffray): Cache common base classes for closures, bound | 2146 // TODO(ngeoffray): Cache common base classes for closures, bound |
| 2031 // closures, and static closures that have common type checks. | 2147 // closures, and static closures that have common type checks. |
| 2032 boundClosures.add( | 2148 boundClosures.add( |
| 2033 js('$classesCollector.$mangledName = #', | 2149 js('$classesCollector.$mangledName = #', |
| 2034 closureBuilder.toObjectInitializer())); | 2150 closureBuilder.toObjectInitializer())); |
| 2035 | 2151 |
| 2036 staticGetters[element] = closureClassElement; | 2152 staticGetters[element] = closureClassElement; |
| 2153 |
| 2154 void emitFunctionTypeSignature(Element method, FunctionType methodType) { |
| 2155 RuntimeTypes rti = backend.rti; |
| 2156 // [:() => null:] is dummy encoding of [this] which is never needed for |
| 2157 // the encoding of the type of the static [method]. |
| 2158 String encoding = rti.getSignatureEncoding(methodType, () => 'null'); |
| 2159 String operatorSignature = namer.operatorSignature(); |
| 2160 // TODO(johnniwinther): Make MiniJsParser support function expressions. |
| 2161 closureBuilder.addProperty(operatorSignature, |
| 2162 new jsAst.LiteralExpression(encoding)); |
| 2163 } |
| 2164 |
| 2165 void emitIsFunctionTypeTest(FunctionType functionType) { |
| 2166 String operator = namer.operatorIsType(functionType); |
| 2167 closureBuilder.addProperty(operator, js('true')); |
| 2168 } |
| 2169 |
| 2170 FunctionType methodType = element.computeType(compiler); |
| 2171 Map<FunctionType, bool> functionTypeChecks = |
| 2172 getFunctionTypeChecksOn(methodType); |
| 2173 generateFunctionTypeTests(element, methodType, functionTypeChecks, |
| 2174 emitFunctionTypeSignature, emitIsFunctionTypeTest); |
| 2037 } | 2175 } |
| 2038 } | 2176 } |
| 2039 | 2177 |
| 2040 void emitClosureClassHeader(String mangledName, | 2178 void emitClosureClassHeader(String mangledName, |
| 2041 String superName, | 2179 String superName, |
| 2042 List<String> fieldNames, | 2180 List<String> fieldNames, |
| 2043 ClassBuilder builder) { | 2181 ClassBuilder builder) { |
| 2044 builder.addProperty('', | 2182 builder.addProperty('', |
| 2045 js.string("$superName;${fieldNames.join(',')}")); | 2183 js.string("$superName;${fieldNames.join(',')}")); |
| 2046 } | 2184 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2084 if (inInterceptor) { | 2222 if (inInterceptor) { |
| 2085 cache = interceptorClosureCache; | 2223 cache = interceptorClosureCache; |
| 2086 } else { | 2224 } else { |
| 2087 cache = boundClosureCache; | 2225 cache = boundClosureCache; |
| 2088 } | 2226 } |
| 2089 List<String> fieldNames = <String>[]; | 2227 List<String> fieldNames = <String>[]; |
| 2090 compiler.boundClosureClass.forEachInstanceField((_, Element field) { | 2228 compiler.boundClosureClass.forEachInstanceField((_, Element field) { |
| 2091 fieldNames.add(namer.getName(field)); | 2229 fieldNames.add(namer.getName(field)); |
| 2092 }); | 2230 }); |
| 2093 | 2231 |
| 2094 Iterable<Element> typedefChecks = | 2232 DartType memberType = member.computeType(compiler); |
| 2095 getTypedefChecksOn(member.computeType(compiler)); | 2233 Map<FunctionType, bool> functionTypeChecks = |
| 2096 bool hasTypedefChecks = !typedefChecks.isEmpty; | 2234 getFunctionTypeChecksOn(memberType); |
| 2235 bool hasFunctionTypeChecks = !functionTypeChecks.isEmpty; |
| 2097 | 2236 |
| 2098 bool canBeShared = !hasOptionalParameters && !hasTypedefChecks; | 2237 bool canBeShared = !hasOptionalParameters && !hasFunctionTypeChecks; |
| 2099 | 2238 |
| 2239 ClassElement classElement = member.getEnclosingClass(); |
| 2100 String closureClass = canBeShared ? cache[parameterCount] : null; | 2240 String closureClass = canBeShared ? cache[parameterCount] : null; |
| 2101 if (closureClass == null) { | 2241 if (closureClass == null) { |
| 2102 // Either the class was not cached yet, or there are optional parameters. | 2242 // Either the class was not cached yet, or there are optional parameters. |
| 2103 // Create a new closure class. | 2243 // Create a new closure class. |
| 2104 String name; | 2244 String name; |
| 2105 if (canBeShared) { | 2245 if (canBeShared) { |
| 2106 if (inInterceptor) { | 2246 if (inInterceptor) { |
| 2107 name = 'BoundClosure\$i${parameterCount}'; | 2247 name = 'BoundClosure\$i${parameterCount}'; |
| 2108 } else { | 2248 } else { |
| 2109 name = 'BoundClosure\$${parameterCount}'; | 2249 name = 'BoundClosure\$${parameterCount}'; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2145 arguments.add(js(name)); | 2285 arguments.add(js(name)); |
| 2146 } | 2286 } |
| 2147 | 2287 |
| 2148 jsAst.Expression fun = js.fun( | 2288 jsAst.Expression fun = js.fun( |
| 2149 parameters, | 2289 parameters, |
| 2150 js.return_( | 2290 js.return_( |
| 2151 js('this')[fieldNames[0]][js('this')[fieldNames[1]]](arguments))); | 2291 js('this')[fieldNames[0]][js('this')[fieldNames[1]]](arguments))); |
| 2152 boundClosureBuilder.addProperty(invocationName, fun); | 2292 boundClosureBuilder.addProperty(invocationName, fun); |
| 2153 | 2293 |
| 2154 addParameterStubs(callElement, boundClosureBuilder.addProperty); | 2294 addParameterStubs(callElement, boundClosureBuilder.addProperty); |
| 2155 typedefChecks.forEach((Element typedef) { | 2295 |
| 2156 String operator = namer.operatorIs(typedef); | 2296 void emitFunctionTypeSignature(Element method, FunctionType methodType) { |
| 2157 boundClosureBuilder.addProperty(operator, js('true')); | 2297 String encoding = backend.rti.getSignatureEncoding( |
| 2158 }); | 2298 methodType, () => 'this.${fieldNames[0]}'); |
| 2299 String operatorSignature = namer.operatorSignature(); |
| 2300 boundClosureBuilder.addProperty(operatorSignature, |
| 2301 new jsAst.LiteralExpression(encoding)); |
| 2302 } |
| 2303 |
| 2304 void emitIsFunctionTypeTest(FunctionType functionType) { |
| 2305 String operator = namer.operatorIsType(functionType); |
| 2306 boundClosureBuilder.addProperty(operator, |
| 2307 new jsAst.LiteralBool(true)); |
| 2308 } |
| 2309 |
| 2310 generateFunctionTypeTests(member, memberType, functionTypeChecks, |
| 2311 emitFunctionTypeSignature, emitIsFunctionTypeTest); |
| 2159 | 2312 |
| 2160 boundClosures.add( | 2313 boundClosures.add( |
| 2161 js('$classesCollector.$mangledName = #', | 2314 js('$classesCollector.$mangledName = #', |
| 2162 boundClosureBuilder.toObjectInitializer())); | 2315 boundClosureBuilder.toObjectInitializer())); |
| 2163 | 2316 |
| 2164 closureClass = namer.isolateAccess(closureClassElement); | 2317 closureClass = namer.isolateAccess(closureClassElement); |
| 2165 | 2318 |
| 2166 // Cache it. | 2319 // Cache it. |
| 2167 if (canBeShared) { | 2320 if (canBeShared) { |
| 2168 cache[parameterCount] = closureClass; | 2321 cache[parameterCount] = closureClass; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2180 if (inInterceptor) { | 2333 if (inInterceptor) { |
| 2181 String receiverArg = fieldNames[2]; | 2334 String receiverArg = fieldNames[2]; |
| 2182 parameters.add(receiverArg); | 2335 parameters.add(receiverArg); |
| 2183 arguments.add(js(receiverArg)); | 2336 arguments.add(js(receiverArg)); |
| 2184 } else { | 2337 } else { |
| 2185 // Put null in the intercepted receiver field. | 2338 // Put null in the intercepted receiver field. |
| 2186 arguments.add(new jsAst.LiteralNull()); | 2339 arguments.add(new jsAst.LiteralNull()); |
| 2187 } | 2340 } |
| 2188 | 2341 |
| 2189 jsAst.Expression getterFunction = js.fun( | 2342 jsAst.Expression getterFunction = js.fun( |
| 2190 parameters, | 2343 parameters, js.return_(js(closureClass).newWith(arguments))); |
| 2191 js.return_(js(closureClass).newWith(arguments))); | |
| 2192 | 2344 |
| 2193 defineStub(getterName, getterFunction); | 2345 defineStub(getterName, getterFunction); |
| 2194 } | 2346 } |
| 2195 | 2347 |
| 2196 /** | 2348 /** |
| 2197 * Documentation wanted -- johnniwinther | 2349 * Documentation wanted -- johnniwinther |
| 2198 * | 2350 * |
| 2199 * Invariant: [member] must be a declaration element. | 2351 * Invariant: [member] must be a declaration element. |
| 2200 */ | 2352 */ |
| 2201 void emitCallStubForGetter(Element member, | 2353 void emitCallStubForGetter(Element member, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2221 ? member.fixedBackendName() | 2373 ? member.fixedBackendName() |
| 2222 : namer.instanceFieldName(member); | 2374 : namer.instanceFieldName(member); |
| 2223 return js('this')[fieldName]; | 2375 return js('this')[fieldName]; |
| 2224 } | 2376 } |
| 2225 } | 2377 } |
| 2226 | 2378 |
| 2227 // Two selectors may match but differ only in type. To avoid generating | 2379 // Two selectors may match but differ only in type. To avoid generating |
| 2228 // identical stubs for each we track untyped selectors which already have | 2380 // identical stubs for each we track untyped selectors which already have |
| 2229 // stubs. | 2381 // stubs. |
| 2230 Set<Selector> generatedSelectors = new Set<Selector>(); | 2382 Set<Selector> generatedSelectors = new Set<Selector>(); |
| 2231 | |
| 2232 for (Selector selector in selectors) { | 2383 for (Selector selector in selectors) { |
| 2233 if (selector.applies(member, compiler)) { | 2384 if (selector.applies(member, compiler)) { |
| 2234 selector = selector.asUntyped; | 2385 selector = selector.asUntyped; |
| 2235 if (generatedSelectors.contains(selector)) continue; | 2386 if (generatedSelectors.contains(selector)) continue; |
| 2236 generatedSelectors.add(selector); | 2387 generatedSelectors.add(selector); |
| 2237 | 2388 |
| 2238 String invocationName = namer.invocationName(selector); | 2389 String invocationName = namer.invocationName(selector); |
| 2239 Selector callSelector = new Selector.callClosureFrom(selector); | 2390 Selector callSelector = new Selector.callClosureFrom(selector); |
| 2240 String closureCallName = namer.invocationName(callSelector); | 2391 String closureCallName = namer.invocationName(callSelector); |
| 2241 | 2392 |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2826 }); | 2977 }); |
| 2827 | 2978 |
| 2828 // 3b. Add classes that are referenced by substitutions in object checks and | 2979 // 3b. Add classes that are referenced by substitutions in object checks and |
| 2829 // their superclasses. | 2980 // their superclasses. |
| 2830 TypeChecks requiredChecks = | 2981 TypeChecks requiredChecks = |
| 2831 backend.rti.computeChecks(neededClasses, checkedClasses); | 2982 backend.rti.computeChecks(neededClasses, checkedClasses); |
| 2832 Set<ClassElement> classesUsedInSubstitutions = | 2983 Set<ClassElement> classesUsedInSubstitutions = |
| 2833 rti.getClassesUsedInSubstitutions(backend, requiredChecks); | 2984 rti.getClassesUsedInSubstitutions(backend, requiredChecks); |
| 2834 addClassesWithSuperclasses(classesUsedInSubstitutions); | 2985 addClassesWithSuperclasses(classesUsedInSubstitutions); |
| 2835 | 2986 |
| 2987 // 3c. Add classes that contain checked generic function types. These are |
| 2988 // needed to store the signature encoding. |
| 2989 for (FunctionType type in checkedFunctionTypes) { |
| 2990 ClassElement contextClass = Types.getClassContext(type); |
| 2991 if (contextClass != null) { |
| 2992 neededClasses.add(contextClass); |
| 2993 } |
| 2994 } |
| 2995 |
| 2836 // 4. Finally, sort the classes. | 2996 // 4. Finally, sort the classes. |
| 2837 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | 2997 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); |
| 2838 | 2998 |
| 2839 // If we need noSuchMethod support, we run through all needed | 2999 // If we need noSuchMethod support, we run through all needed |
| 2840 // classes to figure out if we need the support on any native | 3000 // classes to figure out if we need the support on any native |
| 2841 // class. If so, we let the native emitter deal with it. | 3001 // class. If so, we let the native emitter deal with it. |
| 2842 if (compiler.enabledNoSuchMethod) { | 3002 if (compiler.enabledNoSuchMethod) { |
| 2843 SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD; | 3003 SourceString noSuchMethodName = Compiler.NO_SUCH_METHOD; |
| 2844 Selector noSuchMethodSelector = compiler.noSuchMethodSelector; | 3004 Selector noSuchMethodSelector = compiler.noSuchMethodSelector; |
| 2845 for (ClassElement element in sortedClasses) { | 3005 for (ClassElement element in sortedClasses) { |
| (...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3480 | 3640 |
| 3481 const String HOOKS_API_USAGE = """ | 3641 const String HOOKS_API_USAGE = """ |
| 3482 // The code supports the following hooks: | 3642 // The code supports the following hooks: |
| 3483 // dartPrint(message) - if this function is defined it is called | 3643 // dartPrint(message) - if this function is defined it is called |
| 3484 // instead of the Dart [print] method. | 3644 // instead of the Dart [print] method. |
| 3485 // dartMainRunner(main) - if this function is defined, the Dart [main] | 3645 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 3486 // method will not be invoked directly. | 3646 // method will not be invoked directly. |
| 3487 // Instead, a closure that will invoke [main] is | 3647 // Instead, a closure that will invoke [main] is |
| 3488 // passed to [dartMainRunner]. | 3648 // passed to [dartMainRunner]. |
| 3489 """; | 3649 """; |
| OLD | NEW |