mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-23 00:35:13 +00:00
8286360: ARM32: Fix crashes after JDK-8284161 (Virtual Threads)
Co-authored-by: Sergey Nazarkin <snazarki@openjdk.org> Reviewed-by: dsamersoff
This commit is contained in:
parent
778ed1a760
commit
b6c6cc5d99
@ -518,7 +518,7 @@ void frame::describe_pd(FrameValues& values, int frame_no) {
|
||||
|
||||
// This is a generic constructor which is only used by pns() in debug.cpp.
|
||||
frame::frame(void* sp, void* fp, void* pc) {
|
||||
init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
|
||||
init((intptr_t*)sp, (intptr_t*)sp, (intptr_t*)fp, (address)pc);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -105,7 +105,7 @@
|
||||
|
||||
frame(intptr_t* sp, intptr_t* fp);
|
||||
|
||||
void init(intptr_t* sp, intptr_t* fp, address pc);
|
||||
void init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc);
|
||||
|
||||
// accessors for the instance variables
|
||||
// Note: not necessarily the real 'frame pointer' (see real_fp)
|
||||
|
||||
@ -40,6 +40,7 @@ inline frame::frame() {
|
||||
_cb = NULL;
|
||||
_deopt_state = unknown;
|
||||
_on_heap = false;
|
||||
_oop_map = NULL;
|
||||
DEBUG_ONLY(_frame_index = -1;)
|
||||
}
|
||||
|
||||
@ -47,31 +48,7 @@ inline frame::frame(intptr_t* sp) {
|
||||
Unimplemented();
|
||||
}
|
||||
|
||||
inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
||||
_sp = sp;
|
||||
_unextended_sp = sp;
|
||||
_fp = fp;
|
||||
_pc = pc;
|
||||
assert(pc != NULL, "no pc?");
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
adjust_unextended_sp();
|
||||
DEBUG_ONLY(_frame_index = -1;)
|
||||
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
_pc = original_pc;
|
||||
_deopt_state = is_deoptimized;
|
||||
} else {
|
||||
_deopt_state = not_deoptimized;
|
||||
}
|
||||
_on_heap = false;
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
|
||||
init(sp, fp, pc);
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
|
||||
inline void frame::init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
|
||||
_sp = sp;
|
||||
_unextended_sp = unextended_sp;
|
||||
_fp = fp;
|
||||
@ -85,34 +62,27 @@ inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address
|
||||
if (original_pc != NULL) {
|
||||
_pc = original_pc;
|
||||
assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
|
||||
"original PC must be in the main code section of the the compiled method (or must be immediately following it)");
|
||||
_deopt_state = is_deoptimized;
|
||||
} else {
|
||||
_deopt_state = not_deoptimized;
|
||||
}
|
||||
_on_heap = false;
|
||||
_oop_map = NULL;
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) {
|
||||
init(sp, sp, fp, pc);
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
|
||||
init(sp, unextended_sp, fp, pc);
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
||||
_sp = sp;
|
||||
_unextended_sp = sp;
|
||||
_fp = fp;
|
||||
assert(sp != NULL,"null SP ?");
|
||||
_pc = (address)(sp[-1]);
|
||||
// assert(_pc != NULL, "no pc?"); // see comments in x86
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
adjust_unextended_sp();
|
||||
DEBUG_ONLY(_frame_index = -1;)
|
||||
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
_pc = original_pc;
|
||||
_deopt_state = is_deoptimized;
|
||||
} else {
|
||||
_deopt_state = not_deoptimized;
|
||||
}
|
||||
_on_heap = false;
|
||||
assert(sp != NULL, "null SP?");
|
||||
address pc = (address)(sp[-1]);
|
||||
init(sp, sp, fp, pc);
|
||||
}
|
||||
|
||||
|
||||
@ -243,7 +213,16 @@ inline int frame::frame_size() const {
|
||||
}
|
||||
|
||||
inline const ImmutableOopMap* frame::get_oop_map() const {
|
||||
Unimplemented();
|
||||
if (_cb == NULL) return NULL;
|
||||
if (_cb->oop_maps() != NULL) {
|
||||
NativePostCallNop* nop = nativePostCallNop_at(_pc);
|
||||
if (nop != NULL && nop->displacement() != 0) {
|
||||
int slot = ((nop->displacement() >> 24) & 0xff);
|
||||
return _cb->oop_map_for_slot(slot, _pc);
|
||||
}
|
||||
const ImmutableOopMap* oop_map = OopMapSet::find_map(this);
|
||||
return oop_map;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -337,3 +337,25 @@ NativeCall* rawNativeCall_before(address return_address) {
|
||||
return nativeCall_at(call);
|
||||
}
|
||||
|
||||
void NativePostCallNop::make_deopt() {
|
||||
NativeDeoptInstruction::insert(addr_at(0));
|
||||
}
|
||||
|
||||
void NativePostCallNop::patch(jint diff) {
|
||||
// unsupported for now
|
||||
}
|
||||
|
||||
void NativeDeoptInstruction::verify() {
|
||||
}
|
||||
|
||||
// Inserts an undefined instruction at a given pc
|
||||
void NativeDeoptInstruction::insert(address code_pos) {
|
||||
// UDF, Encoding A1:
|
||||
// 1 1 1 0 | 0 1 1 1 | 1 1 1 1 | imm12 | 1 1 1 1 | imm4 |
|
||||
// e | 7 | f | dec | f | a |
|
||||
// 0xe7 | 0xfd, 0xec | 0xfa
|
||||
uint32_t insn = 0xe7fdecfa;
|
||||
uint32_t *pos = (uint32_t *) code_pos;
|
||||
*pos = insn;
|
||||
ICache::invalidate_range(code_pos, 4);
|
||||
}
|
||||
|
||||
@ -434,33 +434,40 @@ inline NativeCall* nativeCall_before(address return_address) {
|
||||
|
||||
class NativePostCallNop: public NativeInstruction {
|
||||
public:
|
||||
bool check() const { Unimplemented(); return false; }
|
||||
int displacement() const { Unimplemented(); return 0; }
|
||||
void patch(jint diff) { Unimplemented(); }
|
||||
void make_deopt() { Unimplemented(); }
|
||||
bool check() const { return is_nop(); }
|
||||
int displacement() const { return 0; }
|
||||
void patch(jint diff);
|
||||
void make_deopt();
|
||||
};
|
||||
|
||||
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||
Unimplemented();
|
||||
NativePostCallNop* nop = (NativePostCallNop*) address;
|
||||
if (nop->check()) {
|
||||
return nop;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
class NativeDeoptInstruction: public NativeInstruction {
|
||||
public:
|
||||
address instruction_address() const { Unimplemented(); return NULL; }
|
||||
address next_instruction_address() const { Unimplemented(); return NULL; }
|
||||
enum {
|
||||
instruction_size = 4,
|
||||
instruction_offset = 0,
|
||||
};
|
||||
|
||||
void verify() { Unimplemented(); }
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||
|
||||
void verify();
|
||||
|
||||
static bool is_deopt_at(address instr) {
|
||||
Unimplemented();
|
||||
return false;
|
||||
assert(instr != NULL, "");
|
||||
uint32_t value = *(uint32_t *) instr;
|
||||
return value == 0xe7fdecfa;
|
||||
}
|
||||
|
||||
// MT-safe patching
|
||||
static void insert(address code_pos) {
|
||||
Unimplemented();
|
||||
}
|
||||
static void insert(address code_pos);
|
||||
};
|
||||
|
||||
#endif // CPU_ARM_NATIVEINST_ARM_32_HPP
|
||||
|
||||
@ -2959,6 +2959,85 @@ class StubGenerator: public StubCodeGenerator {
|
||||
return stub->entry_point();
|
||||
}
|
||||
|
||||
RuntimeStub* generate_cont_doYield() {
|
||||
if (!Continuations::enabled()) return nullptr;
|
||||
Unimplemented();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
address generate_cont_thaw(const char* label, Continuation::thaw_kind kind) {
|
||||
if (!Continuations::enabled()) return nullptr;
|
||||
Unimplemented();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
address generate_cont_thaw() {
|
||||
return generate_cont_thaw("Cont thaw", Continuation::thaw_top);
|
||||
}
|
||||
|
||||
address generate_cont_returnBarrier() {
|
||||
return generate_cont_thaw("Cont thaw return barrier", Continuation::thaw_return_barrier);
|
||||
}
|
||||
|
||||
address generate_cont_returnBarrier_exception() {
|
||||
return generate_cont_thaw("Cont thaw return barrier exception", Continuation::thaw_return_barrier_exception);
|
||||
}
|
||||
|
||||
#if INCLUDE_JFR
|
||||
|
||||
// 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 {
|
||||
r1_off,
|
||||
r2_off,
|
||||
return_off,
|
||||
framesize // inclusive of return address
|
||||
};
|
||||
|
||||
CodeBuffer code("jfr_write_checkpoint", 512, 64);
|
||||
MacroAssembler* masm = new MacroAssembler(&code);
|
||||
|
||||
address start = __ pc();
|
||||
__ raw_push(R1, R2, LR);
|
||||
address the_pc = __ pc();
|
||||
|
||||
int frame_complete = the_pc - start;
|
||||
|
||||
__ set_last_Java_frame(SP, FP, true, Rtemp);
|
||||
__ mov(c_rarg0, Rthread);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint), c_rarg0);
|
||||
__ reset_last_Java_frame(Rtemp);
|
||||
|
||||
// R0 is jobject handle result, unpack and process it through a barrier.
|
||||
Label L_null_jobject;
|
||||
__ cbz(R0, L_null_jobject);
|
||||
|
||||
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs->load_at(masm, ACCESS_READ | IN_NATIVE, T_OBJECT, R0, Address(R0, 0), Rtemp, R1, R2);
|
||||
|
||||
__ bind(L_null_jobject);
|
||||
|
||||
__ raw_pop(R1, R2, LR);
|
||||
__ ret();
|
||||
|
||||
OopMapSet* oop_maps = new OopMapSet();
|
||||
OopMap* map = new OopMap(framesize, 1);
|
||||
oop_maps->add_gc_map(frame_complete, map);
|
||||
|
||||
RuntimeStub* stub =
|
||||
RuntimeStub::new_runtime_stub(code.name(),
|
||||
&code,
|
||||
frame_complete,
|
||||
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
|
||||
oop_maps,
|
||||
false);
|
||||
return stub;
|
||||
}
|
||||
|
||||
#endif // INCLUDE_JFR
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Initialization
|
||||
|
||||
@ -2991,6 +3070,18 @@ 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
|
||||
@ -3029,11 +3120,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();
|
||||
} else {
|
||||
generate_all();
|
||||
}
|
||||
}
|
||||
}; // end class declaration
|
||||
|
||||
@ -729,6 +729,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
|
||||
//
|
||||
|
||||
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||
if (!Continuations::enabled()) return nullptr;
|
||||
Unimplemented();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user