230 case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
231 case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
232 case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
233 default: throw new InternalError();
234 }
235 LambdaForm lform;
236 if (isCached) {
237 lform = mtype.form().cachedLambdaForm(which);
238 if (lform != null) return lform;
239 }
240 // exactInvokerForm (Object,Object)Object
241 // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
242 final int THIS_MH = 0;
243 final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
244 final int ARG_BASE = CALL_MH + 1;
245 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
246 final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
247 int nameCursor = OUTARG_LIMIT;
248 final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
249 final int CHECK_TYPE = nameCursor++;
250 final int LINKER_CALL = nameCursor++;
251 MethodType invokerFormType = mtype.invokerType();
252 if (isLinker) {
253 if (!customized)
254 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
255 } else {
256 invokerFormType = invokerFormType.invokerType();
257 }
258 Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
259 assert(names.length == nameCursor)
260 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
261 if (MTYPE_ARG >= INARG_LIMIT) {
262 assert(names[MTYPE_ARG] == null);
263 BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
264 names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
265 NamedFunction getter = speciesData.getterFunction(0);
266 names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
267 // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
268 }
269
270 // Make the final call. If isGeneric, then prepend the result of type checking.
271 MethodType outCallType = mtype.basicType();
272 Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
273 Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
274 if (!isGeneric) {
275 names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
276 // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
277 } else {
278 names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
279 // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
280 outArgs[0] = names[CHECK_TYPE];
281 }
282 names[LINKER_CALL] = new Name(outCallType, outArgs);
283 lform = new LambdaForm(debugName, INARG_LIMIT, names);
284 if (isLinker)
285 lform.compileToBytecode(); // JVM needs a real methodOop
286 if (isCached)
287 lform = mtype.form().setCachedLambdaForm(which, lform);
288 return lform;
289 }
290
291 /*non-public*/ static
292 WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
293 // FIXME: merge with JVM logic for throwing WMTE
294 return new WrongMethodTypeException("expected "+expected+" but found "+actual);
295 }
296
297 /** Static definition of MethodHandle.invokeExact checking code. */
298 /*non-public*/ static
299 @ForceInline
300 void checkExactType(Object mhObj, Object expectedObj) {
301 MethodHandle mh = (MethodHandle) mhObj;
369 // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
370 final int PREPEND_MH = 0, PREPEND_COUNT = 1;
371 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
372 // prepend MH argument:
373 System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
374 outArgs[PREPEND_MH] = names[CALL_MH];
375 names[LINKER_CALL] = new Name(mtype, outArgs);
376 lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
377 lform.compileToBytecode(); // JVM needs a real methodOop
378 lform = mtype.form().setCachedLambdaForm(which, lform);
379 return lform;
380 }
381
382 /** Static definition of MethodHandle.invokeGeneric checking code. */
383 /*non-public*/ static
384 @ForceInline
385 Object getCallSiteTarget(Object site) {
386 return ((CallSite)site).getTarget();
387 }
388
389 // Local constant functions:
390 private static final NamedFunction
391 NF_checkExactType,
392 NF_checkGenericType,
393 NF_getCallSiteTarget;
394 static {
395 try {
396 NamedFunction nfs[] = {
397 NF_checkExactType = new NamedFunction(Invokers.class
398 .getDeclaredMethod("checkExactType", Object.class, Object.class)),
399 NF_checkGenericType = new NamedFunction(Invokers.class
400 .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
401 NF_getCallSiteTarget = new NamedFunction(Invokers.class
402 .getDeclaredMethod("getCallSiteTarget", Object.class))
403 };
404 for (NamedFunction nf : nfs) {
405 // Each nf must be statically invocable or we get tied up in our bootstraps.
406 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
407 nf.resolve();
408 }
409 } catch (ReflectiveOperationException ex) {
410 throw newInternalError(ex);
411 }
412 }
413
414 private static class Lazy {
415 private static final MethodHandle MH_asSpreader;
416
417 static {
418 try {
419 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
420 MethodType.methodType(MethodHandle.class, Class.class, int.class));
421 } catch (ReflectiveOperationException ex) {
422 throw newInternalError(ex);
|
230 case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
231 case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
232 case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
233 default: throw new InternalError();
234 }
235 LambdaForm lform;
236 if (isCached) {
237 lform = mtype.form().cachedLambdaForm(which);
238 if (lform != null) return lform;
239 }
240 // exactInvokerForm (Object,Object)Object
241 // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
242 final int THIS_MH = 0;
243 final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
244 final int ARG_BASE = CALL_MH + 1;
245 final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
246 final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
247 int nameCursor = OUTARG_LIMIT;
248 final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
249 final int CHECK_TYPE = nameCursor++;
250 final int CHECK_CUSTOM = (CUSTOMIZE_THRESHOLD >= 0) ? nameCursor++ : -1;
251 final int LINKER_CALL = nameCursor++;
252 MethodType invokerFormType = mtype.invokerType();
253 if (isLinker) {
254 if (!customized)
255 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
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, names[CALL_MH]);
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) {
305 MethodHandle mh = (MethodHandle) mhObj;
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
393 /*non-public*/ static
394 @ForceInline
395 void checkCustomized(MethodHandle mh) {
396 if (mh.form.customized == null) {
397 maybeCustomize(mh);
398 }
399 }
400
401 /*non-public*/ static
402 @DontInline
403 void maybeCustomize(MethodHandle mh) {
404 if (mh.customizationCount >= CUSTOMIZE_THRESHOLD) {
405 mh.customize();
406 } else {
407 mh.customizationCount += 1;
408 }
409 }
410
411 // Local constant functions:
412 private static final NamedFunction
413 NF_checkExactType,
414 NF_checkGenericType,
415 NF_getCallSiteTarget,
416 NF_checkCustomized;
417 static {
418 try {
419 NamedFunction nfs[] = {
420 NF_checkExactType = new NamedFunction(Invokers.class
421 .getDeclaredMethod("checkExactType", Object.class, Object.class)),
422 NF_checkGenericType = new NamedFunction(Invokers.class
423 .getDeclaredMethod("checkGenericType", Object.class, Object.class)),
424 NF_getCallSiteTarget = new NamedFunction(Invokers.class
425 .getDeclaredMethod("getCallSiteTarget", Object.class)),
426 NF_checkCustomized = new NamedFunction(Invokers.class
427 .getDeclaredMethod("checkCustomized", MethodHandle.class))
428 };
429 for (NamedFunction nf : nfs) {
430 // Each nf must be statically invocable or we get tied up in our bootstraps.
431 assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
432 nf.resolve();
433 }
434 } catch (ReflectiveOperationException ex) {
435 throw newInternalError(ex);
436 }
437 }
438
439 private static class Lazy {
440 private static final MethodHandle MH_asSpreader;
441
442 static {
443 try {
444 MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader",
445 MethodType.methodType(MethodHandle.class, Class.class, int.class));
446 } catch (ReflectiveOperationException ex) {
447 throw newInternalError(ex);
|