Skip to content

Commit bcff906

Browse files
committed
Implement RootNode#prepareForCall in Bytecode DSL interpreters
1 parent 326b5b9 commit bcff906

File tree

4 files changed

+109
-11
lines changed

4 files changed

+109
-11
lines changed

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/basic_interpreter/BasicInterpreterTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,26 @@ public void testTags() {
31963196
assertEquals(3L, root.call());
31973197
}
31983198

3199+
@Test
3200+
public void testPrepareForCall() {
3201+
assertThrows(IllegalStateException.class, () -> parse("getCallTargetDuringParse", b -> {
3202+
b.beginRoot();
3203+
b.beginReturn();
3204+
b.emitLoadConstant(42L);
3205+
b.endReturn();
3206+
BasicInterpreter root = b.endRoot();
3207+
root.getCallTarget();
3208+
}));
3209+
3210+
assertTrue(parse("getCallTargetAfterParse", b -> {
3211+
b.beginRoot();
3212+
b.beginReturn();
3213+
b.emitLoadConstant(42L);
3214+
b.endReturn();
3215+
b.endRoot();
3216+
}) != null);
3217+
}
3218+
31993219
@Test
32003220
public void testCloneUninitializedAdd() {
32013221
// return arg0 + arg1;

truffle/src/com.oracle.truffle.api.bytecode.test/src/com/oracle/truffle/api/bytecode/test/error_tests/ErrorTests.java

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,37 +361,86 @@ protected BadOverrides(ErrorLanguage language, FrameDescriptor frameDescriptor)
361361
super(language, frameDescriptor);
362362
}
363363

364-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
364+
private static final String ERROR_MESSAGE = "This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. " +
365+
"You can remove the final modifier to resolve this issue, but since the override will make this method unreachable, it is recommended to simply remove it.";
366+
367+
@ExpectError(ERROR_MESSAGE)
365368
@Override
366369
public final Object execute(VirtualFrame frame) {
367370
return null;
368371
}
369372

370-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
373+
@ExpectError(ERROR_MESSAGE)
374+
@Override
375+
public final int computeSize() {
376+
return 0;
377+
}
378+
379+
@ExpectError(ERROR_MESSAGE)
380+
@Override
381+
public final int findBytecodeIndex(Node node, Frame frame) {
382+
return 0;
383+
}
384+
385+
@ExpectError(ERROR_MESSAGE)
386+
@Override
387+
public final Node findInstrumentableCallNode(Node callNode, Frame frame, int bytecodeIndex) {
388+
return null;
389+
}
390+
391+
@ExpectError(ERROR_MESSAGE)
392+
@Override
393+
public final boolean isInstrumentable() {
394+
return false;
395+
}
396+
397+
@ExpectError(ERROR_MESSAGE)
398+
@Override
399+
public final boolean isCaptureFramesForTrace(boolean compiledFrame) {
400+
return false;
401+
}
402+
403+
@ExpectError(ERROR_MESSAGE)
404+
@Override
405+
public final void prepareForCall() {
406+
}
407+
408+
@ExpectError(ERROR_MESSAGE)
409+
@Override
410+
public final boolean prepareForCompilation(boolean rootCompilation, int compilationTier, boolean lastTier) {
411+
return false;
412+
}
413+
414+
@ExpectError(ERROR_MESSAGE)
415+
@Override
416+
public final void prepareForInstrumentation(Set<Class<?>> tags) {
417+
}
418+
419+
@ExpectError(ERROR_MESSAGE)
371420
public final Object getOSRMetadata() {
372421
return null;
373422
}
374423

375-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
424+
@ExpectError(ERROR_MESSAGE)
376425
public final void setOSRMetadata(Object osrMetadata) {
377426
}
378427

379-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
428+
@ExpectError(ERROR_MESSAGE)
380429
public final Object[] storeParentFrameInArguments(VirtualFrame parentFrame) {
381430
return null;
382431
}
383432

384-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
433+
@ExpectError(ERROR_MESSAGE)
385434
public final Frame restoreParentFrameFromArguments(Object[] arguments) {
386435
return null;
387436
}
388437

389-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
438+
@ExpectError(ERROR_MESSAGE)
390439
public final BytecodeNode getBytecodeNode() {
391440
return null;
392441
}
393442

394-
@ExpectError("This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.")
443+
@ExpectError(ERROR_MESSAGE)
395444
public final BytecodeRootNodes<?> getRootNodes() {
396445
return null;
397446
}
@@ -417,11 +466,13 @@ static int add(int x, int y) {
417466
}
418467
}
419468

469+
@ExpectWarning("This method is overridden by the generated Bytecode DSL class, so this definition is unreachable and can be removed.")
420470
@Override
421471
public int findBytecodeIndex(Node node, Frame frame) {
422472
return super.findBytecodeIndex(node, frame);
423473
}
424474

