| 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 class SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 final JavaScriptBackend backend; | 6 final JavaScriptBackend backend; |
| 7 SsaCodeGeneratorTask(JavaScriptBackend backend) | 7 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 8 : this.backend = backend, | 8 : this.backend = backend, |
| 9 super(backend.compiler); | 9 super(backend.compiler); |
| 10 String get name() => 'SSA code generator'; | 10 String get name() => 'SSA code generator'; |
| (...skipping 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 js.Call jsPropertyCall(js.Expression receiver, | 1396 js.Call jsPropertyCall(js.Expression receiver, |
| 1397 String fieldName, | 1397 String fieldName, |
| 1398 List<js.Expression> arguments) { | 1398 List<js.Expression> arguments) { |
| 1399 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), | 1399 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), |
| 1400 arguments); | 1400 arguments); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 1403 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 1404 use(node.receiver); | 1404 use(node.receiver); |
| 1405 js.Expression object = pop(); | 1405 js.Expression object = pop(); |
| 1406 SourceString name = node.selector.name; |
| 1406 String methodName; | 1407 String methodName; |
| 1407 List<js.Expression> arguments; | 1408 List<js.Expression> arguments; |
| 1408 | 1409 |
| 1409 // Avoid adding the generative constructor name to the list of | 1410 // Avoid adding the generative constructor name to the list of |
| 1410 // seen selectors. | 1411 // seen selectors. |
| 1411 if (node.inputs[0] is HForeignNew) { | 1412 if (node.inputs[0] is HForeignNew) { |
| 1412 // TODO(ahe): The constructor name was statically resolved in | 1413 // TODO(ahe): The constructor name was statically resolved in |
| 1413 // SsaBuilder.buildFactory. Is there a cleaner way to do this? | 1414 // SsaBuilder.buildFactory. Is there a cleaner way to do this? |
| 1414 methodName = node.name.slowToString(); | 1415 methodName = name.slowToString(); |
| 1415 arguments = visitArguments(node.inputs); | 1416 arguments = visitArguments(node.inputs); |
| 1416 } else { | 1417 } else { |
| 1417 methodName = compiler.namer.instanceMethodInvocationName( | 1418 methodName = compiler.namer.instanceMethodInvocationName( |
| 1418 currentLibrary, node.name, node.selector); | 1419 node.selector.library, name, node.selector); |
| 1419 arguments = visitArguments(node.inputs); | 1420 arguments = visitArguments(node.inputs); |
| 1420 bool inLoop = node.block.enclosingLoopHeader !== null; | 1421 bool inLoop = node.block.enclosingLoopHeader !== null; |
| 1421 | 1422 |
| 1422 // Register this invocation to collect the types used at all call sites. | 1423 // Register this invocation to collect the types used at all call sites. |
| 1423 Selector selector = getOptimizedSelectorFor(node, node.selector); | 1424 Selector selector = getOptimizedSelectorFor(node, node.selector); |
| 1424 backend.registerDynamicInvocation(node, selector, types); | 1425 backend.registerDynamicInvocation(node, selector, types); |
| 1425 | 1426 |
| 1426 // If we don't know what we're calling or if we are calling a getter, | 1427 // If we don't know what we're calling or if we are calling a getter, |
| 1427 // we need to register that fact that we may be calling a closure | 1428 // we need to register that fact that we may be calling a closure |
| 1428 // with the same arguments. | 1429 // with the same arguments. |
| 1429 Element target = node.element; | 1430 Element target = node.element; |
| 1430 if (target === null || target.isGetter()) { | 1431 if (target === null || target.isGetter()) { |
| 1431 // TODO(kasperl): If we have a typed selector for the call, we | 1432 // TODO(kasperl): If we have a typed selector for the call, we |
| 1432 // may know something about the types of closures that need | 1433 // may know something about the types of closures that need |
| 1433 // the specific closure call method. | 1434 // the specific closure call method. |
| 1434 Selector call = new Selector.callClosureFrom(selector); | 1435 Selector call = new Selector.callClosureFrom(selector); |
| 1435 world.registerDynamicInvocation(call.name, call); | 1436 world.registerDynamicInvocation(call.name, call); |
| 1436 } | 1437 } |
| 1437 | 1438 |
| 1438 if (target !== null) { | 1439 if (target !== null) { |
| 1439 // If we know we're calling a specific method, register that | 1440 // If we know we're calling a specific method, register that |
| 1440 // method only. | 1441 // method only. |
| 1441 if (inLoop) backend.builder.functionsCalledInLoop.add(target); | 1442 if (inLoop) backend.builder.functionsCalledInLoop.add(target); |
| 1442 world.registerDynamicInvocationOf(target); | 1443 world.registerDynamicInvocationOf(target); |
| 1443 } else { | 1444 } else { |
| 1444 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector; | 1445 if (inLoop) backend.builder.selectorsCalledInLoop[name] = selector; |
| 1445 world.registerDynamicInvocation(node.name, selector); | 1446 world.registerDynamicInvocation(name, selector); |
| 1446 } | 1447 } |
| 1447 } | 1448 } |
| 1448 push(jsPropertyCall(object, methodName, arguments), node); | 1449 push(jsPropertyCall(object, methodName, arguments), node); |
| 1449 } | 1450 } |
| 1450 | 1451 |
| 1451 Selector getOptimizedSelectorFor(HInvokeDynamic node, | 1452 Selector getOptimizedSelectorFor(HInvokeDynamic node, |
| 1452 Selector defaultSelector) { | 1453 Selector defaultSelector) { |
| 1453 // TODO(4434): For private members we need to use the untyped selector. | 1454 // TODO(4434): For private members we need to use the untyped selector. |
| 1454 if (node.name.isPrivate()) return defaultSelector; | 1455 if (defaultSelector.name.isPrivate()) return defaultSelector; |
| 1455 HType receiverHType = types[node.inputs[0]]; | 1456 HType receiverHType = types[node.inputs[0]]; |
| 1456 Type receiverType = receiverHType.computeType(compiler); | 1457 Type receiverType = receiverHType.computeType(compiler); |
| 1457 if (receiverType !== null) { | 1458 if (receiverType !== null) { |
| 1458 return new TypedSelector(receiverType, defaultSelector); | 1459 return new TypedSelector(receiverType, defaultSelector); |
| 1459 } else { | 1460 } else { |
| 1460 return defaultSelector; | 1461 return defaultSelector; |
| 1461 } | 1462 } |
| 1462 } | 1463 } |
| 1463 | 1464 |
| 1464 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 1465 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 1465 use(node.receiver); | 1466 use(node.receiver); |
| 1466 push(jsPropertyCall(pop(), | 1467 Selector setter = node.selector; |
| 1467 compiler.namer.setterName(currentLibrary, node.name), | 1468 String name = compiler.namer.setterName(setter.library, setter.name); |
| 1468 visitArguments(node.inputs)), | 1469 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); |
| 1469 node); | |
| 1470 Selector setter = new Selector.setter(node.name, currentLibrary); | |
| 1471 world.registerDynamicSetter( | 1470 world.registerDynamicSetter( |
| 1472 node.name, getOptimizedSelectorFor(node, setter)); | 1471 setter.name, getOptimizedSelectorFor(node, setter)); |
| 1473 } | 1472 } |
| 1474 | 1473 |
| 1475 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 1474 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
| 1476 use(node.receiver); | 1475 use(node.receiver); |
| 1477 push(jsPropertyCall(pop(), | 1476 Selector getter = node.selector; |
| 1478 compiler.namer.getterName(currentLibrary, node.name), | 1477 String name = compiler.namer.getterName(getter.library, getter.name); |
| 1479 visitArguments(node.inputs)), | 1478 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); |
| 1480 node); | |
| 1481 Selector getter = new Selector.getter(node.name, currentLibrary); | |
| 1482 world.registerDynamicGetter( | 1479 world.registerDynamicGetter( |
| 1483 node.name, getOptimizedSelectorFor(node, getter)); | 1480 getter.name, getOptimizedSelectorFor(node, getter)); |
| 1484 } | 1481 } |
| 1485 | 1482 |
| 1486 visitInvokeClosure(HInvokeClosure node) { | 1483 visitInvokeClosure(HInvokeClosure node) { |
| 1487 use(node.receiver); | 1484 use(node.receiver); |
| 1488 push(jsPropertyCall(pop(), | 1485 push(jsPropertyCall(pop(), |
| 1489 compiler.namer.closureInvocationName(node.selector), | 1486 compiler.namer.closureInvocationName(node.selector), |
| 1490 visitArguments(node.inputs)), | 1487 visitArguments(node.inputs)), |
| 1491 node); | 1488 node); |
| 1492 Selector call = new Selector.callClosureFrom(node.selector); | 1489 Selector call = new Selector.callClosureFrom(node.selector); |
| 1493 world.registerDynamicInvocation(call.name, call); | 1490 world.registerDynamicInvocation(call.name, call); |
| (...skipping 1415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2909 if (leftType.canBeNull() && rightType.canBeNull()) { | 2906 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2910 if (left.isConstantNull() || right.isConstantNull() || | 2907 if (left.isConstantNull() || right.isConstantNull() || |
| 2911 (leftType.isPrimitive() && leftType == rightType)) { | 2908 (leftType.isPrimitive() && leftType == rightType)) { |
| 2912 return '=='; | 2909 return '=='; |
| 2913 } | 2910 } |
| 2914 return null; | 2911 return null; |
| 2915 } else { | 2912 } else { |
| 2916 return '==='; | 2913 return '==='; |
| 2917 } | 2914 } |
| 2918 } | 2915 } |
| OLD | NEW |