8286446: PPC64: fix crashes after JDK-8284161 (virtual threads preview)
Reviewed-by: mdoerr, coleenp, shade
This commit is contained in:
parent
7a2bbbbce5
commit
87f3d2b870
@ -229,20 +229,39 @@ address* frame::compiled_sender_pc_addr(CodeBlob* cb) const {
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
address* pc_addr = (address*)&(own_abi()->lr);
|
||||
|
||||
if (TracePcPatching) {
|
||||
tty->print_cr("patch_pc at address " PTR_FORMAT " [" PTR_FORMAT " -> " PTR_FORMAT "]",
|
||||
p2i(&((address*) _sp)[-1]), p2i(((address*) _sp)[-1]), p2i(pc));
|
||||
}
|
||||
assert(!Continuation::is_return_barrier_entry(*pc_addr), "return barrier");
|
||||
assert(_pc == *pc_addr || pc == *pc_addr || 0 == *pc_addr,
|
||||
"must be (pc: " INTPTR_FORMAT " _pc: " INTPTR_FORMAT " pc_addr: " INTPTR_FORMAT
|
||||
" *pc_addr: " INTPTR_FORMAT " sp: " INTPTR_FORMAT ")",
|
||||
p2i(pc), p2i(_pc), p2i(pc_addr), p2i(*pc_addr), p2i(sp()));
|
||||
DEBUG_ONLY(address old_pc = _pc;)
|
||||
own_abi()->lr = (uint64_t)pc;
|
||||
if (_cb != NULL && _cb->is_nmethod() && ((nmethod*)_cb)->is_deopt_pc(_pc)) {
|
||||
address orig = (((nmethod*)_cb)->get_original_pc(this));
|
||||
assert(orig == _pc, "expected original to be stored before patching");
|
||||
_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 == 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;
|
||||
}
|
||||
assert(!is_compiled_frame() || !_cb->as_compiled_method()->is_deopt_entry(_pc), "must be");
|
||||
|
||||
#ifdef ASSERT
|
||||
{
|
||||
frame f(this->sp(), pc, this->unextended_sp());
|
||||
assert(f.is_deoptimized_frame() == this->is_deoptimized_frame() && f.pc() == this->pc() && f.raw_pc() == this->raw_pc(),
|
||||
"must be (f.is_deoptimized_frame(): %d this->is_deoptimized_frame(): %d "
|
||||
"f.pc(): " INTPTR_FORMAT " this->pc(): " INTPTR_FORMAT " f.raw_pc(): " INTPTR_FORMAT " this->raw_pc(): " INTPTR_FORMAT ")",
|
||||
f.is_deoptimized_frame(), this->is_deoptimized_frame(), p2i(f.pc()), p2i(this->pc()), p2i(f.raw_pc()), p2i(this->raw_pc()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool frame::is_interpreted_frame_valid(JavaThread* thread) const {
|
||||
@ -384,9 +403,14 @@ intptr_t *frame::initial_deoptimization_info() {
|
||||
#ifndef PRODUCT
|
||||
// This is a generic constructor which is only used by pns() in debug.cpp.
|
||||
frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp),
|
||||
_pc((address)pc),
|
||||
_cb(NULL),
|
||||
_oop_map(NULL),
|
||||
_on_heap(false),
|
||||
_unextended_sp((intptr_t*)sp) {
|
||||
find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp
|
||||
DEBUG_ONLY(_frame_index(-1) COMMA)
|
||||
_unextended_sp((intptr_t*)sp),
|
||||
_fp(NULL) {
|
||||
setup(); // also sets _fp and adjusts _unextended_sp
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -374,8 +374,8 @@
|
||||
|
||||
private:
|
||||
|
||||
// Find codeblob and set deopt_state.
|
||||
inline void find_codeblob_and_set_pc_and_deopt_state(address pc);
|
||||
// Initialize frame members (_pc and _sp must be given)
|
||||
inline void setup();
|
||||
|
||||
public:
|
||||
|
||||
@ -383,7 +383,7 @@
|
||||
|
||||
// Constructors
|
||||
inline frame(intptr_t* sp, address pc);
|
||||
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp);
|
||||
inline frame(intptr_t* sp, address pc, intptr_t* unextended_sp, intptr_t* fp = nullptr, CodeBlob* cb = nullptr);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -28,61 +28,66 @@
|
||||
|
||||
#include "code/codeCache.hpp"
|
||||
#include "code/vmreg.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
|
||||
// Inline functions for ppc64 frames:
|
||||
|
||||
// Find codeblob and set deopt_state.
|
||||
inline void frame::find_codeblob_and_set_pc_and_deopt_state(address pc) {
|
||||
assert(pc != NULL, "precondition: must have PC");
|
||||
// Initialize frame members (_pc and _sp must be given)
|
||||
inline void frame::setup() {
|
||||
assert(_pc != nullptr, "precondition: must have PC");
|
||||
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
_pc = pc; // Must be set for get_deopt_original_pc()
|
||||
|
||||
_fp = (intptr_t*)own_abi()->callers_sp;
|
||||
|
||||
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;
|
||||
if (_cb == nullptr) {
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
}
|
||||
|
||||
assert(((uint64_t)_sp & 0xf) == 0, "SP must be 16-byte aligned");
|
||||
if (_fp == nullptr) {
|
||||
_fp = (intptr_t*)own_abi()->callers_sp;
|
||||
}
|
||||
|
||||
// When thawing continuation frames the _unextended_sp passed to the constructor is not aligend
|
||||
assert(_on_heap || (is_aligned(_sp, alignment_in_bytes) && is_aligned(_fp, alignment_in_bytes)),
|
||||
"invalid alignment sp:" PTR_FORMAT " unextended_sp:" PTR_FORMAT " fp:" PTR_FORMAT, p2i(_sp), p2i(_unextended_sp), p2i(_fp));
|
||||
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != nullptr) {
|
||||
_pc = original_pc;
|
||||
_deopt_state = is_deoptimized;
|
||||
assert(_cb == nullptr || _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)");
|
||||
} else {
|
||||
if (_cb == SharedRuntime::deopt_blob()) {
|
||||
_deopt_state = is_deoptimized;
|
||||
} else {
|
||||
_deopt_state = not_deoptimized;
|
||||
}
|
||||
}
|
||||
|
||||
assert(_on_heap || is_aligned(_sp, frame::frame_alignment), "SP must be 16-byte aligned");
|
||||
}
|
||||
|
||||
// Constructors
|
||||
|
||||
// Initialize all fields, _unextended_sp will be adjusted in find_codeblob_and_set_pc_and_deopt_state.
|
||||
inline frame::frame() : _sp(NULL), _pc(NULL), _cb(NULL), _deopt_state(unknown), _on_heap(false),
|
||||
#ifdef ASSERT
|
||||
_frame_index(-1),
|
||||
#endif
|
||||
_unextended_sp(NULL), _fp(NULL) {}
|
||||
inline frame::frame() : _sp(nullptr), _pc(nullptr), _cb(nullptr), _oop_map(nullptr), _deopt_state(unknown),
|
||||
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(nullptr), _fp(nullptr) {}
|
||||
|
||||
inline frame::frame(intptr_t* sp) : _sp(sp), _on_heap(false),
|
||||
#ifdef ASSERT
|
||||
_frame_index(-1),
|
||||
#endif
|
||||
_unextended_sp(sp) {
|
||||
find_codeblob_and_set_pc_and_deopt_state((address)own_abi()->lr); // also sets _fp and adjusts _unextended_sp
|
||||
inline frame::frame(intptr_t* sp)
|
||||
: _sp(sp), _pc((address)own_abi()->lr), _cb(nullptr), _oop_map(nullptr),
|
||||
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(sp), _fp(nullptr) {
|
||||
setup();
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, address pc) : _sp(sp), _on_heap(false),
|
||||
#ifdef ASSERT
|
||||
_frame_index(-1),
|
||||
#endif
|
||||
_unextended_sp(sp) {
|
||||
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
||||
inline frame::frame(intptr_t* sp, address pc)
|
||||
: _sp(sp), _pc(pc), _cb(nullptr), _oop_map(nullptr),
|
||||
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(sp), _fp(nullptr) {
|
||||
setup();
|
||||
}
|
||||
|
||||
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp) : _sp(sp), _on_heap(false),
|
||||
#ifdef ASSERT
|
||||
_frame_index(-1),
|
||||
#endif
|
||||
_unextended_sp(unextended_sp) {
|
||||
find_codeblob_and_set_pc_and_deopt_state(pc); // also sets _fp and adjusts _unextended_sp
|
||||
inline frame::frame(intptr_t* sp, address pc, intptr_t* unextended_sp, intptr_t* fp, CodeBlob* cb)
|
||||
: _sp(sp), _pc(pc), _cb(nullptr), _oop_map(nullptr),
|
||||
_on_heap(false), DEBUG_ONLY(_frame_index(-1) COMMA) _unextended_sp(unextended_sp), _fp(fp) {
|
||||
setup();
|
||||
}
|
||||
|
||||
// Accessors
|
||||
@ -233,7 +238,16 @@ inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -506,13 +506,13 @@ class NativeMovRegMem: public NativeInstruction {
|
||||
class NativePostCallNop: public NativeInstruction {
|
||||
public:
|
||||
bool check() const { Unimplemented(); return false; }
|
||||
int displacement() const { Unimplemented(); return 0; }
|
||||
int displacement() const { return 0; }
|
||||
void patch(jint diff) { Unimplemented(); }
|
||||
void make_deopt() { Unimplemented(); }
|
||||
};
|
||||
|
||||
inline NativePostCallNop* nativePostCallNop_at(address address) {
|
||||
Unimplemented();
|
||||
// Unimplemented();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -524,7 +524,7 @@ public:
|
||||
void verify() { Unimplemented(); }
|
||||
|
||||
static bool is_deopt_at(address instr) {
|
||||
Unimplemented();
|
||||
// Unimplemented();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -4501,6 +4501,87 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
#endif // VM_LITTLE_ENDIAN
|
||||
|
||||
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
|
||||
|
||||
// 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.
|
||||
RuntimeStub* generate_jfr_write_checkpoint() {
|
||||
Register tmp1 = R10_ARG8;
|
||||
Register tmp2 = R9_ARG7;
|
||||
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;
|
||||
|
||||
int framesize = frame::abi_reg_args_size / VMRegImpl::stack_slot_size;
|
||||
address start = __ pc();
|
||||
__ mflr(tmp1);
|
||||
__ std(tmp1, _abi0(lr), R1_SP); // save return pc
|
||||
__ push_frame_reg_args(0, tmp1);
|
||||
int frame_complete = __ pc() - start;
|
||||
__ set_last_Java_frame(R1_SP, noreg);
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, JfrIntrinsicSupport::write_checkpoint), R16_thread);
|
||||
address calls_return_pc = __ last_calls_return_pc();
|
||||
__ reset_last_Java_frame();
|
||||
// The handle is dereferenced through a load barrier.
|
||||
Label null_jobject;
|
||||
__ cmpdi(CCR0, R3_RET, 0);
|
||||
__ beq(CCR0, null_jobject);
|
||||
DecoratorSet decorators = ACCESS_READ | IN_NATIVE;
|
||||
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
|
||||
bs->load_at(_masm, decorators, T_OBJECT, R3_RET /*base*/, (intptr_t)0, R3_RET /*dst*/, tmp1, tmp2, MacroAssembler::PRESERVATION_NONE);
|
||||
__ bind(null_jobject);
|
||||
__ pop_frame();
|
||||
__ ld(tmp1, _abi0(lr), R1_SP);
|
||||
__ mtlr(tmp1);
|
||||
__ blr();
|
||||
|
||||
OopMap* map = new OopMap(framesize, 0);
|
||||
oop_maps->add_gc_map(calls_return_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
|
||||
void generate_initial() {
|
||||
// Generates all stubs and initializes the entry points
|
||||
@ -4536,6 +4617,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
|
||||
|
||||
@ -4608,11 +4702,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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -477,6 +477,7 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) {
|
||||
}
|
||||
|
||||
address TemplateInterpreterGenerator::generate_Continuation_doYield_entry(void) {
|
||||
if (!Continuations::enabled()) return nullptr;
|
||||
Unimplemented();
|
||||
return NULL;
|
||||
}
|
||||
|
@ -104,6 +104,7 @@ bool Continuation::is_continuation_scope_mounted(JavaThread* thread, oop cont_sc
|
||||
// The continuation object can be extracted from the thread.
|
||||
bool Continuation::is_cont_barrier_frame(const frame& f) {
|
||||
assert(f.is_interpreted_frame() || f.cb() != nullptr, "");
|
||||
if (!Continuations::enabled()) return false;
|
||||
return is_return_barrier_entry(f.is_interpreted_frame() ? ContinuationHelper::InterpretedFrame::return_pc(f)
|
||||
: ContinuationHelper::CompiledFrame::return_pc(f));
|
||||
}
|
||||
|
@ -230,6 +230,14 @@ void Fingerprinter::do_type_calling_convention(BasicType type) {
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT:
|
||||
#if defined(PPC64)
|
||||
if (_int_args < Argument::n_int_register_parameters_j) {
|
||||
_int_args++;
|
||||
} else {
|
||||
_stack_arg_slots += 1;
|
||||
}
|
||||
break;
|
||||
#endif // defined(PPC64)
|
||||
case T_LONG:
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
@ -237,14 +245,24 @@ void Fingerprinter::do_type_calling_convention(BasicType type) {
|
||||
if (_int_args < Argument::n_int_register_parameters_j) {
|
||||
_int_args++;
|
||||
} else {
|
||||
PPC64_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
|
||||
_stack_arg_slots += 2;
|
||||
}
|
||||
break;
|
||||
case T_FLOAT:
|
||||
#if defined(PPC64)
|
||||
if (_fp_args < Argument::n_float_register_parameters_j) {
|
||||
_fp_args++;
|
||||
} else {
|
||||
_stack_arg_slots += 1;
|
||||
}
|
||||
break;
|
||||
#endif // defined(PPC64)
|
||||
case T_DOUBLE:
|
||||
if (_fp_args < Argument::n_float_register_parameters_j) {
|
||||
_fp_args++;
|
||||
} else {
|
||||
PPC64_ONLY(_stack_arg_slots = align_up(_stack_arg_slots, 2));
|
||||
_stack_arg_slots += 2;
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user