< prev index next >

src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/abi/ProgrammableInvoker.java

Print this page
*** 23,26 ***
   * questions.
   */
  package jdk.internal.foreign.abi;
  
  import jdk.incubator.foreign.Addressable;
- import jdk.incubator.foreign.MemoryAddress;
- import jdk.incubator.foreign.MemoryLayouts;
  import jdk.incubator.foreign.MemorySegment;
  import jdk.incubator.foreign.ResourceScope;
  import jdk.incubator.foreign.SegmentAllocator;
  import jdk.internal.access.JavaLangInvokeAccess;
  import jdk.internal.access.SharedSecrets;
  import jdk.internal.invoke.NativeEntryPoint;
  import jdk.internal.invoke.VMStorageProxy;
  import sun.security.action.GetPropertyAction;
  
  import java.lang.invoke.MethodHandle;
  import java.lang.invoke.MethodHandles;
  import java.lang.invoke.MethodType;
  import java.lang.invoke.VarHandle;
- import java.lang.ref.Reference;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.stream.Stream;
--- 23,25 ---
   * questions.
   */
  package jdk.internal.foreign.abi;
  
  import jdk.incubator.foreign.Addressable;
  import jdk.incubator.foreign.MemorySegment;
+ import jdk.incubator.foreign.NativeSymbol;
  import jdk.incubator.foreign.ResourceScope;
  import jdk.incubator.foreign.SegmentAllocator;
+ import jdk.incubator.foreign.ValueLayout;
  import jdk.internal.access.JavaLangInvokeAccess;
  import jdk.internal.access.SharedSecrets;
  import jdk.internal.invoke.NativeEntryPoint;
  import jdk.internal.invoke.VMStorageProxy;
  import sun.security.action.GetPropertyAction;
  
  import java.lang.invoke.MethodHandle;
  import java.lang.invoke.MethodHandles;
  import java.lang.invoke.MethodType;
  import java.lang.invoke.VarHandle;
  import java.util.Arrays;
  import java.util.List;
  import java.util.Map;
  import java.util.concurrent.ConcurrentHashMap;
  import java.util.stream.Stream;

*** 68,11 ***
      private static final boolean USE_INTRINSICS = Boolean.parseBoolean(
          GetPropertyAction.privilegedGetProperty("jdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS", "true"));
  
      private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess();
  
!     private static final VarHandle VH_LONG = MemoryLayouts.JAVA_LONG.varHandle(long.class);
  
      private static final MethodHandle MH_INVOKE_MOVES;
      private static final MethodHandle MH_INVOKE_INTERP_BINDINGS;
      private static final MethodHandle MH_ADDR_TO_LONG;
      private static final MethodHandle MH_WRAP_ALLOCATOR;
--- 67,11 ---
      private static final boolean USE_INTRINSICS = Boolean.parseBoolean(
          GetPropertyAction.privilegedGetProperty("jdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS", "true"));
  
      private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess();
  
!     private static final VarHandle VH_LONG = ValueLayout.JAVA_LONG.varHandle();
  
      private static final MethodHandle MH_INVOKE_MOVES;
      private static final MethodHandle MH_INVOKE_INTERP_BINDINGS;
      private static final MethodHandle MH_ADDR_TO_LONG;
      private static final MethodHandle MH_WRAP_ALLOCATOR;

*** 85,14 ***
          try {
              MethodHandles.Lookup lookup = MethodHandles.lookup();
              MH_INVOKE_MOVES = lookup.findVirtual(ProgrammableInvoker.class, "invokeMoves",
                      methodType(Object.class, long.class, Object[].class, Binding.VMStore[].class, Binding.VMLoad[].class));
              MH_INVOKE_INTERP_BINDINGS = lookup.findVirtual(ProgrammableInvoker.class, "invokeInterpBindings",
!                     methodType(Object.class, Addressable.class, SegmentAllocator.class, Object[].class, MethodHandle.class, Map.class, Map.class));
              MH_WRAP_ALLOCATOR = lookup.findStatic(Binding.Context.class, "ofAllocator",
                      methodType(Binding.Context.class, SegmentAllocator.class));
!             MH_ADDR_TO_LONG = lookup.findStatic(ProgrammableInvoker.class, "unboxTargetAddress", methodType(long.class, Addressable.class));
          } catch (ReflectiveOperationException e) {
              throw new RuntimeException(e);
          }
      }
  
