jdk/src/share/classes/sun/dyn/MethodHandleImpl.java
changeset 5722 4ada807383c8
parent 4537 7c3c7f8d5195
child 5723 a58a0eed34b0
equal deleted inserted replaced
5371:ff9031a745d9 5722:4ada807383c8
     1 /*
     1 /*
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 2008-2010 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
   125 
   125 
   126     static private Lookup IMPL_LOOKUP_INIT;
   126     static private Lookup IMPL_LOOKUP_INIT;
   127 
   127 
   128     public static void initLookup(Access token, Lookup lookup) {
   128     public static void initLookup(Access token, Lookup lookup) {
   129         Access.check(token);
   129         Access.check(token);
   130         if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != null)
   130         if (IMPL_LOOKUP_INIT != null)
   131             throw new InternalError();
   131             throw new InternalError();
   132         IMPL_LOOKUP_INIT = lookup;
   132         IMPL_LOOKUP_INIT = lookup;
   133     }
   133     }
   134 
   134 
   135     public static Lookup getLookup(Access token) {
   135     public static Lookup getLookup(Access token) {
   175     MethodHandle findMethod(Access token, MemberName method,
   175     MethodHandle findMethod(Access token, MemberName method,
   176             boolean doDispatch, Class<?> lookupClass) {
   176             boolean doDispatch, Class<?> lookupClass) {
   177         Access.check(token);  // only trusted calls
   177         Access.check(token);  // only trusted calls
   178         MethodType mtype = method.getMethodType();
   178         MethodType mtype = method.getMethodType();
   179         MethodType rtype = mtype;
   179         MethodType rtype = mtype;
   180         if (method.isStatic()) {
   180         if (!method.isStatic()) {
   181             doDispatch = false;
       
   182         } else {
       
   183             // adjust the advertised receiver type to be exactly the one requested
   181             // adjust the advertised receiver type to be exactly the one requested
   184             // (in the case of invokespecial, this will be the calling class)
   182             // (in the case of invokespecial, this will be the calling class)
   185             Class<?> recvType = method.getDeclaringClass();
   183             Class<?> recvType = method.getDeclaringClass();
   186             mtype = mtype.insertParameterTypes(0, recvType);
   184             mtype = mtype.insertParameterTypes(0, recvType);
   187             if (method.isConstructor())
       
   188                 doDispatch = true;
       
   189             // FIXME: JVM has trouble building MH.invoke sites for
   185             // FIXME: JVM has trouble building MH.invoke sites for
   190             // classes off the boot class path
   186             // classes off the boot class path
   191             rtype = mtype;
   187             rtype = mtype;
   192             if (recvType.getClassLoader() != null)
   188             if (recvType.getClassLoader() != null) {
   193                 rtype = rtype.changeParameterType(0, Object.class);
   189                 rtype = rtype.changeParameterType(0, Object.class);
       
   190             }
   194         }
   191         }
   195         DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
   192         DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
   196         if (!mh.isValid())
   193         if (!mh.isValid())
   197             throw newNoAccessException(method, lookupClass);
   194             throw newNoAccessException(method, lookupClass);
   198         MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
   195         if (rtype != mtype) {
   199         if (rmh == null)  throw new InternalError();
   196             MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
   200         return rmh;
   197             if (rmh == null)  throw new InternalError();
       
   198             return rmh;
       
   199         }
       
   200         assert(mh.type() == rtype);
       
   201         return mh;
       
   202     }
       
   203 
       
   204     public static
       
   205     MethodHandle makeAllocator(Access token, MethodHandle rawConstructor) {
       
   206         Access.check(token);
       
   207         MethodType rawConType = rawConstructor.type();
       
   208         // Wrap the raw (unsafe) constructor with the allocation of a suitable object.
       
   209         MethodHandle allocator
       
   210             = AllocateObject.make(token, rawConType.parameterType(0), rawConstructor);
       
   211         assert(allocator.type()
       
   212                .equals(rawConType.dropParameterTypes(0, 1).changeReturnType(rawConType.parameterType(0))));
       
   213         return allocator;
       
   214     }
       
   215 
       
   216     static final class AllocateObject<C> extends JavaMethodHandle {
       
   217         private static final Unsafe unsafe = Unsafe.getUnsafe();
       
   218 
       
   219         private final Class<C> allocateClass;
       
   220         private final MethodHandle rawConstructor;
       
   221 
       
   222         private AllocateObject(MethodHandle invoker,
       
   223                                Class<C> allocateClass, MethodHandle rawConstructor) {
       
   224             super(invoker);
       
   225             this.allocateClass = allocateClass;
       
   226             this.rawConstructor = rawConstructor;
       
   227         }
       
   228         static MethodHandle make(Access token,
       
   229                                  Class<?> allocateClass, MethodHandle rawConstructor) {
       
   230             Access.check(token);
       
   231             MethodType rawConType = rawConstructor.type();
       
   232             assert(rawConType.parameterType(0) == allocateClass);
       
   233             MethodType newType = rawConType.dropParameterTypes(0, 1).changeReturnType(allocateClass);
       
   234             int nargs = rawConType.parameterCount() - 1;
       
   235             if (nargs < INVOKES.length) {
       
   236                 MethodHandle invoke = INVOKES[nargs];
       
   237                 MethodType conType = CON_TYPES[nargs];
       
   238                 MethodHandle gcon = convertArguments(token, rawConstructor, conType, rawConType, null);
       
   239                 if (gcon == null)  return null;
       
   240                 MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
       
   241                 assert(galloc.type() == newType.generic());
       
   242                 return convertArguments(token, galloc, newType, galloc.type(), null);
       
   243             } else {
       
   244                 MethodHandle invoke = VARARGS_INVOKE;
       
   245                 MethodType conType = CON_TYPES[nargs];
       
   246                 MethodHandle gcon = spreadArguments(token, rawConstructor, conType, 1);
       
   247                 if (gcon == null)  return null;
       
   248                 MethodHandle galloc = new AllocateObject(invoke, allocateClass, gcon);
       
   249                 return collectArguments(token, galloc, newType, 1, null);
       
   250             }
       
   251         }
       
   252         @Override
       
   253         public String toString() {
       
   254             return allocateClass.getSimpleName();
       
   255         }
       
   256         @SuppressWarnings("unchecked")
       
   257         private C allocate() throws InstantiationException {
       
   258             return (C) unsafe.allocateInstance(allocateClass);
       
   259         }
       
   260         private C invoke_V(Object... av) throws Throwable {
       
   261             C obj = allocate();
       
   262             rawConstructor.<void>invokeExact((Object)obj, av);
       
   263             return obj;
       
   264         }
       
   265         private C invoke_L0() throws Throwable {
       
   266             C obj = allocate();
       
   267             rawConstructor.<void>invokeExact((Object)obj);
       
   268             return obj;
       
   269         }
       
   270         private C invoke_L1(Object a0) throws Throwable {
       
   271             C obj = allocate();
       
   272             rawConstructor.<void>invokeExact((Object)obj, a0);
       
   273             return obj;
       
   274         }
       
   275         private C invoke_L2(Object a0, Object a1) throws Throwable {
       
   276             C obj = allocate();
       
   277             rawConstructor.<void>invokeExact((Object)obj, a0, a1);
       
   278             return obj;
       
   279         }
       
   280         private C invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
       
   281             C obj = allocate();
       
   282             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2);
       
   283             return obj;
       
   284         }
       
   285         private C invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
       
   286             C obj = allocate();
       
   287             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3);
       
   288             return obj;
       
   289         }
       
   290         private C invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
       
   291             C obj = allocate();
       
   292             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4);
       
   293             return obj;
       
   294         }
       
   295         private C invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
       
   296             C obj = allocate();
       
   297             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5);
       
   298             return obj;
       
   299         }
       
   300         private C invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
       
   301             C obj = allocate();
       
   302             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6);
       
   303             return obj;
       
   304         }
       
   305         private C invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
       
   306             C obj = allocate();
       
   307             rawConstructor.<void>invokeExact((Object)obj, a0, a1, a2, a3, a4, a5, a6, a7);
       
   308             return obj;
       
   309         }
       
   310         static MethodHandle[] makeInvokes() {
       
   311             ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
       
   312             MethodHandles.Lookup lookup = IMPL_LOOKUP;
       
   313             for (;;) {
       
   314                 int nargs = invokes.size();
       
   315                 String name = "invoke_L"+nargs;
       
   316                 MethodHandle invoke = null;
       
   317                 try {
       
   318                     invoke = lookup.findVirtual(AllocateObject.class, name, MethodType.genericMethodType(nargs));
       
   319                 } catch (NoAccessException ex) {
       
   320                 }
       
   321                 if (invoke == null)  break;
       
   322                 invokes.add(invoke);
       
   323             }
       
   324             assert(invokes.size() == 9);  // current number of methods
       
   325             return invokes.toArray(new MethodHandle[0]);
       
   326         };
       
   327         static final MethodHandle[] INVOKES = makeInvokes();
       
   328         // For testing use this:
       
   329         //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
       
   330         static final MethodHandle VARARGS_INVOKE;
       
   331         static {
       
   332             try {
       
   333                 VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(AllocateObject.class, "invoke_V", MethodType.genericMethodType(0, true));
       
   334             } catch (NoAccessException ex) {
       
   335                 throw new InternalError("");
       
   336             }
       
   337         }
       
   338         // Corresponding generic constructor types:
       
   339         static final MethodType[] CON_TYPES = new MethodType[INVOKES.length];
       
   340         static {
       
   341             for (int i = 0; i < INVOKES.length; i++)
       
   342                 CON_TYPES[i] = makeConType(INVOKES[i]);
       
   343         }
       
   344         static final MethodType VARARGS_CON_TYPE = makeConType(VARARGS_INVOKE);
       
   345         static MethodType makeConType(MethodHandle invoke) {
       
   346             MethodType invType = invoke.type();
       
   347             return invType.changeParameterType(0, Object.class).changeReturnType(void.class);
       
   348         }
   201     }
   349     }
   202 
   350 
   203     public static
   351     public static
   204     MethodHandle accessField(Access token,
   352     MethodHandle accessField(Access token,
   205                              MemberName member, boolean isSetter,
   353                              MemberName member, boolean isSetter,
   467                                                 MethodHandle target,
   615                                                 MethodHandle target,
   468                                                 MethodType newType,
   616                                                 MethodType newType,
   469                                                 MethodType oldType,
   617                                                 MethodType oldType,
   470                                                 int[] permutationOrNull) {
   618                                                 int[] permutationOrNull) {
   471         Access.check(token);
   619         Access.check(token);
       
   620         assert(oldType.parameterCount() == target.type().parameterCount());
   472         if (permutationOrNull != null) {
   621         if (permutationOrNull != null) {
   473             int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
   622             int outargs = oldType.parameterCount(), inargs = newType.parameterCount();
   474             if (permutationOrNull.length != outargs)
   623             if (permutationOrNull.length != outargs)
   475                 throw newIllegalArgumentException("wrong number of arguments in permutation");
   624                 throw newIllegalArgumentException("wrong number of arguments in permutation");
   476             // Make the individual outgoing argument types match up first.
   625             // Make the individual outgoing argument types match up first.
   779         throw new UnsupportedOperationException("NYI");
   928         throw new UnsupportedOperationException("NYI");
   780     }
   929     }
   781 
   930 
   782     private static class GuardWithTest extends JavaMethodHandle {
   931     private static class GuardWithTest extends JavaMethodHandle {
   783         private final MethodHandle test, target, fallback;
   932         private final MethodHandle test, target, fallback;
   784         public GuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) {
   933         private GuardWithTest(MethodHandle invoker,
   785             this(INVOKES[target.type().parameterCount()], test, target, fallback);
   934                               MethodHandle test, MethodHandle target, MethodHandle fallback) {
   786         }
       
   787         public GuardWithTest(MethodHandle invoker,
       
   788                              MethodHandle test, MethodHandle target, MethodHandle fallback) {
       
   789             super(invoker);
   935             super(invoker);
   790             this.test = test;
   936             this.test = test;
   791             this.target = target;
   937             this.target = target;
   792             this.fallback = fallback;
   938             this.fallback = fallback;
   793         }
   939         }
       
   940         static MethodHandle make(Access token,
       
   941                                  MethodHandle test, MethodHandle target, MethodHandle fallback) {
       
   942             Access.check(token);
       
   943             MethodType type = target.type();
       
   944             int nargs = type.parameterCount();
       
   945             if (nargs < INVOKES.length) {
       
   946                 MethodHandle invoke = INVOKES[nargs];
       
   947                 MethodType gtype = type.generic();
       
   948                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
       
   949                 MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null);
       
   950                 MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
       
   951                 MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null);
       
   952                 if (gtest == null || gtarget == null || gfallback == null)  return null;
       
   953                 MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
       
   954                 return convertArguments(token, gguard, type, gtype, null);
       
   955             } else {
       
   956                 MethodHandle invoke = VARARGS_INVOKE;
       
   957                 MethodType gtype = MethodType.genericMethodType(1);
       
   958                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
       
   959                 MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0);
       
   960                 MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
       
   961                 MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0);
       
   962                 MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
       
   963                 if (gtest == null || gtarget == null || gfallback == null)  return null;
       
   964                 return collectArguments(token, gguard, type, 0, null);
       
   965             }
       
   966         }
   794         @Override
   967         @Override
   795         public String toString() {
   968         public String toString() {
   796             return target.toString();
   969             return target.toString();
   797         }
   970         }
   798         private Object invoke_V(Object... av) throws Throwable {
   971         private Object invoke_V(Object... av) throws Throwable {
   799             if (test.<boolean>invoke(av))
   972             if (test.<boolean>invokeExact(av))
   800                 return target.<Object>invoke(av);
   973                 return target.<Object>invokeExact(av);
   801             return fallback.<Object>invoke(av);
   974             return fallback.<Object>invokeExact(av);
   802         }
   975         }
   803         private Object invoke_L0() throws Throwable {
   976         private Object invoke_L0() throws Throwable {
   804             if (test.<boolean>invoke())
   977             if (test.<boolean>invokeExact())
   805                 return target.<Object>invoke();
   978                 return target.<Object>invokeExact();
   806             return fallback.<Object>invoke();
   979             return fallback.<Object>invokeExact();
   807         }
   980         }
   808         private Object invoke_L1(Object a0) throws Throwable {
   981         private Object invoke_L1(Object a0) throws Throwable {
   809             if (test.<boolean>invoke(a0))
   982             if (test.<boolean>invokeExact(a0))
   810                 return target.<Object>invoke(a0);
   983                 return target.<Object>invokeExact(a0);
   811             return fallback.<Object>invoke(a0);
   984             return fallback.<Object>invokeExact(a0);
   812         }
   985         }
   813         private Object invoke_L2(Object a0, Object a1) throws Throwable {
   986         private Object invoke_L2(Object a0, Object a1) throws Throwable {
   814             if (test.<boolean>invoke(a0, a1))
   987             if (test.<boolean>invokeExact(a0, a1))
   815                 return target.<Object>invoke(a0, a1);
   988                 return target.<Object>invokeExact(a0, a1);
   816             return fallback.<Object>invoke(a0, a1);
   989             return fallback.<Object>invokeExact(a0, a1);
   817         }
   990         }
   818         private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
   991         private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
   819             if (test.<boolean>invoke(a0, a1, a2))
   992             if (test.<boolean>invokeExact(a0, a1, a2))
   820                 return target.<Object>invoke(a0, a1, a2);
   993                 return target.<Object>invokeExact(a0, a1, a2);
   821             return fallback.<Object>invoke(a0, a1, a2);
   994             return fallback.<Object>invokeExact(a0, a1, a2);
   822         }
   995         }
   823         private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
   996         private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
   824             if (test.<boolean>invoke(a0, a1, a2, a3))
   997             if (test.<boolean>invokeExact(a0, a1, a2, a3))
   825                 return target.<Object>invoke(a0, a1, a2, a3);
   998                 return target.<Object>invokeExact(a0, a1, a2, a3);
   826             return fallback.<Object>invoke(a0, a1, a2, a3);
   999             return fallback.<Object>invokeExact(a0, a1, a2, a3);
   827         }
  1000         }
   828         private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
  1001         private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
   829             if (test.<boolean>invoke(a0, a1, a2, a3, a4))
  1002             if (test.<boolean>invokeExact(a0, a1, a2, a3, a4))
   830                 return target.<Object>invoke(a0, a1, a2, a3, a4);
  1003                 return target.<Object>invokeExact(a0, a1, a2, a3, a4);
   831             return fallback.<Object>invoke(a0, a1, a2, a3, a4);
  1004             return fallback.<Object>invokeExact(a0, a1, a2, a3, a4);
   832         }
  1005         }
   833         private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
  1006         private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
   834             if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5))
  1007             if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5))
   835                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
  1008                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
   836             return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5);
  1009             return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
   837         }
  1010         }
   838         private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
  1011         private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
   839             if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6))
  1012             if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6))
   840                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
  1013                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
   841             return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
  1014             return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
   842         }
  1015         }
   843         private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
  1016         private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
   844             if (test.<boolean>invoke(a0, a1, a2, a3, a4, a5, a6, a7))
  1017             if (test.<boolean>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7))
   845                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
  1018                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
   846             return fallback.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
  1019             return fallback.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
   847         }
  1020         }
   848         static MethodHandle[] makeInvokes() {
  1021         static MethodHandle[] makeInvokes() {
   849             ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
  1022             ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
   850             MethodHandles.Lookup lookup = IMPL_LOOKUP;
  1023             MethodHandles.Lookup lookup = IMPL_LOOKUP;
   851             for (;;) {
  1024             for (;;) {
   878     public static
  1051     public static
   879     MethodHandle makeGuardWithTest(Access token,
  1052     MethodHandle makeGuardWithTest(Access token,
   880                                    MethodHandle test,
  1053                                    MethodHandle test,
   881                                    MethodHandle target,
  1054                                    MethodHandle target,
   882                                    MethodHandle fallback) {
  1055                                    MethodHandle fallback) {
   883         Access.check(token);
  1056         return GuardWithTest.make(token, test, target, fallback);
   884         MethodType type = target.type();
       
   885         int nargs = type.parameterCount();
       
   886         if (nargs < GuardWithTest.INVOKES.length) {
       
   887             MethodType gtype = type.generic();
       
   888             MethodHandle gtest = convertArguments(token, test, gtype.changeReturnType(boolean.class), test.type(), null);
       
   889             MethodHandle gtarget = convertArguments(token, target, gtype, type, null);
       
   890             MethodHandle gfallback = convertArguments(token, fallback, gtype, type, null);
       
   891             if (gtest == null || gtarget == null || gfallback == null)  return null;
       
   892             MethodHandle gguard = new GuardWithTest(gtest, gtarget, gfallback);
       
   893             return convertArguments(token, gguard, type, gtype, null);
       
   894         } else {
       
   895             MethodType gtype = MethodType.genericMethodType(0, true);
       
   896             MethodHandle gtest = spreadArguments(token, test, gtype.changeReturnType(boolean.class), 0);
       
   897             MethodHandle gtarget = spreadArguments(token, target, gtype, 0);
       
   898             MethodHandle gfallback = spreadArguments(token, fallback, gtype, 0);
       
   899             MethodHandle gguard = new GuardWithTest(GuardWithTest.VARARGS_INVOKE, gtest, gtarget, gfallback);
       
   900             if (gtest == null || gtarget == null || gfallback == null)  return null;
       
   901             return collectArguments(token, gguard, type, 0, null);
       
   902         }
       
   903     }
  1057     }
   904 
  1058 
   905     private static class GuardWithCatch extends JavaMethodHandle {
  1059     private static class GuardWithCatch extends JavaMethodHandle {
   906         private final MethodHandle target;
  1060         private final MethodHandle target;
   907         private final Class<? extends Throwable> exType;
  1061         private final Class<? extends Throwable> exType;
   920         public String toString() {
  1074         public String toString() {
   921             return target.toString();
  1075             return target.toString();
   922         }
  1076         }
   923         private Object invoke_V(Object... av) throws Throwable {
  1077         private Object invoke_V(Object... av) throws Throwable {
   924             try {
  1078             try {
   925                 return target.<Object>invoke(av);
  1079                 return target.<Object>invokeExact(av);
   926             } catch (Throwable t) {
  1080             } catch (Throwable t) {
   927                 if (!exType.isInstance(t))  throw t;
  1081                 if (!exType.isInstance(t))  throw t;
   928                 return catcher.<Object>invoke(t, av);
  1082                 return catcher.<Object>invokeExact(t, av);
   929             }
  1083             }
   930         }
  1084         }
   931         private Object invoke_L0() throws Throwable {
  1085         private Object invoke_L0() throws Throwable {
   932             try {
  1086             try {
   933                 return target.<Object>invoke();
  1087                 return target.<Object>invokeExact();
   934             } catch (Throwable t) {
  1088             } catch (Throwable t) {
   935                 if (!exType.isInstance(t))  throw t;
  1089                 if (!exType.isInstance(t))  throw t;
   936                 return catcher.<Object>invoke(t);
  1090                 return catcher.<Object>invokeExact(t);
   937             }
  1091             }
   938         }
  1092         }
   939         private Object invoke_L1(Object a0) throws Throwable {
  1093         private Object invoke_L1(Object a0) throws Throwable {
   940             try {
  1094             try {
   941                 return target.<Object>invoke(a0);
  1095                 return target.<Object>invokeExact(a0);
   942             } catch (Throwable t) {
  1096             } catch (Throwable t) {
   943                 if (!exType.isInstance(t))  throw t;
  1097                 if (!exType.isInstance(t))  throw t;
   944                 return catcher.<Object>invoke(t, a0);
  1098                 return catcher.<Object>invokeExact(t, a0);
   945             }
  1099             }
   946         }
  1100         }
   947         private Object invoke_L2(Object a0, Object a1) throws Throwable {
  1101         private Object invoke_L2(Object a0, Object a1) throws Throwable {
   948             try {
  1102             try {
   949                 return target.<Object>invoke(a0, a1);
  1103                 return target.<Object>invokeExact(a0, a1);
   950             } catch (Throwable t) {
  1104             } catch (Throwable t) {
   951                 if (!exType.isInstance(t))  throw t;
  1105                 if (!exType.isInstance(t))  throw t;
   952                 return catcher.<Object>invoke(t, a0, a1);
  1106                 return catcher.<Object>invokeExact(t, a0, a1);
   953             }
  1107             }
   954         }
  1108         }
   955         private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
  1109         private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
   956             try {
  1110             try {
   957                 return target.<Object>invoke(a0, a1, a2);
  1111                 return target.<Object>invokeExact(a0, a1, a2);
   958             } catch (Throwable t) {
  1112             } catch (Throwable t) {
   959                 if (!exType.isInstance(t))  throw t;
  1113                 if (!exType.isInstance(t))  throw t;
   960                 return catcher.<Object>invoke(t, a0, a1, a2);
  1114                 return catcher.<Object>invokeExact(t, a0, a1, a2);
   961             }
  1115             }
   962         }
  1116         }
   963         private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
  1117         private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
   964             try {
  1118             try {
   965                 return target.<Object>invoke(a0, a1, a2, a3);
  1119                 return target.<Object>invokeExact(a0, a1, a2, a3);
   966             } catch (Throwable t) {
  1120             } catch (Throwable t) {
   967                 if (!exType.isInstance(t))  throw t;
  1121                 if (!exType.isInstance(t))  throw t;
   968                 return catcher.<Object>invoke(t, a0, a1, a2, a3);
  1122                 return catcher.<Object>invokeExact(t, a0, a1, a2, a3);
   969             }
  1123             }
   970         }
  1124         }
   971         private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
  1125         private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
   972             try {
  1126             try {
   973                 return target.<Object>invoke(a0, a1, a2, a3, a4);
  1127                 return target.<Object>invokeExact(a0, a1, a2, a3, a4);
   974             } catch (Throwable t) {
  1128             } catch (Throwable t) {
   975                 if (!exType.isInstance(t))  throw t;
  1129                 if (!exType.isInstance(t))  throw t;
   976                 return catcher.<Object>invoke(t, a0, a1, a2, a3, a4);
  1130                 return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4);
   977             }
  1131             }
   978         }
  1132         }
   979         private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
  1133         private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
   980             try {
  1134             try {
   981                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5);
  1135                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5);
   982             } catch (Throwable t) {
  1136             } catch (Throwable t) {
   983                 if (!exType.isInstance(t))  throw t;
  1137                 if (!exType.isInstance(t))  throw t;
   984                 return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5);
  1138                 return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5);
   985             }
  1139             }
   986         }
  1140         }
   987         private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
  1141         private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
   988             try {
  1142             try {
   989                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6);
  1143                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6);
   990             } catch (Throwable t) {
  1144             } catch (Throwable t) {
   991                 if (!exType.isInstance(t))  throw t;
  1145                 if (!exType.isInstance(t))  throw t;
   992                 return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6);
  1146                 return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
   993             }
  1147             }
   994         }
  1148         }
   995         private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
  1149         private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
   996             try {
  1150             try {
   997                 return target.<Object>invoke(a0, a1, a2, a3, a4, a5, a6, a7);
  1151                 return target.<Object>invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
   998             } catch (Throwable t) {
  1152             } catch (Throwable t) {
   999                 if (!exType.isInstance(t))  throw t;
  1153                 if (!exType.isInstance(t))  throw t;
  1000                 return catcher.<Object>invoke(t, a0, a1, a2, a3, a4, a5, a6, a7);
  1154                 return catcher.<Object>invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
  1001             }
  1155             }
  1002         }
  1156         }
  1003         static MethodHandle[] makeInvokes() {
  1157         static MethodHandle[] makeInvokes() {
  1004             ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
  1158             ArrayList<MethodHandle> invokes = new ArrayList<MethodHandle>();
  1005             MethodHandles.Lookup lookup = IMPL_LOOKUP;
  1159             MethodHandles.Lookup lookup = IMPL_LOOKUP;
  1104             throw new ClassCastException(message);
  1258             throw new ClassCastException(message);
  1105         default:
  1259         default:
  1106             throw new InternalError("unexpected code "+code+": "+message);
  1260             throw new InternalError("unexpected code "+code+": "+message);
  1107         }
  1261         }
  1108     }
  1262     }
       
  1263 
       
  1264     // Linkage support:
       
  1265     public static void registerBootstrap(Access token, Class<?> callerClass, MethodHandle bootstrapMethod) {
       
  1266         Access.check(token);
       
  1267         MethodHandleNatives.registerBootstrap(callerClass, bootstrapMethod);
       
  1268     }
       
  1269     public static MethodHandle getBootstrap(Access token, Class<?> callerClass) {
       
  1270         Access.check(token);
       
  1271         return MethodHandleNatives.getBootstrap(callerClass);
       
  1272     }
  1109 }
  1273 }