8286367: riscv: riscv port is broken after JDK-8284161

Co-authored-by: Fei Yang <fyang@openjdk.org>
Reviewed-by: coleenp, fyang
This commit is contained in:
Yadong Wang 2022-05-10 07:14:31 +00:00 committed by Alan Bateman
parent 4fd79a6ad2
commit bf0dc4f844
7 changed files with 165 additions and 33 deletions

View File

@ -93,8 +93,7 @@ inline void ContinuationHelper::InterpretedFrame::patch_sender_sp(frame& f, intp
}
inline address* ContinuationHelper::Frame::return_pc_address(const frame& f) {
Unimplemented();
return NULL;
return (address*)(f.real_fp() - 1);
}
inline address ContinuationHelper::Frame::real_pc(const frame& f) {

View File

@ -259,22 +259,25 @@ bool frame::safe_for_sender(JavaThread *thread) {
void frame::patch_pc(Thread* thread, address pc) {
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
address* pc_addr = &(((address*) sp())[-1]);
if (TracePcPatching) {
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
}
// Either the return address is the original one or we are going to
// patch in the same address that's already there.
assert(_pc == *pc_addr || pc == *pc_addr, "must be");
assert(_pc == *pc_addr || pc == *pc_addr || *pc_addr == 0, "must be");
DEBUG_ONLY(address old_pc = _pc;)
*pc_addr = pc;
_pc = pc; // must be set before call to get_deopt_original_pc
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
assert(original_pc == _pc, "expected original PC to be stored before patching");
assert(original_pc == old_pc, "expected original PC to be stored before patching");
_deopt_state = is_deoptimized;
// leave _pc as is
_pc = original_pc;
} else {
_deopt_state = not_deoptimized;
_pc = pc;
}
}
@ -378,6 +381,7 @@ void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
#ifdef ASSERT
void frame::adjust_unextended_sp() {
// On riscv, sites calling method handle intrinsics and lambda forms are treated
// as any other call site. Therefore, no special action is needed when we are
@ -394,6 +398,8 @@ void frame::adjust_unextended_sp() {
}
}
}
#endif
//------------------------------------------------------------------------------
// frame::sender_for_interpreter_frame

View File

@ -166,7 +166,7 @@
// original sp we use that convention.
intptr_t* _unextended_sp;
void adjust_unextended_sp();
void adjust_unextended_sp() NOT_DEBUG_RETURN;
intptr_t* ptr_at_addr(int offset) const {
return (intptr_t*) addr_at(offset);
@ -189,6 +189,7 @@
frame(intptr_t* ptr_sp, intptr_t* ptr_fp);
void init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc);
void setup(address pc);
// accessors for the instance variables
// Note: not necessarily the real 'frame pointer' (see real_fp)

View File

