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