Skip to content

Commit 0fb31db

Browse files
committed
8254231: Implementation of Foreign Linker API (Incubator)
Reviewed-by: coleenp, ihse, dholmes, vlivanov
1 parent 53f3835 commit 0fb31db

File tree

212 files changed

+67390
-179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

212 files changed

+67390
-179
lines changed

src/hotspot/cpu/aarch64/aarch64.ad

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,11 @@ int MachCallRuntimeNode::ret_addr_offset() {
17701770
}
17711771
}
17721772

1773+
int MachCallNativeNode::ret_addr_offset() {
1774+
ShouldNotReachHere();
1775+
return -1;
1776+
}
1777+
17731778
// Indicate if the safepoint node needs the polling page as an input
17741779

17751780
// the shared code plants the oop data at the start of the generated
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2019, Arm Limited. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
#include "precompiled.hpp"
26+
#include "runtime/jniHandles.hpp"
27+
#include "runtime/jniHandles.inline.hpp"
28+
#include "oops/typeArrayOop.inline.hpp"
29+
#include "prims/foreign_globals.hpp"
30+
#include "prims/foreign_globals.inline.hpp"
31+
32+
bool ABIDescriptor::is_volatile_reg(Register reg) const {
33+
return _integer_argument_registers.contains(reg)
34+
|| _integer_additional_volatile_registers.contains(reg);
35+
}
36+
37+
bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const {
38+
return _vector_argument_registers.contains(reg)
39+
|| _vector_additional_volatile_registers.contains(reg);
40+
}
41+
42+
#define INTEGER_TYPE 0
43+
#define VECTOR_TYPE 1
44+
45+
const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const {
46+
oop abi_oop = JNIHandles::resolve_non_null(jabi);
47+
ABIDescriptor abi;
48+
49+
objArrayOop inputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.inputStorage_offset));
50+
loadArray(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, as_Register);
51+
loadArray(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_FloatRegister);
52+
53+
objArrayOop outputStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.outputStorage_offset));
54+
loadArray(outputStorage, INTEGER_TYPE, abi._integer_return_registers, as_Register);
55+
loadArray(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_FloatRegister);
56+
57+
objArrayOop volatileStorage = cast<objArrayOop>(abi_oop->obj_field(ABI.volatileStorage_offset));
58+
loadArray(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, as_Register);
59+
loadArray(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_FloatRegister);
60+
61+
abi._stack_alignment_bytes = abi_oop->int_field(ABI.stackAlignment_offset);
62+
abi._shadow_space_bytes = abi_oop->int_field(ABI.shadowSpace_offset);
63+
64+
return abi;
65+
}
66+
67+
const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) const {
68+
oop layout_oop = JNIHandles::resolve_non_null(jlayout);
69+
BufferLayout layout;
70+
71+
layout.stack_args_bytes = layout_oop->long_field(BL.stack_args_bytes_offset);
72+
layout.stack_args = layout_oop->long_field(BL.stack_args_offset);
73+
layout.arguments_next_pc = layout_oop->long_field(BL.arguments_next_pc_offset);
74+
75+
typeArrayOop input_offsets = cast<typeArrayOop>(layout_oop->obj_field(BL.input_type_offsets_offset));
76+
layout.arguments_integer = (size_t) input_offsets->long_at(INTEGER_TYPE);
77+
layout.arguments_vector = (size_t) input_offsets->long_at(VECTOR_TYPE);
78+
79+
typeArrayOop output_offsets = cast<typeArrayOop>(layout_oop->obj_field(BL.output_type_offsets_offset));
80+
layout.returns_integer = (size_t) output_offsets->long_at(INTEGER_TYPE);
81+
layout.returns_vector = (size_t) output_offsets->long_at(VECTOR_TYPE);
82+
83+
layout.buffer_size = layout_oop->long_field(BL.size_offset);
84+
85+
return layout;
86+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2019, Arm Limited. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
#ifndef CPU_AARCH64_VM_FOREIGN_GLOBALS_AARCH64_HPP
26+
#define CPU_AARCH64_VM_FOREIGN_GLOBALS_AARCH64_HPP
27+
28+
#include "asm/macroAssembler.hpp"
29+
#include "utilities/growableArray.hpp"
30+
31+
constexpr size_t float_reg_size = 16; // bytes
32+
33+
struct ABIDescriptor {
34+
GrowableArray<Register> _integer_argument_registers;
35+
GrowableArray<Register> _integer_return_registers;
36+
GrowableArray<FloatRegister> _vector_argument_registers;
37+
GrowableArray<FloatRegister> _vector_return_registers;
38+
39+
GrowableArray<Register> _integer_additional_volatile_registers;
40+
GrowableArray<FloatRegister> _vector_additional_volatile_registers;
41+
42+
int32_t _stack_alignment_bytes;
43+
int32_t _shadow_space_bytes;
44+
45+
bool is_volatile_reg(Register reg) const;
46+
bool is_volatile_reg(FloatRegister reg) const;
47+
};
48+
49+
struct BufferLayout {
50+
size_t stack_args_bytes;
51+
size_t stack_args;
52+
size_t arguments_vector;
53+
size_t arguments_integer;
54+
size_t arguments_next_pc;
55+
size_t returns_vector;
56+
size_t returns_integer;
57+
size_t buffer_size;
58+
};
59+
60+
#endif // CPU_AARCH64_VM_FOREIGN_GLOBALS_AARCH64_HPP

src/hotspot/cpu/aarch64/methodHandles_aarch64.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
178178
return NULL;
179179
}
180180

