|
66 | 66 | import com.oracle.truffle.api.dsl.Bind;
|
67 | 67 | import com.oracle.truffle.api.dsl.Cached;
|
68 | 68 | import com.oracle.truffle.api.dsl.Specialization;
|
| 69 | +import com.oracle.truffle.api.dsl.Cached.Shared; |
69 | 70 | import com.oracle.truffle.api.frame.FrameDescriptor;
|
70 | 71 | import com.oracle.truffle.api.frame.FrameSlotTypeException;
|
71 | 72 | import com.oracle.truffle.api.frame.VirtualFrame;
|
| 73 | +import com.oracle.truffle.api.nodes.Node; |
72 | 74 | import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
73 | 75 |
|
74 | 76 | public class BoxingEliminationTest extends AbstractInstructionTest {
|
@@ -1515,6 +1517,61 @@ public void testRewriteCastLong() {
|
1515 | 1517 | assertStable(quickenings, node, "");
|
1516 | 1518 | }
|
1517 | 1519 |
|
| 1520 | + @Test |
| 1521 | + public void testTimesTwo() { |
| 1522 | + BoxingEliminationTestRootNode node = parse(b -> { |
| 1523 | + b.beginRoot(); |
| 1524 | + b.beginReturn(); |
| 1525 | + b.beginAbs(); |
| 1526 | + b.beginTimesTwo(); |
| 1527 | + b.emitLoadArgument(0); |
| 1528 | + b.endTimesTwo(); |
| 1529 | + b.endAbs(); |
| 1530 | + b.endReturn(); |
| 1531 | + b.endRoot(); |
| 1532 | + }); |
| 1533 | + |
| 1534 | + assertQuickenings(node, 0, 0); |
| 1535 | + assertInstructions(node, |
| 1536 | + "load.argument", |
| 1537 | + "c.TimesTwo", |
| 1538 | + "c.Abs", |
| 1539 | + "return"); |
| 1540 | + assertEquals(42L, node.getCallTarget().call(-21L)); |
| 1541 | + assertInstructions(node, |
| 1542 | + "load.argument", |
| 1543 | + "c.TimesTwo$long", |
| 1544 | + "c.Abs$LessThanZero", |
| 1545 | + "return"); |
| 1546 | + |
| 1547 | + assertEquals(42L, node.getCallTarget().call(21L)); |
| 1548 | + |
| 1549 | + assertInstructions(node, |
| 1550 | + "load.argument", |
| 1551 | + "c.TimesTwo$long", |
| 1552 | + "c.Abs$GreaterZero#LessThanZero", |
| 1553 | + "return"); |
| 1554 | + |
| 1555 | + assertEquals(42, node.getCallTarget().call(-21)); |
| 1556 | + assertInstructions(node, |
| 1557 | + "load.argument", |
| 1558 | + "c.TimesTwo$Generic", |
| 1559 | + "c.Abs", |
| 1560 | + "return"); |
| 1561 | + |
| 1562 | + assertEquals("lala", node.getCallTarget().call("la")); |
| 1563 | + assertInstructions(node, |
| 1564 | + "load.argument", |
| 1565 | + "c.TimesTwo$Generic", |
| 1566 | + "c.Abs", |
| 1567 | + "return"); |
| 1568 | + |
| 1569 | + var quickenings = assertQuickenings(node, 9, 5); |
| 1570 | + assertStable(quickenings, node, 42); |
| 1571 | + assertStable(quickenings, node, 42L); |
| 1572 | + assertStable(quickenings, node, "la"); |
| 1573 | + } |
| 1574 | + |
1518 | 1575 | @Test
|
1519 | 1576 | public void testBinarySubscriptInt() {
|
1520 | 1577 | BoxingEliminationTestRootNode node = parse(b -> {
|
@@ -2016,6 +2073,67 @@ public static Object doObject(Object obj) {
|
2016 | 2073 | }
|
2017 | 2074 | }
|
2018 | 2075 |
|
| 2076 | + @Operation |
| 2077 | + public static final class TimesTwo { |
| 2078 | + |
| 2079 | + @Specialization(rewriteOn = UnexpectedResultException.class) |
| 2080 | + public static int doInt(Object obj, @Cached @Shared TimesTwoNode doubleNode) throws UnexpectedResultException { |
| 2081 | + return doubleNode.executeInt(obj); |
| 2082 | + } |
| 2083 | + |
| 2084 | + @Specialization(rewriteOn = UnexpectedResultException.class) |
| 2085 | + public static long doLong(Object obj, @Cached @Shared TimesTwoNode doubleNode) throws UnexpectedResultException { |
| 2086 | + return doubleNode.executeLong(obj); |
| 2087 | + } |
| 2088 | + |
| 2089 | + @Specialization(replaces = {"doInt", "doLong"}) |
| 2090 | + public static Object doObject(Object obj, @Cached @Shared TimesTwoNode doubleNode) { |
| 2091 | + return doubleNode.executeObject(obj); |
| 2092 | + } |
| 2093 | + |
| 2094 | + @SuppressWarnings("truffle-inlining") |
| 2095 | + abstract static class TimesTwoNode extends Node { |
| 2096 | + |
| 2097 | + int executeInt(Object x) throws UnexpectedResultException { |
| 2098 | + Object result = executeObject(x); |
| 2099 | + if (result instanceof Integer i) { |
| 2100 | + return i; |
| 2101 | + } |
| 2102 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 2103 | + throw new UnexpectedResultException(result); |
| 2104 | + } |
| 2105 | + |
| 2106 | + long executeLong(Object x) throws UnexpectedResultException { |
| 2107 | + Object result = executeObject(x); |
| 2108 | + if (result instanceof Long l) { |
| 2109 | + return l; |
| 2110 | + } |
| 2111 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 2112 | + throw new UnexpectedResultException(result); |
| 2113 | + } |
| 2114 | + |
| 2115 | + abstract Object executeObject(Object x); |
| 2116 | + |
| 2117 | + @Specialization |
| 2118 | + public int doInt(int x) { |
| 2119 | + return x + x; |
| 2120 | + } |
| 2121 | + |
| 2122 | + @Specialization |
| 2123 | + public long doLong(long x) { |
| 2124 | + return x + x; |
| 2125 | + } |
| 2126 | + |
| 2127 | + @Specialization |
| 2128 | + @TruffleBoundary |
| 2129 | + public Object doObject(Object x) { |
| 2130 | + String asString = x.toString(); |
| 2131 | + return asString + asString; |
| 2132 | + } |
| 2133 | + } |
| 2134 | + |
| 2135 | + } |
| 2136 | + |
2019 | 2137 | @Operation
|
2020 | 2138 | @ConstantOperand(type = LocalAccessor.class)
|
2021 | 2139 | public static final class LoadLocalCustom {
|
|
0 commit comments