| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library code_generator; | 5 library code_generator; |
| 6 | 6 |
| 7 import 'glue.dart'; | 7 import 'glue.dart'; |
| 8 | 8 |
| 9 import '../../closure.dart' show | 9 import '../../closure.dart' show |
| 10 ClosureClassElement; | 10 ClosureClassElement; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 | 274 |
| 275 registry.registerInstantiation(node.type); | 275 registry.registerInstantiation(node.type); |
| 276 FunctionElement target = node.target; | 276 FunctionElement target = node.target; |
| 277 List<js.Expression> arguments = visitExpressionList(node.arguments); | 277 List<js.Expression> arguments = visitExpressionList(node.arguments); |
| 278 return buildStaticInvoke( | 278 return buildStaticInvoke( |
| 279 target, | 279 target, |
| 280 arguments, | 280 arguments, |
| 281 sourceInformation: node.sourceInformation); | 281 sourceInformation: node.sourceInformation); |
| 282 } | 282 } |
| 283 | 283 |
| 284 void registerMethodInvoke(tree_ir.InvokeMethod node) { | 284 void registerMethodInvoke(Selector selector, TypeMask receiverType) { |
| 285 Selector selector = node.selector; | 285 registry.registerDynamicUse(new DynamicUse(selector, receiverType)); |
| 286 TypeMask mask = node.mask; | 286 if (!selector.isGetter && !selector.isSetter) { |
| 287 mask = glue.extendMaskIfReachesAll(selector, mask); | |
| 288 if (selector.isGetter) { | |
| 289 registry.registerDynamicUse(new DynamicUse(selector, mask)); | |
| 290 } else if (selector.isSetter) { | |
| 291 registry.registerDynamicUse(new DynamicUse(selector, mask)); | |
| 292 } else { | |
| 293 assert(invariant(CURRENT_ELEMENT_SPANNABLE, | |
| 294 selector.isCall || selector.isOperator || | |
| 295 selector.isIndex || selector.isIndexSet, | |
| 296 message: 'unexpected kind ${selector.kind}')); | |
| 297 // TODO(sigurdm): We should find a better place to register the call. | 287 // TODO(sigurdm): We should find a better place to register the call. |
| 298 Selector call = new Selector.callClosureFrom(selector); | 288 Selector call = new Selector.callClosureFrom(selector); |
| 299 registry.registerDynamicUse(new DynamicUse(call, null)); | 289 registry.registerDynamicUse(new DynamicUse(call, null)); |
| 300 registry.registerDynamicUse(new DynamicUse(selector, mask)); | |
| 301 } | 290 } |
| 302 } | 291 } |
| 303 | 292 |
| 304 @override | 293 @override |
| 305 js.Expression visitInvokeMethod(tree_ir.InvokeMethod node) { | 294 js.Expression visitInvokeMethod(tree_ir.InvokeMethod node) { |
| 306 registerMethodInvoke(node); | 295 TypeMask mask = glue.extendMaskIfReachesAll(node.selector, node.mask); |
| 296 registerMethodInvoke(node.selector, mask); |
| 307 return js.propertyCall(visitExpression(node.receiver), | 297 return js.propertyCall(visitExpression(node.receiver), |
| 308 glue.invocationName(node.selector), | 298 glue.invocationName(node.selector), |
| 309 visitExpressionList(node.arguments)) | 299 visitExpressionList(node.arguments)) |
| 310 .withSourceInformation(node.sourceInformation); | 300 .withSourceInformation(node.sourceInformation); |
| 311 } | 301 } |
| 312 | 302 |
| 313 @override | 303 @override |
| 314 js.Expression visitInvokeStatic(tree_ir.InvokeStatic node) { | 304 js.Expression visitInvokeStatic(tree_ir.InvokeStatic node) { |
| 315 FunctionElement target = node.target; | 305 FunctionElement target = node.target; |
| 316 List<js.Expression> arguments = visitExpressionList(node.arguments); | 306 List<js.Expression> arguments = visitExpressionList(node.arguments); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 new CallStructure.unnamed(node.arguments.length))); | 338 new CallStructure.unnamed(node.arguments.length))); |
| 349 return js.js('#.#.call(#, #)', | 339 return js.js('#.#.call(#, #)', |
| 350 [glue.prototypeAccess(node.target.enclosingClass), | 340 [glue.prototypeAccess(node.target.enclosingClass), |
| 351 glue.invocationName(node.selector), | 341 glue.invocationName(node.selector), |
| 352 visitExpression(node.receiver), | 342 visitExpression(node.receiver), |
| 353 visitExpressionList(node.arguments)]) | 343 visitExpressionList(node.arguments)]) |
| 354 .withSourceInformation(node.sourceInformation); | 344 .withSourceInformation(node.sourceInformation); |
| 355 } | 345 } |
| 356 | 346 |
| 357 @override | 347 @override |
| 348 js.Expression visitOneShotInterceptor(tree_ir.OneShotInterceptor node) { |
| 349 registerMethodInvoke(node.selector, node.mask); |
| 350 registry.registerUseInterceptor(); |
| 351 return js.js('#.#(#)', |
| 352 [glue.getInterceptorLibrary(), |
| 353 glue.registerOneShotInterceptor(node.selector), |
| 354 visitExpressionList(node.arguments)]) |
| 355 .withSourceInformation(node.sourceInformation); |
| 356 } |
| 357 |
| 358 @override |
| 358 js.Expression visitLiteralList(tree_ir.LiteralList node) { | 359 js.Expression visitLiteralList(tree_ir.LiteralList node) { |
| 359 registry.registerInstantiatedClass(glue.listClass); | 360 registry.registerInstantiatedClass(glue.listClass); |
| 360 List<js.Expression> entries = visitExpressionList(node.values); | 361 List<js.Expression> entries = visitExpressionList(node.values); |
| 361 return new js.ArrayInitializer(entries); | 362 return new js.ArrayInitializer(entries); |
| 362 } | 363 } |
| 363 | 364 |
| 364 @override | 365 @override |
| 365 js.Expression visitLiteralMap(tree_ir.LiteralMap node) { | 366 js.Expression visitLiteralMap(tree_ir.LiteralMap node) { |
| 366 ConstructorElement constructor; | 367 ConstructorElement constructor; |
| 367 if (node.entries.isEmpty) { | 368 if (node.entries.isEmpty) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 392 @override | 393 @override |
| 393 js.Expression visitNot(tree_ir.Not node) { | 394 js.Expression visitNot(tree_ir.Not node) { |
| 394 return new js.Prefix("!", visitExpression(node.operand)); | 395 return new js.Prefix("!", visitExpression(node.operand)); |
| 395 } | 396 } |
| 396 | 397 |
| 397 @override | 398 @override |
| 398 js.Expression visitThis(tree_ir.This node) { | 399 js.Expression visitThis(tree_ir.This node) { |
| 399 return new js.This(); | 400 return new js.This(); |
| 400 } | 401 } |
| 401 | 402 |
| 403 /// Ensure that 'instanceof' checks may be performed against [class_]. |
| 404 /// |
| 405 /// Even if the class is never instantiated, a JS constructor must be emitted |
| 406 /// so the 'instanceof' expression does not throw an exception at runtime. |
| 407 /// |
| 408 /// It does not help to ask the class world if the class is instantiated, |
| 409 /// because it could still get tree-shaken if it is unused after optimization. |
| 410 void registerInstanceofCheck(ClassElement class_) { |
| 411 // TODO(asgerf): This is the only hook we have to ensure the JS constructor |
| 412 // gets emitted, but it is very imprecise. We should do better. |
| 413 registry.registerInstantiatedClass(class_); |
| 414 } |
| 415 |
| 402 @override | 416 @override |
| 403 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { | 417 js.Expression visitTypeOperator(tree_ir.TypeOperator node) { |
| 404 js.Expression value = visitExpression(node.value); | 418 js.Expression value = visitExpression(node.value); |
| 405 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments); | 419 List<js.Expression> typeArguments = visitExpressionList(node.typeArguments); |
| 406 DartType type = node.type; | 420 DartType type = node.type; |
| 407 if (type is InterfaceType) { | 421 if (type is InterfaceType) { |
| 408 registry.registerTypeUse(new TypeUse.isCheck(type)); | 422 registry.registerTypeUse(new TypeUse.isCheck(type)); |
| 409 //glue.registerIsCheck(type, registry); | |
| 410 ClassElement clazz = type.element; | 423 ClassElement clazz = type.element; |
| 411 | 424 |
| 412 if (glue.isStringClass(clazz)) { | 425 if (glue.isStringClass(clazz)) { |
| 413 if (node.isTypeTest) { | 426 if (node.isTypeTest) { |
| 414 return js.js(r'typeof # === "string"', <js.Expression>[value]); | 427 return js.js(r'typeof # === "string"', <js.Expression>[value]); |
| 415 } | 428 } |
| 416 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. | 429 // TODO(sra): Implement fast cast via calling 'stringTypeCast'. |
| 417 } else if (glue.isBoolClass(clazz)) { | 430 } else if (glue.isBoolClass(clazz)) { |
| 418 if (node.isTypeTest) { | 431 if (node.isTypeTest) { |
| 419 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); | 432 return js.js(r'typeof # === "boolean"', <js.Expression>[value]); |
| 420 } | 433 } |
| 421 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. | 434 // TODO(sra): Implement fast cast via calling 'boolTypeCast'. |
| 435 } else if (node.isTypeTest && |
| 436 node.typeArguments.isEmpty && |
| 437 glue.mayGenerateInstanceofCheck(type)) { |
| 438 registerInstanceofCheck(clazz); |
| 439 return js.js('# instanceof #', [value, glue.constructorAccess(clazz)]); |
| 422 } | 440 } |
| 423 | 441 |
| 424 // The helper we use needs the JSArray class to exist, but for some | 442 // The helper we use needs the JSArray class to exist, but for some |
| 425 // reason the helper does not cause this dependency to be registered. | 443 // reason the helper does not cause this dependency to be registered. |
| 426 // TODO(asgerf): Most programs need List anyway, but we should fix this. | 444 // TODO(asgerf): Most programs need List anyway, but we should fix this. |
| 427 registry.registerInstantiatedClass(glue.listClass); | 445 registry.registerInstantiatedClass(glue.listClass); |
| 428 | 446 |
| 429 // We use one of the two helpers: | 447 // We use one of the two helpers: |
| 430 // | 448 // |
| 431 // checkSubtype(value, $isT, typeArgs, $asT) | 449 // checkSubtype(value, $isT, typeArgs, $asT) |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1140 void registerDefaultParameterValues(ExecutableElement element) { | 1158 void registerDefaultParameterValues(ExecutableElement element) { |
| 1141 if (element is! FunctionElement) return; | 1159 if (element is! FunctionElement) return; |
| 1142 FunctionElement function = element; | 1160 FunctionElement function = element; |
| 1143 if (function.isStatic) return; // Defaults are inlined at call sites. | 1161 if (function.isStatic) return; // Defaults are inlined at call sites. |
| 1144 function.functionSignature.forEachOptionalParameter((param) { | 1162 function.functionSignature.forEachOptionalParameter((param) { |
| 1145 ConstantValue constant = glue.getDefaultParameterValue(param); | 1163 ConstantValue constant = glue.getDefaultParameterValue(param); |
| 1146 registry.registerCompileTimeConstant(constant); | 1164 registry.registerCompileTimeConstant(constant); |
| 1147 }); | 1165 }); |
| 1148 } | 1166 } |
| 1149 } | 1167 } |
| OLD | NEW |