Skip to content

Commit d293dc8

Browse files
committed
Loom: s390 Port
1 parent e4aed95 commit d293dc8

33 files changed

+1455
-201
lines changed
192 KB
Binary file not shown.

src/hotspot/cpu/s390/abstractInterpreter_s390.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,8 @@ void AbstractInterpreter::layout_activation(Method* method,
197197
assert(is_bottom_frame && (sender_sp == caller->unextended_sp()),
198198
"must initialize sender_sp of bottom skeleton frame when pushing it");
199199
} else {
200-
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame(), "is there a new frame type??");
200+
// FIXME: sender_sp correctly calculated for native frames ?
201+
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame() || caller->is_native_frame(), "is there a new frame type??");
201202
sender_sp = caller->sp(); // Call_stub only uses it's fp.
202203
}
203204

src/hotspot/cpu/s390/assembler_s390.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3279,6 +3279,9 @@ class Assembler : public AbstractAssembler {
32793279
static bool is_z_nop(address x) {
32803280
return is_z_nop(* (short *) x);
32813281
}
3282+
static bool is_z_illtrap(address x) {
3283+
return *(uint16_t*)x == 0u;
3284+
}
32823285
static bool is_z_br(long x) {
32833286
return is_z_bcr(x) && ((x & 0x00f0) == 0x00f0);
32843287
}

src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
511511
__ z_nop();
512512
__ z_brasl(Z_R14, op->addr());
513513
add_call_info(code_offset(), op->info());
514+
__ post_call_nop();
514515
}
515516

516517
void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
@@ -527,6 +528,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
527528
// to determine who we intended to call.
528529
__ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr));
529530
call(op, relocInfo::none);
531+
__ post_call_nop();
530532
}
531533

532534
void LIR_Assembler::move_regs(Register from_reg, Register to_reg) {
@@ -2839,6 +2841,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
28392841
if (info != nullptr) {
28402842
add_call_info_here(info);
28412843
}
2844+
__ post_call_nop();
28422845
}
28432846

28442847
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {

src/hotspot/cpu/s390/continuationEntry_s390.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@
2525
#ifndef CPU_S390_CONTINUATIONENTRY_S390_HPP
2626
#define CPU_S390_CONTINUATIONENTRY_S390_HPP
2727

28+
#include "runtime/frame.hpp"
29+
2830
class ContinuationEntryPD {
29-
// empty
31+
// This is needed to position the ContinuationEntry at the unextended sp of the entry frame
32+
frame::z_abi_160_base _abi;
3033
};
3134

3235
#endif // CPU_S390_CONTINUATIONENTRY_S390_HPP

src/hotspot/cpu/s390/continuationEntry_s390.inline.hpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,26 @@
2525
#ifndef CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
2626
#define CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP
2727

28+
#include "oops/method.inline.hpp"
29+
#include "runtime/frame.inline.hpp"
30+
#include "runtime/registerMap.hpp"
31+
#include "utilities/macros.hpp"
2832
#include "runtime/continuationEntry.hpp"
2933

30-
// TODO: Implement
31-
3234
inline frame ContinuationEntry::to_frame() const {
33-
Unimplemented();
34-
return frame();
35+
static CodeBlob* cb = CodeCache::find_blob_fast(entry_pc());
36+
assert(cb != nullptr, "");
37+
assert(cb->as_nmethod()->method()->is_continuation_enter_intrinsic(), "");
38+
return frame(entry_sp(), entry_pc(), entry_sp(), entry_fp(), cb);
3539
}
3640

3741
inline intptr_t* ContinuationEntry::entry_fp() const {
38-
Unimplemented();
39-
return nullptr;
42+
return (intptr_t*)((address)this + size());
4043
}
4144

4245
inline void ContinuationEntry::update_register_map(RegisterMap* map) const {
43-
Unimplemented();
46+
// TODO: need to revisit
47+
// Nothing to do (no non-volatile registers in java calling convention)
4448
}
4549

4650
#endif // CPU_S390_CONTINUATIONENTRY_S390_INLINE_HPP

src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp

Lines changed: 209 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,57 +29,231 @@
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+
3242
inline 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

3658
template<typename FKind>
3759
inline 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

4276
template<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

47130
void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) {
48-
Unimplemented();
131+
// nothing to do (TODO: why ? will it be same for s390)
49132
}
50133

51134
inline 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

55140
inline 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

59161
inline 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

63187
inline void FreezeBase::patch_pd_unused(intptr_t* sp) {
64-
Unimplemented();
65188
}
66189

67190
inline 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

71194
inline 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

76199
template<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

81250
inline 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

85259
inline 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

90264
inline 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

94269
inline void ThawBase::patch_pd(frame& f, intptr_t* caller_sp) {
@@ -102,11 +277,26 @@ inline intptr_t* ThawBase::push_cleanup_continuation() {
102277

103278
template <typename ConfigT>
104279
inline 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

108298
inline 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

Comments
 (0)