@ -29,6 +29,7 @@
#include "code/codeCache.hpp"
#include "code/vmreg.inline.hpp"
#include "runtime/sharedRuntime.hpp"
// Inline functions for RISCV frames:
@ -54,20 +55,31 @@ inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
_unextended_sp = ptr_sp;
_fp = ptr_fp;
_pc = pc;
_oop_map = NULL;
_on_heap = false;
DEBUG_ONLY(_frame_index = -1;)
assert(pc != NULL, "no pc?");
_cb = CodeCache::find_blob(pc);
setup(pc);
}
inline void frame::setup(address pc) {
adjust_unextended_sp();
address original_pc = CompiledMethod::get_deopt_original_pc(this);
if (original_pc != NULL) {
_pc = original_pc;
_deopt_state = is_deoptimized;
assert(_cb == NULL || _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)");
} else {
_deopt_state = not_deoptimized;
if (_cb == SharedRuntime::deopt_blob()) {
_deopt_state = is_deoptimized;
} else {
_deopt_state = not_deoptimized;
}
}
_on_heap = false;
DEBUG_ONLY(_frame_index = -1;)
}
inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
@ -83,20 +95,11 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* unextended_sp, intptr_t* ptr_fp,
_pc = pc;
assert(pc != NULL, "no pc?");
_cb = CodeCache::find_blob(pc);
adjust_unextended_sp();
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;
}
_oop_map = NULL;
_on_heap = false;
DEBUG_ONLY(_frame_index = -1;)
setup(pc);
}
inline frame::frame(intptr_t* ptr_sp) {
@ -293,7 +296,11 @@ inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
PRAGMA_DIAG_POP
inline const ImmutableOopMap* frame::get_oop_map() const {
Unimplemented();
if (_cb == NULL) return NULL;
if (_cb->oop_maps() != NULL) {
const ImmutableOopMap* oop_map = OopMapSet::find_map(this);
return oop_map;
}
return NULL;
}

View File

@ -28,6 +28,7 @@
#define CPU_RISCV_NATIVEINST_RISCV_HPP
#include "asm/assembler.hpp"
#include "runtime/continuation.hpp"
#include "runtime/icache.hpp"
#include "runtime/os.hpp"
@ -195,7 +196,7 @@ class NativeInstruction {
}
static bool is_lwu_to_zr(address instr);
inline bool is_nop();
inline bool is_nop() const;
inline bool is_jump_or_nop();
bool is_safepoint_poll();
bool is_sigill_zombie_not_entrant();
@ -494,7 +495,7 @@ class NativeIllegalInstruction: public NativeInstruction {
static void insert(address code_pos);
};
inline bool NativeInstruction::is_nop() {
inline bool NativeInstruction::is_nop() const {
uint32_t insn = *(uint32_t*)addr_at(0);
return insn == 0x13;
}
@ -571,14 +572,17 @@ public:
class NativePostCallNop: public NativeInstruction {
public:
bool check() const { Unimplemented(); return false; }
int displacement() const { Unimplemented(); return 0; }
bool check() const { return is_nop(); }
int displacement() const { return 0; }
void patch(jint diff) { Unimplemented(); }
void make_deopt() { Unimplemented(); }
};
inline NativePostCallNop* nativePostCallNop_at(address address) {
Unimplemented();
NativePostCallNop* nop = (NativePostCallNop*) address;
if (nop->check()) {
return nop;
}
return NULL;
}
@ -590,6 +594,7 @@ public:
void verify() { Unimplemented(); }
static bool is_deopt_at(address instr) {
if (!Continuations::enabled()) return false;
Unimplemented();
return false;
}

View File

@ -3700,6 +3700,100 @@ class StubGenerator: public StubCodeGenerator {
return stub->entry_point();
}
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;
}
RuntimeStub* generate_cont_doYield() {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return nullptr;
}
#if INCLUDE_JFR
#undef __
#define __ _masm->
static void jfr_prologue(address the_pc, MacroAssembler* _masm, Register thread) {
__ set_last_Java_frame(sp, fp, the_pc, t0);
__ mv(c_rarg0, thread);
}
static void jfr_epilogue(MacroAssembler* _masm, Register thread) {
__ reset_last_Java_frame(true);
Label null_jobject;
__ beqz(x10, null_jobject);
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->load_at(_masm, decorators, T_OBJECT, x10, Address(x10, 0), c_rarg0, thread);
__ bind(null_jobject);
}
static RuntimeStub* generate_jfr_stub(const char* name, address entrypoint) {
enum layout {
fp_off,
fp_off2,
return_off,
return_off2,
framesize // inclusive of return address
};
int insts_size = 512;
int locs_size = 64;
CodeBuffer code(name, 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, xthread);
__ call_VM_leaf(entrypoint, 1);
jfr_epilogue(_masm, xthread);
__ leave();
__ ret();
OopMap* map = new OopMap(framesize, 1);
oop_maps->add_gc_map(the_pc - start, map);
RuntimeStub* stub = // codeBlob framesize is in words (not VMRegImpl::slot_size)
RuntimeStub::new_runtime_stub(name, &code, frame_complete,
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
oop_maps, false);
return stub;
}
#undef __
RuntimeStub* generate_jfr_write_checkpoint() {
return generate_jfr_stub("jfr_write_checkpoint",
CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint));
}
RuntimeStub* generate_jfr_get_event_writer() {
return generate_jfr_stub("jfr_get_event_writer",
CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::event_writer));
}
#endif // INCLUDE_JFR
// Initialization
void generate_initial() {
// Generate initial stubs and initializes the entry points
@ -3729,6 +3823,23 @@ class StubGenerator: public StubCodeGenerator {
SharedRuntime::throw_delayed_StackOverflowError));
}
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 == nullptr ? nullptr
: StubRoutines::_jfr_write_checkpoint_stub->entry_point();)
JFR_ONLY(StubRoutines::_jfr_get_event_writer_stub = generate_jfr_get_event_writer();)
JFR_ONLY(StubRoutines::_jfr_get_event_writer = StubRoutines::_jfr_get_event_writer_stub == nullptr ? nullptr
: StubRoutines::_jfr_get_event_writer_stub->entry_point();)
}
void generate_all() {
// support for verify_oop (must happen after universe_init)
if (VerifyOops) {
@ -3798,11 +3909,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();
}
}

View File

@ -798,6 +798,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) {
// End of helpers
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
if (!Continuations::enabled()) return nullptr;
Unimplemented();
return NULL;
}