1 /* 2 * Copyright (c) 2020, 2022, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import jdk.internal.vm.annotation.ForceInline; 29 import jdk.internal.invoke.NativeEntryPoint; 30 31 import static java.lang.invoke.LambdaForm.*; 32 import static java.lang.invoke.MethodHandleNatives.Constants.LM_TRUSTED; 33 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic; 34 import static java.lang.invoke.MethodHandleStatics.newInternalError; 35 36 /** 37 * This class models a method handle to a native function. A native method handle is made up of a {@link NativeEntryPoint}, 38 * which is used to capture the characteristics of the native call (such as calling convention to be used, 39 * or whether a native transition is required) and a <em>fallback</em> method handle, which can be used 40 * when intrinsification of this method handle is not possible. 41 */ 42 /*non-public*/ final class NativeMethodHandle extends MethodHandle { 43 final NativeEntryPoint nep; 44 45 private NativeMethodHandle(MethodType type, LambdaForm form, NativeEntryPoint nep) { 46 super(type, form); 47 this.nep = nep; 48 } 49 50 /** 51 * Creates a new native method handle with given {@link NativeEntryPoint} and <em>fallback</em> method handle. 52 */ 53 public static MethodHandle make(NativeEntryPoint nep) { 54 MethodType type = nep.type(); 55 if (!allTypesPrimitive(type)) 56 throw new IllegalArgumentException("Type must only contain primitives: " + type); 57 58 59 LambdaForm lform = preparedLambdaForm(type); 60 return new NativeMethodHandle(type, lform, nep); 61 } 62 63 private static boolean allTypesPrimitive(MethodType type) { 64 if (!type.returnType().isPrimitive()) 65 return false; 66 67 for (Class<?> pType : type.parameterArray()) { 68 if (!pType.isPrimitive()) 69 return false; 70 } 71 72 return true; 73 } 74 75 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); 76 77 private static LambdaForm preparedLambdaForm(MethodType mtype) { 78 int id = MethodTypeForm.LF_INVNATIVE; 79 mtype = mtype.basicType(); 80 LambdaForm lform = mtype.form().cachedLambdaForm(id); 81 if (lform != null) return lform; 82 lform = makePreparedLambdaForm(mtype); 83 return mtype.form().setCachedLambdaForm(id, lform); 84 } 85 86 private static LambdaForm makePreparedLambdaForm(MethodType mtype) { 87 MethodType linkerType = mtype 88 .appendParameterTypes(Object.class); // NEP 89 MemberName linker = new MemberName(MethodHandle.class, "linkToNative", linkerType, REF_invokeStatic); 90 try { 91 linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, LM_TRUSTED, NoSuchMethodException.class); 92 } catch (ReflectiveOperationException ex) { 93 throw newInternalError(ex); 94 } 95 final int NMH_THIS = 0; 96 final int ARG_BASE = 1; 97 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); 98 int nameCursor = ARG_LIMIT; 99 final int GET_NEP = nameCursor++; 100 final int LINKER_CALL = nameCursor++; 101 102 LambdaForm.Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); 103 assert (names.length == nameCursor); 104 105 names[GET_NEP] = new LambdaForm.Name(Lazy.NF_internalNativeEntryPoint, names[NMH_THIS]); 106 107 Object[] outArgs = new Object[linkerType.parameterCount()]; 108 System.arraycopy(names, ARG_BASE, outArgs, 0, mtype.parameterCount()); 109 outArgs[outArgs.length - 1] = names[GET_NEP]; 110 names[LINKER_CALL] = new LambdaForm.Name(linker, outArgs); 111 112 LambdaForm lform = new LambdaForm(ARG_LIMIT, names, LAST_RESULT); 113 // This is a tricky bit of code. Don't send it through the LF interpreter. 114 lform.compileToBytecode(); 115 return lform; 116 } 117 118 final 119 @Override 120 MethodHandle copyWith(MethodType mt, LambdaForm lf) { 121 assert (this.getClass() == NativeMethodHandle.class); // must override in subclasses 122 return new NativeMethodHandle(mt, lf, nep); 123 } 124 125 @Override 126 BoundMethodHandle rebind() { 127 return BoundMethodHandle.makeReinvoker(this); 128 } 129 130 @ForceInline 131 static Object internalNativeEntryPoint(Object mh) { 132 return ((NativeMethodHandle)mh).nep; 133 } 134 135 /** 136 * Pre-initialized NamedFunctions for bootstrapping purposes. 137 * Factored in an inner class to delay initialization until first usage. 138 */ 139 private static class Lazy { 140 141 static final NamedFunction 142 NF_internalNativeEntryPoint; 143 144 static { 145 try { 146 Class<NativeMethodHandle> THIS_CLASS = NativeMethodHandle.class; 147 NamedFunction[] nfs = new NamedFunction[]{ 148 NF_internalNativeEntryPoint = new NamedFunction( 149 THIS_CLASS.getDeclaredMethod("internalNativeEntryPoint", Object.class)), 150 }; 151 for (NamedFunction nf : nfs) { 152 // Each nf must be statically invocable or we get tied up in our bootstraps. 153 assert (InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf; 154 nf.resolve(); 155 } 156 } catch (ReflectiveOperationException ex) { 157 throw newInternalError(ex); 158 } 159 } 160 } 161 }