Skip to content
Permalink
Browse files
8286476: x86_32: Fix crashes with non-preview mode after JDK-8284161 …
…(Virtual Threads)

Reviewed-by: coleenp, stuefe
  • Loading branch information
shipilev committed May 11, 2022
1 parent 87f3d2b commit ae695d6cb79afbca6e38ede59b366ec55eced76a
Showing 2 changed files with 127 additions and 9 deletions.
@@ -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

@@ -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

@@ -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
@@ -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);
@@ -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
@@ -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.)
@@ -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:

1 comment on commit ae695d6

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on ae695d6 May 11, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.