1 /*
   2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package impl.java.dyn;
  27 
  28 import java.dyn.MethodHandle;
  29 import java.dyn.MethodType;
  30 import java.lang.reflect.AccessibleObject;
  31 import java.lang.reflect.Field;
  32 import static impl.java.dyn.MethodHandleNatives.Constants.*;
  33 
  34 /**
  35  * The JVM interface for the method handles package is all here.
  36  * @author jrose
  37  */
  38 class MethodHandleNatives {
  39 
  40     private MethodHandleNatives() { } // static only
  41 
  42     /// MethodName support
  43 
  44     static native void init(MemberName self, Object ref);
  45     static native void expand(MemberName self);
  46     static native void resolve(MemberName self, Class<?> caller);
  47     static native int getMembers(Class<?> defc, String matchName, String matchSig,
  48             int matchFlags, Class<?> caller, int skip, MemberName[] results);
  49 
  50     /// MethodHandle support
  51 
  52     /** Initialize the method handle to adapt the call. */
  53     static native void init(AdapterMethodHandle self, MethodHandle target, int argnum);
  54     /** Initialize the method handle to call the correct method, directly. */
  55     static native void init(BoundMethodHandle self, Object target, int argnum);
  56     /** Initialize the method handle to call as if by an invoke* instruction. */
  57     static native void init(DirectMethodHandle self, Object ref, boolean doDispatch, Class<?> caller);
  58 
  59     /** Initialize a method type, once per form. */
  60     static native void init(MethodType self);
  61 
  62     /** Tell the JVM that we need to change the target of an invokedynamic. */
  63     static native void linkCallSite(CallSiteImpl site, MethodHandle target);
  64 
  65     /** Fetch the vmtarget field.
  66      *  It will be sanitized as necessary to avoid exposing non-Java references.
  67      *  This routine is for debugging and reflection.
  68      */
  69     static native Object getTarget(MethodHandle self, int format);
  70 
  71     /** Fetch the name of the handled method, if available.
  72      *  This routine is for debugging and reflection.
  73      */
  74     static MemberName getMethodName(MethodHandle self) {
  75         if (!JVM_SUPPORT)  return null;
  76         return (MemberName) getTarget(self, ETF_METHOD_NAME);
  77     }
  78 
  79     /** Fetch the reflective version of the handled method, if available.
  80      */
  81     static AccessibleObject getTargetMethod(MethodHandle self) {
  82         if (!JVM_SUPPORT)  return null;
  83         return (AccessibleObject) getTarget(self, ETF_REFLECT_METHOD);
  84     }
  85 
  86     /** Fetch the target of this method handle.
  87      *  If it directly targets a method, return a tuple of method info.
  88      *  The info is of the form new Object[]{defclass, name, sig, refclass}.
  89      *  If it is chained to another method handle, return that handle.
  90      */
  91     static Object getTargetInfo(MethodHandle self) {
  92         if (!JVM_SUPPORT)  return null;
  93         return getTarget(self, ETF_HANDLE_OR_METHOD_NAME);
  94     }
  95 
  96     static Object[] makeTarget(Class<?> defc, String name, String sig, int mods, Class<?> refc) {
  97         return new Object[] { defc, name, sig, mods, refc };
  98     }
  99 
 100     /** Fetch MH-related JVM parameter.
 101      *  which=0 retrieves MethodHandlePushLimit
 102      *  which=1 retrieves stack slot push size (in address units)
 103      */
 104     static native int getConstant(int which);
 105 
 106     /** True iff this HotSpot JVM has built-in support for method handles.
 107      * If false, some test cases might run, but functionality will be missing.
 108      */
 109     public static final boolean JVM_SUPPORT;
 110 
 111     /** Java copy of MethodHandlePushLimit in range 2..255. */
 112     static final int JVM_PUSH_LIMIT;
 113     /** JVM stack motion (in words) after one slot is pushed, usually -1.
 114      */
 115     static final int JVM_STACK_MOVE_UNIT;
 116 
 117     private static native void registerNatives();
 118     static {
 119         boolean JVM_SUPPORT_;
 120         int     JVM_PUSH_LIMIT_;
 121         int     JVM_STACK_MOVE_UNIT_;
 122         try {
 123             registerNatives();
 124             JVM_SUPPORT_ = true;
 125             JVM_PUSH_LIMIT_ = getConstant(Constants.GC_JVM_PUSH_LIMIT);
 126             JVM_STACK_MOVE_UNIT_ = getConstant(Constants.GC_JVM_STACK_MOVE_LIMIT);
 127             //sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
 128         } catch (UnsatisfiedLinkError ee) {
 129             // ignore; if we use init() methods later we'll see linkage errors
 130             JVM_SUPPORT_ = false;
 131             JVM_PUSH_LIMIT_ = 3;  // arbitrary
 132             JVM_STACK_MOVE_UNIT_ = -1;  // arbitrary
 133         }
 134         JVM_SUPPORT = JVM_SUPPORT_;
 135         JVM_PUSH_LIMIT = JVM_PUSH_LIMIT_;
 136         JVM_STACK_MOVE_UNIT = JVM_STACK_MOVE_UNIT_;
 137         if (!JVM_SUPPORT)
 138             System.out.println("Warning: Running with JVM_SUPPORT=false");
 139     }
 140 
 141     // All compile-time constants go here.
 142     // There is an opportunity to check them against the JVM's idea of them.
 143     static class Constants {
 144         Constants() { } // static only
 145         // MethodHandleImpl
 146         static final int // for getConstant
 147                 GC_JVM_PUSH_LIMIT = 0,
 148                 GC_JVM_STACK_MOVE_LIMIT = 1;
 149         static final int
 150                 ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
 151                 ETF_DIRECT_HANDLE         = 1, // ultimate method handle (will be a DMH, may be self)
 152                 ETF_METHOD_NAME           = 2, // ultimate method as MemberName
 153                 ETF_REFLECT_METHOD        = 3; // ultimate method as java.lang.reflect object (sans refClass)
 154 
 155         // MemberName
 156         // The JVM uses values of -2 and above for vtable indexes.
 157         // Field values are simple positive offsets.
 158         // Ref: src/share/vm/oops/methodOop.hpp
 159         // This value is negative enough to avoid such numbers,
 160         // but not too negative.
 161         static final int
 162                 MN_IS_METHOD           = 0x00010000, // method (not constructor)
 163                 MN_IS_CONSTRUCTOR      = 0x00020000, // constructor
 164                 MN_IS_FIELD            = 0x00040000, // field
 165                 MN_IS_TYPE             = 0x00080000, // nested type
 166                 MN_SEARCH_SUPERCLASSES = 0x00100000, // for MHN.getMembers
 167                 MN_SEARCH_INTERFACES   = 0x00200000, // for MHN.getMembers
 168                 VM_INDEX_UNINITIALIZED = -99;
 169 
 170         // AdapterMethodHandle
 171         /** Conversions recognized by the JVM.
 172          *  They must align with enum AdapterKind in vm/prims/methodHandles.hpp.
 173          */
 174         static final int
 175             RETYPE_ONLY      = 0x000, // no argument changes; straight retype
 176             CHECK_CAST       = 0x100, // ref-to-ref conversion; requires a Class argument
 177             PRIM_TO_PRIM     = 0x200, // converts from one primitive to another
 178             REF_TO_PRIM      = 0x300, // unboxes a wrapper to produce a primitive
 179             PRIM_TO_REF      = 0x400, // boxes a primitive into a wrapper (NYI)
 180             SWAP_ARGS        = 0x500, // swap arguments (vminfo is 2nd arg)
 181             ROT_ARGS         = 0x600, // rotate arguments (vminfo is displaced arg)
 182             DUP_ARGS         = 0x700, // duplicates one or more arguments (at TOS)
 183             DROP_ARGS        = 0x800, // remove one or more argument slots
 184             COLLECT_ARGS     = 0x900, // combine one or more arguments into a varargs (NYI)
 185             SPREAD_ARGS      = 0xA00, // expand in place a varargs array (of known size)
 186             FLYBY            = 0xB00, // operate first on reified argument list (NYI)
 187             RICOCHET         = 0xC00; // run an adapter chain on the return value (NYI)
 188         static final int
 189             CONV_OP_MASK     = 0xF00, // byte 3 contains the conversion op field
 190             CONV_VMINFO_MASK = 0x0FF, // LSB is reserved for JVM use
 191             CONV_VMINFO_SHIFT     =  0, // position of bits in CONV_VMINFO_MASK
 192             CONV_OP_SHIFT         =  8, // position of bits in CONV_OP_MASK
 193             CONV_DEST_TYPE_SHIFT  = 12, // byte 3 has the adapter BasicType (if needed)
 194             CONV_SRC_TYPE_SHIFT   = 16, // byte 2 has the source BasicType (if needed)
 195             CONV_STACK_MOVE_SHIFT = 20, // high 12 bits give signed SP change
 196             CONV_STACK_MOVE_MASK  = (1 << (32 - CONV_STACK_MOVE_SHIFT)) - 1;
 197 
 198         /**
 199          * Basic types as encoded in the JVM.  These code values are not
 200          * intended for use outside this class.  They are used as part of
 201          * a private interface between the JVM and this class.
 202          */
 203         static final int
 204             T_BOOLEAN  =  4,
 205             T_CHAR     =  5,
 206             T_FLOAT    =  6,
 207             T_DOUBLE   =  7,
 208             T_BYTE     =  8,
 209             T_SHORT    =  9,
 210             T_INT      = 10,
 211             T_LONG     = 11,
 212             T_OBJECT   = 12,
 213             //T_ARRAY    = 13
 214             T_VOID     = 14;
 215             //T_ADDRESS  = 15
 216     }
 217 
 218     private static native int getNamedCon(int which, Object[] name);
 219     static boolean verifyConstants() {
 220         Object[] box = { null };
 221         for (int i = 0; ; i++) {
 222             box[0] = null;
 223             int vmval = getNamedCon(i, box);
 224             if (box[0] == null)  break;
 225             String name = (String) box[0];
 226             try {
 227                 Field con = Constants.class.getDeclaredField(name);
 228                 int jval = con.getInt(null);
 229                 if (jval != vmval)
 230                     throw new InternalError(name+": JVM has "+vmval+" while Java has "+jval);
 231             } catch (Exception ex) {
 232                 throw new InternalError(name+": access failed, got "+ex);
 233             }
 234         }
 235         return true;
 236     }
 237     static {
 238         if (JVM_SUPPORT)  verifyConstants();
 239     }
 240 }