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 }