--- 84,14 ---
          try {
              MethodHandles.Lookup lookup = MethodHandles.lookup();
              MH_INVOKE_MOVES = lookup.findVirtual(ProgrammableInvoker.class, "invokeMoves",
                      methodType(Object.class, long.class, Object[].class, Binding.VMStore[].class, Binding.VMLoad[].class));
              MH_INVOKE_INTERP_BINDINGS = lookup.findVirtual(ProgrammableInvoker.class, "invokeInterpBindings",
!                     methodType(Object.class, NativeSymbol.class, SegmentAllocator.class, Object[].class, MethodHandle.class, Map.class, Map.class));
              MH_WRAP_ALLOCATOR = lookup.findStatic(Binding.Context.class, "ofAllocator",
                      methodType(Binding.Context.class, SegmentAllocator.class));
!             MH_ADDR_TO_LONG = lookup.findStatic(ProgrammableInvoker.class, "unboxTargetAddress", methodType(long.class, NativeSymbol.class));
          } catch (ReflectiveOperationException e) {
              throw new RuntimeException(e);
          }
      }
  

*** 134,28 ***
                      : Object[].class;
  
          MethodType leafType = methodType(returnType, argMoveTypes);
          MethodType leafTypeWithAddress = leafType.insertParameterTypes(0, long.class);
  
!         MethodHandle handle = insertArguments(MH_INVOKE_MOVES.bindTo(this), 2, argMoves, retMoves);
-         MethodHandle collector = makeCollectorHandle(leafType);
-         handle = collectArguments(handle, 1, collector);
-         handle = handle.asType(leafTypeWithAddress);
  
          boolean isSimple = !(retMoves.length > 1);
          boolean usesStackArgs = stackArgsBytes != 0;
!         if (USE_INTRINSICS && isSimple && !usesStackArgs) {
              NativeEntryPoint nep = NativeEntryPoint.make(
!                 "native_call",
                  abi,
                  toStorageArray(argMoves),
                  toStorageArray(retMoves),
                  !callingSequence.isTrivial(),
                  leafTypeWithAddress
              );
  
!             handle = JLIA.nativeMethodHandle(nep, handle);
          }
          handle = filterArguments(handle, 0, MH_ADDR_TO_LONG);
  
          if (USE_SPEC && isSimple) {
              handle = specialize(handle);
--- 133,30 ---
                      : Object[].class;
  
          MethodType leafType = methodType(returnType, argMoveTypes);
          MethodType leafTypeWithAddress = leafType.insertParameterTypes(0, long.class);
  
!         MethodHandle handle;
  
          boolean isSimple = !(retMoves.length > 1);
          boolean usesStackArgs = stackArgsBytes != 0;
!         if (USE_INTRINSICS && isSimple && !usesStackArgs && supportsNativeInvoker()) {
              NativeEntryPoint nep = NativeEntryPoint.make(
!                 "native_invoker_" + leafType.descriptorString(),
                  abi,
                  toStorageArray(argMoves),
                  toStorageArray(retMoves),
                  !callingSequence.isTrivial(),
                  leafTypeWithAddress
              );
  
!             handle = JLIA.nativeMethodHandle(nep);
+         } else {
+             handle = insertArguments(MH_INVOKE_MOVES.bindTo(this), 2, argMoves, retMoves);
+             MethodHandle collector = makeCollectorHandle(leafType);
+             handle = collectArguments(handle, 1, collector);
+             handle = handle.asType(leafTypeWithAddress);
          }
          handle = filterArguments(handle, 0, MH_ADDR_TO_LONG);
  
          if (USE_SPEC && isSimple) {
              handle = specialize(handle);

*** 170,13 ***
           }
  
          return handle;
      }
  
