| 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 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 if (inLoop) backend.builder.functionsCalledInLoop.add(node.element); | 1413 if (inLoop) backend.builder.functionsCalledInLoop.add(node.element); |
| 1414 world.registerDynamicInvocationOf(node.element); | 1414 world.registerDynamicInvocationOf(node.element); |
| 1415 } else { | 1415 } else { |
| 1416 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector; | 1416 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector; |
| 1417 world.registerDynamicInvocation(node.name, selector); | 1417 world.registerDynamicInvocation(node.name, selector); |
| 1418 } | 1418 } |
| 1419 } | 1419 } |
| 1420 push(jsPropertyCall(object, methodName, arguments), node); | 1420 push(jsPropertyCall(object, methodName, arguments), node); |
| 1421 } | 1421 } |
| 1422 | 1422 |
| 1423 Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) { | 1423 Selector getOptimizedSelectorFor(HInvokeDynamic node, |
| 1424 Selector defaultSelector) { |
| 1424 // TODO(4434): For private members we need to use the untyped selector. | 1425 // TODO(4434): For private members we need to use the untyped selector. |
| 1425 if (node.name.isPrivate()) return defaultSelector; | 1426 if (node.name.isPrivate()) return defaultSelector; |
| 1426 Type receiverType = node.inputs[0].propagatedType.computeType(compiler); | 1427 Type receiverType = node.inputs[0].propagatedType.computeType(compiler); |
| 1427 if (receiverType !== null) { | 1428 if (receiverType !== null) { |
| 1428 return new TypedSelector(receiverType, defaultSelector); | 1429 return new TypedSelector(receiverType, defaultSelector); |
| 1429 } else { | 1430 } else { |
| 1430 return defaultSelector; | 1431 return defaultSelector; |
| 1431 } | 1432 } |
| 1432 } | 1433 } |
| 1433 | 1434 |
| 1434 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 1435 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 1435 use(node.receiver); | 1436 use(node.receiver); |
| 1436 push(jsPropertyCall(pop(), | 1437 push(jsPropertyCall(pop(), |
| 1437 compiler.namer.setterName(currentLibrary, node.name), | 1438 compiler.namer.setterName(currentLibrary, node.name), |
| 1438 visitArguments(node.inputs)), | 1439 visitArguments(node.inputs)), |
| 1439 node); | 1440 node); |
| 1441 Selector setter = new Selector.setter(node.name, currentLibrary); |
| 1440 world.registerDynamicSetter( | 1442 world.registerDynamicSetter( |
| 1441 node.name, getOptimizedSelectorFor(node, Selector.SETTER)); | 1443 node.name, getOptimizedSelectorFor(node, setter)); |
| 1442 } | 1444 } |
| 1443 | 1445 |
| 1444 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 1446 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
| 1445 use(node.receiver); | 1447 use(node.receiver); |
| 1446 push(jsPropertyCall(pop(), | 1448 push(jsPropertyCall(pop(), |
| 1447 compiler.namer.getterName(currentLibrary, node.name), | 1449 compiler.namer.getterName(currentLibrary, node.name), |
| 1448 visitArguments(node.inputs)), | 1450 visitArguments(node.inputs)), |
| 1449 node); | 1451 node); |
| 1452 Selector getter = new Selector.getter(node.name, currentLibrary); |
| 1450 world.registerDynamicGetter( | 1453 world.registerDynamicGetter( |
| 1451 node.name, getOptimizedSelectorFor(node, Selector.GETTER)); | 1454 node.name, getOptimizedSelectorFor(node, getter)); |
| 1452 } | 1455 } |
| 1453 | 1456 |
| 1454 visitInvokeClosure(HInvokeClosure node) { | 1457 visitInvokeClosure(HInvokeClosure node) { |
| 1455 use(node.receiver); | 1458 use(node.receiver); |
| 1456 push(jsPropertyCall(pop(), | 1459 push(jsPropertyCall(pop(), |
| 1457 compiler.namer.closureInvocationName(node.selector), | 1460 compiler.namer.closureInvocationName(node.selector), |
| 1458 visitArguments(node.inputs)), | 1461 visitArguments(node.inputs)), |
| 1459 node); | 1462 node); |
| 1460 // TODO(floitsch): we should have a separate list for closure invocations. | 1463 // TODO(floitsch): we should have a separate list for closure invocations. |
| 1464 Selector call = new Selector.call( |
| 1465 compiler.namer.CLOSURE_INVOCATION_NAME, |
| 1466 node.selector.library, |
| 1467 node.selector.argumentCount, |
| 1468 node.selector.namedArguments); |
| 1461 world.registerDynamicInvocation(compiler.namer.CLOSURE_INVOCATION_NAME, | 1469 world.registerDynamicInvocation(compiler.namer.CLOSURE_INVOCATION_NAME, |
| 1462 node.selector); | 1470 call); |
| 1463 } | 1471 } |
| 1464 | 1472 |
| 1465 visitInvokeStatic(HInvokeStatic node) { | 1473 visitInvokeStatic(HInvokeStatic node) { |
| 1466 use(node.target); | 1474 use(node.target); |
| 1467 push(new js.Call(pop(), visitArguments(node.inputs)), node); | 1475 push(new js.Call(pop(), visitArguments(node.inputs)), node); |
| 1468 } | 1476 } |
| 1469 | 1477 |
| 1470 visitInvokeSuper(HInvokeSuper node) { | 1478 visitInvokeSuper(HInvokeSuper node) { |
| 1471 Element superMethod = node.element; | 1479 Element superMethod = node.element; |
| 1472 Element superClass = superMethod.getEnclosingClass(); | 1480 Element superClass = superMethod.getEnclosingClass(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1510 | 1518 |
| 1511 visitFieldGet(HFieldGet node) { | 1519 visitFieldGet(HFieldGet node) { |
| 1512 String name = | 1520 String name = |
| 1513 compiler.namer.instanceFieldName(node.library, node.fieldName); | 1521 compiler.namer.instanceFieldName(node.library, node.fieldName); |
| 1514 use(node.receiver); | 1522 use(node.receiver); |
| 1515 push(new js.PropertyAccess.field(pop(), name), node); | 1523 push(new js.PropertyAccess.field(pop(), name), node); |
| 1516 if (node.element == null) { | 1524 if (node.element == null) { |
| 1517 // If we don't have an element we register a dynamic field getter. | 1525 // If we don't have an element we register a dynamic field getter. |
| 1518 // This might lead to unnecessary getters, but these cases should be | 1526 // This might lead to unnecessary getters, but these cases should be |
| 1519 // rare. | 1527 // rare. |
| 1520 world.registerDynamicGetter(node.fieldName, Selector.GETTER); | 1528 Selector getter = new Selector.getter(node.fieldName, node.library); |
| 1529 world.registerDynamicGetter(node.fieldName, getter); |
| 1521 } else { | 1530 } else { |
| 1522 Type type = node.receiver.propagatedType.computeType(compiler); | 1531 Type type = node.receiver.propagatedType.computeType(compiler); |
| 1523 if (type != null) { | 1532 if (type != null) { |
| 1524 world.registerFieldGetter(node.element.name, type); | 1533 world.registerFieldGetter(node.element.name, node.library, type); |
| 1525 } | 1534 } |
| 1526 } | 1535 } |
| 1527 } | 1536 } |
| 1528 | 1537 |
| 1529 // Determine if an instruction is a simple number computation | 1538 // Determine if an instruction is a simple number computation |
| 1530 // involving only things with guaranteed number types and a given | 1539 // involving only things with guaranteed number types and a given |
| 1531 // field. | 1540 // field. |
| 1532 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) { | 1541 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) { |
| 1533 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true; | 1542 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true; |
| 1534 if (value is HBinaryArithmetic) { | 1543 if (value is HBinaryArithmetic) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1547 node.block.dominates(currentGraph.exit)) { | 1556 node.block.dominates(currentGraph.exit)) { |
| 1548 backend.updateFieldConstructorSetters(node.element, | 1557 backend.updateFieldConstructorSetters(node.element, |
| 1549 node.value.guaranteedType); | 1558 node.value.guaranteedType); |
| 1550 } | 1559 } |
| 1551 String name = | 1560 String name = |
| 1552 compiler.namer.instanceFieldName(node.library, node.fieldName); | 1561 compiler.namer.instanceFieldName(node.library, node.fieldName); |
| 1553 if (node.element == null) { | 1562 if (node.element == null) { |
| 1554 // If we don't have an element we register a dynamic field setter. | 1563 // If we don't have an element we register a dynamic field setter. |
| 1555 // This might lead to unnecessary setters, but these cases should be | 1564 // This might lead to unnecessary setters, but these cases should be |
| 1556 // rare. | 1565 // rare. |
| 1557 world.registerDynamicSetter(node.fieldName, Selector.SETTER); | 1566 Selector setter = new Selector.setter(node.fieldName, node.library); |
| 1567 world.registerDynamicSetter(node.fieldName, setter); |
| 1558 } else { | 1568 } else { |
| 1559 Type type = node.receiver.propagatedType.computeType(compiler); | 1569 Type type = node.receiver.propagatedType.computeType(compiler); |
| 1560 if (type != null) { | 1570 if (type != null) { |
| 1561 if (!work.element.isGenerativeConstructorBody()) { | 1571 if (!work.element.isGenerativeConstructorBody()) { |
| 1562 world.registerFieldSetter(node.element.name, type); | 1572 world.registerFieldSetter(node.element.name, node.library, type); |
| 1563 } | 1573 } |
| 1564 // Determine the types seen so far for the field. If only number | 1574 // Determine the types seen so far for the field. If only number |
| 1565 // types have been seen and the value of the field set is a | 1575 // types have been seen and the value of the field set is a |
| 1566 // simple number computation only depending on that field, we | 1576 // simple number computation only depending on that field, we |
| 1567 // can safely keep the number type for the field. | 1577 // can safely keep the number type for the field. |
| 1568 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element); | 1578 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element); |
| 1569 HType initializersType = | 1579 HType initializersType = |
| 1570 backend.typeFromInitializersSoFar(node.element); | 1580 backend.typeFromInitializersSoFar(node.element); |
| 1571 HType fieldType = fieldSettersType.union(initializersType); | 1581 HType fieldType = fieldSettersType.union(initializersType); |
| 1572 if (HType.NUMBER.union(fieldType) == HType.NUMBER && | 1582 if (HType.NUMBER.union(fieldType) == HType.NUMBER && |
| (...skipping 1274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2847 if (leftType.canBeNull() && rightType.canBeNull()) { | 2857 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2848 if (left.isConstantNull() || right.isConstantNull() || | 2858 if (left.isConstantNull() || right.isConstantNull() || |
| 2849 (leftType.isPrimitive() && leftType == rightType)) { | 2859 (leftType.isPrimitive() && leftType == rightType)) { |
| 2850 return '=='; | 2860 return '=='; |
| 2851 } | 2861 } |
| 2852 return null; | 2862 return null; |
| 2853 } else { | 2863 } else { |
| 2854 return '==='; | 2864 return '==='; |
| 2855 } | 2865 } |
| 2856 } | 2866 } |
| OLD | NEW |