| 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 Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 HBasicBlock newBlock = addNewBlock(); | 1158 HBasicBlock newBlock = addNewBlock(); |
| 1159 if (!isAborted()) goto(current, newBlock); | 1159 if (!isAborted()) goto(current, newBlock); |
| 1160 open(newBlock); | 1160 open(newBlock); |
| 1161 return newBlock; | 1161 return newBlock; |
| 1162 } | 1162 } |
| 1163 | 1163 |
| 1164 void add(HInstruction instruction) { | 1164 void add(HInstruction instruction) { |
| 1165 current.add(instruction); | 1165 current.add(instruction); |
| 1166 } | 1166 } |
| 1167 | 1167 |
| 1168 void addWithPosition(HInstruction instruction, Node node) { |
| 1169 add(attachPosition(instruction, node)); |
| 1170 } |
| 1171 |
| 1168 void push(HInstruction instruction) { | 1172 void push(HInstruction instruction) { |
| 1169 add(instruction); | 1173 add(instruction); |
| 1170 stack.add(instruction); | 1174 stack.add(instruction); |
| 1171 } | 1175 } |
| 1172 | 1176 |
| 1177 void pushWithPosition(HInstruction instruction, Node node) { |
| 1178 push(attachPosition(instruction, node)); |
| 1179 } |
| 1180 |
| 1173 HInstruction pop() { | 1181 HInstruction pop() { |
| 1174 return stack.removeLast(); | 1182 return stack.removeLast(); |
| 1175 } | 1183 } |
| 1176 | 1184 |
| 1177 void dup() { | 1185 void dup() { |
| 1178 stack.add(stack.last()); | 1186 stack.add(stack.last()); |
| 1179 } | 1187 } |
| 1180 | 1188 |
| 1181 HBoolify popBoolified() { | 1189 HBoolify popBoolified() { |
| 1182 HBoolify boolified = new HBoolify(pop()); | 1190 HBoolify boolified = new HBoolify(pop()); |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1583 node.receiver, | 1591 node.receiver, |
| 1584 () { visit(node.argumentsNode); }, | 1592 () { visit(node.argumentsNode); }, |
| 1585 isAnd: (const SourceString("&&") == op.source)); | 1593 isAnd: (const SourceString("&&") == op.source)); |
| 1586 } | 1594 } |
| 1587 | 1595 |
| 1588 | 1596 |
| 1589 void visitLogicalNot(Send node) { | 1597 void visitLogicalNot(Send node) { |
| 1590 assert(node.argumentsNode is Prefix); | 1598 assert(node.argumentsNode is Prefix); |
| 1591 visit(node.receiver); | 1599 visit(node.receiver); |
| 1592 HNot not = new HNot(popBoolified()); | 1600 HNot not = new HNot(popBoolified()); |
| 1593 push(not); | 1601 pushWithPosition(not, node); |
| 1594 } | 1602 } |
| 1595 | 1603 |
| 1596 void visitUnary(Send node, Operator op) { | 1604 void visitUnary(Send node, Operator op) { |
| 1597 assert(node.argumentsNode is Prefix); | 1605 assert(node.argumentsNode is Prefix); |
| 1598 visit(node.receiver); | 1606 visit(node.receiver); |
| 1599 assert(op.token.kind !== PLUS_TOKEN); | 1607 assert(op.token.kind !== PLUS_TOKEN); |
| 1600 HInstruction operand = pop(); | 1608 HInstruction operand = pop(); |
| 1601 | 1609 |
| 1602 HInstruction target = attachPosition( | 1610 HInstruction target = |
| 1603 new HStatic(interceptors.getPrefixOperatorInterceptor(op)), node); | 1611 new HStatic(interceptors.getPrefixOperatorInterceptor(op)); |
| 1604 add(target); | 1612 add(target); |
| 1605 HInvokeUnary result; | 1613 HInvokeUnary result; |
| 1606 String value = op.source.stringValue; | 1614 String value = op.source.stringValue; |
| 1607 switch (value) { | 1615 switch (value) { |
| 1608 case "-": result = new HNegate(target, operand); break; | 1616 case "-": result = new HNegate(target, operand); break; |
| 1609 case "~": result = new HBitNot(target, operand); break; | 1617 case "~": result = new HBitNot(target, operand); break; |
| 1610 default: | 1618 default: |
| 1611 compiler.internalError('Unexpected unary operator: $value.', node: op); | 1619 compiler.internalError('Unexpected unary operator: $value.', node: op); |
| 1612 break; | 1620 break; |
| 1613 } | 1621 } |
| 1614 // See if we can constant-fold right away. This avoids rewrites later on. | 1622 // See if we can constant-fold right away. This avoids rewrites later on. |
| 1615 if (operand is HConstant) { | 1623 if (operand is HConstant) { |
| 1616 HConstant constant = operand; | 1624 HConstant constant = operand; |
| 1617 Constant folded = result.operation.fold(constant.constant); | 1625 Constant folded = result.operation.fold(constant.constant); |
| 1618 if (folded !== null) { | 1626 if (folded !== null) { |
| 1619 stack.add(graph.addConstant(folded)); | 1627 stack.add(graph.addConstant(folded)); |
| 1620 return; | 1628 return; |
| 1621 } | 1629 } |
| 1622 } | 1630 } |
| 1623 push(result); | 1631 pushWithPosition(result, node); |
| 1624 } | 1632 } |
| 1625 | 1633 |
| 1626 void visitBinary(HInstruction left, Operator op, HInstruction right) { | 1634 void visitBinary(HInstruction left, Operator op, HInstruction right) { |
| 1627 Element element = interceptors.getOperatorInterceptor(op); | 1635 Element element = interceptors.getOperatorInterceptor(op); |
| 1628 assert(element != null); | 1636 assert(element != null); |
| 1629 HInstruction target = new HStatic(element); | 1637 HInstruction target = new HStatic(element); |
| 1630 add(target); | 1638 add(target); |
| 1631 switch (op.source.stringValue) { | 1639 switch (op.source.stringValue) { |
| 1632 case "+": | 1640 case "+": |
| 1633 case "++": | 1641 case "++": |
| 1634 case "+=": | 1642 case "+=": |
| 1635 push(new HAdd(target, left, right)); | 1643 pushWithPosition(new HAdd(target, left, right), op); |
| 1636 break; | 1644 break; |
| 1637 case "-": | 1645 case "-": |
| 1638 case "--": | 1646 case "--": |
| 1639 case "-=": | 1647 case "-=": |
| 1640 push(new HSubtract(target, left, right)); | 1648 pushWithPosition(new HSubtract(target, left, right), op); |
| 1641 break; | 1649 break; |
| 1642 case "*": | 1650 case "*": |
| 1643 case "*=": | 1651 case "*=": |
| 1644 push(new HMultiply(target, left, right)); | 1652 pushWithPosition(new HMultiply(target, left, right), op); |
| 1645 break; | 1653 break; |
| 1646 case "/": | 1654 case "/": |
| 1647 case "/=": | 1655 case "/=": |
| 1648 push(new HDivide(target, left, right)); | 1656 pushWithPosition(new HDivide(target, left, right), op); |
| 1649 break; | 1657 break; |
| 1650 case "~/": | 1658 case "~/": |
| 1651 case "~/=": | 1659 case "~/=": |
| 1652 push(new HTruncatingDivide(target, left, right)); | 1660 pushWithPosition(new HTruncatingDivide(target, left, right), op); |
| 1653 break; | 1661 break; |
| 1654 case "%": | 1662 case "%": |
| 1655 case "%=": | 1663 case "%=": |
| 1656 push(new HModulo(target, left, right)); | 1664 pushWithPosition(new HModulo(target, left, right), op); |
| 1657 break; | 1665 break; |
| 1658 case "<<": | 1666 case "<<": |
| 1659 case "<<=": | 1667 case "<<=": |
| 1660 push(new HShiftLeft(target, left, right)); | 1668 pushWithPosition(new HShiftLeft(target, left, right), op); |
| 1661 break; | 1669 break; |
| 1662 case ">>": | 1670 case ">>": |
| 1663 case ">>=": | 1671 case ">>=": |
| 1664 push(new HShiftRight(target, left, right)); | 1672 pushWithPosition(new HShiftRight(target, left, right), op); |
| 1665 break; | 1673 break; |
| 1666 case "|": | 1674 case "|": |
| 1667 case "|=": | 1675 case "|=": |
| 1668 push(new HBitOr(target, left, right)); | 1676 pushWithPosition(new HBitOr(target, left, right), op); |
| 1669 break; | 1677 break; |
| 1670 case "&": | 1678 case "&": |
| 1671 case "&=": | 1679 case "&=": |
| 1672 push(new HBitAnd(target, left, right)); | 1680 pushWithPosition(new HBitAnd(target, left, right), op); |
| 1673 break; | 1681 break; |
| 1674 case "^": | 1682 case "^": |
| 1675 case "^=": | 1683 case "^=": |
| 1676 push(new HBitXor(target, left, right)); | 1684 pushWithPosition(new HBitXor(target, left, right), op); |
| 1677 break; | 1685 break; |
| 1678 case "==": | 1686 case "==": |
| 1679 push(new HEquals(target, left, right)); | 1687 pushWithPosition(new HEquals(target, left, right), op); |
| 1680 break; | 1688 break; |
| 1681 case "===": | 1689 case "===": |
| 1682 push(new HIdentity(target, left, right)); | 1690 pushWithPosition(new HIdentity(target, left, right), op); |
| 1683 break; | 1691 break; |
| 1684 case "!==": | 1692 case "!==": |
| 1685 HIdentity eq = new HIdentity(target, left, right); | 1693 HIdentity eq = new HIdentity(target, left, right); |
| 1686 add(eq); | 1694 add(eq); |
| 1687 push(new HNot(eq)); | 1695 pushWithPosition(new HNot(eq), op); |
| 1688 break; | 1696 break; |
| 1689 case "<": | 1697 case "<": |
| 1690 push(new HLess(target, left, right)); | 1698 pushWithPosition(new HLess(target, left, right), op); |
| 1691 break; | 1699 break; |
| 1692 case "<=": | 1700 case "<=": |
| 1693 push(new HLessEqual(target, left, right)); | 1701 pushWithPosition(new HLessEqual(target, left, right), op); |
| 1694 break; | 1702 break; |
| 1695 case ">": | 1703 case ">": |
| 1696 push(new HGreater(target, left, right)); | 1704 pushWithPosition(new HGreater(target, left, right), op); |
| 1697 break; | 1705 break; |
| 1698 case ">=": | 1706 case ">=": |
| 1699 push(new HGreaterEqual(target, left, right)); | 1707 pushWithPosition(new HGreaterEqual(target, left, right), op); |
| 1700 break; | 1708 break; |
| 1701 case "!=": | 1709 case "!=": |
| 1702 HEquals eq = new HEquals(target, left, right); | 1710 HEquals eq = new HEquals(target, left, right); |
| 1703 add(eq); | 1711 add(eq); |
| 1704 HBoolify bl = new HBoolify(eq); | 1712 HBoolify bl = new HBoolify(eq); |
| 1705 add(bl); | 1713 add(bl); |
| 1706 push(new HNot(bl)); | 1714 pushWithPosition(new HNot(bl), op); |
| 1707 break; | 1715 break; |
| 1708 default: compiler.unimplemented("SsaBuilder.visitBinary"); | 1716 default: compiler.unimplemented("SsaBuilder.visitBinary"); |
| 1709 } | 1717 } |
| 1710 } | 1718 } |
| 1711 | 1719 |
| 1712 HInstruction generateInstanceSendReceiver(Send send) { | 1720 HInstruction generateInstanceSendReceiver(Send send) { |
| 1713 assert(Elements.isInstanceSend(send, elements)); | 1721 assert(Elements.isInstanceSend(send, elements)); |
| 1714 if (send.receiver == null) { | 1722 if (send.receiver == null) { |
| 1715 return localsHandler.readThis(); | 1723 return localsHandler.readThis(); |
| 1716 } | 1724 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2005 if (node.receiver === null) { | 2013 if (node.receiver === null) { |
| 2006 inputs.add(localsHandler.readThis()); | 2014 inputs.add(localsHandler.readThis()); |
| 2007 } else { | 2015 } else { |
| 2008 visit(node.receiver); | 2016 visit(node.receiver); |
| 2009 inputs.add(pop()); | 2017 inputs.add(pop()); |
| 2010 } | 2018 } |
| 2011 | 2019 |
| 2012 addDynamicSendArgumentsToList(node, inputs); | 2020 addDynamicSendArgumentsToList(node, inputs); |
| 2013 | 2021 |
| 2014 // The first entry in the inputs list is the receiver. | 2022 // The first entry in the inputs list is the receiver. |
| 2015 push(new HInvokeDynamicMethod(selector, dartMethodName, inputs)); | 2023 pushWithPosition(new HInvokeDynamicMethod(selector, dartMethodName, inputs), |
| 2024 node); |
| 2016 | 2025 |
| 2017 if (isNotEquals) { | 2026 if (isNotEquals) { |
| 2018 HNot not = new HNot(popBoolified()); | 2027 HNot not = new HNot(popBoolified()); |
| 2019 push(not); | 2028 push(not); |
| 2020 } | 2029 } |
| 2021 } | 2030 } |
| 2022 | 2031 |
| 2023 visitClosureSend(Send node) { | 2032 visitClosureSend(Send node) { |
| 2024 Selector selector = elements.getSelector(node); | 2033 Selector selector = elements.getSelector(node); |
| 2025 assert(node.receiver === null); | 2034 assert(node.receiver === null); |
| 2026 Element element = elements[node]; | 2035 Element element = elements[node]; |
| 2027 HInstruction closureTarget; | 2036 HInstruction closureTarget; |
| 2028 if (element === null) { | 2037 if (element === null) { |
| 2029 visit(node.selector); | 2038 visit(node.selector); |
| 2030 closureTarget = pop(); | 2039 closureTarget = pop(); |
| 2031 } else { | 2040 } else { |
| 2032 assert(Elements.isLocal(element)); | 2041 assert(Elements.isLocal(element)); |
| 2033 closureTarget = localsHandler.readLocal(element); | 2042 closureTarget = localsHandler.readLocal(element); |
| 2034 } | 2043 } |
| 2035 var inputs = <HInstruction>[]; | 2044 var inputs = <HInstruction>[]; |
| 2036 inputs.add(closureTarget); | 2045 inputs.add(closureTarget); |
| 2037 addDynamicSendArgumentsToList(node, inputs); | 2046 addDynamicSendArgumentsToList(node, inputs); |
| 2038 push(new HInvokeClosure(selector, inputs)); | 2047 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 2039 } | 2048 } |
| 2040 | 2049 |
| 2041 void handleForeignJs(Send node) { | 2050 void handleForeignJs(Send node) { |
| 2042 Link<Node> link = node.arguments; | 2051 Link<Node> link = node.arguments; |
| 2043 // If the invoke is on foreign code, don't visit the first | 2052 // If the invoke is on foreign code, don't visit the first |
| 2044 // argument, which is the type, and the second argument, | 2053 // argument, which is the type, and the second argument, |
| 2045 // which is the foreign code. | 2054 // which is the foreign code. |
| 2046 if (link.isEmpty() || link.isEmpty()) { | 2055 if (link.isEmpty() || link.isEmpty()) { |
| 2047 compiler.cancel('At least two arguments expected', | 2056 compiler.cancel('At least two arguments expected', |
| 2048 node: node.argumentsNode); | 2057 node: node.argumentsNode); |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2276 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2285 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2277 element, inputs); | 2286 element, inputs); |
| 2278 if (!succeeded) { | 2287 if (!succeeded) { |
| 2279 // TODO(ngeoffray): Match the VM behavior and throw an | 2288 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2280 // exception at runtime. | 2289 // exception at runtime. |
| 2281 compiler.cancel('Unimplemented non-matching static call', node: node); | 2290 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2282 } | 2291 } |
| 2283 | 2292 |
| 2284 HType elementType = computeType(element); | 2293 HType elementType = computeType(element); |
| 2285 HInstruction newInstance = new HInvokeStatic(selector, inputs, elementType); | 2294 HInstruction newInstance = new HInvokeStatic(selector, inputs, elementType); |
| 2286 push(newInstance); | 2295 pushWithPosition(newInstance, node); |
| 2287 | 2296 |
| 2288 TypeAnnotation annotation = getTypeAnnotationFromSend(node); | 2297 TypeAnnotation annotation = getTypeAnnotationFromSend(node); |
| 2289 Type type = elements.getType(annotation); | 2298 Type type = elements.getType(annotation); |
| 2290 generateSetRuntimeTypeInformation(newInstance, type); | 2299 generateSetRuntimeTypeInformation(newInstance, type); |
| 2291 } | 2300 } |
| 2292 | 2301 |
| 2293 generateSetRuntimeTypeInformation(HInstruction instance, Type type) { | 2302 generateSetRuntimeTypeInformation(HInstruction instance, Type type) { |
| 2294 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 2303 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
| 2295 String typeString = compiler.codegenWorld.rti.asJsString(type); | 2304 String typeString = compiler.codegenWorld.rti.asJsString(type); |
| 2296 HInstruction typeInfo = new HForeign(new LiteralDartString(typeString), | 2305 HInstruction typeInfo = new HForeign(new LiteralDartString(typeString), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2319 var inputs = <HInstruction>[]; | 2328 var inputs = <HInstruction>[]; |
| 2320 inputs.add(target); | 2329 inputs.add(target); |
| 2321 if (element.kind == ElementKind.FUNCTION) { | 2330 if (element.kind == ElementKind.FUNCTION) { |
| 2322 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2331 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2323 element, inputs); | 2332 element, inputs); |
| 2324 if (!succeeded) { | 2333 if (!succeeded) { |
| 2325 // TODO(ngeoffray): Match the VM behavior and throw an | 2334 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2326 // exception at runtime. | 2335 // exception at runtime. |
| 2327 compiler.cancel('Unimplemented non-matching static call', node: node); | 2336 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2328 } | 2337 } |
| 2329 push(new HInvokeStatic(selector, inputs)); | 2338 pushWithPosition(new HInvokeStatic(selector, inputs), node); |
| 2330 } else { | 2339 } else { |
| 2331 if (element.kind == ElementKind.GETTER) { | 2340 if (element.kind == ElementKind.GETTER) { |
| 2332 target = new HInvokeStatic(Selector.GETTER, inputs); | 2341 target = new HInvokeStatic(Selector.GETTER, inputs); |
| 2333 add(target); | 2342 add(target); |
| 2334 inputs = <HInstruction>[target]; | 2343 inputs = <HInstruction>[target]; |
| 2335 } | 2344 } |
| 2336 addDynamicSendArgumentsToList(node, inputs); | 2345 addDynamicSendArgumentsToList(node, inputs); |
| 2337 push(new HInvokeClosure(selector, inputs)); | 2346 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 2338 } | 2347 } |
| 2339 } | 2348 } |
| 2340 | 2349 |
| 2341 visitGetterSend(Send node) { | 2350 visitGetterSend(Send node) { |
| 2342 generateGetter(node, elements[node]); | 2351 generateGetter(node, elements[node]); |
| 2343 } | 2352 } |
| 2344 | 2353 |
| 2345 // TODO(antonm): migrate rest of SsaBuilder to internalError. | 2354 // TODO(antonm): migrate rest of SsaBuilder to internalError. |
| 2346 internalError(String reason, [Node node]) { | 2355 internalError(String reason, [Node node]) { |
| 2347 compiler.internalError(reason, node: node); | 2356 compiler.internalError(reason, node: node); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2547 native.handleSsaNative(this, node.expression); | 2556 native.handleSsaNative(this, node.expression); |
| 2548 return; | 2557 return; |
| 2549 } | 2558 } |
| 2550 HInstruction value; | 2559 HInstruction value; |
| 2551 if (node.expression === null) { | 2560 if (node.expression === null) { |
| 2552 value = graph.addConstantNull(); | 2561 value = graph.addConstantNull(); |
| 2553 } else { | 2562 } else { |
| 2554 visit(node.expression); | 2563 visit(node.expression); |
| 2555 value = pop(); | 2564 value = pop(); |
| 2556 } | 2565 } |
| 2557 close(new HReturn(value)).addSuccessor(graph.exit); | 2566 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); |
| 2558 } | 2567 } |
| 2559 | 2568 |
| 2560 visitThrow(Throw node) { | 2569 visitThrow(Throw node) { |
| 2561 if (node.expression === null) { | 2570 if (node.expression === null) { |
| 2562 HInstruction exception = rethrowableException; | 2571 HInstruction exception = rethrowableException; |
| 2563 if (exception === null) { | 2572 if (exception === null) { |
| 2564 exception = graph.addConstantNull(); | 2573 exception = graph.addConstantNull(); |
| 2565 compiler.reportError(node, | 2574 compiler.reportError(node, |
| 2566 'throw without expression outside catch block'); | 2575 'throw without expression outside catch block'); |
| 2567 } | 2576 } |
| (...skipping 1006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3574 new HSubGraphBlockInformation(elseBranch.graph)); | 3583 new HSubGraphBlockInformation(elseBranch.graph)); |
| 3575 | 3584 |
| 3576 HBasicBlock conditionStartBlock = conditionBranch.block; | 3585 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 3577 conditionStartBlock.setBlockFlow(info, joinBlock); | 3586 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 3578 SubGraph conditionGraph = conditionBranch.graph; | 3587 SubGraph conditionGraph = conditionBranch.graph; |
| 3579 HIf branch = conditionGraph.end.last; | 3588 HIf branch = conditionGraph.end.last; |
| 3580 assert(branch is HIf); | 3589 assert(branch is HIf); |
| 3581 branch.blockInformation = conditionStartBlock.blockFlow; | 3590 branch.blockInformation = conditionStartBlock.blockFlow; |
| 3582 } | 3591 } |
| 3583 } | 3592 } |
| OLD | NEW |