< prev index next >

src/java.base/share/classes/jdk/internal/invoke/NativeEntryPoint.java

Print this page

  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 jdk.internal.invoke;
 27 
 28 import java.lang.invoke.MethodType;



 29 import java.util.Objects;

 30 
 31 /**
 32  * This class describes a native call, including arguments/return shuffle moves, PC entry point and
 33  * various other info which are relevant when the call will be intrinsified by C2.
 34  */
 35 public class NativeEntryPoint {
 36     static {
 37         registerNatives();
 38     }
 39 
 40     private final int shadowSpace;
 41 
 42     // encoded as VMRegImpl*
 43     private final long[] argMoves;
 44     private final long[] returnMoves;
 45 
 46     private final boolean needTransition;
 47     private final MethodType methodType; // C2 sees erased version (byte -> int), so need this explicitly
 48     private final String name;
 49 






 50     private NativeEntryPoint(int shadowSpace, long[] argMoves, long[] returnMoves,
 51                      boolean needTransition, MethodType methodType, String name) {
 52         this.shadowSpace = shadowSpace;
 53         this.argMoves = Objects.requireNonNull(argMoves);
 54         this.returnMoves = Objects.requireNonNull(returnMoves);
 55         this.needTransition = needTransition;
 56         this.methodType = methodType;
 57         this.name = name;

 58     }
 59 
 60     public static NativeEntryPoint make(String name, ABIDescriptorProxy abi,
 61                                         VMStorageProxy[] argMoves, VMStorageProxy[] returnMoves,
 62                                         boolean needTransition, MethodType methodType) {
 63         if (returnMoves.length > 1) {
 64             throw new IllegalArgumentException("Multiple register return not supported");
 65         }
 66 
 67         return new NativeEntryPoint(abi.shadowSpaceBytes(), encodeVMStorages(argMoves), encodeVMStorages(returnMoves),
 68                 needTransition, methodType, name);












 69     }
 70 
 71     private static long[] encodeVMStorages(VMStorageProxy[] moves) {
 72         long[] out = new long[moves.length];
 73         for (int i = 0; i < moves.length; i++) {
 74             out[i] = vmStorageToVMReg(moves[i].type(), moves[i].index());
 75         }
 76         return out;
 77     }
 78 
 79     private static native long vmStorageToVMReg(int type, int index);
 80 


 81     public MethodType type() {
 82         return methodType;
 83     }
 84 
 85     private static native void registerNatives();
 86 }

  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 jdk.internal.invoke;
 27 
 28 import java.lang.invoke.MethodType;
 29 import java.util.Arrays;
 30 import java.util.List;
 31 import java.util.Map;
 32 import java.util.Objects;
 33 import java.util.concurrent.ConcurrentHashMap;
 34 
 35 /**
 36  * This class describes a native call, including arguments/return shuffle moves, PC entry point and
 37  * various other info which are relevant when the call will be intrinsified by C2.
 38  */
 39 public class NativeEntryPoint {
 40     static {
 41         registerNatives();
 42     }
 43 
 44     private final int shadowSpace;
 45 
 46     // encoded as VMRegImpl*
 47     private final long[] argMoves;
 48     private final long[] returnMoves;
 49 
 50     private final boolean needTransition;
 51     private final MethodType methodType; // C2 sees erased version (byte -> int), so need this explicitly
 52     private final String name;
 53 
 54     private final long invoker;
 55 
 56     private static final Map<CacheKey, Long> INVOKER_CACHE = new ConcurrentHashMap<>();
 57     private record CacheKey(MethodType mt, int shadowSpaceBytes,
 58                             List<VMStorageProxy> argMoves, List<VMStorageProxy> retMoves) {}
 59 
 60     private NativeEntryPoint(int shadowSpace, long[] argMoves, long[] returnMoves,
 61                      boolean needTransition, MethodType methodType, String name, long invoker) {
 62         this.shadowSpace = shadowSpace;
 63         this.argMoves = Objects.requireNonNull(argMoves);
 64         this.returnMoves = Objects.requireNonNull(returnMoves);
 65         this.needTransition = needTransition;
 66         this.methodType = methodType;
 67         this.name = name;
 68         this.invoker = invoker;
 69     }
 70 
 71     public static NativeEntryPoint make(String name, ABIDescriptorProxy abi,
 72                                         VMStorageProxy[] argMoves, VMStorageProxy[] returnMoves,
 73                                         boolean needTransition, MethodType methodType, boolean needsReturnBuffer) {
 74         if (returnMoves.length > 1 != needsReturnBuffer) {
 75             throw new IllegalArgumentException("Multiple register return, but needsReturnBuffer was false");
 76         }
 77 
 78         assert (methodType.parameterType(0) == long.class) : "Address expected";
 79         assert (!needsReturnBuffer || methodType.parameterType(1) == long.class) : "IMR address expected";
 80 
 81         int shadowSpaceBytes = abi.shadowSpaceBytes();
 82         long[] encArgMoves = encodeVMStorages(argMoves);
 83         long[] encRetMoves = encodeVMStorages(returnMoves);
 84 
 85         CacheKey key = new CacheKey(methodType, abi.shadowSpaceBytes(),
 86                 Arrays.asList(argMoves), Arrays.asList(returnMoves));
 87         long invoker = INVOKER_CACHE.computeIfAbsent(key, k ->
 88             makeInvoker(methodType, abi, encArgMoves, encRetMoves, needsReturnBuffer));
 89 
 90         return new NativeEntryPoint(shadowSpaceBytes, encArgMoves, encRetMoves,
 91                 needTransition, methodType, name, invoker);
 92     }
 93 
 94     private static long[] encodeVMStorages(VMStorageProxy[] moves) {
 95         long[] out = new long[moves.length];
 96         for (int i = 0; i < moves.length; i++) {
 97             out[i] = vmStorageToVMReg(moves[i].type(), moves[i].index());
 98         }
 99         return out;
100     }
101 
102     private static native long vmStorageToVMReg(int type, int index);
103 
104     private static native long makeInvoker(MethodType methodType, ABIDescriptorProxy abi, long[] encArgMoves, long[] encRetMoves, boolean needsReturnBuffer);
105 
106     public MethodType type() {
107         return methodType;
108     }
109 
110     private static native void registerNatives();
111 }
< prev index next >