181+
// No need in interpreter entry for linkToNative for now.
182+
// Interpreter calls compiled entry through i2c.
183+
if (iid == vmIntrinsics::_linkToNative) {
184+
__ hlt(0);
185+
return NULL;
186+
}
187+
181188
// r13: sender SP (must preserve; see prepare_to_jump_from_interpreted)
182189
// rmethod: Method*
183190
// r3: argument locator (parameter slot count, added to rsp)
@@ -272,7 +279,10 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
272279
assert_different_registers(temp1, temp2, temp3, receiver_reg);
273280
assert_different_registers(temp1, temp2, temp3, member_reg);
274281

275-
if (iid == vmIntrinsics::_invokeBasic) {
282+
if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) {
283+
if (iid == vmIntrinsics::_linkToNative) {
284+
assert(for_compiler_entry, "only compiler entry is supported");
285+
}
276286
// indirect through MH.form.vmentry.vmtarget
277287
jump_to_lambda_form(_masm, receiver_reg, rmethod, temp1, for_compiler_entry);
278288

src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ static void gen_special_dispatch(MacroAssembler* masm,
11951195
member_arg_pos = method->size_of_parameters() - 1; // trailing MemberName argument
11961196
member_reg = r19; // known to be free at this point
11971197
has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind);
1198-
} else if (iid == vmIntrinsics::_invokeBasic) {
1198+
} else if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) {
11991199
has_receiver = true;
12001200
} else {
12011201
fatal("unexpected intrinsic id %d", iid);
@@ -3069,3 +3069,10 @@ void OptoRuntime::generate_exception_blob() {
30693069
_exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
30703070
}
30713071
#endif // COMPILER2
3072+
3073+
BufferBlob* SharedRuntime::make_native_invoker(address call_target,
3074+
int shadow_space_bytes,
3075+
const GrowableArray<VMReg>& input_registers,
3076+
const GrowableArray<VMReg>& output_registers) {
3077+
return NULL;
3078+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2019, Arm Limited. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* This code is distributed in the hope that it will be useful, but WITHOUT
11+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13+
* version 2 for more details (a copy is included in the LICENSE file that
14+
* accompanied this code).
15+
*
16+
* You should have received a copy of the GNU General Public License version
17+
* 2 along with this work; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19+
*
20+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21+
* or visit www.oracle.com if you need additional information or have any
22+
* questions.
23+
*/
24+
25+
#include "precompiled.hpp"
26+
#include "asm/macroAssembler.hpp"
27+
#include "code/codeBlob.hpp"
28+
#include "memory/resourceArea.hpp"
29+
#include "prims/universalNativeInvoker.hpp"
30+
31+
#define __ _masm->
32+
33+
void ProgrammableInvoker::Generator::generate() {
34+
__ enter();
35+
36+
// Name registers used in the stub code. These are all caller-save so
37+
// may be clobbered by the call to the native function. Avoid using
38+
// rscratch1 here as it's r8 which is the indirect result register in
39+
// the standard ABI.
40+
Register Rctx = r10, Rstack_size = r11;
41+
Register Rwords = r12, Rtmp = r13;
42+
Register Rsrc_ptr = r14, Rdst_ptr = r15;
43+
44+
assert_different_registers(Rctx, Rstack_size, rscratch1, rscratch2);
45+
46+
// TODO: if the callee is not using the standard C ABI then we need to
47+
// preserve more registers here.
48+
49+
__ block_comment("init_and_alloc_stack");
50+
51+
__ mov(Rctx, c_rarg0);
52+
__ str(Rctx, Address(__ pre(sp, -2 * wordSize)));
53+
54+
assert(_abi->_stack_alignment_bytes % 16 == 0, "stack must be 16 byte aligned");
55+
56+
__ block_comment("allocate_stack");
57+
__ ldr(Rstack_size, Address(Rctx, (int) _layout->stack_args_bytes));
58+
__ add(rscratch2, Rstack_size, _abi->_stack_alignment_bytes - 1);
59+
__ andr(rscratch2, rscratch2, -_abi->_stack_alignment_bytes);
60+
__ sub(sp, sp, rscratch2);
61+
62+
__ block_comment("load_arguments");
63+
64+
__ ldr(Rsrc_ptr, Address(Rctx, (int) _layout->stack_args));
65+
__ lsr(Rwords, Rstack_size, LogBytesPerWord);
66+
__ mov(Rdst_ptr, sp);
67+
68+
Label Ldone, Lnext;
69+
__ bind(Lnext);
70+
__ cbz(Rwords, Ldone);
71+
__ ldr(Rtmp, __ post(Rsrc_ptr, wordSize));
72+
__ str(Rtmp, __ post(Rdst_ptr, wordSize));
73+
__ sub(Rwords, Rwords, 1);
74+
__ b(Lnext);
75+
__ bind(Ldone);
76+
77+
for (int i = 0; i < _abi->_vector_argument_registers.length(); i++) {
78+
ssize_t offs = _layout->arguments_vector + i * float_reg_size;
79+
__ ldrq(_abi->_vector_argument_registers.at(i), Address(Rctx, offs));
80+
}
81+
82+
for (int i = 0; i < _abi->_integer_argument_registers.length(); i++) {
83+
ssize_t offs = _layout->arguments_integer + i * sizeof(uintptr_t);
84+
__ ldr(_abi->_integer_argument_registers.at(i), Address(Rctx, offs));
85+
}
86+
87+
assert(_abi->_shadow_space_bytes == 0, "shadow space not supported on AArch64");
88+
89+
// call target function
90+
__ block_comment("call target function");
91+
__ ldr(rscratch2, Address(Rctx, (int) _layout->arguments_next_pc));
92+
__ blr(rscratch2);
93+
94+
__ ldr(Rctx, Address(rfp, -2 * wordSize)); // Might have clobbered Rctx
95+
96+
__ block_comment("store_registers");
97+
98+
for (int i = 0; i < _abi->_integer_return_registers.length(); i++) {
99+
ssize_t offs = _layout->returns_integer + i * sizeof(uintptr_t);
100+
__ str(_abi->_integer_return_registers.at(i), Address(Rctx, offs));
101+
}
102+
103+
for (int i = 0; i < _abi->_vector_return_registers.length(); i++) {
104+
ssize_t offs = _layout->returns_vector + i * float_reg_size;
105+
__ strq(_abi->_vector_return_registers.at(i), Address(Rctx, offs));
106+
}
107+
108+
__ leave();
109+
__ ret(lr);
110+
111+
__ flush();
112+
}
113+
114+
address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) {
115+
ResourceMark rm;
116+
const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
117+
const BufferLayout layout = ForeignGlobals::parse_buffer_layout(jlayout);
118+
119+
BufferBlob* _invoke_native_blob = BufferBlob::create("invoke_native_blob", native_invoker_size);
120+
121+
CodeBuffer code2(_invoke_native_blob);
122+
ProgrammableInvoker::Generator g2(&code2, &abi, &layout);
123+
g2.generate();
124+
code2.log_section_sizes("InvokeNativeBlob");
125+
126+
return _invoke_native_blob->code_begin();
127+
}

0 commit comments

Comments
 (0)