85 abstract
86 public class CallSite {
87 static { MethodHandleImpl.initStatics(); }
88
89 // The actual payload of this call site:
90 /*package-private*/
91 MethodHandle target; // Note: This field is known to the JVM. Do not change.
92
93 /**
94 * Make a blank call site object with the given method type.
95 * An initial target method is supplied which will throw
96 * an {@link IllegalStateException} if called.
97 * <p>
98 * Before this {@code CallSite} object is returned from a bootstrap method,
99 * it is usually provided with a more useful target method,
100 * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
101 * @throws NullPointerException if the proposed type is null
102 */
103 /*package-private*/
104 CallSite(MethodType type) {
105 target = type.invokers().uninitializedCallSite();
106 }
107
108 /**
109 * Make a call site object equipped with an initial target method handle.
110 * @param target the method handle which will be the initial target of the call site
111 * @throws NullPointerException if the proposed target is null
112 */
113 /*package-private*/
114 CallSite(MethodHandle target) {
115 target.type(); // null check
116 this.target = target;
117 }
118
119 /**
120 * Make a call site object equipped with an initial target method handle.
121 * @param targetType the desired type of the call site
122 * @param createTargetHook a hook which will bind the call site to the target method handle
123 * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
124 * or if the target returned by the hook is not of the given {@code targetType}
125 * @throws NullPointerException if the hook returns a null value
200 * <p>
201 * This method is equivalent to the following code:
202 * <blockquote><pre>{@code
203 * MethodHandle getTarget, invoker, result;
204 * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
205 * invoker = MethodHandles.exactInvoker(this.type());
206 * result = MethodHandles.foldArguments(invoker, getTarget)
207 * }</pre></blockquote>
208 *
209 * @return a method handle which always invokes this call site's current target
210 */
211 public abstract MethodHandle dynamicInvoker();
212
213 /*non-public*/ MethodHandle makeDynamicInvoker() {
214 MethodHandle getTarget = GET_TARGET.bindReceiver(this);
215 MethodHandle invoker = MethodHandles.exactInvoker(this.type());
216 return MethodHandles.foldArguments(invoker, getTarget);
217 }
218
219 private static final MethodHandle GET_TARGET;
220 static {
221 try {
222 GET_TARGET = IMPL_LOOKUP.
223 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
224 } catch (ReflectiveOperationException e) {
225 throw newInternalError(e);
226 }
227 }
228
229 /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
230 /*package-private*/
231 static Empty uninitializedCallSite() {
232 throw new IllegalStateException("uninitialized call site");
233 }
234
235 // unsafe stuff:
236 private static final long TARGET_OFFSET;
237 static {
238 try {
239 TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
240 } catch (Exception ex) { throw new Error(ex); }
241 }
242
243 /*package-private*/
244 void setTargetNormal(MethodHandle newTarget) {
245 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
246 }
247 /*package-private*/
248 MethodHandle getTargetVolatile() {
249 return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
250 }
251 /*package-private*/
252 void setTargetVolatile(MethodHandle newTarget) {
253 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
254 }
|
85 abstract
86 public class CallSite {
87 static { MethodHandleImpl.initStatics(); }
88
89 // The actual payload of this call site:
90 /*package-private*/
91 MethodHandle target; // Note: This field is known to the JVM. Do not change.
92
93 /**
94 * Make a blank call site object with the given method type.
95 * An initial target method is supplied which will throw
96 * an {@link IllegalStateException} if called.
97 * <p>
98 * Before this {@code CallSite} object is returned from a bootstrap method,
99 * it is usually provided with a more useful target method,
100 * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
101 * @throws NullPointerException if the proposed type is null
102 */
103 /*package-private*/
104 CallSite(MethodType type) {
105 target = makeUninitializedCallSite(type);
106 }
107
108 /**
109 * Make a call site object equipped with an initial target method handle.
110 * @param target the method handle which will be the initial target of the call site
111 * @throws NullPointerException if the proposed target is null
112 */
113 /*package-private*/
114 CallSite(MethodHandle target) {
115 target.type(); // null check
116 this.target = target;
117 }
118
119 /**
120 * Make a call site object equipped with an initial target method handle.
121 * @param targetType the desired type of the call site
122 * @param createTargetHook a hook which will bind the call site to the target method handle
123 * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
124 * or if the target returned by the hook is not of the given {@code targetType}
125 * @throws NullPointerException if the hook returns a null value
200 * <p>
201 * This method is equivalent to the following code:
202 * <blockquote><pre>{@code
203 * MethodHandle getTarget, invoker, result;
204 * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
205 * invoker = MethodHandles.exactInvoker(this.type());
206 * result = MethodHandles.foldArguments(invoker, getTarget)
207 * }</pre></blockquote>
208 *
209 * @return a method handle which always invokes this call site's current target
210 */
211 public abstract MethodHandle dynamicInvoker();
212
213 /*non-public*/ MethodHandle makeDynamicInvoker() {
214 MethodHandle getTarget = GET_TARGET.bindReceiver(this);
215 MethodHandle invoker = MethodHandles.exactInvoker(this.type());
216 return MethodHandles.foldArguments(invoker, getTarget);
217 }
218
219 private static final MethodHandle GET_TARGET;
220 private static final MethodHandle THROW_UCS;
221 static {
222 try {
223 GET_TARGET = IMPL_LOOKUP.
224 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
225 THROW_UCS = IMPL_LOOKUP.
226 findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class));
227 } catch (ReflectiveOperationException e) {
228 throw newInternalError(e);
229 }
230 }
231
232 /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
233 private static Object uninitializedCallSite(Object... ignore) {
234 throw new IllegalStateException("uninitialized call site");
235 }
236
237 private MethodHandle makeUninitializedCallSite(MethodType targetType) {
238 MethodType basicType = targetType.basicType();
239 MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS);
240 if (invoker == null) {
241 invoker = THROW_UCS.asType(basicType);
242 invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker);
243 }
244 // unchecked view is OK since no values will be received or returned
245 return invoker.viewAsType(targetType);
246 }
247
248 // unsafe stuff:
249 private static final long TARGET_OFFSET;
250 static {
251 try {
252 TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target"));
253 } catch (Exception ex) { throw new Error(ex); }
254 }
255
256 /*package-private*/
257 void setTargetNormal(MethodHandle newTarget) {
258 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
259 }
260 /*package-private*/
261 MethodHandle getTargetVolatile() {
262 return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET);
263 }
264 /*package-private*/
265 void setTargetVolatile(MethodHandle newTarget) {
266 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
267 }
|