1 /*
   2  * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   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
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  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() {
  50         // Trigger selected static initializations.
  51         MemberName.Factory.INSTANCE.getClass();
  52     }
  53 
  54     static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
  55         if (!arrayClass.isArray())
  56             throw newIllegalArgumentException("not an array: "+arrayClass);
  57         MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
  58         MethodType srcType = accessor.type().erase();
  59         MethodType lambdaType = srcType.invokerType();
  60         Name[] names = arguments(1, lambdaType);
  61         Name[] args  = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
  62         names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
  63         LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
  64         MethodHandle mh = SimpleMethodHandle.make(srcType, form);
  65         if (ArrayAccessor.needCast(arrayClass)) {
  66             mh = mh.bindTo(arrayClass);
  67         }
  68         mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
  69         return mh;
  70     }
  71 
  72     static final class ArrayAccessor {
  73         /// Support for array element access
  74         static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>();  // TODO use it
  75         static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>();  // TODO use it
  76 
  77         static int     getElementI(int[]     a, int i)            { return              a[i]; }
  78         static long    getElementJ(long[]    a, int i)            { return              a[i]; }
  79         static float   getElementF(float[]   a, int i)            { return              a[i]; }
  80         static double  getElementD(double[]  a, int i)            { return              a[i]; }
  81         static boolean getElementZ(boolean[] a, int i)            { return              a[i]; }
  82         static byte    getElementB(byte[]    a, int i)            { return              a[i]; }
  83         static short   getElementS(short[]   a, int i)            { return              a[i]; }
  84         static char    getElementC(char[]    a, int i)            { return              a[i]; }
  85         static Object  getElementL(Object[]  a, int i)            { return              a[i]; }
  86 
  87         static void    setElementI(int[]     a, int i, int     x) {              a[i] = x; }
  88         static void    setElementJ(long[]    a, int i, long    x) {              a[i] = x; }
  89         static void    setElementF(float[]   a, int i, float   x) {              a[i] = x; }
  90         static void    setElementD(double[]  a, int i, double  x) {              a[i] = x; }
  91         static void    setElementZ(boolean[] a, int i, boolean x) {              a[i] = x; }
  92         static void    setElementB(byte[]    a, int i, byte    x) {              a[i] = x; }
  93         static void    setElementS(short[]   a, int i, short   x) {              a[i] = x; }
  94         static void    setElementC(char[]    a, int i, char    x) {              a[i] = x; }
  95         static void    setElementL(Object[]  a, int i, Object  x) {              a[i] = x; }
  96 
  97         static Object  getElementL(Class<?> arrayClass, Object[] a, int i)           { arrayClass.cast(a); return a[i]; }
  98         static void    setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
  99 
 100         // Weakly typed wrappers of Object[] accessors:
 101         static Object  getElementL(Object    a, int i)            { return getElementL((Object[])a, i); }
 102         static void    setElementL(Object    a, int i, Object  x) {        setElementL((Object[]) a, i, x); }
 103         static Object  getElementL(Object   arrayClass, Object a, int i)             { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
 104         static void    setElementL(Object   arrayClass, Object a, int i, Object x)   {        setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
 105 
 106         static boolean needCast(Class<?> arrayClass) {
 107             Class<?> elemClass = arrayClass.getComponentType();
 108             return !elemClass.isPrimitive() && elemClass != Object.class;
 109         }
 110         static String name(Class<?> arrayClass, boolean isSetter) {
 111             Class<?> elemClass = arrayClass.getComponentType();
 112             if (elemClass == null)  throw new IllegalArgumentException();
 113             return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
 114         }
 115         static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false;  // FIXME: decide
 116         static MethodType type(Class<?> arrayClass, boolean isSetter) {
 117             Class<?> elemClass = arrayClass.getComponentType();
 118             Class<?> arrayArgClass = arrayClass;
 119             if (!elemClass.isPrimitive()) {
 120                 arrayArgClass = Object[].class;
 121                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 122                     arrayArgClass = Object.class;
 123             }
 124             if (!needCast(arrayClass)) {
 125                 return !isSetter ?
 126                     MethodType.methodType(elemClass,  arrayArgClass, int.class) :
 127                     MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
 128             } else {
 129                 Class<?> classArgClass = Class.class;
 130                 if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
 131                     classArgClass = Object.class;
 132                 return !isSetter ?
 133                     MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
 134                     MethodType.methodType(void.class,   classArgClass, arrayArgClass, int.class, Object.class);
 135             }
 136         }
 137         static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
 138             Class<?> elemClass = arrayClass.getComponentType();
 139             return !isSetter ?
 140                     MethodType.methodType(elemClass,  arrayClass, int.class) :
 141                     MethodType.methodType(void.class, arrayClass, int.class, elemClass);
 142         }
 143         static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
 144             String     name = name(arrayClass, isSetter);
 145             MethodType type = type(arrayClass, isSetter);
 146             try {
 147                 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
 148             } catch (ReflectiveOperationException ex) {
 149                 throw uncaughtException(ex);
 150             }
 151         }
 152     }
 153 
 154     /**
 155      * Create a JVM-level adapter method handle to conform the given method
 156      * handle to the similar newType, using only pairwise argument conversions.
 157      * For each argument, convert incoming argument to the exact type needed.
 158      * The argument conversions allowed are casting, boxing and unboxing,
 159      * integral widening or narrowing, and floating point widening or narrowing.
 160      * @param srcType required call type
 161      * @param target original method handle
 162      * @param level which strength of conversion is allowed
 163      * @return an adapter to the original handle with the desired new type,
 164      *          or the original target if the types are already identical
 165      *          or null if the adaptation cannot be made
 166      */
 167     static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
 168         assert(level >= 0 && level <= 2);
 169         MethodType dstType = target.type();
 170         assert(dstType.parameterCount() == target.type().parameterCount());
 171         if (srcType == dstType)
 172             return target;
 173 
 174         // Calculate extra arguments (temporaries) required in the names array.
 175         // FIXME: Use an ArrayList<Name>.  Some arguments require more than one conversion step.
 176         final int INARG_COUNT = srcType.parameterCount();
 177         int conversions = 0;
 178         boolean[] needConv = new boolean[1+INARG_COUNT];
 179         for (int i = 0; i <= INARG_COUNT; i++) {
 180             Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
 181             Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
 182             if (!VerifyType.isNullConversion(src, dst) ||
 183                 level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
 184                 needConv[i] = true;
 185                 conversions++;
 186             }
 187         }
 188         boolean retConv = needConv[INARG_COUNT];
 189 
 190         final int IN_MH         = 0;
 191         final int INARG_BASE    = 1;
 192         final int INARG_LIMIT   = INARG_BASE + INARG_COUNT;
 193         final int NAME_LIMIT    = INARG_LIMIT + conversions + 1;
 194         final int RETURN_CONV   = (!retConv ? -1         : NAME_LIMIT - 1);
 195         final int OUT_CALL      = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
 196 
 197         // Now build a LambdaForm.
 198         MethodType lambdaType = srcType.basicType().invokerType();
 199         Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
 200 
 201         // Collect the arguments to the outgoing call, maybe with conversions:
 202         final int OUTARG_BASE = 0;  // target MH is Name.function, name Name.arguments[0]
 203         Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
 204 
 205         int nameCursor = INARG_LIMIT;
 206         for (int i = 0; i < INARG_COUNT; i++) {
 207             Class<?> src = srcType.parameterType(i);
 208             Class<?> dst = dstType.parameterType(i);
 209 
 210             if (!needConv[i]) {
 211                 // do nothing: difference is trivial
 212                 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
 213                 continue;
 214             }
 215 
 216             // Tricky case analysis follows.
 217             MethodHandle fn = null;
 218             if (src.isPrimitive()) {
 219                 if (dst.isPrimitive()) {
 220                     fn = ValueConversions.convertPrimitive(src, dst);
 221                 } else {
 222                     Wrapper w = Wrapper.forPrimitiveType(src);
 223                     MethodHandle boxMethod = ValueConversions.box(w);
 224                     if (dst == w.wrapperType())
 225                         fn = boxMethod;
 226                     else
 227                         fn = boxMethod.asType(MethodType.methodType(dst, src));
 228                 }
 229             } else {
 230                 if (dst.isPrimitive()) {
 231                     // Caller has boxed a primitive.  Unbox it for the target.
 232                     Wrapper w = Wrapper.forPrimitiveType(dst);
 233                     if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
 234                         fn = ValueConversions.unbox(dst);
 235                     } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
 236                         // Examples:  Object->int, Number->int, Comparable->int; Byte->int, Character->int
 237                         // must include additional conversions
 238                         // src must be examined at runtime, to detect Byte, Character, etc.
 239                         MethodHandle unboxMethod = (level == 1
 240                                                     ? ValueConversions.unbox(dst)
 241                                                     : ValueConversions.unboxCast(dst));
 242                         fn = unboxMethod;
 243                     } else {
 244                         // Example: Byte->int
 245                         // Do this by reformulating the problem to Byte->byte.
 246                         Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
 247                         MethodHandle unbox = ValueConversions.unbox(srcPrim);
 248                         // Compose the two conversions.  FIXME:  should make two Names for this job
 249                         fn = unbox.asType(MethodType.methodType(dst, src));
 250                     }
 251                 } else {
 252                     // Simple reference conversion.
 253                     // Note:  Do not check for a class hierarchy relation
 254                     // between src and dst.  In all cases a 'null' argument
 255                     // will pass the cast conversion.
 256                     fn = ValueConversions.cast(dst, Lazy.MH_castReference);
 257                 }
 258             }
 259             Name conv = new Name(fn, names[INARG_BASE + i]);
 260             assert(names[nameCursor] == null);
 261             names[nameCursor++] = conv;
 262             assert(outArgs[OUTARG_BASE + i] == null);
 263             outArgs[OUTARG_BASE + i] = conv;
 264         }
 265 
 266         // Build argument array for the call.
 267         assert(nameCursor == OUT_CALL);
 268         names[OUT_CALL] = new Name(target, outArgs);
 269 
 270         if (RETURN_CONV < 0) {
 271             assert(OUT_CALL == names.length-1);
 272         } else {
 273             Class<?> needReturn = srcType.returnType();
 274             Class<?> haveReturn = dstType.returnType();
 275             MethodHandle fn;
 276             Object[] arg = { names[OUT_CALL] };
 277             if (haveReturn == void.class) {
 278                 // synthesize a zero value for the given void
 279                 Object zero = Wrapper.forBasicType(needReturn).zero();
 280                 fn = MethodHandles.constant(needReturn, zero);
 281                 arg = new Object[0];  // don't pass names[OUT_CALL] to conversion
 282             } else {
 283                 MethodHandle identity = MethodHandles.identity(needReturn);
 284                 MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
 285                 fn = makePairwiseConvert(identity, needConversion, level);
 286             }
 287             assert(names[RETURN_CONV] == null);
 288             names[RETURN_CONV] = new Name(fn, arg);
 289             assert(RETURN_CONV == names.length-1);
 290         }
 291 
 292         LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
 293         return SimpleMethodHandle.make(srcType, form);
 294     }
 295 
 296     /**
 297      * Identity function, with reference cast.
 298      * @param t an arbitrary reference type
 299      * @param x an arbitrary reference value
 300      * @return the same value x
 301      */
 302     @ForceInline
 303     @SuppressWarnings("unchecked")
 304     static <T,U> T castReference(Class<? extends T> t, U x) {
 305         // inlined Class.cast because we can't ForceInline it
 306         if (x != null && !t.isInstance(x))
 307             throw newClassCastException(t, x);
 308         return (T) x;
 309     }
 310 
 311     private static ClassCastException newClassCastException(Class<?> t, Object obj) {
 312         return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
 313     }
 314 
 315     static MethodHandle makeReferenceIdentity(Class<?> refType) {
 316         MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
 317         Name[] names = arguments(1, lambdaType);
 318         names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
 319         LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
 320         return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
 321     }
 322 
 323     static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
 324         MethodType type = target.type();
 325         int last = type.parameterCount() - 1;
 326         if (type.parameterType(last) != arrayType)
 327             target = target.asType(type.changeParameterType(last, arrayType));
 328         target = target.asFixedArity();  // make sure this attribute is turned off
 329         return new AsVarargsCollector(target, target.type(), arrayType);
 330     }
 331 
 332     static class AsVarargsCollector extends MethodHandle {
 333         private final MethodHandle target;
 334         private final Class<?> arrayType;
 335         private /*@Stable*/ MethodHandle asCollectorCache;
 336 
 337         AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
 338             super(type, reinvokerForm(target));
 339             this.target = target;
 340             this.arrayType = arrayType;
 341             this.asCollectorCache = target.asCollector(arrayType, 0);
 342         }
 343 
 344         @Override MethodHandle reinvokerTarget() { return target; }
 345 
 346         @Override
 347         public boolean isVarargsCollector() {
 348             return true;
 349         }
 350 
 351         @Override
 352         public MethodHandle asFixedArity() {
 353             return target;
 354         }
 355 
 356         @Override
 357         public MethodHandle asTypeUncached(MethodType newType) {
 358             MethodType type = this.type();
 359             int collectArg = type.parameterCount() - 1;
 360             int newArity = newType.parameterCount();
 361             if (newArity == collectArg+1 &&
 362                 type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
 363                 // if arity and trailing parameter are compatible, do normal thing
 364                 return asTypeCache = asFixedArity().asType(newType);
 365             }
 366             // check cache
 367             MethodHandle acc = asCollectorCache;
 368             if (acc != null && acc.type().parameterCount() == newArity)
 369                 return asTypeCache = acc.asType(newType);
 370             // build and cache a collector
 371             int arrayLength = newArity - collectArg;
 372             MethodHandle collector;
 373             try {
 374                 collector = asFixedArity().asCollector(arrayType, arrayLength);
 375                 assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
 376             } catch (IllegalArgumentException ex) {
 377                 throw new WrongMethodTypeException("cannot build collector", ex);
 378             }
 379             asCollectorCache = collector;
 380             return asTypeCache = collector.asType(newType);
 381         }
 382 
 383         @Override
 384         MethodHandle setVarargs(MemberName member) {
 385             if (member.isVarargs())  return this;
 386             return asFixedArity();
 387         }
 388 
 389         @Override
 390         MethodHandle viewAsType(MethodType newType) {
 391             if (newType.lastParameterType() != type().lastParameterType())
 392                 throw new InternalError();
 393             MethodHandle newTarget = asFixedArity().viewAsType(newType);
 394             // put back the varargs bit:
 395             return new AsVarargsCollector(newTarget, newType, arrayType);
 396         }
 397 
 398         @Override
 399         MemberName internalMemberName() {
 400             return asFixedArity().internalMemberName();
 401         }
 402         @Override
 403         Class<?> internalCallerClass() {
 404             return asFixedArity().internalCallerClass();
 405         }
 406 
 407         /*non-public*/
 408         @Override
 409         boolean isInvokeSpecial() {
 410             return asFixedArity().isInvokeSpecial();
 411         }
 412 
 413 
 414         @Override
 415         MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
 416             return asFixedArity().bindArgument(pos, basicType, value);
 417         }
 418 
 419         @Override
 420         MethodHandle bindReceiver(Object receiver) {
 421             return asFixedArity().bindReceiver(receiver);
 422         }
 423 
 424         @Override
 425         MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
 426             return asFixedArity().dropArguments(srcType, pos, drops);
 427         }
 428 
 429         @Override
 430         MethodHandle permuteArguments(MethodType newType, int[] reorder) {
 431             return asFixedArity().permuteArguments(newType, reorder);
 432         }
 433     }
 434 
 435     /** Factory method:  Spread selected argument. */
 436     static MethodHandle makeSpreadArguments(MethodHandle target,
 437                                             Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
 438         MethodType targetType = target.type();
 439 
 440         for (int i = 0; i < spreadArgCount; i++) {
 441             Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
 442             if (arg == null)  arg = Object.class;
 443             targetType = targetType.changeParameterType(spreadArgPos + i, arg);
 444         }
 445         target = target.asType(targetType);
 446 
 447         MethodType srcType = targetType
 448                 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
 449         // Now build a LambdaForm.
 450         MethodType lambdaType = srcType.invokerType();
 451         Name[] names = arguments(spreadArgCount + 2, lambdaType);
 452         int nameCursor = lambdaType.parameterCount();
 453         int[] indexes = new int[targetType.parameterCount()];
 454 
 455         for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
 456             Class<?> src = lambdaType.parameterType(i);
 457             if (i == spreadArgPos) {
 458                 // Spread the array.
 459                 MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
 460                 Name array = names[argIndex];
 461                 names[nameCursor++] = new Name(Lazy.NF_checkSpreadArgument, array, spreadArgCount);
 462                 for (int j = 0; j < spreadArgCount; i++, j++) {
 463                     indexes[i] = nameCursor;
 464                     names[nameCursor++] = new Name(aload, array, j);
 465                 }
 466             } else if (i < indexes.length) {
 467                 indexes[i] = argIndex;
 468             }
 469         }
 470         assert(nameCursor == names.length-1);  // leave room for the final call
 471 
 472         // Build argument array for the call.
 473         Name[] targetArgs = new Name[targetType.parameterCount()];
 474         for (int i = 0; i < targetType.parameterCount(); i++) {
 475             int idx = indexes[i];
 476             targetArgs[i] = names[idx];
 477         }
 478         names[names.length - 1] = new Name(target, (Object[]) targetArgs);
 479 
 480         LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
 481         return SimpleMethodHandle.make(srcType, form);
 482     }
 483 
 484     static void checkSpreadArgument(Object av, int n) {
 485         if (av == null) {
 486             if (n == 0)  return;
 487         } else if (av instanceof Object[]) {
 488             int len = ((Object[])av).length;
 489             if (len == n)  return;
 490         } else {
 491             int len = java.lang.reflect.Array.getLength(av);
 492             if (len == n)  return;
 493         }
 494         // fall through to error:
 495         throw newIllegalArgumentException("array is not of length "+n);
 496     }
 497 
 498     /**
 499      * Pre-initialized NamedFunctions for bootstrapping purposes.
 500      * Factored in an inner class to delay initialization until first usage.
 501      */
 502     private static class Lazy {
 503         private static final Class<?> MHI = MethodHandleImpl.class;
 504 
 505         static final NamedFunction NF_checkSpreadArgument;
 506         static final NamedFunction NF_guardWithCatch;
 507         static final NamedFunction NF_selectAlternative;
 508         static final NamedFunction NF_throwException;
 509 
 510         static final MethodHandle MH_castReference;
 511 
 512         static {
 513             try {
 514                 NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
 515                 NF_guardWithCatch      = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
 516                                                                                  MethodHandle.class, Object[].class));
 517                 NF_selectAlternative   = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class,
 518                                                                                  MethodHandle.class));
 519                 NF_throwException      = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class));
 520 
 521                 NF_checkSpreadArgument.resolve();
 522                 NF_guardWithCatch.resolve();
 523                 NF_selectAlternative.resolve();
 524                 NF_throwException.resolve();
 525 
 526                 MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class);
 527                 MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt);
 528             } catch (ReflectiveOperationException ex) {
 529                 throw newInternalError(ex);
 530             }
 531         }
 532     }
 533 
 534     /** Factory method:  Collect or filter selected argument(s). */
 535     static MethodHandle makeCollectArguments(MethodHandle target,
 536                 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
 537         MethodType targetType = target.type();          // (a..., c, [b...])=>r
 538         MethodType collectorType = collector.type();    // (b...)=>c
 539         int collectArgCount = collectorType.parameterCount();
 540         Class<?> collectValType = collectorType.returnType();
 541         int collectValCount = (collectValType == void.class ? 0 : 1);
 542         MethodType srcType = targetType                 // (a..., [b...])=>r
 543                 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
 544         if (!retainOriginalArgs) {                      // (a..., b...)=>r
 545             srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
 546         }
 547         // in  arglist: [0: ...keep1 | cpos: collect...  | cpos+cacount: keep2... ]
 548         // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
 549         // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
 550 
 551         // Now build a LambdaForm.
 552         MethodType lambdaType = srcType.invokerType();
 553         Name[] names = arguments(2, lambdaType);
 554         final int collectNamePos = names.length - 2;
 555         final int targetNamePos  = names.length - 1;
 556 
 557         Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
 558         names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
 559 
 560         // Build argument array for the target.
 561         // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ].
 562         // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ].
 563         Name[] targetArgs = new Name[targetType.parameterCount()];
 564         int inputArgPos  = 1;  // incoming LF args to copy to target
 565         int targetArgPos = 0;  // fill pointer for targetArgs
 566         int chunk = collectArgPos;  // |headArgs|
 567         System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 568         inputArgPos  += chunk;
 569         targetArgPos += chunk;
 570         if (collectValType != void.class) {
 571             targetArgs[targetArgPos++] = names[collectNamePos];
 572         }
 573         chunk = collectArgCount;
 574         if (retainOriginalArgs) {
 575             System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 576             targetArgPos += chunk;   // optionally pass on the collected chunk
 577         }
 578         inputArgPos += chunk;
 579         chunk = targetArgs.length - targetArgPos;  // all the rest
 580         System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
 581         assert(inputArgPos + chunk == collectNamePos);  // use of rest of input args also
 582         names[targetNamePos] = new Name(target, (Object[]) targetArgs);
 583 
 584         LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
 585         return SimpleMethodHandle.make(srcType, form);
 586     }
 587 
 588     @LambdaForm.Hidden
 589     static
 590     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
 591         return testResult ? target : fallback;
 592     }
 593 
 594     static
 595     MethodHandle makeGuardWithTest(MethodHandle test,
 596                                    MethodHandle target,
 597                                    MethodHandle fallback) {
 598         MethodType basicType = target.type().basicType();
 599         MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
 600         int arity = basicType.parameterCount();
 601         int extraNames = 3;
 602         MethodType lambdaType = basicType.invokerType();
 603         Name[] names = arguments(extraNames, lambdaType);
 604 
 605         Object[] testArgs   = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
 606         Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
 607 
 608         // call test
 609         names[arity + 1] = new Name(test, testArgs);
 610 
 611         // call selectAlternative
 612         Object[] selectArgs = { names[arity + 1], target, fallback };
 613         names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs);
 614         targetArgs[0] = names[arity + 2];
 615 
 616         // call target or fallback
 617         names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
 618 
 619         LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
 620         return SimpleMethodHandle.make(target.type(), form);
 621     }
 622 
 623     /**
 624      * The LambaForm shape for catchException combinator is the following:
 625      * <blockquote><pre>{@code
 626      *  guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
 627      *    t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
 628      *    t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
 629      *    t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
 630      *    t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
 631      *    t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
 632      *    t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
 633      *    t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
 634      *   t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
 635      * }</pre></blockquote>
 636      *
 637      * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
 638      * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
 639      * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
 640      *
 641      * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
 642      * among catchException combinators with the same basic type.
 643      */
 644     private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
 645         MethodType lambdaType = basicType.invokerType();
 646 
 647         LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
 648         if (lform != null) {
 649             return lform;
 650         }
 651         final int THIS_MH      = 0;  // the BMH_LLLLL
 652         final int ARG_BASE     = 1;  // start of incoming arguments
 653         final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
 654 
 655         int nameCursor = ARG_LIMIT;
 656         final int GET_TARGET       = nameCursor++;
 657         final int GET_CLASS        = nameCursor++;
 658         final int GET_CATCHER      = nameCursor++;
 659         final int GET_COLLECT_ARGS = nameCursor++;
 660         final int GET_UNBOX_RESULT = nameCursor++;
 661         final int BOXED_ARGS       = nameCursor++;
 662         final int TRY_CATCH        = nameCursor++;
 663         final int UNBOX_RESULT     = nameCursor++;
 664 
 665         Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 666 
 667         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 668         names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
 669         names[GET_CLASS]        = new Name(data.getterFunction(1), names[THIS_MH]);
 670         names[GET_CATCHER]      = new Name(data.getterFunction(2), names[THIS_MH]);
 671         names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
 672         names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
 673 
 674         // FIXME: rework argument boxing/result unboxing logic for LF interpretation
 675 
 676         // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
 677         MethodType collectArgsType = basicType.changeReturnType(Object.class);
 678         MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
 679         Object[] args = new Object[invokeBasic.type().parameterCount()];
 680         args[0] = names[GET_COLLECT_ARGS];
 681         System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
 682         names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
 683 
 684         // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
 685         Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
 686         names[TRY_CATCH] = new Name(Lazy.NF_guardWithCatch, gwcArgs);
 687 
 688         // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
 689         MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
 690         Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
 691         names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
 692 
 693         lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
 694 
 695         return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
 696     }
 697 
 698     static
 699     MethodHandle makeGuardWithCatch(MethodHandle target,
 700                                     Class<? extends Throwable> exType,
 701                                     MethodHandle catcher) {
 702         MethodType type = target.type();
 703         LambdaForm form = makeGuardWithCatchForm(type.basicType());
 704 
 705         // Prepare auxiliary method handles used during LambdaForm interpreation.
 706         // Box arguments and wrap them into Object[]: ValueConversions.array().
 707         MethodType varargsType = type.changeReturnType(Object[].class);
 708         MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
 709                                                    .asType(varargsType);
 710         // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
 711         MethodHandle unboxResult;
 712         if (type.returnType().isPrimitive()) {
 713             unboxResult = ValueConversions.unbox(type.returnType());
 714         } else {
 715             unboxResult = ValueConversions.identity();
 716         }
 717 
 718         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
 719         BoundMethodHandle mh;
 720         try {
 721             mh = (BoundMethodHandle)
 722                     data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
 723                                                     (Object) collectArgs, (Object) unboxResult);
 724         } catch (Throwable ex) {
 725             throw uncaughtException(ex);
 726         }
 727         assert(mh.type() == type);
 728         return mh;
 729     }
 730 
 731     /**
 732      * Intrinsified during LambdaForm compilation
 733      * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
 734      */
 735     @LambdaForm.Hidden
 736     static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
 737                                  Object... av) throws Throwable {
 738         // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case.
 739         try {
 740             return target.asFixedArity().invokeWithArguments(av);
 741         } catch (Throwable t) {
 742             if (!exType.isInstance(t)) throw t;
 743             return catcher.asFixedArity().invokeWithArguments(prepend(t, av));
 744         }
 745     }
 746 
 747     /** Prepend an element {@code elem} to an {@code array}. */
 748     @LambdaForm.Hidden
 749     private static Object[] prepend(Object elem, Object[] array) {
 750         Object[] newArray = new Object[array.length+1];
 751         newArray[0] = elem;
 752         System.arraycopy(array, 0, newArray, 1, array.length);
 753         return newArray;
 754     }
 755 
 756     static
 757     MethodHandle throwException(MethodType type) {
 758         assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
 759         int arity = type.parameterCount();
 760         if (arity > 1) {
 761             return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
 762         }
 763         return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
 764     }
 765 
 766     static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
 767 
 768     static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
 769     static MethodHandle fakeMethodHandleInvoke(MemberName method) {
 770         int idx;
 771         assert(method.isMethodHandleInvoke());
 772         switch (method.getName()) {
 773         case "invoke":       idx = 0; break;
 774         case "invokeExact":  idx = 1; break;
 775         default:             throw new InternalError(method.getName());
 776         }
 777         MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
 778         if (mh != null)  return mh;
 779         MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
 780                                                 MethodHandle.class, Object[].class);
 781         mh = throwException(type);
 782         mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
 783         if (!method.getInvocationType().equals(mh.type()))
 784             throw new InternalError(method.toString());
 785         mh = mh.withInternalMemberName(method);
 786         mh = mh.asVarargsCollector(Object[].class);
 787         assert(method.isVarargs());
 788         FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
 789         return mh;
 790     }
 791 
 792     /**
 793      * Create an alias for the method handle which, when called,
 794      * appears to be called from the same class loader and protection domain
 795      * as hostClass.
 796      * This is an expensive no-op unless the method which is called
 797      * is sensitive to its caller.  A small number of system methods
 798      * are in this category, including Class.forName and Method.invoke.
 799      */
 800     static
 801     MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
 802         return BindCaller.bindCaller(mh, hostClass);
 803     }
 804 
 805     // Put the whole mess into its own nested class.
 806     // That way we can lazily load the code and set up the constants.
 807     private static class BindCaller {
 808         static
 809         MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
 810             // Do not use this function to inject calls into system classes.
 811             if (hostClass == null
 812                 ||    (hostClass.isArray() ||
 813                        hostClass.isPrimitive() ||
 814                        hostClass.getName().startsWith("java.") ||
 815                        hostClass.getName().startsWith("sun."))) {
 816                 throw new InternalError();  // does not happen, and should not anyway
 817             }
 818             // For simplicity, convert mh to a varargs-like method.
 819             MethodHandle vamh = prepareForInvoker(mh);
 820             // Cache the result of makeInjectedInvoker once per argument class.
 821             MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
 822             return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
 823         }
 824 
 825         private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
 826             Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null);
 827             if (hostClass.getClassLoader() != bcc.getClassLoader())
 828                 throw new InternalError(hostClass.getName()+" (CL)");
 829             try {
 830                 if (hostClass.getProtectionDomain() != bcc.getProtectionDomain())
 831                     throw new InternalError(hostClass.getName()+" (PD)");
 832             } catch (SecurityException ex) {
 833                 // Self-check was blocked by security manager.  This is OK.
 834                 // In fact the whole try body could be turned into an assertion.
 835             }
 836             try {
 837                 MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class));
 838                 init.invokeExact();  // force initialization of the class
 839             } catch (Throwable ex) {
 840                 throw uncaughtException(ex);
 841             }
 842             MethodHandle bccInvoker;
 843             try {
 844                 MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
 845                 bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT);
 846             } catch (ReflectiveOperationException ex) {
 847                 throw uncaughtException(ex);
 848             }
 849             // Test the invoker, to ensure that it really injects into the right place.
 850             try {
 851                 MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
 852                 Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc});
 853             } catch (Throwable ex) {
 854                 throw new InternalError(ex);
 855             }
 856             return bccInvoker;
 857         }
 858         private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
 859             @Override protected MethodHandle computeValue(Class<?> hostClass) {
 860                 return makeInjectedInvoker(hostClass);
 861             }
 862         };
 863 
 864         // Adapt mh so that it can be called directly from an injected invoker:
 865         private static MethodHandle prepareForInvoker(MethodHandle mh) {
 866             mh = mh.asFixedArity();
 867             MethodType mt = mh.type();
 868             int arity = mt.parameterCount();
 869             MethodHandle vamh = mh.asType(mt.generic());
 870             vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
 871             vamh = vamh.asSpreader(Object[].class, arity);
 872             vamh.internalForm().compileToBytecode();  // eliminate LFI stack frames
 873             return vamh;
 874         }
 875 
 876         // Undo the adapter effect of prepareForInvoker:
 877         private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
 878                                                   MemberName member,
 879                                                   Class<?> hostClass) {
 880             MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
 881             mh = mh.asType(type);
 882             mh = new WrappedMember(mh, type, member, hostClass);
 883             return mh;
 884         }
 885 
 886         private static final MethodHandle MH_checkCallerClass;
 887         static {
 888             final Class<?> THIS_CLASS = BindCaller.class;
 889             assert(checkCallerClass(THIS_CLASS, THIS_CLASS));
 890             try {
 891                 MH_checkCallerClass = IMPL_LOOKUP
 892                     .findStatic(THIS_CLASS, "checkCallerClass",
 893                                 MethodType.methodType(boolean.class, Class.class, Class.class));
 894                 assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS));
 895             } catch (Throwable ex) {
 896                 throw new InternalError(ex);
 897             }
 898         }
 899 
 900         @CallerSensitive
 901         private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
 902             // This method is called via MH_checkCallerClass and so it's
 903             // correct to ask for the immediate caller here.
 904             Class<?> actual = Reflection.getCallerClass();
 905             if (actual != expected && actual != expected2)
 906                 throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
 907                                         +(expected == expected2 ? "" : ", or else "+expected2.getName()));
 908             return true;
 909         }
 910 
 911         private static final byte[] T_BYTES;
 912         static {
 913             final Object[] values = {null};
 914             AccessController.doPrivileged(new PrivilegedAction<Void>() {
 915                     public Void run() {
 916                         try {
 917                             Class<T> tClass = T.class;
 918                             String tName = tClass.getName();
 919                             String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class";
 920                             java.net.URLConnection uconn = tClass.getResource(tResource).openConnection();
 921                             int len = uconn.getContentLength();
 922                             byte[] bytes = new byte[len];
 923                             try (java.io.InputStream str = uconn.getInputStream()) {
 924                                 int nr = str.read(bytes);
 925                                 if (nr != len)  throw new java.io.IOException(tResource);
 926                             }
 927                             values[0] = bytes;
 928                         } catch (java.io.IOException ex) {
 929                             throw new InternalError(ex);
 930                         }
 931                         return null;
 932                     }
 933                 });
 934             T_BYTES = (byte[]) values[0];
 935         }
 936 
 937         // The following class is used as a template for Unsafe.defineAnonymousClass:
 938         private static class T {
 939             static void init() { }  // side effect: initializes this class
 940             static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
 941                 return vamh.invokeExact(args);
 942             }
 943         }
 944     }
 945 
 946 
 947     /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
 948     static class WrappedMember extends MethodHandle {
 949         private final MethodHandle target;
 950         private final MemberName member;
 951         private final Class<?> callerClass;
 952 
 953         private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
 954             super(type, reinvokerForm(target));
 955             this.target = target;
 956             this.member = member;
 957             this.callerClass = callerClass;
 958         }
 959 
 960         @Override
 961         MethodHandle reinvokerTarget() {
 962             return target;
 963         }
 964         @Override
 965         public MethodHandle asTypeUncached(MethodType newType) {
 966             // This MH is an alias for target, except for the MemberName
 967             // Drop the MemberName if there is any conversion.
 968             return asTypeCache = target.asType(newType);
 969         }
 970         @Override
 971         MemberName internalMemberName() {
 972             return member;
 973         }
 974         @Override
 975         Class<?> internalCallerClass() {
 976             return callerClass;
 977         }
 978         @Override
 979         boolean isInvokeSpecial() {
 980             return target.isInvokeSpecial();
 981         }
 982         @Override
 983         MethodHandle viewAsType(MethodType newType) {
 984             return new WrappedMember(target, newType, member, callerClass);
 985         }
 986     }
 987 
 988     static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
 989         if (member.equals(target.internalMemberName()))
 990             return target;
 991         return new WrappedMember(target, target.type(), member, null);
 992     }
 993 
 994 }