1 /*
 2  * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
 3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  *
 5  * This code is free software; you can redistribute it and/or modify it
 6  * under the terms of the GNU General Public License version 2 only, as
 7  * published by the Free Software Foundation.
 8  *
 9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 #include "precompiled.hpp"
25 #include "prims/universalNativeInvoker.hpp"
26 #include "runtime/interfaceSupport.inline.hpp"
27 
28 ProgrammableInvoker::Generator::Generator(CodeBuffer* code, const ABIDescriptor* abi, const BufferLayout* layout)
29   : StubCodeGenerator(code),
30     _abi(abi),
31     _layout(layout) {}
32 
33 void ProgrammableInvoker::invoke_native(Stub stub, address buff, JavaThread* thread) {
34   ThreadToNativeFromVM ttnfvm(thread);
35   // We need WXExec because we are about to call a generated stub. Like in VM
36   // entries, the thread state should be changed while we are still in WXWrite.
37   // See JDK-8265292.
38   MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXExec, thread));
39   stub(buff);
40 }
41 
42 JNI_ENTRY(void, PI_invokeNative(JNIEnv* env, jclass _unused, jlong adapter_stub, jlong buff))
43   assert(thread->thread_state() == _thread_in_vm, "thread state is: %d", thread->thread_state());
44   ProgrammableInvoker::Stub stub = (ProgrammableInvoker::Stub) adapter_stub;
45   address c = (address) buff;
46   ProgrammableInvoker::invoke_native(stub, c, thread);
47 JNI_END
48 
49 JNI_ENTRY(jlong, PI_generateAdapter(JNIEnv* env, jclass _unused, jobject abi, jobject layout))
50   return (jlong) ProgrammableInvoker::generate_adapter(abi, layout);
51 JNI_END
52 
53 #define CC (char*)  /*cast a literal from (const char*)*/
54 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
55 #define FOREIGN_ABI "Ljdk/internal/foreign/abi"
56 
57 static JNINativeMethod PI_methods[] = {
58   {CC "invokeNative",    CC "(JJ)V",                                                             FN_PTR(PI_invokeNative)   },
59   {CC "generateAdapter", CC "(" FOREIGN_ABI "/ABIDescriptor;" FOREIGN_ABI "/BufferLayout;" ")J", FN_PTR(PI_generateAdapter)}
60 };
61 
62 JNI_ENTRY(void, JVM_RegisterProgrammableInvokerMethods(JNIEnv *env, jclass PI_class))
63   ThreadToNativeFromVM ttnfv(thread);
64   int status = env->RegisterNatives(PI_class, PI_methods, sizeof(PI_methods)/sizeof(JNINativeMethod));
65   guarantee(status == JNI_OK && !env->ExceptionOccurred(),
66             "register jdk.internal.foreign.abi.programmable.ProgrammableInvoker natives");
67 JNI_END