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      */
size()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      */
get(int index)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      */
get(int index, Object ifNotPresent)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      */
isPresent(int index)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      */
asList()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      */
asList(Object ifNotPresent)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      */
subGroup(int start, int end)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      */
copyConstants(int start, int end, Object[] buf, int pos)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      */
copyConstants(int start, int end, Object[] buf, int pos, Object ifNotPresent)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      */
makeConstantGroup(List<Object> constants, Object ifNotPresent, IntFunction<Object> constantProvider)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      */
makeConstantGroup(List<Object> constants)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 }
288