24 */ |
24 */ |
25 |
25 |
26 package java.lang.invoke; |
26 package java.lang.invoke; |
27 |
27 |
28 import sun.invoke.empty.Empty; |
28 import sun.invoke.empty.Empty; |
29 import sun.misc.Unsafe; |
29 import static java.lang.invoke.MethodHandleStatics.*; |
30 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; |
30 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; |
31 |
31 |
32 /** |
32 /** |
33 * A {@code CallSite} is a holder for a variable {@link MethodHandle}, |
33 * A {@code CallSite} is a holder for a variable {@link MethodHandle}, |
34 * which is called its {@code target}. |
34 * which is called its {@code target}. |
84 */ |
84 */ |
85 abstract |
85 abstract |
86 public class CallSite { |
86 public class CallSite { |
87 static { MethodHandleImpl.initStatics(); } |
87 static { MethodHandleImpl.initStatics(); } |
88 |
88 |
89 // Fields used only by the JVM. Do not use or change. |
|
90 private MemberName vmmethod; // supplied by the JVM (ref. to calling method) |
|
91 private int vmindex; // supplied by the JVM (BCI within calling method) |
|
92 |
|
93 // The actual payload of this call site: |
89 // The actual payload of this call site: |
94 /*package-private*/ |
90 /*package-private*/ |
95 MethodHandle target; |
91 MethodHandle target; // Note: This field is known to the JVM. Do not change. |
96 |
92 |
97 /** |
93 /** |
98 * Make a blank call site object with the given method type. |
94 * Make a blank call site object with the given method type. |
99 * An initial target method is supplied which will throw |
95 * An initial target method is supplied which will throw |
100 * an {@link IllegalStateException} if called. |
96 * an {@link IllegalStateException} if called. |
147 * @return the type of the current target, which is also the type of any future target |
143 * @return the type of the current target, which is also the type of any future target |
148 */ |
144 */ |
149 public MethodType type() { |
145 public MethodType type() { |
150 // warning: do not call getTarget here, because CCS.getTarget can throw IllegalStateException |
146 // warning: do not call getTarget here, because CCS.getTarget can throw IllegalStateException |
151 return target.type(); |
147 return target.type(); |
152 } |
|
153 |
|
154 /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite. |
|
155 * The parameters are JVM-specific. |
|
156 */ |
|
157 void initializeFromJVM(String name, |
|
158 MethodType type, |
|
159 MemberName callerMethod, |
|
160 int callerBCI) { |
|
161 if (this.vmmethod != null) { |
|
162 // FIXME |
|
163 throw new BootstrapMethodError("call site has already been linked to an invokedynamic instruction"); |
|
164 } |
|
165 if (!this.type().equals(type)) { |
|
166 throw wrongTargetType(target, type); |
|
167 } |
|
168 this.vmindex = callerBCI; |
|
169 this.vmmethod = callerMethod; |
|
170 } |
148 } |
171 |
149 |
172 /** |
150 /** |
173 * Returns the target method of the call site, according to the |
151 * Returns the target method of the call site, according to the |
174 * behavior defined by this call site's specific class. |
152 * behavior defined by this call site's specific class. |
231 * @return a method handle which always invokes this call site's current target |
209 * @return a method handle which always invokes this call site's current target |
232 */ |
210 */ |
233 public abstract MethodHandle dynamicInvoker(); |
211 public abstract MethodHandle dynamicInvoker(); |
234 |
212 |
235 /*non-public*/ MethodHandle makeDynamicInvoker() { |
213 /*non-public*/ MethodHandle makeDynamicInvoker() { |
236 MethodHandle getTarget = MethodHandleImpl.bindReceiver(GET_TARGET, this); |
214 MethodHandle getTarget = GET_TARGET.bindReceiver(this); |
237 MethodHandle invoker = MethodHandles.exactInvoker(this.type()); |
215 MethodHandle invoker = MethodHandles.exactInvoker(this.type()); |
238 return MethodHandles.foldArguments(invoker, getTarget); |
216 return MethodHandles.foldArguments(invoker, getTarget); |
239 } |
217 } |
240 |
218 |
241 private static final MethodHandle GET_TARGET; |
219 private static final MethodHandle GET_TARGET; |
253 static Empty uninitializedCallSite() { |
231 static Empty uninitializedCallSite() { |
254 throw new IllegalStateException("uninitialized call site"); |
232 throw new IllegalStateException("uninitialized call site"); |
255 } |
233 } |
256 |
234 |
257 // unsafe stuff: |
235 // unsafe stuff: |
258 private static final Unsafe unsafe = Unsafe.getUnsafe(); |
|
259 private static final long TARGET_OFFSET; |
236 private static final long TARGET_OFFSET; |
260 |
|
261 static { |
237 static { |
262 try { |
238 try { |
263 TARGET_OFFSET = unsafe.objectFieldOffset(CallSite.class.getDeclaredField("target")); |
239 TARGET_OFFSET = UNSAFE.objectFieldOffset(CallSite.class.getDeclaredField("target")); |
264 } catch (Exception ex) { throw new Error(ex); } |
240 } catch (Exception ex) { throw new Error(ex); } |
265 } |
241 } |
266 |
242 |
267 /*package-private*/ |
243 /*package-private*/ |
268 void setTargetNormal(MethodHandle newTarget) { |
244 void setTargetNormal(MethodHandle newTarget) { |
269 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget); |
245 MethodHandleNatives.setCallSiteTargetNormal(this, newTarget); |
270 } |
246 } |
271 /*package-private*/ |
247 /*package-private*/ |
272 MethodHandle getTargetVolatile() { |
248 MethodHandle getTargetVolatile() { |
273 return (MethodHandle) unsafe.getObjectVolatile(this, TARGET_OFFSET); |
249 return (MethodHandle) UNSAFE.getObjectVolatile(this, TARGET_OFFSET); |
274 } |
250 } |
275 /*package-private*/ |
251 /*package-private*/ |
276 void setTargetVolatile(MethodHandle newTarget) { |
252 void setTargetVolatile(MethodHandle newTarget) { |
277 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget); |
253 MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget); |
278 } |
254 } |
282 // Callee information: |
258 // Callee information: |
283 String name, MethodType type, |
259 String name, MethodType type, |
284 // Extra arguments for BSM, if any: |
260 // Extra arguments for BSM, if any: |
285 Object info, |
261 Object info, |
286 // Caller information: |
262 // Caller information: |
287 MemberName callerMethod, int callerBCI) { |
263 Class<?> callerClass) { |
288 Class<?> callerClass = callerMethod.getDeclaringClass(); |
|
289 Object caller = IMPL_LOOKUP.in(callerClass); |
264 Object caller = IMPL_LOOKUP.in(callerClass); |
290 CallSite site; |
265 CallSite site; |
291 try { |
266 try { |
292 Object binding; |
267 Object binding; |
293 info = maybeReBox(info); |
268 info = maybeReBox(info); |