src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 9088 : 8027827: Improve performance of catchException combinator
Reviewed-by: ?
rev 9089 : [mq]: 8027827.catchException.custom.webrev01
rev 9090 : [mq]: 8027827.catchException.disable_caching
rev 9091 : [mq]: 8027827.catchException.ver03
rev 9092 : [mq]: 8027827.caching


  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.util.ArrayList;
  31 import java.util.Arrays;
  32 import java.util.HashMap;
  33 import sun.invoke.empty.Empty;
  34 import sun.invoke.util.ValueConversions;
  35 import sun.invoke.util.VerifyType;
  36 import sun.invoke.util.Wrapper;
  37 import sun.reflect.CallerSensitive;
  38 import sun.reflect.Reflection;
  39 import static java.lang.invoke.LambdaForm.*;
  40 import static java.lang.invoke.MethodHandleStatics.*;
  41 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  42 
  43 /**
  44  * Trusted implementation code for MethodHandle.
  45  * @author jrose
  46  */
  47 /*non-public*/ abstract class MethodHandleImpl {
  48     /// Factory methods to create method handles:
  49 
  50     static void initStatics() {


 531         inputArgPos  += chunk;
 532         targetArgPos += chunk;
 533         if (collectValType != void.class) {
 534             targetArgs[targetArgPos++] = names[collectNamePos];
 535         }
 536         chunk = collectArgCount;
 537         if (retainOriginalArgs) {
 538             System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 539             targetArgPos += chunk;   // optionally pass on the collected chunk
 540         }
 541         inputArgPos += chunk;
 542         chunk = targetArgs.length - targetArgPos;  // all the rest
 543         System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 544         assert(inputArgPos + chunk == collectNamePos);  // use of rest of input args also
 545         names[targetNamePos] = new Name(target, (Object[]) targetArgs);
 546 
 547         LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
 548         return SimpleMethodHandle.make(srcType, form);
 549     }
 550 

 551     static
 552     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
 553         return testResult ? target : fallback;
 554     }
 555 
 556     static MethodHandle SELECT_ALTERNATIVE;
 557     static MethodHandle selectAlternative() {
 558         if (SELECT_ALTERNATIVE != null)  return SELECT_ALTERNATIVE;
 559         try {
 560             SELECT_ALTERNATIVE
 561             = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
 562                     MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
 563         } catch (ReflectiveOperationException ex) {
 564             throw new RuntimeException(ex);
 565         }
 566         return SELECT_ALTERNATIVE;
 567     }
 568 
 569     static
 570     MethodHandle makeGuardWithTest(MethodHandle test,
 571                                    MethodHandle target,
 572                                    MethodHandle fallback) {
 573         MethodType basicType = target.type().basicType();
 574         MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
 575         int arity = basicType.parameterCount();
 576         int extraNames = 3;
 577         MethodType lambdaType = basicType.invokerType();
 578         Name[] names = arguments(extraNames, lambdaType);
 579 
 580         Object[] testArgs   = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
 581         Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
 582 
 583         // call test
 584         names[arity + 1] = new Name(test, testArgs);
 585 
 586         // call selectAlternative
 587         Object[] selectArgs = { names[arity + 1], target, fallback };
 588         names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
 589         targetArgs[0] = names[arity + 2];
 590 
 591         // call target or fallback
 592         names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
 593 
 594         LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
 595         return SimpleMethodHandle.make(target.type(), form);
 596     }
 597 
 598     private static class GuardWithCatch {
 599         private final MethodHandle target;
 600         private final Class<? extends Throwable> exType;
 601         private final MethodHandle catcher;
 602         // FIXME: Build the control flow out of foldArguments.
 603         GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
 604             this.target = target;
 605             this.exType = exType;
 606             this.catcher = catcher;
 607         }
 608         @LambdaForm.Hidden
 609         private Object invoke_V(Object... av) throws Throwable {
 610             try {
 611                 return target.invokeExact(av);
 612             } catch (Throwable t) {
 613                 if (!exType.isInstance(t))  throw t;
 614                 return catcher.invokeExact(t, av);
 615             }
 616         }
 617         @LambdaForm.Hidden
 618         private Object invoke_L0() throws Throwable {
 619             try {
 620                 return target.invokeExact();
 621             } catch (Throwable t) {
 622                 if (!exType.isInstance(t))  throw t;
 623                 return catcher.invokeExact(t);
 624             }
 625         }
 626         @LambdaForm.Hidden
 627         private Object invoke_L1(Object a0) throws Throwable {
 628             try {
 629                 return target.invokeExact(a0);
 630             } catch (Throwable t) {
 631                 if (!exType.isInstance(t))  throw t;
 632                 return catcher.invokeExact(t, a0);
 633             }
 634         }
 635         @LambdaForm.Hidden
 636         private Object invoke_L2(Object a0, Object a1) throws Throwable {
 637             try {
 638                 return target.invokeExact(a0, a1);
 639             } catch (Throwable t) {
 640                 if (!exType.isInstance(t))  throw t;
 641                 return catcher.invokeExact(t, a0, a1);
 642             }
 643         }
 644         @LambdaForm.Hidden
 645         private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
 646             try {
 647                 return target.invokeExact(a0, a1, a2);
 648             } catch (Throwable t) {
 649                 if (!exType.isInstance(t))  throw t;
 650                 return catcher.invokeExact(t, a0, a1, a2);
 651             }
 652         }
 653         @LambdaForm.Hidden
 654         private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
 655             try {
 656                 return target.invokeExact(a0, a1, a2, a3);
 657             } catch (Throwable t) {
 658                 if (!exType.isInstance(t))  throw t;
 659                 return catcher.invokeExact(t, a0, a1, a2, a3);
 660             }
 661         }
 662         @LambdaForm.Hidden
 663         private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
 664             try {
 665                 return target.invokeExact(a0, a1, a2, a3, a4);
 666             } catch (Throwable t) {
 667                 if (!exType.isInstance(t))  throw t;
 668                 return catcher.invokeExact(t, a0, a1, a2, a3, a4);
 669             }
 670         }
 671         @LambdaForm.Hidden
 672         private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
 673             try {
 674                 return target.invokeExact(a0, a1, a2, a3, a4, a5);
 675             } catch (Throwable t) {
 676                 if (!exType.isInstance(t))  throw t;
 677                 return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
 678             }



















 679         }
 680         @LambdaForm.Hidden
 681         private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {

 682             try {
 683                 return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
 684             } catch (Throwable t) {
 685                 if (!exType.isInstance(t))  throw t;
 686                 return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);

 687             }


 688         }





 689         @LambdaForm.Hidden
 690         private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {











 691             try {
 692                 return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
 693             } catch (Throwable t) {
 694                 if (!exType.isInstance(t))  throw t;
 695                 return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
 696             }
 697         }
 698         static MethodHandle[] makeInvokes() {
 699             ArrayList<MethodHandle> invokes = new ArrayList<>();
 700             MethodHandles.Lookup lookup = IMPL_LOOKUP;
 701             for (;;) {
 702                 int nargs = invokes.size();
 703                 String name = "invoke_L"+nargs;
 704                 MethodHandle invoke = null;
 705                 try {
 706                     invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
 707                 } catch (ReflectiveOperationException ex) {
 708                 }
 709                 if (invoke == null)  break;
 710                 invokes.add(invoke);
 711             }
 712             assert(invokes.size() == 9);  // current number of methods
 713             return invokes.toArray(new MethodHandle[0]);
 714         };
 715         static final MethodHandle[] INVOKES = makeInvokes();
 716         // For testing use this:
 717         //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
 718         static final MethodHandle VARARGS_INVOKE;
 719         static {
 720             try {
 721                 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));


 722             } catch (ReflectiveOperationException ex) {
 723                 throw uncaughtException(ex);
 724             }
 725         }
 726     }
 727 
 728 
 729     static
 730     MethodHandle makeGuardWithCatch(MethodHandle target,
 731                                     Class<? extends Throwable> exType,
 732                                     MethodHandle catcher) {
 733         MethodType type = target.type();
 734         MethodType ctype = catcher.type();
 735         int nargs = type.parameterCount();
 736         if (nargs < GuardWithCatch.INVOKES.length) {
 737             MethodType gtype = type.generic();
 738             MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
 739             // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
 740             MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
 741             MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
 742             GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
 743             if (gtarget == null || gcatcher == null)  throw new InternalError();
 744             MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
 745             return makePairwiseConvert(ginvoker, type, 2);
 746         } else {
 747             target = target.asType(type.changeReturnType(Object.class));
 748             MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
 749             MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
 750                                           .changeReturnType(Object.class);
 751             catcher = catcher.asType(catcherType);
 752             MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
 753             GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
 754             if (gtarget == null || gcatcher == null)  throw new InternalError();
 755             MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
 756             MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
 757             return makePairwiseConvert(gcollect, type, 2);
 758         }
 759     }
 760 
 761     static
 762     MethodHandle throwException(MethodType type) {
 763         assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
 764         int arity = type.parameterCount();
 765         if (arity > 1) {
 766             return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
 767         }
 768         return makePairwiseConvert(throwException(), type, 2);
 769     }
 770 
 771     static MethodHandle THROW_EXCEPTION;
 772     static MethodHandle throwException() {
 773         MethodHandle mh = THROW_EXCEPTION;
 774         if (mh != null)  return mh;
 775         try {
 776             mh
 777             = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
 778                     MethodType.methodType(Empty.class, Throwable.class));
 779         } catch (ReflectiveOperationException ex) {
 780             throw new RuntimeException(ex);
 781         }
 782         THROW_EXCEPTION = mh;
 783         return mh;
 784     }
 785     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
 786 
 787     static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
 788     static MethodHandle fakeMethodHandleInvoke(MemberName method) {
 789         int idx;
 790         assert(method.isMethodHandleInvoke());
 791         switch (method.getName()) {
 792         case "invoke":       idx = 0; break;
 793         case "invokeExact":  idx = 1; break;
 794         default:             throw new InternalError(method.getName());
 795         }
 796         MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
 797         if (mh != null)  return mh;
 798         MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
 799                                                 MethodHandle.class, Object[].class);
 800         mh = throwException(type);




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import java.security.AccessController;
  29 import java.security.PrivilegedAction;

  30 import java.util.Arrays;
  31 import java.util.HashMap;
  32 import sun.invoke.empty.Empty;
  33 import sun.invoke.util.ValueConversions;
  34 import sun.invoke.util.VerifyType;
  35 import sun.invoke.util.Wrapper;
  36 import sun.reflect.CallerSensitive;
  37 import sun.reflect.Reflection;
  38 import static java.lang.invoke.LambdaForm.*;
  39 import static java.lang.invoke.MethodHandleStatics.*;
  40 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  41 
  42 /**
  43  * Trusted implementation code for MethodHandle.
  44  * @author jrose
  45  */
  46 /*non-public*/ abstract class MethodHandleImpl {
  47     /// Factory methods to create method handles:
  48 
  49     static void initStatics() {


 530         inputArgPos  += chunk;
 531         targetArgPos += chunk;
 532         if (collectValType != void.class) {
 533             targetArgs[targetArgPos++] = names[collectNamePos];
 534         }
 535         chunk = collectArgCount;
 536         if (retainOriginalArgs) {
 537             System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 538             targetArgPos += chunk;   // optionally pass on the collected chunk
 539         }
 540         inputArgPos += chunk;
 541         chunk = targetArgs.length - targetArgPos;  // all the rest
 542         System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 543         assert(inputArgPos + chunk == collectNamePos);  // use of rest of input args also
 544         names[targetNamePos] = new Name(target, (Object[]) targetArgs);
 545 
 546         LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
 547         return SimpleMethodHandle.make(srcType, form);
 548     }
 549 
 550     @LambdaForm.Hidden
 551     static
 552     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
 553         return testResult ? target : fallback;
 554     }
 555 
 556     static MethodHandle SELECT_ALTERNATIVE;
 557     static MethodHandle selectAlternative() {
 558         if (SELECT_ALTERNATIVE != null)  return SELECT_ALTERNATIVE;
 559         try {
 560             SELECT_ALTERNATIVE
 561             = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
 562                     MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
 563         } catch (ReflectiveOperationException ex) {
 564             throw uncaughtException(ex);
 565         }
 566         return SELECT_ALTERNATIVE;
 567     }
 568 
 569     static
 570     MethodHandle makeGuardWithTest(MethodHandle test,
 571                                    MethodHandle target,
 572                                    MethodHandle fallback) {
 573         MethodType basicType = target.type().basicType();
 574         MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
 575         int arity = basicType.parameterCount();
 576         int extraNames = 3;
 577         MethodType lambdaType = basicType.invokerType();
 578         Name[] names = arguments(extraNames, lambdaType);
 579 
 580         Object[] testArgs   = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
 581         Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
 582 
 583         // call test
 584         names[arity + 1] = new Name(test, testArgs);
 585 
 586         // call selectAlternative
 587         Object[] selectArgs = { names[arity + 1], target, fallback };
 588         names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
 589         targetArgs[0] = names[arity + 2];
 590 
 591         // call target or fallback
 592         names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
 593 
 594         LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
 595         return SimpleMethodHandle.make(target.type(), form);
 596     }
 597 
 598     /**
 599      * The LambaForm shape for catchException combinator is the following:
 600      * <blockquote><pre>{@code
 601      *  guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
 602      *    t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
 603      *    t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
 604      *    t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
 605      *    t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
 606      *    t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
 607      *    t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
 608      *    t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
 609      *   t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
 610      * }</pre></blockquote>
 611      *
 612      * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
 613      * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
 614      * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
 615      *
 616      * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
 617      * among catchException combinators with the same basic type.
 618      */
 619     private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
 620         MethodType lambdaType = basicType.invokerType();
 621 
 622         LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
 623         if (lform != null) {
 624             return lform;
 625         }
 626 
 627         final int THIS_MH      = 0;  // the BMH_LLLLL
 628         final int ARG_BASE     = 1;  // start of incoming arguments
 629         final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
 630 
 631         int nameCursor = ARG_LIMIT;
 632         final int GET_TARGET       = nameCursor++;
 633         final int GET_CLASS        = nameCursor++;
 634         final int GET_CATCHER      = nameCursor++;
 635         final int GET_COLLECT_ARGS = nameCursor++;
 636         final int GET_UNBOX_RESULT = nameCursor++;
 637         final int BOXED_ARGS       = nameCursor++;
 638         final int TRY_CATCH        = nameCursor++;
 639         final int UNBOX_RESULT     = nameCursor++;
 640 
 641         Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 642 
 643         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 644         names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
 645         names[GET_CLASS]        = new Name(data.getterFunction(1), names[THIS_MH]);
 646         names[GET_CATCHER]      = new Name(data.getterFunction(2), names[THIS_MH]);
 647         names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
 648         names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
 649 
 650         // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
 651         MethodType collectArgsType = basicType.changeReturnType(Object.class);
 652         MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
 653         Object[] args = new Object[invokeBasic.type().parameterCount()];
 654         args[0] = names[GET_COLLECT_ARGS];
 655         System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
 656         names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
 657 
 658         // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
 659         Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
 660         names[TRY_CATCH] = new Name(MethodHandleImpl.guardWithCatch(), gwcArgs);
 661 
 662         // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
 663         MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
 664         Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
 665         names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
 666 
 667         lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
 668 
 669         basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
 670         return lform;







 671     }
 672 
 673     static
 674     MethodHandle makeGuardWithCatch(MethodHandle target,
 675                                     Class<? extends Throwable> exType,
 676                                     MethodHandle catcher) {
 677         MethodType type = target.type();
 678         LambdaForm form = makeGuardWithCatchForm(type.basicType());
 679 
 680         // Prepare auxiliary method handles used during LambdaForm interpreation.
 681         // Box arguments and wrap them into Object[]: ValueConversions.array().
 682         MethodType varargsType = type.changeReturnType(Object[].class);
 683         MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
 684                                                     .asType(varargsType);
 685         // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
 686         MethodHandle unboxResult;
 687         if (type.returnType().isPrimitive()) {
 688             unboxResult = ValueConversions.unbox(type.returnType());
 689         } else {
 690             unboxResult = ValueConversions.identity();
 691         }
 692 
 693         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 694         BoundMethodHandle mh;
 695         try {
 696             mh = (BoundMethodHandle)
 697                     data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
 698                             (Object) collectArgs, (Object) unboxResult);
 699         } catch (Throwable ex) {
 700             throw uncaughtException(ex);
 701         }
 702         assert(mh.type() == type);
 703         return mh;
 704     }
 705 
 706     /**
 707      * Intrinsified during LambdaForm compilation
 708      * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
 709      */
 710     @LambdaForm.Hidden
 711     static Object guardWithCatch(MethodHandle target, Class exType, MethodHandle catcher,
 712                                   Object... av) throws Throwable {
 713         int nargs = target.type().parameterCount();
 714 
 715         MethodHandle ctarget = makePairwiseConvert(target, target.type().generic(), 1);
 716         MethodHandle gtarget = makeSpreadArguments(ctarget, Object[].class, 0, nargs);
 717 
 718         MethodType ccatcherType = catcher.type().generic()
 719                                          .changeParameterType(0, Throwable.class);
 720         MethodHandle ccatcher = makePairwiseConvert(catcher, ccatcherType, 1);
 721         MethodHandle gcatcher = makeSpreadArguments(ccatcher, Object[].class, 1, nargs);
 722 
 723         try {
 724             return gtarget.invokeExact(av);
 725         } catch (Throwable t) {
 726             if (!exType.isInstance(t)) throw t;
 727             return gcatcher.invokeExact(t, av);
 728         }
 729     }
 730 
 731     private static MethodHandle GUARD_WITH_CATCH;
 732     static MethodHandle guardWithCatch() {
 733         if (GUARD_WITH_CATCH != null) {
 734             return GUARD_WITH_CATCH;








 735         }








 736         try {
 737             GUARD_WITH_CATCH
 738                     = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "guardWithCatch",
 739                     MethodType.methodType(Object.class, MethodHandle.class, Class.class, MethodHandle.class, Object[].class));
 740         } catch (ReflectiveOperationException ex) {
 741             throw uncaughtException(ex);
 742         }
 743         return GUARD_WITH_CATCH;

































 744     }
 745 
 746     static
 747     MethodHandle throwException(MethodType type) {
 748         assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
 749         int arity = type.parameterCount();
 750         if (arity > 1) {
 751             return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
 752         }
 753         return makePairwiseConvert(throwException(), type, 2);
 754     }
 755 
 756     static MethodHandle THROW_EXCEPTION;
 757     static MethodHandle throwException() {
 758         MethodHandle mh = THROW_EXCEPTION;
 759         if (mh != null)  return mh;
 760         try {
 761             mh
 762             = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
 763                     MethodType.methodType(Empty.class, Throwable.class));
 764         } catch (ReflectiveOperationException ex) {
 765             throw uncaughtException(ex);
 766         }
 767         THROW_EXCEPTION = mh;
 768         return mh;
 769     }
 770     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
 771 
 772     static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
 773     static MethodHandle fakeMethodHandleInvoke(MemberName method) {
 774         int idx;
 775         assert(method.isMethodHandleInvoke());
 776         switch (method.getName()) {
 777         case "invoke":       idx = 0; break;
 778         case "invokeExact":  idx = 1; break;
 779         default:             throw new InternalError(method.getName());
 780         }
 781         MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
 782         if (mh != null)  return mh;
 783         MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
 784                                                 MethodHandle.class, Object[].class);
 785         mh = throwException(type);


src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File