|
1 /* |
|
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
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.List; |
|
29 import java.util.NoSuchElementException; |
|
30 import java.util.function.IntFunction; |
|
31 |
|
32 /** |
|
33 * An ordered sequence of constants, some of which may not yet |
|
34 * be present. This type is used by {@link BootstrapCallInfo} |
|
35 * to represent the sequence of bootstrap arguments associated |
|
36 * with a bootstrap method, without forcing their immediate |
|
37 * resolution. |
|
38 * <p> |
|
39 * If you use the |
|
40 * {@linkplain ConstantGroup#get(int) simple get method}, |
|
41 * the constant will be resolved, if this has not already |
|
42 * happened. An occasional side effect of resolution is a |
|
43 * {@code LinkageError}, which happens if the system |
|
44 * could not resolve the constant in question. |
|
45 * <p> |
|
46 * In order to peek at a constant without necessarily |
|
47 * resolving it, use the |
|
48 * {@linkplain ConstantGroup#get(int,Object) |
|
49 * non-throwing get method}. |
|
50 * This method will never throw a resolution error. |
|
51 * Instead, if the resolution would result in an error, |
|
52 * or if the implementation elects not to attempt |
|
53 * resolution at this point, then the method will |
|
54 * return the user-supplied sentinel value. |
|
55 * <p> |
|
56 * To iterate through the constants, resolving as you go, |
|
57 * use the iterator provided on the {@link List}-typed view. |
|
58 * If you supply a sentinel, resolution will be suppressed. |
|
59 * <p> |
|
60 * Typically the constant is drawn from a constant pool entry |
|
61 * in the virtual machine. Constant pool entries undergo a |
|
62 * one-time state transition from unresolved to resolved, |
|
63 * with a permanently recorded result. Usually that result |
|
64 * is the desired constant value, but it may also be an error. |
|
65 * In any case, the results displayed by a {@code ConstantGroup} |
|
66 * are stable in the same way. If a query to a particular |
|
67 * constant in a {@code ConstantGroup} throws an exception once, |
|
68 * it will throw the same kind of exception forever after. |
|
69 * If the query returns a constant value once, it will return |
|
70 * the same value forever after. |
|
71 * <p> |
|
72 * The only possible change in the status of a constant is |
|
73 * from the unresolved to the resolved state, and that |
|
74 * happens exactly once. A constant will never revert to |
|
75 * an unlinked state. However, from the point of view of |
|
76 * this interface, constants may appear to spontaneously |
|
77 * resolve. This is so because constant pools are global |
|
78 * structures shared across threads, and because |
|
79 * prefetching of some constants may occur, there are no |
|
80 * strong guarantees when the virtual machine may resolve |
|
81 * constants. |
|
82 * <p> |
|
83 * When choosing sentinel values, be aware that a constant |
|
84 * pool which has {@code CONSTANT_Dynamic} entries |
|
85 * can contain potentially any representable value, |
|
86 * and arbitrary implementations of {@code ConstantGroup} |
|
87 * are also free to produce arbitrary values. |
|
88 * This means some obvious choices for sentinel values, |
|
89 * such as {@code null}, may sometimes fail to distinguish |
|
90 * a resolved from an unresolved constant in the group. |
|
91 * The most reliable sentinel is a privately created object, |
|
92 * or perhaps the {@code ConstantGroup} itself. |
|
93 * @since 1.10 |
|
94 */ |
|
95 // public |
|
96 interface ConstantGroup { |
|
97 /// Access |
|
98 |
|
99 /** |
|
100 * Returns the number of constants in this group. |
|
101 * This value never changes, for any particular group. |
|
102 * @return the number of constants in this group |
|
103 */ |
|
104 int size(); |
|
105 |
|
106 /** |
|
107 * Returns the selected constant, resolving it if necessary. |
|
108 * Throws a linkage error if resolution proves impossible. |
|
109 * @param index which constant to select |
|
110 * @return the selected constant |
|
111 * @throws LinkageError if the selected constant needs resolution and cannot be resolved |
|
112 */ |
|
113 Object get(int index) throws LinkageError; |
|
114 |
|
115 /** |
|
116 * Returns the selected constant, |
|
117 * or the given sentinel value if there is none available. |
|
118 * If the constant cannot be resolved, the sentinel will be returned. |
|
119 * If the constant can (perhaps) be resolved, but has not yet been resolved, |
|
120 * then the sentinel <em>may</em> be returned, at the implementation's discretion. |
|
121 * To force resolution (and a possible exception), call {@link #get(int)}. |
|
122 * @param index the selected constant |
|
123 * @param ifNotPresent the sentinel value to return if the constant is not present |
|
124 * @return the selected constant, if available, else the sentinel value |
|
125 */ |
|
126 Object get(int index, Object ifNotPresent); |
|
127 |
|
128 /** |
|
129 * Returns an indication of whether a constant may be available. |
|
130 * If it returns {@code true}, it will always return true in the future, |
|
131 * and a call to {@link #get(int)} will never throw an exception. |
|
132 * <p> |
|
133 * After a normal return from {@link #get(int)} or a present |
|
134 * value is reported from {@link #get(int,Object)}, this method |
|
135 * must always return true. |
|
136 * <p> |
|
137 * If this method returns {@code false}, nothing in particular |
|
138 * can be inferred, since the query only concerns the internal |
|
139 * logic of the {@code ConstantGroup} object which ensures that |
|
140 a successful * query to a constant will always remain successful. |
|
141 * The only way to force a permanent decision about whether |
|
142 * a constant is available is to call {@link #get(int)} and |
|
143 * be ready for an exception if the constant is unavailable. |
|
144 * @param index the selected constant |
|
145 * @return {@code true} if the selected constant is known by |
|
146 * this object to be present, {@code false} if it is known |
|
147 * not to be present or |
|
148 */ |
|
149 boolean isPresent(int index); |
|
150 |
|
151 /// Views |
|
152 |
|
153 /** |
|
154 * Create a view on this group as a {@link List} view. |
|
155 * Any request for a constant through this view will |
|
156 * force resolution. |
|
157 * @return a {@code List} view on this group which will force resolution |
|
158 */ |
|
159 default List<Object> asList() { |
|
160 return new AbstractConstantGroup.AsList(this, 0, size()); |
|
161 } |
|
162 |
|
163 /** |
|
164 * Create a view on this group as a {@link List} view. |
|
165 * Any request for a constant through this view will |
|
166 * return the given sentinel value, if the corresponding |
|
167 * call to {@link #get(int,Object)} would do so. |
|
168 * @param ifNotPresent the sentinel value to return if a constant is not present |
|
169 * @return a {@code List} view on this group which will not force resolution |
|
170 */ |
|
171 default List<Object> asList(Object ifNotPresent) { |
|
172 return new AbstractConstantGroup.AsList(this, 0, size(), ifNotPresent); |
|
173 } |
|
174 |
|
175 /** |
|
176 * Create a view on a sub-sequence of this group. |
|
177 * @param start the index to begin the view |
|
178 * @param end the index to end the view |
|
179 * @return a view on the selected sub-group |
|
180 */ |
|
181 default ConstantGroup subGroup(int start, int end) { |
|
182 return new AbstractConstantGroup.SubGroup(this, start, end); |
|
183 } |
|
184 |
|
185 /// Bulk operations |
|
186 |
|
187 /** |
|
188 * Copy a sequence of constant values into a given buffer. |
|
189 * This is equivalent to {@code end-offset} separate calls to {@code get}, |
|
190 * for each index in the range from {@code offset} up to but not including {@code end}. |
|
191 * For the first constant that cannot be resolved, |
|
192 * a {@code LinkageError} is thrown, but only after |
|
193 * preceding constant value have been stored. |
|
194 * @param start index of first constant to retrieve |
|
195 * @param end limiting index of constants to retrieve |
|
196 * @param buf array to receive the requested values |
|
197 * @param pos position in the array to offset storing the values |
|
198 * @return the limiting index, {@code end} |
|
199 * @throws LinkageError if a constant cannot be resolved |
|
200 */ |
|
201 default int copyConstants(int start, int end, |
|
202 Object[] buf, int pos) |
|
203 throws LinkageError |
|
204 { |
|
205 int bufBase = pos - start; // buf[bufBase + i] = get(i) |
|
206 for (int i = start; i < end; i++) { |
|
207 buf[bufBase + i] = get(i); |
|
208 } |
|
209 return end; |
|
210 } |
|
211 |
|
212 /** |
|
213 * Copy a sequence of constant values into a given buffer. |
|
214 * This is equivalent to {@code end-offset} separate calls to {@code get}, |
|
215 * for each index in the range from {@code offset} up to but not including {@code end}. |
|
216 * Any constants that cannot be resolved are replaced by the |
|
217 * given sentinel value. |
|
218 * @param start index of first constant to retrieve |
|
219 * @param end limiting index of constants to retrieve |
|
220 * @param buf array to receive the requested values |
|
221 * @param pos position in the array to offset storing the values |
|
222 * @param ifNotPresent sentinel value to store if a value is not available |
|
223 * @return the limiting index, {@code end} |
|
224 * @throws LinkageError if {@code resolve} is true and a constant cannot be resolved |
|
225 */ |
|
226 default int copyConstants(int start, int end, |
|
227 Object[] buf, int pos, |
|
228 Object ifNotPresent) { |
|
229 int bufBase = pos - start; // buf[bufBase + i] = get(i) |
|
230 for (int i = start; i < end; i++) { |
|
231 buf[bufBase + i] = get(i, ifNotPresent); |
|
232 } |
|
233 return end; |
|
234 } |
|
235 |
|
236 /** |
|
237 * Make a new constant group with the given constants. |
|
238 * The value of {@code ifNotPresent} may be any reference. |
|
239 * If this value is encountered as an element of the |
|
240 * {@code constants} list, the new constant group will |
|
241 * regard that element of the list as logically missing. |
|
242 * If the new constant group is called upon to resolve |
|
243 * a missing element of the group, it will refer to the |
|
244 * given {@code constantProvider}, by calling it on the |
|
245 * index of the missing element. |
|
246 * The {@code constantProvider} must be stable, in the sense |
|
247 * that the outcome of calling it on the same index twice |
|
248 * will produce equivalent results. |
|
249 * If {@code constantProvider} is the null reference, then |
|
250 * it will be treated as if it were a function which raises |
|
251 * {@link NoSuchElementException}. |
|
252 * @param constants the elements of this constant group |
|
253 * @param ifNotPresent sentinel value provided instead of a missing constant |
|
254 * @param constantProvider function to call when a missing constant is resolved |
|
255 * @return a new constant group with the given constants and resolution behavior |
|
256 */ |
|
257 static ConstantGroup makeConstantGroup(List<Object> constants, |
|
258 Object ifNotPresent, |
|
259 IntFunction<Object> constantProvider) { |
|
260 class Impl extends AbstractConstantGroup.WithCache { |
|
261 Impl() { |
|
262 super(constants.size()); |
|
263 initializeCache(constants, ifNotPresent); |
|
264 } |
|
265 @Override |
|
266 Object fillCache(int index) { |
|
267 if (constantProvider == null) super.fillCache(index); |
|
268 return constantProvider.apply(index); |
|
269 } |
|
270 } |
|
271 return new Impl(); |
|
272 } |
|
273 |
|
274 /** |
|
275 * Make a new constant group with the given constant values. |
|
276 * The constants will be copied from the given list into the |
|
277 * new constant group, forcing resolution if any are missing. |
|
278 * @param constants the constants of this constant group |
|
279 * @return a new constant group with the given constants |
|
280 */ |
|
281 static ConstantGroup makeConstantGroup(List<Object> constants) { |
|
282 final Object NP = AbstractConstantGroup.WithCache.NOT_PRESENT; |
|
283 assert(!constants.contains(NP)); // secret value |
|
284 return makeConstantGroup(constants, NP, null); |
|
285 } |
|
286 |
|
287 } |