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 
 25 #include "precompiled.hpp"
 26 #include "runtime/interfaceSupport.inline.hpp"
 27 #include "classfile/javaClasses.inline.hpp"
 28 #include "code/vmreg.hpp"
 29 #include "logging/logStream.hpp"
 30 #include "memory/resourceArea.hpp"
 31 #include "oops/typeArrayOop.inline.hpp"
 32 #include "oops/oopCast.inline.hpp"
 33 #include "prims/foreign_globals.inline.hpp"
 34 #include "prims/universalNativeInvoker.hpp"
 35 #include "runtime/jniHandles.inline.hpp"
 36 
 37 JNI_LEAF(jlong, NEP_vmStorageToVMReg(JNIEnv* env, jclass _unused, jint type, jint index))
 38   return ForeignGlobals::vmstorage_to_vmreg(type, index)->value();
 39 JNI_END
 40 
 41 JNI_ENTRY(jlong, NEP_makeInvoker(JNIEnv* env, jclass _unused, jobject method_type, jobject jabi,
 42                                  jlongArray arg_moves, jlongArray ret_moves, jboolean needs_return_buffer))
 43   ResourceMark rm;
 44   const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi);
 45 
 46   oop type = JNIHandles::resolve(method_type);
 47   typeArrayOop arg_moves_oop = oop_cast<typeArrayOop>(JNIHandles::resolve(arg_moves));
 48   typeArrayOop ret_moves_oop = oop_cast<typeArrayOop>(JNIHandles::resolve(ret_moves));
 49   int pcount = java_lang_invoke_MethodType::ptype_count(type);
 50   int pslots = java_lang_invoke_MethodType::ptype_slot_count(type);
 51   BasicType* basic_type = NEW_RESOURCE_ARRAY(BasicType, pslots);
 52 
 53   GrowableArray<VMReg> input_regs(pcount);
 54   for (int i = 0, bt_idx = 0; i < pcount; i++) {
 55     oop type_oop = java_lang_invoke_MethodType::ptype(type, i);
 56     assert(java_lang_Class::is_primitive(type_oop), "Only primitives expected");
 57     BasicType bt = java_lang_Class::primitive_type(type_oop);
 58     basic_type[bt_idx++] = bt;
 59     input_regs.push(VMRegImpl::as_VMReg(arg_moves_oop->long_at(i)));
 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       // NativeCallConv ignores them, but they are needed
 65       // for JavaCallConv
 66     }
 67   }
 68 
 69 
 70   jint outs = ret_moves_oop->length();
 71   GrowableArray<VMReg> 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(VMRegImpl::as_VMReg(ret_moves_oop->long_at(i)));
 78   }
 79 
 80 #ifdef ASSERT
 81   LogTarget(Trace, panama) lt;
 82   if (lt.is_enabled()) {
 83     ResourceMark rm;
 84     LogStream ls(lt);
 85     ls.print_cr("Generating native invoker {");
 86     ls.print("BasicType { ");
 87     for (int i = 0; i < pslots; i++) {
 88       ls.print("%s, ", null_safe_string(type2name(basic_type[i])));
 89     }
 90     ls.print_cr("}");
 91     ls.print_cr("shadow_space_bytes = %d", abi._shadow_space_bytes);
 92     ls.print("input_registers { ");
 93     for (int i = 0; i < input_regs.length(); i++) {
 94       VMReg reg = input_regs.at(i);
 95       ls.print("%s (" INTPTR_FORMAT "), ", reg->name(), reg->value());
 96     }
 97     ls.print_cr("}");
 98       ls.print("output_registers { ");
 99     for (int i = 0; i < output_regs.length(); i++) {
100       VMReg reg = output_regs.at(i);
101       ls.print("%s (" INTPTR_FORMAT "), ", reg->name(), reg->value());
102     }
103     ls.print_cr("}");
104     ls.print_cr("}");
105   }
106 #endif
107 
108   return (jlong) ProgrammableInvoker::make_native_invoker(
109     basic_type, pslots, ret_bt, abi, input_regs, output_regs, needs_return_buffer)->code_begin();
110 JNI_END
111 
112 #define CC (char*)  /*cast a literal from (const char*)*/
113 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
114 
115 static JNINativeMethod NEP_methods[] = {
116   {CC "vmStorageToVMReg", CC "(II)J", FN_PTR(NEP_vmStorageToVMReg)},
117   {CC "makeInvoker", CC "(Ljava/lang/invoke/MethodType;Ljdk/internal/invoke/ABIDescriptorProxy;[J[JZ)J", FN_PTR(NEP_makeInvoker)},
118 };
119 
120 JNI_ENTRY(void, JVM_RegisterNativeEntryPointMethods(JNIEnv *env, jclass NEP_class))
121   ThreadToNativeFromVM ttnfv(thread);
122   int status = env->RegisterNatives(NEP_class, NEP_methods, sizeof(NEP_methods)/sizeof(JNINativeMethod));
123   guarantee(status == JNI_OK && !env->ExceptionOccurred(),
124             "register jdk.internal.invoke.NativeEntryPoint natives");
125 JNI_END