475+
@ExpectWarning("This method is overridden by the generated Bytecode DSL class, so this definition is unreachable and can be removed.")
425476
@Override
426477
public boolean isCaptureFramesForTrace(boolean compiledFrame) {
427478
return super.isCaptureFramesForTrace(compiledFrame);
@@ -777,7 +828,7 @@ public Object fallback(Object a, Object b) {
777828

778829
/**
779830
* These specializations should not be a problem. See
780-
* {@link OperationErrorTests.PackagePrivateSpecializationOperation}
831+
* {@link ErrorTests.BadSpecializationTests.PackagePrivateSpecializationOperation}
781832
*/
782833
@OperationProxy.Proxyable
783834
public abstract static class PackagePrivateSpecializationOperationProxy extends Node {

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ final class BytecodeRootNodeElement extends CodeTypeElement {
385385

386386
// Other root node overrides.
387387
this.add(createIsInstrumentable());
388+
this.add(createPrepareForCall());
388389
this.addOptional(createPrepareForInstrumentation());
389390
this.addOptional(createPrepareForCompilation());
390391

@@ -1622,6 +1623,15 @@ private CodeExecutableElement createIsInstrumentable() {
16221623
return ex;
16231624
}
16241625

1626+
private CodeExecutableElement createPrepareForCall() {
1627+
CodeExecutableElement ex = overrideImplementRootNodeMethod(model, "prepareForCall");
1628+
CodeTreeBuilder b = ex.createBuilder();
1629+
b.startIf().string("!this.nodes.isParsed()").end().startBlock();
1630+
emitThrowIllegalStateException(ex, b, "A call target cannot be created until bytecode parsing completes. Request a call target after the parse is complete instead.");
1631+
b.end();
1632+
return ex;
1633+
}
1634+
16251635
private CodeExecutableElement createPrepareForInstrumentation() {
16261636
if (!model.enableTagInstrumentation) {
16271637
return null;
@@ -8393,6 +8403,7 @@ void lazyInit() {
83938403
this.add(createGetParserImpl());
83948404
this.add(createValidate());
83958405
this.add(createGetLanguage());
8406+
this.add(createIsParsed());
83968407

83978408
if (model.enableSerialization) {
83988409
this.add(createSerialize());
@@ -8618,6 +8629,13 @@ private CodeExecutableElement createGetLanguage() {
86188629
return ex;
86198630
}
86208631

8632+
public CodeExecutableElement createIsParsed() {
8633+
CodeExecutableElement ex = new CodeExecutableElement(Set.of(PRIVATE), type(boolean.class), "isParsed");
8634+
CodeTreeBuilder b = ex.createBuilder();
8635+
b.startReturn().string("nodes != null").end();
8636+
return ex;
8637+
}
8638+
86218639
private CodeExecutableElement createSerialize() {
86228640
CodeExecutableElement ex = GeneratorUtils.override(types.BytecodeRootNodes, "serialize", new String[]{"buffer", "callback"});
86238641
mergeSuppressWarnings(ex, "cast");

truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/bytecode/parser/BytecodeDSLParser.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,23 @@ private void parseBytecodeDSLModel(TypeElement typeElement, BytecodeDSLModel mod
376376
model.interceptTruffleException = ElementUtils.findMethod(typeElement, "interceptTruffleException");
377377

378378
// Detect method implementations that will be overridden by the generated class.
379-
List<ExecutableElement> overrides = List.of(
379+
List<ExecutableElement> overrides = new ArrayList<>(List.of(
380380
ElementUtils.findMethod(types.RootNode, "execute"),
381+
ElementUtils.findMethod(types.RootNode, "computeSize"),
382+
ElementUtils.findMethod(types.RootNode, "findBytecodeIndex"),
383+
ElementUtils.findMethod(types.RootNode, "findInstrumentableCallNode"),
384+
ElementUtils.findMethod(types.RootNode, "isInstrumentable"),
385+
ElementUtils.findMethod(types.RootNode, "isCaptureFramesForTrace"),
386+
ElementUtils.findMethod(types.RootNode, "prepareForCall"),
387+
ElementUtils.findMethod(types.RootNode, "prepareForCompilation"),
388+
ElementUtils.findMethod(types.RootNode, "prepareForInstrumentation"),
381389
ElementUtils.findMethod(types.BytecodeRootNode, "getBytecodeNode"),
382390
ElementUtils.findMethod(types.BytecodeRootNode, "getRootNodes"),
383391
ElementUtils.findMethod(types.BytecodeOSRNode, "executeOSR"),
384392
ElementUtils.findMethod(types.BytecodeOSRNode, "getOSRMetadata"),
385393
ElementUtils.findMethod(types.BytecodeOSRNode, "setOSRMetadata"),
386394
ElementUtils.findMethod(types.BytecodeOSRNode, "storeParentFrameInArguments"),
387-
ElementUtils.findMethod(types.BytecodeOSRNode, "restoreParentFrameFromArguments"));
395+
ElementUtils.findMethod(types.BytecodeOSRNode, "restoreParentFrameFromArguments")));
388396

389397
for (ExecutableElement override : overrides) {
390398
ExecutableElement declared = ElementUtils.findMethod(typeElement, override.getSimpleName().toString());
@@ -394,7 +402,8 @@ private void parseBytecodeDSLModel(TypeElement typeElement, BytecodeDSLModel mod
394402

395403
if (declared.getModifiers().contains(Modifier.FINAL)) {
396404
model.addError(declared,
397-
"This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. Since it is overridden, the definition is unreachable and can be removed.");
405+
"This method is overridden by the generated Bytecode DSL class, so it cannot be declared final. " +
406+
"You can remove the final modifier to resolve this issue, but since the override will make this method unreachable, it is recommended to simply remove it.");
398407
} else {
399408
model.addWarning(declared, "This method is overridden by the generated Bytecode DSL class, so this definition is unreachable and can be removed.");
400409
}

0 commit comments

Comments
 (0)