418 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
419 if (arg == null) arg = Object.class;
420 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
421 }
422 target = target.asType(targetType);
423
424 MethodType srcType = targetType
425 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
426 // Now build a LambdaForm.
427 MethodType lambdaType = srcType.invokerType();
428 Name[] names = arguments(spreadArgCount + 2, lambdaType);
429 int nameCursor = lambdaType.parameterCount();
430 int[] indexes = new int[targetType.parameterCount()];
431
432 for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
433 Class<?> src = lambdaType.parameterType(i);
434 if (i == spreadArgPos) {
435 // Spread the array.
436 MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
437 Name array = names[argIndex];
438 names[nameCursor++] = new Name(NF_checkSpreadArgument, array, spreadArgCount);
439 for (int j = 0; j < spreadArgCount; i++, j++) {
440 indexes[i] = nameCursor;
441 names[nameCursor++] = new Name(aload, array, j);
442 }
443 } else if (i < indexes.length) {
444 indexes[i] = argIndex;
445 }
446 }
447 assert(nameCursor == names.length-1); // leave room for the final call
448
449 // Build argument array for the call.
450 Name[] targetArgs = new Name[targetType.parameterCount()];
451 for (int i = 0; i < targetType.parameterCount(); i++) {
452 int idx = indexes[i];
453 targetArgs[i] = names[idx];
454 }
455 names[names.length - 1] = new Name(target, (Object[]) targetArgs);
456
457 LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
458 return SimpleMethodHandle.make(srcType, form);
463 // but the actual exception raised by an arity mismatch should be WMTE
464 final boolean RAISE_RANDOM_EXCEPTIONS = true; // FIXME: delete in JSR 292 M1
465 if (av == null) {
466 if (n == 0) return;
467 int len;
468 if (RAISE_RANDOM_EXCEPTIONS)
469 len = ((Object[])av).length; // throw NPE; but delete this after tests are fixed
470 } else if (av instanceof Object[]) {
471 int len = ((Object[])av).length;
472 if (len == n) return;
473 } else {
474 int len = java.lang.reflect.Array.getLength(av);
475 if (len == n) return;
476 }
477 // fall through to error:
478 if (RAISE_RANDOM_EXCEPTIONS)
479 throw newIllegalArgumentException("Array is not of length "+n);
480 throw new WrongMethodTypeException("Array is not of length "+n);
481 }
482
483 private static final NamedFunction NF_checkSpreadArgument;
484 static {
485 try {
486 NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
487 .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
488 NF_checkSpreadArgument.resolve();
489 } catch (ReflectiveOperationException ex) {
490 throw newInternalError(ex);
491 }
492 }
493
494 /** Factory method: Collect or filter selected argument(s). */
495 static MethodHandle makeCollectArguments(MethodHandle target,
496 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
497 MethodType targetType = target.type(); // (a..., c, [b...])=>r
498 MethodType collectorType = collector.type(); // (b...)=>c
499 int collectArgCount = collectorType.parameterCount();
500 Class<?> collectValType = collectorType.returnType();
501 int collectValCount = (collectValType == void.class ? 0 : 1);
502 MethodType srcType = targetType // (a..., [b...])=>r
503 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
504 if (!retainOriginalArgs) { // (a..., b...)=>r
505 srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
506 }
507 // in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ]
508 // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
509 // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
510
511 // Now build a LambdaForm.
512 MethodType lambdaType = srcType.invokerType();
|
418 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
419 if (arg == null) arg = Object.class;
420 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
421 }
422 target = target.asType(targetType);
423
424 MethodType srcType = targetType
425 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
426 // Now build a LambdaForm.
427 MethodType lambdaType = srcType.invokerType();
428 Name[] names = arguments(spreadArgCount + 2, lambdaType);
429 int nameCursor = lambdaType.parameterCount();
430 int[] indexes = new int[targetType.parameterCount()];
431
432 for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
433 Class<?> src = lambdaType.parameterType(i);
434 if (i == spreadArgPos) {
435 // Spread the array.
436 MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
437 Name array = names[argIndex];
438 names[nameCursor++] = new Name(NF.checkSpreadArgument, array, spreadArgCount);
439 for (int j = 0; j < spreadArgCount; i++, j++) {
440 indexes[i] = nameCursor;
441 names[nameCursor++] = new Name(aload, array, j);
442 }
443 } else if (i < indexes.length) {
444 indexes[i] = argIndex;
445 }
446 }
447 assert(nameCursor == names.length-1); // leave room for the final call
448
449 // Build argument array for the call.
450 Name[] targetArgs = new Name[targetType.parameterCount()];
451 for (int i = 0; i < targetType.parameterCount(); i++) {
452 int idx = indexes[i];
453 targetArgs[i] = names[idx];
454 }
455 names[names.length - 1] = new Name(target, (Object[]) targetArgs);
456
457 LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
458 return SimpleMethodHandle.make(srcType, form);
463 // but the actual exception raised by an arity mismatch should be WMTE
464 final boolean RAISE_RANDOM_EXCEPTIONS = true; // FIXME: delete in JSR 292 M1
465 if (av == null) {
466 if (n == 0) return;
467 int len;
468 if (RAISE_RANDOM_EXCEPTIONS)
469 len = ((Object[])av).length; // throw NPE; but delete this after tests are fixed
470 } else if (av instanceof Object[]) {
471 int len = ((Object[])av).length;
472 if (len == n) return;
473 } else {
474 int len = java.lang.reflect.Array.getLength(av);
475 if (len == n) return;
476 }
477 // fall through to error:
478 if (RAISE_RANDOM_EXCEPTIONS)
479 throw newIllegalArgumentException("Array is not of length "+n);
480 throw new WrongMethodTypeException("Array is not of length "+n);
481 }
482
483 /**
484 * Pre-initialized NamedFunctions for bootstrapping purposes.
485 * Factored in an inner class to delay initialization until first usage.
486 */
487 private static class NF {
488 static final NamedFunction checkSpreadArgument;
489 static {
490 try {
491 checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
492 .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
493 checkSpreadArgument.resolve();
494 } catch (ReflectiveOperationException ex) {
495 throw newInternalError(ex);
496 }
497 }
498 }
499
500 /** Factory method: Collect or filter selected argument(s). */
501 static MethodHandle makeCollectArguments(MethodHandle target,
502 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
503 MethodType targetType = target.type(); // (a..., c, [b...])=>r
504 MethodType collectorType = collector.type(); // (b...)=>c
505 int collectArgCount = collectorType.parameterCount();
506 Class<?> collectValType = collectorType.returnType();
507 int collectValCount = (collectValType == void.class ? 0 : 1);
508 MethodType srcType = targetType // (a..., [b...])=>r
509 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
510 if (!retainOriginalArgs) { // (a..., b...)=>r
511 srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
512 }
513 // in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ]
514 // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
515 // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
516
517 // Now build a LambdaForm.
518 MethodType lambdaType = srcType.invokerType();
|