180 * the type of the old target.
181 *
182 * @param newTarget the new target
183 * @throws NullPointerException if the proposed new target is null
184 * @throws WrongMethodTypeException if the proposed new target
185 * has a method type that differs from the previous target
186 * @see CallSite#getTarget
187 * @see ConstantCallSite#setTarget
188 * @see MutableCallSite#setTarget
189 * @see VolatileCallSite#setTarget
190 */
191 public abstract void setTarget(MethodHandle newTarget);
192
193 void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
194 MethodType oldType = oldTarget.type();
195 MethodType newType = newTarget.type(); // null check!
196 if (!newType.equals(oldType))
197 throw wrongTargetType(newTarget, oldType);
198 }
199
200 private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
201 return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
202 }
203
204 /**
205 * Produces a method handle equivalent to an invokedynamic instruction
206 * which has been linked to this call site.
207 * <p>
208 * This method is equivalent to the following code:
209 * <blockquote><pre>{@code
210 * MethodHandle getTarget, invoker, result;
211 * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
212 * invoker = MethodHandles.exactInvoker(this.type());
213 * result = MethodHandles.foldArguments(invoker, getTarget)
214 * }</pre></blockquote>
215 *
216 * @return a method handle which always invokes this call site's current target
217 */
218 public abstract MethodHandle dynamicInvoker();
219
220 /*non-public*/ MethodHandle makeDynamicInvoker() {
276 if (offset > 0) {
277 return offset;
278 }
279 offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class, "target");
280 assert(offset > 0);
281 return offset;
282 }
283
284 /*package-private*/
285 void setTargetNormal(MethodHandle newTarget) {
286 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
287 }
288 /*package-private*/
289 MethodHandle getTargetVolatile() {
290 return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset());
291 }
292 /*package-private*/
293 void setTargetVolatile(MethodHandle newTarget) {
294 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
295 }
296
297 // this implements the upcall from the JVM, MethodHandleNatives.linkCallSite:
298 static CallSite makeSite(MethodHandle bootstrapMethod,
299 // Callee information:
300 String name, MethodType type,
301 // Extra arguments for BSM, if any:
302 Object info,
303 // Caller information:
304 Class<?> callerClass) {
305 CallSite site;
306 try {
307 Object binding = BootstrapMethodInvoker.invoke(
308 CallSite.class, bootstrapMethod, name, type, info, callerClass);
309 if (binding instanceof CallSite) {
310 site = (CallSite) binding;
311 } else {
312 // See the "Linking Exceptions" section for the invokedynamic
313 // instruction in JVMS 6.5.
314 // Throws a runtime exception defining the cause that is then
315 // in the "catch (Throwable ex)" a few lines below wrapped in
316 // BootstrapMethodError
317 throw new ClassCastException("CallSite bootstrap method failed to produce an instance of CallSite");
318 }
319 if (!site.getTarget().type().equals(type)) {
320 // See the "Linking Exceptions" section for the invokedynamic
321 // instruction in JVMS 6.5.
322 // Throws a runtime exception defining the cause that is then
323 // in the "catch (Throwable ex)" a few lines below wrapped in
324 // BootstrapMethodError
325 throw wrongTargetType(site.getTarget(), type);
326 }
327 } catch (Error e) {
328 // Pass through an Error, including BootstrapMethodError, any other
329 // form of linkage error, such as IllegalAccessError if the bootstrap
330 // method is inaccessible, or say ThreadDeath/OutOfMemoryError
331 // See the "Linking Exceptions" section for the invokedynamic
332 // instruction in JVMS 6.5.
333 throw e;
334 } catch (Throwable ex) {
335 // Wrap anything else in BootstrapMethodError
336 throw new BootstrapMethodError("CallSite bootstrap method initialization exception", ex);
337 }
338 return site;
339 }
340 }
|
180 * the type of the old target.
181 *
182 * @param newTarget the new target
183 * @throws NullPointerException if the proposed new target is null
184 * @throws WrongMethodTypeException if the proposed new target
185 * has a method type that differs from the previous target
186 * @see CallSite#getTarget
187 * @see ConstantCallSite#setTarget
188 * @see MutableCallSite#setTarget
189 * @see VolatileCallSite#setTarget
190 */
191 public abstract void setTarget(MethodHandle newTarget);
192
193 void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
194 MethodType oldType = oldTarget.type();
195 MethodType newType = newTarget.type(); // null check!
196 if (!newType.equals(oldType))
197 throw wrongTargetType(newTarget, oldType);
198 }
199
200 static WrongMethodTypeException wrongTargetType(Object target, MethodType type) {
201 return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
202 }
203
204 /**
205 * Produces a method handle equivalent to an invokedynamic instruction
206 * which has been linked to this call site.
207 * <p>
208 * This method is equivalent to the following code:
209 * <blockquote><pre>{@code
210 * MethodHandle getTarget, invoker, result;
211 * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
212 * invoker = MethodHandles.exactInvoker(this.type());
213 * result = MethodHandles.foldArguments(invoker, getTarget)
214 * }</pre></blockquote>
215 *
216 * @return a method handle which always invokes this call site's current target
217 */
218 public abstract MethodHandle dynamicInvoker();
219
220 /*non-public*/ MethodHandle makeDynamicInvoker() {
276 if (offset > 0) {
277 return offset;
278 }
279 offset = TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class, "target");
280 assert(offset > 0);
281 return offset;
282 }
283
284 /*package-private*/
285 void setTargetNormal(MethodHandle newTarget) {
286 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
287 }
288 /*package-private*/
289 MethodHandle getTargetVolatile() {
290 return (MethodHandle) UNSAFE.getObjectVolatile(this, getTargetOffset());
291 }
292 /*package-private*/
293 void setTargetVolatile(MethodHandle newTarget) {
294 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
295 }
296 }
|