Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 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>.fixedLength( | 652 new List<jsAst.Parameter>.fixedLength( |
| 654 selector.argumentCount + extraArgumentCount); | 653 selector.argumentCount + extraArgumentCount); |
| 655 // The arguments that will be passed to the real method. | 654 // The arguments that will be passed to the real method. |
| 656 List<jsAst.Expression> argumentsBuffer = | 655 List<jsAst.Expression> argumentsBuffer = |
| 657 new List<jsAst.Expression>.fixedLength( | 656 new List<jsAst.Expression>.fixedLength( |
| 658 parameters.parameterCount + extraArgumentCount); | 657 parameters.parameterCount + extraArgumentCount); |
| 659 | 658 |
| 660 int count = 0; | 659 int count = 0; |
| 661 if (isInterceptorClass) { | 660 if (isInterceptedMethod) { |
| 662 count++; | 661 count++; |
| 663 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); | 662 parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); |
| 664 argumentsBuffer[0] = js[receiverArgumentName]; | 663 argumentsBuffer[0] = js[receiverArgumentName]; |
| 665 } | 664 } |
| 666 | 665 |
| 667 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 666 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
| 668 TreeElements elements = | 667 TreeElements elements = |
| 669 compiler.enqueuer.resolution.getCachedElements(member); | 668 compiler.enqueuer.resolution.getCachedElements(member); |
| 670 | 669 |
| 671 parameters.orderedForEachParameter((Element element) { | 670 parameters.orderedForEachParameter((Element element) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 } | 890 } |
| 892 | 891 |
| 893 /** | 892 /** |
| 894 * Documentation wanted -- johnniwinther | 893 * Documentation wanted -- johnniwinther |
| 895 * | 894 * |
| 896 * Invariant: [classElement] must be a declaration element. | 895 * Invariant: [classElement] must be a declaration element. |
| 897 */ | 896 */ |
| 898 void emitInstanceMembers(ClassElement classElement, | 897 void emitInstanceMembers(ClassElement classElement, |
| 899 ClassBuilder builder) { | 898 ClassBuilder builder) { |
| 900 assert(invariant(classElement, classElement.isDeclaration)); | 899 assert(invariant(classElement, classElement.isDeclaration)); |
| 901 if (classElement == backend.objectInterceptorClass) { | |
| 902 emitInterceptorMethods(builder); | |
| 903 // The ObjectInterceptor does not have any instance methods. | |
| 904 return; | |
| 905 } | |
| 906 | 900 |
| 907 void visitMember(ClassElement enclosing, Element member) { | 901 void visitMember(ClassElement enclosing, Element member) { |
| 908 assert(invariant(classElement, member.isDeclaration)); | 902 assert(invariant(classElement, member.isDeclaration)); |
| 909 if (member.isInstanceMember()) { | 903 if (member.isInstanceMember()) { |
| 910 addInstanceMember(member, builder); | 904 addInstanceMember(member, builder); |
| 911 } | 905 } |
| 912 } | 906 } |
| 913 | 907 |
| 914 // TODO(kasperl): We should make sure to only emit one version of | 908 // TODO(kasperl): We should make sure to only emit one version of |
| 915 // overridden methods. Right now, we rely on the ordering so the | 909 // overridden methods. Right now, we rely on the ordering so the |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 970 && compiler.enabledNoSuchMethod) { | 964 && compiler.enabledNoSuchMethod) { |
| 971 // Emit the noSuchMethod handlers on the Object prototype now, | 965 // Emit the noSuchMethod handlers on the Object prototype now, |
| 972 // so that the code in the dynamicFunction helper can find | 966 // so that the code in the dynamicFunction helper can find |
| 973 // them. Note that this helper is invoked before analyzing the | 967 // them. Note that this helper is invoked before analyzing the |
| 974 // full JS script. | 968 // full JS script. |
| 975 if (!nativeEmitter.handleNoSuchMethod) { | 969 if (!nativeEmitter.handleNoSuchMethod) { |
| 976 emitNoSuchMethodHandlers(builder.addProperty); | 970 emitNoSuchMethodHandlers(builder.addProperty); |
| 977 } | 971 } |
| 978 } | 972 } |
| 979 | 973 |
| 980 if (backend.isInterceptorClass(classElement)) { | 974 if (backend.isInterceptorClass(classElement) |
| 981 // The operator== method in [:Object:] does not take the same | 975 && classElement != compiler.objectClass) { |
| 982 // number of arguments as an intercepted method, therefore we | 976 // We optimize the operator== on interceptor classes to |
| 983 // explicitely add one to all interceptor classes. Note that we | 977 // just do a JavaScript double or triple equals. |
| 984 // would not have do do that if all intercepted methods had | |
| 985 // a calling convention where the receiver is the first | |
| 986 // parameter. | |
| 987 String name = backend.namer.publicInstanceMethodNameByArity( | 978 String name = backend.namer.publicInstanceMethodNameByArity( |
| 988 const SourceString('=='), 1); | 979 const SourceString('=='), 1); |
| 989 Function kind = (classElement == backend.jsNullClass) | 980 Function kind = (classElement == backend.jsNullClass) |
| 990 ? js.equals | 981 ? js.equals |
| 991 : js.strictEquals; | 982 : js.strictEquals; |
| 992 builder.addProperty(name, js.fun(['receiver', 'a'], | 983 builder.addProperty(name, js.fun(['receiver', 'a'], |
| 993 js.block(js.return_(kind(js['receiver'], js['a']))))); | 984 js.block(js.return_(kind(js['receiver'], js['a']))))); |
| 994 } | 985 } |
| 995 } | 986 } |
| 996 | 987 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1101 if ((isInstantiated && !enclosingClass.isNative()) | 1092 if ((isInstantiated && !enclosingClass.isNative()) |
| 1102 || needsGetter | 1093 || needsGetter |
| 1103 || needsSetter) { | 1094 || needsSetter) { |
| 1104 String accessorName = isShadowed | 1095 String accessorName = isShadowed |
| 1105 ? namer.shadowedFieldName(member) | 1096 ? namer.shadowedFieldName(member) |
| 1106 : namer.getName(member); | 1097 : namer.getName(member); |
| 1107 String fieldName = member.hasFixedBackendName() | 1098 String fieldName = member.hasFixedBackendName() |
| 1108 ? member.fixedBackendName() | 1099 ? member.fixedBackendName() |
| 1109 : (isMixinNativeField ? member.name.slowToString() : accessorName); | 1100 : (isMixinNativeField ? member.name.slowToString() : accessorName); |
| 1110 bool needsCheckedSetter = false; | 1101 bool needsCheckedSetter = false; |
| 1111 if (needsSetter && compiler.enableTypeAssertions | 1102 if (needsSetter) { |
| 1112 && canGenerateCheckedSetter(member)) { | 1103 if (compiler.enableTypeAssertions |
| 1113 needsCheckedSetter = true; | 1104 && canGenerateCheckedSetter(member)) { |
| 1114 needsSetter = false; | 1105 needsCheckedSetter = true; |
| 1106 needsSetter = false; | |
| 1107 } else if (backend.isInterceptedMethod(member)) { | |
| 1108 // The [addField] will take care of generating the setter. | |
| 1109 needsSetter = false; | |
| 1110 } | |
| 1115 } | 1111 } |
| 1116 // Getters and setters with suffixes will be generated dynamically. | 1112 // Getters and setters with suffixes will be generated dynamically. |
|
sra1
2013/02/27 05:13:28
How does the dynamic generator know whether to add
ngeoffray
2013/02/28 10:39:42
Yes, nice catch. The dynamic generator does not de
| |
| 1117 addField(member, | 1113 addField(member, |
| 1118 fieldName, | 1114 fieldName, |
| 1119 accessorName, | 1115 accessorName, |
| 1120 needsGetter, | 1116 needsGetter, |
| 1121 needsSetter, | 1117 needsSetter, |
| 1122 needsCheckedSetter); | 1118 needsCheckedSetter); |
| 1123 } | 1119 } |
| 1124 } | 1120 } |
| 1125 | 1121 |
| 1126 // TODO(kasperl): We should make sure to only emit one version of | 1122 // TODO(kasperl): We should make sure to only emit one version of |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1150 void generateGetter(Element member, String fieldName, String accessorName, | 1146 void generateGetter(Element member, String fieldName, String accessorName, |
| 1151 ClassBuilder builder) { | 1147 ClassBuilder builder) { |
| 1152 String getterName = namer.getterNameFromAccessorName(accessorName); | 1148 String getterName = namer.getterNameFromAccessorName(accessorName); |
| 1153 builder.addProperty(getterName, | 1149 builder.addProperty(getterName, |
| 1154 js.fun([], js.return_(js['this'][fieldName]))); | 1150 js.fun([], js.return_(js['this'][fieldName]))); |
| 1155 } | 1151 } |
| 1156 | 1152 |
| 1157 void generateSetter(Element member, String fieldName, String accessorName, | 1153 void generateSetter(Element member, String fieldName, String accessorName, |
| 1158 ClassBuilder builder) { | 1154 ClassBuilder builder) { |
| 1159 String setterName = namer.setterNameFromAccessorName(accessorName); | 1155 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1156 List<String> args = backend.isInterceptedMethod(member) | |
| 1157 ? ['receiver', 'v'] | |
| 1158 : ['v']; | |
| 1160 builder.addProperty(setterName, | 1159 builder.addProperty(setterName, |
| 1161 js.fun(['v'], js['this'][fieldName].assign('v'))); | 1160 js.fun(args, js['this'][fieldName].assign('v'))); |
|
sra1
2013/02/27 05:13:28
Don't you need to choose between
this.field =
ngeoffray
2013/02/28 10:39:42
Good catch again. We never emit implicit getters a
| |
| 1162 } | 1161 } |
| 1163 | 1162 |
| 1164 bool canGenerateCheckedSetter(Element member) { | 1163 bool canGenerateCheckedSetter(Element member) { |
| 1165 DartType type = member.computeType(compiler); | 1164 DartType type = member.computeType(compiler); |
| 1166 if (type.element.isTypeVariable() | 1165 if (type.element.isTypeVariable() |
| 1167 || type.element == compiler.dynamicClass | 1166 || type.element == compiler.dynamicClass |
| 1168 || type.element == compiler.objectClass) { | 1167 || type.element == compiler.objectClass) { |
| 1169 // TODO(ngeoffray): Support type checks on type parameters. | 1168 // TODO(ngeoffray): Support type checks on type parameters. |
| 1170 return false; | 1169 return false; |
| 1171 } | 1170 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 1182 if (type.element.isErroneous()) return; | 1181 if (type.element.isErroneous()) return; |
| 1183 FunctionElement helperElement | 1182 FunctionElement helperElement |
| 1184 = backend.getCheckedModeHelper(type, typeCast: false); | 1183 = backend.getCheckedModeHelper(type, typeCast: false); |
| 1185 String helperName = namer.isolateAccess(helperElement); | 1184 String helperName = namer.isolateAccess(helperElement); |
| 1186 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; | 1185 List<jsAst.Expression> arguments = <jsAst.Expression>[js['v']]; |
| 1187 if (helperElement.computeSignature(compiler).parameterCount != 1) { | 1186 if (helperElement.computeSignature(compiler).parameterCount != 1) { |
| 1188 arguments.add(js.string(namer.operatorIs(type.element))); | 1187 arguments.add(js.string(namer.operatorIs(type.element))); |
| 1189 } | 1188 } |
| 1190 | 1189 |
| 1191 String setterName = namer.setterNameFromAccessorName(accessorName); | 1190 String setterName = namer.setterNameFromAccessorName(accessorName); |
| 1191 List<String> args = backend.isInterceptedMethod(member) | |
| 1192 ? ['receiver', 'v'] | |
| 1193 : ['v']; | |
| 1192 builder.addProperty(setterName, | 1194 builder.addProperty(setterName, |
| 1193 js.fun(['v'], js['this'][fieldName].assign(js[helperName](arguments)))); | 1195 js.fun(args, js['this'][fieldName].assign(js[helperName](arguments)))); |
| 1194 } | 1196 } |
| 1195 | 1197 |
| 1196 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { | 1198 void emitClassConstructor(ClassElement classElement, ClassBuilder builder) { |
| 1197 /* Do nothing. */ | 1199 /* Do nothing. */ |
| 1198 } | 1200 } |
| 1199 | 1201 |
| 1200 void emitSuper(String superName, ClassBuilder builder) { | 1202 void emitSuper(String superName, ClassBuilder builder) { |
| 1201 /* Do nothing. */ | 1203 /* Do nothing. */ |
| 1202 } | 1204 } |
| 1203 | 1205 |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1275 assert(!needsSetter); | 1277 assert(!needsSetter); |
| 1276 generateCheckedSetter(member, name, accessorName, builder); | 1278 generateCheckedSetter(member, name, accessorName, builder); |
| 1277 } | 1279 } |
| 1278 if (!getterAndSetterCanBeImplementedByFieldSpec) { | 1280 if (!getterAndSetterCanBeImplementedByFieldSpec) { |
| 1279 if (needsGetter) { | 1281 if (needsGetter) { |
| 1280 generateGetter(member, name, accessorName, builder); | 1282 generateGetter(member, name, accessorName, builder); |
| 1281 } | 1283 } |
| 1282 if (needsSetter) { | 1284 if (needsSetter) { |
| 1283 generateSetter(member, name, accessorName, builder); | 1285 generateSetter(member, name, accessorName, builder); |
| 1284 } | 1286 } |
| 1287 } else if (backend.isInterceptedMethod(member) | |
| 1288 && instanceFieldNeedsSetter(member)) { | |
| 1289 generateSetter(member, name, accessorName, builder); | |
| 1285 } | 1290 } |
| 1286 }); | 1291 }); |
| 1287 }); | 1292 }); |
| 1288 } | 1293 } |
| 1289 | 1294 |
| 1290 /** | 1295 /** |
| 1291 * Documentation wanted -- johnniwinther | 1296 * Documentation wanted -- johnniwinther |
| 1292 * | 1297 * |
| 1293 * Invariant: [classElement] must be a declaration element. | 1298 * Invariant: [classElement] must be a declaration element. |
| 1294 */ | 1299 */ |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1337 return arity; | 1342 return arity; |
| 1338 } | 1343 } |
| 1339 | 1344 |
| 1340 int _compareSelectorNames(Selector selector1, Selector selector2) { | 1345 int _compareSelectorNames(Selector selector1, Selector selector2) { |
| 1341 String name1 = selector1.name.toString(); | 1346 String name1 = selector1.name.toString(); |
| 1342 String name2 = selector2.name.toString(); | 1347 String name2 = selector2.name.toString(); |
| 1343 if (name1 != name2) return Comparable.compare(name1, name2); | 1348 if (name1 != name2) return Comparable.compare(name1, name2); |
| 1344 return _selectorRank(selector1) - _selectorRank(selector2); | 1349 return _selectorRank(selector1) - _selectorRank(selector2); |
| 1345 } | 1350 } |
| 1346 | 1351 |
| 1347 void emitInterceptorMethods(ClassBuilder builder) { | |
| 1348 // Emit forwarders for the ObjectInterceptor class. We need to | |
| 1349 // emit all possible sends on intercepted methods. Because of | |
| 1350 // typed selectors we have to avoid generating the same forwarder | |
| 1351 // multiple times. | |
| 1352 Set<String> alreadyGenerated = new Set<String>(); | |
| 1353 for (Selector selector in | |
| 1354 backend.usedInterceptors.toList()..sort(_compareSelectorNames)) { | |
| 1355 String name = backend.namer.invocationName(selector); | |
| 1356 if (alreadyGenerated.contains(name)) continue; | |
| 1357 alreadyGenerated.add(name); | |
| 1358 | |
| 1359 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | |
| 1360 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
| 1361 parameters.add(new jsAst.Parameter('receiver')); | |
| 1362 | |
| 1363 if (selector.isSetter()) { | |
| 1364 parameters.add(new jsAst.Parameter('value')); | |
| 1365 arguments.add(js['value']); | |
| 1366 } else { | |
| 1367 for (int i = 0; i < selector.argumentCount; i++) { | |
| 1368 String argName = 'a$i'; | |
| 1369 parameters.add(new jsAst.Parameter(argName)); | |
| 1370 arguments.add(js[argName]); | |
| 1371 } | |
| 1372 } | |
| 1373 jsAst.Fun function = | |
| 1374 js.fun(parameters, js.return_(js['receiver'][name](arguments))); | |
| 1375 builder.addProperty(name, function); | |
| 1376 } | |
| 1377 } | |
| 1378 | |
| 1379 Iterable<Element> getTypedefChecksOn(DartType type) { | 1352 Iterable<Element> getTypedefChecksOn(DartType type) { |
| 1380 bool isSubtype(TypedefElement typedef) { | 1353 bool isSubtype(TypedefElement typedef) { |
| 1381 FunctionType typedefType = | 1354 FunctionType typedefType = |
| 1382 typedef.computeType(compiler).unalias(compiler); | 1355 typedef.computeType(compiler).unalias(compiler); |
| 1383 return compiler.types.isSubtype(type, typedefType); | 1356 return compiler.types.isSubtype(type, typedefType); |
| 1384 } | 1357 } |
| 1385 return checkedTypedefs.where(isSubtype).toList() | 1358 return checkedTypedefs.where(isSubtype).toList() |
| 1386 ..sort(Elements.compareByPosition); | 1359 ..sort(Elements.compareByPosition); |
| 1387 } | 1360 } |
| 1388 | 1361 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1530 for (Constant constant in constants) { | 1503 for (Constant constant in constants) { |
| 1531 if (constant is ConstructedConstant) { | 1504 if (constant is ConstructedConstant) { |
| 1532 Element element = constant.computeType(compiler).element; | 1505 Element element = constant.computeType(compiler).element; |
| 1533 if (backend.isInterceptorClass(element)) { | 1506 if (backend.isInterceptorClass(element)) { |
| 1534 needed.add(element); | 1507 needed.add(element); |
| 1535 } | 1508 } |
| 1536 } | 1509 } |
| 1537 } | 1510 } |
| 1538 | 1511 |
| 1539 // Add unneeded interceptors to the [unneededClasses] set. | 1512 // Add unneeded interceptors to the [unneededClasses] set. |
| 1540 for (ClassElement interceptor in backend.interceptedClasses.keys) { | 1513 for (ClassElement interceptor in backend.interceptedClasses) { |
| 1541 if (!needed.contains(interceptor)) { | 1514 if (!needed.contains(interceptor) |
| 1515 && interceptor != compiler.objectClass) { | |
| 1542 unneededClasses.add(interceptor); | 1516 unneededClasses.add(interceptor); |
| 1543 } | 1517 } |
| 1544 } | 1518 } |
| 1545 | 1519 |
| 1546 return (ClassElement cls) => !unneededClasses.contains(cls); | 1520 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 1547 } | 1521 } |
| 1548 | 1522 |
| 1549 void emitClasses(CodeBuffer buffer) { | 1523 void emitClasses(CodeBuffer buffer) { |
| 1550 // Compute the required type checks to know which classes need a | 1524 // Compute the required type checks to know which classes need a |
| 1551 // 'is$' method. | 1525 // 'is$' method. |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1714 // if they share methods with the same signature. Currently we do this only | 1688 // if they share methods with the same signature. Currently we do this only |
| 1715 // if there are no optional parameters. Closures with optional parameters | 1689 // if there are no optional parameters. Closures with optional parameters |
| 1716 // are more difficult to canonicalize because they would need to have the | 1690 // are more difficult to canonicalize because they would need to have the |
| 1717 // same default values. | 1691 // same default values. |
| 1718 | 1692 |
| 1719 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; | 1693 bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; |
| 1720 int parameterCount = member.parameterCount(compiler); | 1694 int parameterCount = member.parameterCount(compiler); |
| 1721 | 1695 |
| 1722 Map<int, String> cache; | 1696 Map<int, String> cache; |
| 1723 String extraArg = null; | 1697 String extraArg = null; |
| 1724 // Methods on interceptor classes take an extra parameter, which is the | 1698 // Intercepted methods take an extra parameter, which is the |
| 1725 // actual receiver of the call. | 1699 // receiver of the call. |
| 1726 bool inInterceptor = backend.isInterceptorClass(member.getEnclosingClass()); | 1700 bool inInterceptor = backend.isInterceptedMethod(member); |
| 1727 if (inInterceptor) { | 1701 if (inInterceptor) { |
| 1728 cache = interceptorClosureCache; | 1702 cache = interceptorClosureCache; |
| 1729 extraArg = 'receiver'; | 1703 extraArg = 'receiver'; |
| 1730 } else { | 1704 } else { |
| 1731 cache = boundClosureCache; | 1705 cache = boundClosureCache; |
| 1732 } | 1706 } |
| 1733 List<String> fieldNames = compiler.enableMinification | 1707 List<String> fieldNames = compiler.enableMinification |
| 1734 ? inInterceptor ? const ['a', 'b', 'c'] | 1708 ? inInterceptor ? const ['a', 'b', 'c'] |
| 1735 : const ['a', 'b'] | 1709 : const ['a', 'b'] |
| 1736 : inInterceptor ? const ['self', 'target', 'receiver'] | 1710 : inInterceptor ? const ['self', 'target', 'receiver'] |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1839 /** | 1813 /** |
| 1840 * Documentation wanted -- johnniwinther | 1814 * Documentation wanted -- johnniwinther |
| 1841 * | 1815 * |
| 1842 * Invariant: [member] must be a declaration element. | 1816 * Invariant: [member] must be a declaration element. |
| 1843 */ | 1817 */ |
| 1844 void emitCallStubForGetter(Element member, | 1818 void emitCallStubForGetter(Element member, |
| 1845 Set<Selector> selectors, | 1819 Set<Selector> selectors, |
| 1846 DefineStubFunction defineStub) { | 1820 DefineStubFunction defineStub) { |
| 1847 assert(invariant(member, member.isDeclaration)); | 1821 assert(invariant(member, member.isDeclaration)); |
| 1848 LibraryElement memberLibrary = member.getLibrary(); | 1822 LibraryElement memberLibrary = member.getLibrary(); |
| 1849 // If the class is an interceptor class, the stub gets the | 1823 // If the method is intercepted, the stub gets the |
| 1850 // receiver explicitely and we need to pass it to the getter call. | 1824 // receiver explicitely and we need to pass it to the getter call. |
| 1851 bool isInterceptorClass = | 1825 bool isInterceptedMethod = backend.isInterceptedMethod(member); |
| 1852 backend.isInterceptorClass(member.getEnclosingClass()); | |
| 1853 | 1826 |
| 1854 const String receiverArgumentName = r'$receiver'; | 1827 const String receiverArgumentName = r'$receiver'; |
| 1855 | 1828 |
| 1856 jsAst.Expression buildGetter() { | 1829 jsAst.Expression buildGetter() { |
| 1857 if (member.isGetter()) { | 1830 if (member.isGetter()) { |
| 1858 String getterName = namer.getterName(member); | 1831 String getterName = namer.getterName(member); |
| 1859 return js['this'][getterName]( | 1832 return js['this'][getterName]( |
| 1860 isInterceptorClass | 1833 isInterceptedMethod |
| 1861 ? <jsAst.Expression>[js[receiverArgumentName]] | 1834 ? <jsAst.Expression>[js[receiverArgumentName]] |
| 1862 : <jsAst.Expression>[]); | 1835 : <jsAst.Expression>[]); |
| 1863 } else { | 1836 } else { |
| 1864 String fieldName = member.hasFixedBackendName() | 1837 String fieldName = member.hasFixedBackendName() |
| 1865 ? member.fixedBackendName() | 1838 ? member.fixedBackendName() |
| 1866 : namer.instanceFieldName(member); | 1839 : namer.instanceFieldName(member); |
| 1867 return js['this'][fieldName]; | 1840 return js['this'][fieldName]; |
| 1868 } | 1841 } |
| 1869 } | 1842 } |
| 1870 | 1843 |
| 1871 // Two selectors may match but differ only in type. To avoid generating | 1844 // Two selectors may match but differ only in type. To avoid generating |
| 1872 // identical stubs for each we track untyped selectors which already have | 1845 // identical stubs for each we track untyped selectors which already have |
| 1873 // stubs. | 1846 // stubs. |
| 1874 Set<Selector> generatedSelectors = new Set<Selector>(); | 1847 Set<Selector> generatedSelectors = new Set<Selector>(); |
| 1875 | 1848 |
| 1876 for (Selector selector in selectors) { | 1849 for (Selector selector in selectors) { |
| 1877 if (selector.applies(member, compiler)) { | 1850 if (selector.applies(member, compiler)) { |
| 1878 selector = selector.asUntyped; | 1851 selector = selector.asUntyped; |
| 1879 if (generatedSelectors.contains(selector)) continue; | 1852 if (generatedSelectors.contains(selector)) continue; |
| 1880 generatedSelectors.add(selector); | 1853 generatedSelectors.add(selector); |
| 1881 | 1854 |
| 1882 String invocationName = namer.invocationName(selector); | 1855 String invocationName = namer.invocationName(selector); |
| 1883 Selector callSelector = new Selector.callClosureFrom(selector); | 1856 Selector callSelector = new Selector.callClosureFrom(selector); |
| 1884 String closureCallName = namer.invocationName(callSelector); | 1857 String closureCallName = namer.invocationName(callSelector); |
| 1885 | 1858 |
| 1886 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 1859 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 1887 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 1860 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 1888 if (isInterceptorClass) { | 1861 if (isInterceptedMethod) { |
| 1889 parameters.add(new jsAst.Parameter(receiverArgumentName)); | 1862 parameters.add(new jsAst.Parameter(receiverArgumentName)); |
| 1890 } | 1863 } |
| 1891 | 1864 |
| 1892 for (int i = 0; i < selector.argumentCount; i++) { | 1865 for (int i = 0; i < selector.argumentCount; i++) { |
| 1893 String name = 'arg$i'; | 1866 String name = 'arg$i'; |
| 1894 parameters.add(new jsAst.Parameter(name)); | 1867 parameters.add(new jsAst.Parameter(name)); |
| 1895 arguments.add(js[name]); | 1868 arguments.add(js[name]); |
| 1896 } | 1869 } |
| 1897 | 1870 |
| 1898 jsAst.Fun function = js.fun( | 1871 jsAst.Fun function = js.fun( |
| 1899 parameters, | 1872 parameters, |
| 1900 js.return_(buildGetter()[closureCallName](arguments))); | 1873 js.return_(buildGetter()[closureCallName](arguments))); |
| 1901 | 1874 |
| 1902 defineStub(invocationName, function); | 1875 defineStub(invocationName, function); |
| 1903 } | 1876 } |
| 1904 } | 1877 } |
| 1905 } | 1878 } |
| 1906 | 1879 |
| 1907 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1880 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1908 ConstantHandler handler = compiler.constantHandler; | 1881 ConstantHandler handler = compiler.constantHandler; |
| 1909 Iterable<VariableElement> staticNonFinalFields = | 1882 Iterable<VariableElement> staticNonFinalFields = |
| 1910 handler.getStaticNonFinalFieldsForEmission(); | 1883 handler.getStaticNonFinalFieldsForEmission(); |
| 1911 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 1884 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 1885 // [:interceptedNames:] is handled in [emitInterceptedNames]. | |
| 1886 if (element == backend.interceptedNames) continue; | |
| 1912 compiler.withCurrentElement(element, () { | 1887 compiler.withCurrentElement(element, () { |
| 1913 Constant initialValue = handler.getInitialValueFor(element); | 1888 Constant initialValue = handler.getInitialValueFor(element); |
| 1914 jsAst.Expression init = | 1889 jsAst.Expression init = |
| 1915 js[isolateProperties][namer.getName(element)].assign( | 1890 js[isolateProperties][namer.getName(element)].assign( |
| 1916 constantEmitter.referenceInInitializationContext(initialValue)); | 1891 constantEmitter.referenceInInitializationContext(initialValue)); |
| 1917 buffer.add(jsAst.prettyPrint(init, compiler)); | 1892 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1918 buffer.add('$N'); | 1893 buffer.add('$N'); |
| 1919 }); | 1894 }); |
| 1920 } | 1895 } |
| 1921 } | 1896 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2040 | 2015 |
| 2041 List<jsAst.Expression> argNames = | 2016 List<jsAst.Expression> argNames = |
| 2042 selector.getOrderedNamedArguments().map((SourceString name) => | 2017 selector.getOrderedNamedArguments().map((SourceString name) => |
| 2043 js.string(name.slowToString())).toList(); | 2018 js.string(name.slowToString())).toList(); |
| 2044 | 2019 |
| 2045 String internalName = namer.invocationMirrorInternalName(selector); | 2020 String internalName = namer.invocationMirrorInternalName(selector); |
| 2046 | 2021 |
| 2047 String createInvocationMirror = namer.getName( | 2022 String createInvocationMirror = namer.getName( |
| 2048 compiler.createInvocationMirrorElement); | 2023 compiler.createInvocationMirrorElement); |
| 2049 | 2024 |
| 2025 assert(backend.isInterceptedName(Compiler.NO_SUCH_METHOD)); | |
| 2050 jsAst.Expression expression = js['this.$noSuchMethodName']( | 2026 jsAst.Expression expression = js['this.$noSuchMethodName']( |
| 2051 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ | 2027 [js['this'], |
| 2052 js.string(methodName), | 2028 js[namer.CURRENT_ISOLATE][createInvocationMirror]([ |
| 2053 js.string(internalName), | 2029 js.string(methodName), |
| 2054 type, | 2030 js.string(internalName), |
| 2055 new jsAst.ArrayInitializer.from( | 2031 type, |
| 2056 parameters.map((param) => js[param.name]).toList()), | 2032 new jsAst.ArrayInitializer.from( |
| 2057 new jsAst.ArrayInitializer.from(argNames)])); | 2033 parameters.map((param) => js[param.name]).toList()), |
| 2034 new jsAst.ArrayInitializer.from(argNames)])]); | |
| 2035 parameters = backend.isInterceptedName(selector.name) | |
| 2036 ? ([new jsAst.Parameter('\$receiver')]..addAll(parameters)) | |
| 2037 : parameters; | |
| 2058 return js.fun(parameters, js.return_(expression)); | 2038 return js.fun(parameters, js.return_(expression)); |
| 2059 } | 2039 } |
| 2060 | 2040 |
| 2061 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 2041 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 2062 // Cache the object class and type. | 2042 // Cache the object class and type. |
| 2063 ClassElement objectClass = compiler.objectClass; | 2043 ClassElement objectClass = compiler.objectClass; |
| 2064 DartType objectType = objectClass.computeType(compiler); | 2044 DartType objectType = objectClass.computeType(compiler); |
| 2065 | 2045 |
| 2066 for (Selector selector in selectors) { | 2046 for (Selector selector in selectors) { |
| 2067 // Introduce a helper function that determines if the given | 2047 // Introduce a helper function that determines if the given |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2204 dartMainRunner(function() { ${mainCall}; }); | 2184 dartMainRunner(function() { ${mainCall}; }); |
| 2205 } else { | 2185 } else { |
| 2206 ${mainCall}; | 2186 ${mainCall}; |
| 2207 } | 2187 } |
| 2208 } | 2188 } |
| 2209 """); | 2189 """); |
| 2210 addComment('END invoke [main].', buffer); | 2190 addComment('END invoke [main].', buffer); |
| 2211 } | 2191 } |
| 2212 | 2192 |
| 2213 void emitGetInterceptorMethod(CodeBuffer buffer, | 2193 void emitGetInterceptorMethod(CodeBuffer buffer, |
| 2214 String objectName, | |
| 2215 String key, | 2194 String key, |
| 2216 Collection<ClassElement> classes) { | 2195 Collection<ClassElement> classes) { |
| 2217 jsAst.Statement buildReturnInterceptor(ClassElement cls) { | 2196 jsAst.Statement buildReturnInterceptor(ClassElement cls) { |
| 2218 return js.return_(js[namer.isolateAccess(cls)]['prototype']); | 2197 return js.return_(js[namer.isolateAccess(cls)]['prototype']); |
| 2219 } | 2198 } |
| 2220 | 2199 |
| 2221 jsAst.VariableUse receiver = js['receiver']; | 2200 jsAst.VariableUse receiver = js['receiver']; |
| 2222 /** | 2201 /** |
| 2223 * Build a JavaScrit AST node for doing a type check on | 2202 * Build a JavaScrit AST node for doing a type check on |
| 2224 * [cls]. [cls] must be an interceptor class. | 2203 * [cls]. [cls] must be an interceptor class. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2256 bool hasString = false; | 2235 bool hasString = false; |
| 2257 for (ClassElement cls in classes) { | 2236 for (ClassElement cls in classes) { |
| 2258 if (cls == backend.jsArrayClass) hasArray = true; | 2237 if (cls == backend.jsArrayClass) hasArray = true; |
| 2259 else if (cls == backend.jsBoolClass) hasBool = true; | 2238 else if (cls == backend.jsBoolClass) hasBool = true; |
| 2260 else if (cls == backend.jsDoubleClass) hasDouble = true; | 2239 else if (cls == backend.jsDoubleClass) hasDouble = true; |
| 2261 else if (cls == backend.jsFunctionClass) hasFunction = true; | 2240 else if (cls == backend.jsFunctionClass) hasFunction = true; |
| 2262 else if (cls == backend.jsIntClass) hasInt = true; | 2241 else if (cls == backend.jsIntClass) hasInt = true; |
| 2263 else if (cls == backend.jsNullClass) hasNull = true; | 2242 else if (cls == backend.jsNullClass) hasNull = true; |
| 2264 else if (cls == backend.jsNumberClass) hasNumber = true; | 2243 else if (cls == backend.jsNumberClass) hasNumber = true; |
| 2265 else if (cls == backend.jsStringClass) hasString = true; | 2244 else if (cls == backend.jsStringClass) hasString = true; |
| 2266 else throw 'Internal error: $cls'; | 2245 else { |
| 2246 assert(cls == compiler.objectClass); | |
| 2247 } | |
| 2267 } | 2248 } |
| 2268 if (hasDouble) { | 2249 if (hasDouble) { |
| 2269 assert(!hasNumber); | |
| 2270 hasNumber = true; | 2250 hasNumber = true; |
| 2271 } | 2251 } |
| 2272 if (hasInt) hasNumber = true; | 2252 if (hasInt) hasNumber = true; |
| 2273 | 2253 |
| 2274 jsAst.Block block = new jsAst.Block.empty(); | 2254 jsAst.Block block = new jsAst.Block.empty(); |
| 2275 | 2255 |
| 2276 if (hasNumber) { | 2256 if (hasNumber) { |
| 2277 jsAst.Statement whenNumber; | 2257 jsAst.Statement whenNumber; |
| 2278 | 2258 |
| 2279 /// Note: there are two number classes in play: Dart's [num], | 2259 /// Note: there are two number classes in play: Dart's [num], |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2312 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); | 2292 block.statements.add(buildInterceptorCheck(backend.jsFunctionClass)); |
| 2313 } | 2293 } |
| 2314 if (hasBool) { | 2294 if (hasBool) { |
| 2315 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); | 2295 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); |
| 2316 } | 2296 } |
| 2317 // TODO(ahe): It might be faster to check for Array before | 2297 // TODO(ahe): It might be faster to check for Array before |
| 2318 // function and bool. | 2298 // function and bool. |
| 2319 if (hasArray) { | 2299 if (hasArray) { |
| 2320 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); | 2300 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); |
| 2321 } | 2301 } |
| 2322 block.statements.add(js.return_(js[objectName]['prototype'])); | 2302 block.statements.add(js.return_(receiver)); |
| 2323 | 2303 |
| 2324 buffer.add(jsAst.prettyPrint( | 2304 buffer.add(jsAst.prettyPrint( |
| 2325 js[isolateProperties][key].assign(js.fun(['receiver'], block)), | 2305 js[isolateProperties][key].assign(js.fun(['receiver'], block)), |
| 2326 compiler)); | 2306 compiler)); |
| 2327 buffer.add(N); | 2307 buffer.add(N); |
| 2328 } | 2308 } |
| 2329 | 2309 |
| 2330 /** | 2310 /** |
| 2331 * Emit all versions of the [:getInterceptor:] method. | 2311 * Emit all versions of the [:getInterceptor:] method. |
| 2332 */ | 2312 */ |
| 2333 void emitGetInterceptorMethods(CodeBuffer buffer) { | 2313 void emitGetInterceptorMethods(CodeBuffer buffer) { |
| 2334 // If no class needs to be intercepted, just return. | |
| 2335 if (backend.objectInterceptorClass == null) return; | |
| 2336 String objectName = namer.isolateAccess(backend.objectInterceptorClass); | |
| 2337 var specializedGetInterceptors = backend.specializedGetInterceptors; | 2314 var specializedGetInterceptors = backend.specializedGetInterceptors; |
| 2338 for (String name in specializedGetInterceptors.keys.toList()..sort()) { | 2315 for (String name in specializedGetInterceptors.keys.toList()..sort()) { |
| 2339 Collection<ClassElement> classes = specializedGetInterceptors[name]; | 2316 Collection<ClassElement> classes = specializedGetInterceptors[name]; |
| 2340 emitGetInterceptorMethod(buffer, objectName, name, classes); | 2317 emitGetInterceptorMethod(buffer, name, classes); |
| 2341 } | 2318 } |
| 2342 } | 2319 } |
| 2343 | 2320 |
| 2344 void computeNeededClasses() { | 2321 void computeNeededClasses() { |
| 2345 instantiatedClasses = | 2322 instantiatedClasses = |
| 2346 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) | 2323 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) |
| 2347 .toSet(); | 2324 .toSet(); |
| 2348 neededClasses = new Set<ClassElement>.from(instantiatedClasses); | 2325 neededClasses = new Set<ClassElement>.from(instantiatedClasses); |
| 2349 for (ClassElement element in instantiatedClasses) { | 2326 for (ClassElement element in instantiatedClasses) { |
| 2350 for (ClassElement superclass = element.superclass; | 2327 for (ClassElement superclass = element.superclass; |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2511 } | 2488 } |
| 2512 return null; | 2489 return null; |
| 2513 } | 2490 } |
| 2514 | 2491 |
| 2515 void emitOneShotInterceptors(CodeBuffer buffer) { | 2492 void emitOneShotInterceptors(CodeBuffer buffer) { |
| 2516 List<String> names = backend.oneShotInterceptors.keys.toList(); | 2493 List<String> names = backend.oneShotInterceptors.keys.toList(); |
| 2517 names.sort(); | 2494 names.sort(); |
| 2518 for (String name in names) { | 2495 for (String name in names) { |
| 2519 Selector selector = backend.oneShotInterceptors[name]; | 2496 Selector selector = backend.oneShotInterceptors[name]; |
| 2520 Set<ClassElement> classes = | 2497 Set<ClassElement> classes = |
| 2521 backend.getInterceptedClassesOn(selector); | 2498 backend.getInterceptedClassesOn(selector.name); |
| 2522 String getInterceptorName = | 2499 String getInterceptorName = |
| 2523 namer.getInterceptorName(backend.getInterceptorMethod, classes); | 2500 namer.getInterceptorName(backend.getInterceptorMethod, classes); |
| 2524 | 2501 |
| 2525 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 2502 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 2526 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | 2503 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 2527 parameters.add(new jsAst.Parameter('receiver')); | 2504 parameters.add(new jsAst.Parameter('receiver')); |
| 2528 arguments.add(js['receiver']); | 2505 arguments.add(js['receiver']); |
| 2529 | 2506 |
| 2530 if (selector.isSetter()) { | 2507 if (selector.isSetter()) { |
| 2531 parameters.add(new jsAst.Parameter('value')); | 2508 parameters.add(new jsAst.Parameter('value')); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2553 jsAst.Fun function = js.fun(parameters, body); | 2530 jsAst.Fun function = js.fun(parameters, body); |
| 2554 | 2531 |
| 2555 jsAst.PropertyAccess property = | 2532 jsAst.PropertyAccess property = |
| 2556 js[isolateProperties][name]; | 2533 js[isolateProperties][name]; |
| 2557 | 2534 |
| 2558 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); | 2535 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); |
| 2559 buffer.add(N); | 2536 buffer.add(N); |
| 2560 } | 2537 } |
| 2561 } | 2538 } |
| 2562 | 2539 |
| 2540 /** | |
| 2541 * If [:invokeOn:] has been compiled, emit all the possible selector names | |
| 2542 * that are intercepted into the [:interceptedNames:] top-level | |
| 2543 * variable. The implementation of [:invokeOn:] will use it to | |
| 2544 * determine whether it should call the method with an extra | |
| 2545 * parameter. | |
| 2546 */ | |
| 2547 void emitInterceptedNames(CodeBuffer buffer) { | |
| 2548 if (!compiler.enabledInvokeOn) return; | |
| 2549 String name = backend.namer.getName(backend.interceptedNames); | |
| 2550 jsAst.PropertyAccess property = js[isolateProperties][name]; | |
| 2551 | |
| 2552 int index = 0; | |
| 2553 List<jsAst.ArrayElement> elements = backend.usedInterceptors.map( | |
| 2554 (Selector selector) { | |
| 2555 jsAst.Literal str = js.string(namer.invocationName(selector)); | |
| 2556 return new jsAst.ArrayElement(index++, str); | |
| 2557 }).toList(); | |
| 2558 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer( | |
| 2559 backend.usedInterceptors.length, | |
| 2560 elements); | |
| 2561 | |
| 2562 buffer.add(jsAst.prettyPrint(property.assign(array), compiler)); | |
| 2563 buffer.add(N); | |
| 2564 } | |
| 2565 | |
| 2563 void emitInitFunction(CodeBuffer buffer) { | 2566 void emitInitFunction(CodeBuffer buffer) { |
| 2564 jsAst.Fun fun = js.fun([], [ | 2567 jsAst.Fun fun = js.fun([], [ |
| 2565 js['$isolateProperties = {}'], | 2568 js['$isolateProperties = {}'], |
| 2566 ] | 2569 ] |
| 2567 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 2570 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
| 2568 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 2571 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
| 2569 ..addAll(buildFinishIsolateConstructor()) | 2572 ..addAll(buildFinishIsolateConstructor()) |
| 2570 ); | 2573 ); |
| 2571 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 2574 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
| 2572 new jsAst.VariableDeclaration('init'), fun); | 2575 new jsAst.VariableDeclaration('init'), fun); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 2596 emitStaticFunctionGetters(mainBuffer); | 2599 emitStaticFunctionGetters(mainBuffer); |
| 2597 // We need to finish the classes before we construct compile time | 2600 // We need to finish the classes before we construct compile time |
| 2598 // constants. | 2601 // constants. |
| 2599 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2602 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 2600 emitRuntimeClassesAndTests(mainBuffer); | 2603 emitRuntimeClassesAndTests(mainBuffer); |
| 2601 emitCompileTimeConstants(mainBuffer); | 2604 emitCompileTimeConstants(mainBuffer); |
| 2602 // Static field initializations require the classes and compile-time | 2605 // Static field initializations require the classes and compile-time |
| 2603 // constants to be set up. | 2606 // constants to be set up. |
| 2604 emitStaticNonFinalFieldInitializations(mainBuffer); | 2607 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 2605 emitOneShotInterceptors(mainBuffer); | 2608 emitOneShotInterceptors(mainBuffer); |
| 2609 emitInterceptedNames(mainBuffer); | |
| 2606 emitGetInterceptorMethods(mainBuffer); | 2610 emitGetInterceptorMethods(mainBuffer); |
| 2607 emitLazilyInitializedStaticFields(mainBuffer); | 2611 emitLazilyInitializedStaticFields(mainBuffer); |
| 2608 | 2612 |
| 2609 isolateProperties = isolatePropertiesName; | 2613 isolateProperties = isolatePropertiesName; |
| 2610 // The following code should not use the short-hand for the | 2614 // The following code should not use the short-hand for the |
| 2611 // initialStatics. | 2615 // initialStatics. |
| 2612 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); | 2616 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); |
| 2613 if (!boundClosureBuffer.isEmpty) { | 2617 if (!boundClosureBuffer.isEmpty) { |
| 2614 mainBuffer.add(boundClosureBuffer); | 2618 mainBuffer.add(boundClosureBuffer); |
| 2615 emitFinishClassesInvocationIfNecessary(mainBuffer); | 2619 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2708 """; | 2712 """; |
| 2709 const String HOOKS_API_USAGE = """ | 2713 const String HOOKS_API_USAGE = """ |
| 2710 // The code supports the following hooks: | 2714 // The code supports the following hooks: |
| 2711 // dartPrint(message) - if this function is defined it is called | 2715 // dartPrint(message) - if this function is defined it is called |
| 2712 // instead of the Dart [print] method. | 2716 // instead of the Dart [print] method. |
| 2713 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2717 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2714 // method will not be invoked directly. | 2718 // method will not be invoked directly. |
| 2715 // Instead, a closure that will invoke [main] is | 2719 // Instead, a closure that will invoke [main] is |
| 2716 // passed to [dartMainRunner]. | 2720 // passed to [dartMainRunner]. |
| 2717 """; | 2721 """; |
| OLD | NEW |