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