< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page
rev 50075 : imported patch jep181-rev1


  41 import static java.lang.invoke.LambdaForm.Kind.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  45 import static java.lang.invoke.MethodTypeForm.*;
  46 
  47 /**
  48  * The flavor of method handle which implements a constant reference
  49  * to a class member.
  50  * @author jrose
  51  */
  52 class DirectMethodHandle extends MethodHandle {
  53     final MemberName member;
  54 
  55     // Constructors and factory methods in this class *must* be package scoped or private.
  56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
  57         super(mtype, form);
  58         if (!member.isResolved())  throw new InternalError();
  59 
  60         if (member.getDeclaringClass().isInterface() &&
  61                 member.isMethod() && !member.isAbstract()) {

  62             // Check for corner case: invokeinterface of Object method
  63             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  64             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
  65             if (m != null && m.isPublic()) {
  66                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  67                 member = m;
  68             }
  69         }
  70 
  71         this.member = member;
  72     }
  73 
  74     // Factory methods:
  75     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  76         MethodType mtype = member.getMethodOrFieldType();
  77         if (!member.isStatic()) {
  78             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  79                 throw new InternalError(member.toString());
  80             mtype = mtype.insertParameterTypes(0, refc);
  81         }
  82         if (!member.isField()) {


  83             switch (refKind) {
  84                 case REF_invokeSpecial: {
  85                     member = member.asSpecial();
  86                     LambdaForm lform = preparedLambdaForm(member, callerClass);
  87                     Class<?> checkClass = refc;  // Class to use for receiver type check
  88                     if (callerClass != null) {
  89                         checkClass = callerClass;  // potentially strengthen to caller class
  90                     }
  91                     return new Special(mtype, lform, member, checkClass);

  92                 }
  93                 case REF_invokeInterface: {
  94                     LambdaForm lform = preparedLambdaForm(member, callerClass);



  95                     return new Interface(mtype, lform, member, refc);
  96                 }
  97                 default: {
  98                     LambdaForm lform = preparedLambdaForm(member, callerClass);
  99                     return new DirectMethodHandle(mtype, lform, member);
 100                 }
 101             }
 102         } else {
 103             LambdaForm lform = preparedFieldLambdaForm(member);
 104             if (member.isStatic()) {
 105                 long offset = MethodHandleNatives.staticFieldOffset(member);
 106                 Object base = MethodHandleNatives.staticFieldBase(member);
 107                 return new StaticAccessor(mtype, lform, member, base, offset);
 108             } else {
 109                 long offset = MethodHandleNatives.objectFieldOffset(member);
 110                 assert(offset == (int)offset);
 111                 return new Accessor(mtype, lform, member, (int)offset);
 112             }
 113         }
 114     }
 115     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 116         byte refKind = member.getReferenceKind();
 117         if (refKind == REF_invokeSpecial)
 118             refKind =  REF_invokeVirtual;


 148 
 149     @Override
 150     String internalProperties() {
 151         return "\n& DMH.MN="+internalMemberName();
 152     }
 153 
 154     //// Implementation methods.
 155     @Override
 156     @ForceInline
 157     MemberName internalMemberName() {
 158         return member;
 159     }
 160 
 161     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 162 
 163     /**
 164      * Create a LF which can invoke the given method.
 165      * Cache and share this structure among all methods with
 166      * the same basicType and refKind.
 167      */
 168     private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
 169         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
 170         MethodType mtype = m.getInvocationType().basicType();
 171         assert(!m.isMethodHandleInvoke()) : m;
 172         int which;





 173         switch (m.getReferenceKind()) {
 174         case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
 175         case REF_invokeStatic:     which = LF_INVSTATIC;     break;
 176         case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
 177         case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
 178         case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
 179         default:  throw new InternalError(m.toString());
 180         }
 181         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
 182             // precompute the barrier-free version:
 183             preparedLambdaForm(mtype, which);
 184             which = LF_INVSTATIC_INIT;
 185         }
 186         if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
 187             which = LF_INVSPECIAL_IFC;
 188         }
 189         LambdaForm lform = preparedLambdaForm(mtype, which);
 190         maybeCompile(lform, m);
 191         assert(lform.methodType().dropParameterTypes(0, 1)
 192                 .equals(m.getInvocationType().basicType()))
 193                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 194         return lform;
 195     }
 196 
 197     private static LambdaForm preparedLambdaForm(MemberName m) {
 198         return preparedLambdaForm(m, null);
 199     }
 200 
 201     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
 202         LambdaForm lform = mtype.form().cachedLambdaForm(which);
 203         if (lform != null)  return lform;
 204         lform = makePreparedLambdaForm(mtype, which);
 205         return mtype.form().setCachedLambdaForm(which, lform);
 206     }
 207 
 208     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
 209         boolean needsInit = (which == LF_INVSTATIC_INIT);
 210         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
 211         boolean needsReceiverCheck = (which == LF_INVINTERFACE ||
 212                                       which == LF_INVSPECIAL_IFC);
 213 
 214         String linkerName;
 215         LambdaForm.Kind kind;
 216         switch (which) {
 217         case LF_INVVIRTUAL:    linkerName = "linkToVirtual";   kind = DIRECT_INVOKE_VIRTUAL;     break;
 218         case LF_INVSTATIC:     linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC;      break;




  41 import static java.lang.invoke.LambdaForm.Kind.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.*;
  43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
  44 import static java.lang.invoke.MethodHandleStatics.newInternalError;
  45 import static java.lang.invoke.MethodTypeForm.*;
  46 
  47 /**
  48  * The flavor of method handle which implements a constant reference
  49  * to a class member.
  50  * @author jrose
  51  */
  52 class DirectMethodHandle extends MethodHandle {
  53     final MemberName member;
  54 
  55     // Constructors and factory methods in this class *must* be package scoped or private.
  56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
  57         super(mtype, form);
  58         if (!member.isResolved())  throw new InternalError();
  59 
  60         if (member.getDeclaringClass().isInterface() &&
  61             member.getReferenceKind() == REF_invokeInterface &&
  62             member.isMethod() && !member.isAbstract()) {
  63             // Check for corner case: invokeinterface of Object method
  64             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
  65             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
  66             if (m != null && m.isPublic()) {
  67                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
  68                 member = m;
  69             }
  70         }
  71 
  72         this.member = member;
  73     }
  74 
  75     // Factory methods:
  76     static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) {
  77         MethodType mtype = member.getMethodOrFieldType();
  78         if (!member.isStatic()) {
  79             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
  80                 throw new InternalError(member.toString());
  81             mtype = mtype.insertParameterTypes(0, refc);
  82         }
  83         if (!member.isField()) {
  84             // refKind reflects the original type of lookup via findSpecial or
  85             // findVirtual etc.
  86             switch (refKind) {
  87                 case REF_invokeSpecial: {
  88                     member = member.asSpecial();
  89                     // if caller is an interface we need to adapt to get the
  90                     // receiver check inserted
  91                     if (callerClass == null) {
  92                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
  93                     }
  94                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
  95                     return new Special(mtype, lform, member, callerClass);
  96                 }
  97                 case REF_invokeInterface: {
  98                     // for interfaces we always need the receiver typecheck,
  99                     // so we always pass 'true' to ensure we adapt if needed
 100                     // to include the REF_invokeSpecial case
 101                     LambdaForm lform = preparedLambdaForm(member, true);
 102                     return new Interface(mtype, lform, member, refc);
 103                 }
 104                 default: {
 105                     LambdaForm lform = preparedLambdaForm(member);
 106                     return new DirectMethodHandle(mtype, lform, member);
 107                 }
 108             }
 109         } else {
 110             LambdaForm lform = preparedFieldLambdaForm(member);
 111             if (member.isStatic()) {
 112                 long offset = MethodHandleNatives.staticFieldOffset(member);
 113                 Object base = MethodHandleNatives.staticFieldBase(member);
 114                 return new StaticAccessor(mtype, lform, member, base, offset);
 115             } else {
 116                 long offset = MethodHandleNatives.objectFieldOffset(member);
 117                 assert(offset == (int)offset);
 118                 return new Accessor(mtype, lform, member, (int)offset);
 119             }
 120         }
 121     }
 122     static DirectMethodHandle make(Class<?> refc, MemberName member) {
 123         byte refKind = member.getReferenceKind();
 124         if (refKind == REF_invokeSpecial)
 125             refKind =  REF_invokeVirtual;


 155 
 156     @Override
 157     String internalProperties() {
 158         return "\n& DMH.MN="+internalMemberName();
 159     }
 160 
 161     //// Implementation methods.
 162     @Override
 163     @ForceInline
 164     MemberName internalMemberName() {
 165         return member;
 166     }
 167 
 168     private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
 169 
 170     /**
 171      * Create a LF which can invoke the given method.
 172      * Cache and share this structure among all methods with
 173      * the same basicType and refKind.
 174      */
 175     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
 176         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
 177         MethodType mtype = m.getInvocationType().basicType();
 178         assert(!m.isMethodHandleInvoke()) : m;
 179         int which;
 180         // MemberName.getReferenceKind represents the JVM optimized form of the call
 181         // as distinct from the "kind" passed to DMH.make which represents the original
 182         // bytecode-equivalent request. Specifically private/final methods that use a direct
 183         // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual
 184         // invocation mode may be invokevirtual or invokeinterface.
 185         switch (m.getReferenceKind()) {
 186         case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
 187         case REF_invokeStatic:     which = LF_INVSTATIC;     break;
 188         case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
 189         case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
 190         case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
 191         default:  throw new InternalError(m.toString());
 192         }
 193         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
 194             // precompute the barrier-free version:
 195             preparedLambdaForm(mtype, which);
 196             which = LF_INVSTATIC_INIT;
 197         }
 198         if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
 199             which = LF_INVSPECIAL_IFC;
 200         }
 201         LambdaForm lform = preparedLambdaForm(mtype, which);
 202         maybeCompile(lform, m);
 203         assert(lform.methodType().dropParameterTypes(0, 1)
 204                 .equals(m.getInvocationType().basicType()))
 205                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
 206         return lform;
 207     }
 208 
 209     private static LambdaForm preparedLambdaForm(MemberName m) {
 210         return preparedLambdaForm(m, false);
 211     }
 212 
 213     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
 214         LambdaForm lform = mtype.form().cachedLambdaForm(which);
 215         if (lform != null)  return lform;
 216         lform = makePreparedLambdaForm(mtype, which);
 217         return mtype.form().setCachedLambdaForm(which, lform);
 218     }
 219 
 220     static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
 221         boolean needsInit = (which == LF_INVSTATIC_INIT);
 222         boolean doesAlloc = (which == LF_NEWINVSPECIAL);
 223         boolean needsReceiverCheck = (which == LF_INVINTERFACE ||
 224                                       which == LF_INVSPECIAL_IFC);
 225 
 226         String linkerName;
 227         LambdaForm.Kind kind;
 228         switch (which) {
 229         case LF_INVVIRTUAL:    linkerName = "linkToVirtual";   kind = DIRECT_INVOKE_VIRTUAL;     break;
 230         case LF_INVSTATIC:     linkerName = "linkToStatic";    kind = DIRECT_INVOKE_STATIC;      break;


< prev index next >