@Retention(value=CLASS) @Target(value=TYPE) public @interface GenerateWrapper
InstrumentableNode subclass. The
generated subclass has the same class name as the original class name plus the 'Wrapper' suffix.
The generated class has default package visibility. All non-final and non-private methods
starting with execute or resume prefix (when specified) are
overridden by the generated wrapper. The generated overrides notifies execution events as
required by probes. Other abstract methods are directly delegated to the
wrapped node. No other methods are overridden by the generated wrapper. At least one method
starting with execute must be non-private and non-final. Every execute method must have
VirtualFrame as the first declared parameter.
Use methods with execute prefix for ordinary guest code execution. If the guest
language supports yield, add GenerateWrapper.yieldExceptions() argument and specify
resume prefix to mark method(s) that resume the yielded execution.
To successfully match the yielded/resumed execution, override
RootNode.isSameFrame(Frame, Frame) in case the resumed frame is not an identical instance
to the yielded frame.
Example Usage:
@GenerateWrapper
abstract class ExpressionNode extends Node implements InstrumentableNode {
abstract Object execute(VirtualFrame frame);
@Override
public WrapperNode createWrapper(ProbeNode probeNode) {
return new ExpressionNodeWrapper(this, probeNode);
}
}
Example that ignores return values:
@GenerateWrapper
abstract class ExpressionNode extends Node implements InstrumentableNode {
abstract Object execute(VirtualFrame frame);
@Override
public WrapperNode createWrapper(ProbeNode probeNode) {
return new ExpressionNodeWrapper(this, probeNode);
}
@GenerateWrapper.OutgoingConverter
final Object convertOutgoing(Object outgoingValue) {
return null;
}
}
Example that converts incoming byte values to int:
@GenerateWrapper
abstract class ExpressionNode extends Node implements InstrumentableNode {
abstract Object execute(VirtualFrame frame);
@Override
public WrapperNode createWrapper(ProbeNode probeNode) {
return new ExpressionNodeWrapper(this, probeNode);
}
@GenerateWrapper.IncomingConverter
final Object convertIncoming(Object incomingValue) {
if (incomingValue instanceof Byte) {
return (int) ((byte) incomingValue);
}
return incomingValue;
}
}
Example that prevents instrumentation from being added to a method:
@GenerateWrapper
abstract class ExpressionNode extends Node implements InstrumentableNode {
abstract Object execute(VirtualFrame frame);
@Override
public WrapperNode createWrapper(ProbeNode probeNode) {
return new ExpressionNodeWrapper(this, probeNode);
}
@GenerateWrapper.Ignore
abstract Object executeWithoutInstrumentation(VirtualFrame frame);
}
InstrumentableNode,
ProbeNode| Modifier and Type | Optional Element and Description |
|---|---|
String |
resumeMethodPrefix
Prefix of methods that resume execution after
yield. |
Class<?>[] |
yieldExceptions
Exceptions that are thrown to yield the execution of a thread.
|
public abstract Class<?>[] yieldExceptions
GenerateWrapper.YieldException interface. When one of them is thrown,
onYield() is called automatically. To
indicate resume of the execution, provide GenerateWrapper.resumeMethodPrefix().public abstract String resumeMethodPrefix
yield. The prefix is empty by default, which means no resume methods. When non-empty, the
generated wrapper calls ProbeNode.onResume(VirtualFrame) instead of
ProbeNode.onEnter(VirtualFrame).