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.util.Arrays;
  29 import sun.invoke.empty.Empty;
  30 import static java.lang.invoke.MethodHandleStatics.*;
  31 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  32 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
  33 import static java.lang.invoke.LambdaForm.*;
  34 
  35 /**
  36  * Construction and caching of often-used invokers.
  37  * @author jrose
  38  */
  39 class Invokers {
  40     // exact type (sans leading taget MH) for the outgoing call
  41     private final MethodType targetType;
  42 
  43     // FIXME: Get rid of the invokers that are not useful.
  44 
  45     // exact invoker for the outgoing call
  46     private /*lazy*/ MethodHandle exactInvoker;
  47     private /*lazy*/ MethodHandle basicInvoker;  // invokeBasic (unchecked exact)
  48 
  49     // erased (partially untyped but with primitives) invoker for the outgoing call
  50     // FIXME: get rid of
  51     private /*lazy*/ MethodHandle erasedInvoker;
  52     // FIXME: get rid of
  53     /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
  54 
  55     // general invoker for the outgoing call
  56     private /*lazy*/ MethodHandle generalInvoker;
  57 
  58     // general invoker for the outgoing call, uses varargs
  59     private /*lazy*/ MethodHandle varargsInvoker;
  60 
  61     // general invoker for the outgoing call; accepts a trailing Object[]
  62     private final /*lazy*/ MethodHandle[] spreadInvokers;
  63 
  64     // invoker for an unbound callsite
  65     private /*lazy*/ MethodHandle uninitializedCallSite;
  66 
  67     /** Compute and cache information common to all collecting adapters
  68      *  that implement members of the erasure-family of the given erased type.
  69      */
  70     /*non-public*/ Invokers(MethodType targetType) {
  71         this.targetType = targetType;
  72         this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
  73     }
  74 
  75     /*non-public*/ MethodHandle exactInvoker() {
  76         MethodHandle invoker = exactInvoker;
  77         if (invoker != null)  return invoker;
  78         invoker = makeExactOrGeneralInvoker(true);
  79         exactInvoker = invoker;
  80         return invoker;
  81     }
  82 
  83     /*non-public*/ MethodHandle generalInvoker() {
  84         MethodHandle invoker = generalInvoker;
  85         if (invoker != null)  return invoker;
  86         invoker = makeExactOrGeneralInvoker(false);
  87         generalInvoker = invoker;
  88         return invoker;
  89     }
  90 
  91     private MethodHandle makeExactOrGeneralInvoker(boolean isExact) {
  92         MethodType mtype = targetType;
  93         MethodType invokerType = mtype.invokerType();
  94         int which = (isExact ? MethodTypeForm.LF_EX_INVOKER : MethodTypeForm.LF_GEN_INVOKER);
  95         LambdaForm lform = invokeHandleForm(mtype, false, which);
  96         MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
  97         String whichName = (isExact ? "invokeExact" : "invoke");
  98         invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype));
  99         assert(checkInvoker(invoker));
 100         maybeCompileToBytecode(invoker);
 101         return invoker;
 102     }
 103 
 104     /** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
 105     private void maybeCompileToBytecode(MethodHandle invoker) {
 106         final int EAGER_COMPILE_ARITY_LIMIT = 10;
 107         if (targetType == targetType.erase() &&
 108             targetType.parameterCount() < EAGER_COMPILE_ARITY_LIMIT) {
 109             invoker.form.compileToBytecode();
 110         }
 111     }
 112 
 113     /*non-public*/ MethodHandle basicInvoker() {
 114         MethodHandle invoker = basicInvoker;
 115         if (invoker != null)  return invoker;
 116         MethodType basicType = targetType.basicType();
 117         if (basicType != targetType) {
 118             // double cache; not used significantly
 119             return basicInvoker = basicType.invokers().basicInvoker();
 120         }
 121         MemberName method = invokeBasicMethod(basicType);
 122         invoker = DirectMethodHandle.make(method);
 123         assert(checkInvoker(invoker));
 124         basicInvoker = invoker;
 125         return invoker;
 126     }
 127 
 128     // This next one is called from LambdaForm.NamedFunction.<init>.
 129     /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
 130         assert(basicType == basicType.basicType());
 131         try {
 132             //Lookup.findVirtual(MethodHandle.class, name, type);
 133             return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
 134         } catch (ReflectiveOperationException ex) {
 135             throw newInternalError("JVM cannot find invoker for "+basicType, ex);
 136         }
 137     }
 138 
 139     private boolean checkInvoker(MethodHandle invoker) {
 140         assert(targetType.invokerType().equals(invoker.type()))
 141                 : java.util.Arrays.asList(targetType, targetType.invokerType(), invoker);
 142         assert(invoker.internalMemberName() == null ||
 143                invoker.internalMemberName().getMethodType().equals(targetType));
 144         assert(!invoker.isVarargsCollector());
 145         return true;
 146     }
 147 
 148     // FIXME: get rid of
 149     /*non-public*/ MethodHandle erasedInvoker() {
 150         MethodHandle xinvoker = exactInvoker();
 151         MethodHandle invoker = erasedInvoker;
 152         if (invoker != null)  return invoker;
 153         MethodType erasedType = targetType.erase();
 154         invoker = xinvoker.asType(erasedType.invokerType());
 155         erasedInvoker = invoker;
 156         return invoker;
 157     }
 158 
 159     /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
 160         MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
 161         if (vaInvoker != null)  return vaInvoker;
 162         int spreadArgCount = targetType.parameterCount() - leadingArgCount;
 163         MethodType spreadInvokerType = targetType
 164             .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class);
 165         if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
 166             // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a)
 167             // where ginvoker.invoke(mh, a*) => mh.invoke(a*).
 168             MethodHandle genInvoker = generalInvoker();
 169             vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount);
 170         } else {
 171             // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]).
 172             // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
 173             // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
 174             MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType);
 175             MethodHandle makeSpreader;
 176             try {
 177                 makeSpreader = IMPL_LOOKUP
 178                     .findVirtual(MethodHandle.class, "asSpreader",
 179                         MethodType.methodType(MethodHandle.class, Class.class, int.class));
 180             } catch (ReflectiveOperationException ex) {
 181                 throw newInternalError(ex);
 182             }
 183             makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount);
 184             vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
 185         }
 186         assert(vaInvoker.type().equals(spreadInvokerType.invokerType()));
 187         maybeCompileToBytecode(vaInvoker);
 188         spreadInvokers[leadingArgCount] = vaInvoker;
 189         return vaInvoker;
 190     }
 191 
 192     /*non-public*/ MethodHandle varargsInvoker() {
 193         MethodHandle vaInvoker = varargsInvoker;
 194         if (vaInvoker != null)  return vaInvoker;
 195         vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType());
 196         varargsInvoker = vaInvoker;
 197         return vaInvoker;
 198     }
 199 
 200     private static MethodHandle THROW_UCS = null;
 201 
 202     /*non-public*/ MethodHandle uninitializedCallSite() {
 203         MethodHandle invoker = uninitializedCallSite;
 204         if (invoker != null)  return invoker;
 205         if (targetType.parameterCount() > 0) {
 206             MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
 207             Invokers invokers0 = type0.invokers();
 208             invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
 209                                                   0, targetType.parameterList());
 210             assert(invoker.type().equals(targetType));
 211             uninitializedCallSite = invoker;
 212             return invoker;
 213         }
 214         invoker = THROW_UCS;
 215         if (invoker == null) {
 216             try {
 217                 THROW_UCS = invoker = IMPL_LOOKUP
 218                     .findStatic(CallSite.class, "uninitializedCallSite",
 219                                 MethodType.methodType(Empty.class));
 220             } catch (ReflectiveOperationException ex) {
 221                 throw newInternalError(ex);
 222             }
 223         }
 224         invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
 225         invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
 226         assert(invoker.type().equals(targetType));
 227         uninitializedCallSite = invoker;
 228         return invoker;
 229     }
 230 
 231     public String toString() {
 232         return "Invokers"+targetType;
 233     }
 234 
 235     static MemberName methodHandleInvokeLinkerMethod(String name,
 236                                                      MethodType mtype,
 237                                                      Object[] appendixResult) {
 238         int which;
 239         switch (name) {
 240         case "invokeExact":  which = MethodTypeForm.LF_EX_LINKER; break;
 241         case "invoke":       which = MethodTypeForm.LF_GEN_LINKER; break;
 242         default:             throw new InternalError("not invoker: "+name);
 243         }
 244         LambdaForm lform;
 245         if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
 246             lform = invokeHandleForm(mtype, false, which);
 247             appendixResult[0] = mtype;
 248         } else {
 249             lform = invokeHandleForm(mtype, true, which);
 250         }
 251         return lform.vmentry;
 252     }
 253 
 254     // argument count to account for trailing "appendix value" (typically the mtype)
 255     private static final int MH_LINKER_ARG_APPENDED = 1;
 256 
 257     /** Returns an adapter for invokeExact or generic invoke, as a MH or constant pool linker.
 258      * If !customized, caller is responsible for supplying, during adapter execution,
 259      * a copy of the exact mtype.  This is because the adapter might be generalized to
 260      * a basic type.
 261      * @param mtype the caller's method type (either basic or full-custom)
 262      * @param customized whether to use a trailing appendix argument (to carry the mtype)
 263      * @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
 264      *                          0x02 whether it is for invokeExact or generic invoke
 265      */
 266     private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
 267         boolean isCached;
 268         if (!customized) {
 269             mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
 270             isCached = true;
 271         } else {
 272             isCached = false;  // maybe cache if mtype == mtype.basicType()
 273         }
 274         boolean isLinker, isGeneric;
 275         String debugName;
 276         switch (which) {
 277         case MethodTypeForm.LF_EX_LINKER:   isLinker = true;  isGeneric = false; debugName = "invokeExact_MT"; break;
 278         case MethodTypeForm.LF_EX_INVOKER:  isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
 279         case MethodTypeForm.LF_GEN_LINKER:  isLinker = true;  isGeneric = true;  debugName = "invoke_MT"; break;
 280         case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true;  debugName = "invoker"; break;
 281         default: throw new InternalError();
 282         }
 283         LambdaForm lform;
 284         if (isCached) {
 285             lform = mtype.form().cachedLambdaForm(which);
 286             if (lform != null)  return lform;
 287         }
 288         // exactInvokerForm (Object,Object)Object
 289         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
 290         final int THIS_MH      = 0;
 291         final int CALL_MH      = THIS_MH + (isLinker ? 0 : 1);
 292         final int ARG_BASE     = CALL_MH + 1;
 293         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
 294         final int INARG_LIMIT  = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
 295         int nameCursor = OUTARG_LIMIT;
 296         final int MTYPE_ARG    = customized ? -1 : nameCursor++;  // might be last in-argument
 297         final int CHECK_TYPE   = nameCursor++;
 298         final int LINKER_CALL  = nameCursor++;
 299         MethodType invokerFormType = mtype.invokerType();
 300         if (isLinker) {
 301             if (!customized)
 302                 invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
 303         } else {
 304             invokerFormType = invokerFormType.invokerType();
 305         }
 306         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
 307         assert(names.length == nameCursor)
 308                 : Arrays.asList(mtype, customized, which, nameCursor, names.length);
 309         if (MTYPE_ARG >= INARG_LIMIT) {
 310             assert(names[MTYPE_ARG] == null);
 311             NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
 312             names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
 313             // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
 314         }
 315 
 316         // Make the final call.  If isGeneric, then prepend the result of type checking.
 317         MethodType outCallType = mtype.basicType();
 318         Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
 319         Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
 320         if (!isGeneric) {
 321             names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
 322             // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
 323         } else {
 324             names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
 325             // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
 326             outArgs[0] = names[CHECK_TYPE];
 327         }
 328         names[LINKER_CALL] = new Name(outCallType, outArgs);
 329         lform = new LambdaForm(debugName, INARG_LIMIT, names);
 330         if (isLinker)
 331             lform.compileToBytecode();  // JVM needs a real methodOop
 332         if (isCached)
 333             lform = mtype.form().setCachedLambdaForm(which, lform);
 334         return lform;
 335     }
 336 
 337     /*non-public*/ static
 338     WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
 339         // FIXME: merge with JVM logic for throwing WMTE
 340         return new WrongMethodTypeException("expected "+expected+" but found "+actual);
 341     }
 342 
 343     /** Static definition of MethodHandle.invokeExact checking code. */
 344     /*non-public*/ static
 345     @ForceInline
 346     void checkExactType(Object mhObj, Object expectedObj) {
 347         MethodHandle mh = (MethodHandle) mhObj;
 348         MethodType expected = (MethodType) expectedObj;
 349         MethodType actual = mh.type();
 350         if (actual != expected)
 351             throw newWrongMethodTypeException(expected, actual);
 352     }
 353 
 354     /** Static definition of MethodHandle.invokeGeneric checking code.
 355      * Directly returns the type-adjusted MH to invoke, as follows:
 356      * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
 357      */
 358     /*non-public*/ static
 359     @ForceInline
 360     Object checkGenericType(Object mhObj, Object expectedObj) {
 361         MethodHandle mh = (MethodHandle) mhObj;
 362         MethodType expected = (MethodType) expectedObj;
 363         if (mh.type() == expected)  return mh;
 364         MethodHandle atc = mh.asTypeCache;
 365         if (atc != null && atc.type() == expected)  return atc;
 366         return mh.asType(expected);
 367         /* Maybe add more paths here.  Possible optimizations:
 368          * for (R)MH.invoke(a*),
 369          * let MT0 = TYPEOF(a*:R), MT1 = MH.type
 370          *
 371          * if MT0==MT1 or MT1 can be safely called by MT0
 372          *  => MH.invokeBasic(a*)
 373          * if MT1 can be safely called by MT0[R := Object]
 374          *  => MH.invokeBasic(a*) & checkcast(R)
 375          * if MT1 can be safely called by MT0[* := Object]
 376          *  => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
 377          * if a big adapter BA can be pulled out of (MT0,MT1)
 378          *  => BA.invokeBasic(MT0,MH,a*)
 379          * if a local adapter LA can cached on static CS0 = new GICS(MT0)
 380          *  => CS0.LA.invokeBasic(MH,a*)
 381          * else
 382          *  => MH.asType(MT0).invokeBasic(A*)
 383          */
 384     }
 385 
 386     static MemberName linkToCallSiteMethod(MethodType mtype) {
 387         LambdaForm lform = callSiteForm(mtype, false);
 388         return lform.vmentry;
 389     }
 390 
 391     static MemberName linkToTargetMethod(MethodType mtype) {
 392         LambdaForm lform = callSiteForm(mtype, true);
 393         return lform.vmentry;
 394     }
 395 
 396     // skipCallSite is true if we are optimizing a ConstantCallSite
 397     private static LambdaForm callSiteForm(MethodType mtype, boolean skipCallSite) {
 398         mtype = mtype.basicType();  // normalize Z to I, String to Object, etc.
 399         final int which = (skipCallSite ? MethodTypeForm.LF_MH_LINKER : MethodTypeForm.LF_CS_LINKER);
 400         LambdaForm lform = mtype.form().cachedLambdaForm(which);
 401         if (lform != null)  return lform;
 402         // exactInvokerForm (Object,Object)Object
 403         //   link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
 404         final int ARG_BASE     = 0;
 405         final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
 406         final int INARG_LIMIT  = OUTARG_LIMIT + 1;
 407         int nameCursor = OUTARG_LIMIT;
 408         final int APPENDIX_ARG = nameCursor++;  // the last in-argument
 409         final int CSITE_ARG    = skipCallSite ? -1 : APPENDIX_ARG;
 410         final int CALL_MH      = skipCallSite ? APPENDIX_ARG : nameCursor++;  // result of getTarget
 411         final int LINKER_CALL  = nameCursor++;
 412         MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
 413         Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
 414         assert(names.length == nameCursor);
 415         assert(names[APPENDIX_ARG] != null);
 416         if (!skipCallSite)
 417             names[CALL_MH] = new Name(NF_getCallSiteTarget, names[CSITE_ARG]);
 418         // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
 419         final int PREPEND_MH = 0, PREPEND_COUNT = 1;
 420         Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
 421         // prepend MH argument:
 422         System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
 423         outArgs[PREPEND_MH] = names[CALL_MH];
 424         names[LINKER_CALL] = new Name(mtype, outArgs);
 425         lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
 426         lform.compileToBytecode();  // JVM needs a real methodOop
 427         lform = mtype.form().setCachedLambdaForm(which, lform);
 428         return lform;
 429     }
 430 
 431     /** Static definition of MethodHandle.invokeGeneric checking code. */
 432     /*non-public*/ static
 433     @ForceInline
 434     Object getCallSiteTarget(Object site) {
 435         return ((CallSite)site).getTarget();
 436     }
 437 
 438     // Local constant functions:
 439     private static final NamedFunction NF_checkExactType;
 440     private static final NamedFunction NF_checkGenericType;
 441     private static final NamedFunction NF_asType;
 442     private static final NamedFunction NF_getCallSiteTarget;
 443     static {
 444         try {
 445             NF_checkExactType = new NamedFunction(Invokers.class
 446                     .getDeclaredMethod("checkExactType", Object.class, Object.class));
 447             NF_checkGenericType = new NamedFunction(Invokers.class
 448                     .getDeclaredMethod("checkGenericType", Object.class, Object.class));
 449             NF_asType = new NamedFunction(MethodHandle.class
 450                     .getDeclaredMethod("asType", MethodType.class));
 451             NF_getCallSiteTarget = new NamedFunction(Invokers.class
 452                     .getDeclaredMethod("getCallSiteTarget", Object.class));
 453             NF_checkExactType.resolve();
 454             NF_checkGenericType.resolve();
 455             NF_getCallSiteTarget.resolve();
 456             // bound
 457         } catch (ReflectiveOperationException ex) {
 458             throw newInternalError(ex);
 459         }
 460     }
 461 
 462 }