88
88
import jdk .graal .compiler .api .replacements .Fold ;
89
89
import jdk .graal .compiler .core .common .NumUtil ;
90
90
import jdk .graal .compiler .core .common .util .TypeConversion ;
91
+ import jdk .graal .compiler .lir .asm .FrameContext ;
91
92
import jdk .graal .compiler .nodes .UnreachableNode ;
92
93
import jdk .graal .compiler .options .Option ;
93
94
import jdk .graal .compiler .word .BarrieredAccess ;
101
102
102
103
/**
103
104
* Performs deoptimization. The method to deoptimize (= the source method) is either a specialized
104
- * runtime compiled method or an image compiled test method with the {@link Specialize} annotation.
105
- * The target method is always an image compiled method.
105
+ * runtime compiled method or an AOT- compiled test method with the {@link Specialize} annotation.
106
+ * The target method is always an AOT- compiled method.
106
107
* <p>
107
- * Deoptimization is not limited to a single method. It can be done for all deoptimizable methods in
108
+ * Deoptimization is not limited to a single method. It can be done for all deoptimizable methods on
108
109
* the call stack. A method is deoptimizable if {@link FrameInfoQueryResult deoptimization
109
110
* information} is available.
110
111
* <p>
111
112
* Deoptimization can happen eagerly or lazily. For eager deoptimization, a {@link DeoptimizedFrame}
112
- * is constructed immediately and pinned, whereas for lazy deoptimization, the
113
- * {@link DeoptimizedFrame} is not constructed until immediately before it is installed (and
114
- * therefore does not need to be pinned).
113
+ * is constructed immediately and pinned and only installed on the stack later, whereas for lazy
114
+ * deoptimization, the {@link DeoptimizedFrame} is not constructed until immediately before it is
115
+ * installed. Eager deoptimization enables immediately freeing the code metadata needed for
116
+ * constructing the {@link DeoptimizedFrame}, while lazy deoptimization requires keeping it, but
117
+ * does not need the {@link DeoptimizedFrame} to stay allocated and pinned for potentially lengthy
118
+ * periods of time, which is typically preferable especially when many frames might be deoptimized
119
+ * at once. The stack slot at SP[0] of a deoptimizable method is reserved for deoptimization, and
120
+ * can be used freely by lazy and eager deoptimization.
115
121
* <p>
116
- * The stack slot at SP[0] is reserved for deoptimization, and can be used freely by lazy and eager
117
- * deoptimization.
122
+ * With both eager and lazy deoptimization, returns to a deoptimized method are intercepted to enter
123
+ * the deopt stub. Alternatively, {@link ExceptionUnwind} can "far-return" directly to the deopt
124
+ * stub for dispatching an exception while unwinding the stack, in which case the exception object
125
+ * will be passed as if it was the return value from the callee.
118
126
* <p>
119
- * Eager Deoptimization is done in two steps:
127
+ * Eager deoptimization is done in two steps:
120
128
* <ol>
121
- * <li>A call to {@link #deoptimizeInRange} walks the stack and for each method to deoptimize it
122
- * builds a {@link DeoptimizedFrame}. This handle contains all constants and materialized objects
123
- * which are needed to build the deoptimization target frames. It is stored at SP[0] (directly above
124
- * the return address). The return address (to the deoptimized method) is replaced by a pointer to
125
- * {@link #eagerDeoptStub}.
126
- *
127
- * <pre>
128
- * top of stack (lowest address)
129
- *
130
- * | ... |
131
- * +---------------------------------------+-------------
132
- * | | frame of the
133
- * |---------------------------------------| callee of
134
- * | return address (points to deoptStub) | deopt method
135
- * +---------------------------------------+-------------
136
- * | pointer to DeoptimizedFrame | frame of the
137
- * |---------------------------------------| deopt method
138
- * | outgoing stack parameters |
139
- * |---------------------------------------|
140
- * | |
141
- * +---------------------------------------+-------------
142
- * | ... |
143
- * </pre>
129
+ * <li>A call to {@link #deoptimizeInRange} walks the stack, and for each method to deoptimize, it
130
+ * builds a {@link DeoptimizedFrame}. This object contains all constants and materialized objects
131
+ * which are needed to build the deoptimization target frames. A reference to it is stored at SP[0]
132
+ * (directly above the callee's return address). The callee's return address (to the deoptimized
133
+ * method) is replaced by {@link #eagerDeoptStub}. (Find a diagram of the stack further below.)
144
134
* <p>
145
135
* From now on, the frame of the deoptimized method is no longer valid and the GC will ignore it.
146
- * Instead the GC will also visit the pointer to the {@link DeoptimizedFrame}. In other words: the
147
- * frame of the deoptimized method is "replaced" by a single entry, a pointer to
136
+ * Instead, the GC will also visit the reference to the {@link DeoptimizedFrame}. In other words:
137
+ * the frame of the deoptimized method is "replaced" by a single entry, a reference to
148
138
* {@link DeoptimizedFrame}, which contains all objects which are needed by the deoptimization
149
139
* targets.
150
140
* <p>
151
141
* There is one exception: outgoing primitive parameters of a deoptimized method may still be
152
- * accessed by a called method , even after the first step of eager deoptimization is done. Note that
153
- * this does not apply to outgoing object parameters as those are always copied to registers at the
142
+ * accessed by the callee , even after the first step of eager deoptimization is done. Note that this
143
+ * does not apply to outgoing object parameters as those are always copied to registers at the
154
144
* beginning of the called method to avoid problems with the GC.</li>
155
- * <p>
156
- * <li>Now when a called method will return to a deoptimized method, the eager deopt stub will be
157
- * called instead. It reads the {@link DeoptimizedFrame} handle and replaces the deoptimized
158
- * method's frame with the frame(s) of the deopt target method(s). Note that the eager deopt stub is
145
+ * <li>Now when a callee would return to a deoptimized method, the eager deopt stub will be entered
146
+ * instead. It reads the {@link DeoptimizedFrame} reference and replaces the deoptimized method's
147
+ * frame with the frame(s) of the deopt target method(s). Note that the eager deopt stub is
159
148
* completely allocation free.</li>
160
149
* </ol>
161
150
*
162
151
* <p>
163
- * Lazy Deoptimization is also done in two steps:
152
+ * Lazy deoptimization is also done in two steps:
164
153
* <ol>
165
- * <li>During the first step, we patch the frame's return address to the return address of a lazy
166
- * deopt stub. Depending on whether the method being deoptimized returns an object or a primitive,
167
- * this return address either points to {@link #lazyDeoptStubObjectReturn} or
168
- * {@link #lazyDeoptStubPrimitiveReturn}. The stack slot that is used to store the
169
- * {@link DeoptimizedFrame} in eager deoptimization is instead used to store the original return
170
- * address, which points somewhere into the deopt source method.
171
- *
172
- * <pre>
173
- * top of stack (lowest address)
174
- *
175
- * | ... |
176
- * +-------------------------------------------+-------------
177
- * | | frame of the
178
- * |-------------------------------------------| callee of
179
- * | return address (points to lazyDeoptStub) | deopt method
180
- * +-------------------------------------------+-------------
181
- * | original return address | frame of the
182
- * |-------------------------------------------| deopt method
183
- * | outgoing stack parameters |
184
- * |-------------------------------------------|
185
- * | |
186
- * +-------------------------------------------+-------------
187
- * | ... |
188
- * </pre>
189
- *
190
- * Stack walks and GC will now visit this frame that is pending lazy deoptimization as if it was a
191
- * normal stack frame, with the only difference being that the original return address is stored in
192
- * a different slot.</li>
193
- * <li>
154
+ * <li>During the first step, we only patch the callee's return address to point to a lazy deopt
155
+ * stub. Depending on whether the method being deoptimized returns an object or a primitive value,
156
+ * that stub is either {@link #lazyDeoptStubObjectReturn} or {@link #lazyDeoptStubPrimitiveReturn}.
157
+ * The reserved stack slot that is used to store the {@link DeoptimizedFrame} in eager
158
+ * deoptimization is instead used to store the original return address, which points somewhere into
159
+ * the deopt source method.
194
160
* <p>
195
- * When a method returns to this method pending lazy deoptimization, it instead calls one of the
196
- * lazy deopt stubs, which leads to {@link #lazyDeoptStubCore}. This method performs all the
161
+ * Stack walks and GC will now visit this frame that is pending lazy deoptimization as if it was a
162
+ * normal stack frame, with the only difference being that the original return address is taken from
163
+ * the reserved stack slot.</li>
164
+ * <li>When a callee returns to the method pending lazy deoptimization, it instead enters one of the
165
+ * lazy deopt stubs, which in turn invokes {@link #lazyDeoptStubCore}. This method performs all the
197
166
* necessary operations to construct a {@link DeoptimizedFrame} just like the first step of eager
198
167
* deoptimization. The process of constructing the frame is interruptible and involves allocation,
199
- * therefore if {@code gpReturnValue} contains an object reference, it must be turned into an object
200
- * reference so that the GC is aware of said reference.
168
+ * therefore if {@code gpReturnValue} contains an object reference, it must be explicitly turned
169
+ * into an object reference so that the GC is aware of said reference.
201
170
* <p>
202
171
* The frame is then copied onto the stack in {@link #rewriteStackStub}.</li>
203
172
* </ol>
173
+ * The stack at the time of entering a deopt stub looks as follows. Because while returning, the
174
+ * stack pointer has already moved above potential callee-saved arguments and the return address,
175
+ * they must be considered stale because they could have been overwritten by an interrupt or signal
176
+ * handler (despite a safe zone guaranteed by the ABI which could not be large enough).
177
+ *
178
+ * <pre>
179
+ * top of stack (lowest address)
180
+ *
181
+ * : ... :
182
+ * +---------------------------------------+-------------
183
+ * | ... |
184
+ * |---------------------------------------| frame of the callee of deopt'ed method,
185
+ * | potential callee-saved arguments | stale on deopt stub entry
186
+ * |---------------------------------------|
187
+ * | return address (to deopt stub) |
188
+ * +---------------------------------------+------------- <== stack pointer on deopt stub entry
189
+ * | deopt reserved slot |
190
+ * | eager deopt: DeoptimizedFrame object |
191
+ * | lazy deopt: original return address |
192
+ * |---------------------------------------| frame of the deopt'ed method
193
+ * | outgoing stack parameters |
194
+ * |---------------------------------------|
195
+ * | ... |
196
+ * +---------------------------------------+-------------
197
+ * : ... :
198
+ * </pre>
204
199
*/
205
200
public final class Deoptimizer {
206
201
private static final int MAX_DEOPTIMIZATION_EVENT_PRINT_LENGTH = 1000 ;
@@ -285,8 +280,8 @@ public static class Options {
285
280
}
286
281
287
282
/**
288
- * If true, the GC is called during deoptimization. The deoptimizer allocates some objects (in
289
- * the first step), so GC must work inside the deoptimizer .
283
+ * If true, the GC is called during deoptimization. The deoptimizer allocates some objects,
284
+ * which requires GC to work. This is only set to true for testing .
290
285
*/
291
286
public static boolean testGCinDeoptimizer = false ;
292
287
@@ -665,7 +660,7 @@ private static void deoptimize0(IsolateThread targetThread, Pointer sp, CodePoin
665
660
666
661
/**
667
662
* Invalidates the {@link InstalledCode} of the method of the given frame. The method must be a
668
- * runtime compiled method, since there is no {@link InstalledCode} for native image methods.
663
+ * runtime compiled method, since there is no {@link InstalledCode} for AOT-compiled methods.
669
664
*/
670
665
public static void invalidateMethodOfFrame (IsolateThread thread , Pointer sp , SpeculationReason speculation ) {
671
666
VMError .guarantee (thread == CurrentIsolate .getCurrentThread ());
@@ -806,7 +801,9 @@ private static boolean isNonNullValue(UnsignedWord pointer) {
806
801
}
807
802
808
803
/**
809
- * Entry point for the lazy deopt stub.
804
+ * Entry point for the lazy deopt stub. The parameters are computed with instructions generated
805
+ * in this method's prologue by a backend-specific {@link FrameContext}. See the class-level
806
+ * documentation for more context and a diagram of the stack.
810
807
* <p>
811
808
* This method uses {@link StubCallingConvention} for when the callee (the return of which is
812
809
* intercepted) also uses stub calling convention. In that case, the callee (rather than the
@@ -823,6 +820,16 @@ private static boolean isNonNullValue(UnsignedWord pointer) {
823
820
* If the callee does not use stub calling convention, this method unnecessarily saves
824
821
* registers, but it avoids having additional stubs and selecting between them and should not
825
822
* have significant impact.
823
+ * <p>
824
+ *
825
+ * @param originalStackPointer the original stack pointer of the deoptimized method (points to
826
+ * the {@link DeoptimizedFrame} object).
827
+ * @param gpReturnValue This is the value which was stored in the general purpose return
828
+ * register when the deopt stub was reached. It must be restored to the register
829
+ * before completion of the stub.
830
+ * @param fpReturnValue This is the value which was stored in the floating point return register
831
+ * when the deopt stub was reached. It must be restored to the register before
832
+ * completion of the stub.
826
833
*/
827
834
@ StubCallingConvention
828
835
@ DeoptStub (stubType = StubType .EntryStub )
@@ -863,7 +870,7 @@ public static UnsignedWord lazyDeoptStubObjectReturn(Pointer originalStackPointe
863
870
@ DeoptStub (stubType = StubType .EntryStub )
864
871
@ Uninterruptible (reason = "Rewriting stack." )
865
872
public static UnsignedWord lazyDeoptStubPrimitiveReturn (Pointer originalStackPointer , UnsignedWord gpReturnValue , UnsignedWord fpReturnValue ) {
866
- /* Establish the correct return address for this stub (see ObjectReturn stub for details) */
873
+ /* Establish the correct return address for this stub to make the stack walkable. */
867
874
CodePointer returnAddress = DeoptimizationSupport .getLazyDeoptStubPrimitiveReturnPointer ();
868
875
FrameAccess .singleton ().writeReturnAddress (CurrentIsolate .getCurrentThread (), originalStackPointer , returnAddress );
869
876
@@ -980,39 +987,10 @@ private static DeoptimizedFrame constructLazilyDeoptimizedFrameInterruptibly0(Po
980
987
}
981
988
982
989
/**
983
- * Performs the second step of deoptimization: the actual rewriting of a deoptimized method's
984
- * frame.
985
- * <p>
986
- * The pointer to the deopt stub code was installed in the return address slot by
987
- * {@link #deoptimizeInRange}. Therefore the stub is "called" when a method wants to return to a
988
- * deoptimized method.
989
- * <p>
990
- * When {@link #eagerDeoptStub} is "called", the stack looks like this:
991
- *
992
- * <pre>
993
- * : : highest stack address
994
- * | |
995
- * | | frame of the
996
- * +--------------------------------+ deoptimized method
997
- * | pointer to DeoptimizedFrame |
998
- * +--------------------------------+--------- no return address between the frames!
999
- * | |
1000
- * | | frame of
1001
- * | | {@link #eagerDeoptStub}
1002
- * : ... :
1003
- * </pre>
1004
- *
1005
- * The instructions to compute the parameters must be generated in this method's prologue by a
1006
- * backend-specific FrameContext class.
1007
- *
1008
- * @param originalStackPointer the original stack pointer of the deoptimized method (points to
1009
- * the {@link DeoptimizedFrame} object).
1010
- * @param gpReturnValue This is the value which was stored in the general purpose return
1011
- * register when the deopt stub was reached. It must be restored to the register
1012
- * before completion of the stub.
1013
- * @param fpReturnValue This is the value which was stored in the floating point return register
1014
- * when the deopt stub was reached. It must be restored to the register before
1015
- * completion of the stub.
990
+ * See {@link #lazyDeoptStubObjectReturn} for context, but note that here, the deoptimized frame
991
+ * has already been prepared and only needs to be written to the stack. For the same reason,
992
+ * this stub is fully uninterruptible because no allocations are needed, and does not use
993
+ * {@link StubCallingConvention}, because access to any callee-saved registers is not required.
1016
994
*/
1017
995
@ DeoptStub (stubType = StubType .EntryStub )
1018
996
@ Uninterruptible (reason = "Frame holds Objects in unmanaged storage." )
@@ -1136,9 +1114,6 @@ private void deoptSourceFrameLazily(CodePointer pc, boolean ignoreNonDeoptimizab
1136
1114
installLazyDeoptStubReturnAddress (targetInfo .getDeoptReturnValueIsObject (), deoptState .sourceSp , deoptState .targetThread );
1137
1115
}
1138
1116
1139
- /**
1140
- * Deoptimizes a source frame eagerly.
1141
- */
1142
1117
private DeoptimizedFrame deoptSourceFrameEagerly (CodePointer pc , boolean ignoreNonDeoptimizable ) {
1143
1118
if (!canBeDeoptimized (sourceChunk .getFrameInfo ())) {
1144
1119
if (ignoreNonDeoptimizable ) {
@@ -1375,7 +1350,7 @@ public static void logRecentDeoptimizationEvents(Log log) {
1375
1350
}
1376
1351
1377
1352
/**
1378
- * Constructs the frame entries for the deopimization target method.
1353
+ * Constructs the frame entries for the deoptimization target method.
1379
1354
*
1380
1355
* @param targetInfo The bytecode frame (+ some other info) of the target.
1381
1356
* @param sourceFrame The bytecode frame of the source.
0 commit comments