Skip to content
Permalink
Browse files
8264774: Implementation of Foreign Function and Memory API (Incubator)
Co-authored-by: Paul Sandoz <psandoz@openjdk.org>
Co-authored-by: Jorn Vernee <jvernee@openjdk.org>
Co-authored-by: Vladimir Ivanov <vlivanov@openjdk.org>
Co-authored-by: Athijegannathan Sundararajan <sundar@openjdk.org>
Co-authored-by: Chris Hegarty <chegar@openjdk.org>
Reviewed-by: psandoz, chegar, mchung, vlivanov
  • Loading branch information
6 people committed Jun 2, 2021
1 parent 71425dd commit a223189b069a7cfe49511d49b5b09e7107cb3cab
Showing 219 changed files with 10,889 additions and 5,648 deletions.
@@ -84,3 +84,8 @@ const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) con

return layout;
}

const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const {
ShouldNotCallThis();
return {};
}
@@ -359,6 +359,16 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const {
return fr;
}

JavaFrameAnchor* OptimizedEntryBlob::jfa_for_frame(const frame& frame) const {
ShouldNotCallThis();
return nullptr;
}

frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const {
ShouldNotCallThis();
return {};
}

//------------------------------------------------------------------------------
// frame::verify_deopt_original_pc
//
@@ -878,7 +878,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
// 64 bits items (Aarch64 abi) even though java would only store
// 32bits for a parameter. On 32bit it will simply be 32 bits
// So this routine will do 32->32 on 32bit and 32->64 on 64bit
static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
if (src.first()->is_stack()) {
if (dst.first()->is_stack()) {
// stack to stack
@@ -979,7 +979,7 @@ static void object_move(MacroAssembler* masm,
}

// A float arg may have to do float reg int reg conversion
static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
assert(src.first()->is_stack() && dst.first()->is_stack() ||
src.first()->is_reg() && dst.first()->is_reg(), "Unexpected error");
if (src.first()->is_stack()) {
@@ -998,7 +998,7 @@ static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}

// A long move
static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
if (src.first()->is_stack()) {
if (dst.first()->is_stack()) {
// stack to stack
@@ -1022,7 +1022,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {


// A double move
static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
assert(src.first()->is_stack() && dst.first()->is_stack() ||
src.first()->is_reg() && dst.first()->is_reg(), "Unexpected error");
if (src.first()->is_stack()) {
@@ -99,3 +99,12 @@ address ProgrammableUpcallHandler::generate_upcall_stub(jobject rec, jobject jab

return blob->code_begin();
}

address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject mh, Method* entry, jobject jabi, jobject jconv) {
ShouldNotCallThis();
return nullptr;
}

bool ProgrammableUpcallHandler::supports_optimized_upcalls() {
return false;
}
@@ -87,3 +87,32 @@ const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) con

return layout;
}

const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const {
oop conv_oop = JNIHandles::resolve_non_null(jconv);
objArrayOop arg_regs_oop = cast<objArrayOop>(conv_oop->obj_field(CallConvOffsets.arg_regs_offset));
objArrayOop ret_regs_oop = cast<objArrayOop>(conv_oop->obj_field(CallConvOffsets.ret_regs_offset));

CallRegs result;
result._args_length = arg_regs_oop->length();
result._arg_regs = NEW_RESOURCE_ARRAY(VMReg, result._args_length);

result._rets_length = ret_regs_oop->length();
result._ret_regs = NEW_RESOURCE_ARRAY(VMReg, result._rets_length);

for (int i = 0; i < result._args_length; i++) {
oop storage = arg_regs_oop->obj_at(i);
jint index = storage->int_field(VMS.index_offset);
jint type = storage->int_field(VMS.type_offset);
result._arg_regs[i] = VMRegImpl::vmStorageToVMReg(type, index);
}

for (int i = 0; i < result._rets_length; i++) {
oop storage = ret_regs_oop->obj_at(i);
jint index = storage->int_field(VMS.index_offset);
jint type = storage->int_field(VMS.type_offset);
result._ret_regs[i] = VMRegImpl::vmStorageToVMReg(type, index);
}

return result;
}
@@ -102,6 +102,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
if (is_entry_frame()) {
// an entry frame must have a valid fp.
return fp_safe && is_entry_frame_valid(thread);
} else if (is_optimized_entry_frame()) {
return fp_safe;
}

intptr_t* sender_sp = NULL;
@@ -199,6 +201,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
address jcw = (address)sender.entry_frame_call_wrapper();

return thread->is_in_stack_range_excl(jcw, (address)sender.fp());
} else if (sender_blob->is_optimized_entry_blob()) {
return false;
}

CompiledMethod* nm = sender_blob->as_compiled_method_or_null();
@@ -349,6 +353,32 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const {
return fr;
}

JavaFrameAnchor* OptimizedEntryBlob::jfa_for_frame(const frame& frame) const {
// need unextended_sp here, since normal sp is wrong for interpreter callees
return reinterpret_cast<JavaFrameAnchor*>(reinterpret_cast<char*>(frame.unextended_sp()) + in_bytes(jfa_sp_offset()));
}

frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const {
assert(map != NULL, "map must be set");
OptimizedEntryBlob* blob = _cb->as_optimized_entry_blob();
// Java frame called from C; skip all C frames and return top C
// frame of that chunk as the sender
JavaFrameAnchor* jfa = blob->jfa_for_frame(*this);
assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
// Since we are walking the stack now this nested anchor is obviously walkable
// even if it wasn't when it was stacked.
if (!jfa->walkable()) {
// Capture _last_Java_pc (if needed) and mark anchor walkable.
jfa->capture_last_Java_pc();
}
map->clear();
assert(map->include_argument_oops(), "should be set by clear");
vmassert(jfa->last_Java_pc() != NULL, "not walkable");
frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc());

return fr;
}

//------------------------------------------------------------------------------
// frame::verify_deopt_original_pc
//
@@ -478,8 +508,9 @@ frame frame::sender_raw(RegisterMap* map) const {
// update it accordingly
map->set_include_argument_oops(false);

if (is_entry_frame()) return sender_for_entry_frame(map);
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
if (is_entry_frame()) return sender_for_entry_frame(map);
if (is_optimized_entry_frame()) return sender_for_optimized_entry_frame(map);
if (is_interpreted_frame()) return sender_for_interpreter_frame(map);
assert(_cb == CodeCache::find_blob(pc()),"Must be the same");

if (_cb != NULL) {
@@ -70,8 +70,6 @@

address last_Java_pc(void) { return _last_Java_pc; }

private:

static ByteSize last_Java_fp_offset() { return byte_offset_of(JavaFrameAnchor, _last_Java_fp); }

public:
@@ -1124,7 +1124,7 @@ static void object_move(MacroAssembler* masm,
}

// A float arg may have to do float reg int reg conversion
static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
assert(!src.second()->is_valid() && !dst.second()->is_valid(), "bad float_move");

// Because of the calling convention we know that src is either a stack location
@@ -1142,7 +1142,7 @@ static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}

// A long move
static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {

// The only legal possibility for a long_move VMRegPair is:
// 1: two stack slots (possibly unaligned)
@@ -1161,7 +1161,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}

// A double move
static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {

// The only legal possibilities for a double_move VMRegPair are:
// The painful thing here is that like long_move a VMRegPair might be
@@ -1167,7 +1167,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
// 64 bits items (x86_32/64 abi) even though java would only store
// 32bits for a parameter. On 32bit it will simply be 32 bits
// So this routine will do 32->32 on 32bit and 32->64 on 64bit
static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
if (src.first()->is_stack()) {
if (dst.first()->is_stack()) {
// stack to stack
@@ -1285,7 +1285,7 @@ static void object_move(MacroAssembler* masm,
}

// A float arg may have to do float reg int reg conversion
static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
assert(!src.second()->is_valid() && !dst.second()->is_valid(), "bad float_move");

// The calling conventions assures us that each VMregpair is either
@@ -1314,7 +1314,7 @@ static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}

// A long move
static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {

// The calling conventions assures us that each VMregpair is either
// all really one physical register or adjacent stack slots.
@@ -1339,7 +1339,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}

// A double move
static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
void SharedRuntime::double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {

// The calling conventions assures us that each VMregpair is either
// all really one physical register or adjacent stack slots.