--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/ConstantGroup.java Fri Sep 08 10:46:46 2017 -0700
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.invoke;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.function.IntFunction;
+
+/**
+ * An ordered sequence of constants, some of which may not yet
+ * be present. This type is used by {@link BootstrapCallInfo}
+ * to represent the sequence of bootstrap arguments associated
+ * with a bootstrap method, without forcing their immediate
+ * resolution.
+ * <p>
+ * If you use the
+ * {@linkplain ConstantGroup#get(int) simple get method},
+ * the constant will be resolved, if this has not already
+ * happened. An occasional side effect of resolution is a
+ * {@code LinkageError}, which happens if the system
+ * could not resolve the constant in question.
+ * <p>
+ * In order to peek at a constant without necessarily
+ * resolving it, use the
+ * {@linkplain ConstantGroup#get(int,Object)
+ * non-throwing get method}.
+ * This method will never throw a resolution error.
+ * Instead, if the resolution would result in an error,
+ * or if the implementation elects not to attempt
+ * resolution at this point, then the method will
+ * return the user-supplied sentinel value.
+ * <p>
+ * To iterate through the constants, resolving as you go,
+ * use the iterator provided on the {@link List}-typed view.
+ * If you supply a sentinel, resolution will be suppressed.
+ * <p>
+ * Typically the constant is drawn from a constant pool entry
+ * in the virtual machine. Constant pool entries undergo a
+ * one-time state transition from unresolved to resolved,
+ * with a permanently recorded result. Usually that result
+ * is the desired constant value, but it may also be an error.
+ * In any case, the results displayed by a {@code ConstantGroup}
+ * are stable in the same way. If a query to a particular
+ * constant in a {@code ConstantGroup} throws an exception once,
+ * it will throw the same kind of exception forever after.
+ * If the query returns a constant value once, it will return
+ * the same value forever after.
+ * <p>
+ * The only possible change in the status of a constant is
+ * from the unresolved to the resolved state, and that
+ * happens exactly once. A constant will never revert to
+ * an unlinked state. However, from the point of view of
+ * this interface, constants may appear to spontaneously
+ * resolve. This is so because constant pools are global
+ * structures shared across threads, and because
+ * prefetching of some constants may occur, there are no
+ * strong guarantees when the virtual machine may resolve
+ * constants.
+ * <p>
+ * When choosing sentinel values, be aware that a constant
+ * pool which has {@code CONSTANT_Dynamic} entries
+ * can contain potentially any representable value,
+ * and arbitrary implementations of {@code ConstantGroup}
+ * are also free to produce arbitrary values.
+ * This means some obvious choices for sentinel values,
+ * such as {@code null}, may sometimes fail to distinguish
+ * a resolved from an unresolved constant in the group.
+ * The most reliable sentinel is a privately created object,
+ * or perhaps the {@code ConstantGroup} itself.
+ * @since 1.10
+ */
+// public
+interface ConstantGroup {
+ /// Access
+
+ /**
+ * Returns the number of constants in this group.
+ * This value never changes, for any particular group.
+ * @return the number of constants in this group
+ */
+ int size();
+
+ /**
+ * Returns the selected constant, resolving it if necessary.
+ * Throws a linkage error if resolution proves impossible.
+ * @param index which constant to select
+ * @return the selected constant
+ * @throws LinkageError if the selected constant needs resolution and cannot be resolved
+ */
+ Object get(int index) throws LinkageError;
+
+ /**
+ * Returns the selected constant,
+ * or the given sentinel value if there is none available.
+ * If the constant cannot be resolved, the sentinel will be returned.
+ * If the constant can (perhaps) be resolved, but has not yet been resolved,
+ * then the sentinel <em>may</em> be returned, at the implementation's discretion.
+ * To force resolution (and a possible exception), call {@link #get(int)}.
+ * @param index the selected constant
+ * @param ifNotPresent the sentinel value to return if the constant is not present
+ * @return the selected constant, if available, else the sentinel value
+ */
+ Object get(int index, Object ifNotPresent);
+
+ /**
+ * Returns an indication of whether a constant may be available.
+ * If it returns {@code true}, it will always return true in the future,
+ * and a call to {@link #get(int)} will never throw an exception.
+ * <p>
+ * After a normal return from {@link #get(int)} or a present
+ * value is reported from {@link #get(int,Object)}, this method
+ * must always return true.
+ * <p>
+ * If this method returns {@code false}, nothing in particular
+ * can be inferred, since the query only concerns the internal
+ * logic of the {@code ConstantGroup} object which ensures that
+ a successful * query to a constant will always remain successful.
+ * The only way to force a permanent decision about whether
+ * a constant is available is to call {@link #get(int)} and
+ * be ready for an exception if the constant is unavailable.
+ * @param index the selected constant
+ * @return {@code true} if the selected constant is known by
+ * this object to be present, {@code false} if it is known
+ * not to be present or
+ */
+ boolean isPresent(int index);
+
+ /// Views
+
+ /**
+ * Create a view on this group as a {@link List} view.
+ * Any request for a constant through this view will
+ * force resolution.
+ * @return a {@code List} view on this group which will force resolution
+ */
+ default List<Object> asList() {
+ return new AbstractConstantGroup.AsList(this, 0, size());
+ }
+
+ /**
+ * Create a view on this group as a {@link List} view.
+ * Any request for a constant through this view will
+ * return the given sentinel value, if the corresponding
+ * call to {@link #get(int,Object)} would do so.
+ * @param ifNotPresent the sentinel value to return if a constant is not present
+ * @return a {@code List} view on this group which will not force resolution
+ */
+ default List<Object> asList(Object ifNotPresent) {
+ return new AbstractConstantGroup.AsList(this, 0, size(), ifNotPresent);
+ }
+
+ /**
+ * Create a view on a sub-sequence of this group.
+ * @param start the index to begin the view
+ * @param end the index to end the view
+ * @return a view on the selected sub-group
+ */
+ default ConstantGroup subGroup(int start, int end) {
+ return new AbstractConstantGroup.SubGroup(this, start, end);
+ }
+
+ /// Bulk operations
+
+ /**
+ * Copy a sequence of constant values into a given buffer.
+ * This is equivalent to {@code end-offset} separate calls to {@code get},
+ * for each index in the range from {@code offset} up to but not including {@code end}.
+ * For the first constant that cannot be resolved,
+ * a {@code LinkageError} is thrown, but only after
+ * preceding constant value have been stored.
+ * @param start index of first constant to retrieve
+ * @param end limiting index of constants to retrieve
+ * @param buf array to receive the requested values
+ * @param pos position in the array to offset storing the values
+ * @return the limiting index, {@code end}
+ * @throws LinkageError if a constant cannot be resolved
+ */
+ default int copyConstants(int start, int end,
+ Object[] buf, int pos)
+ throws LinkageError
+ {
+ int bufBase = pos - start; // buf[bufBase + i] = get(i)
+ for (int i = start; i < end; i++) {
+ buf[bufBase + i] = get(i);
+ }
+ return end;
+ }
+
+ /**
+ * Copy a sequence of constant values into a given buffer.
+ * This is equivalent to {@code end-offset} separate calls to {@code get},
+ * for each index in the range from {@code offset} up to but not including {@code end}.
+ * Any constants that cannot be resolved are replaced by the
+ * given sentinel value.
+ * @param start index of first constant to retrieve
+ * @param end limiting index of constants to retrieve
+ * @param buf array to receive the requested values
+ * @param pos position in the array to offset storing the values
+ * @param ifNotPresent sentinel value to store if a value is not available
+ * @return the limiting index, {@code end}
+ * @throws LinkageError if {@code resolve} is true and a constant cannot be resolved
+ */
+ default int copyConstants(int start, int end,
+ Object[] buf, int pos,
+ Object ifNotPresent) {
+ int bufBase = pos - start; // buf[bufBase + i] = get(i)
+ for (int i = start; i < end; i++) {
+ buf[bufBase + i] = get(i, ifNotPresent);
+ }
+ return end;
+ }
+
+ /**
+ * Make a new constant group with the given constants.
+ * The value of {@code ifNotPresent} may be any reference.
+ * If this value is encountered as an element of the
+ * {@code constants} list, the new constant group will
+ * regard that element of the list as logically missing.
+ * If the new constant group is called upon to resolve
+ * a missing element of the group, it will refer to the
+ * given {@code constantProvider}, by calling it on the
+ * index of the missing element.
+ * The {@code constantProvider} must be stable, in the sense
+ * that the outcome of calling it on the same index twice
+ * will produce equivalent results.
+ * If {@code constantProvider} is the null reference, then
+ * it will be treated as if it were a function which raises
+ * {@link NoSuchElementException}.
+ * @param constants the elements of this constant group
+ * @param ifNotPresent sentinel value provided instead of a missing constant
+ * @param constantProvider function to call when a missing constant is resolved
+ * @return a new constant group with the given constants and resolution behavior
+ */
+ static ConstantGroup makeConstantGroup(List<Object> constants,
+ Object ifNotPresent,
+ IntFunction<Object> constantProvider) {
+ class Impl extends AbstractConstantGroup.WithCache {
+ Impl() {
+ super(constants.size());
+ initializeCache(constants, ifNotPresent);
+ }
+ @Override
+ Object fillCache(int index) {
+ if (constantProvider == null) super.fillCache(index);
+ return constantProvider.apply(index);
+ }
+ }
+ return new Impl();
+ }
+
+ /**
+ * Make a new constant group with the given constant values.
+ * The constants will be copied from the given list into the
+ * new constant group, forcing resolution if any are missing.
+ * @param constants the constants of this constant group
+ * @return a new constant group with the given constants
+ */
+ static ConstantGroup makeConstantGroup(List<Object> constants) {
+ final Object NP = AbstractConstantGroup.WithCache.NOT_PRESENT;
+ assert(!constants.contains(NP)); // secret value
+ return makeConstantGroup(constants, NP, null);
+ }
+
+}