Skip to content

Commit c08b90f

Browse files
committed
Do not patch dead branch instructions
1 parent 6fecaea commit c08b90f

File tree

3 files changed

+78
-13
lines changed
  • truffle/src
    • com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test
    • com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/introspection
    • com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/bytecode/generator

3 files changed

+78
-13
lines changed

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/DeadCodeTest.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,14 @@
4141
package com.oracle.truffle.api.bytecode.test;
4242

4343
import static org.junit.Assert.assertEquals;
44+
import static org.junit.Assert.fail;
4445

4546
import org.junit.Test;
4647

4748
import com.oracle.truffle.api.TruffleLanguage;
4849
import com.oracle.truffle.api.bytecode.AbstractBytecodeTruffleException;
4950
import com.oracle.truffle.api.bytecode.BytecodeConfig;
51+
import com.oracle.truffle.api.bytecode.BytecodeLabel;
5052
import com.oracle.truffle.api.bytecode.BytecodeParser;
5153
import com.oracle.truffle.api.bytecode.BytecodeRootNode;
5254
import com.oracle.truffle.api.bytecode.BytecodeRootNodes;
@@ -562,6 +564,73 @@ public void testUnreachableFinallyWithLabel() {
562564
"return");
563565
}
564566

567+
@Test
568+
public void testUnreachableBranchIsNotPatched() {
569+
/**
570+
* This is a regression test for a branch fix-up bug. The branch instruction below is dead,
571+
* but its location was included in the list of "fix up" locations. When the label was
572+
* emitted, we would "fix up" that location, overwriting the load_argument (from the
573+
* exception handler) that happened to be at that location.
574+
*
575+
* @formatter:off
576+
* try {
577+
* return throw();
578+
* branch lbl; // dead
579+
* } finally {
580+
* load_argument(0);
581+
* }
582+
* lbl:
583+
* @formatter:on
584+
*/
585+
DeadCodeTestRootNode node = (DeadCodeTestRootNode) parse(b -> {
586+
b.beginRoot(LANGUAGE);
587+
b.beginBlock();
588+
589+
BytecodeLabel lbl = b.createLabel();
590+
b.beginFinallyTry(b.createLocal());
591+
592+
b.emitLoadArgument(0); // finally
593+
594+
b.beginBlock(); // begin try
595+
596+
b.beginReturn();
597+
b.emitThrow();
598+
b.endReturn();
599+
600+
b.emitBranch(lbl);
601+
602+
b.endBlock(); // end try
603+
604+
b.endFinallyTry();
605+
606+
b.emitLabel(lbl);
607+
608+
b.endBlock();
609+
b.endRoot();
610+
}).getRootNode();
611+
612+
assertInstructions(node,
613+
"c.Throw",
614+
"load.argument",
615+
"pop",
616+
"return",
617+
"load.argument",
618+
"pop",
619+
"throw",
620+
"trap");
621+
node.getIntrospectionData().getInstructions().stream() //
622+
.filter(insn -> insn.getName().equals("load.argument")) //
623+
.forEach(insn -> assertEquals(0, insn.getArgumentValues().get(0).getInteger()));
624+
try {
625+
node.getCallTarget().call(42);
626+
fail("exception expected");
627+
} catch (TestException ex) {
628+
// pass
629+
} catch (Exception ex) {
630+
fail("Wrong exception encountered: " + ex.getMessage());
631+
}
632+
}
633+
565634
private static void emitUnreachableCode(Builder b) {
566635
// custom operation
567636
b.beginAdd();

truffle/src/com.oracle.truffle.api.bytecode/src/com/oracle/truffle/api/bytecode/introspection/Argument.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public ArgumentType getKind() {
8686
}
8787

8888
public int getInteger() {
89-
if (getKind() != ArgumentType.CONSTANT) {
89+
if (getKind() != ArgumentType.INTEGER) {
9090
throw new UnsupportedOperationException(String.format("Not supported for argument type %s.", getKind()));
9191
}
9292
return (short) data[2];

truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/bytecode/generator/BytecodeDSLNodeFactory.java

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3424,29 +3424,20 @@ private CodeTree createOperationBeginData(CodeTreeBuilder b, OperationModel oper
34243424
return switch (operation.kind) {
34253425
case STORE_LOCAL, STORE_LOCAL_MATERIALIZED -> {
34263426
if (model.usesBoxingElimination()) {
3427-
34283427
yield createOperationData("StoreLocalData", "(BytecodeLocalImpl)" + operation.getOperationArgumentName(0), UNINIT);
3429-
} else
3430-
3431-
{
3428+
} else {
34323429
yield CodeTreeBuilder.singleString(operation.getOperationArgumentName(0));
34333430
}
34343431
}
3435-
case LOAD_LOCAL_MATERIALIZED ->
3436-
3437-
{
3432+
case LOAD_LOCAL_MATERIALIZED -> {
34383433
yield CodeTreeBuilder.singleString(operation.getOperationArgumentName(0));
34393434
}
34403435
case IF_THEN -> createOperationData("IfThenData", UNINIT, "this.reachable");
34413436
case IF_THEN_ELSE -> createOperationData("IfThenElseData", UNINIT, UNINIT, "this.reachable", "this.reachable");
34423437
case CONDITIONAL -> {
34433438
if (model.usesBoxingElimination()) {
3444-
34453439
yield createOperationData("ConditionalData", UNINIT, UNINIT, "this.reachable", "this.reachable", UNINIT, UNINIT);
3446-
} else
3447-
3448-
{
3449-
3440+
} else {
34503441
yield createOperationData("ConditionalData", UNINIT, UNINIT, "this.reachable", "this.reachable");
34513442
}
34523443
}
@@ -4155,12 +4146,15 @@ private void buildEmitOperationInstruction(CodeTreeBuilder b, OperationModel ope
41554146
b.end();
41564147
// Mark the branch target as uninitialized. Add this location to a work list to
41574148
// be processed once the label is defined.
4149+
4150+
b.startIf().string("this.reachable").end().startBlock();
41584151
b.startStatement().startCall("registerUnresolvedLabel");
41594152
b.string("labelImpl");
41604153
b.string("bci + 1");
41614154
b.string("currentStackHeight");
41624155
b.end(2);
41634156
b.newLine();
4157+
b.end();
41644158

41654159
// Branches inside finally handlers can only be relative to the handler,
41664160
// otherwise a finally handler emitted before a "return" could branch out of the
@@ -4171,8 +4165,10 @@ private void buildEmitOperationInstruction(CodeTreeBuilder b, OperationModel ope
41714165
emitThrowIllegalStateException(b, "\"Branches inside finally handlers can only target labels defined in the same handler.\"");
41724166
b.end();
41734167

4168+
b.startIf().string("this.reachable").end().startBlock();
41744169
b.lineComment("We need to track branch targets inside finally handlers so that they can be adjusted each time the handler is emitted.");
41754170
b.statement("finallyTryContext.finallyRelativeBranches.add(bci + 1)");
4171+
b.end();
41764172

41774173
b.end();
41784174
yield new String[]{UNINIT};

0 commit comments

Comments
 (0)