!     private static long unboxTargetAddress(Addressable addr) {
!         MemoryAddress ma = SharedUtils.checkSymbol(addr);
!         return ma.toRawLongValue();
      }
  
      // Funnel from type to Object[]
      private static MethodHandle makeCollectorHandle(MethodType type) {
          return type.parameterCount() == 0
--- 171,13 ---
           }
  
          return handle;
      }
  
!     private static long unboxTargetAddress(NativeSymbol addr) {
!         SharedUtils.checkSymbol(addr);
!         return addr.address().toRawLongValue();
      }
  
      // Funnel from type to Object[]
      private static MethodHandle makeCollectorHandle(MethodType type) {
          return type.parameterCount() == 0

*** 310,34 ***
                  return returns;
              }
          }
      }
  
!     Object invokeInterpBindings(Addressable address, SegmentAllocator allocator, Object[] args, MethodHandle leaf,
                                  Map<VMStorage, Integer> argIndexMap,
                                  Map<VMStorage, Integer> retIndexMap) throws Throwable {
          Binding.Context unboxContext = bufferCopySize != 0
                  ? Binding.Context.ofBoundedAllocator(bufferCopySize)
                  : Binding.Context.DUMMY;
          try (unboxContext) {
              // do argument processing, get Object[] as result
              Object[] leafArgs = new Object[leaf.type().parameterCount()];
!             leafArgs[0] = address; // addr
              for (int i = 0; i < args.length; i++) {
                  Object arg = args[i];
                  BindingInterpreter.unbox(arg, callingSequence.argumentBindings(i),
                          (storage, type, value) -> {
!                             leafArgs[argIndexMap.get(storage) + 1] = value; // +1 to skip addr
                          }, unboxContext);
              }
  
              // call leaf
              Object o = leaf.invokeWithArguments(leafArgs);
-             // make sure arguments are reachable during the call
-             // technically we only need to do all Addressable parameters here
-             Reference.reachabilityFence(address);
-             Reference.reachabilityFence(args);
  
              // return value processing
              if (o == null) {
                  return null;
              } else if (o instanceof Object[]) {
--- 311,30 ---
                  return returns;
              }
          }
      }
  
!     Object invokeInterpBindings(NativeSymbol symbol, SegmentAllocator allocator, Object[] args, MethodHandle leaf,
                                  Map<VMStorage, Integer> argIndexMap,
                                  Map<VMStorage, Integer> retIndexMap) throws Throwable {
          Binding.Context unboxContext = bufferCopySize != 0
                  ? Binding.Context.ofBoundedAllocator(bufferCopySize)
                  : Binding.Context.DUMMY;
          try (unboxContext) {
              // do argument processing, get Object[] as result
              Object[] leafArgs = new Object[leaf.type().parameterCount()];
!             leafArgs[0] = symbol; // symbol
              for (int i = 0; i < args.length; i++) {
                  Object arg = args[i];
                  BindingInterpreter.unbox(arg, callingSequence.argumentBindings(i),
                          (storage, type, value) -> {
!                             leafArgs[argIndexMap.get(storage) + 1] = value; // +1 to skip symbol
                          }, unboxContext);
              }
  
              // call leaf
              Object o = leaf.invokeWithArguments(leafArgs);
  
              // return value processing
              if (o == null) {
                  return null;
              } else if (o instanceof Object[]) {

*** 353,10 ***
--- 350,11 ---
  
      //natives
  
      static native void invokeNative(long adapterStub, long buff);
      static native long generateAdapter(ABIDescriptor abi, BufferLayout layout);
+     static native boolean supportsNativeInvoker();
  
      private static native void registerNatives();
      static {
          registerNatives();
      }
< prev index next >