Skip to content

Commit

Permalink
Add Instruction#isInstrumentation method
Browse files Browse the repository at this point in the history
  • Loading branch information
DSouzaM committed Apr 10, 2024
1 parent a4a0f9f commit 08c5f9d
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 15 deletions.
1 change: 0 additions & 1 deletion truffle/mx.truffle/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -1703,7 +1703,6 @@
"com.oracle.truffle.api.dsl",
"com.oracle.truffle.api.bytecode",
"com.oracle.truffle.api.bytecode.debug",
"com.oracle.truffle.api.bytecode.introspection",
"com.oracle.truffle.api.bytecode.serialization",
"com.oracle.truffle.api.bytecode.tracing",
"com.oracle.truffle.api.profiles",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import com.oracle.truffle.api.bytecode.EpilogExceptional;
import com.oracle.truffle.api.bytecode.EpilogReturn;
import com.oracle.truffle.api.bytecode.GenerateBytecode;
import com.oracle.truffle.api.bytecode.Instruction;
import com.oracle.truffle.api.bytecode.Operation;
import com.oracle.truffle.api.bytecode.Prolog;
import com.oracle.truffle.api.bytecode.TagTree;
Expand Down Expand Up @@ -243,6 +244,11 @@ public void testStatementsCached() {
"load.local",
"tag.leave",
"return");
boolean[] isInstrumentation = new boolean[] {true, false, false, true, true, false, true, false};
List<Instruction> instructions = node.getBytecodeNode().getInstructionsAsList();
for (int i = 0; i < instructions.size(); i++) {
assertEquals(isInstrumentation[i], instructions.get(i).isInstrumentation());
}

assertEquals(42, node.getCallTarget().call());

Expand All @@ -255,6 +261,10 @@ public void testStatementsCached() {
"load.local$Int$unboxed",
"tag.leave$Int",
"return");
instructions = node.getBytecodeNode().getInstructionsAsList();
for (int i = 0; i < instructions.size(); i++) {
assertEquals(isInstrumentation[i], instructions.get(i).isInstrumentation());
}

