src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java
changeset 50735 2f2af62dfac7
parent 49935 2ace90aec488
child 52220 9c260a6b6471
equal deleted inserted replaced
50734:0828a0f6676b 50735:2f2af62dfac7
    56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
    56     private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
    57         super(mtype, form);
    57         super(mtype, form);
    58         if (!member.isResolved())  throw new InternalError();
    58         if (!member.isResolved())  throw new InternalError();
    59 
    59 
    60         if (member.getDeclaringClass().isInterface() &&
    60         if (member.getDeclaringClass().isInterface() &&
    61                 member.isMethod() && !member.isAbstract()) {
    61             member.getReferenceKind() == REF_invokeInterface &&
       
    62             member.isMethod() && !member.isAbstract()) {
    62             // Check for corner case: invokeinterface of Object method
    63             // Check for corner case: invokeinterface of Object method
    63             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
    64             MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
    64             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
    65             m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
    65             if (m != null && m.isPublic()) {
    66             if (m != null && m.isPublic()) {
    66                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
    67                 assert(member.getReferenceKind() == m.getReferenceKind());  // else this.form is wrong
    78             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
    79             if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor())
    79                 throw new InternalError(member.toString());
    80                 throw new InternalError(member.toString());
    80             mtype = mtype.insertParameterTypes(0, refc);
    81             mtype = mtype.insertParameterTypes(0, refc);
    81         }
    82         }
    82         if (!member.isField()) {
    83         if (!member.isField()) {
       
    84             // refKind reflects the original type of lookup via findSpecial or
       
    85             // findVirtual etc.
    83             switch (refKind) {
    86             switch (refKind) {
    84                 case REF_invokeSpecial: {
    87                 case REF_invokeSpecial: {
    85                     member = member.asSpecial();
    88                     member = member.asSpecial();
    86                     LambdaForm lform = preparedLambdaForm(member, callerClass);
    89                     // if caller is an interface we need to adapt to get the
    87                     Class<?> checkClass = refc;  // Class to use for receiver type check
    90                     // receiver check inserted
    88                     if (callerClass != null) {
    91                     if (callerClass == null) {
    89                         checkClass = callerClass;  // potentially strengthen to caller class
    92                         throw new InternalError("callerClass must not be null for REF_invokeSpecial");
    90                     }
    93                     }
    91                     return new Special(mtype, lform, member, checkClass);
    94                     LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface());
       
    95                     return new Special(mtype, lform, member, callerClass);
    92                 }
    96                 }
    93                 case REF_invokeInterface: {
    97                 case REF_invokeInterface: {
    94                     LambdaForm lform = preparedLambdaForm(member, callerClass);
    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);
    95                     return new Interface(mtype, lform, member, refc);
   102                     return new Interface(mtype, lform, member, refc);
    96                 }
   103                 }
    97                 default: {
   104                 default: {
    98                     LambdaForm lform = preparedLambdaForm(member, callerClass);
   105                     LambdaForm lform = preparedLambdaForm(member);
    99                     return new DirectMethodHandle(mtype, lform, member);
   106                     return new DirectMethodHandle(mtype, lform, member);
   100                 }
   107                 }
   101             }
   108             }
   102         } else {
   109         } else {
   103             LambdaForm lform = preparedFieldLambdaForm(member);
   110             LambdaForm lform = preparedFieldLambdaForm(member);
   163     /**
   170     /**
   164      * Create a LF which can invoke the given method.
   171      * Create a LF which can invoke the given method.
   165      * Cache and share this structure among all methods with
   172      * Cache and share this structure among all methods with
   166      * the same basicType and refKind.
   173      * the same basicType and refKind.
   167      */
   174      */
   168     private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) {
   175     private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) {
   169         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
   176         assert(m.isInvocable()) : m;  // call preparedFieldLambdaForm instead
   170         MethodType mtype = m.getInvocationType().basicType();
   177         MethodType mtype = m.getInvocationType().basicType();
   171         assert(!m.isMethodHandleInvoke()) : m;
   178         assert(!m.isMethodHandleInvoke()) : m;
   172         int which;
   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.
   173         switch (m.getReferenceKind()) {
   185         switch (m.getReferenceKind()) {
   174         case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
   186         case REF_invokeVirtual:    which = LF_INVVIRTUAL;    break;
   175         case REF_invokeStatic:     which = LF_INVSTATIC;     break;
   187         case REF_invokeStatic:     which = LF_INVSTATIC;     break;
   176         case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
   188         case REF_invokeSpecial:    which = LF_INVSPECIAL;    break;
   177         case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
   189         case REF_invokeInterface:  which = LF_INVINTERFACE;  break;
   181         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
   193         if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
   182             // precompute the barrier-free version:
   194             // precompute the barrier-free version:
   183             preparedLambdaForm(mtype, which);
   195             preparedLambdaForm(mtype, which);
   184             which = LF_INVSTATIC_INIT;
   196             which = LF_INVSTATIC_INIT;
   185         }
   197         }
   186         if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) {
   198         if (which == LF_INVSPECIAL && adaptToSpecialIfc) {
   187             which = LF_INVSPECIAL_IFC;
   199             which = LF_INVSPECIAL_IFC;
   188         }
   200         }
   189         LambdaForm lform = preparedLambdaForm(mtype, which);
   201         LambdaForm lform = preparedLambdaForm(mtype, which);
   190         maybeCompile(lform, m);
   202         maybeCompile(lform, m);
   191         assert(lform.methodType().dropParameterTypes(0, 1)
   203         assert(lform.methodType().dropParameterTypes(0, 1)
   193                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
   205                 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
   194         return lform;
   206         return lform;
   195     }
   207     }
   196 
   208 
   197     private static LambdaForm preparedLambdaForm(MemberName m) {
   209     private static LambdaForm preparedLambdaForm(MemberName m) {
   198         return preparedLambdaForm(m, null);
   210         return preparedLambdaForm(m, false);
   199     }
   211     }
   200 
   212 
   201     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
   213     private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
   202         LambdaForm lform = mtype.form().cachedLambdaForm(which);
   214         LambdaForm lform = mtype.form().cachedLambdaForm(which);
   203         if (lform != null)  return lform;
   215         if (lform != null)  return lform;