427 BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos));
428 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
429 Name newBaseAddress;
430 NamedFunction getter = newData.getterFunction(oldData.fieldCount());
431
432 if (pos != 0) {
433 // The newly created LF will run with a different BMH.
434 // Switch over any pre-existing BMH field references to the new BMH class.
435 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
436 newBaseAddress = oldBaseAddress.withConstraint(newData);
437 buf.renameParameter(0, newBaseAddress);
438 buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
439 } else {
440 // cannot bind the MH arg itself, unless oldData is empty
441 assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
442 newBaseAddress = new Name(L_TYPE).withConstraint(newData);
443 buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
444 buf.insertParameter(0, newBaseAddress);
445 }
446
447 buf.endEdit();
448 form = buf.lambdaForm();
449 return putInCache(key, form);
450 }
451 }
|
427 BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos));
428 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
429 Name newBaseAddress;
430 NamedFunction getter = newData.getterFunction(oldData.fieldCount());
431
432 if (pos != 0) {
433 // The newly created LF will run with a different BMH.
434 // Switch over any pre-existing BMH field references to the new BMH class.
435 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
436 newBaseAddress = oldBaseAddress.withConstraint(newData);
437 buf.renameParameter(0, newBaseAddress);
438 buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress));
439 } else {
440 // cannot bind the MH arg itself, unless oldData is empty
441 assert(oldData == BoundMethodHandle.SpeciesData.EMPTY);
442 newBaseAddress = new Name(L_TYPE).withConstraint(newData);
443 buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress));
444 buf.insertParameter(0, newBaseAddress);
445 }
446
447 form = buf.endEdit();
448 return putInCache(key, form);
449 }
450
451 LambdaForm addArgumentForm(int pos, BasicType type) {
452 Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal());
453 LambdaForm form = getInCache(key);
454 if (form != null) {
455 assert(form.arity == lambdaForm.arity+1);
456 assert(form.parameterType(pos) == type);
457 return form;
458 }
459 LambdaFormBuffer buf = buffer();
460 buf.startEdit();
461
462 buf.insertParameter(pos, new Name(type));
463
464 form = buf.endEdit();
465 return putInCache(key, form);
466 }
467
468 LambdaForm dupArgumentForm(int srcPos, int dstPos) {
469 Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos);
470 LambdaForm form = getInCache(key);
471 if (form != null) {
472 assert(form.arity == lambdaForm.arity-1);
473 return form;
474 }
475 LambdaFormBuffer buf = buffer();
476 buf.startEdit();
477
478 assert(lambdaForm.parameter(srcPos).constraint == null);
479 assert(lambdaForm.parameter(dstPos).constraint == null);
480 buf.replaceParameterByCopy(dstPos, srcPos);
481
482 form = buf.endEdit();
483 return putInCache(key, form);
484 }
485
486 LambdaForm spreadArgumentsForm(int pos, Class<?> arrayType, int arrayLength) {
487 Class<?> elementType = arrayType.getComponentType();
488 Class<?> erasedArrayType = arrayType;
489 if (!elementType.isPrimitive())
490 erasedArrayType = Object[].class;
491 BasicType bt = basicType(elementType);
492 int elementTypeKey = bt.ordinal();
493 if (bt.basicTypeClass() != elementType) {
494 if (elementType.isPrimitive()) {
495 elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
496 }
497 }
498 Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength);
499 LambdaForm form = getInCache(key);
500 if (form != null) {
501 assert(form.arity == lambdaForm.arity - arrayLength + 1);
502 return form;
503 }
504 LambdaFormBuffer buf = buffer();
505 buf.startEdit();
506
507 assert(pos <= MethodType.MAX_JVM_ARITY);
508 assert(pos + arrayLength <= lambdaForm.arity);
509 assert(pos > 0); // cannot spread the MH arg itself
510
511 Name spreadParam = new Name(L_TYPE);
512 Name checkSpread = new Name(MethodHandleImpl.Lazy.NF_checkSpreadArgument, spreadParam, arrayLength);
513
514 // insert the new expressions
515 int exprPos = lambdaForm.arity();
516 buf.insertExpression(exprPos++, checkSpread);
517 // adjust the arguments
518 MethodHandle aload = MethodHandles.arrayElementGetter(erasedArrayType);
519 for (int i = 0; i < arrayLength; i++) {
520 Name loadArgument = new Name(aload, spreadParam, i);
521 buf.insertExpression(exprPos + i, loadArgument);
522 buf.replaceParameterByCopy(pos + i, exprPos + i);
523 }
524 buf.insertParameter(pos, spreadParam);
525
526 form = buf.endEdit();
527 return putInCache(key, form);
528 }
529
530 LambdaForm collectArgumentsForm(int pos, MethodType collectorType) {
531 int collectorArity = collectorType.parameterCount();
532 boolean dropResult = (collectorType.returnType() == void.class);
533 if (collectorArity == 1 && !dropResult) {
534 return filterArgumentForm(pos, basicType(collectorType.parameterType(0)));
535 }
536 BasicType[] newTypes = BasicType.basicTypes(collectorType.parameterList());
537 Transform.Kind kind = (dropResult
538 ? Transform.Kind.COLLECT_ARGS_TO_VOID
539 : Transform.Kind.COLLECT_ARGS);
540 if (dropResult && collectorArity == 0) pos = 1; // pure side effect
541 Transform key = Transform.of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes));
542 LambdaForm form = getInCache(key);
543 if (form != null) {
544 assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity);
545 return form;
546 }
547 form = makeArgumentCombinationForm(pos, collectorType, false, dropResult);
548 return putInCache(key, form);
549 }
550
551 LambdaForm collectArgumentArrayForm(int pos, MethodHandle arrayCollector) {
552 MethodType collectorType = arrayCollector.type();
553 int collectorArity = collectorType.parameterCount();
554 assert(arrayCollector.intrinsicName() == Intrinsic.NEW_ARRAY);
555 Class<?> arrayType = collectorType.returnType();
556 Class<?> elementType = arrayType.getComponentType();
557 BasicType argType = basicType(elementType);
558 int argTypeKey = argType.ordinal();
559 if (argType.basicTypeClass() != elementType) {
560 // return null if it requires more metadata (like String[].class)
561 if (!elementType.isPrimitive())
562 return null;
563 argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal();
564 }
565 assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType)));
566 Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY;
567 Transform key = Transform.of(kind, pos, collectorArity, argTypeKey);
568 LambdaForm form = getInCache(key);
569 if (form != null) {
570 assert(form.arity == lambdaForm.arity - 1 + collectorArity);
571 return form;
572 }
573 LambdaFormBuffer buf = buffer();
574 buf.startEdit();
575
576 assert(pos + 1 <= lambdaForm.arity);
577 assert(pos > 0); // cannot filter the MH arg itself
578
579 Name[] newParams = new Name[collectorArity];
580 for (int i = 0; i < collectorArity; i++) {
581 newParams[i] = new Name(pos + i, argType);
582 }
583 Name callCombiner = new Name(arrayCollector, (Object[]) /*...*/ newParams);
584
585 // insert the new expression
586 int exprPos = lambdaForm.arity();
587 buf.insertExpression(exprPos, callCombiner);
588
589 // insert new arguments
590 int argPos = pos + 1; // skip result parameter
591 for (Name newParam : newParams) {
592 buf.insertParameter(argPos++, newParam);
593 }
594 assert(buf.lastIndexOf(callCombiner) == exprPos+newParams.length);
595 buf.replaceParameterByCopy(pos, exprPos+newParams.length);
596
597 form = buf.endEdit();
598 return putInCache(key, form);
599 }
600
601 LambdaForm filterArgumentForm(int pos, BasicType newType) {
602 Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal());
603 LambdaForm form = getInCache(key);
604 if (form != null) {
605 assert(form.arity == lambdaForm.arity);
606 assert(form.parameterType(pos) == newType);
607 return form;
608 }
609
610 BasicType oldType = lambdaForm.parameterType(pos);
611 MethodType filterType = MethodType.methodType(oldType.basicTypeClass(),
612 newType.basicTypeClass());
613 form = makeArgumentCombinationForm(pos, filterType, false, false);
614 return putInCache(key, form);
615 }
616
617 private LambdaForm makeArgumentCombinationForm(int pos,
618 MethodType combinerType,
619 boolean keepArguments, boolean dropResult) {
620 LambdaFormBuffer buf = buffer();
621 buf.startEdit();
622 int combinerArity = combinerType.parameterCount();
623 int resultArity = (dropResult ? 0 : 1);
624
625 assert(pos <= MethodType.MAX_JVM_ARITY);
626 assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= lambdaForm.arity);
627 assert(pos > 0); // cannot filter the MH arg itself
628 assert(combinerType == combinerType.basicType());
629 assert(combinerType.returnType() != void.class || dropResult);
630
631 BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
632 BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE);
633
634 // The newly created LF will run with a different BMH.
635 // Switch over any pre-existing BMH field references to the new BMH class.
636 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
637 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
638 Name newBaseAddress = oldBaseAddress.withConstraint(newData);
639 buf.renameParameter(0, newBaseAddress);
640
641 Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress);
642 Object[] combinerArgs = new Object[1 + combinerArity];
643 combinerArgs[0] = getCombiner;
644 Name[] newParams;
645 if (keepArguments) {
646 newParams = new Name[0];
647 System.arraycopy(lambdaForm.names, pos + resultArity,
648 combinerArgs, 1, combinerArity);
649 } else {
650 newParams = new Name[combinerArity];
651 BasicType[] newTypes = basicTypes(combinerType.parameterList());
652 for (int i = 0; i < newTypes.length; i++) {
653 newParams[i] = new Name(pos + i, newTypes[i]);
654 }
655 System.arraycopy(newParams, 0,
656 combinerArgs, 1, combinerArity);
657 }
658 Name callCombiner = new Name(combinerType, combinerArgs);
659
660 // insert the two new expressions
661 int exprPos = lambdaForm.arity();
662 buf.insertExpression(exprPos+0, getCombiner);
663 buf.insertExpression(exprPos+1, callCombiner);
664
665 // insert new arguments, if needed
666 int argPos = pos + resultArity; // skip result parameter
667 for (Name newParam : newParams) {
668 buf.insertParameter(argPos++, newParam);
669 }
670 assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length);
671 if (!dropResult) {
672 buf.replaceParameterByCopy(pos, exprPos+1+newParams.length);
673 }
674
675 return buf.endEdit();
676 }
677
678 LambdaForm filterReturnForm(BasicType newType, boolean constantZero) {
679 Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN);
680 Transform key = Transform.of(kind, newType.ordinal());
681 LambdaForm form = getInCache(key);
682 if (form != null) {
683 assert(form.arity == lambdaForm.arity);
684 assert(form.returnType() == newType);
685 return form;
686 }
687 LambdaFormBuffer buf = buffer();
688 buf.startEdit();
689
690 int insPos = lambdaForm.names.length;
691 Name callFilter;
692 if (constantZero) {
693 // Synthesize a constant zero value for the given type.
694 if (newType == V_TYPE)
695 callFilter = null;
696 else
697 callFilter = new Name(constantZero(newType));
698 } else {
699 BoundMethodHandle.SpeciesData oldData = oldSpeciesData();
700 BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE);
701
702 // The newly created LF will run with a different BMH.
703 // Switch over any pre-existing BMH field references to the new BMH class.
704 Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values
705 buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress);
706 Name newBaseAddress = oldBaseAddress.withConstraint(newData);
707 buf.renameParameter(0, newBaseAddress);
708
709 Name getFilter = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress);
710 buf.insertExpression(insPos++, getFilter);
711 BasicType oldType = lambdaForm.returnType();
712 if (oldType == V_TYPE) {
713 MethodType filterType = MethodType.methodType(newType.basicTypeClass());
714 callFilter = new Name(filterType, getFilter);
715 } else {
716 MethodType filterType = MethodType.methodType(newType.basicTypeClass(), oldType.basicTypeClass());
717 callFilter = new Name(filterType, getFilter, lambdaForm.names[lambdaForm.result]);
718 }
719 }
720
721 if (callFilter != null)
722 buf.insertExpression(insPos++, callFilter);
723 buf.setResult(callFilter);
724
725 form = buf.endEdit();
726 return putInCache(key, form);
727 }
728
729 LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) {
730 int combinerArity = combinerType.parameterCount();
731 Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS);
732 Transform key = Transform.of(kind, foldPos, combinerArity);
733 LambdaForm form = getInCache(key);
734 if (form != null) {
735 assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0));
736 return form;
737 }
738 form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult);
739 return putInCache(key, form);
740 }
741
742 LambdaForm permuteArgumentsForm(int skip, int[] reorder) {
743 assert(skip == 1); // skip only the leading MH argument, names[0]
744 int length = lambdaForm.names.length;
745 int outArgs = reorder.length;
746 int inTypes = 0;
747 boolean nullPerm = true;
748 for (int i = 0; i < reorder.length; i++) {
749 int inArg = reorder[i];
750 if (inArg != i) nullPerm = false;
751 inTypes = Math.max(inTypes, inArg+1);
752 }
753 assert(skip + reorder.length == lambdaForm.arity);
754 if (nullPerm) return lambdaForm; // do not bother to cache
755 Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder);
756 LambdaForm form = getInCache(key);
757 if (form != null) {
758 assert(form.arity == skip+inTypes) : form;
759 return form;
760 }
761
762 BasicType[] types = new BasicType[inTypes];
763 for (int i = 0; i < outArgs; i++) {
764 int inArg = reorder[i];
765 types[inArg] = lambdaForm.names[skip + i].type;
766 }
767 assert (skip + outArgs == lambdaForm.arity);
768 assert (permutedTypesMatch(reorder, types, lambdaForm.names, skip));
769 int pos = 0;
770 while (pos < outArgs && reorder[pos] == pos) {
771 pos += 1;
772 }
773 Name[] names2 = new Name[length - outArgs + inTypes];
774 System.arraycopy(lambdaForm.names, 0, names2, 0, skip + pos);
775 int bodyLength = length - lambdaForm.arity;
776 System.arraycopy(lambdaForm.names, skip + outArgs, names2, skip + inTypes, bodyLength);
777 int arity2 = names2.length - bodyLength;
778 int result2 = lambdaForm.result;
779 if (result2 >= 0) {
780 if (result2 < skip + outArgs) {
781 result2 = reorder[result2 - skip];
782 } else {
783 result2 = result2 - outArgs + inTypes;
784 }
785 }
786 for (int j = pos; j < outArgs; j++) {
787 Name n = lambdaForm.names[skip + j];
788 int i = reorder[j];
789 Name n2 = names2[skip + i];
790 if (n2 == null) {
791 names2[skip + i] = n2 = new Name(types[i]);
792 } else {
793 assert (n2.type == types[i]);
794 }
795 for (int k = arity2; k < names2.length; k++) {
796 names2[k] = names2[k].replaceName(n, n2);
797 }
798 }
799 for (int i = skip + pos; i < arity2; i++) {
800 if (names2[i] == null) {
801 names2[i] = argument(i, types[i - skip]);
802 }
803 }
804 for (int j = lambdaForm.arity; j < lambdaForm.names.length; j++) {
805 int i = j - lambdaForm.arity + arity2;
806 Name n = lambdaForm.names[j];
807 Name n2 = names2[i];
808 if (n != n2) {
809 for (int k = i + 1; k < names2.length; k++) {
810 names2[k] = names2[k].replaceName(n, n2);
811 }
812 }
813 }
814
815 form = new LambdaForm(lambdaForm.debugName, arity2, names2, result2);
816 return putInCache(key, form);
817 }
818
819 static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) {
820 for (int i = 0; i < reorder.length; i++) {
821 assert (names[skip + i].isParam());
822 assert (names[skip + i].type == types[reorder[i]]);
823 }
824 return true;
825 }
826 }
|