27
28 import java.util.Arrays;
29 import static java.lang.invoke.LambdaForm.*;
30 import static java.lang.invoke.MethodHandleStatics.*;
31
32 /**
33 * A method handle whose invocation behavior is determined by a target.
34 * The delegating MH itself can hold extra "intentions" beyond the simple behavior.
35 * @author jrose
36 */
37 /*non-public*/
38 abstract class DelegatingMethodHandle extends MethodHandle {
39 protected DelegatingMethodHandle(MethodHandle target) {
40 this(target.type(), target);
41 }
42
43 protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
44 super(type, chooseDelegatingForm(target));
45 }
46
47 /** Define this to extract the delegated target which supplies the invocation behavior. */
48 abstract protected MethodHandle getTarget();
49
50 @Override
51 abstract MethodHandle asTypeUncached(MethodType newType);
52
53 @Override
54 MemberName internalMemberName() {
55 return getTarget().internalMemberName();
56 }
57
58 @Override
59 boolean isInvokeSpecial() {
60 return getTarget().isInvokeSpecial();
61 }
62
63 @Override
64 Class<?> internalCallerClass() {
65 return getTarget().internalCallerClass();
66 }
71 throw newIllegalArgumentException("do not use this");
72 }
73
74 @Override
75 String internalProperties() {
76 return "\n& Class="+getClass().getSimpleName()+
77 "\n& Target="+getTarget().debugString();
78 }
79
80 @Override
81 BoundMethodHandle rebind() {
82 return getTarget().rebind();
83 }
84
85 private static LambdaForm chooseDelegatingForm(MethodHandle target) {
86 if (target instanceof SimpleMethodHandle)
87 return target.internalForm(); // no need for an indirection
88 return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
89 }
90
91 /** Create a LF which simply reinvokes a target of the given basic type. */
92 static LambdaForm makeReinvokerForm(MethodHandle target,
93 int whichCache,
94 Object constraint,
95 NamedFunction getTargetFn) {
96 MethodType mtype = target.type().basicType();
97 boolean customized = (whichCache < 0 ||
98 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
99 LambdaForm form;
100 if (!customized) {
101 form = mtype.form().cachedLambdaForm(whichCache);
102 if (form != null) return form;
103 }
104 final int THIS_DMH = 0;
105 final int ARG_BASE = 1;
106 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
107 int nameCursor = ARG_LIMIT;
108 final int NEXT_MH = customized ? -1 : nameCursor++;
109 final int REINVOKE = nameCursor++;
110 LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
111 assert(names.length == nameCursor);
112 names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
113 Object[] targetArgs;
114 if (customized) {
115 targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
116 names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself
117 } else {
118 names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
119 targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
120 targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH
121 names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
122 }
123 String debugString;
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) {
131 form = mtype.form().setCachedLambdaForm(whichCache, form);
132 }
133 return form;
134 }
135
136 private static final NamedFunction NF_getTarget;
137 static {
138 try {
139 NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
140 .getDeclaredMethod("getTarget"));
141 } catch (ReflectiveOperationException ex) {
142 throw newInternalError(ex);
143 }
144 }
145 }
|
27
28 import java.util.Arrays;
29 import static java.lang.invoke.LambdaForm.*;
30 import static java.lang.invoke.MethodHandleStatics.*;
31
32 /**
33 * A method handle whose invocation behavior is determined by a target.
34 * The delegating MH itself can hold extra "intentions" beyond the simple behavior.
35 * @author jrose
36 */
37 /*non-public*/
38 abstract class DelegatingMethodHandle extends MethodHandle {
39 protected DelegatingMethodHandle(MethodHandle target) {
40 this(target.type(), target);
41 }
42
43 protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
44 super(type, chooseDelegatingForm(target));
45 }
46
47 protected DelegatingMethodHandle(MethodType type, LambdaForm form) {
48 super(type, form);
49 }
50
51 /** Define this to extract the delegated target which supplies the invocation behavior. */
52 abstract protected MethodHandle getTarget();
53
54 @Override
55 abstract MethodHandle asTypeUncached(MethodType newType);
56
57 @Override
58 MemberName internalMemberName() {
59 return getTarget().internalMemberName();
60 }
61
62 @Override
63 boolean isInvokeSpecial() {
64 return getTarget().isInvokeSpecial();
65 }
66
67 @Override
68 Class<?> internalCallerClass() {
69 return getTarget().internalCallerClass();
70 }
75 throw newIllegalArgumentException("do not use this");
76 }
77
78 @Override
79 String internalProperties() {
80 return "\n& Class="+getClass().getSimpleName()+
81 "\n& Target="+getTarget().debugString();
82 }
83
84 @Override
85 BoundMethodHandle rebind() {
86 return getTarget().rebind();
87 }
88
89 private static LambdaForm chooseDelegatingForm(MethodHandle target) {
90 if (target instanceof SimpleMethodHandle)
91 return target.internalForm(); // no need for an indirection
92 return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
93 }
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 }
108 /** Create a LF which simply reinvokes a target of the given basic type. */
109 static LambdaForm makeReinvokerForm(MethodHandle target,
110 int whichCache,
111 Object constraint,
112 String debugString,
113 boolean forceInline,
114 NamedFunction getTargetFn,
115 NamedFunction preActionFn) {
116 MethodType mtype = target.type().basicType();
117 boolean customized = (whichCache < 0 ||
118 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
119 boolean hasPreAction = (preActionFn != null);
120 LambdaForm form;
121 if (!customized) {
122 form = mtype.form().cachedLambdaForm(whichCache);
123 if (form != null) return form;
124 }
125 final int THIS_DMH = 0;
126 final int ARG_BASE = 1;
127 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
128 int nameCursor = ARG_LIMIT;
129 final int PRE_ACTION = hasPreAction ? nameCursor++ : -1;
130 final int NEXT_MH = customized ? -1 : nameCursor++;
131 final int REINVOKE = nameCursor++;
132 LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
133 assert(names.length == nameCursor);
134 names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
135 Object[] targetArgs;
136 if (hasPreAction) {
137 names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]);
138 }
139 if (customized) {
140 targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
141 names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself
142 } else {
143 names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
144 targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
145 targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH
146 names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
147 }
148 form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline);
149 if (!customized) {
150 form = mtype.form().setCachedLambdaForm(whichCache, form);
151 }
152 return form;
153 }
154
155 static final NamedFunction NF_getTarget;
156 static {
157 try {
158 NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
159 .getDeclaredMethod("getTarget"));
160 } catch (ReflectiveOperationException ex) {
161 throw newInternalError(ex);
162 }
163 }
164 }
|