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 ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
8 | 8 |
9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
10 | 10 |
(...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1519 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), | 1519 return new js.Call(new js.PropertyAccess.field(receiver, fieldName), |
1520 arguments); | 1520 arguments); |
1521 } | 1521 } |
1522 | 1522 |
1523 // TODO(ngeoffray): Once we remove the old interceptors, we can | 1523 // TODO(ngeoffray): Once we remove the old interceptors, we can |
1524 // start using HInvokeInterceptor to represent interceptor calls on | 1524 // start using HInvokeInterceptor to represent interceptor calls on |
1525 // an Interceptor class. Currently we recognize if a call is a call | 1525 // an Interceptor class. Currently we recognize if a call is a call |
1526 // on an interceptor by checking if the arguments in the inputs list | 1526 // on an interceptor by checking if the arguments in the inputs list |
1527 // is one more than the arguments in the selector. The extra | 1527 // is one more than the arguments in the selector. The extra |
1528 // argument in an interceptor call is the actual receiver. | 1528 // argument in an interceptor call is the actual receiver. |
1529 bool isInterceptorCall(HInvokeDynamicMethod node) { | 1529 bool isInterceptorCall(HInvokeDynamic node) { |
1530 return node.inputs.length - 1 != node.selector.argumentCount; | 1530 return node.inputs.length - 1 != node.selector.argumentCount; |
1531 } | 1531 } |
1532 | 1532 |
1533 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 1533 visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
1534 use(node.receiver); | 1534 use(node.receiver); |
1535 js.Expression object = pop(); | 1535 js.Expression object = pop(); |
1536 SourceString name = node.selector.name; | 1536 SourceString name = node.selector.name; |
1537 String methodName; | 1537 String methodName; |
1538 List<js.Expression> arguments; | 1538 List<js.Expression> arguments; |
1539 Element target = node.element; | 1539 Element target = node.element; |
(...skipping 11 matching lines...) Expand all Loading... |
1551 | 1551 |
1552 // Register this invocation to collect the types used at all call sites. | 1552 // Register this invocation to collect the types used at all call sites. |
1553 Selector selector = getOptimizedSelectorFor(node, node.selector); | 1553 Selector selector = getOptimizedSelectorFor(node, node.selector); |
1554 // TODO(ngeoffray): Remove the following restriction. Because | 1554 // TODO(ngeoffray): Remove the following restriction. Because |
1555 // the second input of this interceptor call is the actual | 1555 // the second input of this interceptor call is the actual |
1556 // receiver (the first is the interceptor), the backend gets | 1556 // receiver (the first is the interceptor), the backend gets |
1557 // confused. We should pass a list of types instead of a node to | 1557 // confused. We should pass a list of types instead of a node to |
1558 // [registerDynamicInvocation]. | 1558 // [registerDynamicInvocation]. |
1559 if (!isInterceptorCall(node)) { | 1559 if (!isInterceptorCall(node)) { |
1560 backend.registerDynamicInvocation(node, selector, types); | 1560 backend.registerDynamicInvocation(node, selector, types); |
| 1561 } else { |
| 1562 backend.addInterceptedSelector(selector); |
1561 } | 1563 } |
1562 | 1564 |
1563 // If we don't know what we're calling or if we are calling a getter, | 1565 // If we don't know what we're calling or if we are calling a getter, |
1564 // we need to register that fact that we may be calling a closure | 1566 // we need to register that fact that we may be calling a closure |
1565 // with the same arguments. | 1567 // with the same arguments. |
1566 if (target == null || target.isGetter()) { | 1568 if (target == null || target.isGetter()) { |
1567 // TODO(kasperl): If we have a typed selector for the call, we | 1569 // TODO(kasperl): If we have a typed selector for the call, we |
1568 // may know something about the types of closures that need | 1570 // may know something about the types of closures that need |
1569 // the specific closure call method. | 1571 // the specific closure call method. |
1570 Selector call = new Selector.callClosureFrom(selector); | 1572 Selector call = new Selector.callClosureFrom(selector); |
(...skipping 10 matching lines...) Expand all Loading... |
1581 world.registerDynamicInvocation(name, selector); | 1583 world.registerDynamicInvocation(name, selector); |
1582 } | 1584 } |
1583 } | 1585 } |
1584 push(jsPropertyCall(object, methodName, arguments), node); | 1586 push(jsPropertyCall(object, methodName, arguments), node); |
1585 } | 1587 } |
1586 | 1588 |
1587 Selector getOptimizedSelectorFor(HInvokeDynamic node, | 1589 Selector getOptimizedSelectorFor(HInvokeDynamic node, |
1588 Selector defaultSelector) { | 1590 Selector defaultSelector) { |
1589 // TODO(4434): For private members we need to use the untyped selector. | 1591 // TODO(4434): For private members we need to use the untyped selector. |
1590 if (defaultSelector.name.isPrivate()) return defaultSelector; | 1592 if (defaultSelector.name.isPrivate()) return defaultSelector; |
| 1593 // TODO(ngeoffray): Type intercepted calls. |
| 1594 if (isInterceptorCall(node)) return defaultSelector; |
1591 // If [JSInvocationMirror.invokeOn] has been called, we must not create a | 1595 // If [JSInvocationMirror.invokeOn] has been called, we must not create a |
1592 // typed selector based on the receiver type. | 1596 // typed selector based on the receiver type. |
1593 if (node.element == null && // Invocation is not exact. | 1597 if (node.element == null && // Invocation is not exact. |
1594 backend.compiler.enabledInvokeOn) { | 1598 backend.compiler.enabledInvokeOn) { |
1595 return defaultSelector; | 1599 return defaultSelector; |
1596 } | 1600 } |
1597 HType receiverHType = types[node.inputs[0]]; | 1601 HType receiverHType = types[node.inputs[0]]; |
1598 DartType receiverType = receiverHType.computeType(compiler); | 1602 DartType receiverType = receiverHType.computeType(compiler); |
1599 if (receiverType != null) { | 1603 if (receiverType != null) { |
1600 return new TypedSelector(receiverType, defaultSelector); | 1604 return new TypedSelector(receiverType, defaultSelector); |
(...skipping 12 matching lines...) Expand all Loading... |
1613 backend.addedDynamicSetter(selector, types[node.inputs[1]]); | 1617 backend.addedDynamicSetter(selector, types[node.inputs[1]]); |
1614 } | 1618 } |
1615 | 1619 |
1616 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 1620 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
1617 use(node.receiver); | 1621 use(node.receiver); |
1618 Selector getter = node.selector; | 1622 Selector getter = node.selector; |
1619 String name = backend.namer.getterName(getter.library, getter.name); | 1623 String name = backend.namer.getterName(getter.library, getter.name); |
1620 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); | 1624 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); |
1621 world.registerDynamicGetter( | 1625 world.registerDynamicGetter( |
1622 getter.name, getOptimizedSelectorFor(node, getter)); | 1626 getter.name, getOptimizedSelectorFor(node, getter)); |
| 1627 if (isInterceptorCall(node)) { |
| 1628 backend.addInterceptedSelector(getter); |
| 1629 } |
1623 } | 1630 } |
1624 | 1631 |
1625 visitInvokeClosure(HInvokeClosure node) { | 1632 visitInvokeClosure(HInvokeClosure node) { |
1626 use(node.receiver); | 1633 use(node.receiver); |
1627 push(jsPropertyCall(pop(), | 1634 push(jsPropertyCall(pop(), |
1628 backend.namer.closureInvocationName(node.selector), | 1635 backend.namer.closureInvocationName(node.selector), |
1629 visitArguments(node.inputs)), | 1636 visitArguments(node.inputs)), |
1630 node); | 1637 node); |
1631 Selector call = new Selector.callClosureFrom(node.selector); | 1638 Selector call = new Selector.callClosureFrom(node.selector); |
1632 world.registerDynamicInvocation(call.name, call); | 1639 world.registerDynamicInvocation(call.name, call); |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 HInstruction input = node.inputs[0]; | 1983 HInstruction input = node.inputs[0]; |
1977 if (input.isConstantNull()) { | 1984 if (input.isConstantNull()) { |
1978 pushStatement(new js.Return(null), node); | 1985 pushStatement(new js.Return(null), node); |
1979 } else { | 1986 } else { |
1980 use(node.inputs[0]); | 1987 use(node.inputs[0]); |
1981 pushStatement(new js.Return(pop()), node); | 1988 pushStatement(new js.Return(pop()), node); |
1982 } | 1989 } |
1983 } | 1990 } |
1984 | 1991 |
1985 visitThis(HThis node) { | 1992 visitThis(HThis node) { |
1986 if (backend.isInterceptorClass(work.element.getEnclosingClass())){ | 1993 push(new js.This()); |
1987 push(new js.VariableUse(variableNames.getName(node)), node); | |
1988 } else { | |
1989 push(new js.This()); | |
1990 } | |
1991 } | 1994 } |
1992 | 1995 |
1993 visitThrow(HThrow node) { | 1996 visitThrow(HThrow node) { |
1994 if (node.isRethrow) { | 1997 if (node.isRethrow) { |
1995 use(node.inputs[0]); | 1998 use(node.inputs[0]); |
1996 pushStatement(new js.Throw(pop()), node); | 1999 pushStatement(new js.Throw(pop()), node); |
1997 } else { | 2000 } else { |
1998 generateThrowWithHelper(r'$throw', node.inputs[0]); | 2001 generateThrowWithHelper(r'$throw', node.inputs[0]); |
1999 } | 2002 } |
2000 } | 2003 } |
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3101 if (leftType.canBeNull() && rightType.canBeNull()) { | 3104 if (leftType.canBeNull() && rightType.canBeNull()) { |
3102 if (left.isConstantNull() || right.isConstantNull() || | 3105 if (left.isConstantNull() || right.isConstantNull() || |
3103 (leftType.isPrimitive() && leftType == rightType)) { | 3106 (leftType.isPrimitive() && leftType == rightType)) { |
3104 return '=='; | 3107 return '=='; |
3105 } | 3108 } |
3106 return null; | 3109 return null; |
3107 } else { | 3110 } else { |
3108 return '==='; | 3111 return '==='; |
3109 } | 3112 } |
3110 } | 3113 } |
OLD | NEW |