Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import java.util.ArrayList;
import java.util.List;

import org.graalvm.polyglot.Context;
Expand All @@ -51,8 +52,10 @@
import com.oracle.truffle.api.bytecode.ContinuationResult;
import com.oracle.truffle.api.bytecode.test.BytecodeDSLTestLanguage;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.AbstractBasicInterpreterTest;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.AbstractBasicInterpreterTest.TestRun;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreter;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreterBuilder;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreterBuilder.BytecodeVariant;
import com.oracle.truffle.api.frame.FrameSlotKind;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.ExecutionEventNode;
Expand All @@ -69,14 +72,18 @@
public class BytecodeDSLCompilationTest extends TestWithSynchronousCompiling {

@Parameters(name = "{0}")
public static List<Class<? extends BasicInterpreter>> getInterpreterClasses() {
return AbstractBasicInterpreterTest.allInterpreters();
public static List<TestRun> getParameters() {
List<TestRun> result = new ArrayList<>();
for (BytecodeVariant bc : AbstractBasicInterpreterTest.allVariants()) {
result.add(new TestRun(bc, false, false));
}
return result;
}

@Parameter(0) public Class<? extends BasicInterpreter> interpreterClass;
@Parameter(0) public TestRun run;

private boolean hasBoxingElimination() {
return new AbstractBasicInterpreterTest.TestRun(interpreterClass, false).hasBoxingElimination();
return run.hasBoxingElimination();
}

Context context;
Expand Down Expand Up @@ -123,7 +130,7 @@ public static void beforeClass() {
*/
@Test
public void testOSR1() {
BasicInterpreter root = parseNode(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, "osrRoot", b -> {
BasicInterpreter root = parseNode(run, BytecodeDSLTestLanguage.REF.get(null), "osrRoot", b -> {
b.beginRoot();

BytecodeLocal iLoc = b.createLocal();
Expand Down Expand Up @@ -223,7 +230,7 @@ public void testOSR1() {
*/
@Test
public void testOSR2() {
BasicInterpreter root = parseNode(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, "osrRoot", b -> {
BasicInterpreter root = parseNode(run, BytecodeDSLTestLanguage.REF.get(null), "osrRoot", b -> {
b.beginRoot();

BytecodeLocal iLoc = b.createLocal();
Expand Down Expand Up @@ -341,7 +348,7 @@ public void testOSR2() {

@Test
public void testCompiles() {
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "addTwoConstants", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "addTwoConstants", b -> {
b.beginRoot();

b.beginReturn();
Expand All @@ -365,7 +372,7 @@ public void testCompiles() {
@Test
public void testMultipleReturns() {
// return 30 + (arg0 ? 12 : (return 123; 0))
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "multipleReturns", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "multipleReturns", b -> {
b.beginRoot();

b.beginReturn();
Expand Down Expand Up @@ -403,7 +410,7 @@ public void testMultipleReturns() {
@Test
public void testStoreInvalidatesCode() {
assumeTrue(hasBoxingElimination());
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, BytecodeConfig.DEFAULT, b -> {
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(run, BytecodeDSLTestLanguage.REF.get(null), BytecodeConfig.DEFAULT, b -> {
b.beginRoot();
BytecodeLocal x = b.createLocal("x", null);
b.beginStoreLocal(x);
Expand Down Expand Up @@ -463,7 +470,7 @@ public void testStoreInvalidatesCode() {
@Test
public void testBytecodeNodeStoreInvalidatesCode() {
assumeTrue(hasBoxingElimination());
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, BytecodeConfig.DEFAULT, b -> {
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(run, BytecodeDSLTestLanguage.REF.get(null), BytecodeConfig.DEFAULT, b -> {
b.beginRoot();
BytecodeLocal x = b.createLocal("x", null);
b.beginStoreLocal(x);
Expand Down Expand Up @@ -537,7 +544,7 @@ public void testBytecodeNodeStoreInvalidatesCode() {
@Test
public void testMaterializedStoreInvalidatesCode() {
assumeTrue(hasBoxingElimination());
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, BytecodeConfig.DEFAULT, b -> {
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(run, BytecodeDSLTestLanguage.REF.get(null), BytecodeConfig.DEFAULT, b -> {
b.beginRoot();
BytecodeLocal x = b.createLocal("x", null);
b.beginStoreLocal(x);
Expand Down Expand Up @@ -615,7 +622,7 @@ public void testMaterializedStoreInvalidatesCode() {
@Test
public void testMaterializedAccessorStoreInvalidatesCode() {
assumeTrue(hasBoxingElimination());
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, BytecodeConfig.DEFAULT, b -> {
BytecodeRootNodes<BasicInterpreter> rootNodes = createNodes(run, BytecodeDSLTestLanguage.REF.get(null), BytecodeConfig.DEFAULT, b -> {
b.beginRoot();
BytecodeLocal x = b.createLocal("x", null);
b.beginStoreLocal(x);
Expand Down Expand Up @@ -688,7 +695,7 @@ public void testMaterializedAccessorStoreInvalidatesCode() {

@Test
public void testInstrumentation() {
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "addTwoConstantsInstrumented", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "addTwoConstantsInstrumented", b -> {
b.beginRoot();

b.beginReturn();
Expand All @@ -710,7 +717,7 @@ public void testInstrumentation() {

// Instrumentation should invalidate the compiled code.
root.getRootNodes().update(
BasicInterpreterBuilder.invokeNewConfigBuilder(interpreterClass).addInstrumentation(BasicInterpreter.IncrementValue.class).build());
run.bytecode().newConfigBuilder().addInstrumentation(BasicInterpreter.IncrementValue.class).build());
assertNotCompiled(target);

// The instrumented interpreter should be recompiled.
Expand All @@ -723,7 +730,7 @@ public void testInstrumentation() {

@Test
public void testYield() {
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "addYield", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "addYield", b -> {
b.beginRoot();

b.beginReturn();
Expand Down Expand Up @@ -763,7 +770,7 @@ public void testYield() {

@Test
public void testYieldInstrumentation() {
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "addYieldInstrumented", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "addYieldInstrumented", b -> {
b.beginRoot();

b.beginReturn();
Expand Down Expand Up @@ -797,7 +804,7 @@ public void testYieldInstrumentation() {

// Instrumentation should invalidate the compiled code.
root.getRootNodes().update(
BasicInterpreterBuilder.invokeNewConfigBuilder(interpreterClass).addInstrumentation(BasicInterpreter.IncrementValue.class).build());
run.bytecode().newConfigBuilder().addInstrumentation(BasicInterpreter.IncrementValue.class).build());
assertNotCompiled(target);
assertNotCompiled(continuationCallTarget);

Expand All @@ -815,7 +822,7 @@ public void testYieldInstrumentation() {
@Test
public void testCompiledSourceInfo() {
Source s = Source.newBuilder("test", "return sourcePosition", "compiledSourceInfo").build();
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "compiledSourceInfo", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "compiledSourceInfo", b -> {
b.beginSource(s);
b.beginSourceSection(0, 21);
b.beginRoot();
Expand Down Expand Up @@ -863,7 +870,7 @@ public void testCompiledSourceInfo() {

@Test
public void testTagInstrumentation() {
BasicInterpreter root = parseNodeForCompilation(interpreterClass, "tagInstrumentation", b -> {
BasicInterpreter root = parseNodeForCompilation(run, "tagInstrumentation", b -> {
b.beginRoot();

// i = 0
Expand Down Expand Up @@ -990,8 +997,9 @@ public void onEnter(VirtualFrame f) {
return c;
}

private static <T extends BasicInterpreterBuilder> BasicInterpreter parseNodeForCompilation(Class<? extends BasicInterpreter> interpreterClass, String rootName, BytecodeParser<T> builder) {
BasicInterpreter result = parseNode(interpreterClass, BytecodeDSLTestLanguage.REF.get(null), false, rootName, builder);
private static BasicInterpreter parseNodeForCompilation(TestRun run,
String rootName, BytecodeParser<BasicInterpreterBuilder> builder) {
BasicInterpreter result = parseNode(run, BytecodeDSLTestLanguage.REF.get(null), rootName, builder);
result.getBytecodeNode().setUncachedThreshold(0); // force interpreter to skip tier 0
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import static com.oracle.truffle.api.bytecode.test.basic_interpreter.AbstractBasicInterpreterTest.parseNode;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

Expand All @@ -43,6 +44,8 @@
import com.oracle.truffle.api.bytecode.test.basic_interpreter.AbstractBasicInterpreterTest;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreter;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreterBuilder;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.AbstractBasicInterpreterTest.TestRun;
import com.oracle.truffle.api.bytecode.test.basic_interpreter.BasicInterpreterBuilder.BytecodeVariant;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.EventContext;
import com.oracle.truffle.api.instrumentation.ExecutionEventListener;
Expand All @@ -58,17 +61,21 @@ public class BytecodeDSLPartialEvaluationTest extends PartialEvaluationTest {
protected static final BytecodeDSLTestLanguage LANGUAGE = null;

@Parameters(name = "{0}")
public static List<Class<? extends BasicInterpreter>> getInterpreterClasses() {
return AbstractBasicInterpreterTest.allInterpreters();
public static List<TestRun> getParameters() {
List<TestRun> result = new ArrayList<>();
for (BytecodeVariant bc : AbstractBasicInterpreterTest.allVariants()) {
result.add(new TestRun(bc, false, false));
}
return result;
}

@Parameter(0) public Class<? extends BasicInterpreter> interpreterClass;
@Parameter(0) public TestRun run;

@Test
public void testAddTwoConstants() {
// return 20 + 22;

BasicInterpreter root = parseNodeForPE(interpreterClass, "addTwoConstants", b -> {
BasicInterpreter root = parseNodeForPE(run, "addTwoConstants", b -> {
b.beginRoot();

b.beginReturn();
Expand All @@ -88,7 +95,7 @@ public void testAddTwoConstants() {
public void testAddThreeConstants() {
// return 40 + 22 + - 20;

BasicInterpreter root = parseNodeForPE(interpreterClass, "addThreeConstants", b -> {
BasicInterpreter root = parseNodeForPE(run, "addThreeConstants", b -> {
b.beginRoot();

b.beginReturn();
Expand All @@ -115,7 +122,7 @@ public void testAddThreeConstants() {
public void testAddThreeConstantsWithConstantOperands() {
// return 40 + 22 + - 20;

BasicInterpreter root = parseNodeForPE(interpreterClass, "addThreeConstantsWithConstantOperands", b -> {
BasicInterpreter root = parseNodeForPE(run, "addThreeConstantsWithConstantOperands", b -> {
b.beginRoot();

b.beginReturn();
Expand Down Expand Up @@ -147,7 +154,7 @@ public void testSum() {

long endValue = 10L;

BasicInterpreter root = parseNodeForPE(interpreterClass, "sum", b -> {
BasicInterpreter root = parseNodeForPE(run, "sum", b -> {
b.beginRoot();

BytecodeLocal i = b.createLocal();
Expand Down Expand Up @@ -208,7 +215,7 @@ public void testTryCatch() {
// return 3;
// @formatter:on

BasicInterpreter root = parseNodeForPE(interpreterClass, "sum", b -> {
BasicInterpreter root = parseNodeForPE(run, "sum", b -> {
b.beginRoot();

b.beginTryCatch();
Expand Down Expand Up @@ -256,7 +263,7 @@ public void testTryCatch2() {
// return 42;
// @formatter:on

BasicInterpreter root = parseNodeForPE(interpreterClass, "sum", b -> {
BasicInterpreter root = parseNodeForPE(run, "sum", b -> {
b.beginRoot();

b.beginTryCatch();
Expand Down Expand Up @@ -306,7 +313,7 @@ public void testTryCatch2() {
public void testConditionalTrue() {
// return true ? 42 : 21;

BasicInterpreter root = parseNodeForPE(interpreterClass, "conditionalTrue", b -> {
BasicInterpreter root = parseNodeForPE(run, "conditionalTrue", b -> {
b.beginRoot();
b.beginReturn();
b.beginConditional();
Expand All @@ -328,7 +335,7 @@ public void testConditionalTrue() {
public void testConditionalFalse() {
// return false ? 21 : 42;

BasicInterpreter root = parseNodeForPE(interpreterClass, "conditionalFalse", b -> {
BasicInterpreter root = parseNodeForPE(run, "conditionalFalse", b -> {
b.beginRoot();

b.beginReturn();
Expand All @@ -354,7 +361,7 @@ public void testEarlyReturn() {
// earlyReturn(42) // throws exception caught by intercept hook
// return 123
// @formatter:on
BasicInterpreter root = parseNodeForPE(interpreterClass, "earlyReturn", b -> {
BasicInterpreter root = parseNodeForPE(run, "earlyReturn", b -> {
b.beginRoot();
b.beginBlock();

Expand All @@ -379,7 +386,7 @@ public void testVariadicLength() {

// Note: the variadic array length is not PE constant beyond 8 arguments.
final int numVariadic = 8;
BasicInterpreter root = parseNodeForPE(interpreterClass, "variadicLength", b -> {
BasicInterpreter root = parseNodeForPE(run, "variadicLength", b -> {
b.beginRoot();
b.beginBlock();

Expand All @@ -405,7 +412,7 @@ public void testEmptyTagInstrumentation() {
try (Context c = Context.create()) {
c.enter();

BasicInterpreter root = parseNodeForPE(interpreterClass, "testEmptyTagInstrumentation", b -> {
BasicInterpreter root = parseNodeForPE(run, "testEmptyTagInstrumentation", b -> {
b.beginRoot();

b.beginTag(ExpressionTag.class);
Expand Down Expand Up @@ -440,7 +447,7 @@ public void testUnwindTagInstrumentation() {

String text = "return 20 + 22";
Source s = Source.newBuilder("test", text, "testUnwindTagInstrumentation").build();
BasicInterpreter root = parseNodeForPE(BytecodeDSLTestLanguage.REF.get(null), interpreterClass, "testUnwindTagInstrumentation", b -> {
BasicInterpreter root = parseNodeForPE(BytecodeDSLTestLanguage.REF.get(null), run, "testUnwindTagInstrumentation", b -> {
b.beginSource(s);
b.beginSourceSection(0, text.length());
b.beginRoot();
Expand Down Expand Up @@ -507,13 +514,15 @@ private static Supplier<Object> supplier(Object result) {
return () -> result;
}

private static <T extends BasicInterpreterBuilder> BasicInterpreter parseNodeForPE(Class<? extends BasicInterpreter> interpreterClass, String rootName, BytecodeParser<T> builder) {
return parseNodeForPE(LANGUAGE, interpreterClass, rootName, builder);
private static BasicInterpreter parseNodeForPE(TestRun run,
String rootName, BytecodeParser<BasicInterpreterBuilder> builder) {
return parseNodeForPE(LANGUAGE, run, rootName, builder);
}

private static <T extends BasicInterpreterBuilder> BasicInterpreter parseNodeForPE(BytecodeDSLTestLanguage language, Class<? extends BasicInterpreter> interpreterClass, String rootName,
BytecodeParser<T> builder) {
BasicInterpreter result = parseNode(interpreterClass, language, false, rootName, builder);
private static <T extends BasicInterpreterBuilder> BasicInterpreter parseNodeForPE(BytecodeDSLTestLanguage language,
TestRun run, String rootName,
BytecodeParser<BasicInterpreterBuilder> builder) {
BasicInterpreter result = parseNode(run, language, rootName, builder);
result.getBytecodeNode().setUncachedThreshold(0); // force interpreter to skip tier 0
return result;
}
Expand Down
9 changes: 9 additions & 0 deletions truffle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ This changelog summarizes major changes between Truffle versions relevant to lan
* GR-69649: Bytecode DSL now encodes primitive constant operands directly in the bytecode, reducing memory indirections in the interpreter. This optimization is enabled by default; you can configure it with `@GenerateBytecode(inlinePrimitiveConstants = true)`.
* GR-68993: Added `HostCompilerDirectives.markThreadedSwitch(int)` to mark a switch statement within a loop as a candidate for threaded switch optimization.
* GR-68993: Bytecode DSL: All bytecode interpreters are now using the threaded switch optimization by default. This new optimization can be configured using `@GenerateBytecode(enableThreadedSwitch=true|false)`.
* GR-71030: Bytecode DSL now generates a new `MyBytecodeRootNodeGen.Bytecode` class that can be accessed via the `MyBytecodeRootNodeGen.BYTECODE` singleton. This class which extends the added `BytecodeDescriptor` allows you to parse, serialize and deserialize bytecode nodes in addition to the already existing static methods in the generated code.
* GR-71030: Bytecode DSL now provides an `InstructionDescriptor` generated implementation for the bytecode interpreter. The instructions can be accessed via the new BytecodeDescriptor like this: `MyBytecodeRootNodeGen.BYTECODE.getInstructionDescriptors()`. There is also `MyBytecodeRootNodeGen.BYTECODE.dump()` to produce a human-readable instruction format.
* GR-71031: Added new method `BytecodeDescriptor.update(MyLanguage, BytecodeConfig)` to update the bytecode config for all current root nodes and root nodes created in the future of a language.
* GR-51945: Bytecode DSL, added `InstructionTracer` with `onInstructionEnter(InstructionAccess, BytecodeNode, int, Frame)`. Tracers can be attached per root via `BytecodeRootNodes.addInstructionTracer(InstructionTracer)` and per descriptor via `BytecodeDescriptor.addInstructionTracer(TruffleLanguage, InstructionTracer)`. Attaching a tracer invalidates affected roots and may trigger reparse and comes at a significant cost.
* GR-51945: Bytecode DSL: added instruction tracer reference implementations `PrintInstructionTracer` and `InstructionHistogramTracer`. These are intended for diagnostics.
* GR-51945: Added option `engine.TraceBytecode` to enable printing each executed Bytecode DSL instruction. Use the `engine.BytecodeMethodFilter` option to print instructions only for a given method.
* GR-51945: Added option `engine.BytecodeHistogram` to enable printing a bytecode histogram on engine close. Use `engine.BytecodeHistogramInterval` to configure the interval at which the histogram is reset and printed.



## Version 25.0
* GR-31495 Added ability to specify language and instrument specific options using `Source.Builder.option(String, String)`. Languages may describe available source options by implementing `TruffleLanguage.getSourceOptionDescriptors()` and `TruffleInstrument.getSourceOptionDescriptors()` respectively.
Expand Down
Loading