QuickeningCounts counts = assertQuickenings(node, 8, 4);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,18 @@
public class BasicInterpreterTest extends AbstractBasicInterpreterTest {
// @formatter:off

private static void assertInstructionEquals(Instruction instr, int bci, String name) {
assertEquals(bci, instr.getBytecodeIndex());
private static void assertInstructionEquals(Instruction instr, Integer bci, String name) {
assertInstructionEquals(instr, bci, name, null);
}

private static void assertInstructionEquals(Instruction instr, Integer bci, String name, Boolean instrumentation) {
if (bci != null) {
assertEquals(bci.intValue(), instr.getBytecodeIndex());
}
assertEquals(name, instr.getName());
if (instrumentation != null) {
assertEquals(instrumentation.booleanValue(), instr.isInstrumentation());
}
}

@Test
Expand Down Expand Up @@ -1133,6 +1142,43 @@ public void testIntrospectionDataSourceInformation() {
assertEquals(instructions.get(3).getBytecodeIndex() + 1, s4.getEndBci());
}

@Test
public void testIntrospectionDataInstrumentationInstructions() {
BasicInterpreter node = parseNode("introspectionDataInstrumentationInstructions", b -> {
b.beginRoot(LANGUAGE);

b.beginReturn();
b.beginTag(ExpressionTag.class);
b.beginAddOperation();
b.emitLoadArgument(0);
b.beginIncrementValue();
b.emitLoadArgument(1);
b.endIncrementValue();
b.endAddOperation();
b.endTag(ExpressionTag.class);
b.endReturn();

b.endRoot();
});

List<Instruction> instructions = node.getBytecodeNode().getInstructionsAsList();
assertEquals(4, instructions.size());
assertInstructionEquals(instructions.get(0), null, "load.argument", false);
assertInstructionEquals(instructions.get(1), null, "load.argument", false);
assertInstructionEquals(instructions.get(2), null, "c.AddOperation", false);
assertInstructionEquals(instructions.get(3), null, "return", false);

node.getRootNodes().update(createBytecodeConfigBuilder().addInstrumentation(BasicInterpreter.IncrementValue.class).build());

instructions = node.getBytecodeNode().getInstructionsAsList();
assertEquals(5, instructions.size());
assertInstructionEquals(instructions.get(0), null, "load.argument", false);
assertInstructionEquals(instructions.get(1), null, "load.argument", false);
assertInstructionEquals(instructions.get(2), null, "c.IncrementValue", true);
assertInstructionEquals(instructions.get(3), null, "c.AddOperation", false);
assertInstructionEquals(instructions.get(4), null, "return", false);
}

@Test
public void testTags() {
RootCallTarget root = parse("tags", b -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public final BytecodeLocation getLocation() {

public abstract List<Argument> getArguments();

public abstract boolean isInstrumentation();

protected abstract Instruction next();

@Override
Expand All @@ -91,7 +93,7 @@ private String toString(String prefix) {
return sb.toString();
}

public static abstract class Argument {
public abstract static class Argument {

protected Argument(Object token) {
BytecodeRootNodes.checkToken(token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6388,6 +6388,7 @@ private void create() {
type.add(createGetLength());
type.add(createGetArguments());
type.add(createGetName());
type.add(createIsInstrumentation());
type.add(createNext());

Set<String> generated = new HashSet<>();
Expand Down Expand Up @@ -6446,6 +6447,33 @@ private CodeExecutableElement createGetName() {
return ex;
}

private CodeExecutableElement createIsInstrumentation() {
CodeExecutableElement ex = GeneratorUtils.overrideImplement(types.Instruction, "isInstrumentation");
CodeTreeBuilder b = ex.createBuilder();

Map<Boolean, List<InstructionModel>> grouped = groupInstructionsByInstrumentation(model.getInstructions());

if (!grouped.containsKey(true)) {
// Simplification: no instruction is an instrumentation instruction.
b.startReturn().string("false").end();
return ex;
}

b.startSwitch().string("opcode").end().startBlock();
for (var entry : grouped.entrySet()) {
for (InstructionModel instruction : entry.getValue()) {
b.startCase().tree(createInstructionConstant(instruction)).end();
}
b.startCaseBlock();
b.startReturn().string(Boolean.toString(entry.getKey())).end();
b.end();
}

b.end();
b.tree(GeneratorUtils.createShouldNotReachHere("Invalid opcode"));
return ex;
}

private CodeExecutableElement createGetLength() {
CodeExecutableElement ex = new CodeExecutableElement(Set.of(FINAL), type(int.class), "getLength");
CodeTreeBuilder b = ex.createBuilder();
Expand Down Expand Up @@ -6499,6 +6527,10 @@ private CodeExecutableElement createGetArguments() {
return ex;
}

private Map<Boolean, List<InstructionModel>> groupInstructionsByInstrumentation(Collection<InstructionModel> models) {
return models.stream().collect(Collectors.groupingBy(InstructionModel::isInstrumentation));
}

private Collection<List<InstructionModel>> groupInstructionsByLength(Collection<InstructionModel> models) {
return models.stream().sorted(Comparator.comparingInt((i) -> i.getInstructionLength())).collect(Collectors.groupingBy((m) -> m.getInstructionLength())).values();
}
Expand Down Expand Up @@ -7699,12 +7731,7 @@ private CodeExecutableElement createFromStableBytecodeIndex() {

private record TranslationInstructionGroup(int instructionLength, boolean instrumentation) implements Comparable<TranslationInstructionGroup> {
TranslationInstructionGroup(InstructionModel instr) {
this(instr.getInstructionLength(), isInstrumentationInstruction(instr));
}

private static boolean isInstrumentationInstruction(InstructionModel instr) {
return instr.kind == InstructionKind.TAG_ENTER || instr.kind == InstructionKind.TAG_LEAVE || instr.kind == InstructionKind.TAG_LEAVE_VOID ||
instr.operation != null && instr.operation.kind == OperationKind.CUSTOM_INSTRUMENTATION;
this(instr.getInstructionLength(), instr.isInstrumentation());
}

// needs a deterministic ordering after grouping
Expand Down Expand Up @@ -11371,10 +11398,6 @@ private static String readConst(String index) {
return String.format("ACCESS.objectArrayRead(constants, %s)", index);
}

private static String readBranchProfile(String index) {
return String.format("branchProfiles == null ? 0 : ACCESS.intArrayRead(branchProfiles, %s)", index);
}

private static CodeTree readTagNode(TypeMirror expectedType, CodeTree index) {
CodeTreeBuilder b = CodeTreeBuilder.createBuilder();
b.startCall("ACCESS.cast");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import javax.lang.model.type.TypeMirror;

import com.oracle.truffle.dsl.processor.ProcessorContext;
import com.oracle.truffle.dsl.processor.bytecode.model.OperationModel.OperationKind;
import com.oracle.truffle.dsl.processor.java.ElementUtils;
import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement;
import com.oracle.truffle.dsl.processor.model.NodeData;
Expand Down Expand Up @@ -343,11 +344,14 @@ public void pp(PrettyPrinter printer) {
}
}

public boolean isInstrumentationOnly() {
public boolean isInstrumentation() {
switch (kind) {
case TAG_ENTER:
case TAG_LEAVE:
case TAG_LEAVE_VOID:
return true;
case CUSTOM:
return operation.kind == OperationKind.CUSTOM_INSTRUMENTATION;
default:
return false;
}
Expand Down

0 comments on commit 08c5f9d

Please sign in to comment.