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
|