37 import sun.invoke.empty.Empty;
38 import sun.invoke.util.ValueConversions;
39 import sun.invoke.util.VerifyType;
40 import sun.invoke.util.Wrapper;
41
42 import java.lang.invoke.MethodHandles.Lookup;
43 import java.lang.reflect.Array;
44 import java.nio.ByteOrder;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.function.Function;
52 import java.util.stream.Stream;
53
54 import static java.lang.invoke.LambdaForm.*;
55 import static java.lang.invoke.MethodHandleStatics.*;
56 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
57 import static java.lang.invoke.MethodHandleNatives.Constants.HIDDEN_CLASS;
58 import static jdk.internal.org.objectweb.asm.Opcodes.*;
59
60 /**
61 * Trusted implementation code for MethodHandle.
62 * @author jrose
63 */
64 /*non-public*/
65 abstract class MethodHandleImpl {
66
67 /// Factory methods to create method handles:
68
69 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
70 if (arrayClass == Object[].class) {
71 return ArrayAccess.objectAccessor(access);
72 }
73 if (!arrayClass.isArray())
74 throw newIllegalArgumentException("not an array: "+arrayClass);
75 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
76 int cacheIndex = ArrayAccess.cacheIndex(access);
77 MethodHandle mh = cache[cacheIndex];
1156 // Cache the result of makeInjectedInvoker once per argument class.
1157 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1158 return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1159 }
1160
1161 private static MethodHandle makeInjectedInvoker(Class<?> targetClass) {
1162 try {
1163 /*
1164 * The invoker class defined to the same class loader as the lookup class
1165 * but in an unnamed package so that the class bytes can be cached and
1166 * reused for any @CSM.
1167 *
1168 * @CSM must be public and exported if called by any module.
1169 */
1170 String name = targetClass.getName() + "$$InjectedInvoker";
1171 if (targetClass.isHiddenClass()) {
1172 // use the original class name
1173 name = name.replace('/', '_');
1174 }
1175 Class<?> invokerClass = new Lookup(targetClass)
1176 .makeHiddenClassDefiner(name, INJECTED_INVOKER_TEMPLATE, 0).defineClass(true);
1177 assert checkInjectedInvoker(targetClass, invokerClass);
1178 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1179 } catch (ReflectiveOperationException ex) {
1180 throw uncaughtException(ex);
1181 }
1182 }
1183
1184 private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1185 @Override protected MethodHandle computeValue(Class<?> hostClass) {
1186 return makeInjectedInvoker(hostClass);
1187 }
1188 };
1189
1190 // Adapt mh so that it can be called directly from an injected invoker:
1191 private static MethodHandle prepareForInvoker(MethodHandle mh) {
1192 mh = mh.asFixedArity();
1193 MethodType mt = mh.type();
1194 int arity = mt.parameterCount();
1195 MethodHandle vamh = mh.asType(mt.generic());
1196 vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
|
37 import sun.invoke.empty.Empty;
38 import sun.invoke.util.ValueConversions;
39 import sun.invoke.util.VerifyType;
40 import sun.invoke.util.Wrapper;
41
42 import java.lang.invoke.MethodHandles.Lookup;
43 import java.lang.reflect.Array;
44 import java.nio.ByteOrder;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.HashMap;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.function.Function;
52 import java.util.stream.Stream;
53
54 import static java.lang.invoke.LambdaForm.*;
55 import static java.lang.invoke.MethodHandleStatics.*;
56 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
57 import static jdk.internal.org.objectweb.asm.Opcodes.*;
58
59 /**
60 * Trusted implementation code for MethodHandle.
61 * @author jrose
62 */
63 /*non-public*/
64 abstract class MethodHandleImpl {
65
66 /// Factory methods to create method handles:
67
68 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
69 if (arrayClass == Object[].class) {
70 return ArrayAccess.objectAccessor(access);
71 }
72 if (!arrayClass.isArray())
73 throw newIllegalArgumentException("not an array: "+arrayClass);
74 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
75 int cacheIndex = ArrayAccess.cacheIndex(access);
76 MethodHandle mh = cache[cacheIndex];
1155 // Cache the result of makeInjectedInvoker once per argument class.
1156 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1157 return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1158 }
1159
1160 private static MethodHandle makeInjectedInvoker(Class<?> targetClass) {
1161 try {
1162 /*
1163 * The invoker class defined to the same class loader as the lookup class
1164 * but in an unnamed package so that the class bytes can be cached and
1165 * reused for any @CSM.
1166 *
1167 * @CSM must be public and exported if called by any module.
1168 */
1169 String name = targetClass.getName() + "$$InjectedInvoker";
1170 if (targetClass.isHiddenClass()) {
1171 // use the original class name
1172 name = name.replace('/', '_');
1173 }
1174 Class<?> invokerClass = new Lookup(targetClass)
1175 .makeHiddenClassDefiner(name, INJECTED_INVOKER_TEMPLATE)
1176 .defineClass(true);
1177 assert checkInjectedInvoker(targetClass, invokerClass);
1178 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1179 } catch (ReflectiveOperationException ex) {
1180 throw uncaughtException(ex);
1181 }
1182 }
1183
1184 private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1185 @Override protected MethodHandle computeValue(Class<?> hostClass) {
1186 return makeInjectedInvoker(hostClass);
1187 }
1188 };
1189
1190 // Adapt mh so that it can be called directly from an injected invoker:
1191 private static MethodHandle prepareForInvoker(MethodHandle mh) {
1192 mh = mh.asFixedArity();
1193 MethodType mt = mh.type();
1194 int arity = mt.parameterCount();
1195 MethodHandle vamh = mh.asType(mt.generic());
1196 vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
|