public final class Deoptimizer extends Object
Specialize
annotation.
The target method is always an image compiled method.
Deoptimization is not limited to a single method. It can be done for all deoptimizable methods in
the call stack. A method is deoptimizable if deoptimization
information
is available.
Deoptimization is done in two steps:
Deoptimizer.deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer, org.graalvm.nativeimage.c.function.CodePointer, boolean)
walks the stack and for each method to deoptimize it
builds a DeoptimizedFrame
. This handle contains all constants and materialized objects
which are needed to build the deoptimization target frames. It is stored in the stack slot right
above the return address. The return address (to the deoptimized method) is replaced by a pointer
to Deoptimizer.deoptStub(com.oracle.svm.core.deopt.DeoptimizedFrame)
.
: :
| |
| |
+--------------------------------+ frame of the
| outgoing stack parameters | deopmethod
+--------------------------------+
| pointer to DeoptimizedFrame |
+--------------------------------+---------
| pointer to deoptStub | return address
+--------------------------------+---------
| |
| | frame of Deoptimizer.deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer, org.graalvm.nativeimage.c.function.CodePointer, boolean)
or
| | a method which called it
: ... :
From now on, the frame of the deoptimized method is no longer valid and the GC will ignore it.
Instead the GC will also visit the pointer to the DeoptimizedFrame
. In other words: the
frame of the deoptimized method is "replaced" by a single entry, a pointer to
DeoptimizedFrame
, which contains all objects which are needed by the deoptimization
targets.
There is one exception: outgoing parameters. Outgoing parameters of a deoptimized method may
still be accessed by a called method, even after the first step of deoptimization is done.
Therefore the calling convention must make sure that there is a free stack slot for the
DeoptimizedFrame
between the outgoing parameters and the return address slot.
Exception from the exception: outgoing object parameters are always copied to registers at the beginning of the called method. Therefore we don't have to worry about GC these parameters.
Deoptimizer.deoptStub(com.oracle.svm.core.deopt.DeoptimizedFrame)
will be
called instead. It reads the DeoptimizedFrame
handle and replaces the deoptimized
method's frame with the frame(s) of the deopt target method(s). Note that the deopt stub is
completely allocation free.Modifier and Type | Class and Description |
---|---|
static interface |
Deoptimizer.DeoptStub |
static class |
Deoptimizer.Options |
static class |
Deoptimizer.StubType
Custom method prologues and epilogues required for deoptimization.
|
Modifier and Type | Field and Description |
---|---|
protected static long |
deoptStubFrameSize
The size of frame for the deoptimization stub.
|
protected int |
targetContentSize
The size of the new stack content after all stack entries are built).
|
static boolean |
testGCinDeoptimizer
If true, the GC is called during deoptimization.
|
Constructor and Description |
---|
Deoptimizer(org.graalvm.word.Pointer sourceSp,
CodeInfoQueryResult sourceChunk) |
Modifier and Type | Method and Description |
---|---|
static DeoptimizedFrame |
checkDeoptimized(org.graalvm.word.Pointer sourceSp)
Checks if a physical stack frame (identified by the stack pointer) was deoptimized, and
returns the
DeoptimizedFrame in that case. |
static int |
decodeDebugId(jdk.vm.ci.meta.JavaConstant actionAndReason) |
static int |
decodeDebugId(long actionAndReason) |
static jdk.vm.ci.meta.DeoptimizationAction |
decodeDeoptAction(jdk.vm.ci.meta.JavaConstant actionAndReason) |
static jdk.vm.ci.meta.DeoptimizationAction |
decodeDeoptAction(long actionAndReason) |
static jdk.vm.ci.meta.DeoptimizationReason |
decodeDeoptReason(jdk.vm.ci.meta.JavaConstant actionAndReason) |
static jdk.vm.ci.meta.DeoptimizationReason |
decodeDeoptReason(long actionAndReason) |
static void |
deoptimizeAll()
Deoptimizes all method(s) in all call stacks (= the calling methods).
|
static void |
deoptimizeFrame(org.graalvm.word.Pointer sourceSp,
boolean ignoreNonDeoptimizable,
jdk.vm.ci.meta.SpeculationLog.SpeculationReason speculation)
Deoptimizes the given frame.
|
static void |
deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer fromIp,
org.graalvm.nativeimage.c.function.CodePointer toIp,
boolean deoptAll)
Deoptimize a specific method.
|
DeoptimizedFrame |
deoptSourceFrame(org.graalvm.nativeimage.c.function.CodePointer pc,
boolean ignoreNonDeoptimizable,
org.graalvm.nativeimage.IsolateThread currentThread)
Deoptimizes a source frame.
|
static void |
deoptStub(DeoptimizedFrame frame)
Performs the second step of deoptimization: the actual rewriting of a deoptimized method's
frame.
|
static jdk.vm.ci.meta.JavaConstant |
encodeDeoptActionAndReason(jdk.vm.ci.meta.DeoptimizationAction action,
jdk.vm.ci.meta.DeoptimizationReason reason,
int speculationId) |
static long |
encodeDeoptActionAndReasonToLong(jdk.vm.ci.meta.DeoptimizationAction action,
jdk.vm.ci.meta.DeoptimizationReason reason,
int speculationId) |
static void |
invalidateMethodOfFrame(org.graalvm.word.Pointer sourceSp,
jdk.vm.ci.meta.SpeculationLog.SpeculationReason speculation)
Invalidates the
InstalledCode of the method of the given frame. |
static void |
logRecentDeoptimizationEvents(Log log) |
jdk.vm.ci.meta.JavaConstant |
readLocalVariable(int idx,
FrameInfoQueryResult sourceFrame)
Reads the value of a local variable in the given frame.
|
public static boolean testGCinDeoptimizer
protected int targetContentSize
protected static long deoptStubFrameSize
public Deoptimizer(org.graalvm.word.Pointer sourceSp, CodeInfoQueryResult sourceChunk)
public static long encodeDeoptActionAndReasonToLong(jdk.vm.ci.meta.DeoptimizationAction action, jdk.vm.ci.meta.DeoptimizationReason reason, int speculationId)
public static jdk.vm.ci.meta.JavaConstant encodeDeoptActionAndReason(jdk.vm.ci.meta.DeoptimizationAction action, jdk.vm.ci.meta.DeoptimizationReason reason, int speculationId)
public static jdk.vm.ci.meta.DeoptimizationAction decodeDeoptAction(long actionAndReason)
public static jdk.vm.ci.meta.DeoptimizationReason decodeDeoptReason(long actionAndReason)
public static int decodeDebugId(long actionAndReason)
public static jdk.vm.ci.meta.DeoptimizationAction decodeDeoptAction(jdk.vm.ci.meta.JavaConstant actionAndReason)
public static jdk.vm.ci.meta.DeoptimizationReason decodeDeoptReason(jdk.vm.ci.meta.JavaConstant actionAndReason)
public static int decodeDebugId(jdk.vm.ci.meta.JavaConstant actionAndReason)
public static DeoptimizedFrame checkDeoptimized(org.graalvm.word.Pointer sourceSp)
DeoptimizedFrame
in that case.public static void deoptimizeAll()
public static void deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer fromIp, org.graalvm.nativeimage.c.function.CodePointer toIp, boolean deoptAll)
fromIp
- The lower address (including) of the method's code.toIp
- The upper address (excluding) of the method's code.public static void deoptimizeFrame(org.graalvm.word.Pointer sourceSp, boolean ignoreNonDeoptimizable, jdk.vm.ci.meta.SpeculationLog.SpeculationReason speculation)
ignoreNonDeoptimizable
- if set to true, a frame that cannot be deoptimized is ignored
instead of raising an error (use for deoptimzation testing only).public static void invalidateMethodOfFrame(org.graalvm.word.Pointer sourceSp, jdk.vm.ci.meta.SpeculationLog.SpeculationReason speculation)
InstalledCode
of the method of the given frame. The method must be a
runtime compiled method, since there is not InstalledCode
for native image methods.public static void deoptStub(DeoptimizedFrame frame)
The pointer to the deopt stub code was installed in the return address slot by
Deoptimizer.deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer, org.graalvm.nativeimage.c.function.CodePointer, boolean)
. Therefore the stub is "called" when a method wants to return to a
deoptimized method.
When Deoptimizer.deoptStub(com.oracle.svm.core.deopt.DeoptimizedFrame)
is "called", the stack looks like this:
: :
| |
| | frame of the
+--------------------------------+ deoptimized method
| pointer to DeoptimizedFrame |
+--------------------------------+--------- no return address between the frames!
| |
| | frame of
| | Deoptimizer.deoptStub(com.oracle.svm.core.deopt.DeoptimizedFrame)
: ... :
frame
- This is the handle which was created in Deoptimizer.deoptimizeInRange(org.graalvm.nativeimage.c.function.CodePointer, org.graalvm.nativeimage.c.function.CodePointer, boolean)
. It is
fetched from the stack (the slot above the original return address) and passed as
parameter. The instructions for fetching the frame handle must be generated in
this method's prolog by a backend-specific FrameContext class. The prolog also
stores the original return value registers in the frame
.public jdk.vm.ci.meta.JavaConstant readLocalVariable(int idx, FrameInfoQueryResult sourceFrame)
idx
- the number of the local variable.sourceFrame
- the frame to access, which must be an inlined frame of the physical frame
that this deoptimizer has been created for.public DeoptimizedFrame deoptSourceFrame(org.graalvm.nativeimage.c.function.CodePointer pc, boolean ignoreNonDeoptimizable, org.graalvm.nativeimage.IsolateThread currentThread)
pc
- A code address inside the source method (= the method to deoptimize)public static void logRecentDeoptimizationEvents(Log log)