1 /* 2 * Copyright (c) 2020, 2026, 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 25 #include "classfile/javaClasses.inline.hpp" 26 #include "code/codeCache.hpp" 27 #include "code/vmreg.hpp" 28 #include "logging/logStream.hpp" 29 #include "memory/resourceArea.hpp" 30 #include "oops/oopCast.inline.hpp" 31 #include "oops/typeArrayOop.inline.hpp" 32 #include "prims/downcallLinker.hpp" 33 #include "prims/foreignGlobals.inline.hpp" 34 #include "runtime/interfaceSupport.inline.hpp" 35 #include "runtime/jniHandles.inline.hpp" 36 37 JNI_ENTRY(jlong, NEP_makeDowncallStub(JNIEnv* env, jclass _unused, jobject method_type, jobject jabi, 38 jobjectArray arg_moves, jobjectArray ret_moves, 39 jboolean needs_return_buffer, jint captured_state_mask, 40 jboolean needs_transition)) 41 ResourceMark rm; 42 const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi); 43 44 oop type = JNIHandles::resolve(method_type); 45 refArrayOop arg_moves_oop = oop_cast<refArrayOop>(JNIHandles::resolve(arg_moves)); 46 refArrayOop ret_moves_oop = oop_cast<refArrayOop>(JNIHandles::resolve(ret_moves)); 47 int pcount = java_lang_invoke_MethodType::ptype_count(type); 48 int pslots = java_lang_invoke_MethodType::ptype_slot_count(type); 49 BasicType* basic_type = NEW_RESOURCE_ARRAY(BasicType, pslots); 50 51 GrowableArray<VMStorage> input_regs(pcount); 52 for (int i = 0, bt_idx = 0; i < pcount; i++) { 53 oop type_oop = java_lang_invoke_MethodType::ptype(type, i); 54 BasicType bt = java_lang_Class::as_BasicType(type_oop); 55 basic_type[bt_idx++] = bt; 56 oop reg_oop = arg_moves_oop->obj_at(i); 57 if (reg_oop != nullptr) { 58 input_regs.push(ForeignGlobals::parse_vmstorage(reg_oop)); 59 } 60 61 if (bt == BasicType::T_DOUBLE || bt == BasicType::T_LONG) { 62 basic_type[bt_idx++] = T_VOID; 63 // we only need these in the basic type 64 // NativeCallingConvention ignores them, but they are needed 65 // for JavaCallingConvention 66 } 67 } 68 69 70 jint outs = ret_moves_oop->length(); 71 GrowableArray<VMStorage> output_regs(outs); 72 oop type_oop = java_lang_invoke_MethodType::rtype(type); 73 BasicType ret_bt = java_lang_Class::primitive_type(type_oop); 74 for (int i = 0; i < outs; i++) { 75 // note that we don't care about long/double upper halfs here: 76 // we are NOT moving Java values, we are moving register-sized values 77 output_regs.push(ForeignGlobals::parse_vmstorage(ret_moves_oop->obj_at(i))); 78 } 79 80 RuntimeStub* stub = DowncallLinker::make_downcall_stub(basic_type, pslots, ret_bt, abi, 81 input_regs, output_regs, 82 needs_return_buffer, captured_state_mask, 83 needs_transition); 84 if (stub == nullptr) { 85 return 0; 86 } 87 return (jlong) stub->code_begin(); 88 JNI_END 89 90 JNI_ENTRY(jboolean, NEP_freeDowncallStub(JNIEnv* env, jclass _unused, jlong invoker)) 91 // safe to call without code cache lock, because stub is always alive 92 CodeBlob* cb = CodeCache::find_blob((char*) invoker); 93 if (cb == nullptr) { 94 return false; 95 } 96 RuntimeStub::free(cb->as_runtime_stub()); 97 return true; 98 JNI_END 99 100 #define CC (char*) /*cast a literal from (const char*)*/ 101 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) 102 #define METHOD_TYPE "Ljava/lang/invoke/MethodType;" 103 #define ABI_DESC "Ljdk/internal/foreign/abi/ABIDescriptor;" 104 #define VM_STORAGE_ARR "[Ljdk/internal/foreign/abi/VMStorage;" 105 106 static JNINativeMethod NEP_methods[] = { 107 {CC "makeDowncallStub", CC "(" METHOD_TYPE ABI_DESC VM_STORAGE_ARR VM_STORAGE_ARR "ZIZ)J", FN_PTR(NEP_makeDowncallStub)}, 108 {CC "freeDowncallStub0", CC "(J)Z", FN_PTR(NEP_freeDowncallStub)}, 109 }; 110 111 #undef METHOD_TYPE 112 #undef ABI_DESC 113 #undef VM_STORAGE_ARR 114 115 JNI_ENTRY(void, JVM_RegisterNativeEntryPointMethods(JNIEnv *env, jclass NEP_class)) 116 ThreadToNativeFromVM ttnfv(thread); 117 int status = env->RegisterNatives(NEP_class, NEP_methods, sizeof(NEP_methods)/sizeof(JNINativeMethod)); 118 guarantee(status == JNI_OK && !env->ExceptionCheck(), 119 "register jdk.internal.foreign.abi.NativeEntryPoint natives"); 120 JNI_END --- EOF ---