Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8286476: x86_32: Fix crashes with non-preview mode after JDK-8284161 (Virtual Threads) #8630

Closed
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
121 changes: 117 additions & 4 deletions src/hotspot/cpu/x86/stubGenerator_x86_32.cpp
Expand Up @@ -3866,6 +3866,104 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::x86::_fpu_subnormal_bias2[2]= 0x7bff;
}

RuntimeStub* generate_cont_doYield() {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}

address generate_cont_thaw(bool return_barrier, bool exception) {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}

address generate_cont_thaw() {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}

address generate_cont_returnBarrier() {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}

address generate_cont_returnBarrier_exception() {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}

#if INCLUDE_JFR

static void jfr_prologue(address the_pc, MacroAssembler* masm) {
Register java_thread = rdi;
__ get_thread(java_thread);
__ set_last_Java_frame(java_thread, rsp, rbp, the_pc);
__ movptr(Address(rsp, 0), java_thread);
}

// The handle is dereferenced through a load barrier.
static void jfr_epilogue(MacroAssembler* masm) {
Register java_thread = rdi;
__ get_thread(java_thread);
__ reset_last_Java_frame(java_thread, true);
Label null_jobject;
__ testptr(rax, rax);
__ jcc(Assembler::zero, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(masm, decorators, T_OBJECT, rax, Address(rax, 0), noreg, java_thread);
__ bind(null_jobject);
}

// For c2: c_rarg0 is junk, call to runtime to write a checkpoint.
// It returns a jobject handle to the event writer.
// The handle is dereferenced and the return value is the event writer oop.
static RuntimeStub* generate_jfr_write_checkpoint() {
enum layout {
FPUState_off = 0,
rbp_off = FPUStateSizeInWords,
rdi_off,
rsi_off,
rcx_off,
rbx_off,
saved_argument_off,
saved_argument_off2, // 2nd half of double
framesize
};

int insts_size = 512;
int locs_size = 64;
CodeBuffer code("jfr_write_checkpoint", insts_size, locs_size);
OopMapSet* oop_maps = new OopMapSet();
MacroAssembler* masm = new MacroAssembler(&code);
MacroAssembler* _masm = masm;

address start = __ pc();
__ enter();
int frame_complete = __ pc() - start;
address the_pc = __ pc();
jfr_prologue(the_pc, _masm);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint), 1);
jfr_epilogue(_masm);
__ leave();
__ ret(0);

OopMap* map = new OopMap(framesize, 1); // rbp
oop_maps->add_gc_map(the_pc - start, map);

RuntimeStub* stub = // codeBlob framesize is in words (not VMRegImpl::slot_size)
RuntimeStub::new_runtime_stub("jfr_write_checkpoint", &code, frame_complete,
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
oop_maps, false);
return stub;
}

#endif // INCLUDE_JFR

//---------------------------------------------------------------------------
// Initialization

Expand Down Expand Up @@ -3953,6 +4051,19 @@ class StubGenerator: public StubCodeGenerator {
}
}

void generate_phase1() {
// Continuation stubs:
StubRoutines::_cont_thaw = generate_cont_thaw();
StubRoutines::_cont_returnBarrier = generate_cont_returnBarrier();
StubRoutines::_cont_returnBarrierExc = generate_cont_returnBarrier_exception();
StubRoutines::_cont_doYield_stub = generate_cont_doYield();
StubRoutines::_cont_doYield = StubRoutines::_cont_doYield_stub == nullptr ? nullptr
: StubRoutines::_cont_doYield_stub->entry_point();

JFR_ONLY(StubRoutines::_jfr_write_checkpoint_stub = generate_jfr_write_checkpoint();)
JFR_ONLY(StubRoutines::_jfr_write_checkpoint = StubRoutines::_jfr_write_checkpoint_stub->entry_point();)
}

void generate_all() {
// Generates all stubs and initializes the entry points

Expand Down Expand Up @@ -4044,11 +4155,13 @@ class StubGenerator: public StubCodeGenerator {


public:
StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
if (all) {
generate_all();
} else {
StubGenerator(CodeBuffer* code, int phase) : StubCodeGenerator(code) {
if (phase == 0) {
generate_initial();
} else if (phase == 1) {
generate_phase1(); // stubs that must be available for the interpreter
} else {
generate_all();
}
}
}; // end class declaration
Expand Down
15 changes: 10 additions & 5 deletions src/hotspot/share/runtime/signature.cpp
Expand Up @@ -116,7 +116,7 @@ ReferenceArgumentCount::ReferenceArgumentCount(Symbol* signature)
do_parameters_on(this); // non-virtual template execution
}

#ifdef ASSERT
#if !defined(_LP64) || defined(ZERO) || defined(ASSERT)
static int compute_num_stack_arg_slots(Symbol* signature, int sizeargs, bool is_static) {
ResourceMark rm;
BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs);
Expand All @@ -138,7 +138,7 @@ static int compute_num_stack_arg_slots(Symbol* signature, int sizeargs, bool is_

return SharedRuntime::java_calling_convention(sig_bt, regs, sizeargs);
}
#endif // ASSERT
#endif

void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) {
// See if we fingerprinted this method already
Expand Down Expand Up @@ -177,13 +177,15 @@ void Fingerprinter::compute_fingerprint_and_return_type(bool static_flag) {
_param_size += 1; // this is the convention for Method::compute_size_of_parameters
}

#if defined(_LP64) && !defined(ZERO)
_stack_arg_slots = align_up(_stack_arg_slots, 2);

#ifdef ASSERT
int dbg_stack_arg_slots = compute_num_stack_arg_slots(_signature, _param_size, static_flag);
#if defined(_LP64) && !defined(ZERO)
assert(_stack_arg_slots == dbg_stack_arg_slots, "fingerprinter: %d full: %d", _stack_arg_slots, dbg_stack_arg_slots);
#endif
#else
// Fallback: computed _stack_arg_slots is unreliable, compute directly.
_stack_arg_slots = compute_num_stack_arg_slots(_signature, _param_size, static_flag);
#endif

// Detect overflow. (We counted _param_size correctly.)
Expand Down Expand Up @@ -220,7 +222,10 @@ void Fingerprinter::initialize_calling_convention(bool static_flag) {

void Fingerprinter::do_type_calling_convention(BasicType type) {
// We compute the number of slots for stack-passed arguments in compiled calls.
// The value computed for 32-bit ports and for zero is bogus, and will need to be fixed.
// TODO: SharedRuntime::java_calling_convention is the shared code that knows all details
// about the platform-specific calling conventions. This method tries to compute the stack
// args number... poorly, at least for 32-bit ports and for zero. Current code has the fallback
// that recomputes the stack args number from SharedRuntime::java_calling_convention.
#if defined(_LP64) && !defined(ZERO)
switch (type) {
case T_VOID:
Expand Down