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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
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 }
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 }
|
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import java.util.Arrays;
29 import static java.lang.invoke.LambdaForm.*;
30 import static java.lang.invoke.LambdaForm.Kind.*;
31 import static java.lang.invoke.MethodHandleStatics.*;
32
33 /**
34 * A method handle whose invocation behavior is determined by a target.
35 * The delegating MH itself can hold extra "intentions" beyond the simple behavior.
36 * @author jrose
37 */
38 /*non-public*/
39 abstract class DelegatingMethodHandle extends MethodHandle {
40 protected DelegatingMethodHandle(MethodHandle target) {
41 this(target.type(), target);
42 }
43
44 protected DelegatingMethodHandle(MethodType type, MethodHandle target) {
45 super(type, chooseDelegatingForm(target));
46 }
47
48 protected DelegatingMethodHandle(MethodType type, LambdaForm form) {
49 super(type, form);
50 }
80 String internalProperties() {
81 return "\n& Class="+getClass().getSimpleName()+
82 "\n& Target="+getTarget().debugString();
83 }
84
85 @Override
86 BoundMethodHandle rebind() {
87 return getTarget().rebind();
88 }
89
90 private static LambdaForm chooseDelegatingForm(MethodHandle target) {
91 if (target instanceof SimpleMethodHandle)
92 return target.internalForm(); // no need for an indirection
93 return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
94 }
95
96 static LambdaForm makeReinvokerForm(MethodHandle target,
97 int whichCache,
98 Object constraint,
99 NamedFunction getTargetFn) {
100 // No pre-action needed.
101 return makeReinvokerForm(target, whichCache, constraint, null, true, getTargetFn, null);
102 }
103 /** Create a LF which simply reinvokes a target of the given basic type. */
104 static LambdaForm makeReinvokerForm(MethodHandle target,
105 int whichCache,
106 Object constraint,
107 String debugString,
108 boolean forceInline,
109 NamedFunction getTargetFn,
110 NamedFunction preActionFn) {
111 MethodType mtype = target.type().basicType();
112 Kind kind = whichKind(whichCache);
113 if (debugString == null) {
114 debugString = kind.defaultLambdaName;
115 }
116 boolean customized = (whichCache < 0 ||
117 mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY);
118 boolean hasPreAction = (preActionFn != null);
119 LambdaForm form;
120 if (!customized) {
121 form = mtype.form().cachedLambdaForm(whichCache);
122 if (form != null) return form;
123 }
124 final int THIS_DMH = 0;
125 final int ARG_BASE = 1;
126 final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
127 int nameCursor = ARG_LIMIT;
128 final int PRE_ACTION = hasPreAction ? nameCursor++ : -1;
129 final int NEXT_MH = customized ? -1 : nameCursor++;
130 final int REINVOKE = nameCursor++;
131 LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
132 assert(names.length == nameCursor);
133 names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
134 Object[] targetArgs;
135 if (hasPreAction) {
136 names[PRE_ACTION] = new LambdaForm.Name(preActionFn, names[THIS_DMH]);
137 }
138 if (customized) {
139 targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
140 names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself
141 } else {
142 names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]);
143 targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class);
144 targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH
145 names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs);
146 }
147 form = new LambdaForm(debugString, ARG_LIMIT, names, forceInline, kind);
148 if (!customized) {
149 form = mtype.form().setCachedLambdaForm(whichCache, form);
150 }
151 return form;
152 }
153
154 private static Kind whichKind(int whichCache) {
155 switch(whichCache) {
156 case MethodTypeForm.LF_REBIND: return BOUND_REINVOKER;
157 case MethodTypeForm.LF_DELEGATE: return DELEGATE;
158 default: return REINVOKER;
159 }
160 }
161
162 static final NamedFunction NF_getTarget;
163 static {
164 try {
165 NF_getTarget = new NamedFunction(DelegatingMethodHandle.class
166 .getDeclaredMethod("getTarget"));
167 } catch (ReflectiveOperationException ex) {
168 throw newInternalError(ex);
169 }
170 // The Holder class will contain pre-generated DelegatingMethodHandles resolved
171 // speculatively using MemberName.getFactory().resolveOrNull. However, that
172 // doesn't initialize the class, which subtly breaks inlining etc. By forcing
173 // initialization of the Holder class we avoid these issues.
174 UNSAFE.ensureClassInitialized(Holder.class);
175 }
176
177 /* Placeholder class for DelegatingMethodHandles generated ahead of time */
178 final class Holder {}
179 }
|