| 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 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 // If the method is in an interceptor class, we need to also pass | 477 // If the method is in an interceptor class, we need to also pass |
| 478 // the actual receiver. | 478 // the actual receiver. |
| 479 int extraArgumentCount = isInterceptorClass ? 1 : 0; | 479 int extraArgumentCount = isInterceptorClass ? 1 : 0; |
| 480 // Use '$receiver' to avoid clashes with other parameter names. Using | 480 // Use '$receiver' to avoid clashes with other parameter names. Using |
| 481 // '$receiver' works because [JsNames.getValid] used for getting parameter | 481 // '$receiver' works because [JsNames.getValid] used for getting parameter |
| 482 // names never returns a name beginning with a single '$'. | 482 // names never returns a name beginning with a single '$'. |
| 483 String receiverArgumentName = r'$receiver'; | 483 String receiverArgumentName = r'$receiver'; |
| 484 | 484 |
| 485 // The parameters that this stub takes. | 485 // The parameters that this stub takes. |
| 486 List<js.Parameter> parametersBuffer = | 486 List<js.Parameter> parametersBuffer = |
| 487 new List<js.Parameter>(selector.argumentCount + extraArgumentCount); | 487 new List<js.Parameter>.fixedLength( |
| 488 selector.argumentCount + extraArgumentCount); |
| 488 // The arguments that will be passed to the real method. | 489 // The arguments that will be passed to the real method. |
| 489 List<js.Expression> argumentsBuffer = | 490 List<js.Expression> argumentsBuffer = |
| 490 new List<js.Expression>(parameters.parameterCount + extraArgumentCount); | 491 new List<js.Expression>.fixedLength( |
| 492 parameters.parameterCount + extraArgumentCount); |
| 491 | 493 |
| 492 int count = 0; | 494 int count = 0; |
| 493 if (isInterceptorClass) { | 495 if (isInterceptorClass) { |
| 494 count++; | 496 count++; |
| 495 parametersBuffer[0] = new js.Parameter(receiverArgumentName); | 497 parametersBuffer[0] = new js.Parameter(receiverArgumentName); |
| 496 argumentsBuffer[0] = new js.VariableUse(receiverArgumentName); | 498 argumentsBuffer[0] = new js.VariableUse(receiverArgumentName); |
| 497 } | 499 } |
| 498 | 500 |
| 499 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; | 501 int indexOfLastOptionalArgumentInParameters = positionalArgumentCount - 1; |
| 500 TreeElements elements = | 502 TreeElements elements = |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 new js.Block( | 1102 new js.Block( |
| 1101 <js.Statement>[ | 1103 <js.Statement>[ |
| 1102 new js.Return( | 1104 new js.Return( |
| 1103 new js.VariableUse('receiver') | 1105 new js.VariableUse('receiver') |
| 1104 .dot(name) | 1106 .dot(name) |
| 1105 .callWith(arguments))])); | 1107 .callWith(arguments))])); |
| 1106 builder.addProperty(name, function); | 1108 builder.addProperty(name, function); |
| 1107 } | 1109 } |
| 1108 } | 1110 } |
| 1109 | 1111 |
| 1110 Collection<Element> getTypedefChecksOn(DartType type) { | 1112 Iterable<Element> getTypedefChecksOn(DartType type) { |
| 1111 return checkedTypedefs.filter((TypedefElement typedef) { | 1113 return checkedTypedefs.where((TypedefElement typedef) { |
| 1112 FunctionType typedefType = | 1114 FunctionType typedefType = |
| 1113 typedef.computeType(compiler).unalias(compiler); | 1115 typedef.computeType(compiler).unalias(compiler); |
| 1114 return compiler.types.isSubtype(type, typedefType); | 1116 return compiler.types.isSubtype(type, typedefType); |
| 1115 }); | 1117 }); |
| 1116 } | 1118 } |
| 1117 | 1119 |
| 1118 /** | 1120 /** |
| 1119 * Generate "is tests" for [cls]: itself, and the "is tests" for the | 1121 * Generate "is tests" for [cls]: itself, and the "is tests" for the |
| 1120 * classes it implements. We don't need to add the "is tests" of the | 1122 * classes it implements. We don't need to add the "is tests" of the |
| 1121 * super class because they will be inherited at runtime. | 1123 * super class because they will be inherited at runtime. |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 js.Expression assignment = | 1277 js.Expression assignment = |
| 1276 js.assign(js.use(isolateProperties).dot(name), functionExpression); | 1278 js.assign(js.use(isolateProperties).dot(name), functionExpression); |
| 1277 buffer.add(js.prettyPrint(assignment, compiler)); | 1279 buffer.add(js.prettyPrint(assignment, compiler)); |
| 1278 buffer.add('$N$n'); | 1280 buffer.add('$N$n'); |
| 1279 } | 1281 } |
| 1280 | 1282 |
| 1281 void emitStaticFunctions(CodeBuffer buffer) { | 1283 void emitStaticFunctions(CodeBuffer buffer) { |
| 1282 bool isStaticFunction(Element element) => | 1284 bool isStaticFunction(Element element) => |
| 1283 !element.isInstanceMember() && !element.isField(); | 1285 !element.isInstanceMember() && !element.isField(); |
| 1284 | 1286 |
| 1285 Collection<Element> elements = | 1287 Iterable<Element> elements = |
| 1286 compiler.codegenWorld.generatedCode.keys.filter(isStaticFunction); | 1288 compiler.codegenWorld.generatedCode.keys.where(isStaticFunction); |
| 1287 Set<Element> pendingElementsWithBailouts = | 1289 Set<Element> pendingElementsWithBailouts = |
| 1288 new Set<Element>.from( | 1290 compiler.codegenWorld.generatedBailoutCode.keys |
| 1289 compiler.codegenWorld.generatedBailoutCode.keys.filter( | 1291 .where(isStaticFunction) |
| 1290 isStaticFunction)); | 1292 .toSet(); |
| 1291 | 1293 |
| 1292 for (Element element in Elements.sortedByPosition(elements)) { | 1294 for (Element element in Elements.sortedByPosition(elements)) { |
| 1293 js.Expression code = compiler.codegenWorld.generatedCode[element]; | 1295 js.Expression code = compiler.codegenWorld.generatedCode[element]; |
| 1294 emitStaticFunction(buffer, namer.getName(element), code); | 1296 emitStaticFunction(buffer, namer.getName(element), code); |
| 1295 js.Expression bailoutCode = | 1297 js.Expression bailoutCode = |
| 1296 compiler.codegenWorld.generatedBailoutCode[element]; | 1298 compiler.codegenWorld.generatedBailoutCode[element]; |
| 1297 if (bailoutCode != null) { | 1299 if (bailoutCode != null) { |
| 1298 pendingElementsWithBailouts.remove(element); | 1300 pendingElementsWithBailouts.remove(element); |
| 1299 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); | 1301 emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); |
| 1300 } | 1302 } |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 buildGetter().dot(closureCallName) | 1571 buildGetter().dot(closureCallName) |
| 1570 .callWith(arguments))])); | 1572 .callWith(arguments))])); |
| 1571 | 1573 |
| 1572 defineStub(invocationName, function); | 1574 defineStub(invocationName, function); |
| 1573 } | 1575 } |
| 1574 } | 1576 } |
| 1575 } | 1577 } |
| 1576 | 1578 |
| 1577 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1579 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1578 ConstantHandler handler = compiler.constantHandler; | 1580 ConstantHandler handler = compiler.constantHandler; |
| 1579 List<VariableElement> staticNonFinalFields = | 1581 Iterable<VariableElement> staticNonFinalFields = |
| 1580 handler.getStaticNonFinalFieldsForEmission(); | 1582 handler.getStaticNonFinalFieldsForEmission(); |
| 1581 for (Element element in staticNonFinalFields) { | 1583 for (Element element in staticNonFinalFields) { |
| 1582 compiler.withCurrentElement(element, () { | 1584 compiler.withCurrentElement(element, () { |
| 1583 Constant initialValue = handler.getInitialValueFor(element); | 1585 Constant initialValue = handler.getInitialValueFor(element); |
| 1584 js.Expression init = | 1586 js.Expression init = |
| 1585 new js.Assignment( | 1587 new js.Assignment( |
| 1586 new js.PropertyAccess.field( | 1588 new js.PropertyAccess.field( |
| 1587 new js.VariableUse(isolateProperties), | 1589 new js.VariableUse(isolateProperties), |
| 1588 namer.getName(element)), | 1590 namer.getName(element)), |
| 1589 constantEmitter.referenceInInitializationContext(initialValue)); | 1591 constantEmitter.referenceInInitializationContext(initialValue)); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1725 // Values match JSInvocationMirror in js-helper library. | 1727 // Values match JSInvocationMirror in js-helper library. |
| 1726 int type = selector.invocationMirrorKind; | 1728 int type = selector.invocationMirrorKind; |
| 1727 String methodName = selector.invocationMirrorMemberName; | 1729 String methodName = selector.invocationMirrorMemberName; |
| 1728 List<js.Parameter> parameters = <js.Parameter>[]; | 1730 List<js.Parameter> parameters = <js.Parameter>[]; |
| 1729 CodeBuffer args = new CodeBuffer(); | 1731 CodeBuffer args = new CodeBuffer(); |
| 1730 for (int i = 0; i < selector.argumentCount; i++) { | 1732 for (int i = 0; i < selector.argumentCount; i++) { |
| 1731 parameters.add(new js.Parameter('\$$i')); | 1733 parameters.add(new js.Parameter('\$$i')); |
| 1732 } | 1734 } |
| 1733 | 1735 |
| 1734 List<js.Expression> argNames = | 1736 List<js.Expression> argNames = |
| 1735 selector.getOrderedNamedArguments().map((SourceString name) => | 1737 selector.getOrderedNamedArguments().mappedBy((SourceString name) => |
| 1736 js.string(name.slowToString())); | 1738 js.string(name.slowToString())).toList(); |
| 1737 | 1739 |
| 1738 String internalName = namer.invocationMirrorInternalName(selector); | 1740 String internalName = namer.invocationMirrorInternalName(selector); |
| 1739 | 1741 |
| 1740 String createInvocationMirror = namer.getName( | 1742 String createInvocationMirror = namer.getName( |
| 1741 compiler.createInvocationMirrorElement); | 1743 compiler.createInvocationMirrorElement); |
| 1742 | 1744 |
| 1743 js.Expression expression = | 1745 js.Expression expression = |
| 1744 new js.This() | 1746 new js.This() |
| 1745 .dot(noSuchMethodName) | 1747 .dot(noSuchMethodName) |
| 1746 .callWith( | 1748 .callWith( |
| 1747 <js.Expression>[ | 1749 <js.Expression>[ |
| 1748 new js.VariableUse(namer.CURRENT_ISOLATE) | 1750 new js.VariableUse(namer.CURRENT_ISOLATE) |
| 1749 .dot(createInvocationMirror) | 1751 .dot(createInvocationMirror) |
| 1750 .callWith( | 1752 .callWith( |
| 1751 <js.Expression>[ | 1753 <js.Expression>[ |
| 1752 js.string(methodName), | 1754 js.string(methodName), |
| 1753 js.string(internalName), | 1755 js.string(internalName), |
| 1754 new js.LiteralNumber('$type'), | 1756 new js.LiteralNumber('$type'), |
| 1755 new js.ArrayInitializer.from( | 1757 new js.ArrayInitializer.from( |
| 1756 parameters.map((param) => js.use(param.name))), | 1758 parameters.mappedBy((param) => js.use(param.name))
.toList()), |
| 1757 new js.ArrayInitializer.from(argNames)])]); | 1759 new js.ArrayInitializer.from(argNames)])]); |
| 1758 js.Expression function = | 1760 js.Expression function = |
| 1759 new js.Fun(parameters, | 1761 new js.Fun(parameters, |
| 1760 new js.Block(<js.Statement>[new js.Return(expression)])); | 1762 new js.Block(<js.Statement>[new js.Return(expression)])); |
| 1761 return function; | 1763 return function; |
| 1762 } | 1764 } |
| 1763 | 1765 |
| 1764 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { | 1766 void addNoSuchMethodHandlers(SourceString ignore, Set<Selector> selectors) { |
| 1765 // Cache the object class and type. | 1767 // Cache the object class and type. |
| 1766 ClassElement objectClass = compiler.objectClass; | 1768 ClassElement objectClass = compiler.objectClass; |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 if (backend.objectInterceptorClass == null) return; | 2082 if (backend.objectInterceptorClass == null) return; |
| 2081 String objectName = namer.isolateAccess(backend.objectInterceptorClass); | 2083 String objectName = namer.isolateAccess(backend.objectInterceptorClass); |
| 2082 backend.specializedGetInterceptors.forEach( | 2084 backend.specializedGetInterceptors.forEach( |
| 2083 (String key, Collection<ClassElement> classes) { | 2085 (String key, Collection<ClassElement> classes) { |
| 2084 emitGetInterceptorMethod(buffer, objectName, key, classes); | 2086 emitGetInterceptorMethod(buffer, objectName, key, classes); |
| 2085 }); | 2087 }); |
| 2086 } | 2088 } |
| 2087 | 2089 |
| 2088 void computeNeededClasses() { | 2090 void computeNeededClasses() { |
| 2089 instantiatedClasses = | 2091 instantiatedClasses = |
| 2090 compiler.codegenWorld.instantiatedClasses.filter(computeClassFilter()); | 2092 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()); |
| 2091 neededClasses = new Set<ClassElement>.from(instantiatedClasses); | 2093 neededClasses = instantiatedClasses.toSet(); |
| 2092 for (ClassElement element in instantiatedClasses) { | 2094 for (ClassElement element in instantiatedClasses) { |
| 2093 for (ClassElement superclass = element.superclass; | 2095 for (ClassElement superclass = element.superclass; |
| 2094 superclass != null; | 2096 superclass != null; |
| 2095 superclass = superclass.superclass) { | 2097 superclass = superclass.superclass) { |
| 2096 if (neededClasses.contains(superclass)) break; | 2098 if (neededClasses.contains(superclass)) break; |
| 2097 neededClasses.add(superclass); | 2099 neededClasses.add(superclass); |
| 2098 } | 2100 } |
| 2099 } | 2101 } |
| 2100 } | 2102 } |
| 2101 | 2103 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2180 """; | 2182 """; |
| 2181 const String HOOKS_API_USAGE = """ | 2183 const String HOOKS_API_USAGE = """ |
| 2182 // The code supports the following hooks: | 2184 // The code supports the following hooks: |
| 2183 // dartPrint(message) - if this function is defined it is called | 2185 // dartPrint(message) - if this function is defined it is called |
| 2184 // instead of the Dart [print] method. | 2186 // instead of the Dart [print] method. |
| 2185 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2187 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2186 // method will not be invoked directly. | 2188 // method will not be invoked directly. |
| 2187 // Instead, a closure that will invoke [main] is | 2189 // Instead, a closure that will invoke [main] is |
| 2188 // passed to [dartMainRunner]. | 2190 // passed to [dartMainRunner]. |
| 2189 """; | 2191 """; |
| OLD | NEW |