Skip to content

Commit 11cee9e

Browse files
pchilanoTobiHartmann
authored andcommitted
8336845: [lworld] Virtual threads don't support the value class calling convention
Co-authored-by: Tobias Hartmann <[email protected]> Reviewed-by: thartmann, coleenp
1 parent 0836ed5 commit 11cee9e

25 files changed

+1386
-139
lines changed

src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ inline frame FreezeBase::sender(const frame& f) {
6767

6868
int slot = 0;
6969
CodeBlob* sender_cb = CodeCache::find_blob_and_oopmap(sender_pc, slot);
70+
71+
// Repair the sender sp if the frame has been extended
72+
if (sender_cb->is_nmethod()) {
73+
sender_sp = f.repair_sender_sp(sender_sp, link_addr);
74+
}
75+
7076
return sender_cb != nullptr
7177
? frame(sender_sp, sender_sp, *link_addr, sender_pc, sender_cb,
7278
slot == -1 ? nullptr : sender_cb->oop_map_for_slot(slot, sender_pc),
@@ -75,7 +81,7 @@ inline frame FreezeBase::sender(const frame& f) {
7581
}
7682

7783
template<typename FKind>
78-
frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
84+
frame FreezeBase::new_heap_frame(frame& f, frame& caller, int size_adjust) {
7985
assert(FKind::is_instance(f), "");
8086
assert(!caller.is_interpreted_frame()
8187
|| caller.unextended_sp() == (intptr_t*)caller.at(frame::interpreter_frame_last_sp_offset), "");
@@ -106,8 +112,8 @@ frame FreezeBase::new_heap_frame(frame& f, frame& caller) {
106112
fp = *(intptr_t**)(f.sp() - frame::sender_sp_offset);
107113

108114
int fsize = FKind::size(f);
109-
sp = caller.unextended_sp() - fsize;
110-
if (caller.is_interpreted_frame()) {
115+
sp = caller.unextended_sp() - fsize - size_adjust;
116+
if (caller.is_interpreted_frame() && size_adjust == 0) {
111117
// If the caller is interpreted, our stackargs are not supposed to overlap with it
112118
// so we make more room by moving sp down by argsize
113119
int argsize = FKind::stack_argsize(f);
@@ -180,11 +186,12 @@ inline void FreezeBase::set_top_frame_metadata_pd(const frame& hf) {
180186
: (intptr_t)hf.fp();
181187
}
182188

183-
inline void FreezeBase::patch_pd(frame& hf, const frame& caller) {
189+
inline void FreezeBase::patch_pd(frame& hf, const frame& caller, bool is_bottom_frame) {
184190
if (caller.is_interpreted_frame()) {
185191
assert(!caller.is_empty(), "");
186192
patch_callee_link_relative(caller, caller.fp());
187-
} else {
193+
} else if (is_bottom_frame && caller.pc() != nullptr) {
194+
assert(caller.is_compiled_frame(), "");
188195
// If we're the bottom-most frame frozen in this freeze, the caller might have stayed frozen in the chunk,
189196
// and its oop-containing fp fixed. We've now just overwritten it, so we must patch it back to its value
190197
// as read from the chunk.
@@ -215,7 +222,7 @@ inline frame ThawBase::new_entry_frame() {
215222
return frame(sp, sp, _cont.entryFP(), _cont.entryPC()); // TODO PERF: This finds code blob and computes deopt state
216223
}
217224

218-
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom) {
225+
template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame& caller, bool bottom, int size_adjust) {
219226
assert(FKind::is_instance(hf), "");
220227
// The values in the returned frame object will be written into the callee's stack in patch.
221228

@@ -243,24 +250,23 @@ template<typename FKind> frame ThawBase::new_stack_frame(const frame& hf, frame&
243250
return f;
244251
} else {
245252
int fsize = FKind::size(hf);
246-
intptr_t* frame_sp = caller.unextended_sp() - fsize;
253+
intptr_t* frame_sp = caller.unextended_sp() - fsize - size_adjust;
247254
if (bottom || caller.is_interpreted_frame()) {
248-
int argsize = FKind::stack_argsize(hf);
249-
250-
fsize += argsize;
251-
frame_sp -= argsize;
252-
caller.set_sp(caller.sp() - argsize);
253-
assert(caller.sp() == frame_sp + (fsize-argsize), "");
254-
255+
if (size_adjust == 0) {
256+
int argsize = FKind::stack_argsize(hf);
257+
frame_sp -= argsize;
258+
}
255259
frame_sp = align(hf, frame_sp, caller, bottom);
256260
}
261+
caller.set_sp(frame_sp + fsize);
262+
assert(is_aligned(frame_sp, frame::frame_alignment), "");
257263

258264
assert(hf.cb() != nullptr, "");
259265
assert(hf.oop_map() != nullptr, "");
260266
intptr_t* fp;
261267
if (PreserveFramePointer) {
262268
// we need to recreate a "real" frame pointer, pointing into the stack
263-
fp = frame_sp + FKind::size(hf) - frame::sender_sp_offset;
269+
fp = frame_sp + fsize - frame::sender_sp_offset;
264270
} else {
265271
fp = FKind::stub || FKind::native
266272
? frame_sp + fsize - frame::sender_sp_offset // fp always points to the address below the pushed return pc. We need correct address.
@@ -275,16 +281,16 @@ inline intptr_t* ThawBase::align(const frame& hf, intptr_t* frame_sp, frame& cal
275281
if (((intptr_t)frame_sp & 0xf) != 0) {
276282
assert(caller.is_interpreted_frame() || (bottom && hf.compiled_frame_stack_argsize() % 2 != 0), "");
277283
frame_sp--;
278-
caller.set_sp(caller.sp() - 1);
279284
}
280285
assert(is_aligned(frame_sp, frame::frame_alignment), "");
281286
#endif
282-
283287
return frame_sp;
284288
}
285289

286290
inline void ThawBase::patch_pd(frame& f, const frame& caller) {
287-
patch_callee_link(caller, caller.fp());
291+
if (caller.is_interpreted_frame() || PreserveFramePointer) {
292+
patch_callee_link(caller, caller.fp());
293+
}
288294
}
289295

290296
inline void ThawBase::patch_pd(frame& f, intptr_t* caller_sp) {

src/hotspot/cpu/aarch64/continuationHelper_aarch64.inline.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) {
141141
return pauth_strip_pointer(*pc_addr);
142142
}
143143

144-
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
145-
address* pc_addr = &(((address*) f.sp())[-1]);
144+
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) {
145+
address* pc_addr = &(((address*) (callee_augmented ? f.unextended_sp() : f.sp()))[-1]);
146146
*pc_addr = pauth_sign_return_address(pc);
147147
}
148148

src/hotspot/cpu/aarch64/frame_aarch64.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,9 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
670670
} else {
671671
ret_pc_loc = real_fp() - return_addr_offset;
672672
fp_loc = real_fp() - sender_sp_offset;
673+
if (cb()->is_nmethod() && cb()->as_nmethod_or_null()->needs_stack_repair()) {
674+
values.describe(frame_no, fp_loc - 1, err_msg("fsize for #%d", frame_no), 1);
675+
}
673676
}
674677
address ret_pc = *(address*)ret_pc_loc;
675678
values.describe(frame_no, ret_pc_loc,
@@ -841,6 +844,28 @@ intptr_t* frame::repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr)
841844
return sender_sp;
842845
}
843846

847+
intptr_t* frame::repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr) {
848+
assert(nm != nullptr && nm->needs_stack_repair(), "");
849+
// The stack increment resides just below the saved FP on the stack and
850+
// records the total frame size excluding the two words for saving FP and LR.
851+
intptr_t* real_frame_size_addr = (intptr_t*) (saved_fp_addr - 1);
852+
int real_frame_size = (*real_frame_size_addr / wordSize) + 2;
853+
assert(real_frame_size >= nm->frame_size() && real_frame_size <= 1000000, "invalid frame size");
854+
return sp + real_frame_size;
855+
}
856+
857+
bool frame::was_augmented_on_entry(int& real_size) const {
858+
assert(is_compiled_frame(), "");
859+
if (_cb->as_nmethod_or_null()->needs_stack_repair()) {
860+
intptr_t* real_frame_size_addr = unextended_sp() + _cb->frame_size() - sender_sp_offset - 1;
861+
log_trace(continuations)("real_frame_size is addr is " INTPTR_FORMAT, p2i(real_frame_size_addr));
862+
real_size = (*real_frame_size_addr / wordSize) + 2;
863+
return real_size != _cb->frame_size();
864+
}
865+
real_size = _cb->frame_size();
866+
return false;
867+
}
868+
844869
void JavaFrameAnchor::make_walkable() {
845870
// last frame set?
846871
if (last_Java_sp() == nullptr) return;

src/hotspot/cpu/aarch64/frame_aarch64.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,13 @@
152152
return (intptr_t*) addr_at(offset);
153153
}
154154

155+
public:
155156
// Support for scalarized inline type calling convention
156157
intptr_t* repair_sender_sp(intptr_t* sender_sp, intptr_t** saved_fp_addr) const;
158+
static intptr_t* repair_sender_sp(nmethod* nm, intptr_t* sp, intptr_t** saved_fp_addr);
159+
bool was_augmented_on_entry(int& real_size) const;
160+
161+
private:
157162

158163
#ifdef ASSERT
159164
// Used in frame::sender_for_{interpreter,compiled}_frame

src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,30 @@ template <ChunkFrames frame_kind>
3535
inline bool StackChunkFrameStream<frame_kind>::is_in_frame(void* p0) const {
3636
assert(!is_done(), "");
3737
intptr_t* p = (intptr_t*)p0;
38-
int argsize = is_compiled() ? (_cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0;
39-
int frame_size = _cb->frame_size() + argsize;
38+
int frame_size = _cb->frame_size();
39+
if (is_compiled()) {
40+
nmethod* nm = _cb->as_nmethod_or_null();
41+
if (nm->needs_stack_repair() && nm->is_compiled_by_c2()) {
42+
frame f = to_frame();
43+
bool augmented = f.was_augmented_on_entry(frame_size);
44+
if (!augmented) {
45+
// Fix: C2 caller, so frame was not extended and thus the
46+
// size read from the frame does not include the arguments.
47+
// Ideally we have to count the arg size for the scalarized
48+
// convention. For now we include the size of the caller frame
49+
// which would at least be equal to that.
50+
RegisterMap map(nullptr,
51+
RegisterMap::UpdateMap::skip,
52+
RegisterMap::ProcessFrames::skip,
53+
RegisterMap::WalkContinuation::skip);
54+
frame caller = to_frame().sender(&map);
55+
assert(caller.is_compiled_frame() && caller.cb()->as_nmethod()->is_compiled_by_c2(), "needs stack repair but was not extended with c1/interpreter caller");
56+
frame_size += (caller.real_fp() - caller.sp());
57+
}
58+
} else {
59+
frame_size += _cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size >> LogBytesPerWord;
60+
}
61+
}
4062
return p == sp() - frame::sender_sp_offset || ((p - unextended_sp()) >= 0 && (p - unextended_sp()) < frame_size);
4163
}
4264
#endif
@@ -46,15 +68,21 @@ inline frame StackChunkFrameStream<frame_kind>::to_frame() const {
4668
if (is_done()) {
4769
return frame(_sp, _sp, nullptr, nullptr, nullptr, nullptr, true);
4870
} else {
49-
return frame(sp(), unextended_sp(), fp(), pc(), cb(), _oopmap, true);
71+
frame f = frame(sp(), unextended_sp(), fp(), pc(), cb(), _oopmap, true);
72+
// If caller tries to get the sender of this frame and PreserveFramePointer
73+
// is set, fp() will be used which contains the old value at the time of
74+
// freeze (fp is reconstructed again during thaw). Setting sp as trusted
75+
// causes the sender code to use _unextended_sp instead (see sender_for_compiled_frame()).
76+
f.set_sp_is_trusted();
77+
return f;
5078
}
5179
}
5280

5381
template <ChunkFrames frame_kind>
5482
inline address StackChunkFrameStream<frame_kind>::get_pc() const {
5583
assert(!is_done(), "");
5684
// Just strip it for frames on the heap.
57-
return pauth_strip_pointer(*(address*)(_sp - 1));
85+
return pauth_strip_pointer(*(address*)((_callee_augmented ? _unextended_sp : _sp) - 1));
5886
}
5987

6088
template <ChunkFrames frame_kind>

src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10480,6 +10480,30 @@ class StubGenerator: public StubCodeGenerator {
1048010480
}
1048110481
#endif // LINUX
1048210482

10483+
static void save_return_registers(MacroAssembler* masm) {
10484+
if (InlineTypeReturnedAsFields) {
10485+
masm->push(RegSet::range(r0, r7), sp);
10486+
masm->sub(sp, sp, 4 * wordSize);
10487+
masm->st1(v0, v1, v2, v3, masm->T1D, Address(sp));
10488+
masm->sub(sp, sp, 4 * wordSize);
10489+
masm->st1(v4, v5, v6, v7, masm->T1D, Address(sp));
10490+
} else {
10491+
masm->fmovd(rscratch1, v0);
10492+
masm->stp(rscratch1, r0, Address(masm->pre(sp, -2 * wordSize)));
10493+
}
10494+
}
10495+
10496+
static void restore_return_registers(MacroAssembler* masm) {
10497+
if (InlineTypeReturnedAsFields) {
10498+
masm->ld1(v4, v5, v6, v7, masm->T1D, Address(masm->post(sp, 4 * wordSize)));
10499+
masm->ld1(v0, v1, v2, v3, masm->T1D, Address(masm->post(sp, 4 * wordSize)));
10500+
masm->pop(RegSet::range(r0, r7), sp);
10501+
} else {
10502+
masm->ldp(rscratch1, r0, Address(masm->post(sp, 2 * wordSize)));
10503+
masm->fmovd(v0, rscratch1);
10504+
}
10505+
}
10506+
1048310507
address generate_cont_thaw(Continuation::thaw_kind kind) {
1048410508
bool return_barrier = Continuation::is_thaw_return_barrier(kind);
1048510509
bool return_barrier_exception = Continuation::is_thaw_return_barrier_exception(kind);
@@ -10494,8 +10518,7 @@ class StubGenerator: public StubCodeGenerator {
1049410518

1049510519
if (return_barrier) {
1049610520
// preserve possible return value from a method returning to the return barrier
10497-
__ fmovd(rscratch1, v0);
10498-
__ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
10521+
save_return_registers(_masm);
1049910522
}
1050010523

1050110524
__ movw(c_rarg1, (return_barrier ? 1 : 0));
@@ -10504,8 +10527,7 @@ class StubGenerator: public StubCodeGenerator {
1050410527

1050510528
if (return_barrier) {
1050610529
// restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
10507-
__ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
10508-
__ fmovd(v0, rscratch1);
10530+
restore_return_registers(_masm);
1050910531
}
1051010532
assert_asm(_masm, (__ ldr(rscratch1, Address(rthread, JavaThread::cont_entry_offset())), __ cmp(sp, rscratch1)), Assembler::EQ, "incorrect sp");
1051110533

@@ -10524,8 +10546,7 @@ class StubGenerator: public StubCodeGenerator {
1052410546

1052510547
if (return_barrier) {
1052610548
// save original return value -- again
10527-
__ fmovd(rscratch1, v0);
10528-
__ stp(rscratch1, r0, Address(__ pre(sp, -2 * wordSize)));
10549+
save_return_registers(_masm);
1052910550
}
1053010551

1053110552
// If we want, we can templatize thaw by kind, and have three different entries
@@ -10536,8 +10557,7 @@ class StubGenerator: public StubCodeGenerator {
1053610557

1053710558
if (return_barrier) {
1053810559
// restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
10539-
__ ldp(rscratch1, r0, Address(__ post(sp, 2 * wordSize)));
10540-
__ fmovd(v0, rscratch1);
10560+
restore_return_registers(_masm);
1054110561
} else {
1054210562
__ mov(r0, zr); // return 0 (success) from doYield
1054310563
}

src/hotspot/cpu/arm/continuationHelper_arm.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) {
107107
return nullptr;
108108
}
109109

110-
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
110+
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) {
111111
Unimplemented();
112112
}
113113

src/hotspot/cpu/ppc/continuationHelper_ppc.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) {
110110
return (address)f.own_abi()->lr;
111111
}
112112

113-
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
113+
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) {
114114
f.own_abi()->lr = (uint64_t)pc;
115115
}
116116

src/hotspot/cpu/riscv/continuationHelper_riscv.inline.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) {
128128
return *pc_addr;
129129
}
130130

131-
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
131+
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) {
132132
address* pc_addr = &(((address*) f.sp())[-1]);
133133
*pc_addr = pc;
134134
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ inline address ContinuationHelper::Frame::real_pc(const frame& f) {
107107
return nullptr;
108108
}
109109

110-
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc) {
110+
inline void ContinuationHelper::Frame::patch_pc(const frame& f, address pc, bool callee_augmented) {
111111
Unimplemented();
112112
}
113113

0 commit comments

Comments
 (0)