256 } else {
257 invokerFormType = invokerFormType.invokerType();
258 }
259 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
260 assert(names.length == nameCursor)
261 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
262 if (MTYPE_ARG >= INARG_LIMIT) {
263 assert(names[MTYPE_ARG] == null);
264 BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
265 names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
266 NamedFunction getter = speciesData.getterFunction(0);
267 names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
268 // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
269 }
270
271 // Make the final call. If isGeneric, then prepend the result of type checking.
272 MethodType outCallType = mtype.basicType();
273 Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
274 Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
275 if (!isGeneric) {
276 names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
277 // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
278 } else {
279 names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
280 // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
281 outArgs[0] = names[CHECK_TYPE];
282 }
283 if (CHECK_CUSTOM != -1) {
284 names[CHECK_CUSTOM] = new Name(NF_checkCustomized, outArgs[0]);
285 }
286 names[LINKER_CALL] = new Name(outCallType, outArgs);
287 lform = new LambdaForm(debugName, INARG_LIMIT, names);
288 if (isLinker)
289 lform.compileToBytecode(); // JVM needs a real methodOop
290 if (isCached)
291 lform = mtype.form().setCachedLambdaForm(which, lform);
292 return lform;
293 }
294
295 /*non-public*/ static
296 WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
297 // FIXME: merge with JVM logic for throwing WMTE
298 return new WrongMethodTypeException("expected "+expected+" but found "+actual);
299 }
300
301 /** Static definition of MethodHandle.invokeExact checking code. */
302 /*non-public*/ static
303 @ForceInline
304 void checkExactType(Object mhObj, Object expectedObj) {
352 private static LambdaForm callSiteForm(MethodType mtype, boolean skipCallSite) {
353 mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
354 final int which = (skipCallSite ? MethodTypeForm.LF_MH_LINKER : MethodTypeForm.LF_CS_LINKER);
355 LambdaForm lform = mtype.form().cachedLambdaForm(which);
356 if (lform != null) return lform;
357 // exactInvokerForm (Object,Object)Object
358 // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
359 final int ARG_BASE = 0;
360 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
361 final int INARG_LIMIT = OUTARG_LIMIT + 1;
362 int nameCursor = OUTARG_LIMIT;
363 final int APPENDIX_ARG = nameCursor++; // the last in-argument
364 final int CSITE_ARG = skipCallSite ? -1 : APPENDIX_ARG;
365 final int CALL_MH = skipCallSite ? APPENDIX_ARG : nameCursor++; // result of getTarget
366 final int LINKER_CALL = nameCursor++;
367 MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
368 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
369 assert(names.length == nameCursor);
370 assert(names[APPENDIX_ARG] != null);
371 if (!skipCallSite)
372 names[CALL_MH] = new Name(NF_getCallSiteTarget, names[CSITE_ARG]);
373 // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
374 final int PREPEND_MH = 0, PREPEND_COUNT = 1;
375 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
376 // prepend MH argument:
377 System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
378 outArgs[PREPEND_MH] = names[CALL_MH];
379 names[LINKER_CALL] = new Name(mtype, outArgs);
380 lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
381 lform.compileToBytecode(); // JVM needs a real methodOop
382 lform = mtype.form().setCachedLambdaForm(which, lform);
383 return lform;
384 }
385
386 /** Static definition of MethodHandle.invokeGeneric checking code. */
387 /*non-public*/ static
388 @ForceInline
389 Object getCallSiteTarget(Object site) {
390 return ((CallSite)site).getTarget();
391 }
392
394 @ForceInline
395 void checkCustomized(Object o) {
396 MethodHandle mh = (MethodHandle)o;
397 if (MethodHandleImpl.isCompileConstant(mh)) return;
398 if (mh.form.customized == null) {
399 maybeCustomize(mh);
400 }
401 }
402
403 /*non-public*/ static
404 @DontInline
405 void maybeCustomize(MethodHandle mh) {
406 byte count = mh.customizationCount;
407 if (count >= CUSTOMIZE_THRESHOLD) {
408 mh.customize();
409 } else {
410 mh.customizationCount = (byte)(count+1);
411 }
412 }
413
414 // Local constant functions:
415 private static final NamedFunction
416 NF_checkExactType,
417 NF_checkGenericType,
418 NF_getCallSiteTarget,
419 NF_checkCustomized;
420 static {
421 try {
422 NamedFunction nfs[] = {
423 NF_checkExactType = new NamedFunction(Invokers.class
424 .getDeclaredMethod("checkExactType", Object.class, Object.class)),
425 NF_checkGenericType = new NamedFunction(Invokers.class
426 .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
427 NF_getCallSiteTarget = new NamedFunction(Invokers.class
428 .getDeclaredMethod("getCallSiteTarget", Object.class)),
429 NF_checkCustomized = new NamedFunction(Invokers.class
430 .getDeclaredMethod("checkCustomized", Object.class))
431 };
432 for (NamedFunction nf : nfs) {
433 // Each nf must be statically invocable or we get tied up in our bootstraps.
434 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
435 nf.resolve();
436 }
437 } catch (ReflectiveOperationException ex) {
438 throw newInternalError(ex);
439 }
440 }
441
442 private static class Lazy {
443 private static final MethodHandle MH_asSpreader;
444
445 static {
446 try {
447 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
448 MethodType.methodType(MethodHandle.class, Class.class, int.class));
449 } catch (ReflectiveOperationException ex) {
450 throw newInternalError(ex);
451 }
452 }
453 }
454 }
|
256 } else {
257 invokerFormType = invokerFormType.invokerType();
258 }
259 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
260 assert(names.length == nameCursor)
261 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
262 if (MTYPE_ARG >= INARG_LIMIT) {
263 assert(names[MTYPE_ARG] == null);
264 BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
265 names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
266 NamedFunction getter = speciesData.getterFunction(0);
267 names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
268 // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
269 }
270
271 // Make the final call. If isGeneric, then prepend the result of type checking.
272 MethodType outCallType = mtype.basicType();
273 Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
274 Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
275 if (!isGeneric) {
276 names[CHECK_TYPE] = new Name(getConstantFunction(NF_checkExactType), names[CALL_MH], mtypeArg);
277 // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
278 } else {
279 names[CHECK_TYPE] = new Name(getConstantFunction(NF_checkGenericType), names[CALL_MH], mtypeArg);
280 // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
281 outArgs[0] = names[CHECK_TYPE];
282 }
283 if (CHECK_CUSTOM != -1) {
284 names[CHECK_CUSTOM] = new Name(getConstantFunction(NF_checkCustomized), outArgs[0]);
285 }
286 names[LINKER_CALL] = new Name(outCallType, outArgs);
287 lform = new LambdaForm(debugName, INARG_LIMIT, names);
288 if (isLinker)
289 lform.compileToBytecode(); // JVM needs a real methodOop
290 if (isCached)
291 lform = mtype.form().setCachedLambdaForm(which, lform);
292 return lform;
293 }
294
295 /*non-public*/ static
296 WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
297 // FIXME: merge with JVM logic for throwing WMTE
298 return new WrongMethodTypeException("expected "+expected+" but found "+actual);
299 }
300
301 /** Static definition of MethodHandle.invokeExact checking code. */
302 /*non-public*/ static
303 @ForceInline
304 void checkExactType(Object mhObj, Object expectedObj) {
352 private static LambdaForm callSiteForm(MethodType mtype, boolean skipCallSite) {
353 mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
354 final int which = (skipCallSite ? MethodTypeForm.LF_MH_LINKER : MethodTypeForm.LF_CS_LINKER);
355 LambdaForm lform = mtype.form().cachedLambdaForm(which);
356 if (lform != null) return lform;
357 // exactInvokerForm (Object,Object)Object
358 // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
359 final int ARG_BASE = 0;
360 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
361 final int INARG_LIMIT = OUTARG_LIMIT + 1;
362 int nameCursor = OUTARG_LIMIT;
363 final int APPENDIX_ARG = nameCursor++; // the last in-argument
364 final int CSITE_ARG = skipCallSite ? -1 : APPENDIX_ARG;
365 final int CALL_MH = skipCallSite ? APPENDIX_ARG : nameCursor++; // result of getTarget
366 final int LINKER_CALL = nameCursor++;
367 MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
368 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
369 assert(names.length == nameCursor);
370 assert(names[APPENDIX_ARG] != null);
371 if (!skipCallSite)
372 names[CALL_MH] = new Name(getConstantFunction(NF_getCallSiteTarget), names[CSITE_ARG]);
373 // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
374 final int PREPEND_MH = 0, PREPEND_COUNT = 1;
375 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
376 // prepend MH argument:
377 System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
378 outArgs[PREPEND_MH] = names[CALL_MH];
379 names[LINKER_CALL] = new Name(mtype, outArgs);
380 lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
381 lform.compileToBytecode(); // JVM needs a real methodOop
382 lform = mtype.form().setCachedLambdaForm(which, lform);
383 return lform;
384 }
385
386 /** Static definition of MethodHandle.invokeGeneric checking code. */
387 /*non-public*/ static
388 @ForceInline
389 Object getCallSiteTarget(Object site) {
390 return ((CallSite)site).getTarget();
391 }
392
394 @ForceInline
395 void checkCustomized(Object o) {
396 MethodHandle mh = (MethodHandle)o;
397 if (MethodHandleImpl.isCompileConstant(mh)) return;
398 if (mh.form.customized == null) {
399 maybeCustomize(mh);
400 }
401 }
402
403 /*non-public*/ static
404 @DontInline
405 void maybeCustomize(MethodHandle mh) {
406 byte count = mh.customizationCount;
407 if (count >= CUSTOMIZE_THRESHOLD) {
408 mh.customize();
409 } else {
410 mh.customizationCount = (byte)(count+1);
411 }
412 }
413
414 private static NamedFunction getConstantFunction(int idx) {
415 NamedFunction function = FUNCTIONS[idx];
416 if (function != null) {
417 return function;
418 }
419 return setCachedFunction(idx, makeConstantFunction(idx));
420 }
421
422 private static synchronized NamedFunction setCachedFunction(int idx, final NamedFunction function) {
423 // Simulate a CAS, to avoid racy duplication of results.
424 NamedFunction prev = FUNCTIONS[idx];
425 if (prev != null) {
426 return prev;
427 }
428 FUNCTIONS[idx] = function;
429 function.resolve();
430 return function;
431 }
432
433 // Indexes into constant functions:
434 private static final int
435 NF_checkExactType = 0,
436 NF_checkGenericType = 1,
437 NF_getCallSiteTarget = 2,
438 NF_checkCustomized = 3,
439 NF_LIMIT = 4;
440
441 // Local constant functions:
442 private static final @Stable NamedFunction[] FUNCTIONS = new NamedFunction[NF_LIMIT];
443
444 private static NamedFunction makeConstantFunction(int idx) {
445 try {
446 switch (idx) {
447 case NF_checkExactType:
448 return new NamedFunction(Invokers.class
449 .getDeclaredMethod("checkExactType", Object.class, Object.class));
450 case NF_checkGenericType:
451 return new NamedFunction(Invokers.class
452 .getDeclaredMethod("checkGenericType", Object.class, Object.class));
453 case NF_getCallSiteTarget:
454 return new NamedFunction(Invokers.class
455 .getDeclaredMethod("getCallSiteTarget", Object.class));
456 case NF_checkCustomized:
457 return new NamedFunction(Invokers.class
458 .getDeclaredMethod("checkCustomized", Object.class));
459 }
460 } catch (ReflectiveOperationException ex) {
461 throw newInternalError(ex);
462 }
463 throw newInternalError("Unknown function index: " + idx);
464 }
465
466 private static class Lazy {
467 private static final MethodHandle MH_asSpreader;
468
469 static {
470 try {
471 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
472 MethodType.methodType(MethodHandle.class, Class.class, int.class));
473 } catch (ReflectiveOperationException ex) {
474 throw newInternalError(ex);
475 }
476 }
477 }
478 }
|