Mercurial > hg > graal-jvmci-8
changeset 20820:ca57c045b1e8
Truffle: add bytecode interpreter example using virtual dispatch instead of switch
author | Andreas Woess <andreas.woess@oracle.com> |
---|---|
date | Thu, 09 Apr 2015 02:15:16 +0200 |
parents | 42a9e77c68be |
children | 1bfa14fd1275 |
files | graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java |
diffstat | 1 files changed, 213 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java Thu Apr 09 01:26:59 2015 +0200 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/BytecodeInterpreterPartialEvaluationTest.java Thu Apr 09 02:15:16 2015 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.truffle.test; +import java.util.*; + import org.junit.*; import com.oracle.truffle.api.*; @@ -155,11 +157,11 @@ return 42; } - private static void assertReturns42(Program program) { + private static void assertReturns42(RootNode program) { Assert.assertEquals(Integer.valueOf(42), Truffle.getRuntime().createCallTarget(program).call()); } - private void assertPartialEvalEqualsAndRunsCorrect(Program program) { + private void assertPartialEvalEqualsAndRunsCorrect(RootNode program) { assertReturns42(program); assertPartialEvalEquals("constant42", program); } @@ -317,4 +319,213 @@ /* 44: */Bytecode.RETURN}; assertPartialEvalEqualsAndRunsCorrect(new Program("manyIfsProgram", bytecodes, 0, 3)); } + + public abstract static class Inst { + public abstract boolean execute(VirtualFrame frame); + + public abstract int getTrueSucc(); + + public abstract int getFalseSucc(); + + public static class Const extends Inst { + private final FrameSlot slot; + private final int value; + private final int next; + + public Const(FrameSlot slot, int value, int next) { + this.slot = slot; + this.value = value; + this.next = next; + } + + @Override + public boolean execute(VirtualFrame frame) { + frame.setInt(slot, value); + return true; + } + + @Override + public int getTrueSucc() { + return next; + } + + @Override + public int getFalseSucc() { + return next; + } + } + + public static class Return extends Inst { + public Return() { + } + + @Override + public boolean execute(VirtualFrame frame) { + return true; + } + + @Override + public int getTrueSucc() { + return -1; + } + + @Override + public int getFalseSucc() { + return -1; + } + } + + public static class IfZero extends Inst { + private final FrameSlot slot; + private final int thenInst; + private final int elseInst; + + public IfZero(FrameSlot slot, int thenInst, int elseInst) { + this.slot = slot; + this.thenInst = thenInst; + this.elseInst = elseInst; + } + + @Override + public boolean execute(VirtualFrame frame) { + return (FrameUtil.getIntSafe(frame, slot) == 0); + } + + @Override + public int getTrueSucc() { + return thenInst; + } + + @Override + public int getFalseSucc() { + return elseInst; + } + } + + public static class IfLt extends Inst { + private final FrameSlot slot1; + private final FrameSlot slot2; + private final int thenInst; + private final int elseInst; + + public IfLt(FrameSlot slot1, FrameSlot slot2, int thenInst, int elseInst) { + this.slot1 = slot1; + this.slot2 = slot2; + this.thenInst = thenInst; + this.elseInst = elseInst; + } + + @Override + public boolean execute(VirtualFrame frame) { + return (FrameUtil.getIntSafe(frame, slot1) < FrameUtil.getIntSafe(frame, slot2)); + } + + @Override + public int getTrueSucc() { + return thenInst; + } + + @Override + public int getFalseSucc() { + return elseInst; + } + } + } + + public static class InstArrayProgram extends RootNode { + private final String name; + @CompilationFinal protected final Inst[] inst; + protected final FrameSlot returnSlot; + + public InstArrayProgram(String name, Inst[] inst, FrameSlot returnSlot, FrameDescriptor fd) { + super(null, fd); + this.name = name; + this.inst = inst; + this.returnSlot = returnSlot; + } + + @Override + public String toString() { + return name; + } + + @Override + @ExplodeLoop(merge = true) + public Object execute(VirtualFrame frame) { + int ip = 0; + while (ip != -1) { + CompilerAsserts.partialEvaluationConstant(ip); + if (inst[ip].execute(frame)) { + ip = inst[ip].getTrueSucc(); + } else { + ip = inst[ip].getFalseSucc(); + } + } + return FrameUtil.getIntSafe(frame, returnSlot); + } + } + + @Test + public void instArraySimpleIfProgram() { + FrameDescriptor fd = new FrameDescriptor(); + FrameSlot valueSlot = fd.addFrameSlot("value", FrameSlotKind.Int); + FrameSlot returnSlot = fd.addFrameSlot("return", FrameSlotKind.Int); + Inst[] inst = new Inst[]{ + /* 0: */new Inst.Const(valueSlot, 1, 1), + /* 1: */new Inst.IfZero(valueSlot, 2, 4), + /* 2: */new Inst.Const(returnSlot, 41, 3), + /* 3: */new Inst.Return(), + /* 4: */new Inst.Const(returnSlot, 42, 5), + /* 5: */new Inst.Return()}; + assertPartialEvalEqualsAndRunsCorrect(new InstArrayProgram("instArraySimpleIfProgram", inst, returnSlot, fd)); + } + + /** + * Slightly modified version to expose a partial evaluation bug with ExplodeLoop(merge=true). + */ + public static class InstArrayProgram2 extends InstArrayProgram { + public InstArrayProgram2(String name, Inst[] inst, FrameSlot returnSlot, FrameDescriptor fd) { + super(name, inst, returnSlot, fd); + } + + @Override + @ExplodeLoop(merge = true) + public Object execute(VirtualFrame frame) { + int ip = 0; + while (ip != -1) { + CompilerAsserts.partialEvaluationConstant(ip); + if (inst[ip].execute(frame)) { + ip = inst[ip].getTrueSucc(); + } else { + ip = inst[ip].getFalseSucc(); + } + } + if (frame.getArguments().length > 0) { + return new Random(); + } else { + return FrameUtil.getIntSafe(frame, returnSlot); + } + } + } + + @Ignore("produces a bad graph") + @Test + public void instArraySimpleIfProgram2() { + FrameDescriptor fd = new FrameDescriptor(); + FrameSlot value1Slot = fd.addFrameSlot("value1", FrameSlotKind.Int); + FrameSlot value2Slot = fd.addFrameSlot("value2", FrameSlotKind.Int); + FrameSlot returnSlot = fd.addFrameSlot("return", FrameSlotKind.Int); + Inst[] inst = new Inst[]{ + /* 0: */new Inst.Const(value1Slot, 100, 1), + /* 1: */new Inst.Const(value2Slot, 100, 2), + /* 2: */new Inst.IfLt(value1Slot, value2Slot, 3, 5), + /* 3: */new Inst.Const(returnSlot, 41, 4), + /* 4: */new Inst.Return(), + /* 5: */new Inst.Const(returnSlot, 42, 6), + /* 6: */new Inst.Return()}; + InstArrayProgram program = new InstArrayProgram2("instArraySimpleIfProgram2", inst, returnSlot, fd); + program.execute(Truffle.getRuntime().createVirtualFrame(new Object[0], fd)); + program.execute(Truffle.getRuntime().createVirtualFrame(new Object[1], fd)); + assertPartialEvalEqualsAndRunsCorrect(program); + } }