Annotation Interface CompilerDirectives.EarlyEscapeAnalysis
- Enclosing class:
CompilerDirectives
@Retention(RUNTIME)
@Target({METHOD,CONSTRUCTOR})
public static @interface CompilerDirectives.EarlyEscapeAnalysis
Requests the Truffle compiler to run escape analysis on this method before partial
evaluation.
When a method or constructor is annotated with @EarlyEscapeAnalysis, a dedicated
partial escape analysis phase is executed for that method before partial evaluation. This
allows allocations that do not escape the method to be virtualized or eliminated, and their
fields to be treated as partial-evaluation-time constants where possible.
Typical use cases
- Methods that allocate temporary objects whose fields are used only locally and are expected to become constants after partial evaluation.
- Interpreters that keep loop state in a small object (for example a bytecode index), in
combination with
ExplodeLoopandCompilerDirectives.EarlyInline, so that the state object can be fully scalar replaced.
Example: non-escaping temporary object
@EarlyEscapeAnalysis
private static int computeConstant() {
TestEscape v = new TestEscape(42);
CompilerAsserts.partialEvaluationConstant(v.value);
// After early escape analysis and partial evaluation this method reduces to "return 42".
return v.value;
}
static final class TestEscape {
int value;
TestEscape(int value) {
this.value = value;
}
}
Example: loop state object in a merge-exploded interpreter
static final class BytecodeIndex {
int bci;
}
@CompilationFinal(dimensions = 1) private final byte[] bytecodes = new byte[]{0, 1, 4, 2, 3};
@ExplodeLoop(kind = LoopExplosionKind.MERGE_EXPLODE)
@EarlyEscapeAnalysis
int execute(Boolean v) {
byte[] bc = this.bytecodes;
BytecodeIndex index = new BytecodeIndex();
while (true) {
CompilerAsserts.partialEvaluationConstant(index.bci);
switch (bc[index.bci]) {
case 0:
index.bci++;
break;
case 1:
// {@code branchTrue} is early inlined and sees the virtual {@code index}
// object.
branchTrue(bc, index, v);
break;
case 2:
return 41;
case 3:
return 42;
case 4:
throw CompilerDirectives.shouldNotReachHere();
}
}
}
@EarlyInline
private static void branchTrue(byte[] bc, BytecodeIndex index, Boolean v) {
if (v) {
index.bci = bc[index.bci + 1];
} else {
index.bci = index.bci + 2;
}
}
- Since:
- 25.1