291 final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
292 final int ARG_BASE = CALL_MH + 1;
293 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
294 final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
295 int nameCursor = OUTARG_LIMIT;
296 final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
297 final int CHECK_TYPE = nameCursor++;
298 final int LINKER_CALL = nameCursor++;
299 MethodType invokerFormType = mtype.invokerType();
300 if (isLinker) {
301 if (!customized)
302 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
303 } else {
304 invokerFormType = invokerFormType.invokerType();
305 }
306 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
307 assert(names.length == nameCursor)
308 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
309 if (MTYPE_ARG >= INARG_LIMIT) {
310 assert(names[MTYPE_ARG] == null);
311 NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
312 names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
313 // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
314 }
315
316 // Make the final call. If isGeneric, then prepend the result of type checking.
317 MethodType outCallType = mtype.basicType();
318 Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
319 Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
320 if (!isGeneric) {
321 names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
322 // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
323 } else {
324 names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
325 // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
326 outArgs[0] = names[CHECK_TYPE];
327 }
328 names[LINKER_CALL] = new Name(outCallType, outArgs);
329 lform = new LambdaForm(debugName, INARG_LIMIT, names);
330 if (isLinker)
331 lform.compileToBytecode(); // JVM needs a real methodOop
343 /** Static definition of MethodHandle.invokeExact checking code. */
344 /*non-public*/ static
345 @ForceInline
346 void checkExactType(Object mhObj, Object expectedObj) {
347 MethodHandle mh = (MethodHandle) mhObj;
348 MethodType expected = (MethodType) expectedObj;
349 MethodType actual = mh.type();
350 if (actual != expected)
351 throw newWrongMethodTypeException(expected, actual);
352 }
353
354 /** Static definition of MethodHandle.invokeGeneric checking code.
355 * Directly returns the type-adjusted MH to invoke, as follows:
356 * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
357 */
358 /*non-public*/ static
359 @ForceInline
360 Object checkGenericType(Object mhObj, Object expectedObj) {
361 MethodHandle mh = (MethodHandle) mhObj;
362 MethodType expected = (MethodType) expectedObj;
363 if (mh.type() == expected) return mh;
364 MethodHandle atc = mh.asTypeCache;
365 if (atc != null && atc.type() == expected) return atc;
366 return mh.asType(expected);
367 /* Maybe add more paths here. Possible optimizations:
368 * for (R)MH.invoke(a*),
369 * let MT0 = TYPEOF(a*:R), MT1 = MH.type
370 *
371 * if MT0==MT1 or MT1 can be safely called by MT0
372 * => MH.invokeBasic(a*)
373 * if MT1 can be safely called by MT0[R := Object]
374 * => MH.invokeBasic(a*) & checkcast(R)
375 * if MT1 can be safely called by MT0[* := Object]
376 * => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
377 * if a big adapter BA can be pulled out of (MT0,MT1)
378 * => BA.invokeBasic(MT0,MH,a*)
379 * if a local adapter LA can cached on static CS0 = new GICS(MT0)
380 * => CS0.LA.invokeBasic(MH,a*)
381 * else
382 * => MH.asType(MT0).invokeBasic(A*)
383 */
384 }
385
419 final int PREPEND_MH = 0, PREPEND_COUNT = 1;
420 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
421 // prepend MH argument:
422 System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
423 outArgs[PREPEND_MH] = names[CALL_MH];
424 names[LINKER_CALL] = new Name(mtype, outArgs);
425 lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
426 lform.compileToBytecode(); // JVM needs a real methodOop
427 lform = mtype.form().setCachedLambdaForm(which, lform);
428 return lform;
429 }
430
431 /** Static definition of MethodHandle.invokeGeneric checking code. */
432 /*non-public*/ static
433 @ForceInline
434 Object getCallSiteTarget(Object site) {
435 return ((CallSite)site).getTarget();
436 }
437
438 // Local constant functions:
439 private static final NamedFunction NF_checkExactType;
440 private static final NamedFunction NF_checkGenericType;
441 private static final NamedFunction NF_asType;
442 private static final NamedFunction NF_getCallSiteTarget;
443 static {
444 try {
445 NF_checkExactType = new NamedFunction(Invokers.class
446 .getDeclaredMethod("checkExactType", Object.class, Object.class));
447 NF_checkGenericType = new NamedFunction(Invokers.class
448 .getDeclaredMethod("checkGenericType", Object.class, Object.class));
449 NF_asType = new NamedFunction(MethodHandle.class
450 .getDeclaredMethod("asType", MethodType.class));
451 NF_getCallSiteTarget = new NamedFunction(Invokers.class
452 .getDeclaredMethod("getCallSiteTarget", Object.class));
453 NF_checkExactType.resolve();
454 NF_checkGenericType.resolve();
455 NF_getCallSiteTarget.resolve();
456 // bound
457 } catch (ReflectiveOperationException ex) {
458 throw newInternalError(ex);
459 }
460 }
461
462 }
|
291 final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
292 final int ARG_BASE = CALL_MH + 1;
293 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
294 final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
295 int nameCursor = OUTARG_LIMIT;
296 final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
297 final int CHECK_TYPE = nameCursor++;
298 final int LINKER_CALL = nameCursor++;
299 MethodType invokerFormType = mtype.invokerType();
300 if (isLinker) {
301 if (!customized)
302 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
303 } else {
304 invokerFormType = invokerFormType.invokerType();
305 }
306 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
307 assert(names.length == nameCursor)
308 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
309 if (MTYPE_ARG >= INARG_LIMIT) {
310 assert(names[MTYPE_ARG] == null);
311 NamedFunction getter = BoundMethodHandle.speciesData_L().getterFunction(0);
312 names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
313 // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
314 }
315
316 // Make the final call. If isGeneric, then prepend the result of type checking.
317 MethodType outCallType = mtype.basicType();
318 Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
319 Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
320 if (!isGeneric) {
321 names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
322 // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
323 } else {
324 names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
325 // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
326 outArgs[0] = names[CHECK_TYPE];
327 }
328 names[LINKER_CALL] = new Name(outCallType, outArgs);
329 lform = new LambdaForm(debugName, INARG_LIMIT, names);
330 if (isLinker)
331 lform.compileToBytecode(); // JVM needs a real methodOop
343 /** Static definition of MethodHandle.invokeExact checking code. */
344 /*non-public*/ static
345 @ForceInline
346 void checkExactType(Object mhObj, Object expectedObj) {
347 MethodHandle mh = (MethodHandle) mhObj;
348 MethodType expected = (MethodType) expectedObj;
349 MethodType actual = mh.type();
350 if (actual != expected)
351 throw newWrongMethodTypeException(expected, actual);
352 }
353
354 /** Static definition of MethodHandle.invokeGeneric checking code.
355 * Directly returns the type-adjusted MH to invoke, as follows:
356 * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
357 */
358 /*non-public*/ static
359 @ForceInline
360 Object checkGenericType(Object mhObj, Object expectedObj) {
361 MethodHandle mh = (MethodHandle) mhObj;
362 MethodType expected = (MethodType) expectedObj;
363 return mh.asType(expected);
364 /* Maybe add more paths here. Possible optimizations:
365 * for (R)MH.invoke(a*),
366 * let MT0 = TYPEOF(a*:R), MT1 = MH.type
367 *
368 * if MT0==MT1 or MT1 can be safely called by MT0
369 * => MH.invokeBasic(a*)
370 * if MT1 can be safely called by MT0[R := Object]
371 * => MH.invokeBasic(a*) & checkcast(R)
372 * if MT1 can be safely called by MT0[* := Object]
373 * => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
374 * if a big adapter BA can be pulled out of (MT0,MT1)
375 * => BA.invokeBasic(MT0,MH,a*)
376 * if a local adapter LA can cached on static CS0 = new GICS(MT0)
377 * => CS0.LA.invokeBasic(MH,a*)
378 * else
379 * => MH.asType(MT0).invokeBasic(A*)
380 */
381 }
382
416 final int PREPEND_MH = 0, PREPEND_COUNT = 1;
417 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
418 // prepend MH argument:
419 System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
420 outArgs[PREPEND_MH] = names[CALL_MH];
421 names[LINKER_CALL] = new Name(mtype, outArgs);
422 lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
423 lform.compileToBytecode(); // JVM needs a real methodOop
424 lform = mtype.form().setCachedLambdaForm(which, lform);
425 return lform;
426 }
427
428 /** Static definition of MethodHandle.invokeGeneric checking code. */
429 /*non-public*/ static
430 @ForceInline
431 Object getCallSiteTarget(Object site) {
432 return ((CallSite)site).getTarget();
433 }
434
435 // Local constant functions:
436 private static final NamedFunction
437 NF_checkExactType,
438 NF_checkGenericType,
439 NF_getCallSiteTarget;
440 static {
441 try {
442 NamedFunction nfs[] = {
443 NF_checkExactType = new NamedFunction(Invokers.class
444 .getDeclaredMethod("checkExactType", Object.class, Object.class)),
445 NF_checkGenericType = new NamedFunction(Invokers.class
446 .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
447 NF_getCallSiteTarget = new NamedFunction(Invokers.class
448 .getDeclaredMethod("getCallSiteTarget", Object.class))
449 };
450 for (NamedFunction nf : nfs) {
451 // Each nf must be statically invocable or we get tied up in our bootstraps.
452 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
453 nf.resolve();
454 }
455 } catch (ReflectiveOperationException ex) {
456 throw newInternalError(ex);
457 }
458 }
459
460 }
|