Skip to content

Commit

Permalink
8286360: ARM32: Fix crashes after JDK-8284161 (Virtual Threads)
Browse files Browse the repository at this point in the history
Co-authored-by: Sergey Nazarkin <snazarki@openjdk.org>
Reviewed-by: dsamersoff
  • Loading branch information
shipilev and Sergey Nazarkin committed Jun 7, 2022
1 parent 778ed1a commit b6c6cc5
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/hotspot/cpu/arm/frame_arm.cpp
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/cpu/arm/frame_arm.hpp
Expand Up @@ -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)
Expand Down
63 changes: 21 additions & 42 deletions src/hotspot/cpu/arm/frame_arm.inline.hpp
Expand Up @@ -40,16 +40,17 @@ inline frame::frame() {
_cb = NULL;
_deopt_state = unknown;
_on_heap = false;
_oop_map = NULL;
DEBUG_ONLY(_frame_index = -1;)
}

inline frame::frame(intptr_t* sp) {
Unimplemented();
}

inline void frame::init(intptr_t* 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 = sp;
_unextended_sp = unextended_sp;
_fp = fp;
_pc = pc;
assert(pc != NULL, "no pc?");
Expand All @@ -60,59 +61,28 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
address original_pc = CompiledMethod::get_deopt_original_pc(this);
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 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, fp, pc);
init(sp, sp, fp, pc);
}

inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) {
_sp = sp;
_unextended_sp = unextended_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;
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)");
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
}
_on_heap = false;
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);
}


Expand Down Expand Up @@ -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;
}

Expand Down
22 changes: 22 additions & 0 deletions src/hotspot/cpu/arm/nativeInst_arm_32.cpp
Expand Up @@ -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);
}
33 changes: 20 additions & 13 deletions src/hotspot/cpu/arm/nativeInst_arm_32.hpp
Expand Up @@ -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
101 changes: 97 additions & 4 deletions src/hotspot/cpu/arm/stubGenerator_arm.cpp
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp
Expand Up @@ -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;
}
Expand Down

0 comments on commit b6c6cc5

Please sign in to comment.