| 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 1094 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1105 new js.VariableUse('receiver') | 1105 new js.VariableUse('receiver') |
| 1106 .dot(name) | 1106 .dot(name) |
| 1107 .callWith(arguments))])); | 1107 .callWith(arguments))])); |
| 1108 | 1108 |
| 1109 CodeBuffer code = new CodeBuffer(); | 1109 CodeBuffer code = new CodeBuffer(); |
| 1110 code.add(js.prettyPrint(function, compiler)); | 1110 code.add(js.prettyPrint(function, compiler)); |
| 1111 defineInstanceMember(name, code); | 1111 defineInstanceMember(name, code); |
| 1112 } | 1112 } |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 void emitTypedefChecksOn(DartType type, void emitTest(Element element)) { |
| 1116 for (TypedefElement typedef in checkedTypedefs) { |
| 1117 FunctionType typedefType = |
| 1118 typedef.computeType(compiler).unalias(compiler); |
| 1119 if (compiler.types.isSubtype(type, typedefType)) { |
| 1120 emitTest(typedef); |
| 1121 } |
| 1122 } |
| 1123 } |
| 1124 |
| 1115 /** | 1125 /** |
| 1116 * Generate "is tests" for [cls]: itself, and the "is tests" for the | 1126 * Generate "is tests" for [cls]: itself, and the "is tests" for the |
| 1117 * classes it implements. We don't need to add the "is tests" of the | 1127 * classes it implements. We don't need to add the "is tests" of the |
| 1118 * super class because they will be inherited at runtime. | 1128 * super class because they will be inherited at runtime. |
| 1119 */ | 1129 */ |
| 1120 void generateIsTestsOn(ClassElement cls, | 1130 void generateIsTestsOn(ClassElement cls, |
| 1121 void emitIsTest(Element element)) { | 1131 void emitIsTest(Element element)) { |
| 1122 if (checkedClasses.contains(cls)) { | 1132 if (checkedClasses.contains(cls)) { |
| 1123 emitIsTest(cls); | 1133 emitIsTest(cls); |
| 1124 } | 1134 } |
| 1125 | 1135 |
| 1126 Set<Element> generated = new Set<Element>(); | 1136 Set<Element> generated = new Set<Element>(); |
| 1127 // A class that defines a [:call:] method implicitly implements | 1137 // A class that defines a [:call:] method implicitly implements |
| 1128 // [Function] and needs checks for all typedefs that are used in is-checks. | 1138 // [Function] and needs checks for all typedefs that are used in is-checks. |
| 1129 if (checkedClasses.contains(compiler.functionClass) || | 1139 if (checkedClasses.contains(compiler.functionClass) || |
| 1130 !checkedTypedefs.isEmpty) { | 1140 !checkedTypedefs.isEmpty) { |
| 1131 FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); | 1141 FunctionElement call = cls.lookupLocalMember(Compiler.CALL_OPERATOR_NAME); |
| 1132 if (call == null) { | 1142 if (call == null) { |
| 1133 // If [cls] is a closure, it has a synthetic call operator method. | 1143 // If [cls] is a closure, it has a synthetic call operator method. |
| 1134 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); | 1144 call = cls.lookupBackendMember(Compiler.CALL_OPERATOR_NAME); |
| 1135 } | 1145 } |
| 1136 if (call != null) { | 1146 if (call != null) { |
| 1137 generateInterfacesIsTests(compiler.functionClass, | 1147 generateInterfacesIsTests(compiler.functionClass, |
| 1138 emitIsTest, | 1148 emitIsTest, |
| 1139 generated); | 1149 generated); |
| 1140 FunctionType callType = call.computeType(compiler); | 1150 emitTypedefChecksOn(call.computeType(compiler), emitIsTest); |
| 1141 for (TypedefElement typedef in checkedTypedefs) { | |
| 1142 FunctionType typedefType = | |
| 1143 typedef.computeType(compiler).unalias(compiler); | |
| 1144 if (compiler.types.isSubtype(callType, typedefType)) { | |
| 1145 emitIsTest(typedef); | |
| 1146 } | |
| 1147 } | |
| 1148 } | 1151 } |
| 1149 } | 1152 } |
| 1150 for (DartType interfaceType in cls.interfaces) { | 1153 for (DartType interfaceType in cls.interfaces) { |
| 1151 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); | 1154 generateInterfacesIsTests(interfaceType.element, emitIsTest, generated); |
| 1152 } | 1155 } |
| 1153 } | 1156 } |
| 1154 | 1157 |
| 1155 /** | 1158 /** |
| 1156 * Generate "is tests" where [cls] is being implemented. | 1159 * Generate "is tests" where [cls] is being implemented. |
| 1157 */ | 1160 */ |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1275 | 1278 |
| 1276 void emitStaticFunctionWithNamer(CodeBuffer buffer, | 1279 void emitStaticFunctionWithNamer(CodeBuffer buffer, |
| 1277 Element element, | 1280 Element element, |
| 1278 CodeBuffer functionBuffer, | 1281 CodeBuffer functionBuffer, |
| 1279 String functionNamer(Element element)) { | 1282 String functionNamer(Element element)) { |
| 1280 String functionName = functionNamer(element); | 1283 String functionName = functionNamer(element); |
| 1281 buffer.add('$isolateProperties.$functionName$_=$_'); | 1284 buffer.add('$isolateProperties.$functionName$_=$_'); |
| 1282 buffer.add(functionBuffer); | 1285 buffer.add(functionBuffer); |
| 1283 buffer.add('$N$n'); | 1286 buffer.add('$N$n'); |
| 1284 } | 1287 } |
| 1288 |
| 1285 void emitStaticFunctionsWithNamer(CodeBuffer buffer, | 1289 void emitStaticFunctionsWithNamer(CodeBuffer buffer, |
| 1286 Map<Element, CodeBuffer> generatedCode, | 1290 Map<Element, CodeBuffer> generatedCode, |
| 1287 String functionNamer(Element element)) { | 1291 String functionNamer(Element element)) { |
| 1288 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { | 1292 generatedCode.forEach((Element element, CodeBuffer functionBuffer) { |
| 1289 if (!element.isInstanceMember() && !element.isField()) { | 1293 if (!element.isInstanceMember() && !element.isField()) { |
| 1290 emitStaticFunctionWithNamer( | 1294 emitStaticFunctionWithNamer( |
| 1291 buffer, element, functionBuffer,functionNamer); | 1295 buffer, element, functionBuffer,functionNamer); |
| 1292 } | 1296 } |
| 1293 }); | 1297 }); |
| 1294 } | 1298 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1317 String invocationName = namer.instanceMethodName(callElement); | 1321 String invocationName = namer.instanceMethodName(callElement); |
| 1318 String fieldAccess = '$isolateProperties.$staticName'; | 1322 String fieldAccess = '$isolateProperties.$staticName'; |
| 1319 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); | 1323 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); |
| 1320 addParameterStubs(callElement, (String name, CodeBuffer value) { | 1324 addParameterStubs(callElement, (String name, CodeBuffer value) { |
| 1321 buffer.add('$fieldAccess.$name$_=$_$value$N'); | 1325 buffer.add('$fieldAccess.$name$_=$_$value$N'); |
| 1322 }); | 1326 }); |
| 1323 // If a static function is used as a closure we need to add its name | 1327 // If a static function is used as a closure we need to add its name |
| 1324 // in case it is used in spawnFunction. | 1328 // in case it is used in spawnFunction. |
| 1325 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1329 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| 1326 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); | 1330 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); |
| 1331 emitTypedefChecksOn(element.computeType(compiler), (Element typedef) { |
| 1332 String operator = namer.operatorIs(typedef); |
| 1333 buffer.add('$fieldAccess.$operator$_=${_}true$N'); |
| 1334 }); |
| 1327 } | 1335 } |
| 1328 } | 1336 } |
| 1329 | 1337 |
| 1330 void emitBoundClosureClassHeader(String mangledName, | 1338 void emitBoundClosureClassHeader(String mangledName, |
| 1331 String superName, | 1339 String superName, |
| 1332 List<String> fieldNames, | 1340 List<String> fieldNames, |
| 1333 CodeBuffer buffer) { | 1341 CodeBuffer buffer) { |
| 1334 buffer.add('$classesCollector.$mangledName$_=$_' | 1342 buffer.add('$classesCollector.$mangledName$_=$_' |
| 1335 '{"":"$superName;${Strings.join(fieldNames,',')}",'); | 1343 '{"":"$superName;${Strings.join(fieldNames,',')}",'); |
| 1336 } | 1344 } |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1430 new js.This().dot(fieldNames[0]), | 1438 new js.This().dot(fieldNames[0]), |
| 1431 new js.This().dot(fieldNames[1])) | 1439 new js.This().dot(fieldNames[1])) |
| 1432 .callWith(arguments))])); | 1440 .callWith(arguments))])); |
| 1433 | 1441 |
| 1434 boundClosureBuffer.add( | 1442 boundClosureBuffer.add( |
| 1435 '$_$invocationName:$_${js.prettyPrint(fun,compiler)}'); | 1443 '$_$invocationName:$_${js.prettyPrint(fun,compiler)}'); |
| 1436 | 1444 |
| 1437 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { | 1445 addParameterStubs(callElement, (String stubName, CodeBuffer memberValue) { |
| 1438 boundClosureBuffer.add(',\n$_$stubName:$_$memberValue'); | 1446 boundClosureBuffer.add(',\n$_$stubName:$_$memberValue'); |
| 1439 }); | 1447 }); |
| 1448 |
| 1449 emitTypedefChecksOn(member.computeType(compiler), (Element typedef) { |
| 1450 String operator = namer.operatorIs(typedef); |
| 1451 boundClosureBuffer.add(',\n$_$operator$_:${_}true'); |
| 1452 }); |
| 1453 |
| 1440 boundClosureBuffer.add("$n}$N"); | 1454 boundClosureBuffer.add("$n}$N"); |
| 1441 | 1455 |
| 1442 closureClass = namer.isolateAccess(closureClassElement); | 1456 closureClass = namer.isolateAccess(closureClassElement); |
| 1443 | 1457 |
| 1444 // Cache it. | 1458 // Cache it. |
| 1445 if (!hasOptionalParameters) { | 1459 if (!hasOptionalParameters) { |
| 1446 cache[parameterCount] = closureClass; | 1460 cache[parameterCount] = closureClass; |
| 1447 } | 1461 } |
| 1448 } | 1462 } |
| 1449 | 1463 |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2067 """; | 2081 """; |
| 2068 const String HOOKS_API_USAGE = """ | 2082 const String HOOKS_API_USAGE = """ |
| 2069 // The code supports the following hooks: | 2083 // The code supports the following hooks: |
| 2070 // dartPrint(message) - if this function is defined it is called | 2084 // dartPrint(message) - if this function is defined it is called |
| 2071 // instead of the Dart [print] method. | 2085 // instead of the Dart [print] method. |
| 2072 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2086 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2073 // method will not be invoked directly. | 2087 // method will not be invoked directly. |
| 2074 // Instead, a closure that will invoke [main] is | 2088 // Instead, a closure that will invoke [main] is |
| 2075 // passed to [dartMainRunner]. | 2089 // passed to [dartMainRunner]. |
| 2076 """; | 2090 """; |
| OLD | NEW |