jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java
changeset 27295 8ed31033bf48
parent 26479 a60a19ec5ce5
child 32649 2ee9017c7597
equal deleted inserted replaced
27294:dfd89723bd6f 27295:8ed31033bf48
    42 
    42 
    43     protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
    43     protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
    44         super(type, chooseDelegatingForm(target));
    44         super(type, chooseDelegatingForm(target));
    45     }
    45     }
    46 
    46 
       
    47     protected DelegatingMethodHandle(MethodType type, LambdaForm form) {
       
    48         super(type, form);
       
    49     }
       
    50 
    47     /** Define this to extract the delegated target which supplies the invocation behavior. */
    51     /** Define this to extract the delegated target which supplies the invocation behavior. */
    48     abstract protected MethodHandle getTarget();
    52     abstract protected MethodHandle getTarget();
    49 
    53 
    50     @Override
    54     @Override
    51     abstract MethodHandle asTypeUncached(MethodType newType);
    55     abstract MethodHandle asTypeUncached(MethodType newType);
    86         if (target instanceof SimpleMethodHandle)
    90         if (target instanceof SimpleMethodHandle)
    87             return target.internalForm();  // no need for an indirection
    91             return target.internalForm();  // no need for an indirection
    88         return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
    92         return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
    89     }
    93     }
    90 
    94 
       
    95     static LambdaForm makeReinvokerForm(MethodHandle target,
       
    96                                         int whichCache,
       
    97                                         Object constraint,
       
    98                                         NamedFunction getTargetFn) {
       
    99         String debugString;
       
   100         switch(whichCache) {
       
   101             case MethodTypeForm.LF_REBIND:            debugString = "BMH.reinvoke";      break;
       
   102             case MethodTypeForm.LF_DELEGATE:          debugString = "MH.delegate";       break;
       
   103             default:                                  debugString = "MH.reinvoke";       break;
       
   104         }
       
   105         // No pre-action needed.
       
   106         return makeReinvokerForm(target, whichCache, constraint, debugString, true, getTargetFn, null);
       
   107     }
    91     /** Create a LF which simply reinvokes a target of the given basic type. */
   108     /** Create a LF which simply reinvokes a target of the given basic type. */
    92     static LambdaForm makeReinvokerForm(MethodHandle target,
   109     static LambdaForm makeReinvokerForm(MethodHandle target,
    93                                         int whichCache,
   110                                         int whichCache,
    94                                         Object constraint,
   111                                         Object constraint,
    95                                         NamedFunction getTargetFn) {
   112                                         String debugString,
       
   113                                         boolean forceInline,
       
   114                                         NamedFunction getTargetFn,
       
   115                                         NamedFunction preActionFn) {
    96         MethodType mtype = target.type().basicType();
   116         MethodType mtype = target.type().basicType();
    97         boolean customized = (whichCache < 0 ||
   117         boolean customized = (whichCache < 0 ||
    98                 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
   118                 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
       
   119         boolean hasPreAction = (preActionFn != null);
    99         LambdaForm form;
   120         LambdaForm form;
   100         if (!customized) {
   121         if (!customized) {
   101             form = mtype.form().cachedLambdaForm(whichCache);
   122             form = mtype.form().cachedLambdaForm(whichCache);
   102             if (form != null)  return form;
   123             if (form != null)  return form;
   103         }
   124         }
   104         final int THIS_DMH    = 0;
   125         final int THIS_DMH    = 0;
   105         final int ARG_BASE    = 1;
   126         final int ARG_BASE    = 1;
   106         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
   127         final int ARG_LIMIT   = ARG_BASE + mtype.parameterCount();
   107         int nameCursor = ARG_LIMIT;
   128         int nameCursor = ARG_LIMIT;
       
   129         final int PRE_ACTION   = hasPreAction ? nameCursor++ : -1;
   108         final int NEXT_MH     = customized ? -1 : nameCursor++;
   130         final int NEXT_MH     = customized ? -1 : nameCursor++;
   109         final int REINVOKE    = nameCursor++;
   131         final int REINVOKE    = nameCursor++;
   110         LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
   132         LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
   111         assert(names.length == nameCursor);
   133         assert(names.length == nameCursor);
   112         names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
   134         names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
   113         Object[] targetArgs;
   135         Object[] targetArgs;
       
   136         if (hasPreAction) {
       
   137             names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]);
       
   138         }
   114         if (customized) {
   139         if (customized) {
   115             targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
   140             targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
   116             names[REINVOKE] = new LambdaForm.Name(target, targetArgs);  // the invoker is the target itself
   141             names[REINVOKE] = new LambdaForm.Name(target, targetArgs);  // the invoker is the target itself
   117         } else {
   142         } else {
   118             names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
   143             names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
   119             targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
   144             targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
   120             targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
   145             targetArgs[0] = names[NEXT_MH];  // overwrite this MH with next MH
   121             names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
   146             names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
   122         }
   147         }
   123         String debugString;
   148         form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline);
   124         switch(whichCache) {
       
   125             case MethodTypeForm.LF_REBIND:   debugString = "BMH.reinvoke"; break;
       
   126             case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate";  break;
       
   127             default:                         debugString = "MH.reinvoke";  break;
       
   128         }
       
   129         form = new LambdaForm(debugString, ARG_LIMIT, names);
       
   130         if (!customized) {
   149         if (!customized) {
   131             form = mtype.form().setCachedLambdaForm(whichCache, form);
   150             form = mtype.form().setCachedLambdaForm(whichCache, form);
   132         }
   151         }
   133         return form;
   152         return form;
   134     }
   153     }
   135 
   154 
   136     private static final NamedFunction NF_getTarget;
   155     static final NamedFunction NF_getTarget;
   137     static {
   156     static {
   138         try {
   157         try {
   139             NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
   158             NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
   140                                              .getDeclaredMethod("getTarget"));
   159                                              .getDeclaredMethod("getTarget"));
   141         } catch (ReflectiveOperationException ex) {
   160         } catch (ReflectiveOperationException ex) {