2929#include " runtime/frame.hpp"
3030#include " runtime/frame.inline.hpp"
3131
32+ inline void patch_callee_link (const frame& f, intptr_t * fp) {
33+ *ContinuationHelper::Frame::callee_link_address (f) = fp;
34+ }
35+
36+ inline void patch_callee_link_relative (const frame& f, intptr_t * fp) {
37+ intptr_t * la = (intptr_t *)ContinuationHelper::Frame::callee_link_address (f);
38+ intptr_t new_value = fp - la;
39+ *la = new_value;
40+ }
41+
3242inline void FreezeBase::set_top_frame_metadata_pd (const frame& hf) {
33- Unimplemented ();
43+ stackChunkOop chunk = _cont.tail ();
44+ assert (chunk->is_in_chunk (hf.sp ()), " hf.sp()=" PTR_FORMAT, p2i (hf.sp ()));
45+
46+ hf.own_abi ()->return_pc = (uint64_t )hf.pc ();
47+ if (hf.is_interpreted_frame ()) {
48+ patch_callee_link_relative (hf, hf.fp ());
49+ }
50+ #ifdef ASSERT
51+ else {
52+ // See also FreezeBase::patch_pd()
53+ patch_callee_link (hf, (intptr_t *)badAddress);
54+ }
55+ #endif
3456}
3557
3658template <typename FKind>
3759inline frame FreezeBase::sender (const frame& f) {
38- Unimplemented ();
39- return frame ();
60+ assert (FKind::is_instance (f), " " );
61+
62+ if (FKind::interpreted) {
63+ return frame (f.sender_sp (), f.sender_pc (), f.interpreter_frame_sender_sp ());
64+ }
65+
66+ intptr_t * sender_sp = f.sender_sp ();
67+ address sender_pc = f.sender_pc ();
68+ assert (sender_sp != f.sp (), " must have changed" );
69+ int slot = 0 ;
70+ CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap (sender_pc, slot);
71+ return sender_cb != nullptr
72+ ? frame (sender_sp, sender_sp, nullptr , sender_pc, sender_cb, slot == -1 ? nullptr : sender_cb->oop_map_for_slot (slot, sender_pc))
73+ : frame (sender_sp, sender_pc, sender_sp);
4074}
4175
4276template <typename FKind> frame FreezeBase::new_heap_frame (frame& f, frame& caller) {
43- Unimplemented ();
44- return frame ();
77+ assert (FKind::is_instance (f), " " );
78+ intptr_t *sp, *fp;
79+ if (FKind::interpreted) {
80+ intptr_t locals_offset = *f.addr_at (_z_ijava_idx (locals));
81+
82+ // TODO: update this comment ?
83+ // If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set
84+ // the chunk's argsize in finalize_freeze and make room for it above the unextended_sp
85+ // See also comment on StackChunkFrameStream<frame_kind>::interpreter_frame_size()
86+
87+ int overlap =
88+ (caller.is_interpreted_frame () || caller.is_empty ())
89+ ? ContinuationHelper::InterpretedFrame::stack_argsize (f) + frame::metadata_words_at_top
90+ : 0 ;
91+
92+ // TODO: this works but I don't know why, I don't know what does it even do ?
93+ fp = caller.unextended_sp () - 1 - locals_offset + overlap;
94+
95+ // esp points one slot below the last argument
96+ intptr_t * x86_64_like_unextended_sp = f.interpreter_frame_esp () + 1 - frame::metadata_words_at_top;
97+
98+ sp = fp - (f.fp () - x86_64_like_unextended_sp);
99+ assert (sp <= fp && (fp <= caller.unextended_sp () || caller.is_interpreted_frame ()),
100+ " sp=" PTR_FORMAT " fp=" PTR_FORMAT " caller.unextended_sp()=" PTR_FORMAT " caller.is_interpreted_frame()=%d" ,
101+ p2i (sp), p2i (fp), p2i (caller.unextended_sp ()), caller.is_interpreted_frame ());
102+ caller.set_sp (fp);
103+
104+ assert (_cont.tail ()->is_in_chunk (sp), " " );
105+
106+ frame hf (sp, sp, fp, f.pc (), nullptr , nullptr , true /* on_heap */ );
107+ // frame_top() and frame_bottom() read these before relativize_interpreted_frame_metadata() is called
108+ *hf.addr_at (_z_ijava_idx (locals)) = locals_offset;
109+ *hf.addr_at (_z_ijava_idx (esp)) = f.interpreter_frame_esp () - f.fp ();
110+ return hf;
111+ } else {
112+ // TODO: needs to step through it at some point of time.
113+ int fsize = FKind::size (f);
114+ sp = caller.unextended_sp () - fsize;
115+ if (caller.is_interpreted_frame ()) {
116+ // If the caller is interpreted, our stackargs are not supposed to overlap with it
117+ // so we make more room by moving sp down by argsize
118+ int argsize = FKind::stack_argsize (f);
119+ sp -= argsize + frame::metadata_words_at_top;
120+ }
121+ fp = sp + fsize;
122+ caller.set_sp (fp);
123+
124+ assert (_cont.tail ()->is_in_chunk (sp), " " );
125+
126+ return frame (sp, sp, fp, f.pc (), nullptr , nullptr , true /* on_heap */ );
127+ }
45128}
46129
47130void FreezeBase::adjust_interpreted_frame_unextended_sp (frame& f) {
48- Unimplemented ();
131+ // nothing to do (TODO: why ? will it be same for s390)
49132}
50133
51134inline void FreezeBase::prepare_freeze_interpreted_top_frame (frame& f) {
52- Unimplemented ();
135+ // nothing to do
136+ DEBUG_ONLY ( intptr_t * lspp = f.interpreter_frame_top_frame_sp ();)
137+ assert (lspp == f.unextended_sp (), " should be top_frame_sp : " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT, p2i (lspp), p2i (f.unextended_sp ()));
53138}
54139
55140inline void FreezeBase::relativize_interpreted_frame_metadata (const frame& f, const frame& hf) {
56- Unimplemented ();
141+ intptr_t * vfp = f.fp ();
142+ intptr_t * hfp = hf.fp ();
143+ assert (f.fp () > (intptr_t *)f.interpreter_frame_esp (), " " );
144+
145+ // There is alignment padding between vfp and f's locals array in the original
146+ // frame, because we freeze the padding (see recurse_freeze_interpreted_frame)
147+ // in order to keep the same relativized locals pointer, we don't need to change it here.
148+
149+ // Make sure that monitors is already relativized.
150+ assert (hf.at_absolute (_z_ijava_idx (monitors)) <= -(frame::z_ijava_state_size / wordSize), " " );
151+ // Make sure that esp is already relativized.
152+ assert (hf.at_absolute (_z_ijava_idx (esp)) <= hf.at_absolute (_z_ijava_idx (monitors)), " " );
153+ // top_frame_sp is already relativized
154+
155+ // hfp == hf.sp() + (f.fp() - f.sp()) is not true on ppc because the stack frame has room for
156+ // the maximal expression stack and the expression stack in the heap frame is trimmed.
157+ assert (hf.fp () == hf.interpreter_frame_esp () + (f.fp () - f.interpreter_frame_esp ()), " " );
158+ assert (hf.fp () <= (intptr_t *)hf.at (_z_ijava_idx (locals)), " " );
57159}
58160
59161inline void FreezeBase::patch_pd (frame& hf, const frame& caller) {
60- Unimplemented ();
162+ if (caller.is_interpreted_frame ()) {
163+ assert (!caller.is_empty (), " " );
164+ patch_callee_link_relative (caller, caller.fp ());
165+ }
166+ #ifdef ASSERT
167+ else {
168+ // TODO: is below comment valid ?
169+
170+ // For compiled frames the back link is actually redundant. It gets computed
171+ // as unextended_sp + frame_size.
172+
173+ // Note the difference on x86_64: the link is not made relative if the caller
174+ // is a compiled frame because there rbp is used as a non-volatile register by
175+ // c1/c2 so it could be a computed value local to the caller.
176+
177+ // See also:
178+ // - FreezeBase::set_top_frame_metadata_pd
179+ // - StackChunkFrameStream<frame_kind>::fp()
180+ // - UseContinuationFastPath: compiled frames are copied in a batch w/o patching the back link.
181+ // The backlinks are restored when thawing (see Thaw<ConfigT>::patch_caller_links())
182+ patch_callee_link (hf, (intptr_t *)badAddress);
183+ }
184+ #endif
61185}
62186
63187inline void FreezeBase::patch_pd_unused (intptr_t * sp) {
64- Unimplemented ();
65188}
66189
67190inline void FreezeBase::patch_stack_pd (intptr_t * frame_sp, intptr_t * heap_sp) {
68- Unimplemented ();
191+ // Nothing to do. The backchain is reconstructed when thawing (see Thaw<ConfigT>::patch_caller_links())
69192}
70193
71194inline frame ThawBase::new_entry_frame () {
72- Unimplemented ();
73- return frame ();
195+ intptr_t * sp = _cont. entrySP ();
196+ return frame (sp, _cont. entryPC (), sp, _cont. entryFP () );
74197}
75198
76199template <typename FKind> frame ThawBase::new_stack_frame (const frame& hf, frame& caller, bool bottom) {
77- Unimplemented ();
78- return frame ();
200+ assert (FKind::is_instance (hf), " " );
201+
202+ assert (is_aligned (caller.fp (), frame::frame_alignment), PTR_FORMAT, p2i (caller.fp ()));
203+ // caller.sp() can be unaligned. This is fixed below.
204+ if (FKind::interpreted) {
205+ // TODO: needs to be checked below comment validity.
206+ // Note: we have to overlap with the caller, at least if it is interpreted, to match the
207+ // max_thawing_size calculation during freeze. See also comment above.
208+ intptr_t * heap_sp = hf.unextended_sp ();
209+ const int fsize = ContinuationHelper::InterpretedFrame::frame_bottom (hf) - hf.unextended_sp ();
210+ const int overlap = !caller.is_interpreted_frame () ? 0
211+ : ContinuationHelper::InterpretedFrame::stack_argsize (hf) + frame::metadata_words_at_top;
212+ intptr_t * frame_sp = caller.unextended_sp () + overlap - fsize;
213+ intptr_t * fp = frame_sp + (hf.fp () - heap_sp);
214+ // align fp
215+ int padding = fp - align_down (fp, frame::frame_alignment);
216+ fp -= padding;
217+ // alignment of sp is done by callee or in finish_thaw()
218+ frame_sp -= padding;
219+
220+ // TODO: really ??
221+ // On s390x esp points to the next free slot on the expression stack and sp + metadata points to the last parameter
222+ DEBUG_ONLY (intptr_t * esp = fp + *hf.addr_at (_z_ijava_idx (esp));)
223+ assert (frame_sp + frame::metadata_words_at_top == esp+1 , " frame_sp=" PTR_FORMAT " esp=" PTR_FORMAT, p2i (frame_sp), p2i (esp));
224+ caller.set_sp (fp);
225+ frame f (frame_sp, hf.pc (), frame_sp, fp);
226+ // we need to set the locals so that the caller of new_stack_frame() can call
227+ // ContinuationHelper::InterpretedFrame::frame_bottom
228+ // copy relativized locals from the heap frame
229+ *f.addr_at (_z_ijava_idx (locals)) = *hf.addr_at (_z_ijava_idx (locals));
230+
231+ return f;
232+ } else {
233+ int fsize = FKind::size (hf);
234+ int argsize = FKind::stack_argsize (hf);
235+ intptr_t * frame_sp = caller.sp () - fsize;
236+
237+ if ((bottom && argsize > 0 ) || caller.is_interpreted_frame ()) {
238+ frame_sp -= argsize + frame::metadata_words_at_top;
239+ frame_sp = align_down (frame_sp, frame::alignment_in_bytes);
240+ caller.set_sp (frame_sp + fsize);
241+ }
242+
243+ assert (hf.cb () != nullptr , " " );
244+ assert (hf.oop_map () != nullptr , " " );
245+ intptr_t * fp = frame_sp + fsize;
246+ return frame (frame_sp, frame_sp, fp, hf.pc (), hf.cb (), hf.oop_map (), false );
247+ }
79248}
80249
81250inline void ThawBase::derelativize_interpreted_frame_metadata (const frame& hf, const frame& f) {
82- Unimplemented ();
251+ intptr_t * vfp = f.fp ();
252+ // Make sure that monitors is still relativized.
253+ assert (f.at_absolute (_z_ijava_idx (monitors)) <= -(frame::z_ijava_state_size / wordSize), " " );
254+ // Make sure that esp is still relativized.
255+ assert (f.at_absolute (_z_ijava_idx (esp)) <= f.at_absolute (_z_ijava_idx (monitors)), " " );
256+ // Keep top_frame_sp relativized.
83257}
84258
85259inline intptr_t * ThawBase::align (const frame& hf, intptr_t * frame_sp, frame& caller, bool bottom) {
@@ -88,7 +262,8 @@ inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& cal
88262}
89263
90264inline void ThawBase::patch_pd (frame& f, const frame& caller) {
91- Unimplemented ();
265+ // TODO: 1. https://bugs.openjdk.org/browse/JDK-8299375
266+ patch_callee_link (caller, caller.fp ());
92267}
93268
94269inline void ThawBase::patch_pd (frame& f, intptr_t * caller_sp) {
@@ -102,11 +277,26 @@ inline intptr_t* ThawBase::push_cleanup_continuation() {
102277
103278template <typename ConfigT>
104279inline void Thaw<ConfigT>::patch_caller_links(intptr_t * sp, intptr_t * bottom) {
105- Unimplemented ();
280+ for (intptr_t * callers_sp; sp < bottom; sp = callers_sp) {
281+ address pc = (address)((frame::z_java_abi*) sp)->return_pc ;
282+ assert (pc != nullptr , " " );
283+ // see ThawBase::patch_return() which gets called just before
284+ bool is_entry_frame = pc == StubRoutines::cont_returnBarrier () || pc == _cont.entryPC ();
285+ if (is_entry_frame) {
286+ callers_sp = _cont.entryFP ();
287+ } else {
288+ assert (!Interpreter::contains (pc), " sp:" PTR_FORMAT " pc:" PTR_FORMAT, p2i (sp), p2i (pc));
289+ // TODO: 8290965: PPC64: Implement post-call NOPs
290+ CodeBlob* cb = CodeCache::find_blob (pc);
291+ callers_sp = sp + cb->frame_size ();
292+ }
293+ // set the back link
294+ ((frame::z_java_abi*) sp)->callers_sp = (intptr_t ) callers_sp;
295+ }
106296}
107297
108298inline void ThawBase::prefetch_chunk_pd (void * start, int size) {
109- Unimplemented ();
299+
110300}
111301
112302#endif // CPU_S390_CONTINUATION_S390_INLINE_HPP
0 commit comments