jdk/src/share/classes/sun/dyn/Invokers.java
changeset 8345 9e2483e6cfab
parent 7668 d4a77089c587
child 8346 3b891698c4ec
equal deleted inserted replaced
8126:c5df55701e91 8345:9e2483e6cfab
     1 /*
     1 /*
     2  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
     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.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    45 
    45 
    46     // generic (untyped) invoker for the outgoing call
    46     // generic (untyped) invoker for the outgoing call
    47     private /*lazy*/ MethodHandle genericInvoker;
    47     private /*lazy*/ MethodHandle genericInvoker;
    48 
    48 
    49     // generic (untyped) invoker for the outgoing call; accepts a single Object[]
    49     // generic (untyped) invoker for the outgoing call; accepts a single Object[]
    50     private final /*lazy*/ MethodHandle[] varargsInvokers;
    50     private final /*lazy*/ MethodHandle[] spreadInvokers;
    51 
    51 
    52     // invoker for an unbound callsite
    52     // invoker for an unbound callsite
    53     private /*lazy*/ MethodHandle uninitializedCallSite;
    53     private /*lazy*/ MethodHandle uninitializedCallSite;
    54 
    54 
    55     /** Compute and cache information common to all collecting adapters
    55     /** Compute and cache information common to all collecting adapters
    56      *  that implement members of the erasure-family of the given erased type.
    56      *  that implement members of the erasure-family of the given erased type.
    57      */
    57      */
    58     public Invokers(Access token, MethodType targetType) {
    58     /*non-public*/ Invokers(MethodType targetType) {
    59         Access.check(token);
       
    60         this.targetType = targetType;
    59         this.targetType = targetType;
    61         this.varargsInvokers = new MethodHandle[targetType.parameterCount()+1];
    60         this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
    62     }
    61     }
    63 
    62 
    64     public static MethodType invokerType(MethodType targetType) {
    63     public static MethodType invokerType(MethodType targetType) {
    65         return targetType.insertParameterTypes(0, MethodHandle.class);
    64         return targetType.insertParameterTypes(0, MethodHandle.class);
    66     }
    65     }
    67 
    66 
    68     public MethodHandle exactInvoker() {
    67     public MethodHandle exactInvoker() {
    69         MethodHandle invoker = exactInvoker;
    68         MethodHandle invoker = exactInvoker;
    70         if (invoker != null)  return invoker;
    69         if (invoker != null)  return invoker;
    71         try {
    70         try {
    72             invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invoke", targetType);
    71             invoker = MethodHandleImpl.IMPL_LOOKUP.findVirtual(MethodHandle.class, "invokeExact", targetType);
    73         } catch (NoAccessException ex) {
    72         } catch (NoAccessException ex) {
    74             throw new InternalError("JVM cannot find invoker for "+targetType);
    73             throw new InternalError("JVM cannot find invoker for "+targetType);
    75         }
    74         }
    76         assert(invokerType(targetType) == invoker.type());
    75         assert(invokerType(targetType) == invoker.type());
    77         exactInvoker = invoker;
    76         exactInvoker = invoker;
    99             invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
    98             invoker = MethodHandles.convertArguments(invoker1, invokerType(erasedType));
   100         erasedInvoker = invoker;
    99         erasedInvoker = invoker;
   101         return invoker;
   100         return invoker;
   102     }
   101     }
   103 
   102 
   104     public MethodHandle varargsInvoker(int objectArgCount) {
   103     public MethodHandle spreadInvoker(int objectArgCount) {
   105         MethodHandle vaInvoker = varargsInvokers[objectArgCount];
   104         MethodHandle vaInvoker = spreadInvokers[objectArgCount];
   106         if (vaInvoker != null)  return vaInvoker;
   105         if (vaInvoker != null)  return vaInvoker;
   107         MethodHandle gInvoker = genericInvoker();
   106         MethodHandle gInvoker = genericInvoker();
   108         MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
   107         MethodType vaType = MethodType.genericMethodType(objectArgCount, true);
   109         vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType));
   108         vaInvoker = MethodHandles.spreadArguments(gInvoker, invokerType(vaType));
   110         varargsInvokers[objectArgCount] = vaInvoker;
   109         spreadInvokers[objectArgCount] = vaInvoker;
   111         return vaInvoker;
   110         return vaInvoker;
   112     }
   111     }
   113 
   112 
   114     private static MethodHandle THROW_UCS = null;
   113     private static MethodHandle THROW_UCS = null;
   115 
   114 
   116     public MethodHandle uninitializedCallSite() {
   115     public MethodHandle uninitializedCallSite() {
   117         MethodHandle invoker = uninitializedCallSite;
   116         MethodHandle invoker = uninitializedCallSite;
   118         if (invoker != null)  return invoker;
   117         if (invoker != null)  return invoker;
   119         if (targetType.parameterCount() > 0) {
   118         if (targetType.parameterCount() > 0) {
   120             MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
   119             MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
   121             Invokers invokers0 = MethodTypeImpl.invokers(Access.TOKEN, type0);
   120             Invokers invokers0 = MethodTypeImpl.invokers(type0);
   122             invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
   121             invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
   123                                                   0, targetType.parameterList());
   122                                                   0, targetType.parameterList());
   124             assert(invoker.type().equals(targetType));
   123             assert(invoker.type().equals(targetType));
   125             uninitializedCallSite = invoker;
   124             uninitializedCallSite = invoker;
   126             return invoker;
   125             return invoker;