| 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 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 // hit the method directly. | 646 // hit the method directly. |
| 647 return; | 647 return; |
| 648 } | 648 } |
| 649 ConstantHandler handler = compiler.constantHandler; | 649 ConstantHandler handler = compiler.constantHandler; |
| 650 List<SourceString> names = selector.getOrderedNamedArguments(); | 650 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 651 | 651 |
| 652 String invocationName = namer.invocationName(selector); | 652 String invocationName = namer.invocationName(selector); |
| 653 if (alreadyGenerated.contains(invocationName)) return; | 653 if (alreadyGenerated.contains(invocationName)) return; |
| 654 alreadyGenerated.add(invocationName); | 654 alreadyGenerated.add(invocationName); |
| 655 | 655 |
| 656 bool isInterceptorClass = | 656 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 657 backend.isInterceptorClass(member.getEnclosingClass()); | |
| 658 | 657 |
| 659 // If the method is in an interceptor class, we need to also pass | 658 // If the method is intercepted, we need to also pass |
| 660 // the actual receiver. | 659 // the actual receiver. |
| 661 int extraArgumentCount = isInterceptorClass ? 1 : 0; | 660 int extraArgumentCount = isInterceptedMethod ? 1 : 0; |
| 662 // Use '$receiver' to avoid clashes with other parameter names. Using | 661 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 663 // '$receiver' works because [:namer.safeName:] used for getting parameter | 662 // '$receiver' works because [:namer.safeName:] used for getting parameter |
| 664 // names never returns a name beginning with a single '$'. | 663 // names never returns a name beginning with a single '$'. |
| 665 String receiverArgumentName = r'$receiver'; | 664 String receiverArgumentName = r'$receiver'; |
| 666 | 665 |
| 667 // The parameters that this stub takes. | 666 // The parameters that this stub takes. |
| 668 List<jsAst.Parameter> parametersBuffer = | 667 List<jsAst.Parameter> parametersBuffer = |
| 669 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); | 668 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); |
| 670 // The arguments that will be passed to the real method. | 669 // The arguments that will be passed to the real method. |
| 671 List<jsAst.Expression> argumentsBuffer = | 670 List<jsAst.Expression> argumentsBuffer = |
| 672 new List<jsAst.Expression>( | 671 new List<jsAst.Expression>( |
| 673 parameters.parameterCount + extraArgumentCount); | 672 parameters.parameterCount + extraArgumentCount); |
| 674 | 673 |
| 675 int count = 0; | 674 int count = 0; |
| 676 if (isInterceptorClass) { | 675 if (isInterceptedMethod) { |
| 677 count++; | 676 count++; |
| 678 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 677 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 679 argumentsBuffer[0] = js[receiverArgumentName]; | 678 argumentsBuffer[0] = js[receiverArgumentName]; |
| 680 } | 679 } |
| 681 | 680 |
| 682 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 681 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
| 683 TreeElements elements = | 682 TreeElements elements = |
| 684 compiler.enqueuer.resolution.getCachedElements(member); | 683 compiler.enqueuer.resolution.getCachedElements(member); |
| 685 | 684 |
| 686 parameters.orderedForEachParameter((Element element) { | 685 parameters.orderedForEachParameter((Element element) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 906 } | 905 } |
| 907 | 906 |
| 908 /** | 907 /** |
| 909 * Documentation wanted -- johnniwinther | 908 * Documentation wanted -- johnniwinther |
| 910 * | 909 * |
| 911 * Invariant: [classElement] must be a declaration element. | 910 * Invariant: [classElement] must be a declaration element. |
| 912 */ | 911 */ |
| 913 void emitInstanceMembers(ClassElement classElement, | 912 void emitInstanceMembers(ClassElement classElement, |
| 914 ClassBuilder builder) { | 913 ClassBuilder builder) { |
| 915 assert(invariant(classElement, classElement.isDeclaration)); | 914 assert(invariant(classElement, classElement.isDeclaration)); |
| 916 if (classElement == backend.objectInterceptorClass) { | |
| 917 emitInterceptorMethods(builder); | |
| 918 // The ObjectInterceptor does not have any instance methods. | |
| 919 return; | |
| 920 } | |
| 921 | 915 |
| 922 void visitMember(ClassElement enclosing, Element member) { | 916 void visitMember(ClassElement enclosing, Element member) { |
| 923 assert(invariant(classElement, member.isDeclaration)); | 917 assert(invariant(classElement, member.isDeclaration)); |
| 924 if (member.isInstanceMember()) { | 918 if (member.isInstanceMember()) { |
| 925 addInstanceMember(member, builder); | 919 addInstanceMember(member, builder); |
| 926 } | 920 } |
| 927 } | 921 } |
| 928 | 922 |
| 929 // TODO(kasperl): We should make sure to only emit one version of | 923 // TODO(kasperl): We should make sure to only emit one version of |
| 930 // overridden methods. Right now, we rely on the ordering so the | 924 // overridden methods. Right now, we rely on the ordering so the |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 988 && compiler.enabledNoSuchMethod) { | 982 && compiler.enabledNoSuchMethod) { |
| 989 // Emit the noSuchMethod handlers on the Object prototype now, | 983 // Emit the noSuchMethod handlers on the Object prototype now, |
| 990 // so that the code in the dynamicFunction helper can find | 984 // so that the code in the dynamicFunction helper can find |
| 991 // them. Note that this helper is invoked before analyzing the | 985 // them. Note that this helper is invoked before analyzing the |
| 992 // full JS script. | 986 // full JS script. |
| 993 if (!nativeEmitter.handleNoSuchMethod) { | 987 if (!nativeEmitter.handleNoSuchMethod) { |
| 994 emitNoSuchMethodHandlers(builder.addProperty); | 988 emitNoSuchMethodHandlers(builder.addProperty); |
| 995 } | 989 } |
| 996 } | 990 } |
| 997 | 991 |
| 998 if (backend.isInterceptorClass(classElement)) { | 992 if (backend.isInterceptorClass(classElement) |
| 999 // The operator== method in [:Object:] does not take the same | 993 && classElement != compiler.objectClass) { |
| 1000 // number of arguments as an intercepted method, therefore we | 994 // We optimize the operator== on interceptor classes to |
| 1001 // explicitely add one to all interceptor classes. Note that we | 995 // just do a JavaScript double or triple equals. |
| 1002 // would not have do do that if all intercepted methods had | |
| 1003 // a calling convention where the receiver is the first | |
| 1004 // parameter. | |
| 1005 String name = backend.namer.publicInstanceMethodNameByArity( | 996 String name = backend.namer.publicInstanceMethodNameByArity( |
| 1006 const SourceString('=='), 1); | 997 const SourceString('=='), 1); |
| 1007 Function kind = (classElement == backend.jsNullClass) | 998 Function kind = (classElement == backend.jsNullClass) |
| 1008 ? js.equals | 999 ? js.equals |
| 1009 : js.strictEquals; | 1000 : js.strictEquals; |
| 1010 builder.addProperty(name, js.fun(['receiver', 'a'], | 1001 builder.addProperty(name, js.fun(['receiver', 'a'], |
| 1011 js.block(js.return_(kind(js['receiver'], js['a']))))); | 1002 js.block(js.return_(kind(js['receiver'], js['a']))))); |
| 1012 } | 1003 } |
| 1013 } | 1004 } |
| 1014 | 1005 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 if ((isInstantiated && !enclosingClass.isNative()) | 1113 if ((isInstantiated && !enclosingClass.isNative()) |
| 1123 || needsGetter | 1114 || needsGetter |
| 1124 || needsSetter) { | 1115 || needsSetter) { |
| 1125 String accessorName = isShadowed | 1116 String accessorName = isShadowed |
| 1126 ? namer.shadowedFieldName(member) | 1117 ? namer.shadowedFieldName(member) |
| 1127 : namer.getName(member); | 1118 : namer.getName(member); |
| 1128 String fieldName = member.hasFixedBackendName() | 1119 String fieldName = member.hasFixedBackendName() |
| 1129 ? member.fixedBackendName() | 1120 ? member.fixedBackendName() |
| 1130 : (isMixinNativeField ? member.name.slowToString() : accessorName); | 1121 : (isMixinNativeField ? member.name.slowToString() : accessorName); |
| 1131 bool needsCheckedSetter = false; | 1122 bool needsCheckedSetter = false; |
| 1132 if (needsSetter && compiler.enableTypeAssertions | 1123 if (needsSetter) { |
| 1133 && canGenerateCheckedSetter(member)) { | 1124 if (compiler.enableTypeAssertions |
| 1134 needsCheckedSetter = true; | 1125 && canGenerateCheckedSetter(member)) { |
| 1135 needsSetter = false; | 1126 needsCheckedSetter = true; |
| 1127 needsSetter = false; |
| 1128 } else if (backend.isInterceptedMethod(member)) { |
| 1129 // The [addField] will take care of generating the setter. |
| 1130 needsSetter = false; |
| 1131 } |
| 1136 } | 1132 } |
| 1137 // Getters and setters with suffixes will be generated dynamically. | 1133 // Getters and setters with suffixes will be generated dynamically. |
| 1138 addField(member, | 1134 addField(member, |
| 1139 fieldName, | 1135 fieldName, |
| 1140 accessorName, | 1136 accessorName, |
| 1141 needsGetter, | 1137 needsGetter, |
| 1142 needsSetter, | 1138 needsSetter, |
| 1143 needsCheckedSetter); | 1139 needsCheckedSetter); |
| 1144 } | 1140 } |
| 1145 } | 1141 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1163 // allowed on fields that are in [classElement] we don't need to visit | 1159 // allowed on fields that are in [classElement] we don't need to visit |
| 1164 // superclasses for non-instantiated classes. | 1160 // superclasses for non-instantiated classes. |
| 1165 classElement.implementation.forEachInstanceField( | 1161 classElement.implementation.forEachInstanceField( |
| 1166 visitField, | 1162 visitField, |
| 1167 includeBackendMembers: true, | 1163 includeBackendMembers: true, |
| 1168 includeSuperMembers: isInstantiated && !classElement.isNative()); | 1164 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 1169 } | 1165 } |
| 1170 | 1166 |
| 1171 void generateGetter(Element member, String fieldName, String accessorName, | 1167 void generateGetter(Element member, String fieldName, String accessorName, |
| 1172 ClassBuilder builder) { | 1168 ClassBuilder builder) { |
| 1169 assert(!backend.isInterceptorClass(member)); |
| 1173 String getterName = namer.getterNameFromAccessorName(accessorName); | 1170 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 1174 builder.addProperty(getterName, | 1171 builder.addProperty(getterName, |
| 1175 js.fun([], js.return_(js['this'][fieldName]))); | 1172 js.fun([], js.return_(js['this'][fieldName]))); |
| 1176 } | 1173 } |
| 1177 | 1174 |
| 1178 void generateSetter(Element member, String fieldName, String accessorName, | 1175 void generateSetter(Element member, String fieldName, String accessorName, |
| 1179 ClassBuilder builder) { | 1176 ClassBuilder builder) { |
| 1177 assert(!backend.isInterceptorClass(member)); |
| 1180 String setterName = namer.setterNameFromAccessorName(accessorName); | 1178 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1179 List<String> args = backend.isInterceptedMethod(member) |
| 1180 ? ['receiver', 'v'] |
| 1181 : ['v']; |
| 1181 builder.addProperty(setterName, | 1182 builder.addProperty(setterName, |
| 1182 js.fun(['v'], js['this'][fieldName].assign('v'))); | 1183 js.fun(args, js['this'][fieldName].assign('v'))); |
| 1183 } | 1184 } |
| 1184 | 1185 |
| 1185 bool canGenerateCheckedSetter(Element member) { | 1186 bool canGenerateCheckedSetter(Element member) { |
| 1186 DartType type = member.computeType(compiler); | 1187 DartType type = member.computeType(compiler); |
| 1187 if (type.element.isTypeVariable() | 1188 if (type.element.isTypeVariable() |
| 1188 || type.element == compiler.dynamicClass | 1189 || type.element == compiler.dynamicClass |
| 1189 || type.element == compiler.objectClass) { | 1190 || type.element == compiler.objectClass) { |
| 1190 // TODO(ngeoffray): Support type checks on type parameters. | 1191 // TODO(ngeoffray): Support type checks on type parameters. |
| 1191 return false; | 1192 return false; |
| 1192 } | 1193 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1203 if (type.element.isErroneous()) return; | 1204 if (type.element.isErroneous()) return; |
| 1204 FunctionElement helperElement | 1205 FunctionElement helperElement |
| 1205 = backend.getCheckedModeHelper(type, typeCast: false); | 1206 = backend.getCheckedModeHelper(type, typeCast: false); |
| 1206 String helperName = namer.isolateAccess(helperElement); | 1207 String helperName = namer.isolateAccess(helperElement); |
| 1207 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; | 1208 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; |
| 1208 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 1209 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 1209 arguments.add(js.string(namer.operatorIs(type.element))); | 1210 arguments.add(js.string(namer.operatorIs(type.element))); |
| 1210 } | 1211 } |
| 1211 | 1212 |
| 1212 String setterName = namer.setterNameFromAccessorName(accessorName); | 1213 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1214 List<String> args = backend.isInterceptedMethod(member) |
| 1215 ? ['receiver', 'v'] |
| 1216 : ['v']; |
| 1213 builder.addProperty(setterName, | 1217 builder.addProperty(setterName, |
| 1214 js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments)))); | 1218 js.fun(args, js['this'][fieldName].assign(js[helperName](arguments)))); |
| 1215 } | 1219 } |
| 1216 | 1220 |
| 1217 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { | 1221 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { |
| 1218 /* Do nothing. */ | 1222 /* Do nothing. */ |
| 1219 } | 1223 } |
| 1220 | 1224 |
| 1221 void emitSuper(String superName, ClassBuilder builder) { | 1225 void emitSuper(String superName, ClassBuilder builder) { |
| 1222 /* Do nothing. */ | 1226 /* Do nothing. */ |
| 1223 } | 1227 } |
| 1224 | 1228 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 assert(!needsSetter); | 1300 assert(!needsSetter); |
| 1297 generateCheckedSetter(member, name, accessorName, builder); | 1301 generateCheckedSetter(member, name, accessorName, builder); |
| 1298 } | 1302 } |
| 1299 if (!getterAndSetterCanBeImplementedByFieldSpec) { | 1303 if (!getterAndSetterCanBeImplementedByFieldSpec) { |
| 1300 if (needsGetter) { | 1304 if (needsGetter) { |
| 1301 generateGetter(member, name, accessorName, builder); | 1305 generateGetter(member, name, accessorName, builder); |
| 1302 } | 1306 } |
| 1303 if (needsSetter) { | 1307 if (needsSetter) { |
| 1304 generateSetter(member, name, accessorName, builder); | 1308 generateSetter(member, name, accessorName, builder); |
| 1305 } | 1309 } |
| 1310 } else if (backend.isInterceptedMethod(member) |
| 1311 && instanceFieldNeedsSetter(member)) { |
| 1312 generateSetter(member, name, accessorName, builder); |
| 1306 } | 1313 } |
| 1307 }); | 1314 }); |
| 1308 }); | 1315 }); |
| 1309 } | 1316 } |
| 1310 | 1317 |
| 1311 /** | 1318 /** |
| 1312 * Documentation wanted -- johnniwinther | 1319 * Documentation wanted -- johnniwinther |
| 1313 * | 1320 * |
| 1314 * Invariant: [classElement] must be a declaration element. | 1321 * Invariant: [classElement] must be a declaration element. |
| 1315 */ | 1322 */ |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1355 return arity; | 1362 return arity; |
| 1356 } | 1363 } |
| 1357 | 1364 |
| 1358 int _compareSelectorNames(Selector selector1, Selector selector2) { | 1365 int _compareSelectorNames(Selector selector1, Selector selector2) { |
| 1359 String name1 = selector1.name.toString(); | 1366 String name1 = selector1.name.toString(); |
| 1360 String name2 = selector2.name.toString(); | 1367 String name2 = selector2.name.toString(); |
| 1361 if (name1 != name2) return Comparable.compare(name1, name2); | 1368 if (name1 != name2) return Comparable.compare(name1, name2); |
| 1362 return _selectorRank(selector1) - _selectorRank(selector2); | 1369 return _selectorRank(selector1) - _selectorRank(selector2); |
| 1363 } | 1370 } |
| 1364 | 1371 |
| 1365 void emitInterceptorMethods(ClassBuilder builder) { | |
| 1366 // Emit forwarders for the ObjectInterceptor class. We need to | |
| 1367 // emit all possible sends on intercepted methods. Because of | |
| 1368 // typed selectors we have to avoid generating the same forwarder | |
| 1369 // multiple times. | |
| 1370 Set<String> alreadyGenerated = new Set<String>(); | |
| 1371 for (Selector selector in | |
| 1372 backend.usedInterceptors.toList()..sort(_compareSelectorNames)) { | |
| 1373 String name = backend.namer.invocationName(selector); | |
| 1374 if (alreadyGenerated.contains(name)) continue; | |
| 1375 alreadyGenerated.add(name); | |
| 1376 | |
| 1377 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | |
| 1378 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
| 1379 parameters.add(new jsAst.Parameter('receiver')); | |
| 1380 | |
| 1381 if (selector.isSetter()) { | |
| 1382 parameters.add(new jsAst.Parameter('value')); | |
| 1383 arguments.add(js['value']); | |
| 1384 } else { | |
| 1385 for (int i = 0; i < selector.argumentCount; i++) { | |
| 1386 String argName = 'a$i'; | |
| 1387 parameters.add(new jsAst.Parameter(argName)); | |
| 1388 arguments.add(js[argName]); | |
| 1389 } | |
| 1390 } | |
| 1391 jsAst.Fun function = | |
| 1392 js.fun(parameters, js.return_(js['receiver'][name](arguments))); | |
| 1393 builder.addProperty(name, function); | |
| 1394 } | |
| 1395 } | |
| 1396 | |
| 1397 Iterable<Element> getTypedefChecksOn(DartType type) { | 1372 Iterable<Element> getTypedefChecksOn(DartType type) { |
| 1398 bool isSubtype(TypedefElement typedef) { | 1373 bool isSubtype(TypedefElement typedef) { |
| 1399 FunctionType typedefType = | 1374 FunctionType typedefType = |
| 1400 typedef.computeType(compiler).unalias(compiler); | 1375 typedef.computeType(compiler).unalias(compiler); |
| 1401 return compiler.types.isSubtype(type, typedefType); | 1376 return compiler.types.isSubtype(type, typedefType); |
| 1402 } | 1377 } |
| 1403 return checkedTypedefs.where(isSubtype).toList() | 1378 return checkedTypedefs.where(isSubtype).toList() |
| 1404 ..sort(Elements.compareByPosition); | 1379 ..sort(Elements.compareByPosition); |
| 1405 } | 1380 } |
| 1406 | 1381 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1553 for (Constant constant in constants) { | 1528 for (Constant constant in constants) { |
| 1554 if (constant is ConstructedConstant) { | 1529 if (constant is ConstructedConstant) { |
| 1555 Element element = constant.computeType(compiler).element; | 1530 Element element = constant.computeType(compiler).element; |
| 1556 if (backend.isInterceptorClass(element)) { | 1531 if (backend.isInterceptorClass(element)) { |
| 1557 needed.add(element); | 1532 needed.add(element); |
| 1558 } | 1533 } |
| 1559 } | 1534 } |
| 1560 } | 1535 } |
| 1561 | 1536 |
| 1562 // Add unneeded interceptors to the [unneededClasses] set. | 1537 // Add unneeded interceptors to the [unneededClasses] set. |
| 1563 for (ClassElement interceptor in backend.interceptedClasses.keys) { | 1538 for (ClassElement interceptor in backend.interceptedClasses) { |
| 1564 if (!needed.contains(interceptor)) { | 1539 if (!needed.contains(interceptor) |
| 1540 && interceptor != compiler.objectClass) { |
| 1565 unneededClasses.add(interceptor); | 1541 unneededClasses.add(interceptor); |
| 1566 } | 1542 } |
| 1567 } | 1543 } |
| 1568 | 1544 |
| 1569 return (ClassElement cls) => !unneededClasses.contains(cls); | 1545 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1570 } | 1546 } |
| 1571 | 1547 |
| 1572 void emitClosureClassIfNeeded(CodeBuffer buffer) { | 1548 void emitClosureClassIfNeeded(CodeBuffer buffer) { |
| 1573 // The closure class could have become necessary because of the generation | 1549 // The closure class could have become necessary because of the generation |
| 1574 // of stubs. | 1550 // of stubs. |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1704 // if they share methods with the same signature. Currently we do this only | 1680 // if they share methods with the same signature. Currently we do this only |
| 1705 // if there are no optional parameters. Closures with optional parameters | 1681 // if there are no optional parameters. Closures with optional parameters |
| 1706 // are more difficult to canonicalize because they would need to have the | 1682 // are more difficult to canonicalize because they would need to have the |
| 1707 // same default values. | 1683 // same default values. |
| 1708 | 1684 |
| 1709 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; | 1685 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; |
| 1710 int parameterCount = member.parameterCount(compiler); | 1686 int parameterCount = member.parameterCount(compiler); |
| 1711 | 1687 |
| 1712 Map<int, String> cache; | 1688 Map<int, String> cache; |
| 1713 String extraArg = null; | 1689 String extraArg = null; |
| 1714 // Methods on interceptor classes take an extra parameter, which is the | 1690 // Intercepted methods take an extra parameter, which is the |
| 1715 // actual receiver of the call. | 1691 // receiver of the call. |
| 1716 bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass()); | 1692 bool inInterceptor = backend.isInterceptedMethod(member); |
| 1717 if (inInterceptor) { | 1693 if (inInterceptor) { |
| 1718 cache = interceptorClosureCache; | 1694 cache = interceptorClosureCache; |
| 1719 extraArg = 'receiver'; | 1695 extraArg = 'receiver'; |
| 1720 } else { | 1696 } else { |
| 1721 cache = boundClosureCache; | 1697 cache = boundClosureCache; |
| 1722 } | 1698 } |
| 1723 List<String> fieldNames = compiler.enableMinification | 1699 List<String> fieldNames = compiler.enableMinification |
| 1724 ? inInterceptor ? const ['a', 'b', 'c'] | 1700 ? inInterceptor ? const ['a', 'b', 'c'] |
| 1725 : const ['a', 'b'] | 1701 : const ['a', 'b'] |
| 1726 : inInterceptor ? const ['self', 'target', 'receiver'] | 1702 : inInterceptor ? const ['self', 'target', 'receiver'] |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1827 /** | 1803 /** |
| 1828 * Documentation wanted -- johnniwinther | 1804 * Documentation wanted -- johnniwinther |
| 1829 * | 1805 * |
| 1830 * Invariant: [member] must be a declaration element. | 1806 * Invariant: [member] must be a declaration element. |
| 1831 */ | 1807 */ |
| 1832 void emitCallStubForGetter(Element member, | 1808 void emitCallStubForGetter(Element member, |
| 1833 Set<Selector> selectors, | 1809 Set<Selector> selectors, |
| 1834 DefineStubFunction defineStub) { | 1810 DefineStubFunction defineStub) { |
| 1835 assert(invariant(member, member.isDeclaration)); | 1811 assert(invariant(member, member.isDeclaration)); |
| 1836 LibraryElement memberLibrary = member.getLibrary(); | 1812 LibraryElement memberLibrary = member.getLibrary(); |
| 1837 // If the class is an interceptor class, the stub gets the | 1813 // If the method is intercepted, the stub gets the |
| 1838 // receiver explicitely and we need to pass it to the getter call. | 1814 // receiver explicitely and we need to pass it to the getter call. |
| 1839 bool isInterceptorClass = | 1815 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 1840 backend.isInterceptorClass(member.getEnclosingClass()); | |
| 1841 | 1816 |
| 1842 const String receiverArgumentName = r'$receiver'; | 1817 const String receiverArgumentName = r'$receiver'; |
| 1843 | 1818 |
| 1844 jsAst.Expression buildGetter() { | 1819 jsAst.Expression buildGetter() { |
| 1845 if (member.isGetter()) { | 1820 if (member.isGetter()) { |
| 1846 String getterName = namer.getterName(member); | 1821 String getterName = namer.getterName(member); |
| 1847 return js['this'][getterName]( | 1822 return js['this'][getterName]( |
| 1848 isInterceptorClass | 1823 isInterceptedMethod |
| 1849 ? <jsAst.Expression>[js[receiverArgumentName]] | 1824 ? <jsAst.Expression>[js[receiverArgumentName]] |
| 1850 : <jsAst.Expression>[]); | 1825 : <jsAst.Expression>[]); |
| 1851 } else { | 1826 } else { |
| 1852 String fieldName = member.hasFixedBackendName() | 1827 String fieldName = member.hasFixedBackendName() |
| 1853 ? member.fixedBackendName() | 1828 ? member.fixedBackendName() |
| 1854 : namer.instanceFieldName(member); | 1829 : namer.instanceFieldName(member); |
| 1855 return js['this'][fieldName]; | 1830 return js['this'][fieldName]; |
| 1856 } | 1831 } |
| 1857 } | 1832 } |
| 1858 | 1833 |
| 1859 // Two selectors may match but differ only in type. To avoid generating | 1834 // Two selectors may match but differ only in type. To avoid generating |
| 1860 // identical stubs for each we track untyped selectors which already have | 1835 // identical stubs for each we track untyped selectors which already have |
| 1861 // stubs. | 1836 // stubs. |
| 1862 Set<Selector> generatedSelectors = new Set<Selector>(); | 1837 Set<Selector> generatedSelectors = new Set<Selector>(); |
| 1863 | 1838 |
| 1864 for (Selector selector in selectors) { | 1839 for (Selector selector in selectors) { |
| 1865 if (selector.applies(member, compiler)) { | 1840 if (selector.applies(member, compiler)) { |
| 1866 selector = selector.asUntyped; | 1841 selector = selector.asUntyped; |
| 1867 if (generatedSelectors.contains(selector)) continue; | 1842 if (generatedSelectors.contains(selector)) continue; |
| 1868 generatedSelectors.add(selector); | 1843 generatedSelectors.add(selector); |
| 1869 | 1844 |
| 1870 String invocationName = namer.invocationName(selector); | 1845 String invocationName = namer.invocationName(selector); |
| 1871 Selector callSelector = new Selector.callClosureFrom(selector); | 1846 Selector callSelector = new Selector.callClosureFrom(selector); |
| 1872 String closureCallName = namer.invocationName(callSelector); | 1847 String closureCallName = namer.invocationName(callSelector); |
| 1873 | 1848 |
| 1874 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 1849 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 1875 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 1850 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 1876 if (isInterceptorClass) { | 1851 if (isInterceptedMethod) { |
| 1877 parameters.add(new jsAst.Parameter(receiverArgumentName)); | 1852 parameters.add(new jsAst.Parameter(receiverArgumentName)); |
| 1878 } | 1853 } |
| 1879 | 1854 |
| 1880 for (int i = 0; i < selector.argumentCount; i++) { | 1855 for (int i = 0; i < selector.argumentCount; i++) { |
| 1881 String name = 'arg$i'; | 1856 String name = 'arg$i'; |
| 1882 parameters.add(new jsAst.Parameter(name)); | 1857 parameters.add(new jsAst.Parameter(name)); |
| 1883 arguments.add(js[name]); | 1858 arguments.add(js[name]); |
| 1884 } | 1859 } |
| 1885 | 1860 |
| 1886 jsAst.Fun function = js.fun( | 1861 jsAst.Fun function = js.fun( |
| 1887 parameters, | 1862 parameters, |
| 1888 js.return_(buildGetter()[closureCallName](arguments))); | 1863 js.return_(buildGetter()[closureCallName](arguments))); |
| 1889 | 1864 |
| 1890 defineStub(invocationName, function); | 1865 defineStub(invocationName, function); |
| 1891 } | 1866 } |
| 1892 } | 1867 } |
| 1893 } | 1868 } |
| 1894 | 1869 |
| 1895 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1870 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1896 ConstantHandler handler = compiler.constantHandler; | 1871 ConstantHandler handler = compiler.constantHandler; |
| 1897 Iterable<VariableElement> staticNonFinalFields = | 1872 Iterable<VariableElement> staticNonFinalFields = |
| 1898 handler.getStaticNonFinalFieldsForEmission(); | 1873 handler.getStaticNonFinalFieldsForEmission(); |
| 1899 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 1874 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 1875 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
| 1876 if (element == backend.interceptedNames) continue; |
| 1900 compiler.withCurrentElement(element, () { | 1877 compiler.withCurrentElement(element, () { |
| 1901 Constant initialValue = handler.getInitialValueFor(element); | 1878 Constant initialValue = handler.getInitialValueFor(element); |
| 1902 jsAst.Expression init = | 1879 jsAst.Expression init = |
| 1903 js[isolateProperties][namer.getName(element)].assign( | 1880 js[isolateProperties][namer.getName(element)].assign( |
| 1904 constantEmitter.referenceInInitializationContext(initialValue)); | 1881 constantEmitter.referenceInInitializationContext(initialValue)); |
| 1905 buffer.add(jsAst.prettyPrint(init, compiler)); | 1882 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1906 buffer.add('$N'); | 1883 buffer.add('$N'); |
| 1907 }); | 1884 }); |
| 1908 } | 1885 } |
| 1909 } | 1886 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2028 | 2005 |
| 2029 List<jsAst.Expression> argNames = | 2006 List<jsAst.Expression> argNames = |
| 2030 selector.getOrderedNamedArguments().map((SourceString name) => | 2007 selector.getOrderedNamedArguments().map((SourceString name) => |
| 2031 js.string(name.slowToString())).toList(); | 2008 js.string(name.slowToString())).toList(); |
| 2032 | 2009 |
| 2033 String internalName = namer.invocationMirrorInternalName(selector); | 2010 String internalName = namer.invocationMirrorInternalName(selector); |
| 2034 | 2011 |
| 2035 String createInvocationMirror = namer.getName( | 2012 String createInvocationMirror = namer.getName( |
| 2036 compiler.createInvocationMirrorElement); | 2013 compiler.createInvocationMirrorElement); |
| 2037 | 2014 |
| 2015 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD)); |
| 2038 jsAst.Expression expression = js['this.$noSuchMethodName']( | 2016 jsAst.Expression expression = js['this.$noSuchMethodName']( |
| 2039 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ | 2017 [js['this'], |
| 2040 js.string(methodName), | 2018 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ |
| 2041 js.string(internalName), | 2019 js.string(methodName), |
| 2042 type, | 2020 js.string(internalName), |
| 2043 new jsAst.ArrayInitializer.from( | 2021 type, |
| 2044 parameters.map((param) => js[param.name]).toList()), | 2022 new jsAst.ArrayInitializer.from( |
| 2045 new jsAst.ArrayInitializer.from(argNames)])); | 2023 parameters.map((param) => js[param.name]).toList()), |
| 2024 new jsAst.ArrayInitializer.from(argNames)])]); |
| 2025 parameters = backend.isInterceptedName(selector.name) |
| 2026 ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters)) |
| 2027 : parameters; |
| 2046 return js.fun(parameters, js.return_(expression)); | 2028 return js.fun(parameters, js.return_(expression)); |
| 2047 } | 2029 } |
| 2048 | 2030 |
| 2049 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 2031 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 2050 // Cache the object class and type. | 2032 // Cache the object class and type. |
| 2051 ClassElement objectClass = compiler.objectClass; | 2033 ClassElement objectClass = compiler.objectClass; |
| 2052 DartType objectType = objectClass.computeType(compiler); | 2034 DartType objectType = objectClass.computeType(compiler); |
| 2053 | 2035 |
| 2054 for (Selector selector in selectors) { | 2036 for (Selector selector in selectors) { |
| 2055 // Introduce a helper function that determines if the given | 2037 // Introduce a helper function that determines if the given |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2176 dartMainRunner(function() { ${mainCall}; }); | 2158 dartMainRunner(function() { ${mainCall}; }); |
| 2177 } else { | 2159 } else { |
| 2178 ${mainCall}; | 2160 ${mainCall}; |
| 2179 } | 2161 } |
| 2180 } | 2162 } |
| 2181 """); | 2163 """); |
| 2182 addComment('END invoke [main].', buffer); | 2164 addComment('END invoke [main].', buffer); |
| 2183 } | 2165 } |
| 2184 | 2166 |
| 2185 void emitGetInterceptorMethod(CodeBuffer buffer, | 2167 void emitGetInterceptorMethod(CodeBuffer buffer, |
| 2186 String objectName, | |
| 2187 String key, | 2168 String key, |
| 2188 Collection<ClassElement> classes) { | 2169 Collection<ClassElement> classes) { |
| 2189 jsAst.Statement buildReturnInterceptor(ClassElement cls) { | 2170 jsAst.Statement buildReturnInterceptor(ClassElement cls) { |
| 2190 return js.return_(js[namer.isolateAccess(cls)]['prototype']); | 2171 return js.return_(js[namer.isolateAccess(cls)]['prototype']); |
| 2191 } | 2172 } |
| 2192 | 2173 |
| 2193 jsAst.VariableUse receiver = js['receiver']; | 2174 jsAst.VariableUse receiver = js['receiver']; |
| 2194 /** | 2175 /** |
| 2195 * Build a JavaScrit AST node for doing a type check on | 2176 * Build a JavaScrit AST node for doing a type check on |
| 2196 * [cls]. [cls] must be an interceptor class. | 2177 * [cls]. [cls] must be an interceptor class. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2228 bool hasString = false; | 2209 bool hasString = false; |
| 2229 for (ClassElement cls in classes) { | 2210 for (ClassElement cls in classes) { |
| 2230 if (cls == backend.jsArrayClass) hasArray = true; | 2211 if (cls == backend.jsArrayClass) hasArray = true; |
| 2231 else if (cls == backend.jsBoolClass) hasBool = true; | 2212 else if (cls == backend.jsBoolClass) hasBool = true; |
| 2232 else if (cls == backend.jsDoubleClass) hasDouble = true; | 2213 else if (cls == backend.jsDoubleClass) hasDouble = true; |
| 2233 else if (cls == backend.jsFunctionClass) hasFunction = true; | 2214 else if (cls == backend.jsFunctionClass) hasFunction = true; |
| 2234 else if (cls == backend.jsIntClass) hasInt = true; | 2215 else if (cls == backend.jsIntClass) hasInt = true; |
| 2235 else if (cls == backend.jsNullClass) hasNull = true; | 2216 else if (cls == backend.jsNullClass) hasNull = true; |
| 2236 else if (cls == backend.jsNumberClass) hasNumber = true; | 2217 else if (cls == backend.jsNumberClass) hasNumber = true; |
| 2237 else if (cls == backend.jsStringClass) hasString = true; | 2218 else if (cls == backend.jsStringClass) hasString = true; |
| 2238 else throw 'Internal error: $cls'; | 2219 else { |
| 2220 assert(cls == compiler.objectClass); |
| 2221 } |
| 2239 } | 2222 } |
| 2240 if (hasDouble) { | 2223 if (hasDouble) { |
| 2241 assert(!hasNumber); | |
| 2242 hasNumber = true; | 2224 hasNumber = true; |
| 2243 } | 2225 } |
| 2244 if (hasInt) hasNumber = true; | 2226 if (hasInt) hasNumber = true; |
| 2245 | 2227 |
| 2246 jsAst.Block block = new jsAst.Block.empty(); | 2228 jsAst.Block block = new jsAst.Block.empty(); |
| 2247 | 2229 |
| 2248 if (hasNumber) { | 2230 if (hasNumber) { |
| 2249 jsAst.Statement whenNumber; | 2231 jsAst.Statement whenNumber; |
| 2250 | 2232 |
| 2251 /// Note: there are two number classes in play: Dart's [num], | 2233 /// Note: there are two number classes in play: Dart's [num], |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2284 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); | 2266 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); |
| 2285 } | 2267 } |
| 2286 if (hasBool) { | 2268 if (hasBool) { |
| 2287 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); | 2269 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); |
| 2288 } | 2270 } |
| 2289 // TODO(ahe): It might be faster to check for Array before | 2271 // TODO(ahe): It might be faster to check for Array before |
| 2290 // function and bool. | 2272 // function and bool. |
| 2291 if (hasArray) { | 2273 if (hasArray) { |
| 2292 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); | 2274 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); |
| 2293 } | 2275 } |
| 2294 block.statements.add(js.return_(js[objectName]['prototype'])); | 2276 block.statements.add(js.return_(receiver)); |
| 2295 | 2277 |
| 2296 buffer.add(jsAst.prettyPrint( | 2278 buffer.add(jsAst.prettyPrint( |
| 2297 js[isolateProperties][key].assign(js.fun(['receiver'], block)), | 2279 js[isolateProperties][key].assign(js.fun(['receiver'], block)), |
| 2298 compiler)); | 2280 compiler)); |
| 2299 buffer.add(N); | 2281 buffer.add(N); |
| 2300 } | 2282 } |
| 2301 | 2283 |
| 2302 /** | 2284 /** |
| 2303 * Emit all versions of the [:getInterceptor:] method. | 2285 * Emit all versions of the [:getInterceptor:] method. |
| 2304 */ | 2286 */ |
| 2305 void emitGetInterceptorMethods(CodeBuffer buffer) { | 2287 void emitGetInterceptorMethods(CodeBuffer buffer) { |
| 2306 // If no class needs to be intercepted, just return. | |
| 2307 if (backend.objectInterceptorClass == null) return; | |
| 2308 String objectName = namer.isolateAccess(backend.objectInterceptorClass); | |
| 2309 var specializedGetInterceptors = backend.specializedGetInterceptors; | 2288 var specializedGetInterceptors = backend.specializedGetInterceptors; |
| 2310 for (String name in specializedGetInterceptors.keys.toList()..sort()) { | 2289 for (String name in specializedGetInterceptors.keys.toList()..sort()) { |
| 2311 Collection<ClassElement> classes = specializedGetInterceptors[name]; | 2290 Collection<ClassElement> classes = specializedGetInterceptors[name]; |
| 2312 emitGetInterceptorMethod(buffer, objectName, name, classes); | 2291 emitGetInterceptorMethod(buffer, name, classes); |
| 2313 } | 2292 } |
| 2314 } | 2293 } |
| 2315 | 2294 |
| 2316 /** | 2295 /** |
| 2317 * Compute all the classes that must be emitted. | 2296 * Compute all the classes that must be emitted. |
| 2318 */ | 2297 */ |
| 2319 void computeNeededClasses() { | 2298 void computeNeededClasses() { |
| 2320 instantiatedClasses = | 2299 instantiatedClasses = |
| 2321 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) | 2300 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) |
| 2322 .toSet(); | 2301 .toSet(); |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2528 } | 2507 } |
| 2529 return null; | 2508 return null; |
| 2530 } | 2509 } |
| 2531 | 2510 |
| 2532 void emitOneShotInterceptors(CodeBuffer buffer) { | 2511 void emitOneShotInterceptors(CodeBuffer buffer) { |
| 2533 List<String> names = backend.oneShotInterceptors.keys.toList(); | 2512 List<String> names = backend.oneShotInterceptors.keys.toList(); |
| 2534 names.sort(); | 2513 names.sort(); |
| 2535 for (String name in names) { | 2514 for (String name in names) { |
| 2536 Selector selector = backend.oneShotInterceptors[name]; | 2515 Selector selector = backend.oneShotInterceptors[name]; |
| 2537 Set<ClassElement> classes = | 2516 Set<ClassElement> classes = |
| 2538 backend.getInterceptedClassesOn(selector); | 2517 backend.getInterceptedClassesOn(selector.name); |
| 2539 String getInterceptorName = | 2518 String getInterceptorName = |
| 2540 namer.getInterceptorName(backend.getInterceptorMethod, classes); | 2519 namer.getInterceptorName(backend.getInterceptorMethod, classes); |
| 2541 | 2520 |
| 2542 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 2521 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 2543 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 2522 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 2544 parameters.add(new jsAst.Parameter('receiver')); | 2523 parameters.add(new jsAst.Parameter('receiver')); |
| 2545 arguments.add(js['receiver']); | 2524 arguments.add(js['receiver']); |
| 2546 | 2525 |
| 2547 if (selector.isSetter()) { | 2526 if (selector.isSetter()) { |
| 2548 parameters.add(new jsAst.Parameter('value')); | 2527 parameters.add(new jsAst.Parameter('value')); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2570 jsAst.Fun function = js.fun(parameters, body); | 2549 jsAst.Fun function = js.fun(parameters, body); |
| 2571 | 2550 |
| 2572 jsAst.PropertyAccess property = | 2551 jsAst.PropertyAccess property = |
| 2573 js[isolateProperties][name]; | 2552 js[isolateProperties][name]; |
| 2574 | 2553 |
| 2575 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); | 2554 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); |
| 2576 buffer.add(N); | 2555 buffer.add(N); |
| 2577 } | 2556 } |
| 2578 } | 2557 } |
| 2579 | 2558 |
| 2559 /** |
| 2560 * If [:invokeOn:] has been compiled, emit all the possible selector names |
| 2561 * that are intercepted into the [:interceptedNames:] top-level |
| 2562 * variable. The implementation of [:invokeOn:] will use it to |
| 2563 * determine whether it should call the method with an extra |
| 2564 * parameter. |
| 2565 */ |
| 2566 void emitInterceptedNames(CodeBuffer buffer) { |
| 2567 if (!compiler.enabledInvokeOn) return; |
| 2568 String name = backend.namer.getName(backend.interceptedNames); |
| 2569 jsAst.PropertyAccess property = js[isolateProperties][name]; |
| 2570 |
| 2571 int index = 0; |
| 2572 List<jsAst.ArrayElement> elements = backend.usedInterceptors.map( |
| 2573 (Selector selector) { |
| 2574 jsAst.Literal str = js.string(namer.invocationName(selector)); |
| 2575 return new jsAst.ArrayElement(index++, str); |
| 2576 }).toList(); |
| 2577 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer( |
| 2578 backend.usedInterceptors.length, |
| 2579 elements); |
| 2580 |
| 2581 buffer.add(jsAst.prettyPrint(property.assign(array), compiler)); |
| 2582 buffer.add(N); |
| 2583 } |
| 2584 |
| 2580 void emitInitFunction(CodeBuffer buffer) { | 2585 void emitInitFunction(CodeBuffer buffer) { |
| 2581 jsAst.Fun fun = js.fun([], [ | 2586 jsAst.Fun fun = js.fun([], [ |
| 2582 js['$isolateProperties = {}'], | 2587 js['$isolateProperties = {}'], |
| 2583 ] | 2588 ] |
| 2584 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 2589 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
| 2585 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 2590 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
| 2586 ..addAll(buildFinishIsolateConstructor()) | 2591 ..addAll(buildFinishIsolateConstructor()) |
| 2587 ); | 2592 ); |
| 2588 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 2593 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
| 2589 new jsAst.VariableDeclaration('init'), fun); | 2594 new jsAst.VariableDeclaration('init'), fun); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2671 | 2676 |
| 2672 emitStaticFunctions(mainBuffer); | 2677 emitStaticFunctions(mainBuffer); |
| 2673 emitStaticFunctionGetters(mainBuffer); | 2678 emitStaticFunctionGetters(mainBuffer); |
| 2674 | 2679 |
| 2675 emitRuntimeTypeSupport(mainBuffer); | 2680 emitRuntimeTypeSupport(mainBuffer); |
| 2676 emitCompileTimeConstants(mainBuffer); | 2681 emitCompileTimeConstants(mainBuffer); |
| 2677 // Static field initializations require the classes and compile-time | 2682 // Static field initializations require the classes and compile-time |
| 2678 // constants to be set up. | 2683 // constants to be set up. |
| 2679 emitStaticNonFinalFieldInitializations(mainBuffer); | 2684 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 2680 emitOneShotInterceptors(mainBuffer); | 2685 emitOneShotInterceptors(mainBuffer); |
| 2686 emitInterceptedNames(mainBuffer); |
| 2681 emitGetInterceptorMethods(mainBuffer); | 2687 emitGetInterceptorMethods(mainBuffer); |
| 2682 emitLazilyInitializedStaticFields(mainBuffer); | 2688 emitLazilyInitializedStaticFields(mainBuffer); |
| 2683 | 2689 |
| 2684 isolateProperties = isolatePropertiesName; | 2690 isolateProperties = isolatePropertiesName; |
| 2685 // The following code should not use the short-hand for the | 2691 // The following code should not use the short-hand for the |
| 2686 // initialStatics. | 2692 // initialStatics. |
| 2687 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 2693 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| 2688 | 2694 |
| 2689 emitFinishIsolateConstructorInvocation(mainBuffer); | 2695 emitFinishIsolateConstructorInvocation(mainBuffer); |
| 2690 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' | 2696 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=' |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2771 """; | 2777 """; |
| 2772 const String HOOKS_API_USAGE = """ | 2778 const String HOOKS_API_USAGE = """ |
| 2773 // The code supports the following hooks: | 2779 // The code supports the following hooks: |
| 2774 // dartPrint(message) - if this function is defined it is called | 2780 // dartPrint(message) - if this function is defined it is called |
| 2775 // instead of the Dart [print] method. | 2781 // instead of the Dart [print] method. |
| 2776 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2782 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2777 // method will not be invoked directly. | 2783 // method will not be invoked directly. |
| 2778 // Instead, a closure that will invoke [main] is | 2784 // Instead, a closure that will invoke [main] is |
| 2779 // passed to [dartMainRunner]. | 2785 // passed to [dartMainRunner]. |
| 2780 """; | 2786 """; |
| OLD | NEW |