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