src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 9490 : 8037210: Get rid of char-based descriptions 'J' of basic types
Reviewed-by: jrose, ?
rev 9491 : imported patch meth-asm.enum
rev 9492 : 8038261: JSR292: cache and reuse typed array accessors
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com


  35 import sun.invoke.util.Wrapper;
  36 import sun.reflect.CallerSensitive;
  37 import sun.reflect.Reflection;
  38 import static java.lang.invoke.LambdaForm.*;
  39 import static java.lang.invoke.MethodHandleStatics.*;
  40 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  41 
  42 /**
  43  * Trusted implementation code for MethodHandle.
  44  * @author jrose
  45  */
  46 /*non-public*/ abstract class MethodHandleImpl {
  47     /// Factory methods to create method handles:
  48 
  49     static void initStatics() {
  50         // Trigger selected static initializations.
  51         MemberName.Factory.INSTANCE.getClass();
  52     }
  53 
  54     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {


  55         if (!arrayClass.isArray())
  56             throw newIllegalArgumentException("not an array: "+arrayClass);
  57         MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
  58         MethodType srcType = accessor.type().erase();
  59         MethodType lambdaType = srcType.invokerType();
  60         Name[] names = arguments(1, lambdaType);
  61         Name[] args  = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
  62         names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
  63         LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
  64         MethodHandle mh = SimpleMethodHandle.make(srcType, form);
  65         if (ArrayAccessor.needCast(arrayClass)) {
  66             mh = mh.bindTo(arrayClass);


  67         }
  68         mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
  69         return mh;
  70     }
  71 
  72     static final class ArrayAccessor {
  73         /// Support for array element access
  74         static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>();  // TODO use it
  75         static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>();  // TODO use it















  76 
  77         static int     getElementI(int[]     a, int i)            { return              a[i]; }
  78         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
  79         static float   getElementF(float[]   a, int i)            { return              a[i]; }
  80         static double  getElementD(double[]  a, int i)            { return              a[i]; }
  81         static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
  82         static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
  83         static short   getElementS(short[]   a, int i)            { return              a[i]; }
  84         static char    getElementC(char[]    a, int i)            { return              a[i]; }
  85         static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
  86 
  87         static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
  88         static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
  89         static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
  90         static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
  91         static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
  92         static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
  93         static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
  94         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
  95         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
  96 
  97         static Object  getElementL(Class<?> arrayClass, Object[] a, int i)           { arrayClass.cast(a); return a[i]; }
  98         static void    setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
  99 
 100         static boolean needCast(Class<?> arrayClass) {
 101             Class<?> elemClass = arrayClass.getComponentType();
 102             return !elemClass.isPrimitive() && elemClass != Object.class;
 103         }
 104         static String name(Class<?> arrayClass, boolean isSetter) {
 105             Class<?> elemClass = arrayClass.getComponentType();
 106             if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
 107             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
 108         }
 109         static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
 110         static MethodType type(Class<?> arrayClass, boolean isSetter) {
 111             Class<?> elemClass = arrayClass.getComponentType();
 112             Class<?> arrayArgClass = arrayClass;
 113             if (!elemClass.isPrimitive()) {
 114                 arrayArgClass = Object[].class;
 115                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 116                     arrayArgClass = Object.class;
 117             }
 118             if (!needCast(arrayClass)) {
 119                 return !isSetter ?
 120                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
 121                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
 122             } else {
 123                 Class<?> classArgClass = Class.class;
 124                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 125                     classArgClass = Object.class;
 126                 return !isSetter ?
 127                     MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
 128                     MethodType.methodType(void.class,   classArgClass, arrayArgClass, int.class, Object.class);
 129             }
 130         }
 131         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
 132             Class<?> elemClass = arrayClass.getComponentType();
 133             return !isSetter ?
 134                     MethodType.methodType(elemClass,  arrayClass, int.class) :
 135                     MethodType.methodType(void.class, arrayClass, int.class, elemClass);
 136         }
 137         static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
 138             String     name = name(arrayClass, isSetter);
 139             MethodType type = type(arrayClass, isSetter);
 140             try {
 141                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
 142             } catch (ReflectiveOperationException ex) {
 143                 throw uncaughtException(ex);
 144             }
 145         }
 146     }
 147 
 148     /**
 149      * Create a JVM-level adapter method handle to conform the given method




  35 import sun.invoke.util.Wrapper;
  36 import sun.reflect.CallerSensitive;
  37 import sun.reflect.Reflection;
  38 import static java.lang.invoke.LambdaForm.*;
  39 import static java.lang.invoke.MethodHandleStatics.*;
  40 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  41 
  42 /**
  43  * Trusted implementation code for MethodHandle.
  44  * @author jrose
  45  */
  46 /*non-public*/ abstract class MethodHandleImpl {
  47     /// Factory methods to create method handles:
  48 
  49     static void initStatics() {
  50         // Trigger selected static initializations.
  51         MemberName.Factory.INSTANCE.getClass();
  52     }
  53 
  54     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
  55         if (arrayClass == Object[].class)
  56             return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
  57         if (!arrayClass.isArray())
  58             throw newIllegalArgumentException("not an array: "+arrayClass);
  59         MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
  60         int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
  61         MethodHandle mh = cache[cacheIndex];
  62         if (mh != null)  return mh;
  63         mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
  64         MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
  65         if (mh.type() != correctType) {
  66             assert(mh.type().parameterType(0) == Object[].class);
  67             assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
  68             assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
  69             // safe to view non-strictly, because element type follows from array type
  70             mh = mh.viewAsType(correctType);
  71         }
  72         cache[cacheIndex] = mh;
  73         return mh;
  74     }
  75 
  76     static final class ArrayAccessor {
  77         /// Support for array element access
  78         static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
  79         static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
  80                 = new ClassValue<MethodHandle[]>() {
  81                     @Override
  82                     protected MethodHandle[] computeValue(Class<?> type) {
  83                         return new MethodHandle[INDEX_LIMIT];
  84                     }
  85                 };
  86         static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER;
  87         static {
  88             MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
  89             cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = getAccessor(Object[].class, false);
  90             cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = getAccessor(Object[].class, true);
  91 
  92             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
  93             assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
  94         }
  95 
  96         static int     getElementI(int[]     a, int i)            { return              a[i]; }
  97         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
  98         static float   getElementF(float[]   a, int i)            { return              a[i]; }
  99         static double  getElementD(double[]  a, int i)            { return              a[i]; }
 100         static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
 101         static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
 102         static short   getElementS(short[]   a, int i)            { return              a[i]; }
 103         static char    getElementC(char[]    a, int i)            { return              a[i]; }
 104         static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
 105 
 106         static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
 107         static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
 108         static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
 109         static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
 110         static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
 111         static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
 112         static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
 113         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
 114         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
 115 



 116         static boolean needCast(Class<?> arrayClass) {
 117             Class<?> elemClass = arrayClass.getComponentType();
 118             return !elemClass.isPrimitive() && elemClass != Object.class;
 119         }
 120         static String name(Class<?> arrayClass, boolean isSetter) {
 121             Class<?> elemClass = arrayClass.getComponentType();
 122             if (elemClass == null)  throw newIllegalArgumentException("not an array", arrayClass);
 123             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
 124         }

 125         static MethodType type(Class<?> arrayClass, boolean isSetter) {
 126             Class<?> elemClass = arrayClass.getComponentType();
 127             Class<?> arrayArgClass = arrayClass;
 128             if (!elemClass.isPrimitive()) {
 129                 arrayArgClass = Object[].class;
 130                 elemClass = Object.class;

 131             }

 132             return !isSetter ?
 133                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
 134                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);








 135         }
 136         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
 137             Class<?> elemClass = arrayClass.getComponentType();
 138             return !isSetter ?
 139                     MethodType.methodType(elemClass,  arrayClass, int.class) :
 140                     MethodType.methodType(void.class, arrayClass, int.class, elemClass);
 141         }
 142         static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
 143             String     name = name(arrayClass, isSetter);
 144             MethodType type = type(arrayClass, isSetter);
 145             try {
 146                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
 147             } catch (ReflectiveOperationException ex) {
 148                 throw uncaughtException(ex);
 149             }
 150         }
 151     }
 152 
 153     /**
 154      * Create a JVM-level adapter method handle to conform the given method


src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File