Skip to content

Commit bca3aef

Browse files
committed
Validate that endTag receives same tags as beginTag, when possible
1 parent 88fe963 commit bca3aef

File tree

2 files changed

+52
-6
lines changed
  • truffle/src
    • com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test
    • com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/bytecode/generator

2 files changed

+52
-6
lines changed

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,46 @@ public void testTagsEmptyErrors() {
334334
});
335335
}
336336

337+
@Test
338+
public void testTagsMismatchError() {
339+
TagInstrumentationTestRootNode node = parse((b) -> {
340+
b.beginRoot(TagTestLanguage.REF.get(null));
341+
b.beginReturn();
342+
b.beginTag(StatementTag.class, ExpressionTag.class);
343+
b.emitLoadConstant(42);
344+
b.endTag(StatementTag.class);
345+
b.endReturn();
346+
b.endRoot();
347+
});
348+
349+
assertInstructions(node,
350+
"load.constant",
351+
"return");
352+
assertEquals(42, node.getCallTarget().call());
353+
354+
// When we include statement tags, they balance, so there should be no errors.
355+
List<Event> events = attachEventListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.StatementTag.class).build());
356+
assertInstructions(node,
357+
"tag.enter",
358+
"load.constant",
359+
"tag.leave",
360+
"return");
361+
assertEquals(42, node.getCallTarget().call());
362+
363+
List<Instruction> instructions = node.getBytecodeNode().getInstructionsAsList();
364+
int enter = instructions.get(0).getBytecodeIndex();
365+
int leave = instructions.get(2).getBytecodeIndex();
366+
367+
assertEvents(node,
368+
events,
369+
new Event(EventKind.ENTER, enter, leave, null, StatementTag.class),
370+
new Event(EventKind.RETURN_VALUE, enter, leave, 42, StatementTag.class));
371+
372+
// When we include expression tags, the mismatch should be detected.
373+
assertFails(() -> attachEventListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.StatementTag.class,
374+
StandardTags.ExpressionTag.class).build()), IllegalArgumentException.class);
375+
}
376+
337377
@Test
338378
public void testStatementsUncached() {
339379
TagInstrumentationTestRootNode node = parse((b) -> {

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4371,32 +4371,38 @@ private CodeExecutableElement createEnd(OperationModel operation) {
43714371
b.statement("markReachable(false)");
43724372
break;
43734373
case TAG:
4374+
b.declaration(tagNode.asType(), "tagNode", "operationData.node");
4375+
4376+
b.startIf().string("(encodedTags & this.tags) != tagNode.tags").end().startBlock();
4377+
emitThrow(b, IllegalArgumentException.class, "\"The tags provided to endTag do not match the tags provided to the corresponding beginTag call.\"");
4378+
b.end();
4379+
4380+
// If this tag operation is nested in another, add it to the outer tag tree
43744381
b.declaration(type(int.class), "sp", "operationSp - 1");
43754382
b.startWhile().string("sp >= 0").end().startBlock();
43764383
b.startIf().string("operationStack[sp].data instanceof TagOperationData t").end().startBlock();
43774384
b.startIf().string("t.children == null").end().startBlock();
43784385
b.statement("t.children = new ArrayList<>(3)");
43794386
b.end();
4380-
b.statement("t.children.add(operationData.node)");
4387+
b.statement("t.children.add(tagNode)");
43814388
b.statement("break");
43824389
b.end(); // if
43834390
b.statement("sp--");
43844391
b.end(); // while
43854392

4393+
// Otherwise, this tag is the root of a tag tree.
43864394
b.startIf().string("sp < 0").end().startBlock();
43874395
b.lineComment("not found");
43884396
b.startIf().string("tagRoots == null").end().startBlock();
43894397
b.statement("tagRoots = new ArrayList<>(3)");
43904398
b.end();
4391-
b.statement("tagRoots.add(operationData.node)");
4392-
4393-
b.end();
4394-
b.end();
4399+
b.statement("tagRoots.add(tagNode)");
4400+
b.end(); // while
43954401

4396-
b.declaration(tagNode.asType(), "tagNode", "operationData.node");
43974402
b.declaration(arrayOf(tagNode.asType()), "children");
43984403
b.declaration(generic(type(List.class), tagNode.asType()), "operationChildren", "operationData.children");
43994404

4405+
// Set the children array and adopt children.
44004406
b.startIf().string("operationChildren == null").end().startBlock();
44014407
b.statement("children = TagNode.EMPTY_ARRAY");
44024408
b.end().startElseBlock();

0 commit comments

Comments
 (0)