23 * have any questions. |
23 * have any questions. |
24 */ |
24 */ |
25 |
25 |
26 package java.dyn; |
26 package java.dyn; |
27 |
27 |
28 import sun.dyn.util.BytecodeName; |
|
29 import sun.dyn.Access; |
28 import sun.dyn.Access; |
|
29 import sun.dyn.MemberName; |
30 import sun.dyn.CallSiteImpl; |
30 import sun.dyn.CallSiteImpl; |
31 import sun.dyn.MethodHandleImpl; |
|
32 |
31 |
33 /** |
32 /** |
34 * An {@code invokedynamic} call site, as reified by the |
33 * A {@code CallSite} reifies an {@code invokedynamic} instruction from bytecode, |
35 * containing class's bootstrap method. |
34 * and controls its linkage. |
36 * Every call site object corresponds to a distinct instance |
35 * Every linked {@code CallSite} object corresponds to a distinct instance |
37 * of the <code>invokedynamic</code> instruction, and vice versa. |
36 * of the {@code invokedynamic} instruction, and vice versa. |
38 * Every call site has one state variable, called the {@code target}. |
37 * <p> |
39 * It is typed as a {@link MethodHandle}. This state is never null, and |
38 * Every linked {@code CallSite} object has one state variable, |
40 * it is the responsibility of the bootstrap method to produce call sites |
39 * a {@link MethodHandle} reference called the {@code target}. |
41 * which have been pre-linked to an initial target method. |
40 * This reference is never null. Though it can change its value |
42 * <p> |
41 * successive values must always have exactly the {@link MethodType method type} |
43 * (Note: The bootstrap method may elect to produce call sites of a |
42 * called for by the bytecodes of the associated {@code invokedynamic} instruction |
|
43 * <p> |
|
44 * It is the responsibility of each class's |
|
45 * {@link Linkage#registerBootstrapMethod(Class, MethodHandle) bootstrap method} |
|
46 * to produce call sites which have been pre-linked to an initial target method. |
|
47 * The required {@link MethodType type} for the target method is a parameter |
|
48 * to each bootstrap method call. |
|
49 * <p> |
|
50 * The bootstrap method may elect to produce call sites of a |
44 * language-specific subclass of {@code CallSite}. In such a case, |
51 * language-specific subclass of {@code CallSite}. In such a case, |
45 * the subclass may claim responsibility for initializing its target to |
52 * the subclass may claim responsibility for initializing its target to |
46 * a non-null value, by overriding {@link #initialTarget}.) |
53 * a non-null value, by overriding {@link #initialTarget}. |
47 * <p> |
54 * <p> |
48 * An {@code invokedynamic} instruction which has not yet been executed |
55 * An {@code invokedynamic} instruction which has not yet been executed |
49 * is said to be <em>unlinked</em>. When an unlinked call site is executed, |
56 * is said to be <em>unlinked</em>. When an unlinked call site is executed, |
50 * the containing class's bootstrap method is called to manufacture a call site, |
57 * the containing class's bootstrap method is called to manufacture a call site, |
51 * for the instruction. If the bootstrap method does not assign a non-null |
58 * for the instruction. If the bootstrap method does not assign a non-null |
52 * value to the new call site's target variable, the method {@link #initialTarget} |
59 * value to the new call site's target variable, the method {@link #initialTarget} |
53 * is called to produce the new call site's first target method. |
60 * is called to produce the new call site's first target method. |
54 * <p> |
61 * <p> |
|
62 * A freshly-created {@code CallSite} object is not yet in a linked state. |
|
63 * An unlinked {@code CallSite} object reports null for its {@code callerClass}. |
|
64 * When the JVM receives a {@code CallSite} object from a bootstrap method, |
|
65 * it first ensures that its target is non-null and of the correct type. |
|
66 * The JVM then links the {@code CallSite} object to the call site instruction, |
|
67 * enabling the {@code callerClass} to return the class in which the instruction occurs. |
|
68 * <p> |
|
69 * Next, the JVM links the instruction to the {@code CallSite}, at which point |
|
70 * any further execution of the {@code invokedynamic} instruction implicitly |
|
71 * invokes the current target of the {@code CallSite} object. |
|
72 * After this two-way linkage, both the instruction and the {@code CallSite} |
|
73 * object are said to be linked. |
|
74 * <p> |
|
75 * This state of linkage continues until the method containing the |
|
76 * dynamic call site is garbage collected, or the dynamic call site |
|
77 * is invalidated by an explicit request. |
|
78 * <p> |
|
79 * Linkage happens once in the lifetime of any given {@code CallSite} object. |
|
80 * Because of call site invalidation, this linkage can be repeated for |
|
81 * a single {@code invokedynamic} instruction, with multiple {@code CallSite} objects. |
|
82 * When a {@code CallSite} is unlinked from an {@code invokedynamic} instruction, |
|
83 * the instruction is reset so that it is no longer associated with |
|
84 * the {@code CallSite} object, but the {@code CallSite} does not change |
|
85 * state. |
|
86 * <p> |
|
87 * Here is a sample use of call sites and bootstrap methods which links every |
|
88 * dynamic call site to print its arguments: |
|
89 <blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java --> |
|
90 private static void printArgs(Object... args) { |
|
91 System.out.println(java.util.Arrays.deepToString(args)); |
|
92 } |
|
93 private static final MethodHandle printArgs; |
|
94 static { |
|
95 MethodHandles.Lookup lookup = MethodHandles.lookup(); |
|
96 Class thisClass = lookup.lookupClass(); // (who am I?) |
|
97 printArgs = lookup.findStatic(thisClass, |
|
98 "printArgs", MethodType.methodType(void.class, Object[].class)); |
|
99 Linkage.registerBootstrapMethod("bootstrapDynamic"); |
|
100 } |
|
101 private static CallSite bootstrapDynamic(Class caller, String name, MethodType type) { |
|
102 // ignore caller and name, but match the type: |
|
103 return new CallSite(MethodHandles.collectArguments(printArgs, type)); |
|
104 } |
|
105 </pre></blockquote> |
55 * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle) |
106 * @see Linkage#registerBootstrapMethod(java.lang.Class, java.dyn.MethodHandle) |
56 * @author John Rose, JSR 292 EG |
107 * @author John Rose, JSR 292 EG |
57 */ |
108 */ |
58 public class CallSite |
109 public class CallSite |
59 // Note: This is an implementation inheritance hack, and will be removed |
|
60 // with a JVM change which moves the required hidden state onto this class. |
|
61 extends CallSiteImpl |
|
62 { |
110 { |
63 private static final Access IMPL_TOKEN = Access.getToken(); |
111 private static final Access IMPL_TOKEN = Access.getToken(); |
64 |
112 |
65 /* |
|
66 |
|
67 // Fields used only by the JVM. Do not use or change. |
113 // Fields used only by the JVM. Do not use or change. |
68 private Object vmmethod; |
114 private MemberName vmmethod; // supplied by the JVM (ref. to calling method) |
69 int callerMID, callerBCI; // supplied by the JVM |
115 private int vmindex; // supplied by the JVM (BCI within calling method) |
70 |
116 |
|
117 // The actual payload of this call site: |
71 private MethodHandle target; |
118 private MethodHandle target; |
72 |
119 |
73 final Object caller; // usually a class |
120 // Remove this field for PFD and delete deprecated methods: |
74 final String name; |
121 private MemberName calleeNameRemoveForPFD; |
75 final MethodType type; |
122 |
76 */ |
123 /** |
77 |
124 * Make a blank call site object. |
78 /** |
125 * Before it is returned from a bootstrap method, this {@code CallSite} object |
79 * Make a call site given the parameters from a call to the bootstrap method. |
126 * must be provided with |
80 * The resulting call site is in an unlinked state, which means that before |
127 * a target method via a call to {@link CallSite#setTarget(MethodHandle) setTarget}, |
81 * it is returned from a bootstrap method call it must be provided with |
128 * or by a subclass override of {@link CallSite#initialTarget(Class,String,MethodType) initialTarget}. |
82 * a target method via a call to {@link CallSite#setTarget}. |
129 */ |
83 * @param caller the class in which the relevant {@code invokedynamic} instruction occurs |
130 public CallSite() { |
84 * @param name the name specified by the {@code invokedynamic} instruction |
131 } |
85 * @param type the method handle type derived from descriptor of the {@code invokedynamic} instruction |
132 |
86 */ |
133 /** |
87 public CallSite(Object caller, String name, MethodType type) { |
134 * Make a blank call site object, possibly equipped with an initial target method handle. |
88 super(IMPL_TOKEN, caller, name, type); |
135 * The initial target reference may be null, in which case the {@code CallSite} object |
89 } |
136 * must be provided with a target method via a call to {@link CallSite#setTarget}, |
90 |
137 * or by a subclass override of {@link CallSite#initialTarget}. |
91 private static void privateInitializeCallSite(CallSite site, int callerMID, int callerBCI) { |
138 * @param target the method handle which will be the initial target of the call site, or null if there is none yet |
92 site.callerMID = callerMID; |
139 */ |
93 site.callerBCI = callerBCI; |
140 public CallSite(MethodHandle target) { |
94 site.ensureTarget(); |
141 this.target = target; |
95 } |
142 } |
96 private void ensureTarget() { |
143 |
97 // Note use of super, which accesses the field directly, |
144 /** @deprecated transitional form defined in EDR but removed in PFD */ |
98 // without deferring to possible subclass overrides. |
145 public CallSite(Class<?> caller, String name, MethodType type) { |
99 if (super.getTarget() == null) { |
146 this.calleeNameRemoveForPFD = new MemberName(caller, name, type); |
100 super.setTarget(this.initialTarget()); |
147 } |
101 super.getTarget().type(); // provoke NPE if still null |
148 /** @deprecated transitional form defined in EDR but removed in PFD */ |
102 } |
149 public Class<?> callerClass() { |
|
150 MemberName callee = this.calleeNameRemoveForPFD; |
|
151 return callee == null ? null : callee.getDeclaringClass(); |
|
152 } |
|
153 /** @deprecated transitional form defined in EDR but removed in PFD */ |
|
154 public String name() { |
|
155 MemberName callee = this.calleeNameRemoveForPFD; |
|
156 return callee == null ? null : callee.getName(); |
|
157 } |
|
158 /** @deprecated transitional form defined in EDR but removed in PFD */ |
|
159 public MethodType type() { |
|
160 MemberName callee = this.calleeNameRemoveForPFD; |
|
161 return callee == null ? (target == null ? null : target.type()) : callee.getMethodType(); |
|
162 } |
|
163 /** @deprecated transitional form defined in EDR but removed in PFD */ |
|
164 protected MethodHandle initialTarget() { |
|
165 return initialTarget(callerClass(), name(), type()); |
|
166 } |
|
167 |
|
168 /** Report if the JVM has linked this {@code CallSite} object to a dynamic call site instruction. |
|
169 * Once it is linked, it is never unlinked. |
|
170 */ |
|
171 private boolean isLinked() { |
|
172 return vmmethod != null; |
|
173 } |
|
174 |
|
175 /** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite. |
|
176 * The parameters are JVM-specific. |
|
177 */ |
|
178 void initializeFromJVM(String name, |
|
179 MethodType type, |
|
180 MemberName callerMethod, |
|
181 int callerBCI) { |
|
182 if (this.isLinked()) { |
|
183 throw new InvokeDynamicBootstrapError("call site has already been linked to an invokedynamic instruction"); |
|
184 } |
|
185 MethodHandle target = this.target; |
|
186 if (target == null) { |
|
187 this.target = target = this.initialTarget(callerMethod.getDeclaringClass(), name, type); |
|
188 } |
|
189 if (!target.type().equals(type)) { |
|
190 throw wrongTargetType(target, type); |
|
191 } |
|
192 this.vmindex = callerBCI; |
|
193 this.vmmethod = callerMethod; |
|
194 assert(this.isLinked()); |
103 } |
195 } |
104 |
196 |
105 /** |
197 /** |
106 * Just after a call site is created by a bootstrap method handle, |
198 * Just after a call site is created by a bootstrap method handle, |
107 * if the target has not been initialized by the factory method itself, |
199 * if the target has not been initialized by the factory method itself, |
108 * the method {@code initialTarget} is called to produce an initial |
200 * the method {@code initialTarget} is called to produce an initial |
109 * non-null target. (Live call sites must never have null targets.) |
201 * non-null target. (Live call sites must never have null targets.) |
|
202 * <p> |
|
203 * The arguments are the same as those passed to the bootstrap method. |
|
204 * Thus, a bootstrap method is free to ignore the arguments and simply |
|
205 * create a "blank" {@code CallSite} object of an appropriate subclass. |
110 * <p> |
206 * <p> |
111 * If the bootstrap method itself does not initialize the call site, |
207 * If the bootstrap method itself does not initialize the call site, |
112 * this method must be overridden, because it just raises an |
208 * this method must be overridden, because it just raises an |
113 * {@code InvokeDynamicBootstrapError}, which in turn causes the |
209 * {@code InvokeDynamicBootstrapError}, which in turn causes the |
114 * linkage of the {@code invokedynamic} instruction to terminate |
210 * linkage of the {@code invokedynamic} instruction to terminate |
115 * abnormally. |
211 * abnormally. |
116 */ |
212 */ |
117 protected MethodHandle initialTarget() { |
213 protected MethodHandle initialTarget(Class<?> callerClass, String name, MethodType type) { |
118 throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+this); |
214 throw new InvokeDynamicBootstrapError("target must be initialized before call site is linked: "+name+type); |
119 } |
215 } |
120 |
216 |
121 /** |
217 /** |
122 * Report the current linkage state of the call site. (This is mutable.) |
218 * Report the current linkage state of the call site. (This is mutable.) |
123 * The value may not be null after the {@code CallSite} object is returned |
219 * The value may not be null after the {@code CallSite} object is returned |
135 * a recent update to the target by another thread. |
231 * a recent update to the target by another thread. |
136 * @return the current linkage state of the call site |
232 * @return the current linkage state of the call site |
137 * @see #setTarget |
233 * @see #setTarget |
138 */ |
234 */ |
139 public MethodHandle getTarget() { |
235 public MethodHandle getTarget() { |
140 return super.getTarget(); |
236 return target; |
141 } |
237 } |
142 |
238 |
143 /** |
239 /** |
144 * Link or relink the call site, by setting its target method. |
240 * Set the target method of this call site. |
145 * <p> |
241 * <p> |
146 * The interactions of {@code setTarget} with memory are the same |
242 * The interactions of {@code setTarget} with memory are the same |
147 * as of a write to an ordinary variable, such as an array element or a |
243 * as of a write to an ordinary variable, such as an array element or a |
148 * non-volatile, non-final field. |
244 * non-volatile, non-final field. |
149 * <p> |
245 * <p> |
150 * In particular, unrelated threads may fail to see the updated target |
246 * In particular, unrelated threads may fail to see the updated target |
151 * until they perform a read from memory. |
247 * until they perform a read from memory. |
152 * Stronger guarantees can be created by putting appropriate operations |
248 * Stronger guarantees can be created by putting appropriate operations |
153 * into the bootstrap method and/or the target methods used |
249 * into the bootstrap method and/or the target methods used |
154 * at any given call site. |
250 * at any given call site. |
155 * @param target the new target, or null if it is to be unlinked |
251 * @param newTarget the new target |
156 * @throws NullPointerException if the proposed new target is null |
252 * @throws NullPointerException if the proposed new target is null |
157 * @throws WrongMethodTypeException if the proposed new target |
253 * @throws WrongMethodTypeException if the call site is linked and the proposed new target |
158 * has a method type that differs from the call site's {@link #type()} |
254 * has a method type that differs from the previous target |
159 */ |
255 */ |
160 public void setTarget(MethodHandle target) { |
256 public void setTarget(MethodHandle newTarget) { |
161 checkTarget(target); |
257 MethodType newType = newTarget.type(); // null check! |
162 super.setTarget(target); |
258 MethodHandle oldTarget = this.target; |
163 } |
259 if (oldTarget == null) { |
164 |
260 // CallSite is not yet linked. |
165 protected void checkTarget(MethodHandle target) { |
261 assert(!isLinked()); |
166 target.type(); // provoke NPE |
262 this.target = newTarget; // might be null! |
167 if (!canSetTarget(target)) |
263 return; |
168 throw new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type()); |
264 } |
169 } |
265 MethodType oldType = oldTarget.type(); |
170 |
266 if (!newTarget.type().equals(oldType)) |
171 protected boolean canSetTarget(MethodHandle target) { |
267 throw wrongTargetType(newTarget, oldType); |
172 return (target != null && target.type() == type()); |
268 if (oldTarget != newTarget) |
173 } |
269 CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget); |
174 |
270 } |
175 /** |
271 |
176 * Report the class containing the call site. |
272 private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) { |
177 * This is an immutable property of the call site, set from the first argument to the constructor. |
273 return new WrongMethodTypeException(String.valueOf(target)+target.type()+" should be of type "+type); |
178 * @return class containing the call site |
274 } |
179 */ |
275 |
180 public Class<?> callerClass() { |
276 /** Produce a printed representation that displays information about this call site |
181 return (Class) caller; |
277 * that may be useful to the human reader. |
182 } |
278 */ |
183 |
|
184 /** |
|
185 * Report the method name specified in the {@code invokedynamic} instruction. |
|
186 * This is an immutable property of the call site, set from the second argument to the constructor. |
|
187 * <p> |
|
188 * Note that the name is a JVM bytecode name, and as such can be any |
|
189 * non-empty string, as long as it does not contain certain "dangerous" |
|
190 * characters such as slash {@code '/'} and dot {@code '.'}. |
|
191 * See the Java Virtual Machine specification for more details. |
|
192 * <p> |
|
193 * Application such as a language runtimes may need to encode |
|
194 * arbitrary program element names and other configuration information |
|
195 * into the name. A standard convention for doing this is |
|
196 * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>. |
|
197 * @return method name specified by the call site |
|
198 */ |
|
199 public String name() { |
|
200 return name; |
|
201 } |
|
202 |
|
203 /** |
|
204 * Report the method name specified in the {@code invokedynamic} instruction, |
|
205 * as a series of components, individually demangled according to |
|
206 * the standard convention |
|
207 * <a href="http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm">specified here</a>. |
|
208 * <p> |
|
209 * Non-empty runs of characters between dangerous characters are demangled. |
|
210 * Each component is either a completely arbitrary demangled string, |
|
211 * or else a character constant for a punctuation character, typically ':'. |
|
212 * (In principle, the character can be any dangerous character that the |
|
213 * JVM lets through in a method name, such as '$' or ']'. |
|
214 * Runtime implementors are encouraged to use colon ':' for building |
|
215 * structured names.) |
|
216 * <p> |
|
217 * In the common case where the name contains no dangerous characters, |
|
218 * the result is an array whose only element array is the demangled |
|
219 * name at the call site. Such a demangled name can be any sequence |
|
220 * of any number of any unicode characters. |
|
221 * @return method name components specified by the call site |
|
222 */ |
|
223 public Object[] nameComponents() { |
|
224 return BytecodeName.parseBytecodeName(name); |
|
225 } |
|
226 |
|
227 /** |
|
228 * Report the resolved result and parameter types of this call site, |
|
229 * which are derived from its bytecode-level invocation descriptor. |
|
230 * The types are packaged into a {@link MethodType}. |
|
231 * Any linked target of this call site must be exactly this method type. |
|
232 * This is an immutable property of the call site, set from the third argument to the constructor. |
|
233 * @return method type specified by the call site |
|
234 */ |
|
235 public MethodType type() { |
|
236 return type; |
|
237 } |
|
238 |
|
239 @Override |
279 @Override |
240 public String toString() { |
280 public String toString() { |
241 return "CallSite#"+hashCode()+"["+name+type+" => "+getTarget()+"]"; |
281 StringBuilder buf = new StringBuilder("CallSite#"); |
242 } |
282 buf.append(hashCode()); |
243 |
283 if (!isLinked()) |
244 // Package-local constant: |
284 buf.append("[unlinked]"); |
245 static final MethodHandle GET_TARGET = MethodHandleImpl.getLookup(IMPL_TOKEN). |
285 else |
246 findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); |
286 buf.append("[") |
247 } |
287 .append("from ").append(vmmethod.getDeclaringClass().getName()) |
|
288 .append(" : ").append(getTarget().type()) |
|
289 .append(" => ").append(getTarget()) |
|
290 .append("]"); |
|
291 return buf.toString(); |
|
292 } |
|
293 } |