162 }
163 static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
164 String name = name(arrayClass, isSetter);
165 MethodType type = type(arrayClass, isSetter);
166 try {
167 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
168 } catch (ReflectiveOperationException ex) {
169 throw uncaughtException(ex);
170 }
171 }
172 }
173
174 /**
175 * Create a JVM-level adapter method handle to conform the given method
176 * handle to the similar newType, using only pairwise argument conversions.
177 * For each argument, convert incoming argument to the exact type needed.
178 * The argument conversions allowed are casting, boxing and unboxing,
179 * integral widening or narrowing, and floating point widening or narrowing.
180 * @param srcType required call type
181 * @param target original method handle
182 * @param level which strength of conversion is allowed
183 * @return an adapter to the original handle with the desired new type,
184 * or the original target if the types are already identical
185 * or null if the adaptation cannot be made
186 */
187 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
188 assert(level >= 0 && level <= 2);
189 MethodType dstType = target.type();
190 assert(dstType.parameterCount() == target.type().parameterCount());
191 if (srcType == dstType)
192 return target;
193
194 // Calculate extra arguments (temporaries) required in the names array.
195 // FIXME: Use an ArrayList<Name>. Some arguments require more than one conversion step.
196 final int INARG_COUNT = srcType.parameterCount();
197 int conversions = 0;
198 boolean[] needConv = new boolean[1+INARG_COUNT];
199 for (int i = 0; i <= INARG_COUNT; i++) {
200 Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
201 Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
202 if (!VerifyType.isNullConversion(src, dst, false) ||
203 level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
204 needConv[i] = true;
205 conversions++;
206 }
207 }
208 boolean retConv = needConv[INARG_COUNT];
209 if (retConv && srcType.returnType() == void.class) {
210 retConv = false;
211 conversions--;
212 }
213
214 final int IN_MH = 0;
215 final int INARG_BASE = 1;
216 final int INARG_LIMIT = INARG_BASE + INARG_COUNT;
217 final int NAME_LIMIT = INARG_LIMIT + conversions + 1;
218 final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1);
219 final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
220 final int RESULT = (srcType.returnType() == void.class ? -1 : NAME_LIMIT - 1);
221
222 // Now build a LambdaForm.
223 MethodType lambdaType = srcType.basicType().invokerType();
224 Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
225
226 // Collect the arguments to the outgoing call, maybe with conversions:
227 final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0]
228 Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
229
230 int nameCursor = INARG_LIMIT;
231 for (int i = 0; i < INARG_COUNT; i++) {
232 Class<?> src = srcType.parameterType(i);
233 Class<?> dst = dstType.parameterType(i);
234
235 if (!needConv[i]) {
236 // do nothing: difference is trivial
237 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
238 continue;
239 }
240
241 // Tricky case analysis follows.
242 MethodHandle fn = null;
243 if (src.isPrimitive()) {
244 if (dst.isPrimitive()) {
245 fn = ValueConversions.convertPrimitive(src, dst);
246 } else {
247 Wrapper w = Wrapper.forPrimitiveType(src);
248 MethodHandle boxMethod = ValueConversions.box(w);
249 if (dst == w.wrapperType())
250 fn = boxMethod;
251 else
252 fn = boxMethod.asType(MethodType.methodType(dst, src));
253 }
254 } else {
255 if (dst.isPrimitive()) {
256 // Caller has boxed a primitive. Unbox it for the target.
257 Wrapper w = Wrapper.forPrimitiveType(dst);
258 if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType(), false)) {
259 fn = ValueConversions.unbox(dst);
260 } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
261 // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int
262 // must include additional conversions
263 // src must be examined at runtime, to detect Byte, Character, etc.
264 MethodHandle unboxMethod = (level == 1
265 ? ValueConversions.unbox(dst)
266 : ValueConversions.unboxCast(dst));
267 fn = unboxMethod;
268 } else {
269 // Example: Byte->int
270 // Do this by reformulating the problem to Byte->byte.
271 Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
272 MethodHandle unbox = ValueConversions.unbox(srcPrim);
273 // Compose the two conversions. FIXME: should make two Names for this job
274 fn = unbox.asType(MethodType.methodType(dst, src));
275 }
276 } else {
277 // Simple reference conversion.
278 // Note: Do not check for a class hierarchy relation
279 // between src and dst. In all cases a 'null' argument
280 // will pass the cast conversion.
281 fn = ValueConversions.cast(dst, Lazy.MH_castReference);
282 }
283 }
284 Name conv = new Name(fn, names[INARG_BASE + i]);
285 assert(names[nameCursor] == null);
286 names[nameCursor++] = conv;
287 assert(outArgs[OUTARG_BASE + i] == null);
288 outArgs[OUTARG_BASE + i] = conv;
289 }
290
291 // Build argument array for the call.
292 assert(nameCursor == OUT_CALL);
293 names[OUT_CALL] = new Name(target, outArgs);
294
295 if (RETURN_CONV < 0) {
296 assert(OUT_CALL == names.length-1);
297 } else {
298 Class<?> needReturn = srcType.returnType();
299 Class<?> haveReturn = dstType.returnType();
300 MethodHandle fn;
301 Object[] arg = { names[OUT_CALL] };
302 if (haveReturn == void.class) {
303 // synthesize a zero value for the given void
304 Object zero = Wrapper.forBasicType(needReturn).zero();
305 fn = MethodHandles.constant(needReturn, zero);
306 arg = new Object[0]; // don't pass names[OUT_CALL] to conversion
307 } else {
308 MethodHandle identity = MethodHandles.identity(needReturn);
309 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
310 fn = makePairwiseConvert(identity, needConversion, level);
311 }
312 assert(names[RETURN_CONV] == null);
313 names[RETURN_CONV] = new Name(fn, arg);
314 assert(RETURN_CONV == names.length-1);
315 }
316
317 LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT);
318 return SimpleMethodHandle.make(srcType, form);
319 }
320
321 /**
322 * Identity function, with reference cast.
323 * @param t an arbitrary reference type
324 * @param x an arbitrary reference value
325 * @return the same value x
326 */
327 @ForceInline
328 @SuppressWarnings("unchecked")
329 static <T,U> T castReference(Class<? extends T> t, U x) {
330 // inlined Class.cast because we can't ForceInline it
331 if (x != null && !t.isInstance(x))
332 throw newClassCastException(t, x);
333 return (T) x;
334 }
335
336 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
337 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
338 }
339
340 static MethodHandle makeReferenceIdentity(Class<?> refType) {
341 MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
342 Name[] names = arguments(1, lambdaType);
343 names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
344 LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
345 return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
346 }
347
348 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
349 MethodType type = target.type();
350 int last = type.parameterCount() - 1;
351 if (type.parameterType(last) != arrayType)
352 target = target.asType(type.changeParameterType(last, arrayType));
353 target = target.asFixedArity(); // make sure this attribute is turned off
354 return new AsVarargsCollector(target, arrayType);
355 }
356
357 private static final class AsVarargsCollector extends DelegatingMethodHandle {
358 private final MethodHandle target;
359 private final Class<?> arrayType;
360 private @Stable MethodHandle asCollectorCache;
361
362 AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
363 this(target.type(), target, arrayType);
364 }
365 AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
366 super(type, target);
367 this.target = target;
703 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
704
705 lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
706
707 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
708 }
709
710 static
711 MethodHandle makeGuardWithCatch(MethodHandle target,
712 Class<? extends Throwable> exType,
713 MethodHandle catcher) {
714 MethodType type = target.type();
715 LambdaForm form = makeGuardWithCatchForm(type.basicType());
716
717 // Prepare auxiliary method handles used during LambdaForm interpreation.
718 // Box arguments and wrap them into Object[]: ValueConversions.array().
719 MethodType varargsType = type.changeReturnType(Object[].class);
720 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
721 // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
722 MethodHandle unboxResult;
723 if (type.returnType().isPrimitive()) {
724 unboxResult = ValueConversions.unbox(type.returnType());
725 } else {
726 unboxResult = ValueConversions.identity();
727 }
728
729 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
730 BoundMethodHandle mh;
731 try {
732 mh = (BoundMethodHandle)
733 data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
734 (Object) collectArgs, (Object) unboxResult);
735 } catch (Throwable ex) {
736 throw uncaughtException(ex);
737 }
738 assert(mh.type() == type);
739 return mh;
740 }
741
742 /**
743 * Intrinsified during LambdaForm compilation
744 * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
745 */
746 @LambdaForm.Hidden
756 }
757
758 /** Prepend an element {@code elem} to an {@code array}. */
759 @LambdaForm.Hidden
760 private static Object[] prepend(Object elem, Object[] array) {
761 Object[] newArray = new Object[array.length+1];
762 newArray[0] = elem;
763 System.arraycopy(array, 0, newArray, 1, array.length);
764 return newArray;
765 }
766
767 static
768 MethodHandle throwException(MethodType type) {
769 assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
770 int arity = type.parameterCount();
771 if (arity > 1) {
772 MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
773 mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
774 return mh;
775 }
776 return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
777 }
778
779 static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
780
781 static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
782 static MethodHandle fakeMethodHandleInvoke(MemberName method) {
783 int idx;
784 assert(method.isMethodHandleInvoke());
785 switch (method.getName()) {
786 case "invoke": idx = 0; break;
787 case "invokeExact": idx = 1; break;
788 default: throw new InternalError(method.getName());
789 }
790 MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
791 if (mh != null) return mh;
792 MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
793 MethodHandle.class, Object[].class);
794 mh = throwException(type);
795 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
796 if (!method.getInvocationType().equals(mh.type()))
|
162 }
163 static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
164 String name = name(arrayClass, isSetter);
165 MethodType type = type(arrayClass, isSetter);
166 try {
167 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
168 } catch (ReflectiveOperationException ex) {
169 throw uncaughtException(ex);
170 }
171 }
172 }
173
174 /**
175 * Create a JVM-level adapter method handle to conform the given method
176 * handle to the similar newType, using only pairwise argument conversions.
177 * For each argument, convert incoming argument to the exact type needed.
178 * The argument conversions allowed are casting, boxing and unboxing,
179 * integral widening or narrowing, and floating point widening or narrowing.
180 * @param srcType required call type
181 * @param target original method handle
182 * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed
183 * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double)
184 * @return an adapter to the original handle with the desired new type,
185 * or the original target if the types are already identical
186 * or null if the adaptation cannot be made
187 */
188 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
189 boolean strict, boolean monobox) {
190 MethodType dstType = target.type();
191 assert(dstType.parameterCount() == target.type().parameterCount());
192 if (srcType == dstType)
193 return target;
194 return makePairwiseConvertIndirect(target, srcType, strict, monobox);
195 }
196
197 private static int countNonNull(Object[] array) {
198 int count = 0;
199 for (Object x : array) {
200 if (x != null) ++count;
201 }
202 return count;
203 }
204
205 static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
206 boolean strict, boolean monobox) {
207 // Calculate extra arguments (temporaries) required in the names array.
208 Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
209 final int INARG_COUNT = srcType.parameterCount();
210 int convCount = countNonNull(convSpecs);
211 boolean retConv = (convSpecs[INARG_COUNT] != null);
212 boolean retVoid = srcType.returnType() == void.class;
213 if (retConv && retVoid) {
214 convCount -= 1;
215 retConv = false;
216 }
217
218 final int IN_MH = 0;
219 final int INARG_BASE = 1;
220 final int INARG_LIMIT = INARG_BASE + INARG_COUNT;
221 final int NAME_LIMIT = INARG_LIMIT + convCount + 1;
222 final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1);
223 final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
224 final int RESULT = (retVoid ? -1 : NAME_LIMIT - 1);
225
226 // Now build a LambdaForm.
227 MethodType lambdaType = srcType.basicType().invokerType();
228 Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
229
230 // Collect the arguments to the outgoing call, maybe with conversions:
231 final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0]
232 Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
233
234 int nameCursor = INARG_LIMIT;
235 for (int i = 0; i < INARG_COUNT; i++) {
236 Object convSpec = convSpecs[i];
237 if (convSpec == null) {
238 // do nothing: difference is trivial
239 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
240 continue;
241 }
242
243 Name conv;
244 if (convSpec instanceof Class) {
245 Class<?> convClass = (Class<?>) convSpec;
246 conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]);
247 } else {
248 MethodHandle fn = (MethodHandle) convSpec;
249 conv = new Name(fn, names[INARG_BASE + i]);
250 }
251 assert(names[nameCursor] == null);
252 names[nameCursor++] = conv;
253 assert(outArgs[OUTARG_BASE + i] == null);
254 outArgs[OUTARG_BASE + i] = conv;
255 }
256
257 // Build argument array for the call.
258 assert(nameCursor == OUT_CALL);
259 names[OUT_CALL] = new Name(target, outArgs);
260
261 Object convSpec = convSpecs[INARG_COUNT];
262 if (!retConv) {
263 assert(OUT_CALL == names.length-1);
264 } else {
265 Name conv;
266 if (convSpec == void.class) {
267 conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType())));
268 } else if (convSpec instanceof Class) {
269 Class<?> convClass = (Class<?>) convSpec;
270 conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]);
271 } else {
272 MethodHandle fn = (MethodHandle) convSpec;
273 if (fn.type().parameterCount() == 0)
274 conv = new Name(fn); // don't pass retval to void conversion
275 else
276 conv = new Name(fn, names[OUT_CALL]);
277 }
278 assert(names[RETURN_CONV] == null);
279 names[RETURN_CONV] = conv;
280 assert(RETURN_CONV == names.length-1);
281 }
282
283 LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT);
284 return SimpleMethodHandle.make(srcType, form);
285 }
286
287 /**
288 * Identity function, with reference cast.
289 * @param t an arbitrary reference type
290 * @param x an arbitrary reference value
291 * @return the same value x
292 */
293 @ForceInline
294 @SuppressWarnings("unchecked")
295 static <T,U> T castReference(Class<? extends T> t, U x) {
296 // inlined Class.cast because we can't ForceInline it
297 if (x != null && !t.isInstance(x))
298 throw newClassCastException(t, x);
299 return (T) x;
300 }
301
302 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
303 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
304 }
305
306 static MethodHandle makeReferenceIdentity(Class<?> refType) {
307 MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
308 Name[] names = arguments(1, lambdaType);
309 names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
310 LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
311 return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
312 }
313
314 static Object[] computeValueConversions(MethodType srcType, MethodType dstType,
315 boolean strict, boolean monobox) {
316 final int INARG_COUNT = srcType.parameterCount();
317 Object[] convSpecs = new Object[INARG_COUNT+1];
318 for (int i = 0; i <= INARG_COUNT; i++) {
319 boolean isRet = (i == INARG_COUNT);
320 Class<?> src = isRet ? dstType.returnType() : srcType.parameterType(i);
321 Class<?> dst = isRet ? srcType.returnType() : dstType.parameterType(i);
322 if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) {
323 convSpecs[i] = valueConversion(src, dst, strict, monobox);
324 }
325 }
326 return convSpecs;
327 }
328 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
329 boolean strict) {
330 return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false);
331 }
332
333 /**
334 * Find a conversion function from the given source to the given destination.
335 * This conversion function will be used as a LF NamedFunction.
336 * Return a Class object if a simple cast is needed.
337 * Return void.class if void is involved.
338 */
339 static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
340 assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)); // caller responsibility
341 if (dst == void.class)
342 return dst;
343 MethodHandle fn;
344 if (src.isPrimitive()) {
345 if (src == void.class) {
346 return void.class; // caller must recognize this specially
347 } else if (dst.isPrimitive()) {
348 // Examples: int->byte, byte->int, boolean->int (!strict)
349 fn = ValueConversions.convertPrimitive(src, dst);
350 } else {
351 // Examples: int->Integer, boolean->Object, float->Number
352 Wrapper wsrc = Wrapper.forPrimitiveType(src);
353 fn = ValueConversions.boxExact(wsrc);
354 assert(fn.type().parameterType(0) == wsrc.primitiveType());
355 assert(fn.type().returnType() == wsrc.wrapperType());
356 if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
357 // Corner case, such as int->Long, which will probably fail.
358 MethodType mt = MethodType.methodType(dst, src);
359 if (strict)
360 fn = fn.asType(mt);
361 else
362 fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false);
363 }
364 }
365 } else {
366 if (dst.isPrimitive()) {
367 Wrapper wdst = Wrapper.forPrimitiveType(dst);
368 if (monobox || src == wdst.wrapperType()) {
369 // Use a strongly-typed unboxer, if possible.
370 fn = ValueConversions.unboxExact(wdst, strict);
371 } else {
372 // Examples: Object->int, Number->int, Comparable->int, Byte->int
373 // must include additional conversions
374 // src must be examined at runtime, to detect Byte, Character, etc.
375 fn = (strict
376 ? ValueConversions.unboxWiden(wdst)
377 : ValueConversions.unboxCast(wdst));
378 }
379 } else {
380 // Simple reference conversion.
381 // Note: Do not check for a class hierarchy relation
382 // between src and dst. In all cases a 'null' argument
383 // will pass the cast conversion.
384 return dst;
385 }
386 }
387 assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
388 return fn;
389 }
390
391 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
392 MethodType type = target.type();
393 int last = type.parameterCount() - 1;
394 if (type.parameterType(last) != arrayType)
395 target = target.asType(type.changeParameterType(last, arrayType));
396 target = target.asFixedArity(); // make sure this attribute is turned off
397 return new AsVarargsCollector(target, arrayType);
398 }
399
400 private static final class AsVarargsCollector extends DelegatingMethodHandle {
401 private final MethodHandle target;
402 private final Class<?> arrayType;
403 private @Stable MethodHandle asCollectorCache;
404
405 AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
406 this(target.type(), target, arrayType);
407 }
408 AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
409 super(type, target);
410 this.target = target;
746 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
747
748 lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
749
750 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
751 }
752
753 static
754 MethodHandle makeGuardWithCatch(MethodHandle target,
755 Class<? extends Throwable> exType,
756 MethodHandle catcher) {
757 MethodType type = target.type();
758 LambdaForm form = makeGuardWithCatchForm(type.basicType());
759
760 // Prepare auxiliary method handles used during LambdaForm interpreation.
761 // Box arguments and wrap them into Object[]: ValueConversions.array().
762 MethodType varargsType = type.changeReturnType(Object[].class);
763 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
764 // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
765 MethodHandle unboxResult;
766 Class<?> rtype = type.returnType();
767 if (rtype.isPrimitive()) {
768 if (rtype == void.class) {
769 unboxResult = ValueConversions.ignore();
770 } else {
771 Wrapper w = Wrapper.forPrimitiveType(type.returnType());
772 unboxResult = ValueConversions.unboxExact(w);
773 }
774 } else {
775 unboxResult = MethodHandles.identity(Object.class);
776 }
777
778 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
779 BoundMethodHandle mh;
780 try {
781 mh = (BoundMethodHandle)
782 data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
783 (Object) collectArgs, (Object) unboxResult);
784 } catch (Throwable ex) {
785 throw uncaughtException(ex);
786 }
787 assert(mh.type() == type);
788 return mh;
789 }
790
791 /**
792 * Intrinsified during LambdaForm compilation
793 * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
794 */
795 @LambdaForm.Hidden
805 }
806
807 /** Prepend an element {@code elem} to an {@code array}. */
808 @LambdaForm.Hidden
809 private static Object[] prepend(Object elem, Object[] array) {
810 Object[] newArray = new Object[array.length+1];
811 newArray[0] = elem;
812 System.arraycopy(array, 0, newArray, 1, array.length);
813 return newArray;
814 }
815
816 static
817 MethodHandle throwException(MethodType type) {
818 assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
819 int arity = type.parameterCount();
820 if (arity > 1) {
821 MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
822 mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
823 return mh;
824 }
825 return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, false, true);
826 }
827
828 static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
829
830 static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
831 static MethodHandle fakeMethodHandleInvoke(MemberName method) {
832 int idx;
833 assert(method.isMethodHandleInvoke());
834 switch (method.getName()) {
835 case "invoke": idx = 0; break;
836 case "invokeExact": idx = 1; break;
837 default: throw new InternalError(method.getName());
838 }
839 MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
840 if (mh != null) return mh;
841 MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
842 MethodHandle.class, Object[].class);
843 mh = throwException(type);
844 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
845 if (!method.getInvocationType().equals(mh.type()))
|