| 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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 // hit the method directly. | 630 // hit the method directly. |
| 631 return; | 631 return; |
| 632 } | 632 } |
| 633 ConstantHandler handler = compiler.constantHandler; | 633 ConstantHandler handler = compiler.constantHandler; |
| 634 List<SourceString> names = selector.getOrderedNamedArguments(); | 634 List<SourceString> names = selector.getOrderedNamedArguments(); |
| 635 | 635 |
| 636 String invocationName = namer.invocationName(selector); | 636 String invocationName = namer.invocationName(selector); |
| 637 if (alreadyGenerated.contains(invocationName)) return; | 637 if (alreadyGenerated.contains(invocationName)) return; |
| 638 alreadyGenerated.add(invocationName); | 638 alreadyGenerated.add(invocationName); |
| 639 | 639 |
| 640 bool isInterceptorClass = | 640 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 641 backend.isInterceptorClass(member.getEnclosingClass()); | |
| 642 | 641 |
| 643 // If the method is in an interceptor class, we need to also pass | 642 // If the method is intercepted, we need to also pass |
| 644 // the actual receiver. | 643 // the actual receiver. |
| 645 int extraArgumentCount = isInterceptorClass ? 1 : 0; | 644 int extraArgumentCount = isInterceptedMethod ? 1 : 0; |
| 646 // Use '$receiver' to avoid clashes with other parameter names. Using | 645 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 647 // '$receiver' works because [:namer.safeName:] used for getting parameter | 646 // '$receiver' works because [:namer.safeName:] used for getting parameter |
| 648 // names never returns a name beginning with a single '$'. | 647 // names never returns a name beginning with a single '$'. |
| 649 String receiverArgumentName = r'$receiver'; | 648 String receiverArgumentName = r'$receiver'; |
| 650 | 649 |
| 651 // The parameters that this stub takes. | 650 // The parameters that this stub takes. |
| 652 List<jsAst.Parameter> parametersBuffer = | 651 List<jsAst.Parameter> parametersBuffer = |
| 653 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); | 652 new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); |
| 654 // The arguments that will be passed to the real method. | 653 // The arguments that will be passed to the real method. |
| 655 List<jsAst.Expression> argumentsBuffer = | 654 List<jsAst.Expression> argumentsBuffer = |
| 656 new List<jsAst.Expression>( | 655 new List<jsAst.Expression>( |
| 657 parameters.parameterCount + extraArgumentCount); | 656 parameters.parameterCount + extraArgumentCount); |
| 658 | 657 |
| 659 int count = 0; | 658 int count = 0; |
| 660 if (isInterceptorClass) { | 659 if (isInterceptedMethod) { |
| 661 count++; | 660 count++; |
| 662 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 661 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 663 argumentsBuffer[0] = js[receiverArgumentName]; | 662 argumentsBuffer[0] = js[receiverArgumentName]; |
| 664 } | 663 } |
| 665 | 664 |
| 666 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 665 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
| 667 TreeElements elements = | 666 TreeElements elements = |
| 668 compiler.enqueuer.resolution.getCachedElements(member); | 667 compiler.enqueuer.resolution.getCachedElements(member); |
| 669 | 668 |
| 670 parameters.orderedForEachParameter((Element element) { | 669 parameters.orderedForEachParameter((Element element) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 } | 889 } |
| 891 | 890 |
| 892 /** | 891 /** |
| 893 * Documentation wanted -- johnniwinther | 892 * Documentation wanted -- johnniwinther |
| 894 * | 893 * |
| 895 * Invariant: [classElement] must be a declaration element. | 894 * Invariant: [classElement] must be a declaration element. |
| 896 */ | 895 */ |
| 897 void emitInstanceMembers(ClassElement classElement, | 896 void emitInstanceMembers(ClassElement classElement, |
| 898 ClassBuilder builder) { | 897 ClassBuilder builder) { |
| 899 assert(invariant(classElement, classElement.isDeclaration)); | 898 assert(invariant(classElement, classElement.isDeclaration)); |
| 900 if (classElement == backend.objectInterceptorClass) { | |
| 901 emitInterceptorMethods(builder); | |
| 902 // The ObjectInterceptor does not have any instance methods. | |
| 903 return; | |
| 904 } | |
| 905 | 899 |
| 906 void visitMember(ClassElement enclosing, Element member) { | 900 void visitMember(ClassElement enclosing, Element member) { |
| 907 assert(invariant(classElement, member.isDeclaration)); | 901 assert(invariant(classElement, member.isDeclaration)); |
| 908 if (member.isInstanceMember()) { | 902 if (member.isInstanceMember()) { |
| 909 addInstanceMember(member, builder); | 903 addInstanceMember(member, builder); |
| 910 } | 904 } |
| 911 } | 905 } |
| 912 | 906 |
| 913 // TODO(kasperl): We should make sure to only emit one version of | 907 // TODO(kasperl): We should make sure to only emit one version of |
| 914 // overridden methods. Right now, we rely on the ordering so the | 908 // overridden methods. Right now, we rely on the ordering so the |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 && compiler.enabledNoSuchMethod) { | 963 && compiler.enabledNoSuchMethod) { |
| 970 // Emit the noSuchMethod handlers on the Object prototype now, | 964 // Emit the noSuchMethod handlers on the Object prototype now, |
| 971 // so that the code in the dynamicFunction helper can find | 965 // so that the code in the dynamicFunction helper can find |
| 972 // them. Note that this helper is invoked before analyzing the | 966 // them. Note that this helper is invoked before analyzing the |
| 973 // full JS script. | 967 // full JS script. |
| 974 if (!nativeEmitter.handleNoSuchMethod) { | 968 if (!nativeEmitter.handleNoSuchMethod) { |
| 975 emitNoSuchMethodHandlers(builder.addProperty); | 969 emitNoSuchMethodHandlers(builder.addProperty); |
| 976 } | 970 } |
| 977 } | 971 } |
| 978 | 972 |
| 979 if (backend.isInterceptorClass(classElement)) { | 973 if (backend.isInterceptorClass(classElement) |
| 980 // The operator== method in [:Object:] does not take the same | 974 && classElement != compiler.objectClass) { |
| 981 // number of arguments as an intercepted method, therefore we | 975 // We optimize the operator== on interceptor classes to |
| 982 // explicitely add one to all interceptor classes. Note that we | 976 // just do a JavaScript double or triple equals. |
| 983 // would not have do do that if all intercepted methods had | |
| 984 // a calling convention where the receiver is the first | |
| 985 // parameter. | |
| 986 String name = backend.namer.publicInstanceMethodNameByArity( | 977 String name = backend.namer.publicInstanceMethodNameByArity( |
| 987 const SourceString('=='), 1); | 978 const SourceString('=='), 1); |
| 988 Function kind = (classElement == backend.jsNullClass) | 979 Function kind = (classElement == backend.jsNullClass) |
| 989 ? js.equals | 980 ? js.equals |
| 990 : js.strictEquals; | 981 : js.strictEquals; |
| 991 builder.addProperty(name, js.fun(['receiver', 'a'], | 982 builder.addProperty(name, js.fun(['receiver', 'a'], |
| 992 js.block(js.return_(kind(js['receiver'], js['a']))))); | 983 js.block(js.return_(kind(js['receiver'], js['a']))))); |
| 993 } | 984 } |
| 994 } | 985 } |
| 995 | 986 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 if ((isInstantiated && !enclosingClass.isNative()) | 1091 if ((isInstantiated && !enclosingClass.isNative()) |
| 1101 || needsGetter | 1092 || needsGetter |
| 1102 || needsSetter) { | 1093 || needsSetter) { |
| 1103 String accessorName = isShadowed | 1094 String accessorName = isShadowed |
| 1104 ? namer.shadowedFieldName(member) | 1095 ? namer.shadowedFieldName(member) |
| 1105 : namer.getName(member); | 1096 : namer.getName(member); |
| 1106 String fieldName = member.hasFixedBackendName() | 1097 String fieldName = member.hasFixedBackendName() |
| 1107 ? member.fixedBackendName() | 1098 ? member.fixedBackendName() |
| 1108 : (isMixinNativeField ? member.name.slowToString() : accessorName); | 1099 : (isMixinNativeField ? member.name.slowToString() : accessorName); |
| 1109 bool needsCheckedSetter = false; | 1100 bool needsCheckedSetter = false; |
| 1110 if (needsSetter && compiler.enableTypeAssertions | 1101 if (needsSetter) { |
| 1111 && canGenerateCheckedSetter(member)) { | 1102 if (compiler.enableTypeAssertions |
| 1112 needsCheckedSetter = true; | 1103 && canGenerateCheckedSetter(member)) { |
| 1113 needsSetter = false; | 1104 needsCheckedSetter = true; |
| 1105 needsSetter = false; |
| 1106 } else if (backend.isInterceptedMethod(member)) { |
| 1107 // The [addField] will take care of generating the setter. |
| 1108 needsSetter = false; |
| 1109 } |
| 1114 } | 1110 } |
| 1115 // Getters and setters with suffixes will be generated dynamically. | 1111 // Getters and setters with suffixes will be generated dynamically. |
| 1116 addField(member, | 1112 addField(member, |
| 1117 fieldName, | 1113 fieldName, |
| 1118 accessorName, | 1114 accessorName, |
| 1119 needsGetter, | 1115 needsGetter, |
| 1120 needsSetter, | 1116 needsSetter, |
| 1121 needsCheckedSetter); | 1117 needsCheckedSetter); |
| 1122 } | 1118 } |
| 1123 } | 1119 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1141 // allowed on fields that are in [classElement] we don't need to visit | 1137 // allowed on fields that are in [classElement] we don't need to visit |
| 1142 // superclasses for non-instantiated classes. | 1138 // superclasses for non-instantiated classes. |
| 1143 classElement.implementation.forEachInstanceField( | 1139 classElement.implementation.forEachInstanceField( |
| 1144 visitField, | 1140 visitField, |
| 1145 includeBackendMembers: true, | 1141 includeBackendMembers: true, |
| 1146 includeSuperMembers: isInstantiated && !classElement.isNative()); | 1142 includeSuperMembers: isInstantiated && !classElement.isNative()); |
| 1147 } | 1143 } |
| 1148 | 1144 |
| 1149 void generateGetter(Element member, String fieldName, String accessorName, | 1145 void generateGetter(Element member, String fieldName, String accessorName, |
| 1150 ClassBuilder builder) { | 1146 ClassBuilder builder) { |
| 1147 assert(!backend.isInterceptorClass(member)); |
| 1151 String getterName = namer.getterNameFromAccessorName(accessorName); | 1148 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 1152 builder.addProperty(getterName, | 1149 builder.addProperty(getterName, |
| 1153 js.fun([], js.return_(js['this'][fieldName]))); | 1150 js.fun([], js.return_(js['this'][fieldName]))); |
| 1154 } | 1151 } |
| 1155 | 1152 |
| 1156 void generateSetter(Element member, String fieldName, String accessorName, | 1153 void generateSetter(Element member, String fieldName, String accessorName, |
| 1157 ClassBuilder builder) { | 1154 ClassBuilder builder) { |
| 1155 assert(!backend.isInterceptorClass(member)); |
| 1158 String setterName = namer.setterNameFromAccessorName(accessorName); | 1156 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1157 List<String> args = backend.isInterceptedMethod(member) |
| 1158 ? ['receiver', 'v'] |
| 1159 : ['v']; |
| 1159 builder.addProperty(setterName, | 1160 builder.addProperty(setterName, |
| 1160 js.fun(['v'], js['this'][fieldName].assign('v'))); | 1161 js.fun(args, js['this'][fieldName].assign('v'))); |
| 1161 } | 1162 } |
| 1162 | 1163 |
| 1163 bool canGenerateCheckedSetter(Element member) { | 1164 bool canGenerateCheckedSetter(Element member) { |
| 1164 DartType type = member.computeType(compiler); | 1165 DartType type = member.computeType(compiler); |
| 1165 if (type.element.isTypeVariable() | 1166 if (type.element.isTypeVariable() |
| 1166 || type.element == compiler.dynamicClass | 1167 || type.element == compiler.dynamicClass |
| 1167 || type.element == compiler.objectClass) { | 1168 || type.element == compiler.objectClass) { |
| 1168 // TODO(ngeoffray): Support type checks on type parameters. | 1169 // TODO(ngeoffray): Support type checks on type parameters. |
| 1169 return false; | 1170 return false; |
| 1170 } | 1171 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1181 if (type.element.isErroneous()) return; | 1182 if (type.element.isErroneous()) return; |
| 1182 FunctionElement helperElement | 1183 FunctionElement helperElement |
| 1183 = backend.getCheckedModeHelper(type, typeCast: false); | 1184 = backend.getCheckedModeHelper(type, typeCast: false); |
| 1184 String helperName = namer.isolateAccess(helperElement); | 1185 String helperName = namer.isolateAccess(helperElement); |
| 1185 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; | 1186 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; |
| 1186 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 1187 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 1187 arguments.add(js.string(namer.operatorIs(type.element))); | 1188 arguments.add(js.string(namer.operatorIs(type.element))); |
| 1188 } | 1189 } |
| 1189 | 1190 |
| 1190 String setterName = namer.setterNameFromAccessorName(accessorName); | 1191 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1192 List<String> args = backend.isInterceptedMethod(member) |
| 1193 ? ['receiver', 'v'] |
| 1194 : ['v']; |
| 1191 builder.addProperty(setterName, | 1195 builder.addProperty(setterName, |
| 1192 js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments)))); | 1196 js.fun(args, js['this'][fieldName].assign(js[helperName](arguments)))); |
| 1193 } | 1197 } |
| 1194 | 1198 |
| 1195 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { | 1199 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { |
| 1196 /* Do nothing. */ | 1200 /* Do nothing. */ |
| 1197 } | 1201 } |
| 1198 | 1202 |
| 1199 void emitSuper(String superName, ClassBuilder builder) { | 1203 void emitSuper(String superName, ClassBuilder builder) { |
| 1200 /* Do nothing. */ | 1204 /* Do nothing. */ |
| 1201 } | 1205 } |
| 1202 | 1206 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 assert(!needsSetter); | 1278 assert(!needsSetter); |
| 1275 generateCheckedSetter(member, name, accessorName, builder); | 1279 generateCheckedSetter(member, name, accessorName, builder); |
| 1276 } | 1280 } |
| 1277 if (!getterAndSetterCanBeImplementedByFieldSpec) { | 1281 if (!getterAndSetterCanBeImplementedByFieldSpec) { |
| 1278 if (needsGetter) { | 1282 if (needsGetter) { |
| 1279 generateGetter(member, name, accessorName, builder); | 1283 generateGetter(member, name, accessorName, builder); |
| 1280 } | 1284 } |
| 1281 if (needsSetter) { | 1285 if (needsSetter) { |
| 1282 generateSetter(member, name, accessorName, builder); | 1286 generateSetter(member, name, accessorName, builder); |
| 1283 } | 1287 } |
| 1288 } else if (backend.isInterceptedMethod(member) |
| 1289 && instanceFieldNeedsSetter(member)) { |
| 1290 generateSetter(member, name, accessorName, builder); |
| 1284 } | 1291 } |
| 1285 }); | 1292 }); |
| 1286 }); | 1293 }); |
| 1287 } | 1294 } |
| 1288 | 1295 |
| 1289 /** | 1296 /** |
| 1290 * Documentation wanted -- johnniwinther | 1297 * Documentation wanted -- johnniwinther |
| 1291 * | 1298 * |
| 1292 * Invariant: [classElement] must be a declaration element. | 1299 * Invariant: [classElement] must be a declaration element. |
| 1293 */ | 1300 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 return arity; | 1343 return arity; |
| 1337 } | 1344 } |
| 1338 | 1345 |
| 1339 int _compareSelectorNames(Selector selector1, Selector selector2) { | 1346 int _compareSelectorNames(Selector selector1, Selector selector2) { |
| 1340 String name1 = selector1.name.toString(); | 1347 String name1 = selector1.name.toString(); |
| 1341 String name2 = selector2.name.toString(); | 1348 String name2 = selector2.name.toString(); |
| 1342 if (name1 != name2) return Comparable.compare(name1, name2); | 1349 if (name1 != name2) return Comparable.compare(name1, name2); |
| 1343 return _selectorRank(selector1) - _selectorRank(selector2); | 1350 return _selectorRank(selector1) - _selectorRank(selector2); |
| 1344 } | 1351 } |
| 1345 | 1352 |
| 1346 void emitInterceptorMethods(ClassBuilder builder) { | |
| 1347 // Emit forwarders for the ObjectInterceptor class. We need to | |
| 1348 // emit all possible sends on intercepted methods. Because of | |
| 1349 // typed selectors we have to avoid generating the same forwarder | |
| 1350 // multiple times. | |
| 1351 Set<String> alreadyGenerated = new Set<String>(); | |
| 1352 for (Selector selector in | |
| 1353 backend.usedInterceptors.toList()..sort(_compareSelectorNames)) { | |
| 1354 String name = backend.namer.invocationName(selector); | |
| 1355 if (alreadyGenerated.contains(name)) continue; | |
| 1356 alreadyGenerated.add(name); | |
| 1357 | |
| 1358 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | |
| 1359 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
| 1360 parameters.add(new jsAst.Parameter('receiver')); | |
| 1361 | |
| 1362 if (selector.isSetter()) { | |
| 1363 parameters.add(new jsAst.Parameter('value')); | |
| 1364 arguments.add(js['value']); | |
| 1365 } else { | |
| 1366 for (int i = 0; i < selector.argumentCount; i++) { | |
| 1367 String argName = 'a$i'; | |
| 1368 parameters.add(new jsAst.Parameter(argName)); | |
| 1369 arguments.add(js[argName]); | |
| 1370 } | |
| 1371 } | |
| 1372 jsAst.Fun function = | |
| 1373 js.fun(parameters, js.return_(js['receiver'][name](arguments))); | |
| 1374 builder.addProperty(name, function); | |
| 1375 } | |
| 1376 } | |
| 1377 | |
| 1378 Iterable<Element> getTypedefChecksOn(DartType type) { | 1353 Iterable<Element> getTypedefChecksOn(DartType type) { |
| 1379 bool isSubtype(TypedefElement typedef) { | 1354 bool isSubtype(TypedefElement typedef) { |
| 1380 FunctionType typedefType = | 1355 FunctionType typedefType = |
| 1381 typedef.computeType(compiler).unalias(compiler); | 1356 typedef.computeType(compiler).unalias(compiler); |
| 1382 return compiler.types.isSubtype(type, typedefType); | 1357 return compiler.types.isSubtype(type, typedefType); |
| 1383 } | 1358 } |
| 1384 return checkedTypedefs.where(isSubtype).toList() | 1359 return checkedTypedefs.where(isSubtype).toList() |
| 1385 ..sort(Elements.compareByPosition); | 1360 ..sort(Elements.compareByPosition); |
| 1386 } | 1361 } |
| 1387 | 1362 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 for (Constant constant in constants) { | 1504 for (Constant constant in constants) { |
| 1530 if (constant is ConstructedConstant) { | 1505 if (constant is ConstructedConstant) { |
| 1531 Element element = constant.computeType(compiler).element; | 1506 Element element = constant.computeType(compiler).element; |
| 1532 if (backend.isInterceptorClass(element)) { | 1507 if (backend.isInterceptorClass(element)) { |
| 1533 needed.add(element); | 1508 needed.add(element); |
| 1534 } | 1509 } |
| 1535 } | 1510 } |
| 1536 } | 1511 } |
| 1537 | 1512 |
| 1538 // Add unneeded interceptors to the [unneededClasses] set. | 1513 // Add unneeded interceptors to the [unneededClasses] set. |
| 1539 for (ClassElement interceptor in backend.interceptedClasses.keys) { | 1514 for (ClassElement interceptor in backend.interceptedClasses) { |
| 1540 if (!needed.contains(interceptor)) { | 1515 if (!needed.contains(interceptor) |
| 1516 && interceptor != compiler.objectClass) { |
| 1541 unneededClasses.add(interceptor); | 1517 unneededClasses.add(interceptor); |
| 1542 } | 1518 } |
| 1543 } | 1519 } |
| 1544 | 1520 |
| 1545 return (ClassElement cls) => !unneededClasses.contains(cls); | 1521 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1546 } | 1522 } |
| 1547 | 1523 |
| 1548 void emitClasses(CodeBuffer buffer) { | 1524 void emitClasses(CodeBuffer buffer) { |
| 1549 // Compute the required type checks to know which classes need a | 1525 // Compute the required type checks to know which classes need a |
| 1550 // 'is$' method. | 1526 // 'is$' method. |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 // if they share methods with the same signature. Currently we do this only | 1689 // if they share methods with the same signature. Currently we do this only |
| 1714 // if there are no optional parameters. Closures with optional parameters | 1690 // if there are no optional parameters. Closures with optional parameters |
| 1715 // are more difficult to canonicalize because they would need to have the | 1691 // are more difficult to canonicalize because they would need to have the |
| 1716 // same default values. | 1692 // same default values. |
| 1717 | 1693 |
| 1718 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; | 1694 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; |
| 1719 int parameterCount = member.parameterCount(compiler); | 1695 int parameterCount = member.parameterCount(compiler); |
| 1720 | 1696 |
| 1721 Map<int, String> cache; | 1697 Map<int, String> cache; |
| 1722 String extraArg = null; | 1698 String extraArg = null; |
| 1723 // Methods on interceptor classes take an extra parameter, which is the | 1699 // Intercepted methods take an extra parameter, which is the |
| 1724 // actual receiver of the call. | 1700 // receiver of the call. |
| 1725 bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass()); | 1701 bool inInterceptor = backend.isInterceptedMethod(member); |
| 1726 if (inInterceptor) { | 1702 if (inInterceptor) { |
| 1727 cache = interceptorClosureCache; | 1703 cache = interceptorClosureCache; |
| 1728 extraArg = 'receiver'; | 1704 extraArg = 'receiver'; |
| 1729 } else { | 1705 } else { |
| 1730 cache = boundClosureCache; | 1706 cache = boundClosureCache; |
| 1731 } | 1707 } |
| 1732 List<String> fieldNames = compiler.enableMinification | 1708 List<String> fieldNames = compiler.enableMinification |
| 1733 ? inInterceptor ? const ['a', 'b', 'c'] | 1709 ? inInterceptor ? const ['a', 'b', 'c'] |
| 1734 : const ['a', 'b'] | 1710 : const ['a', 'b'] |
| 1735 : inInterceptor ? const ['self', 'target', 'receiver'] | 1711 : inInterceptor ? const ['self', 'target', 'receiver'] |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1838 /** | 1814 /** |
| 1839 * Documentation wanted -- johnniwinther | 1815 * Documentation wanted -- johnniwinther |
| 1840 * | 1816 * |
| 1841 * Invariant: [member] must be a declaration element. | 1817 * Invariant: [member] must be a declaration element. |
| 1842 */ | 1818 */ |
| 1843 void emitCallStubForGetter(Element member, | 1819 void emitCallStubForGetter(Element member, |
| 1844 Set<Selector> selectors, | 1820 Set<Selector> selectors, |
| 1845 DefineStubFunction defineStub) { | 1821 DefineStubFunction defineStub) { |
| 1846 assert(invariant(member, member.isDeclaration)); | 1822 assert(invariant(member, member.isDeclaration)); |
| 1847 LibraryElement memberLibrary = member.getLibrary(); | 1823 LibraryElement memberLibrary = member.getLibrary(); |
| 1848 // If the class is an interceptor class, the stub gets the | 1824 // If the method is intercepted, the stub gets the |
| 1849 // receiver explicitely and we need to pass it to the getter call. | 1825 // receiver explicitely and we need to pass it to the getter call. |
| 1850 bool isInterceptorClass = | 1826 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 1851 backend.isInterceptorClass(member.getEnclosingClass()); | |
| 1852 | 1827 |
| 1853 const String receiverArgumentName = r'$receiver'; | 1828 const String receiverArgumentName = r'$receiver'; |
| 1854 | 1829 |
| 1855 jsAst.Expression buildGetter() { | 1830 jsAst.Expression buildGetter() { |
| 1856 if (member.isGetter()) { | 1831 if (member.isGetter()) { |
| 1857 String getterName = namer.getterName(member); | 1832 String getterName = namer.getterName(member); |
| 1858 return js['this'][getterName]( | 1833 return js['this'][getterName]( |
| 1859 isInterceptorClass | 1834 isInterceptedMethod |
| 1860 ? <jsAst.Expression>[js[receiverArgumentName]] | 1835 ? <jsAst.Expression>[js[receiverArgumentName]] |
| 1861 : <jsAst.Expression>[]); | 1836 : <jsAst.Expression>[]); |
| 1862 } else { | 1837 } else { |
| 1863 String fieldName = member.hasFixedBackendName() | 1838 String fieldName = member.hasFixedBackendName() |
| 1864 ? member.fixedBackendName() | 1839 ? member.fixedBackendName() |
| 1865 : namer.instanceFieldName(member); | 1840 : namer.instanceFieldName(member); |
| 1866 return js['this'][fieldName]; | 1841 return js['this'][fieldName]; |
| 1867 } | 1842 } |
| 1868 } | 1843 } |
| 1869 | 1844 |
| 1870 // Two selectors may match but differ only in type. To avoid generating | 1845 // Two selectors may match but differ only in type. To avoid generating |
| 1871 // identical stubs for each we track untyped selectors which already have | 1846 // identical stubs for each we track untyped selectors which already have |
| 1872 // stubs. | 1847 // stubs. |
| 1873 Set<Selector> generatedSelectors = new Set<Selector>(); | 1848 Set<Selector> generatedSelectors = new Set<Selector>(); |
| 1874 | 1849 |
| 1875 for (Selector selector in selectors) { | 1850 for (Selector selector in selectors) { |
| 1876 if (selector.applies(member, compiler)) { | 1851 if (selector.applies(member, compiler)) { |
| 1877 selector = selector.asUntyped; | 1852 selector = selector.asUntyped; |
| 1878 if (generatedSelectors.contains(selector)) continue; | 1853 if (generatedSelectors.contains(selector)) continue; |
| 1879 generatedSelectors.add(selector); | 1854 generatedSelectors.add(selector); |
| 1880 | 1855 |
| 1881 String invocationName = namer.invocationName(selector); | 1856 String invocationName = namer.invocationName(selector); |
| 1882 Selector callSelector = new Selector.callClosureFrom(selector); | 1857 Selector callSelector = new Selector.callClosureFrom(selector); |
| 1883 String closureCallName = namer.invocationName(callSelector); | 1858 String closureCallName = namer.invocationName(callSelector); |
| 1884 | 1859 |
| 1885 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 1860 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 1886 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 1861 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 1887 if (isInterceptorClass) { | 1862 if (isInterceptedMethod) { |
| 1888 parameters.add(new jsAst.Parameter(receiverArgumentName)); | 1863 parameters.add(new jsAst.Parameter(receiverArgumentName)); |
| 1889 } | 1864 } |
| 1890 | 1865 |
| 1891 for (int i = 0; i < selector.argumentCount; i++) { | 1866 for (int i = 0; i < selector.argumentCount; i++) { |
| 1892 String name = 'arg$i'; | 1867 String name = 'arg$i'; |
| 1893 parameters.add(new jsAst.Parameter(name)); | 1868 parameters.add(new jsAst.Parameter(name)); |
| 1894 arguments.add(js[name]); | 1869 arguments.add(js[name]); |
| 1895 } | 1870 } |
| 1896 | 1871 |
| 1897 jsAst.Fun function = js.fun( | 1872 jsAst.Fun function = js.fun( |
| 1898 parameters, | 1873 parameters, |
| 1899 js.return_(buildGetter()[closureCallName](arguments))); | 1874 js.return_(buildGetter()[closureCallName](arguments))); |
| 1900 | 1875 |
| 1901 defineStub(invocationName, function); | 1876 defineStub(invocationName, function); |
| 1902 } | 1877 } |
| 1903 } | 1878 } |
| 1904 } | 1879 } |
| 1905 | 1880 |
| 1906 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1881 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1907 ConstantHandler handler = compiler.constantHandler; | 1882 ConstantHandler handler = compiler.constantHandler; |
| 1908 Iterable<VariableElement> staticNonFinalFields = | 1883 Iterable<VariableElement> staticNonFinalFields = |
| 1909 handler.getStaticNonFinalFieldsForEmission(); | 1884 handler.getStaticNonFinalFieldsForEmission(); |
| 1910 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 1885 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 1886 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
| 1887 if (element == backend.interceptedNames) continue; |
| 1911 compiler.withCurrentElement(element, () { | 1888 compiler.withCurrentElement(element, () { |
| 1912 Constant initialValue = handler.getInitialValueFor(element); | 1889 Constant initialValue = handler.getInitialValueFor(element); |
| 1913 jsAst.Expression init = | 1890 jsAst.Expression init = |
| 1914 js[isolateProperties][namer.getName(element)].assign( | 1891 js[isolateProperties][namer.getName(element)].assign( |
| 1915 constantEmitter.referenceInInitializationContext(initialValue)); | 1892 constantEmitter.referenceInInitializationContext(initialValue)); |
| 1916 buffer.add(jsAst.prettyPrint(init, compiler)); | 1893 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1917 buffer.add('$N'); | 1894 buffer.add('$N'); |
| 1918 }); | 1895 }); |
| 1919 } | 1896 } |
| 1920 } | 1897 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 | 2016 |
| 2040 List<jsAst.Expression> argNames = | 2017 List<jsAst.Expression> argNames = |
| 2041 selector.getOrderedNamedArguments().map((SourceString name) => | 2018 selector.getOrderedNamedArguments().map((SourceString name) => |
| 2042 js.string(name.slowToString())).toList(); | 2019 js.string(name.slowToString())).toList(); |
| 2043 | 2020 |
| 2044 String internalName = namer.invocationMirrorInternalName(selector); | 2021 String internalName = namer.invocationMirrorInternalName(selector); |
| 2045 | 2022 |
| 2046 String createInvocationMirror = namer.getName( | 2023 String createInvocationMirror = namer.getName( |
| 2047 compiler.createInvocationMirrorElement); | 2024 compiler.createInvocationMirrorElement); |
| 2048 | 2025 |
| 2026 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD)); |
| 2049 jsAst.Expression expression = js['this.$noSuchMethodName']( | 2027 jsAst.Expression expression = js['this.$noSuchMethodName']( |
| 2050 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ | 2028 [js['this'], |
| 2051 js.string(methodName), | 2029 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ |
| 2052 js.string(internalName), | 2030 js.string(methodName), |
| 2053 type, | 2031 js.string(internalName), |
| 2054 new jsAst.ArrayInitializer.from( | 2032 type, |
| 2055 parameters.map((param) => js[param.name]).toList()), | 2033 new jsAst.ArrayInitializer.from( |
| 2056 new jsAst.ArrayInitializer.from(argNames)])); | 2034 parameters.map((param) => js[param.name]).toList()), |
| 2035 new jsAst.ArrayInitializer.from(argNames)])]); |
| 2036 parameters = backend.isInterceptedName(selector.name) |
| 2037 ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters)) |
| 2038 : parameters; |
| 2057 return js.fun(parameters, js.return_(expression)); | 2039 return js.fun(parameters, js.return_(expression)); |
| 2058 } | 2040 } |
| 2059 | 2041 |
| 2060 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 2042 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 2061 // Cache the object class and type. | 2043 // Cache the object class and type. |
| 2062 ClassElement objectClass = compiler.objectClass; | 2044 ClassElement objectClass = compiler.objectClass; |
| 2063 DartType objectType = objectClass.computeType(compiler); | 2045 DartType objectType = objectClass.computeType(compiler); |
| 2064 | 2046 |
| 2065 for (Selector selector in selectors) { | 2047 for (Selector selector in selectors) { |
| 2066 // Introduce a helper function that determines if the given | 2048 // Introduce a helper function that determines if the given |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2187 dartMainRunner(function() { ${mainCall}; }); | 2169 dartMainRunner(function() { ${mainCall}; }); |
| 2188 } else { | 2170 } else { |
| 2189 ${mainCall}; | 2171 ${mainCall}; |
| 2190 } | 2172 } |
| 2191 } | 2173 } |
| 2192 """); | 2174 """); |
| 2193 addComment('END invoke [main].', buffer); | 2175 addComment('END invoke [main].', buffer); |
| 2194 } | 2176 } |
| 2195 | 2177 |
| 2196 void emitGetInterceptorMethod(CodeBuffer buffer, | 2178 void emitGetInterceptorMethod(CodeBuffer buffer, |
| 2197 String objectName, | |
| 2198 String key, | 2179 String key, |
| 2199 Collection<ClassElement> classes) { | 2180 Collection<ClassElement> classes) { |
| 2200 jsAst.Statement buildReturnInterceptor(ClassElement cls) { | 2181 jsAst.Statement buildReturnInterceptor(ClassElement cls) { |
| 2201 return js.return_(js[namer.isolateAccess(cls)]['prototype']); | 2182 return js.return_(js[namer.isolateAccess(cls)]['prototype']); |
| 2202 } | 2183 } |
| 2203 | 2184 |
| 2204 jsAst.VariableUse receiver = js['receiver']; | 2185 jsAst.VariableUse receiver = js['receiver']; |
| 2205 /** | 2186 /** |
| 2206 * Build a JavaScrit AST node for doing a type check on | 2187 * Build a JavaScrit AST node for doing a type check on |
| 2207 * [cls]. [cls] must be an interceptor class. | 2188 * [cls]. [cls] must be an interceptor class. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2239 bool hasString = false; | 2220 bool hasString = false; |
| 2240 for (ClassElement cls in classes) { | 2221 for (ClassElement cls in classes) { |
| 2241 if (cls == backend.jsArrayClass) hasArray = true; | 2222 if (cls == backend.jsArrayClass) hasArray = true; |
| 2242 else if (cls == backend.jsBoolClass) hasBool = true; | 2223 else if (cls == backend.jsBoolClass) hasBool = true; |
| 2243 else if (cls == backend.jsDoubleClass) hasDouble = true; | 2224 else if (cls == backend.jsDoubleClass) hasDouble = true; |
| 2244 else if (cls == backend.jsFunctionClass) hasFunction = true; | 2225 else if (cls == backend.jsFunctionClass) hasFunction = true; |
| 2245 else if (cls == backend.jsIntClass) hasInt = true; | 2226 else if (cls == backend.jsIntClass) hasInt = true; |
| 2246 else if (cls == backend.jsNullClass) hasNull = true; | 2227 else if (cls == backend.jsNullClass) hasNull = true; |
| 2247 else if (cls == backend.jsNumberClass) hasNumber = true; | 2228 else if (cls == backend.jsNumberClass) hasNumber = true; |
| 2248 else if (cls == backend.jsStringClass) hasString = true; | 2229 else if (cls == backend.jsStringClass) hasString = true; |
| 2249 else throw 'Internal error: $cls'; | 2230 else { |
| 2231 assert(cls == compiler.objectClass); |
| 2232 } |
| 2250 } | 2233 } |
| 2251 if (hasDouble) { | 2234 if (hasDouble) { |
| 2252 assert(!hasNumber); | |
| 2253 hasNumber = true; | 2235 hasNumber = true; |
| 2254 } | 2236 } |
| 2255 if (hasInt) hasNumber = true; | 2237 if (hasInt) hasNumber = true; |
| 2256 | 2238 |
| 2257 jsAst.Block block = new jsAst.Block.empty(); | 2239 jsAst.Block block = new jsAst.Block.empty(); |
| 2258 | 2240 |
| 2259 if (hasNumber) { | 2241 if (hasNumber) { |
| 2260 jsAst.Statement whenNumber; | 2242 jsAst.Statement whenNumber; |
| 2261 | 2243 |
| 2262 /// Note: there are two number classes in play: Dart's [num], | 2244 /// Note: there are two number classes in play: Dart's [num], |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2295 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); | 2277 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); |
| 2296 } | 2278 } |
| 2297 if (hasBool) { | 2279 if (hasBool) { |
| 2298 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); | 2280 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); |
| 2299 } | 2281 } |
| 2300 // TODO(ahe): It might be faster to check for Array before | 2282 // TODO(ahe): It might be faster to check for Array before |
| 2301 // function and bool. | 2283 // function and bool. |
| 2302 if (hasArray) { | 2284 if (hasArray) { |
| 2303 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); | 2285 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); |
| 2304 } | 2286 } |
| 2305 block.statements.add(js.return_(js[objectName]['prototype'])); | 2287 block.statements.add(js.return_(receiver)); |
| 2306 | 2288 |
| 2307 buffer.add(jsAst.prettyPrint( | 2289 buffer.add(jsAst.prettyPrint( |
| 2308 js[isolateProperties][key].assign(js.fun(['receiver'], block)), | 2290 js[isolateProperties][key].assign(js.fun(['receiver'], block)), |
| 2309 compiler)); | 2291 compiler)); |
| 2310 buffer.add(N); | 2292 buffer.add(N); |
| 2311 } | 2293 } |
| 2312 | 2294 |
| 2313 /** | 2295 /** |
| 2314 * Emit all versions of the [:getInterceptor:] method. | 2296 * Emit all versions of the [:getInterceptor:] method. |
| 2315 */ | 2297 */ |
| 2316 void emitGetInterceptorMethods(CodeBuffer buffer) { | 2298 void emitGetInterceptorMethods(CodeBuffer buffer) { |
| 2317 // If no class needs to be intercepted, just return. | |
| 2318 if (backend.objectInterceptorClass == null) return; | |
| 2319 String objectName = namer.isolateAccess(backend.objectInterceptorClass); | |
| 2320 var specializedGetInterceptors = backend.specializedGetInterceptors; | 2299 var specializedGetInterceptors = backend.specializedGetInterceptors; |
| 2321 for (String name in specializedGetInterceptors.keys.toList()..sort()) { | 2300 for (String name in specializedGetInterceptors.keys.toList()..sort()) { |
| 2322 Collection<ClassElement> classes = specializedGetInterceptors[name]; | 2301 Collection<ClassElement> classes = specializedGetInterceptors[name]; |
| 2323 emitGetInterceptorMethod(buffer, objectName, name, classes); | 2302 emitGetInterceptorMethod(buffer, name, classes); |
| 2324 } | 2303 } |
| 2325 } | 2304 } |
| 2326 | 2305 |
| 2327 void computeNeededClasses() { | 2306 void computeNeededClasses() { |
| 2328 instantiatedClasses = | 2307 instantiatedClasses = |
| 2329 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) | 2308 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) |
| 2330 .toSet(); | 2309 .toSet(); |
| 2331 neededClasses = new Set<ClassElement>.from(instantiatedClasses); | 2310 neededClasses = new Set<ClassElement>.from(instantiatedClasses); |
| 2332 for (ClassElement element in instantiatedClasses) { | 2311 for (ClassElement element in instantiatedClasses) { |
| 2333 for (ClassElement superclass = element.superclass; | 2312 for (ClassElement superclass = element.superclass; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2494 } | 2473 } |
| 2495 return null; | 2474 return null; |
| 2496 } | 2475 } |
| 2497 | 2476 |
| 2498 void emitOneShotInterceptors(CodeBuffer buffer) { | 2477 void emitOneShotInterceptors(CodeBuffer buffer) { |
| 2499 List<String> names = backend.oneShotInterceptors.keys.toList(); | 2478 List<String> names = backend.oneShotInterceptors.keys.toList(); |
| 2500 names.sort(); | 2479 names.sort(); |
| 2501 for (String name in names) { | 2480 for (String name in names) { |
| 2502 Selector selector = backend.oneShotInterceptors[name]; | 2481 Selector selector = backend.oneShotInterceptors[name]; |
| 2503 Set<ClassElement> classes = | 2482 Set<ClassElement> classes = |
| 2504 backend.getInterceptedClassesOn(selector); | 2483 backend.getInterceptedClassesOn(selector.name); |
| 2505 String getInterceptorName = | 2484 String getInterceptorName = |
| 2506 namer.getInterceptorName(backend.getInterceptorMethod, classes); | 2485 namer.getInterceptorName(backend.getInterceptorMethod, classes); |
| 2507 | 2486 |
| 2508 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 2487 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 2509 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 2488 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 2510 parameters.add(new jsAst.Parameter('receiver')); | 2489 parameters.add(new jsAst.Parameter('receiver')); |
| 2511 arguments.add(js['receiver']); | 2490 arguments.add(js['receiver']); |
| 2512 | 2491 |
| 2513 if (selector.isSetter()) { | 2492 if (selector.isSetter()) { |
| 2514 parameters.add(new jsAst.Parameter('value')); | 2493 parameters.add(new jsAst.Parameter('value')); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2536 jsAst.Fun function = js.fun(parameters, body); | 2515 jsAst.Fun function = js.fun(parameters, body); |
| 2537 | 2516 |
| 2538 jsAst.PropertyAccess property = | 2517 jsAst.PropertyAccess property = |
| 2539 js[isolateProperties][name]; | 2518 js[isolateProperties][name]; |
| 2540 | 2519 |
| 2541 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); | 2520 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); |
| 2542 buffer.add(N); | 2521 buffer.add(N); |
| 2543 } | 2522 } |
| 2544 } | 2523 } |
| 2545 | 2524 |
| 2525 /** |
| 2526 * If [:invokeOn:] has been compiled, emit all the possible selector names |
| 2527 * that are intercepted into the [:interceptedNames:] top-level |
| 2528 * variable. The implementation of [:invokeOn:] will use it to |
| 2529 * determine whether it should call the method with an extra |
| 2530 * parameter. |
| 2531 */ |
| 2532 void emitInterceptedNames(CodeBuffer buffer) { |
| 2533 if (!compiler.enabledInvokeOn) return; |
| 2534 String name = backend.namer.getName(backend.interceptedNames); |
| 2535 jsAst.PropertyAccess property = js[isolateProperties][name]; |
| 2536 |
| 2537 int index = 0; |
| 2538 List<jsAst.ArrayElement> elements = backend.usedInterceptors.map( |
| 2539 (Selector selector) { |
| 2540 jsAst.Literal str = js.string(namer.invocationName(selector)); |
| 2541 return new jsAst.ArrayElement(index++, str); |
| 2542 }).toList(); |
| 2543 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer( |
| 2544 backend.usedInterceptors.length, |
| 2545 elements); |
| 2546 |
| 2547 buffer.add(jsAst.prettyPrint(property.assign(array), compiler)); |
| 2548 buffer.add(N); |
| 2549 } |
| 2550 |
| 2546 void emitInitFunction(CodeBuffer buffer) { | 2551 void emitInitFunction(CodeBuffer buffer) { |
| 2547 jsAst.Fun fun = js.fun([], [ | 2552 jsAst.Fun fun = js.fun([], [ |
| 2548 js['$isolateProperties = {}'], | 2553 js['$isolateProperties = {}'], |
| 2549 ] | 2554 ] |
| 2550 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 2555 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
| 2551 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 2556 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
| 2552 ..addAll(buildFinishIsolateConstructor()) | 2557 ..addAll(buildFinishIsolateConstructor()) |
| 2553 ); | 2558 ); |
| 2554 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 2559 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
| 2555 new jsAst.VariableDeclaration('init'), fun); | 2560 new jsAst.VariableDeclaration('init'), fun); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2579 emitStaticFunctionGetters(mainBuffer); | 2584 emitStaticFunctionGetters(mainBuffer); |
| 2580 // We need to finish the classes before we construct compile time | 2585 // We need to finish the classes before we construct compile time |
| 2581 // constants. | 2586 // constants. |
| 2582 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2587 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 2583 emitRuntimeClassesAndTests(mainBuffer); | 2588 emitRuntimeClassesAndTests(mainBuffer); |
| 2584 emitCompileTimeConstants(mainBuffer); | 2589 emitCompileTimeConstants(mainBuffer); |
| 2585 // Static field initializations require the classes and compile-time | 2590 // Static field initializations require the classes and compile-time |
| 2586 // constants to be set up. | 2591 // constants to be set up. |
| 2587 emitStaticNonFinalFieldInitializations(mainBuffer); | 2592 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 2588 emitOneShotInterceptors(mainBuffer); | 2593 emitOneShotInterceptors(mainBuffer); |
| 2594 emitInterceptedNames(mainBuffer); |
| 2589 emitGetInterceptorMethods(mainBuffer); | 2595 emitGetInterceptorMethods(mainBuffer); |
| 2590 emitLazilyInitializedStaticFields(mainBuffer); | 2596 emitLazilyInitializedStaticFields(mainBuffer); |
| 2591 | 2597 |
| 2592 isolateProperties = isolatePropertiesName; | 2598 isolateProperties = isolatePropertiesName; |
| 2593 // The following code should not use the short-hand for the | 2599 // The following code should not use the short-hand for the |
| 2594 // initialStatics. | 2600 // initialStatics. |
| 2595 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 2601 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| 2596 if (!boundClosureBuffer.isEmpty) { | 2602 if (!boundClosureBuffer.isEmpty) { |
| 2597 mainBuffer.add(boundClosureBuffer); | 2603 mainBuffer.add(boundClosureBuffer); |
| 2598 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2604 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2691 """; | 2697 """; |
| 2692 const String HOOKS_API_USAGE = """ | 2698 const String HOOKS_API_USAGE = """ |
| 2693 // The code supports the following hooks: | 2699 // The code supports the following hooks: |
| 2694 // dartPrint(message) - if this function is defined it is called | 2700 // dartPrint(message) - if this function is defined it is called |
| 2695 // instead of the Dart [print] method. | 2701 // instead of the Dart [print] method. |
| 2696 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2702 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2697 // method will not be invoked directly. | 2703 // method will not be invoked directly. |
| 2698 // Instead, a closure that will invoke [main] is | 2704 // Instead, a closure that will invoke [main] is |
| 2699 // passed to [dartMainRunner]. | 2705 // passed to [dartMainRunner]. |
| 2700 """; | 2706 """; |
| OLD | NEW |