Home » openjdk-7 » java.lang.invoke » [javadoc | source]

    1   /*
    2    * Copyright (c) 2008, 2011, 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 sun.invoke.empty.Empty;
   29   import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
   30   
   31   /**
   32    * Construction and caching of often-used invokers.
   33    * @author jrose
   34    */
   35   class Invokers {
   36       // exact type (sans leading taget MH) for the outgoing call
   37       private final MethodType targetType;
   38   
   39       // exact invoker for the outgoing call
   40       private /*lazy*/ MethodHandle exactInvoker;
   41   
   42       // erased (partially untyped but with primitives) invoker for the outgoing call
   43       private /*lazy*/ MethodHandle erasedInvoker;
   44       /*lazy*/ MethodHandle erasedInvokerWithDrops;  // for InvokeGeneric
   45   
   46       // general invoker for the outgoing call
   47       private /*lazy*/ MethodHandle generalInvoker;
   48   
   49       // general invoker for the outgoing call, uses varargs
   50       private /*lazy*/ MethodHandle varargsInvoker;
   51   
   52       // general invoker for the outgoing call; accepts a trailing Object[]
   53       private final /*lazy*/ MethodHandle[] spreadInvokers;
   54   
   55       // invoker for an unbound callsite
   56       private /*lazy*/ MethodHandle uninitializedCallSite;
   57   
   58       /** Compute and cache information common to all collecting adapters
   59        *  that implement members of the erasure-family of the given erased type.
   60        */
   61       /*non-public*/ Invokers(MethodType targetType) {
   62           this.targetType = targetType;
   63           this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
   64       }
   65   
   66       /*non-public*/ static MethodType invokerType(MethodType targetType) {
   67           return targetType.insertParameterTypes(0, MethodHandle.class);
   68       }
   69   
   70       /*non-public*/ MethodHandle exactInvoker() {
   71           MethodHandle invoker = exactInvoker;
   72           if (invoker != null)  return invoker;
   73           invoker = lookupInvoker("invokeExact");
   74           exactInvoker = invoker;
   75           return invoker;
   76       }
   77   
   78       /*non-public*/ MethodHandle generalInvoker() {
   79           MethodHandle invoker = generalInvoker;
   80           if (invoker != null)  return invoker;
   81           invoker = lookupInvoker("invoke");
   82           generalInvoker = invoker;
   83           return invoker;
   84       }
   85   
   86       private MethodHandle lookupInvoker(String name) {
   87           MethodHandle invoker;
   88           try {
   89               invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, name, targetType);
   90           } catch (ReflectiveOperationException ex) {
   91               throw new InternalError("JVM cannot find invoker for "+targetType);
   92           }
   93           assert(invokerType(targetType) == invoker.type());
   94           assert(!invoker.isVarargsCollector());
   95           return invoker;
   96       }
   97   
   98       /*non-public*/ MethodHandle erasedInvoker() {
   99           MethodHandle xinvoker = exactInvoker();
  100           MethodHandle invoker = erasedInvoker;
  101           if (invoker != null)  return invoker;
  102           MethodType erasedType = targetType.erase();
  103           invoker = xinvoker.asType(invokerType(erasedType));
  104           erasedInvoker = invoker;
  105           return invoker;
  106       }
  107   
  108       /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
  109           MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
  110           if (vaInvoker != null)  return vaInvoker;
  111           MethodHandle gInvoker = generalInvoker();
  112           int spreadArgCount = targetType.parameterCount() - leadingArgCount;
  113           vaInvoker = gInvoker.asSpreader(Object[].class, spreadArgCount);
  114           spreadInvokers[leadingArgCount] = vaInvoker;
  115           return vaInvoker;
  116       }
  117   
  118       /*non-public*/ MethodHandle varargsInvoker() {
  119           MethodHandle vaInvoker = varargsInvoker;
  120           if (vaInvoker != null)  return vaInvoker;
  121           vaInvoker = spreadInvoker(0).asType(invokerType(MethodType.genericMethodType(0, true)));
  122           varargsInvoker = vaInvoker;
  123           return vaInvoker;
  124       }
  125   
  126       private static MethodHandle THROW_UCS = null;
  127   
  128       /*non-public*/ MethodHandle uninitializedCallSite() {
  129           MethodHandle invoker = uninitializedCallSite;
  130           if (invoker != null)  return invoker;
  131           if (targetType.parameterCount() > 0) {
  132               MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
  133               Invokers invokers0 = type0.invokers();
  134               invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
  135                                                     0, targetType.parameterList());
  136               assert(invoker.type().equals(targetType));
  137               uninitializedCallSite = invoker;
  138               return invoker;
  139           }
  140           if (THROW_UCS == null) {
  141               try {
  142                   THROW_UCS = IMPL_LOOKUP
  143                       .findStatic(CallSite.class, "uninitializedCallSite",
  144                                   MethodType.methodType(Empty.class));
  145               } catch (ReflectiveOperationException ex) {
  146                   throw new RuntimeException(ex);
  147               }
  148           }
  149           invoker = AdapterMethodHandle.makeRetypeRaw(targetType, THROW_UCS);
  150           assert(invoker.type().equals(targetType));
  151           uninitializedCallSite = invoker;
  152           return invoker;
  153       }
  154   
  155       public String toString() {
  156           return "Invokers"+targetType;
  157       }
  158   }

Home » openjdk-7 » java.lang.invoke » [javadoc | source]