Removing all the JDK8 invokeDynamic infrastructure. We don't need it when we are using retrolambda.
1.1 --- a/rt/emul/compact/pom.xml Sun Aug 17 20:09:05 2014 +0200
1.2 +++ b/rt/emul/compact/pom.xml Sun Aug 17 20:15:56 2014 +0200
1.3 @@ -55,8 +55,8 @@
1.4 <compilerArguments>
1.5 <bootclasspath>netbeans.ignore.jdk.bootclasspath</bootclasspath>
1.6 </compilerArguments>
1.7 - <source>1.8</source>
1.8 - <target>1.8</target>
1.9 + <source>1.7</source>
1.10 + <target>1.7</target>
1.11 </configuration>
1.12 </plugin>
1.13 <plugin>
2.1 --- a/rt/emul/compact/src/main/java/java/lang/BootstrapMethodError.java Sun Aug 17 20:09:05 2014 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,80 +0,0 @@
2.4 -/*
2.5 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
2.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2.7 - *
2.8 - * This code is free software; you can redistribute it and/or modify it
2.9 - * under the terms of the GNU General Public License version 2 only, as
2.10 - * published by the Free Software Foundation. Oracle designates this
2.11 - * particular file as subject to the "Classpath" exception as provided
2.12 - * by Oracle in the LICENSE file that accompanied this code.
2.13 - *
2.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
2.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
2.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
2.17 - * version 2 for more details (a copy is included in the LICENSE file that
2.18 - * accompanied this code).
2.19 - *
2.20 - * You should have received a copy of the GNU General Public License version
2.21 - * 2 along with this work; if not, write to the Free Software Foundation,
2.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2.23 - *
2.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2.25 - * or visit www.oracle.com if you need additional information or have any
2.26 - * questions.
2.27 - */
2.28 -
2.29 -package java.lang;
2.30 -
2.31 -/**
2.32 - * Thrown to indicate that an {@code invokedynamic} instruction has
2.33 - * failed to find its bootstrap method,
2.34 - * or the bootstrap method has failed to provide a
2.35 - * {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
2.36 - * of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
2.37 - *
2.38 - * @author John Rose, JSR 292 EG
2.39 - * @since 1.7
2.40 - */
2.41 -public class BootstrapMethodError extends LinkageError {
2.42 - private static final long serialVersionUID = 292L;
2.43 -
2.44 - /**
2.45 - * Constructs a {@code BootstrapMethodError} with no detail message.
2.46 - */
2.47 - public BootstrapMethodError() {
2.48 - super();
2.49 - }
2.50 -
2.51 - /**
2.52 - * Constructs a {@code BootstrapMethodError} with the specified
2.53 - * detail message.
2.54 - *
2.55 - * @param s the detail message.
2.56 - */
2.57 - public BootstrapMethodError(String s) {
2.58 - super(s);
2.59 - }
2.60 -
2.61 - /**
2.62 - * Constructs a {@code BootstrapMethodError} with the specified
2.63 - * detail message and cause.
2.64 - *
2.65 - * @param s the detail message.
2.66 - * @param cause the cause, may be {@code null}.
2.67 - */
2.68 - public BootstrapMethodError(String s, Throwable cause) {
2.69 - super(s, cause);
2.70 - }
2.71 -
2.72 - /**
2.73 - * Constructs a {@code BootstrapMethodError} with the specified
2.74 - * cause.
2.75 - *
2.76 - * @param cause the cause, may be {@code null}.
2.77 - */
2.78 - public BootstrapMethodError(Throwable cause) {
2.79 - // cf. Throwable(Throwable cause) constructor.
2.80 - super(cause == null ? null : cause.toString());
2.81 - initCause(cause);
2.82 - }
2.83 -}
3.1 --- a/rt/emul/compact/src/main/java/java/lang/ClassValue.java Sun Aug 17 20:09:05 2014 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,760 +0,0 @@
3.4 -/*
3.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3.7 - *
3.8 - * This code is free software; you can redistribute it and/or modify it
3.9 - * under the terms of the GNU General Public License version 2 only, as
3.10 - * published by the Free Software Foundation. Oracle designates this
3.11 - * particular file as subject to the "Classpath" exception as provided
3.12 - * by Oracle in the LICENSE file that accompanied this code.
3.13 - *
3.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
3.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3.17 - * version 2 for more details (a copy is included in the LICENSE file that
3.18 - * accompanied this code).
3.19 - *
3.20 - * You should have received a copy of the GNU General Public License version
3.21 - * 2 along with this work; if not, write to the Free Software Foundation,
3.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3.23 - *
3.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3.25 - * or visit www.oracle.com if you need additional information or have any
3.26 - * questions.
3.27 - */
3.28 -
3.29 -package java.lang;
3.30 -
3.31 -import java.lang.ClassValue.ClassValueMap;
3.32 -import java.util.WeakHashMap;
3.33 -import java.lang.ref.WeakReference;
3.34 -import java.util.concurrent.atomic.AtomicInteger;
3.35 -
3.36 -import static java.lang.ClassValue.ClassValueMap.probeHomeLocation;
3.37 -import static java.lang.ClassValue.ClassValueMap.probeBackupLocations;
3.38 -
3.39 -/**
3.40 - * Lazily associate a computed value with (potentially) every type.
3.41 - * For example, if a dynamic language needs to construct a message dispatch
3.42 - * table for each class encountered at a message send call site,
3.43 - * it can use a {@code ClassValue} to cache information needed to
3.44 - * perform the message send quickly, for each class encountered.
3.45 - * @author John Rose, JSR 292 EG
3.46 - * @since 1.7
3.47 - */
3.48 -public abstract class ClassValue<T> {
3.49 - /**
3.50 - * Sole constructor. (For invocation by subclass constructors, typically
3.51 - * implicit.)
3.52 - */
3.53 - protected ClassValue() {
3.54 - }
3.55 -
3.56 - /**
3.57 - * Computes the given class's derived value for this {@code ClassValue}.
3.58 - * <p>
3.59 - * This method will be invoked within the first thread that accesses
3.60 - * the value with the {@link #get get} method.
3.61 - * <p>
3.62 - * Normally, this method is invoked at most once per class,
3.63 - * but it may be invoked again if there has been a call to
3.64 - * {@link #remove remove}.
3.65 - * <p>
3.66 - * If this method throws an exception, the corresponding call to {@code get}
3.67 - * will terminate abnormally with that exception, and no class value will be recorded.
3.68 - *
3.69 - * @param type the type whose class value must be computed
3.70 - * @return the newly computed value associated with this {@code ClassValue}, for the given class or interface
3.71 - * @see #get
3.72 - * @see #remove
3.73 - */
3.74 - protected abstract T computeValue(Class<?> type);
3.75 -
3.76 - /**
3.77 - * Returns the value for the given class.
3.78 - * If no value has yet been computed, it is obtained by
3.79 - * an invocation of the {@link #computeValue computeValue} method.
3.80 - * <p>
3.81 - * The actual installation of the value on the class
3.82 - * is performed atomically.
3.83 - * At that point, if several racing threads have
3.84 - * computed values, one is chosen, and returned to
3.85 - * all the racing threads.
3.86 - * <p>
3.87 - * The {@code type} parameter is typically a class, but it may be any type,
3.88 - * such as an interface, a primitive type (like {@code int.class}), or {@code void.class}.
3.89 - * <p>
3.90 - * In the absence of {@code remove} calls, a class value has a simple
3.91 - * state diagram: uninitialized and initialized.
3.92 - * When {@code remove} calls are made,
3.93 - * the rules for value observation are more complex.
3.94 - * See the documentation for {@link #remove remove} for more information.
3.95 - *
3.96 - * @param type the type whose class value must be computed or retrieved
3.97 - * @return the current value associated with this {@code ClassValue}, for the given class or interface
3.98 - * @throws NullPointerException if the argument is null
3.99 - * @see #remove
3.100 - * @see #computeValue
3.101 - */
3.102 - public T get(Class<?> type) {
3.103 - // non-racing this.hashCodeForCache : final int
3.104 - Entry<?>[] cache;
3.105 - Entry<T> e = probeHomeLocation(cache = getCacheCarefully(type), this);
3.106 - // racing e : current value <=> stale value from current cache or from stale cache
3.107 - // invariant: e is null or an Entry with readable Entry.version and Entry.value
3.108 - if (match(e))
3.109 - // invariant: No false positive matches. False negatives are OK if rare.
3.110 - // The key fact that makes this work: if this.version == e.version,
3.111 - // then this thread has a right to observe (final) e.value.
3.112 - return e.value();
3.113 - // The fast path can fail for any of these reasons:
3.114 - // 1. no entry has been computed yet
3.115 - // 2. hash code collision (before or after reduction mod cache.length)
3.116 - // 3. an entry has been removed (either on this type or another)
3.117 - // 4. the GC has somehow managed to delete e.version and clear the reference
3.118 - return getFromBackup(cache, type);
3.119 - }
3.120 -
3.121 - /**
3.122 - * Removes the associated value for the given class.
3.123 - * If this value is subsequently {@linkplain #get read} for the same class,
3.124 - * its value will be reinitialized by invoking its {@link #computeValue computeValue} method.
3.125 - * This may result in an additional invocation of the
3.126 - * {@code computeValue} method for the given class.
3.127 - * <p>
3.128 - * In order to explain the interaction between {@code get} and {@code remove} calls,
3.129 - * we must model the state transitions of a class value to take into account
3.130 - * the alternation between uninitialized and initialized states.
3.131 - * To do this, number these states sequentially from zero, and note that
3.132 - * uninitialized (or removed) states are numbered with even numbers,
3.133 - * while initialized (or re-initialized) states have odd numbers.
3.134 - * <p>
3.135 - * When a thread {@code T} removes a class value in state {@code 2N},
3.136 - * nothing happens, since the class value is already uninitialized.
3.137 - * Otherwise, the state is advanced atomically to {@code 2N+1}.
3.138 - * <p>
3.139 - * When a thread {@code T} queries a class value in state {@code 2N},
3.140 - * the thread first attempts to initialize the class value to state {@code 2N+1}
3.141 - * by invoking {@code computeValue} and installing the resulting value.
3.142 - * <p>
3.143 - * When {@code T} attempts to install the newly computed value,
3.144 - * if the state is still at {@code 2N}, the class value will be initialized
3.145 - * with the computed value, advancing it to state {@code 2N+1}.
3.146 - * <p>
3.147 - * Otherwise, whether the new state is even or odd,
3.148 - * {@code T} will discard the newly computed value
3.149 - * and retry the {@code get} operation.
3.150 - * <p>
3.151 - * Discarding and retrying is an important proviso,
3.152 - * since otherwise {@code T} could potentially install
3.153 - * a disastrously stale value. For example:
3.154 - * <ul>
3.155 - * <li>{@code T} calls {@code CV.get(C)} and sees state {@code 2N}
3.156 - * <li>{@code T} quickly computes a time-dependent value {@code V0} and gets ready to install it
3.157 - * <li>{@code T} is hit by an unlucky paging or scheduling event, and goes to sleep for a long time
3.158 - * <li>...meanwhile, {@code T2} also calls {@code CV.get(C)} and sees state {@code 2N}
3.159 - * <li>{@code T2} quickly computes a similar time-dependent value {@code V1} and installs it on {@code CV.get(C)}
3.160 - * <li>{@code T2} (or a third thread) then calls {@code CV.remove(C)}, undoing {@code T2}'s work
3.161 - * <li> the previous actions of {@code T2} are repeated several times
3.162 - * <li> also, the relevant computed values change over time: {@code V1}, {@code V2}, ...
3.163 - * <li>...meanwhile, {@code T} wakes up and attempts to install {@code V0}; <em>this must fail</em>
3.164 - * </ul>
3.165 - * We can assume in the above scenario that {@code CV.computeValue} uses locks to properly
3.166 - * observe the time-dependent states as it computes {@code V1}, etc.
3.167 - * This does not remove the threat of a stale value, since there is a window of time
3.168 - * between the return of {@code computeValue} in {@code T} and the installation
3.169 - * of the the new value. No user synchronization is possible during this time.
3.170 - *
3.171 - * @param type the type whose class value must be removed
3.172 - * @throws NullPointerException if the argument is null
3.173 - */
3.174 - public void remove(Class<?> type) {
3.175 - ClassValueMap map = getMap(type);
3.176 - map.removeEntry(this);
3.177 - }
3.178 -
3.179 - // Possible functionality for JSR 292 MR 1
3.180 - /*public*/ void put(Class<?> type, T value) {
3.181 - ClassValueMap map = getMap(type);
3.182 - map.changeEntry(this, value);
3.183 - }
3.184 -
3.185 - /// --------
3.186 - /// Implementation...
3.187 - /// --------
3.188 -
3.189 - /** Return the cache, if it exists, else a dummy empty cache. */
3.190 - private static Entry<?>[] getCacheCarefully(Class<?> type) {
3.191 - // racing type.classValueMap{.cacheArray} : null => new Entry[X] <=> new Entry[Y]
3.192 - ClassValueMap map = (ClassValueMap) type.classValueMap;
3.193 - if (map == null) return EMPTY_CACHE;
3.194 - Entry<?>[] cache = map.getCache();
3.195 - return cache;
3.196 - // invariant: returned value is safe to dereference and check for an Entry
3.197 - }
3.198 -
3.199 - /** Initial, one-element, empty cache used by all Class instances. Must never be filled. */
3.200 - private static final Entry<?>[] EMPTY_CACHE = { null };
3.201 -
3.202 - /**
3.203 - * Slow tail of ClassValue.get to retry at nearby locations in the cache,
3.204 - * or take a slow lock and check the hash table.
3.205 - * Called only if the first probe was empty or a collision.
3.206 - * This is a separate method, so compilers can process it independently.
3.207 - */
3.208 - private T getFromBackup(Entry<?>[] cache, Class<?> type) {
3.209 - Entry<T> e = probeBackupLocations(cache, this);
3.210 - if (e != null)
3.211 - return e.value();
3.212 - return getFromHashMap(type);
3.213 - }
3.214 -
3.215 - // Hack to suppress warnings on the (T) cast, which is a no-op.
3.216 - @SuppressWarnings("unchecked")
3.217 - Entry<T> castEntry(Entry<?> e) { return (Entry<T>) e; }
3.218 -
3.219 - /** Called when the fast path of get fails, and cache reprobe also fails.
3.220 - */
3.221 - private T getFromHashMap(Class<?> type) {
3.222 - // The fail-safe recovery is to fall back to the underlying classValueMap.
3.223 - ClassValueMap map = getMap(type);
3.224 - for (;;) {
3.225 - Entry<T> e = map.startEntry(this);
3.226 - if (!e.isPromise())
3.227 - return e.value();
3.228 - try {
3.229 - // Try to make a real entry for the promised version.
3.230 - e = makeEntry(e.version(), computeValue(type));
3.231 - } finally {
3.232 - // Whether computeValue throws or returns normally,
3.233 - // be sure to remove the empty entry.
3.234 - e = map.finishEntry(this, e);
3.235 - }
3.236 - if (e != null)
3.237 - return e.value();
3.238 - // else try again, in case a racing thread called remove (so e == null)
3.239 - }
3.240 - }
3.241 -
3.242 - /** Check that e is non-null, matches this ClassValue, and is live. */
3.243 - boolean match(Entry<?> e) {
3.244 - // racing e.version : null (blank) => unique Version token => null (GC-ed version)
3.245 - // non-racing this.version : v1 => v2 => ... (updates are read faithfully from volatile)
3.246 - return (e != null && e.get() == this.version);
3.247 - // invariant: No false positives on version match. Null is OK for false negative.
3.248 - // invariant: If version matches, then e.value is readable (final set in Entry.<init>)
3.249 - }
3.250 -
3.251 - /** Internal hash code for accessing Class.classValueMap.cacheArray. */
3.252 - final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK;
3.253 -
3.254 - /** Value stream for hashCodeForCache. See similar structure in ThreadLocal. */
3.255 - private static final AtomicInteger nextHashCode = new AtomicInteger();
3.256 -
3.257 - /** Good for power-of-two tables. See similar structure in ThreadLocal. */
3.258 - private static final int HASH_INCREMENT = 0x61c88647;
3.259 -
3.260 - /** Mask a hash code to be positive but not too large, to prevent wraparound. */
3.261 - static final int HASH_MASK = (-1 >>> 2);
3.262 -
3.263 - /**
3.264 - * Private key for retrieval of this object from ClassValueMap.
3.265 - */
3.266 - static class Identity {
3.267 - }
3.268 - /**
3.269 - * This ClassValue's identity, expressed as an opaque object.
3.270 - * The main object {@code ClassValue.this} is incorrect since
3.271 - * subclasses may override {@code ClassValue.equals}, which
3.272 - * could confuse keys in the ClassValueMap.
3.273 - */
3.274 - final Identity identity = new Identity();
3.275 -
3.276 - /**
3.277 - * Current version for retrieving this class value from the cache.
3.278 - * Any number of computeValue calls can be cached in association with one version.
3.279 - * But the version changes when a remove (on any type) is executed.
3.280 - * A version change invalidates all cache entries for the affected ClassValue,
3.281 - * by marking them as stale. Stale cache entries do not force another call
3.282 - * to computeValue, but they do require a synchronized visit to a backing map.
3.283 - * <p>
3.284 - * All user-visible state changes on the ClassValue take place under
3.285 - * a lock inside the synchronized methods of ClassValueMap.
3.286 - * Readers (of ClassValue.get) are notified of such state changes
3.287 - * when this.version is bumped to a new token.
3.288 - * This variable must be volatile so that an unsynchronized reader
3.289 - * will receive the notification without delay.
3.290 - * <p>
3.291 - * If version were not volatile, one thread T1 could persistently hold onto
3.292 - * a stale value this.value == V1, while while another thread T2 advances
3.293 - * (under a lock) to this.value == V2. This will typically be harmless,
3.294 - * but if T1 and T2 interact causally via some other channel, such that
3.295 - * T1's further actions are constrained (in the JMM) to happen after
3.296 - * the V2 event, then T1's observation of V1 will be an error.
3.297 - * <p>
3.298 - * The practical effect of making this.version be volatile is that it cannot
3.299 - * be hoisted out of a loop (by an optimizing JIT) or otherwise cached.
3.300 - * Some machines may also require a barrier instruction to execute
3.301 - * before this.version.
3.302 - */
3.303 - private volatile Version<T> version = new Version<>(this);
3.304 - Version<T> version() { return version; }
3.305 - void bumpVersion() { version = new Version<>(this); }
3.306 - static class Version<T> {
3.307 - private final ClassValue<T> classValue;
3.308 - private final Entry<T> promise = new Entry<>(this);
3.309 - Version(ClassValue<T> classValue) { this.classValue = classValue; }
3.310 - ClassValue<T> classValue() { return classValue; }
3.311 - Entry<T> promise() { return promise; }
3.312 - boolean isLive() { return classValue.version() == this; }
3.313 - }
3.314 -
3.315 - /** One binding of a value to a class via a ClassValue.
3.316 - * States are:<ul>
3.317 - * <li> promise if value == Entry.this
3.318 - * <li> else dead if version == null
3.319 - * <li> else stale if version != classValue.version
3.320 - * <li> else live </ul>
3.321 - * Promises are never put into the cache; they only live in the
3.322 - * backing map while a computeValue call is in flight.
3.323 - * Once an entry goes stale, it can be reset at any time
3.324 - * into the dead state.
3.325 - */
3.326 - static class Entry<T> extends WeakReference<Version<T>> {
3.327 - final Object value; // usually of type T, but sometimes (Entry)this
3.328 - Entry(Version<T> version, T value) {
3.329 - super(version);
3.330 - this.value = value; // for a regular entry, value is of type T
3.331 - }
3.332 - private void assertNotPromise() { assert(!isPromise()); }
3.333 - /** For creating a promise. */
3.334 - Entry(Version<T> version) {
3.335 - super(version);
3.336 - this.value = this; // for a promise, value is not of type T, but Entry!
3.337 - }
3.338 - /** Fetch the value. This entry must not be a promise. */
3.339 - @SuppressWarnings("unchecked") // if !isPromise, type is T
3.340 - T value() { assertNotPromise(); return (T) value; }
3.341 - boolean isPromise() { return value == this; }
3.342 - Version<T> version() { return get(); }
3.343 - ClassValue<T> classValueOrNull() {
3.344 - Version<T> v = version();
3.345 - return (v == null) ? null : v.classValue();
3.346 - }
3.347 - boolean isLive() {
3.348 - Version<T> v = version();
3.349 - if (v == null) return false;
3.350 - if (v.isLive()) return true;
3.351 - clear();
3.352 - return false;
3.353 - }
3.354 - Entry<T> refreshVersion(Version<T> v2) {
3.355 - assertNotPromise();
3.356 - @SuppressWarnings("unchecked") // if !isPromise, type is T
3.357 - Entry<T> e2 = new Entry<>(v2, (T) value);
3.358 - clear();
3.359 - // value = null -- caller must drop
3.360 - return e2;
3.361 - }
3.362 - static final Entry<?> DEAD_ENTRY = new Entry<>(null, null);
3.363 - }
3.364 -
3.365 - /** Return the backing map associated with this type. */
3.366 - private static ClassValueMap getMap(Class<?> type) {
3.367 - // racing type.classValueMap : null (blank) => unique ClassValueMap
3.368 - // if a null is observed, a map is created (lazily, synchronously, uniquely)
3.369 - // all further access to that map is synchronized
3.370 - ClassValueMap map = (ClassValueMap)type.classValueMap;
3.371 - if (map != null) return map;
3.372 - return initializeMap(type);
3.373 - }
3.374 -
3.375 - private static final Object CRITICAL_SECTION = new Object();
3.376 - private static ClassValueMap initializeMap(Class<?> type) {
3.377 - ClassValueMap map;
3.378 - synchronized (CRITICAL_SECTION) { // private object to avoid deadlocks
3.379 - // happens about once per type
3.380 - if ((map = (ClassValueMap)type.classValueMap) == null)
3.381 - type.classValueMap = map = new ClassValueMap(type);
3.382 - }
3.383 - return map;
3.384 - }
3.385 -
3.386 - static <T> Entry<T> makeEntry(Version<T> explicitVersion, T value) {
3.387 - // Note that explicitVersion might be different from this.version.
3.388 - return new Entry<>(explicitVersion, value);
3.389 -
3.390 - // As soon as the Entry is put into the cache, the value will be
3.391 - // reachable via a data race (as defined by the Java Memory Model).
3.392 - // This race is benign, assuming the value object itself can be
3.393 - // read safely by multiple threads. This is up to the user.
3.394 - //
3.395 - // The entry and version fields themselves can be safely read via
3.396 - // a race because they are either final or have controlled states.
3.397 - // If the pointer from the entry to the version is still null,
3.398 - // or if the version goes immediately dead and is nulled out,
3.399 - // the reader will take the slow path and retry under a lock.
3.400 - }
3.401 -
3.402 - // The following class could also be top level and non-public:
3.403 -
3.404 - /** A backing map for all ClassValues, relative a single given type.
3.405 - * Gives a fully serialized "true state" for each pair (ClassValue cv, Class type).
3.406 - * Also manages an unserialized fast-path cache.
3.407 - */
3.408 - static class ClassValueMap extends WeakHashMap<ClassValue.Identity, Entry<?>> {
3.409 - private final Class<?> type;
3.410 - private Entry<?>[] cacheArray;
3.411 - private int cacheLoad, cacheLoadLimit;
3.412 -
3.413 - /** Number of entries initially allocated to each type when first used with any ClassValue.
3.414 - * It would be pointless to make this much smaller than the Class and ClassValueMap objects themselves.
3.415 - * Must be a power of 2.
3.416 - */
3.417 - private static final int INITIAL_ENTRIES = 32;
3.418 -
3.419 - /** Build a backing map for ClassValues, relative the given type.
3.420 - * Also, create an empty cache array and install it on the class.
3.421 - */
3.422 - ClassValueMap(Class<?> type) {
3.423 - this.type = type;
3.424 - sizeCache(INITIAL_ENTRIES);
3.425 - }
3.426 -
3.427 - Entry<?>[] getCache() { return cacheArray; }
3.428 -
3.429 - /** Initiate a query. Store a promise (placeholder) if there is no value yet. */
3.430 - synchronized
3.431 - <T> Entry<T> startEntry(ClassValue<T> classValue) {
3.432 - @SuppressWarnings("unchecked") // one map has entries for all value types <T>
3.433 - Entry<T> e = (Entry<T>) get(classValue.identity);
3.434 - Version<T> v = classValue.version();
3.435 - if (e == null) {
3.436 - e = v.promise();
3.437 - // The presence of a promise means that a value is pending for v.
3.438 - // Eventually, finishEntry will overwrite the promise.
3.439 - put(classValue.identity, e);
3.440 - // Note that the promise is never entered into the cache!
3.441 - return e;
3.442 - } else if (e.isPromise()) {
3.443 - // Somebody else has asked the same question.
3.444 - // Let the races begin!
3.445 - if (e.version() != v) {
3.446 - e = v.promise();
3.447 - put(classValue.identity, e);
3.448 - }
3.449 - return e;
3.450 - } else {
3.451 - // there is already a completed entry here; report it
3.452 - if (e.version() != v) {
3.453 - // There is a stale but valid entry here; make it fresh again.
3.454 - // Once an entry is in the hash table, we don't care what its version is.
3.455 - e = e.refreshVersion(v);
3.456 - put(classValue.identity, e);
3.457 - }
3.458 - // Add to the cache, to enable the fast path, next time.
3.459 - checkCacheLoad();
3.460 - addToCache(classValue, e);
3.461 - return e;
3.462 - }
3.463 - }
3.464 -
3.465 - /** Finish a query. Overwrite a matching placeholder. Drop stale incoming values. */
3.466 - synchronized
3.467 - <T> Entry<T> finishEntry(ClassValue<T> classValue, Entry<T> e) {
3.468 - @SuppressWarnings("unchecked") // one map has entries for all value types <T>
3.469 - Entry<T> e0 = (Entry<T>) get(classValue.identity);
3.470 - if (e == e0) {
3.471 - // We can get here during exception processing, unwinding from computeValue.
3.472 - assert(e.isPromise());
3.473 - remove(classValue.identity);
3.474 - return null;
3.475 - } else if (e0 != null && e0.isPromise() && e0.version() == e.version()) {
3.476 - // If e0 matches the intended entry, there has not been a remove call
3.477 - // between the previous startEntry and now. So now overwrite e0.
3.478 - Version<T> v = classValue.version();
3.479 - if (e.version() != v)
3.480 - e = e.refreshVersion(v);
3.481 - put(classValue.identity, e);
3.482 - // Add to the cache, to enable the fast path, next time.
3.483 - checkCacheLoad();
3.484 - addToCache(classValue, e);
3.485 - return e;
3.486 - } else {
3.487 - // Some sort of mismatch; caller must try again.
3.488 - return null;
3.489 - }
3.490 - }
3.491 -
3.492 - /** Remove an entry. */
3.493 - synchronized
3.494 - void removeEntry(ClassValue<?> classValue) {
3.495 - Entry<?> e = remove(classValue.identity);
3.496 - if (e == null) {
3.497 - // Uninitialized, and no pending calls to computeValue. No change.
3.498 - } else if (e.isPromise()) {
3.499 - // State is uninitialized, with a pending call to finishEntry.
3.500 - // Since remove is a no-op in such a state, keep the promise
3.501 - // by putting it back into the map.
3.502 - put(classValue.identity, e);
3.503 - } else {
3.504 - // In an initialized state. Bump forward, and de-initialize.
3.505 - classValue.bumpVersion();
3.506 - // Make all cache elements for this guy go stale.
3.507 - removeStaleEntries(classValue);
3.508 - }
3.509 - }
3.510 -
3.511 - /** Change the value for an entry. */
3.512 - synchronized
3.513 - <T> void changeEntry(ClassValue<T> classValue, T value) {
3.514 - @SuppressWarnings("unchecked") // one map has entries for all value types <T>
3.515 - Entry<T> e0 = (Entry<T>) get(classValue.identity);
3.516 - Version<T> version = classValue.version();
3.517 - if (e0 != null) {
3.518 - if (e0.version() == version && e0.value() == value)
3.519 - // no value change => no version change needed
3.520 - return;
3.521 - classValue.bumpVersion();
3.522 - removeStaleEntries(classValue);
3.523 - }
3.524 - Entry<T> e = makeEntry(version, value);
3.525 - put(classValue.identity, e);
3.526 - // Add to the cache, to enable the fast path, next time.
3.527 - checkCacheLoad();
3.528 - addToCache(classValue, e);
3.529 - }
3.530 -
3.531 - /// --------
3.532 - /// Cache management.
3.533 - /// --------
3.534 -
3.535 - // Statics do not need synchronization.
3.536 -
3.537 - /** Load the cache entry at the given (hashed) location. */
3.538 - static Entry<?> loadFromCache(Entry<?>[] cache, int i) {
3.539 - // non-racing cache.length : constant
3.540 - // racing cache[i & (mask)] : null <=> Entry
3.541 - return cache[i & (cache.length-1)];
3.542 - // invariant: returned value is null or well-constructed (ready to match)
3.543 - }
3.544 -
3.545 - /** Look in the cache, at the home location for the given ClassValue. */
3.546 - static <T> Entry<T> probeHomeLocation(Entry<?>[] cache, ClassValue<T> classValue) {
3.547 - return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache));
3.548 - }
3.549 -
3.550 - /** Given that first probe was a collision, retry at nearby locations. */
3.551 - static <T> Entry<T> probeBackupLocations(Entry<?>[] cache, ClassValue<T> classValue) {
3.552 - if (PROBE_LIMIT <= 0) return null;
3.553 - // Probe the cache carefully, in a range of slots.
3.554 - int mask = (cache.length-1);
3.555 - int home = (classValue.hashCodeForCache & mask);
3.556 - Entry<?> e2 = cache[home]; // victim, if we find the real guy
3.557 - if (e2 == null) {
3.558 - return null; // if nobody is at home, no need to search nearby
3.559 - }
3.560 - // assume !classValue.match(e2), but do not assert, because of races
3.561 - int pos2 = -1;
3.562 - for (int i = home + 1; i < home + PROBE_LIMIT; i++) {
3.563 - Entry<?> e = cache[i & mask];
3.564 - if (e == null) {
3.565 - break; // only search within non-null runs
3.566 - }
3.567 - if (classValue.match(e)) {
3.568 - // relocate colliding entry e2 (from cache[home]) to first empty slot
3.569 - cache[home] = e;
3.570 - if (pos2 >= 0) {
3.571 - cache[i & mask] = Entry.DEAD_ENTRY;
3.572 - } else {
3.573 - pos2 = i;
3.574 - }
3.575 - cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT)
3.576 - ? e2 // put e2 here if it fits
3.577 - : Entry.DEAD_ENTRY);
3.578 - return classValue.castEntry(e);
3.579 - }
3.580 - // Remember first empty slot, if any:
3.581 - if (!e.isLive() && pos2 < 0) pos2 = i;
3.582 - }
3.583 - return null;
3.584 - }
3.585 -
3.586 - /** How far out of place is e? */
3.587 - private static int entryDislocation(Entry<?>[] cache, int pos, Entry<?> e) {
3.588 - ClassValue<?> cv = e.classValueOrNull();
3.589 - if (cv == null) return 0; // entry is not live!
3.590 - int mask = (cache.length-1);
3.591 - return (pos - cv.hashCodeForCache) & mask;
3.592 - }
3.593 -
3.594 - /// --------
3.595 - /// Below this line all functions are private, and assume synchronized access.
3.596 - /// --------
3.597 -
3.598 - private void sizeCache(int length) {
3.599 - assert((length & (length-1)) == 0); // must be power of 2
3.600 - cacheLoad = 0;
3.601 - cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100);
3.602 - cacheArray = new Entry<?>[length];
3.603 - }
3.604 -
3.605 - /** Make sure the cache load stays below its limit, if possible. */
3.606 - private void checkCacheLoad() {
3.607 - if (cacheLoad >= cacheLoadLimit) {
3.608 - reduceCacheLoad();
3.609 - }
3.610 - }
3.611 - private void reduceCacheLoad() {
3.612 - removeStaleEntries();
3.613 - if (cacheLoad < cacheLoadLimit)
3.614 - return; // win
3.615 - Entry<?>[] oldCache = getCache();
3.616 - if (oldCache.length > HASH_MASK)
3.617 - return; // lose
3.618 - sizeCache(oldCache.length * 2);
3.619 - for (Entry<?> e : oldCache) {
3.620 - if (e != null && e.isLive()) {
3.621 - addToCache(e);
3.622 - }
3.623 - }
3.624 - }
3.625 -
3.626 - /** Remove stale entries in the given range.
3.627 - * Should be executed under a Map lock.
3.628 - */
3.629 - private void removeStaleEntries(Entry<?>[] cache, int begin, int count) {
3.630 - if (PROBE_LIMIT <= 0) return;
3.631 - int mask = (cache.length-1);
3.632 - int removed = 0;
3.633 - for (int i = begin; i < begin + count; i++) {
3.634 - Entry<?> e = cache[i & mask];
3.635 - if (e == null || e.isLive())
3.636 - continue; // skip null and live entries
3.637 - Entry<?> replacement = null;
3.638 - if (PROBE_LIMIT > 1) {
3.639 - // avoid breaking up a non-null run
3.640 - replacement = findReplacement(cache, i);
3.641 - }
3.642 - cache[i & mask] = replacement;
3.643 - if (replacement == null) removed += 1;
3.644 - }
3.645 - cacheLoad = Math.max(0, cacheLoad - removed);
3.646 - }
3.647 -
3.648 - /** Clearing a cache slot risks disconnecting following entries
3.649 - * from the head of a non-null run, which would allow them
3.650 - * to be found via reprobes. Find an entry after cache[begin]
3.651 - * to plug into the hole, or return null if none is needed.
3.652 - */
3.653 - private Entry<?> findReplacement(Entry<?>[] cache, int home1) {
3.654 - Entry<?> replacement = null;
3.655 - int haveReplacement = -1, replacementPos = 0;
3.656 - int mask = (cache.length-1);
3.657 - for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) {
3.658 - Entry<?> e2 = cache[i2 & mask];
3.659 - if (e2 == null) break; // End of non-null run.
3.660 - if (!e2.isLive()) continue; // Doomed anyway.
3.661 - int dis2 = entryDislocation(cache, i2, e2);
3.662 - if (dis2 == 0) continue; // e2 already optimally placed
3.663 - int home2 = i2 - dis2;
3.664 - if (home2 <= home1) {
3.665 - // e2 can replace entry at cache[home1]
3.666 - if (home2 == home1) {
3.667 - // Put e2 exactly where he belongs.
3.668 - haveReplacement = 1;
3.669 - replacementPos = i2;
3.670 - replacement = e2;
3.671 - } else if (haveReplacement <= 0) {
3.672 - haveReplacement = 0;
3.673 - replacementPos = i2;
3.674 - replacement = e2;
3.675 - }
3.676 - // And keep going, so we can favor larger dislocations.
3.677 - }
3.678 - }
3.679 - if (haveReplacement >= 0) {
3.680 - if (cache[(replacementPos+1) & mask] != null) {
3.681 - // Be conservative, to avoid breaking up a non-null run.
3.682 - cache[replacementPos & mask] = (Entry<?>) Entry.DEAD_ENTRY;
3.683 - } else {
3.684 - cache[replacementPos & mask] = null;
3.685 - cacheLoad -= 1;
3.686 - }
3.687 - }
3.688 - return replacement;
3.689 - }
3.690 -
3.691 - /** Remove stale entries in the range near classValue. */
3.692 - private void removeStaleEntries(ClassValue<?> classValue) {
3.693 - removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT);
3.694 - }
3.695 -
3.696 - /** Remove all stale entries, everywhere. */
3.697 - private void removeStaleEntries() {
3.698 - Entry<?>[] cache = getCache();
3.699 - removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);
3.700 - }
3.701 -
3.702 - /** Add the given entry to the cache, in its home location, unless it is out of date. */
3.703 - private <T> void addToCache(Entry<T> e) {
3.704 - ClassValue<T> classValue = e.classValueOrNull();
3.705 - if (classValue != null)
3.706 - addToCache(classValue, e);
3.707 - }
3.708 -
3.709 - /** Add the given entry to the cache, in its home location. */
3.710 - private <T> void addToCache(ClassValue<T> classValue, Entry<T> e) {
3.711 - if (PROBE_LIMIT <= 0) return; // do not fill cache
3.712 - // Add e to the cache.
3.713 - Entry<?>[] cache = getCache();
3.714 - int mask = (cache.length-1);
3.715 - int home = classValue.hashCodeForCache & mask;
3.716 - Entry<?> e2 = placeInCache(cache, home, e, false);
3.717 - if (e2 == null) return; // done
3.718 - if (PROBE_LIMIT > 1) {
3.719 - // try to move e2 somewhere else in his probe range
3.720 - int dis2 = entryDislocation(cache, home, e2);
3.721 - int home2 = home - dis2;
3.722 - for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) {
3.723 - if (placeInCache(cache, i2 & mask, e2, true) == null) {
3.724 - return;
3.725 - }
3.726 - }
3.727 - }
3.728 - // Note: At this point, e2 is just dropped from the cache.
3.729 - }
3.730 -
3.731 - /** Store the given entry. Update cacheLoad, and return any live victim.
3.732 - * 'Gently' means return self rather than dislocating a live victim.
3.733 - */
3.734 - private Entry<?> placeInCache(Entry<?>[] cache, int pos, Entry<?> e, boolean gently) {
3.735 - Entry<?> e2 = overwrittenEntry(cache[pos]);
3.736 - if (gently && e2 != null) {
3.737 - // do not overwrite a live entry
3.738 - return e;
3.739 - } else {
3.740 - cache[pos] = e;
3.741 - return e2;
3.742 - }
3.743 - }
3.744 -
3.745 - /** Note an entry that is about to be overwritten.
3.746 - * If it is not live, quietly replace it by null.
3.747 - * If it is an actual null, increment cacheLoad,
3.748 - * because the caller is going to store something
3.749 - * in its place.
3.750 - */
3.751 - private <T> Entry<T> overwrittenEntry(Entry<T> e2) {
3.752 - if (e2 == null) cacheLoad += 1;
3.753 - else if (e2.isLive()) return e2;
3.754 - return null;
3.755 - }
3.756 -
3.757 - /** Percent loading of cache before resize. */
3.758 - private static final int CACHE_LOAD_LIMIT = 67; // 0..100
3.759 - /** Maximum number of probes to attempt. */
3.760 - private static final int PROBE_LIMIT = 6; // 1..
3.761 - // N.B. Set PROBE_LIMIT=0 to disable all fast paths.
3.762 - }
3.763 -}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/rt/emul/compact/src/main/java/java/lang/Cloneable.java Sun Aug 17 20:15:56 2014 +0200
4.3 @@ -0,0 +1,54 @@
4.4 +/*
4.5 + * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4.7 + *
4.8 + * This code is free software; you can redistribute it and/or modify it
4.9 + * under the terms of the GNU General Public License version 2 only, as
4.10 + * published by the Free Software Foundation. Oracle designates this
4.11 + * particular file as subject to the "Classpath" exception as provided
4.12 + * by Oracle in the LICENSE file that accompanied this code.
4.13 + *
4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
4.17 + * version 2 for more details (a copy is included in the LICENSE file that
4.18 + * accompanied this code).
4.19 + *
4.20 + * You should have received a copy of the GNU General Public License version
4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4.23 + *
4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4.25 + * or visit www.oracle.com if you need additional information or have any
4.26 + * questions.
4.27 + */
4.28 +
4.29 +package java.lang;
4.30 +
4.31 +/**
4.32 + * A class implements the <code>Cloneable</code> interface to
4.33 + * indicate to the {@link java.lang.Object#clone()} method that it
4.34 + * is legal for that method to make a
4.35 + * field-for-field copy of instances of that class.
4.36 + * <p>
4.37 + * Invoking Object's clone method on an instance that does not implement the
4.38 + * <code>Cloneable</code> interface results in the exception
4.39 + * <code>CloneNotSupportedException</code> being thrown.
4.40 + * <p>
4.41 + * By convention, classes that implement this interface should override
4.42 + * <tt>Object.clone</tt> (which is protected) with a public method.
4.43 + * See {@link java.lang.Object#clone()} for details on overriding this
4.44 + * method.
4.45 + * <p>
4.46 + * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
4.47 + * Therefore, it is not possible to clone an object merely by virtue of the
4.48 + * fact that it implements this interface. Even if the clone method is invoked
4.49 + * reflectively, there is no guarantee that it will succeed.
4.50 + *
4.51 + * @author unascribed
4.52 + * @see java.lang.CloneNotSupportedException
4.53 + * @see java.lang.Object#clone()
4.54 + * @since JDK1.0
4.55 + */
4.56 +public interface Cloneable {
4.57 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/rt/emul/compact/src/main/java/java/lang/IncompatibleClassChangeError.java Sun Aug 17 20:15:56 2014 +0200
5.3 @@ -0,0 +1,57 @@
5.4 +/*
5.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5.7 + *
5.8 + * This code is free software; you can redistribute it and/or modify it
5.9 + * under the terms of the GNU General Public License version 2 only, as
5.10 + * published by the Free Software Foundation. Oracle designates this
5.11 + * particular file as subject to the "Classpath" exception as provided
5.12 + * by Oracle in the LICENSE file that accompanied this code.
5.13 + *
5.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
5.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
5.17 + * version 2 for more details (a copy is included in the LICENSE file that
5.18 + * accompanied this code).
5.19 + *
5.20 + * You should have received a copy of the GNU General Public License version
5.21 + * 2 along with this work; if not, write to the Free Software Foundation,
5.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5.23 + *
5.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5.25 + * or visit www.oracle.com if you need additional information or have any
5.26 + * questions.
5.27 + */
5.28 +
5.29 +package java.lang;
5.30 +
5.31 +/**
5.32 + * Thrown when an incompatible class change has occurred to some class
5.33 + * definition. The definition of some class, on which the currently
5.34 + * executing method depends, has since changed.
5.35 + *
5.36 + * @author unascribed
5.37 + * @since JDK1.0
5.38 + */
5.39 +public
5.40 +class IncompatibleClassChangeError extends LinkageError {
5.41 + private static final long serialVersionUID = -4914975503642802119L;
5.42 +
5.43 + /**
5.44 + * Constructs an <code>IncompatibleClassChangeError</code> with no
5.45 + * detail message.
5.46 + */
5.47 + public IncompatibleClassChangeError () {
5.48 + super();
5.49 + }
5.50 +
5.51 + /**
5.52 + * Constructs an <code>IncompatibleClassChangeError</code> with the
5.53 + * specified detail message.
5.54 + *
5.55 + * @param s the detail message.
5.56 + */
5.57 + public IncompatibleClassChangeError(String s) {
5.58 + super(s);
5.59 + }
5.60 +}
6.1 --- a/rt/emul/compact/src/main/java/java/lang/InternalError.java Sun Aug 17 20:09:05 2014 +0200
6.2 +++ b/rt/emul/compact/src/main/java/java/lang/InternalError.java Sun Aug 17 20:15:56 2014 +0200
6.3 @@ -1,5 +1,5 @@
6.4 /*
6.5 - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
6.6 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
6.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6.8 *
6.9 * This code is free software; you can redistribute it and/or modify it
6.10 @@ -32,7 +32,8 @@
6.11 * @author unascribed
6.12 * @since JDK1.0
6.13 */
6.14 -public class InternalError extends VirtualMachineError {
6.15 +public
6.16 +class InternalError extends VirtualMachineError {
6.17 private static final long serialVersionUID = -9062593416125562365L;
6.18
6.19 /**
6.20 @@ -46,45 +47,9 @@
6.21 * Constructs an <code>InternalError</code> with the specified
6.22 * detail message.
6.23 *
6.24 - * @param message the detail message.
6.25 + * @param s the detail message.
6.26 */
6.27 - public InternalError(String message) {
6.28 - super(message);
6.29 + public InternalError(String s) {
6.30 + super(s);
6.31 }
6.32 -
6.33 -
6.34 - /**
6.35 - * Constructs an {@code InternalError} with the specified detail
6.36 - * message and cause. <p>Note that the detail message associated
6.37 - * with {@code cause} is <i>not</i> automatically incorporated in
6.38 - * this error's detail message.
6.39 - *
6.40 - * @param message the detail message (which is saved for later retrieval
6.41 - * by the {@link #getMessage()} method).
6.42 - * @param cause the cause (which is saved for later retrieval by the
6.43 - * {@link #getCause()} method). (A {@code null} value is
6.44 - * permitted, and indicates that the cause is nonexistent or
6.45 - * unknown.)
6.46 - * @since 1.8
6.47 - */
6.48 - public InternalError(String message, Throwable cause) {
6.49 - super(message, cause);
6.50 - }
6.51 -
6.52 - /**
6.53 - * Constructs an {@code InternalError} with the specified cause
6.54 - * and a detail message of {@code (cause==null ? null :
6.55 - * cause.toString())} (which typically contains the class and
6.56 - * detail message of {@code cause}).
6.57 - *
6.58 - * @param cause the cause (which is saved for later retrieval by the
6.59 - * {@link #getCause()} method). (A {@code null} value is
6.60 - * permitted, and indicates that the cause is nonexistent or
6.61 - * unknown.)
6.62 - * @since 1.8
6.63 - */
6.64 - public InternalError(Throwable cause) {
6.65 - super(cause);
6.66 - }
6.67 -
6.68 }
7.1 --- a/rt/emul/compact/src/main/java/java/lang/NoSuchFieldException.java Sun Aug 17 20:09:05 2014 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,52 +0,0 @@
7.4 -/*
7.5 - * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
7.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7.7 - *
7.8 - * This code is free software; you can redistribute it and/or modify it
7.9 - * under the terms of the GNU General Public License version 2 only, as
7.10 - * published by the Free Software Foundation. Oracle designates this
7.11 - * particular file as subject to the "Classpath" exception as provided
7.12 - * by Oracle in the LICENSE file that accompanied this code.
7.13 - *
7.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
7.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
7.17 - * version 2 for more details (a copy is included in the LICENSE file that
7.18 - * accompanied this code).
7.19 - *
7.20 - * You should have received a copy of the GNU General Public License version
7.21 - * 2 along with this work; if not, write to the Free Software Foundation,
7.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
7.23 - *
7.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
7.25 - * or visit www.oracle.com if you need additional information or have any
7.26 - * questions.
7.27 - */
7.28 -
7.29 -package java.lang;
7.30 -
7.31 -/**
7.32 - * Signals that the class doesn't have a field of a specified name.
7.33 - *
7.34 - * @author unascribed
7.35 - * @since JDK1.1
7.36 - */
7.37 -public class NoSuchFieldException extends ReflectiveOperationException {
7.38 - private static final long serialVersionUID = -6143714805279938260L;
7.39 -
7.40 - /**
7.41 - * Constructor.
7.42 - */
7.43 - public NoSuchFieldException() {
7.44 - super();
7.45 - }
7.46 -
7.47 - /**
7.48 - * Constructor with a detail message.
7.49 - *
7.50 - * @param s the detail message
7.51 - */
7.52 - public NoSuchFieldException(String s) {
7.53 - super(s);
7.54 - }
7.55 -}
8.1 --- a/rt/emul/compact/src/main/java/java/lang/TypeNotPresentException.java Sun Aug 17 20:09:05 2014 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,70 +0,0 @@
8.4 -/*
8.5 - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
8.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8.7 - *
8.8 - * This code is free software; you can redistribute it and/or modify it
8.9 - * under the terms of the GNU General Public License version 2 only, as
8.10 - * published by the Free Software Foundation. Oracle designates this
8.11 - * particular file as subject to the "Classpath" exception as provided
8.12 - * by Oracle in the LICENSE file that accompanied this code.
8.13 - *
8.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
8.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
8.17 - * version 2 for more details (a copy is included in the LICENSE file that
8.18 - * accompanied this code).
8.19 - *
8.20 - * You should have received a copy of the GNU General Public License version
8.21 - * 2 along with this work; if not, write to the Free Software Foundation,
8.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8.23 - *
8.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8.25 - * or visit www.oracle.com if you need additional information or have any
8.26 - * questions.
8.27 - */
8.28 -
8.29 -package java.lang;
8.30 -
8.31 -/**
8.32 - * Thrown when an application tries to access a type using a string
8.33 - * representing the type's name, but no definition for the type with
8.34 - * the specified name can be found. This exception differs from
8.35 - * {@link ClassNotFoundException} in that <tt>ClassNotFoundException</tt> is a
8.36 - * checked exception, whereas this exception is unchecked.
8.37 - *
8.38 - * <p>Note that this exception may be used when undefined type variables
8.39 - * are accessed as well as when types (e.g., classes, interfaces or
8.40 - * annotation types) are loaded.
8.41 - * In particular, this exception can be thrown by the {@linkplain
8.42 - * java.lang.reflect.AnnotatedElement API used to read annotations
8.43 - * reflectively}.
8.44 - *
8.45 - * @author Josh Bloch
8.46 - * @see java.lang.reflect.AnnotatedElement
8.47 - * @since 1.5
8.48 - */
8.49 -public class TypeNotPresentException extends RuntimeException {
8.50 - private static final long serialVersionUID = -5101214195716534496L;
8.51 -
8.52 - private String typeName;
8.53 -
8.54 - /**
8.55 - * Constructs a <tt>TypeNotPresentException</tt> for the named type
8.56 - * with the specified cause.
8.57 - *
8.58 - * @param typeName the fully qualified name of the unavailable type
8.59 - * @param cause the exception that was thrown when the system attempted to
8.60 - * load the named type, or <tt>null</tt> if unavailable or inapplicable
8.61 - */
8.62 - public TypeNotPresentException(String typeName, Throwable cause) {
8.63 - super("Type " + typeName + " not present", cause);
8.64 - this.typeName = typeName;
8.65 - }
8.66 -
8.67 - /**
8.68 - * Returns the fully qualified name of the unavailable type.
8.69 - *
8.70 - * @return the fully qualified name of the unavailable type
8.71 - */
8.72 - public String typeName() { return typeName;}
8.73 -}
9.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/AbstractValidatingLambdaMetafactory.java Sun Aug 17 20:09:05 2014 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,375 +0,0 @@
9.4 -/*
9.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
9.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
9.7 - *
9.8 - * This code is free software; you can redistribute it and/or modify it
9.9 - * under the terms of the GNU General Public License version 2 only, as
9.10 - * published by the Free Software Foundation. Oracle designates this
9.11 - * particular file as subject to the "Classpath" exception as provided
9.12 - * by Oracle in the LICENSE file that accompanied this code.
9.13 - *
9.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
9.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9.17 - * version 2 for more details (a copy is included in the LICENSE file that
9.18 - * accompanied this code).
9.19 - *
9.20 - * You should have received a copy of the GNU General Public License version
9.21 - * 2 along with this work; if not, write to the Free Software Foundation,
9.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
9.23 - *
9.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
9.25 - * or visit www.oracle.com if you need additional information or have any
9.26 - * questions.
9.27 - */
9.28 -package java.lang.invoke;
9.29 -
9.30 -import sun.invoke.util.Wrapper;
9.31 -
9.32 -import static sun.invoke.util.Wrapper.forPrimitiveType;
9.33 -import static sun.invoke.util.Wrapper.forWrapperType;
9.34 -import static sun.invoke.util.Wrapper.isWrapperType;
9.35 -
9.36 -/**
9.37 - * Abstract implementation of a lambda metafactory which provides parameter
9.38 - * unrolling and input validation.
9.39 - *
9.40 - * @see LambdaMetafactory
9.41 - */
9.42 -/* package */ abstract class AbstractValidatingLambdaMetafactory {
9.43 -
9.44 - /*
9.45 - * For context, the comments for the following fields are marked in quotes
9.46 - * with their values, given this program:
9.47 - * interface II<T> { Object foo(T x); }
9.48 - * interface JJ<R extends Number> extends II<R> { }
9.49 - * class CC { String impl(int i) { return "impl:"+i; }}
9.50 - * class X {
9.51 - * public static void main(String[] args) {
9.52 - * JJ<Integer> iii = (new CC())::impl;
9.53 - * System.out.printf(">>> %s\n", iii.foo(44));
9.54 - * }}
9.55 - */
9.56 - final Class<?> targetClass; // The class calling the meta-factory via invokedynamic "class X"
9.57 - final MethodType invokedType; // The type of the invoked method "(CC)II"
9.58 - final Class<?> samBase; // The type of the returned instance "interface JJ"
9.59 - final String samMethodName; // Name of the SAM method "foo"
9.60 - final MethodType samMethodType; // Type of the SAM method "(Object)Object"
9.61 - final MethodHandle implMethod; // Raw method handle for the implementation method
9.62 - final MethodHandleInfo implInfo; // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]"
9.63 - final int implKind; // Invocation kind for implementation "5"=invokevirtual
9.64 - final boolean implIsInstanceMethod; // Is the implementation an instance method "true"
9.65 - final Class<?> implDefiningClass; // Type defining the implementation "class CC"
9.66 - final MethodType implMethodType; // Type of the implementation method "(int)String"
9.67 - final MethodType instantiatedMethodType; // Instantiated erased functional interface method type "(Integer)Object"
9.68 - final boolean isSerializable; // Should the returned instance be serializable
9.69 - final Class<?>[] markerInterfaces; // Additional marker interfaces to be implemented
9.70 - final MethodType[] additionalBridges; // Signatures of additional methods to bridge
9.71 -
9.72 -
9.73 - /**
9.74 - * Meta-factory constructor.
9.75 - *
9.76 - * @param caller Stacked automatically by VM; represents a lookup context
9.77 - * with the accessibility privileges of the caller.
9.78 - * @param invokedType Stacked automatically by VM; the signature of the
9.79 - * invoked method, which includes the expected static
9.80 - * type of the returned lambda object, and the static
9.81 - * types of the captured arguments for the lambda. In
9.82 - * the event that the implementation method is an
9.83 - * instance method, the first argument in the invocation
9.84 - * signature will correspond to the receiver.
9.85 - * @param samMethodName Name of the method in the functional interface to
9.86 - * which the lambda or method reference is being
9.87 - * converted, represented as a String.
9.88 - * @param samMethodType Type of the method in the functional interface to
9.89 - * which the lambda or method reference is being
9.90 - * converted, represented as a MethodType.
9.91 - * @param implMethod The implementation method which should be called
9.92 - * (with suitable adaptation of argument types, return
9.93 - * types, and adjustment for captured arguments) when
9.94 - * methods of the resulting functional interface instance
9.95 - * are invoked.
9.96 - * @param instantiatedMethodType The signature of the primary functional
9.97 - * interface method after type variables are
9.98 - * substituted with their instantiation from
9.99 - * the capture site
9.100 - * @param isSerializable Should the lambda be made serializable? If set,
9.101 - * either the target type or one of the additional SAM
9.102 - * types must extend {@code Serializable}.
9.103 - * @param markerInterfaces Additional interfaces which the lambda object
9.104 - * should implement.
9.105 - * @param additionalBridges Method types for additional signatures to be
9.106 - * bridged to the implementation method
9.107 - * @throws LambdaConversionException If any of the meta-factory protocol
9.108 - * invariants are violated
9.109 - */
9.110 - AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller,
9.111 - MethodType invokedType,
9.112 - String samMethodName,
9.113 - MethodType samMethodType,
9.114 - MethodHandle implMethod,
9.115 - MethodType instantiatedMethodType,
9.116 - boolean isSerializable,
9.117 - Class<?>[] markerInterfaces,
9.118 - MethodType[] additionalBridges)
9.119 - throws LambdaConversionException {
9.120 - if ((caller.lookupModes() & MethodHandles.Lookup.PRIVATE) == 0) {
9.121 - throw new LambdaConversionException(String.format(
9.122 - "Invalid caller: %s",
9.123 - caller.lookupClass().getName()));
9.124 - }
9.125 - this.targetClass = caller.lookupClass();
9.126 - this.invokedType = invokedType;
9.127 -
9.128 - this.samBase = invokedType.returnType();
9.129 -
9.130 - this.samMethodName = samMethodName;
9.131 - this.samMethodType = samMethodType;
9.132 -
9.133 - this.implMethod = implMethod;
9.134 - this.implInfo = caller.revealDirect(implMethod);
9.135 - this.implKind = implInfo.getReferenceKind();
9.136 - this.implIsInstanceMethod =
9.137 - implKind == MethodHandleInfo.REF_invokeVirtual ||
9.138 - implKind == MethodHandleInfo.REF_invokeSpecial ||
9.139 - implKind == MethodHandleInfo.REF_invokeInterface;
9.140 - this.implDefiningClass = implInfo.getDeclaringClass();
9.141 - this.implMethodType = implInfo.getMethodType();
9.142 - this.instantiatedMethodType = instantiatedMethodType;
9.143 - this.isSerializable = isSerializable;
9.144 - this.markerInterfaces = markerInterfaces;
9.145 - this.additionalBridges = additionalBridges;
9.146 -
9.147 - if (!samBase.isInterface()) {
9.148 - throw new LambdaConversionException(String.format(
9.149 - "Functional interface %s is not an interface",
9.150 - samBase.getName()));
9.151 - }
9.152 -
9.153 - for (Class<?> c : markerInterfaces) {
9.154 - if (!c.isInterface()) {
9.155 - throw new LambdaConversionException(String.format(
9.156 - "Marker interface %s is not an interface",
9.157 - c.getName()));
9.158 - }
9.159 - }
9.160 - }
9.161 -
9.162 - /**
9.163 - * Build the CallSite.
9.164 - *
9.165 - * @return a CallSite, which, when invoked, will return an instance of the
9.166 - * functional interface
9.167 - * @throws ReflectiveOperationException
9.168 - */
9.169 - abstract CallSite buildCallSite()
9.170 - throws LambdaConversionException;
9.171 -
9.172 - /**
9.173 - * Check the meta-factory arguments for errors
9.174 - * @throws LambdaConversionException if there are improper conversions
9.175 - */
9.176 - void validateMetafactoryArgs() throws LambdaConversionException {
9.177 - switch (implKind) {
9.178 - case MethodHandleInfo.REF_invokeInterface:
9.179 - case MethodHandleInfo.REF_invokeVirtual:
9.180 - case MethodHandleInfo.REF_invokeStatic:
9.181 - case MethodHandleInfo.REF_newInvokeSpecial:
9.182 - case MethodHandleInfo.REF_invokeSpecial:
9.183 - break;
9.184 - default:
9.185 - throw new LambdaConversionException(String.format("Unsupported MethodHandle kind: %s", implInfo));
9.186 - }
9.187 -
9.188 - // Check arity: optional-receiver + captured + SAM == impl
9.189 - final int implArity = implMethodType.parameterCount();
9.190 - final int receiverArity = implIsInstanceMethod ? 1 : 0;
9.191 - final int capturedArity = invokedType.parameterCount();
9.192 - final int samArity = samMethodType.parameterCount();
9.193 - final int instantiatedArity = instantiatedMethodType.parameterCount();
9.194 - if (implArity + receiverArity != capturedArity + samArity) {
9.195 - throw new LambdaConversionException(
9.196 - String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface method parameters, %d implementation parameters",
9.197 - implIsInstanceMethod ? "instance" : "static", implInfo,
9.198 - capturedArity, samArity, implArity));
9.199 - }
9.200 - if (instantiatedArity != samArity) {
9.201 - throw new LambdaConversionException(
9.202 - String.format("Incorrect number of parameters for %s method %s; %d instantiated parameters, %d functional interface method parameters",
9.203 - implIsInstanceMethod ? "instance" : "static", implInfo,
9.204 - instantiatedArity, samArity));
9.205 - }
9.206 - for (MethodType bridgeMT : additionalBridges) {
9.207 - if (bridgeMT.parameterCount() != samArity) {
9.208 - throw new LambdaConversionException(
9.209 - String.format("Incorrect number of parameters for bridge signature %s; incompatible with %s",
9.210 - bridgeMT, samMethodType));
9.211 - }
9.212 - }
9.213 -
9.214 - // If instance: first captured arg (receiver) must be subtype of class where impl method is defined
9.215 - final int capturedStart;
9.216 - final int samStart;
9.217 - if (implIsInstanceMethod) {
9.218 - final Class<?> receiverClass;
9.219 -
9.220 - // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
9.221 - if (capturedArity == 0) {
9.222 - // receiver is function parameter
9.223 - capturedStart = 0;
9.224 - samStart = 1;
9.225 - receiverClass = instantiatedMethodType.parameterType(0);
9.226 - } else {
9.227 - // receiver is a captured variable
9.228 - capturedStart = 1;
9.229 - samStart = 0;
9.230 - receiverClass = invokedType.parameterType(0);
9.231 - }
9.232 -
9.233 - // check receiver type
9.234 - if (!implDefiningClass.isAssignableFrom(receiverClass)) {
9.235 - throw new LambdaConversionException(
9.236 - String.format("Invalid receiver type %s; not a subtype of implementation type %s",
9.237 - receiverClass, implDefiningClass));
9.238 - }
9.239 -
9.240 - Class<?> implReceiverClass = implMethod.type().parameterType(0);
9.241 - if (implReceiverClass != implDefiningClass && !implReceiverClass.isAssignableFrom(receiverClass)) {
9.242 - throw new LambdaConversionException(
9.243 - String.format("Invalid receiver type %s; not a subtype of implementation receiver type %s",
9.244 - receiverClass, implReceiverClass));
9.245 - }
9.246 - } else {
9.247 - // no receiver
9.248 - capturedStart = 0;
9.249 - samStart = 0;
9.250 - }
9.251 -
9.252 - // Check for exact match on non-receiver captured arguments
9.253 - final int implFromCaptured = capturedArity - capturedStart;
9.254 - for (int i=0; i<implFromCaptured; i++) {
9.255 - Class<?> implParamType = implMethodType.parameterType(i);
9.256 - Class<?> capturedParamType = invokedType.parameterType(i + capturedStart);
9.257 - if (!capturedParamType.equals(implParamType)) {
9.258 - throw new LambdaConversionException(
9.259 - String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
9.260 - i, capturedParamType, implParamType));
9.261 - }
9.262 - }
9.263 - // Check for adaptation match on SAM arguments
9.264 - final int samOffset = samStart - implFromCaptured;
9.265 - for (int i=implFromCaptured; i<implArity; i++) {
9.266 - Class<?> implParamType = implMethodType.parameterType(i);
9.267 - Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i + samOffset);
9.268 - if (!isAdaptableTo(instantiatedParamType, implParamType, true)) {
9.269 - throw new LambdaConversionException(
9.270 - String.format("Type mismatch for lambda argument %d: %s is not convertible to %s",
9.271 - i, instantiatedParamType, implParamType));
9.272 - }
9.273 - }
9.274 -
9.275 - // Adaptation match: return type
9.276 - Class<?> expectedType = instantiatedMethodType.returnType();
9.277 - Class<?> actualReturnType =
9.278 - (implKind == MethodHandleInfo.REF_newInvokeSpecial)
9.279 - ? implDefiningClass
9.280 - : implMethodType.returnType();
9.281 - Class<?> samReturnType = samMethodType.returnType();
9.282 - if (!isAdaptableToAsReturn(actualReturnType, expectedType)) {
9.283 - throw new LambdaConversionException(
9.284 - String.format("Type mismatch for lambda return: %s is not convertible to %s",
9.285 - actualReturnType, expectedType));
9.286 - }
9.287 - if (!isAdaptableToAsReturnStrict(expectedType, samReturnType)) {
9.288 - throw new LambdaConversionException(
9.289 - String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
9.290 - expectedType, samReturnType));
9.291 - }
9.292 - for (MethodType bridgeMT : additionalBridges) {
9.293 - if (!isAdaptableToAsReturnStrict(expectedType, bridgeMT.returnType())) {
9.294 - throw new LambdaConversionException(
9.295 - String.format("Type mismatch for lambda expected return: %s is not convertible to %s",
9.296 - expectedType, bridgeMT.returnType()));
9.297 - }
9.298 - }
9.299 - }
9.300 -
9.301 - /**
9.302 - * Check type adaptability for parameter types.
9.303 - * @param fromType Type to convert from
9.304 - * @param toType Type to convert to
9.305 - * @param strict If true, do strict checks, else allow that fromType may be parameterized
9.306 - * @return True if 'fromType' can be passed to an argument of 'toType'
9.307 - */
9.308 - private boolean isAdaptableTo(Class<?> fromType, Class<?> toType, boolean strict) {
9.309 - if (fromType.equals(toType)) {
9.310 - return true;
9.311 - }
9.312 - if (fromType.isPrimitive()) {
9.313 - Wrapper wfrom = forPrimitiveType(fromType);
9.314 - if (toType.isPrimitive()) {
9.315 - // both are primitive: widening
9.316 - Wrapper wto = forPrimitiveType(toType);
9.317 - return wto.isConvertibleFrom(wfrom);
9.318 - } else {
9.319 - // from primitive to reference: boxing
9.320 - return toType.isAssignableFrom(wfrom.wrapperType());
9.321 - }
9.322 - } else {
9.323 - if (toType.isPrimitive()) {
9.324 - // from reference to primitive: unboxing
9.325 - Wrapper wfrom;
9.326 - if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
9.327 - // fromType is a primitive wrapper; unbox+widen
9.328 - Wrapper wto = forPrimitiveType(toType);
9.329 - return wto.isConvertibleFrom(wfrom);
9.330 - } else {
9.331 - // must be convertible to primitive
9.332 - return !strict;
9.333 - }
9.334 - } else {
9.335 - // both are reference types: fromType should be a superclass of toType.
9.336 - return !strict || toType.isAssignableFrom(fromType);
9.337 - }
9.338 - }
9.339 - }
9.340 -
9.341 - /**
9.342 - * Check type adaptability for return types --
9.343 - * special handling of void type) and parameterized fromType
9.344 - * @return True if 'fromType' can be converted to 'toType'
9.345 - */
9.346 - private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
9.347 - return toType.equals(void.class)
9.348 - || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
9.349 - }
9.350 - private boolean isAdaptableToAsReturnStrict(Class<?> fromType, Class<?> toType) {
9.351 - if (fromType.equals(void.class)) return toType.equals(void.class);
9.352 - return isAdaptableTo(fromType, toType, true);
9.353 - }
9.354 -
9.355 -
9.356 - /*********** Logging support -- for debugging only, uncomment as needed
9.357 - static final Executor logPool = Executors.newSingleThreadExecutor();
9.358 - protected static void log(final String s) {
9.359 - MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
9.360 - @Override
9.361 - public void run() {
9.362 - System.out.println(s);
9.363 - }
9.364 - });
9.365 - }
9.366 -
9.367 - protected static void log(final String s, final Throwable e) {
9.368 - MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
9.369 - @Override
9.370 - public void run() {
9.371 - System.out.println(s);
9.372 - e.printStackTrace(System.out);
9.373 - }
9.374 - });
9.375 - }
9.376 - ***********************/
9.377 -
9.378 -}
10.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/BoundMethodHandle.java Sun Aug 17 20:09:05 2014 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,491 +0,0 @@
10.4 -/*
10.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
10.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10.7 - *
10.8 - * This code is free software; you can redistribute it and/or modify it
10.9 - * under the terms of the GNU General Public License version 2 only, as
10.10 - * published by the Free Software Foundation. Oracle designates this
10.11 - * particular file as subject to the "Classpath" exception as provided
10.12 - * by Oracle in the LICENSE file that accompanied this code.
10.13 - *
10.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
10.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10.17 - * version 2 for more details (a copy is included in the LICENSE file that
10.18 - * accompanied this code).
10.19 - *
10.20 - * You should have received a copy of the GNU General Public License version
10.21 - * 2 along with this work; if not, write to the Free Software Foundation,
10.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
10.23 - *
10.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
10.25 - * or visit www.oracle.com if you need additional information or have any
10.26 - * questions.
10.27 - */
10.28 -
10.29 -package java.lang.invoke;
10.30 -
10.31 -import static java.lang.invoke.LambdaForm.basicTypes;
10.32 -import static java.lang.invoke.MethodHandleStatics.*;
10.33 -
10.34 -import java.lang.invoke.LambdaForm.Name;
10.35 -import java.lang.invoke.LambdaForm.NamedFunction;
10.36 -import java.lang.invoke.MethodHandles.Lookup;
10.37 -import java.util.Arrays;
10.38 -import java.util.HashMap;
10.39 -
10.40 -import sun.invoke.util.ValueConversions;
10.41 -
10.42 -/**
10.43 - * The flavor of method handle which emulates an invoke instruction
10.44 - * on a predetermined argument. The JVM dispatches to the correct method
10.45 - * when the handle is created, not when it is invoked.
10.46 - *
10.47 - * All bound arguments are encapsulated in dedicated species.
10.48 - */
10.49 -/* non-public */ abstract class BoundMethodHandle extends MethodHandle {
10.50 -
10.51 - /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
10.52 - super(type, form);
10.53 - }
10.54 -
10.55 - //
10.56 - // BMH API and internals
10.57 - //
10.58 -
10.59 - static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) {
10.60 - // for some type signatures, there exist pre-defined concrete BMH classes
10.61 - try {
10.62 - switch (xtype) {
10.63 - case 'L':
10.64 - if (true) return bindSingle(type, form, x); // Use known fast path.
10.65 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
10.66 - case 'I':
10.67 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
10.68 - case 'J':
10.69 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
10.70 - case 'F':
10.71 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
10.72 - case 'D':
10.73 - return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
10.74 - default : throw new InternalError("unexpected xtype: " + xtype);
10.75 - }
10.76 - } catch (Throwable t) {
10.77 - throw newInternalError(t);
10.78 - }
10.79 - }
10.80 -
10.81 - static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
10.82 - return new Species_L(type, form, x);
10.83 - }
10.84 -
10.85 - MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
10.86 - try {
10.87 - switch (xtype) {
10.88 - case 'L': return cloneExtendL(type, form, x);
10.89 - case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
10.90 - case 'J': return cloneExtendJ(type, form, (long) x);
10.91 - case 'F': return cloneExtendF(type, form, (float) x);
10.92 - case 'D': return cloneExtendD(type, form, (double) x);
10.93 - }
10.94 - } catch (Throwable t) {
10.95 - throw newInternalError(t);
10.96 - }
10.97 - throw new InternalError("unexpected type: " + xtype);
10.98 - }
10.99 -
10.100 - @Override
10.101 - MethodHandle bindArgument(int pos, char basicType, Object value) {
10.102 - MethodType type = type().dropParameterTypes(pos, pos+1);
10.103 - LambdaForm form = internalForm().bind(1+pos, speciesData());
10.104 - return cloneExtend(type, form, basicType, value);
10.105 - }
10.106 -
10.107 - @Override
10.108 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
10.109 - LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
10.110 - try {
10.111 - return clone(srcType, form);
10.112 - } catch (Throwable t) {
10.113 - throw newInternalError(t);
10.114 - }
10.115 - }
10.116 -
10.117 - @Override
10.118 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
10.119 - try {
10.120 - return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
10.121 - } catch (Throwable t) {
10.122 - throw newInternalError(t);
10.123 - }
10.124 - }
10.125 -
10.126 - static final String EXTENSION_TYPES = "LIJFD";
10.127 - static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4;
10.128 - static byte extensionIndex(char type) {
10.129 - int i = EXTENSION_TYPES.indexOf(type);
10.130 - if (i < 0) throw new InternalError();
10.131 - return (byte) i;
10.132 - }
10.133 -
10.134 - /**
10.135 - * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
10.136 - * static field containing this value, and they must accordingly implement this method.
10.137 - */
10.138 - protected abstract SpeciesData speciesData();
10.139 -
10.140 - @Override
10.141 - final Object internalProperties() {
10.142 - return "/BMH="+internalValues();
10.143 - }
10.144 -
10.145 - @Override
10.146 - final Object internalValues() {
10.147 - Object[] boundValues = new Object[speciesData().fieldCount()];
10.148 - for (int i = 0; i < boundValues.length; ++i) {
10.149 - boundValues[i] = arg(i);
10.150 - }
10.151 - return Arrays.asList(boundValues);
10.152 - }
10.153 -
10.154 - public final Object arg(int i) {
10.155 - try {
10.156 - switch (speciesData().fieldType(i)) {
10.157 - case 'L': return argL(i);
10.158 - case 'I': return argI(i);
10.159 - case 'F': return argF(i);
10.160 - case 'D': return argD(i);
10.161 - case 'J': return argJ(i);
10.162 - }
10.163 - } catch (Throwable ex) {
10.164 - throw newInternalError(ex);
10.165 - }
10.166 - throw new InternalError("unexpected type: " + speciesData().types+"."+i);
10.167 - }
10.168 - public final Object argL(int i) throws Throwable { return speciesData().getters[i].invokeBasic(this); }
10.169 - public final int argI(int i) throws Throwable { return (int) speciesData().getters[i].invokeBasic(this); }
10.170 - public final float argF(int i) throws Throwable { return (float) speciesData().getters[i].invokeBasic(this); }
10.171 - public final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
10.172 - public final long argJ(int i) throws Throwable { return (long) speciesData().getters[i].invokeBasic(this); }
10.173 -
10.174 - //
10.175 - // cloning API
10.176 - //
10.177 -
10.178 - public abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
10.179 - public abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
10.180 - public abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable;
10.181 - public abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable;
10.182 - public abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable;
10.183 - public abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
10.184 -
10.185 - // The following is a grossly irregular hack:
10.186 - @Override MethodHandle reinvokerTarget() {
10.187 - try {
10.188 - return (MethodHandle) argL(0);
10.189 - } catch (Throwable ex) {
10.190 - throw newInternalError(ex);
10.191 - }
10.192 - }
10.193 -
10.194 - //
10.195 - // concrete BMH classes required to close bootstrap loops
10.196 - //
10.197 -
10.198 - private // make it private to force users to access the enclosing class first
10.199 - static final class Species_L extends BoundMethodHandle {
10.200 - final Object argL0;
10.201 - public Species_L(MethodType mt, LambdaForm lf, Object argL0) {
10.202 - super(mt, lf);
10.203 - this.argL0 = argL0;
10.204 - }
10.205 - // The following is a grossly irregular hack:
10.206 - @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
10.207 - @Override
10.208 - public SpeciesData speciesData() {
10.209 - return SPECIES_DATA;
10.210 - }
10.211 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
10.212 - @Override
10.213 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
10.214 - return new Species_L(mt, lf, argL0);
10.215 - }
10.216 - @Override
10.217 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
10.218 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, narg);
10.219 - }
10.220 - @Override
10.221 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
10.222 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, narg);
10.223 - }
10.224 - @Override
10.225 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
10.226 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, narg);
10.227 - }
10.228 - @Override
10.229 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
10.230 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, narg);
10.231 - }
10.232 - @Override
10.233 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
10.234 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
10.235 - }
10.236 - }
10.237 -
10.238 -/*
10.239 - static final class Species_LL extends BoundMethodHandle {
10.240 - final Object argL0;
10.241 - final Object argL1;
10.242 - public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
10.243 - super(mt, lf);
10.244 - this.argL0 = argL0;
10.245 - this.argL1 = argL1;
10.246 - }
10.247 - @Override
10.248 - public SpeciesData speciesData() {
10.249 - return SPECIES_DATA;
10.250 - }
10.251 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
10.252 - @Override
10.253 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
10.254 - return new Species_LL(mt, lf, argL0, argL1);
10.255 - }
10.256 - @Override
10.257 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
10.258 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
10.259 - }
10.260 - @Override
10.261 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
10.262 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
10.263 - }
10.264 - @Override
10.265 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
10.266 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
10.267 - }
10.268 - @Override
10.269 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
10.270 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
10.271 - }
10.272 - @Override
10.273 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
10.274 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
10.275 - }
10.276 - }
10.277 -
10.278 - static final class Species_JL extends BoundMethodHandle {
10.279 - final long argJ0;
10.280 - final Object argL1;
10.281 - public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
10.282 - super(mt, lf);
10.283 - this.argJ0 = argJ0;
10.284 - this.argL1 = argL1;
10.285 - }
10.286 - @Override
10.287 - public SpeciesData speciesData() {
10.288 - return SPECIES_DATA;
10.289 - }
10.290 - public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
10.291 - @Override public final long argJ0() { return argJ0; }
10.292 - @Override public final Object argL1() { return argL1; }
10.293 - @Override
10.294 - public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
10.295 - return new Species_JL(mt, lf, argJ0, argL1);
10.296 - }
10.297 - @Override
10.298 - public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
10.299 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
10.300 - }
10.301 - @Override
10.302 - public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
10.303 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
10.304 - }
10.305 - @Override
10.306 - public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
10.307 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
10.308 - }
10.309 - @Override
10.310 - public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
10.311 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
10.312 - }
10.313 - @Override
10.314 - public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
10.315 - return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
10.316 - }
10.317 - }
10.318 -*/
10.319 -
10.320 - //
10.321 - // BMH species meta-data
10.322 - //
10.323 -
10.324 - /**
10.325 - * Meta-data wrapper for concrete BMH classes.
10.326 - */
10.327 - static class SpeciesData {
10.328 - final String types;
10.329 - final Class<? extends BoundMethodHandle> clazz;
10.330 - // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
10.331 - // Therefore, we need a non-final link in the chain. Use array elements.
10.332 - final MethodHandle[] constructor;
10.333 - final MethodHandle[] getters;
10.334 - final SpeciesData[] extensions;
10.335 -
10.336 - public int fieldCount() {
10.337 - return types.length();
10.338 - }
10.339 - public char fieldType(int i) {
10.340 - return types.charAt(i);
10.341 - }
10.342 -
10.343 - public String toString() {
10.344 - return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
10.345 - }
10.346 -
10.347 - /**
10.348 - * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
10.349 - * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
10.350 - * getter.
10.351 - */
10.352 - Name getterName(Name mhName, int i) {
10.353 - MethodHandle mh = getters[i];
10.354 - assert(mh != null) : this+"."+i;
10.355 - return new Name(mh, mhName);
10.356 - }
10.357 -
10.358 - NamedFunction getterFunction(int i) {
10.359 - return new NamedFunction(getters[i]);
10.360 - }
10.361 -
10.362 - static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
10.363 -
10.364 - private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
10.365 - this.types = types;
10.366 - this.clazz = clazz;
10.367 - if (!INIT_DONE) {
10.368 - this.constructor = new MethodHandle[1];
10.369 - this.getters = new MethodHandle[types.length()];
10.370 - } else {
10.371 - throw new IllegalStateException("bound method handle");
10.372 -// this.constructor = Factory.makeCtors(clazz, types, null);
10.373 -// this.getters = Factory.makeGetters(clazz, types, null);
10.374 - }
10.375 - this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
10.376 - }
10.377 -
10.378 - private void initForBootstrap() {
10.379 - assert(!INIT_DONE);
10.380 - if (constructor[0] == null) {
10.381 -// Factory.makeCtors(clazz, types, this.constructor);
10.382 -// Factory.makeGetters(clazz, types, this.getters);
10.383 - }
10.384 - }
10.385 -
10.386 - private SpeciesData(String types) {
10.387 - // Placeholder only.
10.388 - this.types = types;
10.389 - this.clazz = null;
10.390 - this.constructor = null;
10.391 - this.getters = null;
10.392 - this.extensions = null;
10.393 - }
10.394 - private boolean isPlaceholder() { return clazz == null; }
10.395 -
10.396 - private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
10.397 - static { CACHE.put("", EMPTY); } // make bootstrap predictable
10.398 - private static final boolean INIT_DONE; // set after <clinit> finishes...
10.399 -
10.400 - SpeciesData extendWithType(char type) {
10.401 - int i = extensionIndex(type);
10.402 - SpeciesData d = extensions[i];
10.403 - if (d != null) return d;
10.404 - extensions[i] = d = get(types+type);
10.405 - return d;
10.406 - }
10.407 -
10.408 - SpeciesData extendWithIndex(byte index) {
10.409 - SpeciesData d = extensions[index];
10.410 - if (d != null) return d;
10.411 - extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
10.412 - return d;
10.413 - }
10.414 -
10.415 - private static SpeciesData get(String types) {
10.416 - // Acquire cache lock for query.
10.417 - SpeciesData d = lookupCache(types);
10.418 - if (!d.isPlaceholder())
10.419 - return d;
10.420 - synchronized (d) {
10.421 - // Use synch. on the placeholder to prevent multiple instantiation of one species.
10.422 - // Creating this class forces a recursive call to getForClass.
10.423 - if (lookupCache(types).isPlaceholder())
10.424 - throw new IllegalStateException("Cannot generate anything");
10.425 - }
10.426 - // Reacquire cache lock.
10.427 - d = lookupCache(types);
10.428 - // Class loading must have upgraded the cache.
10.429 - assert(d != null && !d.isPlaceholder());
10.430 - return d;
10.431 - }
10.432 - static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
10.433 - // clazz is a new class which is initializing its SPECIES_DATA field
10.434 - return updateCache(types, new SpeciesData(types, clazz));
10.435 - }
10.436 - private static synchronized SpeciesData lookupCache(String types) {
10.437 - SpeciesData d = CACHE.get(types);
10.438 - if (d != null) return d;
10.439 - d = new SpeciesData(types);
10.440 - assert(d.isPlaceholder());
10.441 - CACHE.put(types, d);
10.442 - return d;
10.443 - }
10.444 - private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
10.445 - SpeciesData d2;
10.446 - assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
10.447 - assert(!d.isPlaceholder());
10.448 - CACHE.put(types, d);
10.449 - return d;
10.450 - }
10.451 -
10.452 - static {
10.453 - // pre-fill the BMH speciesdata cache with BMH's inner classes
10.454 - final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
10.455 - SpeciesData d0 = BoundMethodHandle.SPECIES_DATA; // trigger class init
10.456 - assert(d0 == null || d0 == lookupCache("")) : d0;
10.457 - try {
10.458 - /*
10.459 - for (Class<?> c : rootCls.getDeclaredClasses()) {
10.460 - if (rootCls.isAssignableFrom(c)) {
10.461 - final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
10.462 - SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
10.463 - assert(d != null) : cbmh.getName();
10.464 - assert(d.clazz == cbmh);
10.465 - assert(d == lookupCache(d.types));
10.466 - }
10.467 - }
10.468 - */
10.469 - } catch (Throwable e) {
10.470 - throw newInternalError(e);
10.471 - }
10.472 -
10.473 - for (SpeciesData d : CACHE.values()) {
10.474 - d.initForBootstrap();
10.475 - }
10.476 - // Note: Do not simplify this, because INIT_DONE must not be
10.477 - // a compile-time constant during bootstrapping.
10.478 - INIT_DONE = Boolean.TRUE;
10.479 - }
10.480 - }
10.481 -
10.482 - static SpeciesData getSpeciesData(String types) {
10.483 - return SpeciesData.get(types);
10.484 - }
10.485 -
10.486 -
10.487 -
10.488 - private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
10.489 -
10.490 - /**
10.491 - * All subclasses must provide such a value describing their type signature.
10.492 - */
10.493 - static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
10.494 -}
11.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/CallSite.java Sun Aug 17 20:09:05 2014 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,339 +0,0 @@
11.4 -/*
11.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
11.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
11.7 - *
11.8 - * This code is free software; you can redistribute it and/or modify it
11.9 - * under the terms of the GNU General Public License version 2 only, as
11.10 - * published by the Free Software Foundation. Oracle designates this
11.11 - * particular file as subject to the "Classpath" exception as provided
11.12 - * by Oracle in the LICENSE file that accompanied this code.
11.13 - *
11.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
11.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11.17 - * version 2 for more details (a copy is included in the LICENSE file that
11.18 - * accompanied this code).
11.19 - *
11.20 - * You should have received a copy of the GNU General Public License version
11.21 - * 2 along with this work; if not, write to the Free Software Foundation,
11.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
11.23 - *
11.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
11.25 - * or visit www.oracle.com if you need additional information or have any
11.26 - * questions.
11.27 - */
11.28 -
11.29 -package java.lang.invoke;
11.30 -
11.31 -import sun.invoke.empty.Empty;
11.32 -import static java.lang.invoke.MethodHandleStatics.*;
11.33 -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
11.34 -
11.35 -/**
11.36 - * A {@code CallSite} is a holder for a variable {@link MethodHandle},
11.37 - * which is called its {@code target}.
11.38 - * An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
11.39 - * all calls to the site's current target.
11.40 - * A {@code CallSite} may be associated with several {@code invokedynamic}
11.41 - * instructions, or it may be "free floating", associated with none.
11.42 - * In any case, it may be invoked through an associated method handle
11.43 - * called its {@linkplain #dynamicInvoker dynamic invoker}.
11.44 - * <p>
11.45 - * {@code CallSite} is an abstract class which does not allow
11.46 - * direct subclassing by users. It has three immediate,
11.47 - * concrete subclasses that may be either instantiated or subclassed.
11.48 - * <ul>
11.49 - * <li>If a mutable target is not required, an {@code invokedynamic} instruction
11.50 - * may be permanently bound by means of a {@linkplain ConstantCallSite constant call site}.
11.51 - * <li>If a mutable target is required which has volatile variable semantics,
11.52 - * because updates to the target must be immediately and reliably witnessed by other threads,
11.53 - * a {@linkplain VolatileCallSite volatile call site} may be used.
11.54 - * <li>Otherwise, if a mutable target is required,
11.55 - * a {@linkplain MutableCallSite mutable call site} may be used.
11.56 - * </ul>
11.57 - * <p>
11.58 - * A non-constant call site may be <em>relinked</em> by changing its target.
11.59 - * The new target must have the same {@linkplain MethodHandle#type() type}
11.60 - * as the previous target.
11.61 - * Thus, though a call site can be relinked to a series of
11.62 - * successive targets, it cannot change its type.
11.63 - * <p>
11.64 - * Here is a sample use of call sites and bootstrap methods which links every
11.65 - * dynamic call site to print its arguments:
11.66 -<blockquote><pre>{@code
11.67 -static void test() throws Throwable {
11.68 - // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
11.69 - InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
11.70 -}
11.71 -private static void printArgs(Object... args) {
11.72 - System.out.println(java.util.Arrays.deepToString(args));
11.73 -}
11.74 -private static final MethodHandle printArgs;
11.75 -static {
11.76 - MethodHandles.Lookup lookup = MethodHandles.lookup();
11.77 - Class thisClass = lookup.lookupClass(); // (who am I?)
11.78 - printArgs = lookup.findStatic(thisClass,
11.79 - "printArgs", MethodType.methodType(void.class, Object[].class));
11.80 -}
11.81 -private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) {
11.82 - // ignore caller and name, but match the type:
11.83 - return new ConstantCallSite(printArgs.asType(type));
11.84 -}
11.85 -}</pre></blockquote>
11.86 - * @author John Rose, JSR 292 EG
11.87 - */
11.88 -abstract
11.89 -public class CallSite {
11.90 - static { MethodHandleImpl.initStatics(); }
11.91 -
11.92 - // The actual payload of this call site:
11.93 - /*package-private*/
11.94 - MethodHandle target; // Note: This field is known to the JVM. Do not change.
11.95 -
11.96 - /**
11.97 - * Make a blank call site object with the given method type.
11.98 - * An initial target method is supplied which will throw
11.99 - * an {@link IllegalStateException} if called.
11.100 - * <p>
11.101 - * Before this {@code CallSite} object is returned from a bootstrap method,
11.102 - * it is usually provided with a more useful target method,
11.103 - * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
11.104 - * @throws NullPointerException if the proposed type is null
11.105 - */
11.106 - /*package-private*/
11.107 - CallSite(MethodType type) {
11.108 - target = type.invokers().uninitializedCallSite();
11.109 - }
11.110 -
11.111 - /**
11.112 - * Make a call site object equipped with an initial target method handle.
11.113 - * @param target the method handle which will be the initial target of the call site
11.114 - * @throws NullPointerException if the proposed target is null
11.115 - */
11.116 - /*package-private*/
11.117 - CallSite(MethodHandle target) {
11.118 - target.type(); // null check
11.119 - this.target = target;
11.120 - }
11.121 -
11.122 - /**
11.123 - * Make a call site object equipped with an initial target method handle.
11.124 - * @param targetType the desired type of the call site
11.125 - * @param createTargetHook a hook which will bind the call site to the target method handle
11.126 - * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
11.127 - * or if the target returned by the hook is not of the given {@code targetType}
11.128 - * @throws NullPointerException if the hook returns a null value
11.129 - * @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
11.130 - * @throws Throwable anything else thrown by the hook function
11.131 - */
11.132 - /*package-private*/
11.133 - CallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
11.134 - this(targetType);
11.135 - ConstantCallSite selfCCS = (ConstantCallSite) this;
11.136 - MethodHandle boundTarget = (MethodHandle) createTargetHook.invokeWithArguments(selfCCS);
11.137 - checkTargetChange(this.target, boundTarget);
11.138 - this.target = boundTarget;
11.139 - }
11.140 -
11.141 - /**
11.142 - * Returns the type of this call site's target.
11.143 - * Although targets may change, any call site's type is permanent, and can never change to an unequal type.
11.144 - * The {@code setTarget} method enforces this invariant by refusing any new target that does
11.145 - * not have the previous target's type.
11.146 - * @return the type of the current target, which is also the type of any future target
11.147 - */
11.148 - public MethodType type() {
11.149 - // warning: do not call getTarget here, because CCS.getTarget can throw IllegalStateException
11.150 - return target.type();
11.151 - }
11.152 -
11.153 - /**
11.154 - * Returns the target method of the call site, according to the
11.155 - * behavior defined by this call site's specific class.
11.156 - * The immediate subclasses of {@code CallSite} document the
11.157 - * class-specific behaviors of this method.
11.158 - *
11.159 - * @return the current linkage state of the call site, its target method handle
11.160 - * @see ConstantCallSite
11.161 - * @see VolatileCallSite
11.162 - * @see #setTarget
11.163 - * @see ConstantCallSite#getTarget
11.164 - * @see MutableCallSite#getTarget
11.165 - * @see VolatileCallSite#getTarget
11.166 - */
11.167 - public abstract MethodHandle getTarget();
11.168 -
11.169 - /**
11.170 - * Updates the target method of this call site, according to the
11.171 - * behavior defined by this call site's specific class.
11.172 - * The immediate subclasses of {@code CallSite} document the
11.173 - * class-specific behaviors of this method.
11.174 - * <p>
11.175 - * The type of the new target must be {@linkplain MethodType#equals equal to}
11.176 - * the type of the old target.
11.177 - *
11.178 - * @param newTarget the new target
11.179 - * @throws NullPointerException if the proposed new target is null
11.180 - * @throws WrongMethodTypeException if the proposed new target
11.181 - * has a method type that differs from the previous target
11.182 - * @see CallSite#getTarget
11.183 - * @see ConstantCallSite#setTarget
11.184 - * @see MutableCallSite#setTarget
11.185 - * @see VolatileCallSite#setTarget
11.186 - */
11.187 - public abstract void setTarget(MethodHandle newTarget);
11.188 -
11.189 - void checkTargetChange(MethodHandle oldTarget, MethodHandle newTarget) {
11.190 - MethodType oldType = oldTarget.type();
11.191 - MethodType newType = newTarget.type(); // null check!
11.192 - if (!newType.equals(oldType))
11.193 - throw wrongTargetType(newTarget, oldType);
11.194 - }
11.195 -
11.196 - private static WrongMethodTypeException wrongTargetType(MethodHandle target, MethodType type) {
11.197 - return new WrongMethodTypeException(String.valueOf(target)+" should be of type "+type);
11.198 - }
11.199 -
11.200 - /**
11.201 - * Produces a method handle equivalent to an invokedynamic instruction
11.202 - * which has been linked to this call site.
11.203 - * <p>
11.204 - * This method is equivalent to the following code:
11.205 - * <blockquote><pre>{@code
11.206 - * MethodHandle getTarget, invoker, result;
11.207 - * getTarget = MethodHandles.publicLookup().bind(this, "getTarget", MethodType.methodType(MethodHandle.class));
11.208 - * invoker = MethodHandles.exactInvoker(this.type());
11.209 - * result = MethodHandles.foldArguments(invoker, getTarget)
11.210 - * }</pre></blockquote>
11.211 - *
11.212 - * @return a method handle which always invokes this call site's current target
11.213 - */
11.214 - public abstract MethodHandle dynamicInvoker();
11.215 -
11.216 - /*non-public*/ MethodHandle makeDynamicInvoker() {
11.217 - MethodHandle getTarget = GET_TARGET.bindReceiver(this);
11.218 - MethodHandle invoker = MethodHandles.exactInvoker(this.type());
11.219 - return MethodHandles.foldArguments(invoker, getTarget);
11.220 - }
11.221 -
11.222 - private static final MethodHandle GET_TARGET;
11.223 - static {
11.224 - try {
11.225 - GET_TARGET = IMPL_LOOKUP.
11.226 - findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class));
11.227 - } catch (ReflectiveOperationException e) {
11.228 - throw newInternalError(e);
11.229 - }
11.230 - }
11.231 -
11.232 - /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
11.233 - /*package-private*/
11.234 - static Empty uninitializedCallSite() {
11.235 - throw new IllegalStateException("uninitialized call site");
11.236 - }
11.237 -
11.238 - /*package-private*/
11.239 - void setTargetNormal(MethodHandle newTarget) {
11.240 - MethodHandleNatives.setCallSiteTargetNormal(this, newTarget);
11.241 - }
11.242 - /*package-private*/
11.243 - MethodHandle getTargetVolatile() {
11.244 - return target;
11.245 - }
11.246 - /*package-private*/
11.247 - void setTargetVolatile(MethodHandle newTarget) {
11.248 - MethodHandleNatives.setCallSiteTargetVolatile(this, newTarget);
11.249 - }
11.250 -
11.251 - // this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
11.252 - static CallSite makeSite(MethodHandle bootstrapMethod,
11.253 - // Callee information:
11.254 - String name, MethodType type,
11.255 - // Extra arguments for BSM, if any:
11.256 - Object info,
11.257 - // Caller information:
11.258 - Class<?> callerClass) {
11.259 - MethodHandles.Lookup caller = IMPL_LOOKUP.in(callerClass);
11.260 - CallSite site;
11.261 - try {
11.262 - Object binding;
11.263 - info = maybeReBox(info);
11.264 - if (info == null) {
11.265 - binding = bootstrapMethod.invoke(caller, name, type);
11.266 - } else if (!info.getClass().isArray()) {
11.267 - binding = bootstrapMethod.invoke(caller, name, type, info);
11.268 - } else {
11.269 - Object[] argv = (Object[]) info;
11.270 - maybeReBoxElements(argv);
11.271 - switch (argv.length) {
11.272 - case 0:
11.273 - binding = bootstrapMethod.invoke(caller, name, type);
11.274 - break;
11.275 - case 1:
11.276 - binding = bootstrapMethod.invoke(caller, name, type,
11.277 - argv[0]);
11.278 - break;
11.279 - case 2:
11.280 - binding = bootstrapMethod.invoke(caller, name, type,
11.281 - argv[0], argv[1]);
11.282 - break;
11.283 - case 3:
11.284 - binding = bootstrapMethod.invoke(caller, name, type,
11.285 - argv[0], argv[1], argv[2]);
11.286 - break;
11.287 - case 4:
11.288 - binding = bootstrapMethod.invoke(caller, name, type,
11.289 - argv[0], argv[1], argv[2], argv[3]);
11.290 - break;
11.291 - case 5:
11.292 - binding = bootstrapMethod.invoke(caller, name, type,
11.293 - argv[0], argv[1], argv[2], argv[3], argv[4]);
11.294 - break;
11.295 - case 6:
11.296 - binding = bootstrapMethod.invoke(caller, name, type,
11.297 - argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
11.298 - break;
11.299 - default:
11.300 - final int NON_SPREAD_ARG_COUNT = 3; // (caller, name, type)
11.301 - if (NON_SPREAD_ARG_COUNT + argv.length > MethodType.MAX_MH_ARITY)
11.302 - throw new BootstrapMethodError("too many bootstrap method arguments");
11.303 - MethodType bsmType = bootstrapMethod.type();
11.304 - MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
11.305 - MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
11.306 - MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
11.307 - binding = spreader.invokeExact(typedBSM, (Object)caller, (Object)name, (Object)type, argv);
11.308 - }
11.309 - }
11.310 - //System.out.println("BSM for "+name+type+" => "+binding);
11.311 - if (binding instanceof CallSite) {
11.312 - site = (CallSite) binding;
11.313 - } else {
11.314 - throw new ClassCastException("bootstrap method failed to produce a CallSite");
11.315 - }
11.316 - if (!site.getTarget().type().equals(type))
11.317 - throw new WrongMethodTypeException("wrong type: "+site.getTarget());
11.318 - } catch (Throwable ex) {
11.319 - BootstrapMethodError bex;
11.320 - if (ex instanceof BootstrapMethodError)
11.321 - bex = (BootstrapMethodError) ex;
11.322 - else
11.323 - bex = new BootstrapMethodError("call site initialization exception", ex);
11.324 - throw bex;
11.325 - }
11.326 - return site;
11.327 - }
11.328 -
11.329 - private static Object maybeReBox(Object x) {
11.330 - if (x instanceof Integer) {
11.331 - int xi = (int) x;
11.332 - if (xi == (byte) xi)
11.333 - x = xi; // must rebox; see JLS 5.1.7
11.334 - }
11.335 - return x;
11.336 - }
11.337 - private static void maybeReBoxElements(Object[] xa) {
11.338 - for (int i = 0; i < xa.length; i++) {
11.339 - xa[i] = maybeReBox(xa[i]);
11.340 - }
11.341 - }
11.342 -}
12.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/ConstantCallSite.java Sun Aug 17 20:09:05 2014 +0200
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,120 +0,0 @@
12.4 -/*
12.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
12.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
12.7 - *
12.8 - * This code is free software; you can redistribute it and/or modify it
12.9 - * under the terms of the GNU General Public License version 2 only, as
12.10 - * published by the Free Software Foundation. Oracle designates this
12.11 - * particular file as subject to the "Classpath" exception as provided
12.12 - * by Oracle in the LICENSE file that accompanied this code.
12.13 - *
12.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
12.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12.17 - * version 2 for more details (a copy is included in the LICENSE file that
12.18 - * accompanied this code).
12.19 - *
12.20 - * You should have received a copy of the GNU General Public License version
12.21 - * 2 along with this work; if not, write to the Free Software Foundation,
12.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
12.23 - *
12.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
12.25 - * or visit www.oracle.com if you need additional information or have any
12.26 - * questions.
12.27 - */
12.28 -
12.29 -package java.lang.invoke;
12.30 -
12.31 -/**
12.32 - * A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
12.33 - * An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
12.34 - * bound to the call site's target.
12.35 - * @author John Rose, JSR 292 EG
12.36 - */
12.37 -public class ConstantCallSite extends CallSite {
12.38 - private final boolean isFrozen;
12.39 -
12.40 - /**
12.41 - * Creates a call site with a permanent target.
12.42 - * @param target the target to be permanently associated with this call site
12.43 - * @throws NullPointerException if the proposed target is null
12.44 - */
12.45 - public ConstantCallSite(MethodHandle target) {
12.46 - super(target);
12.47 - isFrozen = true;
12.48 - }
12.49 -
12.50 - /**
12.51 - * Creates a call site with a permanent target, possibly bound to the call site itself.
12.52 - * <p>
12.53 - * During construction of the call site, the {@code createTargetHook} is invoked to
12.54 - * produce the actual target, as if by a call of the form
12.55 - * {@code (MethodHandle) createTargetHook.invoke(this)}.
12.56 - * <p>
12.57 - * Note that user code cannot perform such an action directly in a subclass constructor,
12.58 - * since the target must be fixed before the {@code ConstantCallSite} constructor returns.
12.59 - * <p>
12.60 - * The hook is said to bind the call site to a target method handle,
12.61 - * and a typical action would be {@code someTarget.bindTo(this)}.
12.62 - * However, the hook is free to take any action whatever,
12.63 - * including ignoring the call site and returning a constant target.
12.64 - * <p>
12.65 - * The result returned by the hook must be a method handle of exactly
12.66 - * the same type as the call site.
12.67 - * <p>
12.68 - * While the hook is being called, the new {@code ConstantCallSite}
12.69 - * object is in a partially constructed state.
12.70 - * In this state,
12.71 - * a call to {@code getTarget}, or any other attempt to use the target,
12.72 - * will result in an {@code IllegalStateException}.
12.73 - * It is legal at all times to obtain the call site's type using the {@code type} method.
12.74 - *
12.75 - * @param targetType the type of the method handle to be permanently associated with this call site
12.76 - * @param createTargetHook a method handle to invoke (on the call site) to produce the call site's target
12.77 - * @throws WrongMethodTypeException if the hook cannot be invoked on the required arguments,
12.78 - * or if the target returned by the hook is not of the given {@code targetType}
12.79 - * @throws NullPointerException if the hook returns a null value
12.80 - * @throws ClassCastException if the hook returns something other than a {@code MethodHandle}
12.81 - * @throws Throwable anything else thrown by the hook function
12.82 - */
12.83 - protected ConstantCallSite(MethodType targetType, MethodHandle createTargetHook) throws Throwable {
12.84 - super(targetType, createTargetHook);
12.85 - isFrozen = true;
12.86 - }
12.87 -
12.88 - /**
12.89 - * Returns the target method of the call site, which behaves
12.90 - * like a {@code final} field of the {@code ConstantCallSite}.
12.91 - * That is, the target is always the original value passed
12.92 - * to the constructor call which created this instance.
12.93 - *
12.94 - * @return the immutable linkage state of this call site, a constant method handle
12.95 - * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
12.96 - */
12.97 - @Override public final MethodHandle getTarget() {
12.98 - if (!isFrozen) throw new IllegalStateException();
12.99 - return target;
12.100 - }
12.101 -
12.102 - /**
12.103 - * Always throws an {@link UnsupportedOperationException}.
12.104 - * This kind of call site cannot change its target.
12.105 - * @param ignore a new target proposed for the call site, which is ignored
12.106 - * @throws UnsupportedOperationException because this kind of call site cannot change its target
12.107 - */
12.108 - @Override public final void setTarget(MethodHandle ignore) {
12.109 - throw new UnsupportedOperationException();
12.110 - }
12.111 -
12.112 - /**
12.113 - * Returns this call site's permanent target.
12.114 - * Since that target will never change, this is a correct implementation
12.115 - * of {@link CallSite#dynamicInvoker CallSite.dynamicInvoker}.
12.116 - * @return the immutable linkage state of this call site, a constant method handle
12.117 - * @throws IllegalStateException if the {@code ConstantCallSite} constructor has not completed
12.118 - */
12.119 - @Override
12.120 - public final MethodHandle dynamicInvoker() {
12.121 - return getTarget();
12.122 - }
12.123 -}
13.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/DirectMethodHandle.java Sun Aug 17 20:09:05 2014 +0200
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,730 +0,0 @@
13.4 -/*
13.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
13.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
13.7 - *
13.8 - * This code is free software; you can redistribute it and/or modify it
13.9 - * under the terms of the GNU General Public License version 2 only, as
13.10 - * published by the Free Software Foundation. Oracle designates this
13.11 - * particular file as subject to the "Classpath" exception as provided
13.12 - * by Oracle in the LICENSE file that accompanied this code.
13.13 - *
13.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
13.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13.17 - * version 2 for more details (a copy is included in the LICENSE file that
13.18 - * accompanied this code).
13.19 - *
13.20 - * You should have received a copy of the GNU General Public License version
13.21 - * 2 along with this work; if not, write to the Free Software Foundation,
13.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
13.23 - *
13.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
13.25 - * or visit www.oracle.com if you need additional information or have any
13.26 - * questions.
13.27 - */
13.28 -
13.29 -package java.lang.invoke;
13.30 -
13.31 -import java.lang.reflect.Method;
13.32 -import java.util.Arrays;
13.33 -import sun.invoke.util.VerifyAccess;
13.34 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
13.35 -import static java.lang.invoke.LambdaForm.*;
13.36 -import static java.lang.invoke.MethodTypeForm.*;
13.37 -import static java.lang.invoke.MethodHandleStatics.*;
13.38 -import java.lang.ref.WeakReference;
13.39 -import java.lang.reflect.Field;
13.40 -import sun.invoke.util.ValueConversions;
13.41 -import sun.invoke.util.VerifyType;
13.42 -import sun.invoke.util.Wrapper;
13.43 -
13.44 -/**
13.45 - * The flavor of method handle which implements a constant reference
13.46 - * to a class member.
13.47 - * @author jrose
13.48 - */
13.49 -class DirectMethodHandle extends MethodHandle {
13.50 - final MemberName member;
13.51 -
13.52 - // Constructors and factory methods in this class *must* be package scoped or private.
13.53 - private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
13.54 - super(mtype, form);
13.55 - if (!member.isResolved()) throw new InternalError();
13.56 -
13.57 - if (member.getDeclaringClass().isInterface() &&
13.58 - member.isMethod() && !member.isAbstract()) {
13.59 - // Check for corner case: invokeinterface of Object method
13.60 - MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind());
13.61 - m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null);
13.62 - if (m != null && m.isPublic()) {
13.63 - member = m;
13.64 - }
13.65 - }
13.66 -
13.67 - this.member = member;
13.68 - }
13.69 -
13.70 - // Factory methods:
13.71 - static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) {
13.72 - MethodType mtype = member.getMethodOrFieldType();
13.73 - if (!member.isStatic()) {
13.74 - if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor())
13.75 - throw new InternalError(member.toString());
13.76 - mtype = mtype.insertParameterTypes(0, receiver);
13.77 - }
13.78 - if (!member.isField()) {
13.79 - if (refKind == REF_invokeSpecial) {
13.80 - member = member.asSpecial();
13.81 - LambdaForm lform = preparedLambdaForm(member);
13.82 - return new Special(mtype, lform, member);
13.83 - } else {
13.84 - LambdaForm lform = preparedLambdaForm(member);
13.85 - return new DirectMethodHandle(mtype, lform, member);
13.86 - }
13.87 - } else {
13.88 - LambdaForm lform = preparedFieldLambdaForm(member);
13.89 - if (member.isStatic()) {
13.90 - long offset = MethodHandleNatives.staticFieldOffset(member);
13.91 - Object base = MethodHandleNatives.staticFieldBase(member);
13.92 - return new StaticAccessor(mtype, lform, member, base, offset);
13.93 - } else {
13.94 - long offset = MethodHandleNatives.objectFieldOffset(member);
13.95 - assert(offset == (int)offset);
13.96 - return new Accessor(mtype, lform, member, (int)offset);
13.97 - }
13.98 - }
13.99 - }
13.100 - static DirectMethodHandle make(Class<?> receiver, MemberName member) {
13.101 - byte refKind = member.getReferenceKind();
13.102 - if (refKind == REF_invokeSpecial)
13.103 - refKind = REF_invokeVirtual;
13.104 - return make(refKind, receiver, member);
13.105 - }
13.106 - static DirectMethodHandle make(MemberName member) {
13.107 - if (member.isConstructor())
13.108 - return makeAllocator(member);
13.109 - return make(member.getDeclaringClass(), member);
13.110 - }
13.111 - static DirectMethodHandle make(Method method) {
13.112 - return make(method.getDeclaringClass(), new MemberName(method));
13.113 - }
13.114 - static DirectMethodHandle make(Field field) {
13.115 - return make(field.getDeclaringClass(), new MemberName(field));
13.116 - }
13.117 - private static DirectMethodHandle makeAllocator(MemberName ctor) {
13.118 - assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
13.119 - Class<?> instanceClass = ctor.getDeclaringClass();
13.120 - ctor = ctor.asConstructor();
13.121 - assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
13.122 - MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
13.123 - LambdaForm lform = preparedLambdaForm(ctor);
13.124 - MemberName init = ctor.asSpecial();
13.125 - assert(init.getMethodType().returnType() == void.class);
13.126 - return new Constructor(mtype, lform, ctor, init, instanceClass);
13.127 - }
13.128 -
13.129 - @Override
13.130 - MethodHandle copyWith(MethodType mt, LambdaForm lf) {
13.131 - return new DirectMethodHandle(mt, lf, member);
13.132 - }
13.133 -
13.134 - @Override
13.135 - String internalProperties() {
13.136 - return "/DMH="+member.toString();
13.137 - }
13.138 -
13.139 - //// Implementation methods.
13.140 - @Override
13.141 - MethodHandle viewAsType(MethodType newType) {
13.142 - return new DirectMethodHandle(newType, form, member);
13.143 - }
13.144 - @Override
13.145 - @ForceInline
13.146 - MemberName internalMemberName() {
13.147 - return member;
13.148 - }
13.149 -
13.150 - @Override
13.151 - MethodHandle bindArgument(int pos, char basicType, Object value) {
13.152 - // If the member needs dispatching, do so.
13.153 - if (pos == 0 && basicType == 'L') {
13.154 - DirectMethodHandle concrete = maybeRebind(value);
13.155 - if (concrete != null)
13.156 - return concrete.bindReceiver(value);
13.157 - }
13.158 - return super.bindArgument(pos, basicType, value);
13.159 - }
13.160 -
13.161 - @Override
13.162 - MethodHandle bindReceiver(Object receiver) {
13.163 - // If the member needs dispatching, do so.
13.164 - DirectMethodHandle concrete = maybeRebind(receiver);
13.165 - if (concrete != null)
13.166 - return concrete.bindReceiver(receiver);
13.167 - return super.bindReceiver(receiver);
13.168 - }
13.169 -
13.170 - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
13.171 -
13.172 - private DirectMethodHandle maybeRebind(Object receiver) {
13.173 - if (receiver != null) {
13.174 - switch (member.getReferenceKind()) {
13.175 - case REF_invokeInterface:
13.176 - case REF_invokeVirtual:
13.177 - // Pre-dispatch the member.
13.178 - Class<?> concreteClass = receiver.getClass();
13.179 - MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial);
13.180 - concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass);
13.181 - if (concrete != null)
13.182 - return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete);
13.183 - break;
13.184 - }
13.185 - }
13.186 - return null;
13.187 - }
13.188 -
13.189 - /**
13.190 - * Create a LF which can invoke the given method.
13.191 - * Cache and share this structure among all methods with
13.192 - * the same basicType and refKind.
13.193 - */
13.194 - private static LambdaForm preparedLambdaForm(MemberName m) {
13.195 - assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead
13.196 - MethodType mtype = m.getInvocationType().basicType();
13.197 - assert(!m.isMethodHandleInvoke() || "invokeBasic".equals(m.getName())) : m;
13.198 - int which;
13.199 - switch (m.getReferenceKind()) {
13.200 - case REF_invokeVirtual: which = LF_INVVIRTUAL; break;
13.201 - case REF_invokeStatic: which = LF_INVSTATIC; break;
13.202 - case REF_invokeSpecial: which = LF_INVSPECIAL; break;
13.203 - case REF_invokeInterface: which = LF_INVINTERFACE; break;
13.204 - case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break;
13.205 - default: throw new InternalError(m.toString());
13.206 - }
13.207 - if (which == LF_INVSTATIC && shouldBeInitialized(m)) {
13.208 - // precompute the barrier-free version:
13.209 - preparedLambdaForm(mtype, which);
13.210 - which = LF_INVSTATIC_INIT;
13.211 - }
13.212 - LambdaForm lform = preparedLambdaForm(mtype, which);
13.213 - maybeCompile(lform, m);
13.214 - assert(lform.methodType().dropParameterTypes(0, 1)
13.215 - .equals(m.getInvocationType().basicType()))
13.216 - : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
13.217 - return lform;
13.218 - }
13.219 -
13.220 - private static LambdaForm preparedLambdaForm(MethodType mtype, int which) {
13.221 - LambdaForm lform = mtype.form().cachedLambdaForm(which);
13.222 - if (lform != null) return lform;
13.223 - lform = makePreparedLambdaForm(mtype, which);
13.224 - return mtype.form().setCachedLambdaForm(which, lform);
13.225 - }
13.226 -
13.227 - private static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) {
13.228 - boolean needsInit = (which == LF_INVSTATIC_INIT);
13.229 - boolean doesAlloc = (which == LF_NEWINVSPECIAL);
13.230 - String linkerName, lambdaName;
13.231 - switch (which) {
13.232 - case LF_INVVIRTUAL: linkerName = "linkToVirtual"; lambdaName = "DMH.invokeVirtual"; break;
13.233 - case LF_INVSTATIC: linkerName = "linkToStatic"; lambdaName = "DMH.invokeStatic"; break;
13.234 - case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; lambdaName = "DMH.invokeStaticInit"; break;
13.235 - case LF_INVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.invokeSpecial"; break;
13.236 - case LF_INVINTERFACE: linkerName = "linkToInterface"; lambdaName = "DMH.invokeInterface"; break;
13.237 - case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; lambdaName = "DMH.newInvokeSpecial"; break;
13.238 - default: throw new InternalError("which="+which);
13.239 - }
13.240 - MethodType mtypeWithArg = mtype.appendParameterTypes(MemberName.class);
13.241 - if (doesAlloc)
13.242 - mtypeWithArg = mtypeWithArg
13.243 - .insertParameterTypes(0, Object.class) // insert newly allocated obj
13.244 - .changeReturnType(void.class); // <init> returns void
13.245 - MemberName linker = new MemberName(MethodHandle.class, linkerName, mtypeWithArg, REF_invokeStatic);
13.246 - try {
13.247 - linker = IMPL_NAMES.resolveOrFail(REF_invokeStatic, linker, null, NoSuchMethodException.class);
13.248 - } catch (ReflectiveOperationException ex) {
13.249 - throw newInternalError(ex);
13.250 - }
13.251 - final int DMH_THIS = 0;
13.252 - final int ARG_BASE = 1;
13.253 - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
13.254 - int nameCursor = ARG_LIMIT;
13.255 - final int NEW_OBJ = (doesAlloc ? nameCursor++ : -1);
13.256 - final int GET_MEMBER = nameCursor++;
13.257 - final int LINKER_CALL = nameCursor++;
13.258 - Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
13.259 - assert(names.length == nameCursor);
13.260 - if (doesAlloc) {
13.261 - // names = { argx,y,z,... new C, init method }
13.262 - names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
13.263 - names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
13.264 - } else if (needsInit) {
13.265 - names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
13.266 - } else {
13.267 - names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
13.268 - }
13.269 - Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
13.270 - assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
13.271 - int result = LambdaForm.LAST_RESULT;
13.272 - if (doesAlloc) {
13.273 - assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one
13.274 - System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
13.275 - outArgs[0] = names[NEW_OBJ];
13.276 - result = NEW_OBJ;
13.277 - }
13.278 - names[LINKER_CALL] = new Name(linker, outArgs);
13.279 - lambdaName += "_" + LambdaForm.basicTypeSignature(mtype);
13.280 - LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
13.281 - // This is a tricky bit of code. Don't send it through the LF interpreter.
13.282 - lform.compileToBytecode();
13.283 - return lform;
13.284 - }
13.285 -
13.286 - private static void maybeCompile(LambdaForm lform, MemberName m) {
13.287 - if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
13.288 - // Help along bootstrapping...
13.289 - lform.compileToBytecode();
13.290 - }
13.291 -
13.292 - /** Static wrapper for DirectMethodHandle.internalMemberName. */
13.293 - @ForceInline
13.294 - /*non-public*/ static Object internalMemberName(Object mh) {
13.295 - return ((DirectMethodHandle)mh).member;
13.296 - }
13.297 -
13.298 - /** Static wrapper for DirectMethodHandle.internalMemberName.
13.299 - * This one also forces initialization.
13.300 - */
13.301 - /*non-public*/ static Object internalMemberNameEnsureInit(Object mh) {
13.302 - DirectMethodHandle dmh = (DirectMethodHandle)mh;
13.303 - dmh.ensureInitialized();
13.304 - return dmh.member;
13.305 - }
13.306 -
13.307 - /*non-public*/ static
13.308 - boolean shouldBeInitialized(MemberName member) {
13.309 - switch (member.getReferenceKind()) {
13.310 - case REF_invokeStatic:
13.311 - case REF_getStatic:
13.312 - case REF_putStatic:
13.313 - case REF_newInvokeSpecial:
13.314 - break;
13.315 - default:
13.316 - // No need to initialize the class on this kind of member.
13.317 - return false;
13.318 - }
13.319 - Class<?> cls = member.getDeclaringClass();
13.320 - if (cls == ValueConversions.class ||
13.321 - cls == MethodHandleImpl.class ||
13.322 - cls == Invokers.class) {
13.323 - // These guys have lots of <clinit> DMH creation but we know
13.324 - // the MHs will not be used until the system is booted.
13.325 - return false;
13.326 - }
13.327 - if (VerifyAccess.isSamePackage(MethodHandle.class, cls) ||
13.328 - VerifyAccess.isSamePackage(ValueConversions.class, cls)) {
13.329 - // It is a system class. It is probably in the process of
13.330 - // being initialized, but we will help it along just to be safe.
13.331 - if (shouldBeInitialized(cls)) {
13.332 - ensureClassInitialized(cls);
13.333 - }
13.334 - return false;
13.335 - }
13.336 - return shouldBeInitialized(cls);
13.337 - }
13.338 -
13.339 - private static class EnsureInitialized extends ClassValue<WeakReference<Thread>> {
13.340 - @Override
13.341 - protected WeakReference<Thread> computeValue(Class<?> type) {
13.342 - ensureClassInitialized(type);
13.343 - if (shouldBeInitialized(type))
13.344 - // If the previous call didn't block, this can happen.
13.345 - // We are executing inside <clinit>.
13.346 - return new WeakReference<>(Thread.currentThread());
13.347 - return null;
13.348 - }
13.349 - static final EnsureInitialized INSTANCE = new EnsureInitialized();
13.350 - }
13.351 -
13.352 - private void ensureInitialized() {
13.353 - if (checkInitialized(member)) {
13.354 - // The coast is clear. Delete the <clinit> barrier.
13.355 - if (member.isField())
13.356 - updateForm(preparedFieldLambdaForm(member));
13.357 - else
13.358 - updateForm(preparedLambdaForm(member));
13.359 - }
13.360 - }
13.361 - private static boolean checkInitialized(MemberName member) {
13.362 - Class<?> defc = member.getDeclaringClass();
13.363 - WeakReference<Thread> ref = EnsureInitialized.INSTANCE.get(defc);
13.364 - if (ref == null) {
13.365 - return true; // the final state
13.366 - }
13.367 - Thread clinitThread = ref.get();
13.368 - // Somebody may still be running defc.<clinit>.
13.369 - if (clinitThread == Thread.currentThread()) {
13.370 - // If anybody is running defc.<clinit>, it is this thread.
13.371 - if (shouldBeInitialized(defc))
13.372 - // Yes, we are running it; keep the barrier for now.
13.373 - return false;
13.374 - } else {
13.375 - // We are in a random thread. Block.
13.376 - ensureClassInitialized(defc);
13.377 - }
13.378 - assert(!shouldBeInitialized(defc));
13.379 - // put it into the final state
13.380 - EnsureInitialized.INSTANCE.remove(defc);
13.381 - return true;
13.382 - }
13.383 -
13.384 - /*non-public*/ static void ensureInitialized(Object mh) {
13.385 - ((DirectMethodHandle)mh).ensureInitialized();
13.386 - }
13.387 -
13.388 - /** This subclass represents invokespecial instructions. */
13.389 - static class Special extends DirectMethodHandle {
13.390 - private Special(MethodType mtype, LambdaForm form, MemberName member) {
13.391 - super(mtype, form, member);
13.392 - }
13.393 - @Override
13.394 - boolean isInvokeSpecial() {
13.395 - return true;
13.396 - }
13.397 - @Override
13.398 - MethodHandle viewAsType(MethodType newType) {
13.399 - return new Special(newType, form, member);
13.400 - }
13.401 - }
13.402 -
13.403 - /** This subclass handles constructor references. */
13.404 - static class Constructor extends DirectMethodHandle {
13.405 - final MemberName initMethod;
13.406 - final Class<?> instanceClass;
13.407 -
13.408 - private Constructor(MethodType mtype, LambdaForm form, MemberName constructor,
13.409 - MemberName initMethod, Class<?> instanceClass) {
13.410 - super(mtype, form, constructor);
13.411 - this.initMethod = initMethod;
13.412 - this.instanceClass = instanceClass;
13.413 - assert(initMethod.isResolved());
13.414 - }
13.415 - @Override
13.416 - MethodHandle viewAsType(MethodType newType) {
13.417 - return new Constructor(newType, form, member, initMethod, instanceClass);
13.418 - }
13.419 - }
13.420 -
13.421 - /*non-public*/ static Object constructorMethod(Object mh) {
13.422 - Constructor dmh = (Constructor)mh;
13.423 - return dmh.initMethod;
13.424 - }
13.425 -
13.426 - /*non-public*/ static Object allocateInstance(Object mh) throws InstantiationException {
13.427 - Constructor dmh = (Constructor)mh;
13.428 - try {
13.429 - return dmh.instanceClass.newInstance();
13.430 -// return UNSAFE.allocateInstance(dmh.instanceClass);
13.431 - } catch (IllegalAccessException ex) {
13.432 - throw (InstantiationException)new InstantiationException().initCause(ex);
13.433 - }
13.434 - }
13.435 -
13.436 - /** This subclass handles non-static field references. */
13.437 - static class Accessor extends DirectMethodHandle {
13.438 - final Class<?> fieldType;
13.439 - final int fieldOffset;
13.440 - private Accessor(MethodType mtype, LambdaForm form, MemberName member,
13.441 - int fieldOffset) {
13.442 - super(mtype, form, member);
13.443 - this.fieldType = member.getFieldType();
13.444 - this.fieldOffset = fieldOffset;
13.445 - }
13.446 -
13.447 - @Override Object checkCast(Object obj) {
13.448 - return fieldType.cast(obj);
13.449 - }
13.450 - @Override
13.451 - MethodHandle viewAsType(MethodType newType) {
13.452 - return new Accessor(newType, form, member, fieldOffset);
13.453 - }
13.454 - }
13.455 -
13.456 - @ForceInline
13.457 - /*non-public*/ static long fieldOffset(Object accessorObj) {
13.458 - // Note: We return a long because that is what Unsafe.getObject likes.
13.459 - // We store a plain int because it is more compact.
13.460 - return ((Accessor)accessorObj).fieldOffset;
13.461 - }
13.462 -
13.463 - @ForceInline
13.464 - /*non-public*/ static Object checkBase(Object obj) {
13.465 - // Note that the object's class has already been verified,
13.466 - // since the parameter type of the Accessor method handle
13.467 - // is either member.getDeclaringClass or a subclass.
13.468 - // This was verified in DirectMethodHandle.make.
13.469 - // Therefore, the only remaining check is for null.
13.470 - // Since this check is *not* guaranteed by Unsafe.getInt
13.471 - // and its siblings, we need to make an explicit one here.
13.472 - obj.getClass(); // maybe throw NPE
13.473 - return obj;
13.474 - }
13.475 -
13.476 - /** This subclass handles static field references. */
13.477 - static class StaticAccessor extends DirectMethodHandle {
13.478 - final private Class<?> fieldType;
13.479 - final private Object staticBase;
13.480 - final private long staticOffset;
13.481 -
13.482 - private StaticAccessor(MethodType mtype, LambdaForm form, MemberName member,
13.483 - Object staticBase, long staticOffset) {
13.484 - super(mtype, form, member);
13.485 - this.fieldType = member.getFieldType();
13.486 - this.staticBase = staticBase;
13.487 - this.staticOffset = staticOffset;
13.488 - }
13.489 -
13.490 - @Override Object checkCast(Object obj) {
13.491 - return fieldType.cast(obj);
13.492 - }
13.493 - @Override
13.494 - MethodHandle viewAsType(MethodType newType) {
13.495 - return new StaticAccessor(newType, form, member, staticBase, staticOffset);
13.496 - }
13.497 - }
13.498 -
13.499 - @ForceInline
13.500 - /*non-public*/ static Object nullCheck(Object obj) {
13.501 - obj.getClass();
13.502 - return obj;
13.503 - }
13.504 -
13.505 - @ForceInline
13.506 - /*non-public*/ static Object staticBase(Object accessorObj) {
13.507 - return ((StaticAccessor)accessorObj).staticBase;
13.508 - }
13.509 -
13.510 - @ForceInline
13.511 - /*non-public*/ static long staticOffset(Object accessorObj) {
13.512 - return ((StaticAccessor)accessorObj).staticOffset;
13.513 - }
13.514 -
13.515 - @ForceInline
13.516 - /*non-public*/ static Object checkCast(Object mh, Object obj) {
13.517 - return ((DirectMethodHandle) mh).checkCast(obj);
13.518 - }
13.519 -
13.520 - Object checkCast(Object obj) {
13.521 - return member.getReturnType().cast(obj);
13.522 - }
13.523 -
13.524 - // Caching machinery for field accessors:
13.525 - private static byte
13.526 - AF_GETFIELD = 0,
13.527 - AF_PUTFIELD = 1,
13.528 - AF_GETSTATIC = 2,
13.529 - AF_PUTSTATIC = 3,
13.530 - AF_GETSTATIC_INIT = 4,
13.531 - AF_PUTSTATIC_INIT = 5,
13.532 - AF_LIMIT = 6;
13.533 - // Enumerate the different field kinds using Wrapper,
13.534 - // with an extra case added for checked references.
13.535 - private static int
13.536 - FT_LAST_WRAPPER = Wrapper.values().length-1,
13.537 - FT_UNCHECKED_REF = Wrapper.OBJECT.ordinal(),
13.538 - FT_CHECKED_REF = FT_LAST_WRAPPER+1,
13.539 - FT_LIMIT = FT_LAST_WRAPPER+2;
13.540 - private static int afIndex(byte formOp, boolean isVolatile, int ftypeKind) {
13.541 - return ((formOp * FT_LIMIT * 2)
13.542 - + (isVolatile ? FT_LIMIT : 0)
13.543 - + ftypeKind);
13.544 - }
13.545 - private static final LambdaForm[] ACCESSOR_FORMS
13.546 - = new LambdaForm[afIndex(AF_LIMIT, false, 0)];
13.547 - private static int ftypeKind(Class<?> ftype) {
13.548 - if (ftype.isPrimitive())
13.549 - return Wrapper.forPrimitiveType(ftype).ordinal();
13.550 - else if (VerifyType.isNullReferenceConversion(Object.class, ftype))
13.551 - return FT_UNCHECKED_REF;
13.552 - else
13.553 - return FT_CHECKED_REF;
13.554 - }
13.555 -
13.556 - /**
13.557 - * Create a LF which can access the given field.
13.558 - * Cache and share this structure among all fields with
13.559 - * the same basicType and refKind.
13.560 - */
13.561 - private static LambdaForm preparedFieldLambdaForm(MemberName m) {
13.562 - Class<?> ftype = m.getFieldType();
13.563 - boolean isVolatile = m.isVolatile();
13.564 - byte formOp;
13.565 - switch (m.getReferenceKind()) {
13.566 - case REF_getField: formOp = AF_GETFIELD; break;
13.567 - case REF_putField: formOp = AF_PUTFIELD; break;
13.568 - case REF_getStatic: formOp = AF_GETSTATIC; break;
13.569 - case REF_putStatic: formOp = AF_PUTSTATIC; break;
13.570 - default: throw new InternalError(m.toString());
13.571 - }
13.572 - if (shouldBeInitialized(m)) {
13.573 - // precompute the barrier-free version:
13.574 - preparedFieldLambdaForm(formOp, isVolatile, ftype);
13.575 - assert((AF_GETSTATIC_INIT - AF_GETSTATIC) ==
13.576 - (AF_PUTSTATIC_INIT - AF_PUTSTATIC));
13.577 - formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC);
13.578 - }
13.579 - LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype);
13.580 - maybeCompile(lform, m);
13.581 - assert(lform.methodType().dropParameterTypes(0, 1)
13.582 - .equals(m.getInvocationType().basicType()))
13.583 - : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType());
13.584 - return lform;
13.585 - }
13.586 - private static LambdaForm preparedFieldLambdaForm(byte formOp, boolean isVolatile, Class<?> ftype) {
13.587 - int afIndex = afIndex(formOp, isVolatile, ftypeKind(ftype));
13.588 - LambdaForm lform = ACCESSOR_FORMS[afIndex];
13.589 - if (lform != null) return lform;
13.590 - lform = makePreparedFieldLambdaForm(formOp, isVolatile, ftypeKind(ftype));
13.591 - ACCESSOR_FORMS[afIndex] = lform; // don't bother with a CAS
13.592 - return lform;
13.593 - }
13.594 -
13.595 - private static LambdaForm makePreparedFieldLambdaForm(byte formOp, boolean isVolatile, int ftypeKind) {
13.596 - boolean isGetter = (formOp & 1) == (AF_GETFIELD & 1);
13.597 - boolean isStatic = (formOp >= AF_GETSTATIC);
13.598 - boolean needsInit = (formOp >= AF_GETSTATIC_INIT);
13.599 - boolean needsCast = (ftypeKind == FT_CHECKED_REF);
13.600 - Wrapper fw = (needsCast ? Wrapper.OBJECT : Wrapper.values()[ftypeKind]);
13.601 - Class<?> ft = fw.primitiveType();
13.602 - assert(ftypeKind(needsCast ? String.class : ft) == ftypeKind);
13.603 - String tname = fw.primitiveSimpleName();
13.604 - String ctname = Character.toUpperCase(tname.charAt(0)) + tname.substring(1);
13.605 - if (isVolatile) ctname += "Volatile";
13.606 - String getOrPut = (isGetter ? "get" : "put");
13.607 - String linkerName = (getOrPut + ctname); // getObject, putIntVolatile, etc.
13.608 - MethodType linkerType;
13.609 - if (isGetter)
13.610 - linkerType = MethodType.methodType(ft, Object.class, long.class);
13.611 - else
13.612 - linkerType = MethodType.methodType(void.class, Object.class, long.class, ft);
13.613 - MemberName linker = null;//new MemberName(Unsafe.class, linkerName, linkerType, REF_invokeVirtual);
13.614 - try {
13.615 - linker = IMPL_NAMES.resolveOrFail(REF_invokeVirtual, linker, null, NoSuchMethodException.class);
13.616 - } catch (ReflectiveOperationException ex) {
13.617 - throw newInternalError(ex);
13.618 - }
13.619 -
13.620 - // What is the external type of the lambda form?
13.621 - MethodType mtype;
13.622 - if (isGetter)
13.623 - mtype = MethodType.methodType(ft);
13.624 - else
13.625 - mtype = MethodType.methodType(void.class, ft);
13.626 - mtype = mtype.basicType(); // erase short to int, etc.
13.627 - if (!isStatic)
13.628 - mtype = mtype.insertParameterTypes(0, Object.class);
13.629 - final int DMH_THIS = 0;
13.630 - final int ARG_BASE = 1;
13.631 - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
13.632 - // if this is for non-static access, the base pointer is stored at this index:
13.633 - final int OBJ_BASE = isStatic ? -1 : ARG_BASE;
13.634 - // if this is for write access, the value to be written is stored at this index:
13.635 - final int SET_VALUE = isGetter ? -1 : ARG_LIMIT - 1;
13.636 - int nameCursor = ARG_LIMIT;
13.637 - final int F_HOLDER = (isStatic ? nameCursor++ : -1); // static base if any
13.638 - final int F_OFFSET = nameCursor++; // Either static offset or field offset.
13.639 - final int OBJ_CHECK = (OBJ_BASE >= 0 ? nameCursor++ : -1);
13.640 - final int INIT_BAR = (needsInit ? nameCursor++ : -1);
13.641 - final int PRE_CAST = (needsCast && !isGetter ? nameCursor++ : -1);
13.642 - final int LINKER_CALL = nameCursor++;
13.643 - final int POST_CAST = (needsCast && isGetter ? nameCursor++ : -1);
13.644 - final int RESULT = nameCursor-1; // either the call or the cast
13.645 - Name[] names = arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
13.646 - if (needsInit)
13.647 - names[INIT_BAR] = new Name(Lazy.NF_ensureInitialized, names[DMH_THIS]);
13.648 - if (needsCast && !isGetter)
13.649 - names[PRE_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[SET_VALUE]);
13.650 - Object[] outArgs = new Object[1 + linkerType.parameterCount()];
13.651 - assert(outArgs.length == (isGetter ? 3 : 4));
13.652 -// outArgs[0] = UNSAFE;
13.653 - if (isStatic) {
13.654 - outArgs[1] = names[F_HOLDER] = new Name(Lazy.NF_staticBase, names[DMH_THIS]);
13.655 - outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_staticOffset, names[DMH_THIS]);
13.656 - } else {
13.657 - outArgs[1] = names[OBJ_CHECK] = new Name(Lazy.NF_checkBase, names[OBJ_BASE]);
13.658 - outArgs[2] = names[F_OFFSET] = new Name(Lazy.NF_fieldOffset, names[DMH_THIS]);
13.659 - }
13.660 - if (!isGetter) {
13.661 - outArgs[3] = (needsCast ? names[PRE_CAST] : names[SET_VALUE]);
13.662 - }
13.663 - for (Object a : outArgs) assert(a != null);
13.664 - names[LINKER_CALL] = new Name(linker, outArgs);
13.665 - if (needsCast && isGetter)
13.666 - names[POST_CAST] = new Name(Lazy.NF_checkCast, names[DMH_THIS], names[LINKER_CALL]);
13.667 - for (Name n : names) assert(n != null);
13.668 - String fieldOrStatic = (isStatic ? "Static" : "Field");
13.669 - String lambdaName = (linkerName + fieldOrStatic); // significant only for debugging
13.670 - if (needsCast) lambdaName += "Cast";
13.671 - if (needsInit) lambdaName += "Init";
13.672 - return new LambdaForm(lambdaName, ARG_LIMIT, names, RESULT);
13.673 - }
13.674 -
13.675 - /**
13.676 - * Pre-initialized NamedFunctions for bootstrapping purposes.
13.677 - * Factored in an inner class to delay initialization until first usage.
13.678 - */
13.679 - private static class Lazy {
13.680 - static final NamedFunction
13.681 - NF_internalMemberName,
13.682 - NF_internalMemberNameEnsureInit,
13.683 - NF_ensureInitialized,
13.684 - NF_fieldOffset,
13.685 - NF_checkBase,
13.686 - NF_staticBase,
13.687 - NF_staticOffset,
13.688 - NF_checkCast,
13.689 - NF_allocateInstance,
13.690 - NF_constructorMethod;
13.691 - static {
13.692 - try {
13.693 - NamedFunction nfs[] = {
13.694 - NF_internalMemberName = new NamedFunction(DirectMethodHandle.class
13.695 - .getDeclaredMethod("internalMemberName", Object.class)),
13.696 - NF_internalMemberNameEnsureInit = new NamedFunction(DirectMethodHandle.class
13.697 - .getDeclaredMethod("internalMemberNameEnsureInit", Object.class)),
13.698 - NF_ensureInitialized = new NamedFunction(DirectMethodHandle.class
13.699 - .getDeclaredMethod("ensureInitialized", Object.class)),
13.700 - NF_fieldOffset = new NamedFunction(DirectMethodHandle.class
13.701 - .getDeclaredMethod("fieldOffset", Object.class)),
13.702 - NF_checkBase = new NamedFunction(DirectMethodHandle.class
13.703 - .getDeclaredMethod("checkBase", Object.class)),
13.704 - NF_staticBase = new NamedFunction(DirectMethodHandle.class
13.705 - .getDeclaredMethod("staticBase", Object.class)),
13.706 - NF_staticOffset = new NamedFunction(DirectMethodHandle.class
13.707 - .getDeclaredMethod("staticOffset", Object.class)),
13.708 - NF_checkCast = new NamedFunction(DirectMethodHandle.class
13.709 - .getDeclaredMethod("checkCast", Object.class, Object.class)),
13.710 - NF_allocateInstance = new NamedFunction(DirectMethodHandle.class
13.711 - .getDeclaredMethod("allocateInstance", Object.class)),
13.712 - NF_constructorMethod = new NamedFunction(DirectMethodHandle.class
13.713 - .getDeclaredMethod("constructorMethod", Object.class))
13.714 - };
13.715 - for (NamedFunction nf : nfs) {
13.716 - // Each nf must be statically invocable or we get tied up in our bootstraps.
13.717 -// assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf;
13.718 - nf.resolve();
13.719 - }
13.720 - } catch (ReflectiveOperationException ex) {
13.721 - throw newInternalError(ex);
13.722 - }
13.723 - }
13.724 - }
13.725 -
13.726 - private static boolean shouldBeInitialized(Class<?> c) {
13.727 - return false;
13.728 - }
13.729 -
13.730 - private static void ensureClassInitialized(Class<?> c) {
13.731 - c.getName();
13.732 - }
13.733 -}
14.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/DontInline.java Sun Aug 17 20:09:05 2014 +0200
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,37 +0,0 @@
14.4 -/*
14.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
14.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
14.7 - *
14.8 - * This code is free software; you can redistribute it and/or modify it
14.9 - * under the terms of the GNU General Public License version 2 only, as
14.10 - * published by the Free Software Foundation. Oracle designates this
14.11 - * particular file as subject to the "Classpath" exception as provided
14.12 - * by Oracle in the LICENSE file that accompanied this code.
14.13 - *
14.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
14.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14.17 - * version 2 for more details (a copy is included in the LICENSE file that
14.18 - * accompanied this code).
14.19 - *
14.20 - * You should have received a copy of the GNU General Public License version
14.21 - * 2 along with this work; if not, write to the Free Software Foundation,
14.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
14.23 - *
14.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
14.25 - * or visit www.oracle.com if you need additional information or have any
14.26 - * questions.
14.27 - */
14.28 -
14.29 -package java.lang.invoke;
14.30 -
14.31 -import java.lang.annotation.*;
14.32 -
14.33 -/**
14.34 - * Internal marker for some methods in the JSR 292 implementation.
14.35 - */
14.36 -/*non-public*/
14.37 -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
14.38 -@Retention(RetentionPolicy.RUNTIME)
14.39 -@interface DontInline {
14.40 -}
15.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/ForceInline.java Sun Aug 17 20:09:05 2014 +0200
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,37 +0,0 @@
15.4 -/*
15.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
15.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
15.7 - *
15.8 - * This code is free software; you can redistribute it and/or modify it
15.9 - * under the terms of the GNU General Public License version 2 only, as
15.10 - * published by the Free Software Foundation. Oracle designates this
15.11 - * particular file as subject to the "Classpath" exception as provided
15.12 - * by Oracle in the LICENSE file that accompanied this code.
15.13 - *
15.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
15.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15.17 - * version 2 for more details (a copy is included in the LICENSE file that
15.18 - * accompanied this code).
15.19 - *
15.20 - * You should have received a copy of the GNU General Public License version
15.21 - * 2 along with this work; if not, write to the Free Software Foundation,
15.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
15.23 - *
15.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
15.25 - * or visit www.oracle.com if you need additional information or have any
15.26 - * questions.
15.27 - */
15.28 -
15.29 -package java.lang.invoke;
15.30 -
15.31 -import java.lang.annotation.*;
15.32 -
15.33 -/**
15.34 - * Internal marker for some methods in the JSR 292 implementation.
15.35 - */
15.36 -/*non-public*/
15.37 -@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
15.38 -@Retention(RetentionPolicy.RUNTIME)
15.39 -@interface ForceInline {
15.40 -}
16.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/InfoFromMemberName.java Sun Aug 17 20:09:05 2014 +0200
16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
16.3 @@ -1,145 +0,0 @@
16.4 -/*
16.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
16.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
16.7 - *
16.8 - * This code is free software; you can redistribute it and/or modify it
16.9 - * under the terms of the GNU General Public License version 2 only, as
16.10 - * published by the Free Software Foundation. Oracle designates this
16.11 - * particular file as subject to the "Classpath" exception as provided
16.12 - * by Oracle in the LICENSE file that accompanied this code.
16.13 - *
16.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
16.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16.17 - * version 2 for more details (a copy is included in the LICENSE file that
16.18 - * accompanied this code).
16.19 - *
16.20 - * You should have received a copy of the GNU General Public License version
16.21 - * 2 along with this work; if not, write to the Free Software Foundation,
16.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
16.23 - *
16.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
16.25 - * or visit www.oracle.com if you need additional information or have any
16.26 - * questions.
16.27 - */
16.28 -
16.29 -package java.lang.invoke;
16.30 -
16.31 -import java.security.*;
16.32 -import java.lang.reflect.*;
16.33 -import java.lang.invoke.MethodHandleNatives.Constants;
16.34 -import java.lang.invoke.MethodHandles.Lookup;
16.35 -import static java.lang.invoke.MethodHandleStatics.*;
16.36 -
16.37 -/*
16.38 - * Auxiliary to MethodHandleInfo, wants to nest in MethodHandleInfo but must be non-public.
16.39 - */
16.40 -/*non-public*/
16.41 -final
16.42 -class InfoFromMemberName implements MethodHandleInfo {
16.43 - private final MemberName member;
16.44 - private final int referenceKind;
16.45 -
16.46 - InfoFromMemberName(Lookup lookup, MemberName member, byte referenceKind) {
16.47 - assert(member.isResolved() || member.isMethodHandleInvoke());
16.48 - assert(member.referenceKindIsConsistentWith(referenceKind));
16.49 - this.member = member;
16.50 - this.referenceKind = referenceKind;
16.51 - }
16.52 -
16.53 - @Override
16.54 - public Class<?> getDeclaringClass() {
16.55 - return member.getDeclaringClass();
16.56 - }
16.57 -
16.58 - @Override
16.59 - public String getName() {
16.60 - return member.getName();
16.61 - }
16.62 -
16.63 - @Override
16.64 - public MethodType getMethodType() {
16.65 - return member.getMethodOrFieldType();
16.66 - }
16.67 -
16.68 - @Override
16.69 - public int getModifiers() {
16.70 - return member.getModifiers();
16.71 - }
16.72 -
16.73 - @Override
16.74 - public int getReferenceKind() {
16.75 - return referenceKind;
16.76 - }
16.77 -
16.78 - @Override
16.79 - public String toString() {
16.80 - return MethodHandleInfo.toString(getReferenceKind(), getDeclaringClass(), getName(), getMethodType());
16.81 - }
16.82 -
16.83 - @Override
16.84 - public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup) {
16.85 - if (member.isMethodHandleInvoke() && !member.isVarargs()) {
16.86 - // This member is an instance of a signature-polymorphic method, which cannot be reflected
16.87 - // A method handle invoker can come in either of two forms:
16.88 - // A generic placeholder (present in the source code, and varargs)
16.89 - // and a signature-polymorphic instance (synthetic and not varargs).
16.90 - // For more information see comments on {@link MethodHandleNatives#linkMethod}.
16.91 - throw new IllegalArgumentException("cannot reflect signature polymorphic method");
16.92 - }
16.93 - Member mem = AccessController.doPrivileged(new PrivilegedAction<Member>() {
16.94 - public Member run() {
16.95 - try {
16.96 - return reflectUnchecked();
16.97 - } catch (ReflectiveOperationException ex) {
16.98 - throw new IllegalArgumentException(ex);
16.99 - }
16.100 - }
16.101 - });
16.102 - try {
16.103 - Class<?> defc = getDeclaringClass();
16.104 - byte refKind = (byte) getReferenceKind();
16.105 - lookup.checkAccess(refKind, defc, convertToMemberName(refKind, mem));
16.106 - } catch (IllegalAccessException ex) {
16.107 - throw new IllegalArgumentException(ex);
16.108 - }
16.109 - return expected.cast(mem);
16.110 - }
16.111 -
16.112 - private Member reflectUnchecked() throws ReflectiveOperationException {
16.113 - byte refKind = (byte) getReferenceKind();
16.114 - Class<?> defc = getDeclaringClass();
16.115 - boolean isPublic = Modifier.isPublic(getModifiers());
16.116 - if (MethodHandleNatives.refKindIsMethod(refKind)) {
16.117 - if (isPublic)
16.118 - return defc.getMethod(getName(), getMethodType().parameterArray());
16.119 - else
16.120 - return defc.getDeclaredMethod(getName(), getMethodType().parameterArray());
16.121 - } else if (MethodHandleNatives.refKindIsConstructor(refKind)) {
16.122 - if (isPublic)
16.123 - return defc.getConstructor(getMethodType().parameterArray());
16.124 - else
16.125 - return defc.getDeclaredConstructor(getMethodType().parameterArray());
16.126 - } else if (MethodHandleNatives.refKindIsField(refKind)) {
16.127 - if (isPublic)
16.128 - return defc.getField(getName());
16.129 - else
16.130 - return defc.getDeclaredField(getName());
16.131 - } else {
16.132 - throw new IllegalArgumentException("referenceKind="+refKind);
16.133 - }
16.134 - }
16.135 -
16.136 - private static MemberName convertToMemberName(byte refKind, Member mem) throws IllegalAccessException {
16.137 - if (mem instanceof Method) {
16.138 - boolean wantSpecial = (refKind == REF_invokeSpecial);
16.139 - return new MemberName((Method) mem, wantSpecial);
16.140 - } else if (mem instanceof Constructor) {
16.141 - return new MemberName((Constructor) mem);
16.142 - } else if (mem instanceof Field) {
16.143 - boolean isSetter = (refKind == REF_putField || refKind == REF_putStatic);
16.144 - return new MemberName((Field) mem, isSetter);
16.145 - }
16.146 - throw new InternalError(mem.getClass().getName());
16.147 - }
16.148 -}
17.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/InvokeDynamic.java Sun Aug 17 20:09:05 2014 +0200
17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
17.3 @@ -1,33 +0,0 @@
17.4 -/*
17.5 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
17.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
17.7 - *
17.8 - * This code is free software; you can redistribute it and/or modify it
17.9 - * under the terms of the GNU General Public License version 2 only, as
17.10 - * published by the Free Software Foundation. Oracle designates this
17.11 - * particular file as subject to the "Classpath" exception as provided
17.12 - * by Oracle in the LICENSE file that accompanied this code.
17.13 - *
17.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
17.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17.17 - * version 2 for more details (a copy is included in the LICENSE file that
17.18 - * accompanied this code).
17.19 - *
17.20 - * You should have received a copy of the GNU General Public License version
17.21 - * 2 along with this work; if not, write to the Free Software Foundation,
17.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17.23 - *
17.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
17.25 - * or visit www.oracle.com if you need additional information or have any
17.26 - * questions.
17.27 - */
17.28 -
17.29 -package java.lang.invoke;
17.30 -
17.31 -/**
17.32 - * This is a place-holder class. Some HotSpot implementations need to see it.
17.33 - */
17.34 -final class InvokeDynamic {
17.35 - private InvokeDynamic() { throw new InternalError(); } // do not instantiate
17.36 -}
18.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/Invokers.java Sun Aug 17 20:09:05 2014 +0200
18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
18.3 @@ -1,462 +0,0 @@
18.4 -/*
18.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
18.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
18.7 - *
18.8 - * This code is free software; you can redistribute it and/or modify it
18.9 - * under the terms of the GNU General Public License version 2 only, as
18.10 - * published by the Free Software Foundation. Oracle designates this
18.11 - * particular file as subject to the "Classpath" exception as provided
18.12 - * by Oracle in the LICENSE file that accompanied this code.
18.13 - *
18.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
18.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18.17 - * version 2 for more details (a copy is included in the LICENSE file that
18.18 - * accompanied this code).
18.19 - *
18.20 - * You should have received a copy of the GNU General Public License version
18.21 - * 2 along with this work; if not, write to the Free Software Foundation,
18.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18.23 - *
18.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
18.25 - * or visit www.oracle.com if you need additional information or have any
18.26 - * questions.
18.27 - */
18.28 -
18.29 -package java.lang.invoke;
18.30 -
18.31 -import java.util.Arrays;
18.32 -import sun.invoke.empty.Empty;
18.33 -import static java.lang.invoke.MethodHandleStatics.*;
18.34 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
18.35 -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
18.36 -import static java.lang.invoke.LambdaForm.*;
18.37 -
18.38 -/**
18.39 - * Construction and caching of often-used invokers.
18.40 - * @author jrose
18.41 - */
18.42 -class Invokers {
18.43 - // exact type (sans leading taget MH) for the outgoing call
18.44 - private final MethodType targetType;
18.45 -
18.46 - // FIXME: Get rid of the invokers that are not useful.
18.47 -
18.48 - // exact invoker for the outgoing call
18.49 - private /*lazy*/ MethodHandle exactInvoker;
18.50 - private /*lazy*/ MethodHandle basicInvoker; // invokeBasic (unchecked exact)
18.51 -
18.52 - // erased (partially untyped but with primitives) invoker for the outgoing call
18.53 - // FIXME: get rid of
18.54 - private /*lazy*/ MethodHandle erasedInvoker;
18.55 - // FIXME: get rid of
18.56 - /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric
18.57 -
18.58 - // general invoker for the outgoing call
18.59 - private /*lazy*/ MethodHandle generalInvoker;
18.60 -
18.61 - // general invoker for the outgoing call, uses varargs
18.62 - private /*lazy*/ MethodHandle varargsInvoker;
18.63 -
18.64 - // general invoker for the outgoing call; accepts a trailing Object[]
18.65 - private final /*lazy*/ MethodHandle[] spreadInvokers;
18.66 -
18.67 - // invoker for an unbound callsite
18.68 - private /*lazy*/ MethodHandle uninitializedCallSite;
18.69 -
18.70 - /** Compute and cache information common to all collecting adapters
18.71 - * that implement members of the erasure-family of the given erased type.
18.72 - */
18.73 - /*non-public*/ Invokers(MethodType targetType) {
18.74 - this.targetType = targetType;
18.75 - this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1];
18.76 - }
18.77 -
18.78 - /*non-public*/ MethodHandle exactInvoker() {
18.79 - MethodHandle invoker = exactInvoker;
18.80 - if (invoker != null) return invoker;
18.81 - invoker = makeExactOrGeneralInvoker(true);
18.82 - exactInvoker = invoker;
18.83 - return invoker;
18.84 - }
18.85 -
18.86 - /*non-public*/ MethodHandle generalInvoker() {
18.87 - MethodHandle invoker = generalInvoker;
18.88 - if (invoker != null) return invoker;
18.89 - invoker = makeExactOrGeneralInvoker(false);
18.90 - generalInvoker = invoker;
18.91 - return invoker;
18.92 - }
18.93 -
18.94 - private MethodHandle makeExactOrGeneralInvoker(boolean isExact) {
18.95 - MethodType mtype = targetType;
18.96 - MethodType invokerType = mtype.invokerType();
18.97 - int which = (isExact ? MethodTypeForm.LF_EX_INVOKER : MethodTypeForm.LF_GEN_INVOKER);
18.98 - LambdaForm lform = invokeHandleForm(mtype, false, which);
18.99 - MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype);
18.100 - String whichName = (isExact ? "invokeExact" : "invoke");
18.101 - invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype));
18.102 - assert(checkInvoker(invoker));
18.103 - maybeCompileToBytecode(invoker);
18.104 - return invoker;
18.105 - }
18.106 -
18.107 - /** If the target type seems to be common enough, eagerly compile the invoker to bytecodes. */
18.108 - private void maybeCompileToBytecode(MethodHandle invoker) {
18.109 - final int EAGER_COMPILE_ARITY_LIMIT = 10;
18.110 - if (targetType == targetType.erase() &&
18.111 - targetType.parameterCount() < EAGER_COMPILE_ARITY_LIMIT) {
18.112 - invoker.form.compileToBytecode();
18.113 - }
18.114 - }
18.115 -
18.116 - /*non-public*/ MethodHandle basicInvoker() {
18.117 - MethodHandle invoker = basicInvoker;
18.118 - if (invoker != null) return invoker;
18.119 - MethodType basicType = targetType.basicType();
18.120 - if (basicType != targetType) {
18.121 - // double cache; not used significantly
18.122 - return basicInvoker = basicType.invokers().basicInvoker();
18.123 - }
18.124 - MemberName method = invokeBasicMethod(basicType);
18.125 - invoker = DirectMethodHandle.make(method);
18.126 - assert(checkInvoker(invoker));
18.127 - basicInvoker = invoker;
18.128 - return invoker;
18.129 - }
18.130 -
18.131 - // This next one is called from LambdaForm.NamedFunction.<init>.
18.132 - /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
18.133 - assert(basicType == basicType.basicType());
18.134 - try {
18.135 - //Lookup.findVirtual(MethodHandle.class, name, type);
18.136 - return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
18.137 - } catch (ReflectiveOperationException ex) {
18.138 - throw newInternalError("JVM cannot find invoker for "+basicType, ex);
18.139 - }
18.140 - }
18.141 -
18.142 - private boolean checkInvoker(MethodHandle invoker) {
18.143 - assert(targetType.invokerType().equals(invoker.type()))
18.144 - : java.util.Arrays.asList(targetType, targetType.invokerType(), invoker);
18.145 - assert(invoker.internalMemberName() == null ||
18.146 - invoker.internalMemberName().getMethodType().equals(targetType));
18.147 - assert(!invoker.isVarargsCollector());
18.148 - return true;
18.149 - }
18.150 -
18.151 - // FIXME: get rid of
18.152 - /*non-public*/ MethodHandle erasedInvoker() {
18.153 - MethodHandle xinvoker = exactInvoker();
18.154 - MethodHandle invoker = erasedInvoker;
18.155 - if (invoker != null) return invoker;
18.156 - MethodType erasedType = targetType.erase();
18.157 - invoker = xinvoker.asType(erasedType.invokerType());
18.158 - erasedInvoker = invoker;
18.159 - return invoker;
18.160 - }
18.161 -
18.162 - /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) {
18.163 - MethodHandle vaInvoker = spreadInvokers[leadingArgCount];
18.164 - if (vaInvoker != null) return vaInvoker;
18.165 - int spreadArgCount = targetType.parameterCount() - leadingArgCount;
18.166 - MethodType spreadInvokerType = targetType
18.167 - .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class);
18.168 - if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) {
18.169 - // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a)
18.170 - // where ginvoker.invoke(mh, a*) => mh.invoke(a*).
18.171 - MethodHandle genInvoker = generalInvoker();
18.172 - vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount);
18.173 - } else {
18.174 - // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]).
18.175 - // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a)
18.176 - // where filter(mh) == mh.asSpreader(Object[], spreadArgCount)
18.177 - MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType);
18.178 - MethodHandle makeSpreader;
18.179 - try {
18.180 - makeSpreader = IMPL_LOOKUP
18.181 - .findVirtual(MethodHandle.class, "asSpreader",
18.182 - MethodType.methodType(MethodHandle.class, Class.class, int.class));
18.183 - } catch (ReflectiveOperationException ex) {
18.184 - throw newInternalError(ex);
18.185 - }
18.186 - makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount);
18.187 - vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader);
18.188 - }
18.189 - assert(vaInvoker.type().equals(spreadInvokerType.invokerType()));
18.190 - maybeCompileToBytecode(vaInvoker);
18.191 - spreadInvokers[leadingArgCount] = vaInvoker;
18.192 - return vaInvoker;
18.193 - }
18.194 -
18.195 - /*non-public*/ MethodHandle varargsInvoker() {
18.196 - MethodHandle vaInvoker = varargsInvoker;
18.197 - if (vaInvoker != null) return vaInvoker;
18.198 - vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType());
18.199 - varargsInvoker = vaInvoker;
18.200 - return vaInvoker;
18.201 - }
18.202 -
18.203 - private static MethodHandle THROW_UCS = null;
18.204 -
18.205 - /*non-public*/ MethodHandle uninitializedCallSite() {
18.206 - MethodHandle invoker = uninitializedCallSite;
18.207 - if (invoker != null) return invoker;
18.208 - if (targetType.parameterCount() > 0) {
18.209 - MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount());
18.210 - Invokers invokers0 = type0.invokers();
18.211 - invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(),
18.212 - 0, targetType.parameterList());
18.213 - assert(invoker.type().equals(targetType));
18.214 - uninitializedCallSite = invoker;
18.215 - return invoker;
18.216 - }
18.217 - invoker = THROW_UCS;
18.218 - if (invoker == null) {
18.219 - try {
18.220 - THROW_UCS = invoker = IMPL_LOOKUP
18.221 - .findStatic(CallSite.class, "uninitializedCallSite",
18.222 - MethodType.methodType(Empty.class));
18.223 - } catch (ReflectiveOperationException ex) {
18.224 - throw newInternalError(ex);
18.225 - }
18.226 - }
18.227 - invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType()));
18.228 - invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount());
18.229 - assert(invoker.type().equals(targetType));
18.230 - uninitializedCallSite = invoker;
18.231 - return invoker;
18.232 - }
18.233 -
18.234 - public String toString() {
18.235 - return "Invokers"+targetType;
18.236 - }
18.237 -
18.238 - static MemberName methodHandleInvokeLinkerMethod(String name,
18.239 - MethodType mtype,
18.240 - Object[] appendixResult) {
18.241 - int which;
18.242 - switch (name) {
18.243 - case "invokeExact": which = MethodTypeForm.LF_EX_LINKER; break;
18.244 - case "invoke": which = MethodTypeForm.LF_GEN_LINKER; break;
18.245 - default: throw new InternalError("not invoker: "+name);
18.246 - }
18.247 - LambdaForm lform;
18.248 - if (mtype.parameterSlotCount() <= MethodType.MAX_MH_ARITY - MH_LINKER_ARG_APPENDED) {
18.249 - lform = invokeHandleForm(mtype, false, which);
18.250 - appendixResult[0] = mtype;
18.251 - } else {
18.252 - lform = invokeHandleForm(mtype, true, which);
18.253 - }
18.254 - return lform.vmentry;
18.255 - }
18.256 -
18.257 - // argument count to account for trailing "appendix value" (typically the mtype)
18.258 - private static final int MH_LINKER_ARG_APPENDED = 1;
18.259 -
18.260 - /** Returns an adapter for invokeExact or generic invoke, as a MH or constant pool linker.
18.261 - * If !customized, caller is responsible for supplying, during adapter execution,
18.262 - * a copy of the exact mtype. This is because the adapter might be generalized to
18.263 - * a basic type.
18.264 - * @param mtype the caller's method type (either basic or full-custom)
18.265 - * @param customized whether to use a trailing appendix argument (to carry the mtype)
18.266 - * @param which bit-encoded 0x01 whether it is a CP adapter ("linker") or MHs.invoker value ("invoker");
18.267 - * 0x02 whether it is for invokeExact or generic invoke
18.268 - */
18.269 - private static LambdaForm invokeHandleForm(MethodType mtype, boolean customized, int which) {
18.270 - boolean isCached;
18.271 - if (!customized) {
18.272 - mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
18.273 - isCached = true;
18.274 - } else {
18.275 - isCached = false; // maybe cache if mtype == mtype.basicType()
18.276 - }
18.277 - boolean isLinker, isGeneric;
18.278 - String debugName;
18.279 - switch (which) {
18.280 - case MethodTypeForm.LF_EX_LINKER: isLinker = true; isGeneric = false; debugName = "invokeExact_MT"; break;
18.281 - case MethodTypeForm.LF_EX_INVOKER: isLinker = false; isGeneric = false; debugName = "exactInvoker"; break;
18.282 - case MethodTypeForm.LF_GEN_LINKER: isLinker = true; isGeneric = true; debugName = "invoke_MT"; break;
18.283 - case MethodTypeForm.LF_GEN_INVOKER: isLinker = false; isGeneric = true; debugName = "invoker"; break;
18.284 - default: throw new InternalError();
18.285 - }
18.286 - LambdaForm lform;
18.287 - if (isCached) {
18.288 - lform = mtype.form().cachedLambdaForm(which);
18.289 - if (lform != null) return lform;
18.290 - }
18.291 - // exactInvokerForm (Object,Object)Object
18.292 - // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
18.293 - final int THIS_MH = 0;
18.294 - final int CALL_MH = THIS_MH + (isLinker ? 0 : 1);
18.295 - final int ARG_BASE = CALL_MH + 1;
18.296 - final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
18.297 - final int INARG_LIMIT = OUTARG_LIMIT + (isLinker && !customized ? 1 : 0);
18.298 - int nameCursor = OUTARG_LIMIT;
18.299 - final int MTYPE_ARG = customized ? -1 : nameCursor++; // might be last in-argument
18.300 - final int CHECK_TYPE = nameCursor++;
18.301 - final int LINKER_CALL = nameCursor++;
18.302 - MethodType invokerFormType = mtype.invokerType();
18.303 - if (isLinker) {
18.304 - if (!customized)
18.305 - invokerFormType = invokerFormType.appendParameterTypes(MemberName.class);
18.306 - } else {
18.307 - invokerFormType = invokerFormType.invokerType();
18.308 - }
18.309 - Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
18.310 - assert(names.length == nameCursor)
18.311 - : Arrays.asList(mtype, customized, which, nameCursor, names.length);
18.312 - if (MTYPE_ARG >= INARG_LIMIT) {
18.313 - assert(names[MTYPE_ARG] == null);
18.314 - NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0);
18.315 - names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
18.316 - // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
18.317 - }
18.318 -
18.319 - // Make the final call. If isGeneric, then prepend the result of type checking.
18.320 - MethodType outCallType = mtype.basicType();
18.321 - Object[] outArgs = Arrays.copyOfRange(names, CALL_MH, OUTARG_LIMIT, Object[].class);
18.322 - Object mtypeArg = (customized ? mtype : names[MTYPE_ARG]);
18.323 - if (!isGeneric) {
18.324 - names[CHECK_TYPE] = new Name(NF_checkExactType, names[CALL_MH], mtypeArg);
18.325 - // mh.invokeExact(a*):R => checkExactType(mh, TYPEOF(a*:R)); mh.invokeBasic(a*)
18.326 - } else {
18.327 - names[CHECK_TYPE] = new Name(NF_checkGenericType, names[CALL_MH], mtypeArg);
18.328 - // mh.invokeGeneric(a*):R => checkGenericType(mh, TYPEOF(a*:R)).invokeBasic(a*)
18.329 - outArgs[0] = names[CHECK_TYPE];
18.330 - }
18.331 - names[LINKER_CALL] = new Name(outCallType, outArgs);
18.332 - lform = new LambdaForm(debugName, INARG_LIMIT, names);
18.333 - if (isLinker)
18.334 - lform.compileToBytecode(); // JVM needs a real methodOop
18.335 - if (isCached)
18.336 - lform = mtype.form().setCachedLambdaForm(which, lform);
18.337 - return lform;
18.338 - }
18.339 -
18.340 - /*non-public*/ static
18.341 - WrongMethodTypeException newWrongMethodTypeException(MethodType actual, MethodType expected) {
18.342 - // FIXME: merge with JVM logic for throwing WMTE
18.343 - return new WrongMethodTypeException("expected "+expected+" but found "+actual);
18.344 - }
18.345 -
18.346 - /** Static definition of MethodHandle.invokeExact checking code. */
18.347 - /*non-public*/ static
18.348 - @ForceInline
18.349 - void checkExactType(Object mhObj, Object expectedObj) {
18.350 - MethodHandle mh = (MethodHandle) mhObj;
18.351 - MethodType expected = (MethodType) expectedObj;
18.352 - MethodType actual = mh.type();
18.353 - if (actual != expected)
18.354 - throw newWrongMethodTypeException(expected, actual);
18.355 - }
18.356 -
18.357 - /** Static definition of MethodHandle.invokeGeneric checking code.
18.358 - * Directly returns the type-adjusted MH to invoke, as follows:
18.359 - * {@code (R)MH.invoke(a*) => MH.asType(TYPEOF(a*:R)).invokeBasic(a*)}
18.360 - */
18.361 - /*non-public*/ static
18.362 - @ForceInline
18.363 - Object checkGenericType(Object mhObj, Object expectedObj) {
18.364 - MethodHandle mh = (MethodHandle) mhObj;
18.365 - MethodType expected = (MethodType) expectedObj;
18.366 - if (mh.type() == expected) return mh;
18.367 - MethodHandle atc = mh.asTypeCache;
18.368 - if (atc != null && atc.type() == expected) return atc;
18.369 - return mh.asType(expected);
18.370 - /* Maybe add more paths here. Possible optimizations:
18.371 - * for (R)MH.invoke(a*),
18.372 - * let MT0 = TYPEOF(a*:R), MT1 = MH.type
18.373 - *
18.374 - * if MT0==MT1 or MT1 can be safely called by MT0
18.375 - * => MH.invokeBasic(a*)
18.376 - * if MT1 can be safely called by MT0[R := Object]
18.377 - * => MH.invokeBasic(a*) & checkcast(R)
18.378 - * if MT1 can be safely called by MT0[* := Object]
18.379 - * => checkcast(A)* & MH.invokeBasic(a*) & checkcast(R)
18.380 - * if a big adapter BA can be pulled out of (MT0,MT1)
18.381 - * => BA.invokeBasic(MT0,MH,a*)
18.382 - * if a local adapter LA can cached on static CS0 = new GICS(MT0)
18.383 - * => CS0.LA.invokeBasic(MH,a*)
18.384 - * else
18.385 - * => MH.asType(MT0).invokeBasic(A*)
18.386 - */
18.387 - }
18.388 -
18.389 - static MemberName linkToCallSiteMethod(MethodType mtype) {
18.390 - LambdaForm lform = callSiteForm(mtype, false);
18.391 - return lform.vmentry;
18.392 - }
18.393 -
18.394 - static MemberName linkToTargetMethod(MethodType mtype) {
18.395 - LambdaForm lform = callSiteForm(mtype, true);
18.396 - return lform.vmentry;
18.397 - }
18.398 -
18.399 - // skipCallSite is true if we are optimizing a ConstantCallSite
18.400 - private static LambdaForm callSiteForm(MethodType mtype, boolean skipCallSite) {
18.401 - mtype = mtype.basicType(); // normalize Z to I, String to Object, etc.
18.402 - final int which = (skipCallSite ? MethodTypeForm.LF_MH_LINKER : MethodTypeForm.LF_CS_LINKER);
18.403 - LambdaForm lform = mtype.form().cachedLambdaForm(which);
18.404 - if (lform != null) return lform;
18.405 - // exactInvokerForm (Object,Object)Object
18.406 - // link with java.lang.invoke.MethodHandle.invokeBasic(MethodHandle,Object,Object)Object/invokeSpecial
18.407 - final int ARG_BASE = 0;
18.408 - final int OUTARG_LIMIT = ARG_BASE + mtype.parameterCount();
18.409 - final int INARG_LIMIT = OUTARG_LIMIT + 1;
18.410 - int nameCursor = OUTARG_LIMIT;
18.411 - final int APPENDIX_ARG = nameCursor++; // the last in-argument
18.412 - final int CSITE_ARG = skipCallSite ? -1 : APPENDIX_ARG;
18.413 - final int CALL_MH = skipCallSite ? APPENDIX_ARG : nameCursor++; // result of getTarget
18.414 - final int LINKER_CALL = nameCursor++;
18.415 - MethodType invokerFormType = mtype.appendParameterTypes(skipCallSite ? MethodHandle.class : CallSite.class);
18.416 - Name[] names = arguments(nameCursor - INARG_LIMIT, invokerFormType);
18.417 - assert(names.length == nameCursor);
18.418 - assert(names[APPENDIX_ARG] != null);
18.419 - if (!skipCallSite)
18.420 - names[CALL_MH] = new Name(NF_getCallSiteTarget, names[CSITE_ARG]);
18.421 - // (site.)invokedynamic(a*):R => mh = site.getTarget(); mh.invokeBasic(a*)
18.422 - final int PREPEND_MH = 0, PREPEND_COUNT = 1;
18.423 - Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, OUTARG_LIMIT + PREPEND_COUNT, Object[].class);
18.424 - // prepend MH argument:
18.425 - System.arraycopy(outArgs, 0, outArgs, PREPEND_COUNT, outArgs.length - PREPEND_COUNT);
18.426 - outArgs[PREPEND_MH] = names[CALL_MH];
18.427 - names[LINKER_CALL] = new Name(mtype, outArgs);
18.428 - lform = new LambdaForm((skipCallSite ? "linkToTargetMethod" : "linkToCallSite"), INARG_LIMIT, names);
18.429 - lform.compileToBytecode(); // JVM needs a real methodOop
18.430 - lform = mtype.form().setCachedLambdaForm(which, lform);
18.431 - return lform;
18.432 - }
18.433 -
18.434 - /** Static definition of MethodHandle.invokeGeneric checking code. */
18.435 - /*non-public*/ static
18.436 - @ForceInline
18.437 - Object getCallSiteTarget(Object site) {
18.438 - return ((CallSite)site).getTarget();
18.439 - }
18.440 -
18.441 - // Local constant functions:
18.442 - private static final NamedFunction NF_checkExactType;
18.443 - private static final NamedFunction NF_checkGenericType;
18.444 - private static final NamedFunction NF_asType;
18.445 - private static final NamedFunction NF_getCallSiteTarget;
18.446 - static {
18.447 - try {
18.448 - NF_checkExactType = new NamedFunction(Invokers.class
18.449 - .getDeclaredMethod("checkExactType", Object.class, Object.class));
18.450 - NF_checkGenericType = new NamedFunction(Invokers.class
18.451 - .getDeclaredMethod("checkGenericType", Object.class, Object.class));
18.452 - NF_asType = new NamedFunction(MethodHandle.class
18.453 - .getDeclaredMethod("asType", MethodType.class));
18.454 - NF_getCallSiteTarget = new NamedFunction(Invokers.class
18.455 - .getDeclaredMethod("getCallSiteTarget", Object.class));
18.456 - NF_checkExactType.resolve();
18.457 - NF_checkGenericType.resolve();
18.458 - NF_getCallSiteTarget.resolve();
18.459 - // bound
18.460 - } catch (ReflectiveOperationException ex) {
18.461 - throw newInternalError(ex);
18.462 - }
18.463 - }
18.464 -
18.465 -}
19.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaConversionException.java Sun Aug 17 20:09:05 2014 +0200
19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
19.3 @@ -1,76 +0,0 @@
19.4 -/*
19.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
19.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
19.7 - *
19.8 - * This code is free software; you can redistribute it and/or modify it
19.9 - * under the terms of the GNU General Public License version 2 only, as
19.10 - * published by the Free Software Foundation. Oracle designates this
19.11 - * particular file as subject to the "Classpath" exception as provided
19.12 - * by Oracle in the LICENSE file that accompanied this code.
19.13 - *
19.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
19.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19.17 - * version 2 for more details (a copy is included in the LICENSE file that
19.18 - * accompanied this code).
19.19 - *
19.20 - * You should have received a copy of the GNU General Public License version
19.21 - * 2 along with this work; if not, write to the Free Software Foundation,
19.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19.23 - *
19.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19.25 - * or visit www.oracle.com if you need additional information or have any
19.26 - * questions.
19.27 - */
19.28 -
19.29 -package java.lang.invoke;
19.30 -
19.31 -/**
19.32 - * LambdaConversionException
19.33 - */
19.34 -public class LambdaConversionException extends Exception {
19.35 - private static final long serialVersionUID = 292L + 8L;
19.36 -
19.37 - /**
19.38 - * Constructs a {@code LambdaConversionException}.
19.39 - */
19.40 - public LambdaConversionException() {
19.41 - }
19.42 -
19.43 - /**
19.44 - * Constructs a {@code LambdaConversionException} with a message.
19.45 - * @param message the detail message
19.46 - */
19.47 - public LambdaConversionException(String message) {
19.48 - super(message);
19.49 - }
19.50 -
19.51 - /**
19.52 - * Constructs a {@code LambdaConversionException} with a message and cause.
19.53 - * @param message the detail message
19.54 - * @param cause the cause
19.55 - */
19.56 - public LambdaConversionException(String message, Throwable cause) {
19.57 - super(message, cause);
19.58 - }
19.59 -
19.60 - /**
19.61 - * Constructs a {@code LambdaConversionException} with a cause.
19.62 - * @param cause the cause
19.63 - */
19.64 - public LambdaConversionException(Throwable cause) {
19.65 - super(cause);
19.66 - }
19.67 -
19.68 - /**
19.69 - * Constructs a {@code LambdaConversionException} with a message,
19.70 - * cause, and other settings.
19.71 - * @param message the detail message
19.72 - * @param cause the cause
19.73 - * @param enableSuppression whether or not suppressed exceptions are enabled
19.74 - * @param writableStackTrace whether or not the stack trace is writable
19.75 - */
19.76 - public LambdaConversionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
19.77 - super(message, cause, enableSuppression, writableStackTrace);
19.78 - }
19.79 -}
20.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaForm.java Sun Aug 17 20:09:05 2014 +0200
20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
20.3 @@ -1,1650 +0,0 @@
20.4 -/*
20.5 - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
20.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
20.7 - *
20.8 - * This code is free software; you can redistribute it and/or modify it
20.9 - * under the terms of the GNU General Public License version 2 only, as
20.10 - * published by the Free Software Foundation. Oracle designates this
20.11 - * particular file as subject to the "Classpath" exception as provided
20.12 - * by Oracle in the LICENSE file that accompanied this code.
20.13 - *
20.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
20.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20.17 - * version 2 for more details (a copy is included in the LICENSE file that
20.18 - * accompanied this code).
20.19 - *
20.20 - * You should have received a copy of the GNU General Public License version
20.21 - * 2 along with this work; if not, write to the Free Software Foundation,
20.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20.23 - *
20.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20.25 - * or visit www.oracle.com if you need additional information or have any
20.26 - * questions.
20.27 - */
20.28 -
20.29 -package java.lang.invoke;
20.30 -
20.31 -import java.lang.annotation.*;
20.32 -import java.lang.reflect.Method;
20.33 -import java.util.Map;
20.34 -import java.util.List;
20.35 -import java.util.Arrays;
20.36 -import java.util.ArrayList;
20.37 -import java.util.HashMap;
20.38 -import java.util.concurrent.ConcurrentHashMap;
20.39 -import sun.invoke.util.Wrapper;
20.40 -import static java.lang.invoke.MethodHandleStatics.*;
20.41 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
20.42 -import java.lang.reflect.Field;
20.43 -import java.util.Objects;
20.44 -
20.45 -/**
20.46 - * The symbolic, non-executable form of a method handle's invocation semantics.
20.47 - * It consists of a series of names.
20.48 - * The first N (N=arity) names are parameters,
20.49 - * while any remaining names are temporary values.
20.50 - * Each temporary specifies the application of a function to some arguments.
20.51 - * The functions are method handles, while the arguments are mixes of
20.52 - * constant values and local names.
20.53 - * The result of the lambda is defined as one of the names, often the last one.
20.54 - * <p>
20.55 - * Here is an approximate grammar:
20.56 - * <blockquote><pre>{@code
20.57 - * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
20.58 - * ArgName = "a" N ":" T
20.59 - * TempName = "t" N ":" T "=" Function "(" Argument* ");"
20.60 - * Function = ConstantValue
20.61 - * Argument = NameRef | ConstantValue
20.62 - * Result = NameRef | "void"
20.63 - * NameRef = "a" N | "t" N
20.64 - * N = (any whole number)
20.65 - * T = "L" | "I" | "J" | "F" | "D" | "V"
20.66 - * }</pre></blockquote>
20.67 - * Names are numbered consecutively from left to right starting at zero.
20.68 - * (The letters are merely a taste of syntax sugar.)
20.69 - * Thus, the first temporary (if any) is always numbered N (where N=arity).
20.70 - * Every occurrence of a name reference in an argument list must refer to
20.71 - * a name previously defined within the same lambda.
20.72 - * A lambda has a void result if and only if its result index is -1.
20.73 - * If a temporary has the type "V", it cannot be the subject of a NameRef,
20.74 - * even though possesses a number.
20.75 - * Note that all reference types are erased to "L", which stands for {@code Object}.
20.76 - * All subword types (boolean, byte, short, char) are erased to "I" which is {@code int}.
20.77 - * The other types stand for the usual primitive types.
20.78 - * <p>
20.79 - * Function invocation closely follows the static rules of the Java verifier.
20.80 - * Arguments and return values must exactly match when their "Name" types are
20.81 - * considered.
20.82 - * Conversions are allowed only if they do not change the erased type.
20.83 - * <ul>
20.84 - * <li>L = Object: casts are used freely to convert into and out of reference types
20.85 - * <li>I = int: subword types are forcibly narrowed when passed as arguments (see {@code explicitCastArguments})
20.86 - * <li>J = long: no implicit conversions
20.87 - * <li>F = float: no implicit conversions
20.88 - * <li>D = double: no implicit conversions
20.89 - * <li>V = void: a function result may be void if and only if its Name is of type "V"
20.90 - * </ul>
20.91 - * Although implicit conversions are not allowed, explicit ones can easily be
20.92 - * encoded by using temporary expressions which call type-transformed identity functions.
20.93 - * <p>
20.94 - * Examples:
20.95 - * <blockquote><pre>{@code
20.96 - * (a0:J)=>{ a0 }
20.97 - * == identity(long)
20.98 - * (a0:I)=>{ t1:V = System.out#println(a0); void }
20.99 - * == System.out#println(int)
20.100 - * (a0:L)=>{ t1:V = System.out#println(a0); a0 }
20.101 - * == identity, with printing side-effect
20.102 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
20.103 - * t3:L = BoundMethodHandle#target(a0);
20.104 - * t4:L = MethodHandle#invoke(t3, t2, a1); t4 }
20.105 - * == general invoker for unary insertArgument combination
20.106 - * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
20.107 - * t3:L = MethodHandle#invoke(t2, a1);
20.108 - * t4:L = FilterMethodHandle#target(a0);
20.109 - * t5:L = MethodHandle#invoke(t4, t3); t5 }
20.110 - * == general invoker for unary filterArgument combination
20.111 - * (a0:L, a1:L)=>{ ...(same as previous example)...
20.112 - * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
20.113 - * == general invoker for unary/unary foldArgument combination
20.114 - * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
20.115 - * == invoker for identity method handle which performs i2l
20.116 - * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
20.117 - * t3:L = Class#cast(t2,a1); t3 }
20.118 - * == invoker for identity method handle which performs cast
20.119 - * }</pre></blockquote>
20.120 - * <p>
20.121 - * @author John Rose, JSR 292 EG
20.122 - */
20.123 -class LambdaForm {
20.124 - final int arity;
20.125 - final int result;
20.126 - @Stable final Name[] names;
20.127 - final String debugName;
20.128 - MemberName vmentry; // low-level behavior, or null if not yet prepared
20.129 - private boolean isCompiled;
20.130 -
20.131 - // Caches for common structural transforms:
20.132 - LambdaForm[] bindCache;
20.133 -
20.134 - public static final int VOID_RESULT = -1, LAST_RESULT = -2;
20.135 -
20.136 - LambdaForm(String debugName,
20.137 - int arity, Name[] names, int result) {
20.138 - assert(namesOK(arity, names));
20.139 - this.arity = arity;
20.140 - this.result = fixResult(result, names);
20.141 - this.names = names.clone();
20.142 - this.debugName = debugName;
20.143 - normalize();
20.144 - }
20.145 -
20.146 - LambdaForm(String debugName,
20.147 - int arity, Name[] names) {
20.148 - this(debugName,
20.149 - arity, names, LAST_RESULT);
20.150 - }
20.151 -
20.152 - LambdaForm(String debugName,
20.153 - Name[] formals, Name[] temps, Name result) {
20.154 - this(debugName,
20.155 - formals.length, buildNames(formals, temps, result), LAST_RESULT);
20.156 - }
20.157 -
20.158 - private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
20.159 - int arity = formals.length;
20.160 - int length = arity + temps.length + (result == null ? 0 : 1);
20.161 - Name[] names = Arrays.copyOf(formals, length);
20.162 - System.arraycopy(temps, 0, names, arity, temps.length);
20.163 - if (result != null)
20.164 - names[length - 1] = result;
20.165 - return names;
20.166 - }
20.167 -
20.168 - private LambdaForm(String sig) {
20.169 - // Make a blank lambda form, which returns a constant zero or null.
20.170 - // It is used as a template for managing the invocation of similar forms that are non-empty.
20.171 - // Called only from getPreparedForm.
20.172 - assert(isValidSignature(sig));
20.173 - this.arity = signatureArity(sig);
20.174 - this.result = (signatureReturn(sig) == 'V' ? -1 : arity);
20.175 - this.names = buildEmptyNames(arity, sig);
20.176 - this.debugName = "LF.zero";
20.177 - assert(nameRefsAreLegal());
20.178 - assert(isEmpty());
20.179 - assert(sig.equals(basicTypeSignature()));
20.180 - }
20.181 -
20.182 - private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
20.183 - assert(isValidSignature(basicTypeSignature));
20.184 - int resultPos = arity + 1; // skip '_'
20.185 - if (arity < 0 || basicTypeSignature.length() != resultPos+1)
20.186 - throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
20.187 - int numRes = (basicTypeSignature.charAt(resultPos) == 'V' ? 0 : 1);
20.188 - Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
20.189 - for (int i = 0; i < numRes; i++) {
20.190 - names[arity + i] = constantZero(arity + i, basicTypeSignature.charAt(resultPos + i));
20.191 - }
20.192 - return names;
20.193 - }
20.194 -
20.195 - private static int fixResult(int result, Name[] names) {
20.196 - if (result >= 0) {
20.197 - if (names[result].type == 'V')
20.198 - return -1;
20.199 - } else if (result == LAST_RESULT) {
20.200 - return names.length - 1;
20.201 - }
20.202 - return result;
20.203 - }
20.204 -
20.205 - private static boolean namesOK(int arity, Name[] names) {
20.206 - for (int i = 0; i < names.length; i++) {
20.207 - Name n = names[i];
20.208 - assert(n != null) : "n is null";
20.209 - if (i < arity)
20.210 - assert( n.isParam()) : n + " is not param at " + i;
20.211 - else
20.212 - assert(!n.isParam()) : n + " is param at " + i;
20.213 - }
20.214 - return true;
20.215 - }
20.216 -
20.217 - /** Renumber and/or replace params so that they are interned and canonically numbered. */
20.218 - private void normalize() {
20.219 - Name[] oldNames = null;
20.220 - int changesStart = 0;
20.221 - for (int i = 0; i < names.length; i++) {
20.222 - Name n = names[i];
20.223 - if (!n.initIndex(i)) {
20.224 - if (oldNames == null) {
20.225 - oldNames = names.clone();
20.226 - changesStart = i;
20.227 - }
20.228 - names[i] = n.cloneWithIndex(i);
20.229 - }
20.230 - }
20.231 - if (oldNames != null) {
20.232 - int startFixing = arity;
20.233 - if (startFixing <= changesStart)
20.234 - startFixing = changesStart+1;
20.235 - for (int i = startFixing; i < names.length; i++) {
20.236 - Name fixed = names[i].replaceNames(oldNames, names, changesStart, i);
20.237 - names[i] = fixed.newIndex(i);
20.238 - }
20.239 - }
20.240 - assert(nameRefsAreLegal());
20.241 - int maxInterned = Math.min(arity, INTERNED_ARGUMENT_LIMIT);
20.242 - boolean needIntern = false;
20.243 - for (int i = 0; i < maxInterned; i++) {
20.244 - Name n = names[i], n2 = internArgument(n);
20.245 - if (n != n2) {
20.246 - names[i] = n2;
20.247 - needIntern = true;
20.248 - }
20.249 - }
20.250 - if (needIntern) {
20.251 - for (int i = arity; i < names.length; i++) {
20.252 - names[i].internArguments();
20.253 - }
20.254 - assert(nameRefsAreLegal());
20.255 - }
20.256 - }
20.257 -
20.258 - /**
20.259 - * Check that all embedded Name references are localizable to this lambda,
20.260 - * and are properly ordered after their corresponding definitions.
20.261 - * <p>
20.262 - * Note that a Name can be local to multiple lambdas, as long as
20.263 - * it possesses the same index in each use site.
20.264 - * This allows Name references to be freely reused to construct
20.265 - * fresh lambdas, without confusion.
20.266 - */
20.267 - private boolean nameRefsAreLegal() {
20.268 - assert(arity >= 0 && arity <= names.length);
20.269 - assert(result >= -1 && result < names.length);
20.270 - // Do all names possess an index consistent with their local definition order?
20.271 - for (int i = 0; i < arity; i++) {
20.272 - Name n = names[i];
20.273 - assert(n.index() == i) : Arrays.asList(n.index(), i);
20.274 - assert(n.isParam());
20.275 - }
20.276 - // Also, do all local name references
20.277 - for (int i = arity; i < names.length; i++) {
20.278 - Name n = names[i];
20.279 - assert(n.index() == i);
20.280 - for (Object arg : n.arguments) {
20.281 - if (arg instanceof Name) {
20.282 - Name n2 = (Name) arg;
20.283 - int i2 = n2.index;
20.284 - assert(0 <= i2 && i2 < names.length) : n.debugString() + ": 0 <= i2 && i2 < names.length: 0 <= " + i2 + " < " + names.length;
20.285 - assert(names[i2] == n2) : Arrays.asList("-1-", i, "-2-", n.debugString(), "-3-", i2, "-4-", n2.debugString(), "-5-", names[i2].debugString(), "-6-", this);
20.286 - assert(i2 < i); // ref must come after def!
20.287 - }
20.288 - }
20.289 - }
20.290 - return true;
20.291 - }
20.292 -
20.293 - /** Invoke this form on the given arguments. */
20.294 - // final Object invoke(Object... args) throws Throwable {
20.295 - // // NYI: fit this into the fast path?
20.296 - // return interpretWithArguments(args);
20.297 - // }
20.298 -
20.299 - /** Report the return type. */
20.300 - char returnType() {
20.301 - if (result < 0) return 'V';
20.302 - Name n = names[result];
20.303 - return n.type;
20.304 - }
20.305 -
20.306 - /** Report the N-th argument type. */
20.307 - char parameterType(int n) {
20.308 - assert(n < arity);
20.309 - return names[n].type;
20.310 - }
20.311 -
20.312 - /** Report the arity. */
20.313 - int arity() {
20.314 - return arity;
20.315 - }
20.316 -
20.317 - /** Return the method type corresponding to my basic type signature. */
20.318 - MethodType methodType() {
20.319 - return signatureType(basicTypeSignature());
20.320 - }
20.321 - /** Return ABC_Z, where the ABC are parameter type characters, and Z is the return type character. */
20.322 - final String basicTypeSignature() {
20.323 - StringBuilder buf = new StringBuilder(arity() + 3);
20.324 - for (int i = 0, a = arity(); i < a; i++)
20.325 - buf.append(parameterType(i));
20.326 - return buf.append('_').append(returnType()).toString();
20.327 - }
20.328 - static int signatureArity(String sig) {
20.329 - assert(isValidSignature(sig));
20.330 - return sig.indexOf('_');
20.331 - }
20.332 - static char signatureReturn(String sig) {
20.333 - return sig.charAt(signatureArity(sig)+1);
20.334 - }
20.335 - static boolean isValidSignature(String sig) {
20.336 - int arity = sig.indexOf('_');
20.337 - if (arity < 0) return false; // must be of the form *_*
20.338 - int siglen = sig.length();
20.339 - if (siglen != arity + 2) return false; // *_X
20.340 - for (int i = 0; i < siglen; i++) {
20.341 - if (i == arity) continue; // skip '_'
20.342 - char c = sig.charAt(i);
20.343 - if (c == 'V')
20.344 - return (i == siglen - 1 && arity == siglen - 2);
20.345 - if (ALL_TYPES.indexOf(c) < 0) return false; // must be [LIJFD]
20.346 - }
20.347 - return true; // [LIJFD]*_[LIJFDV]
20.348 - }
20.349 - static Class<?> typeClass(char t) {
20.350 - switch (t) {
20.351 - case 'I': return int.class;
20.352 - case 'J': return long.class;
20.353 - case 'F': return float.class;
20.354 - case 'D': return double.class;
20.355 - case 'L': return Object.class;
20.356 - case 'V': return void.class;
20.357 - default: assert false;
20.358 - }
20.359 - return null;
20.360 - }
20.361 - static MethodType signatureType(String sig) {
20.362 - Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
20.363 - for (int i = 0; i < ptypes.length; i++)
20.364 - ptypes[i] = typeClass(sig.charAt(i));
20.365 - Class<?> rtype = typeClass(signatureReturn(sig));
20.366 - return MethodType.methodType(rtype, ptypes);
20.367 - }
20.368 -
20.369 - /*
20.370 - * Code generation issues:
20.371 - *
20.372 - * Compiled LFs should be reusable in general.
20.373 - * The biggest issue is how to decide when to pull a name into
20.374 - * the bytecode, versus loading a reified form from the MH data.
20.375 - *
20.376 - * For example, an asType wrapper may require execution of a cast
20.377 - * after a call to a MH. The target type of the cast can be placed
20.378 - * as a constant in the LF itself. This will force the cast type
20.379 - * to be compiled into the bytecodes and native code for the MH.
20.380 - * Or, the target type of the cast can be erased in the LF, and
20.381 - * loaded from the MH data. (Later on, if the MH as a whole is
20.382 - * inlined, the data will flow into the inlined instance of the LF,
20.383 - * as a constant, and the end result will be an optimal cast.)
20.384 - *
20.385 - * This erasure of cast types can be done with any use of
20.386 - * reference types. It can also be done with whole method
20.387 - * handles. Erasing a method handle might leave behind
20.388 - * LF code that executes correctly for any MH of a given
20.389 - * type, and load the required MH from the enclosing MH's data.
20.390 - * Or, the erasure might even erase the expected MT.
20.391 - *
20.392 - * Also, for direct MHs, the MemberName of the target
20.393 - * could be erased, and loaded from the containing direct MH.
20.394 - * As a simple case, a LF for all int-valued non-static
20.395 - * field getters would perform a cast on its input argument
20.396 - * (to non-constant base type derived from the MemberName)
20.397 - * and load an integer value from the input object
20.398 - * (at a non-constant offset also derived from the MemberName).
20.399 - * Such MN-erased LFs would be inlinable back to optimized
20.400 - * code, whenever a constant enclosing DMH is available
20.401 - * to supply a constant MN from its data.
20.402 - *
20.403 - * The main problem here is to keep LFs reasonably generic,
20.404 - * while ensuring that hot spots will inline good instances.
20.405 - * "Reasonably generic" means that we don't end up with
20.406 - * repeated versions of bytecode or machine code that do
20.407 - * not differ in their optimized form. Repeated versions
20.408 - * of machine would have the undesirable overheads of
20.409 - * (a) redundant compilation work and (b) extra I$ pressure.
20.410 - * To control repeated versions, we need to be ready to
20.411 - * erase details from LFs and move them into MH data,
20.412 - * whevener those details are not relevant to significant
20.413 - * optimization. "Significant" means optimization of
20.414 - * code that is actually hot.
20.415 - *
20.416 - * Achieving this may require dynamic splitting of MHs, by replacing
20.417 - * a generic LF with a more specialized one, on the same MH,
20.418 - * if (a) the MH is frequently executed and (b) the MH cannot
20.419 - * be inlined into a containing caller, such as an invokedynamic.
20.420 - *
20.421 - * Compiled LFs that are no longer used should be GC-able.
20.422 - * If they contain non-BCP references, they should be properly
20.423 - * interlinked with the class loader(s) that their embedded types
20.424 - * depend on. This probably means that reusable compiled LFs
20.425 - * will be tabulated (indexed) on relevant class loaders,
20.426 - * or else that the tables that cache them will have weak links.
20.427 - */
20.428 -
20.429 - /**
20.430 - * Make this LF directly executable, as part of a MethodHandle.
20.431 - * Invariant: Every MH which is invoked must prepare its LF
20.432 - * before invocation.
20.433 - * (In principle, the JVM could do this very lazily,
20.434 - * as a sort of pre-invocation linkage step.)
20.435 - */
20.436 - public void prepare() {
20.437 - if (COMPILE_THRESHOLD == 0) {
20.438 - compileToBytecode();
20.439 - }
20.440 - if (this.vmentry != null) {
20.441 - // already prepared (e.g., a primitive DMH invoker form)
20.442 - return;
20.443 - }
20.444 - LambdaForm prep = getPreparedForm(basicTypeSignature());
20.445 - this.vmentry = prep.vmentry;
20.446 - // TO DO: Maybe add invokeGeneric, invokeWithArguments
20.447 - }
20.448 -
20.449 - /** Generate optimizable bytecode for this form. */
20.450 - MemberName compileToBytecode() {
20.451 - MethodType invokerType = methodType();
20.452 - assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
20.453 - if (vmentry != null && isCompiled) {
20.454 - return vmentry; // already compiled somehow
20.455 - }
20.456 - throw newInternalError("compileToBytecode", new Exception());
20.457 -// try {
20.458 -// vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
20.459 -// if (TRACE_INTERPRETER)
20.460 -// traceInterpreter("compileToBytecode", this);
20.461 -// isCompiled = true;
20.462 -// return vmentry;
20.463 -// } catch (Error | Exception ex) {
20.464 -// throw newInternalError("compileToBytecode", ex);
20.465 -// }
20.466 - }
20.467 -
20.468 - private static final ConcurrentHashMap<String,LambdaForm> PREPARED_FORMS;
20.469 - static {
20.470 - int capacity = 512; // expect many distinct signatures over time
20.471 - float loadFactor = 0.75f; // normal default
20.472 - int writers = 1;
20.473 - PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers);
20.474 - }
20.475 -
20.476 - private static Map<String,LambdaForm> computeInitialPreparedForms() {
20.477 - // Find all predefined invokers and associate them with canonical empty lambda forms.
20.478 - HashMap<String,LambdaForm> forms = new HashMap<>();
20.479 - for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
20.480 - if (!m.isStatic() || !m.isPackage()) continue;
20.481 - MethodType mt = m.getMethodType();
20.482 - if (mt.parameterCount() > 0 &&
20.483 - mt.parameterType(0) == MethodHandle.class &&
20.484 - m.getName().startsWith("interpret_")) {
20.485 - String sig = basicTypeSignature(mt);
20.486 - assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
20.487 - LambdaForm form = new LambdaForm(sig);
20.488 - form.vmentry = m;
20.489 - mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form);
20.490 - // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only
20.491 - forms.put(sig, form);
20.492 - }
20.493 - }
20.494 - //System.out.println("computeInitialPreparedForms => "+forms);
20.495 - return forms;
20.496 - }
20.497 -
20.498 - // Set this false to disable use of the interpret_L methods defined in this file.
20.499 - private static final boolean USE_PREDEFINED_INTERPRET_METHODS = true;
20.500 -
20.501 - // The following are predefined exact invokers. The system must build
20.502 - // a separate invoker for each distinct signature.
20.503 - static Object interpret_L(MethodHandle mh) throws Throwable {
20.504 - Object[] av = {mh};
20.505 - String sig = null;
20.506 - assert(argumentTypesMatch(sig = "L_L", av));
20.507 - Object res = mh.form.interpretWithArguments(av);
20.508 - assert(returnTypesMatch(sig, av, res));
20.509 - return res;
20.510 - }
20.511 - static Object interpret_L(MethodHandle mh, Object x1) throws Throwable {
20.512 - Object[] av = {mh, x1};
20.513 - String sig = null;
20.514 - assert(argumentTypesMatch(sig = "LL_L", av));
20.515 - Object res = mh.form.interpretWithArguments(av);
20.516 - assert(returnTypesMatch(sig, av, res));
20.517 - return res;
20.518 - }
20.519 - static Object interpret_L(MethodHandle mh, Object x1, Object x2) throws Throwable {
20.520 - Object[] av = {mh, x1, x2};
20.521 - String sig = null;
20.522 - assert(argumentTypesMatch(sig = "LLL_L", av));
20.523 - Object res = mh.form.interpretWithArguments(av);
20.524 - assert(returnTypesMatch(sig, av, res));
20.525 - return res;
20.526 - }
20.527 - private static LambdaForm getPreparedForm(String sig) {
20.528 - MethodType mtype = signatureType(sig);
20.529 - //LambdaForm prep = PREPARED_FORMS.get(sig);
20.530 - LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
20.531 - if (prep != null) return prep;
20.532 - assert(isValidSignature(sig));
20.533 - prep = new LambdaForm(sig);
20.534 -// prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig);
20.535 - if (true) throw new IllegalStateException();
20.536 -
20.537 - //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep);
20.538 - return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
20.539 - }
20.540 -
20.541 - // The next few routines are called only from assert expressions
20.542 - // They verify that the built-in invokers process the correct raw data types.
20.543 - private static boolean argumentTypesMatch(String sig, Object[] av) {
20.544 - int arity = signatureArity(sig);
20.545 - assert(av.length == arity) : "av.length == arity: av.length=" + av.length + ", arity=" + arity;
20.546 - assert(av[0] instanceof MethodHandle) : "av[0] not instace of MethodHandle: " + av[0];
20.547 - MethodHandle mh = (MethodHandle) av[0];
20.548 - MethodType mt = mh.type();
20.549 - assert(mt.parameterCount() == arity-1);
20.550 - for (int i = 0; i < av.length; i++) {
20.551 - Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1));
20.552 - assert(valueMatches(sig.charAt(i), pt, av[i]));
20.553 - }
20.554 - return true;
20.555 - }
20.556 - private static boolean valueMatches(char tc, Class<?> type, Object x) {
20.557 - // The following line is needed because (...)void method handles can use non-void invokers
20.558 - if (type == void.class) tc = 'V'; // can drop any kind of value
20.559 - assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type);
20.560 - switch (tc) {
20.561 - case 'I': assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break;
20.562 - case 'J': assert x instanceof Long : "instanceof Long: " + x; break;
20.563 - case 'F': assert x instanceof Float : "instanceof Float: " + x; break;
20.564 - case 'D': assert x instanceof Double : "instanceof Double: " + x; break;
20.565 - case 'L': assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break;
20.566 - case 'V': break; // allow anything here; will be dropped
20.567 - default: assert(false);
20.568 - }
20.569 - return true;
20.570 - }
20.571 - private static boolean returnTypesMatch(String sig, Object[] av, Object res) {
20.572 - MethodHandle mh = (MethodHandle) av[0];
20.573 - return valueMatches(signatureReturn(sig), mh.type().returnType(), res);
20.574 - }
20.575 - private static boolean checkInt(Class<?> type, Object x) {
20.576 - assert(x instanceof Integer);
20.577 - if (type == int.class) return true;
20.578 - Wrapper w = Wrapper.forBasicType(type);
20.579 - assert(w.isSubwordOrInt());
20.580 - Object x1 = Wrapper.INT.wrap(w.wrap(x));
20.581 - return x.equals(x1);
20.582 - }
20.583 - private static boolean checkRef(Class<?> type, Object x) {
20.584 - assert(!type.isPrimitive());
20.585 - if (x == null) return true;
20.586 - if (type.isInterface()) return true;
20.587 - return type.isInstance(x);
20.588 - }
20.589 -
20.590 - /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */
20.591 - private static final int COMPILE_THRESHOLD;
20.592 - static {
20.593 - if (MethodHandleStatics.COMPILE_THRESHOLD != null)
20.594 - COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD;
20.595 - else
20.596 - COMPILE_THRESHOLD = 30; // default value
20.597 - }
20.598 - private int invocationCounter = 0;
20.599 -
20.600 - @Hidden
20.601 - @DontInline
20.602 - /** Interpretively invoke this form on the given arguments. */
20.603 - Object interpretWithArguments(Object... argumentValues) throws Throwable {
20.604 - if (TRACE_INTERPRETER)
20.605 - return interpretWithArgumentsTracing(argumentValues);
20.606 - checkInvocationCounter();
20.607 - assert(arityCheck(argumentValues));
20.608 - Object[] values = Arrays.copyOf(argumentValues, names.length);
20.609 - for (int i = argumentValues.length; i < values.length; i++) {
20.610 - values[i] = interpretName(names[i], values);
20.611 - }
20.612 - return (result < 0) ? null : values[result];
20.613 - }
20.614 -
20.615 - @Hidden
20.616 - @DontInline
20.617 - /** Evaluate a single Name within this form, applying its function to its arguments. */
20.618 - Object interpretName(Name name, Object[] values) throws Throwable {
20.619 - if (TRACE_INTERPRETER)
20.620 - traceInterpreter("| interpretName", name.debugString(), (Object[]) null);
20.621 - Object[] arguments = Arrays.copyOf(name.arguments, name.arguments.length, Object[].class);
20.622 - for (int i = 0; i < arguments.length; i++) {
20.623 - Object a = arguments[i];
20.624 - if (a instanceof Name) {
20.625 - int i2 = ((Name)a).index();
20.626 - assert(names[i2] == a);
20.627 - a = values[i2];
20.628 - arguments[i] = a;
20.629 - }
20.630 - }
20.631 - return name.function.invokeWithArguments(arguments);
20.632 - }
20.633 -
20.634 - private void checkInvocationCounter() {
20.635 - if (COMPILE_THRESHOLD != 0 &&
20.636 - invocationCounter < COMPILE_THRESHOLD) {
20.637 - invocationCounter++; // benign race
20.638 - if (invocationCounter >= COMPILE_THRESHOLD) {
20.639 - // Replace vmentry with a bytecode version of this LF.
20.640 - compileToBytecode();
20.641 - }
20.642 - }
20.643 - }
20.644 - Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
20.645 - traceInterpreter("[ interpretWithArguments", this, argumentValues);
20.646 - if (invocationCounter < COMPILE_THRESHOLD) {
20.647 - int ctr = invocationCounter++; // benign race
20.648 - traceInterpreter("| invocationCounter", ctr);
20.649 - if (invocationCounter >= COMPILE_THRESHOLD) {
20.650 - compileToBytecode();
20.651 - }
20.652 - }
20.653 - Object rval;
20.654 - try {
20.655 - assert(arityCheck(argumentValues));
20.656 - Object[] values = Arrays.copyOf(argumentValues, names.length);
20.657 - for (int i = argumentValues.length; i < values.length; i++) {
20.658 - values[i] = interpretName(names[i], values);
20.659 - }
20.660 - rval = (result < 0) ? null : values[result];
20.661 - } catch (Throwable ex) {
20.662 - traceInterpreter("] throw =>", ex);
20.663 - throw ex;
20.664 - }
20.665 - traceInterpreter("] return =>", rval);
20.666 - return rval;
20.667 - }
20.668 -
20.669 - //** This transform is applied (statically) to every name.function. */
20.670 - /*
20.671 - private static MethodHandle eraseSubwordTypes(MethodHandle mh) {
20.672 - MethodType mt = mh.type();
20.673 - if (mt.hasPrimitives()) {
20.674 - mt = mt.changeReturnType(eraseSubwordType(mt.returnType()));
20.675 - for (int i = 0; i < mt.parameterCount(); i++) {
20.676 - mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i)));
20.677 - }
20.678 - mh = MethodHandles.explicitCastArguments(mh, mt);
20.679 - }
20.680 - return mh;
20.681 - }
20.682 - private static Class<?> eraseSubwordType(Class<?> type) {
20.683 - if (!type.isPrimitive()) return type;
20.684 - if (type == int.class) return type;
20.685 - Wrapper w = Wrapper.forPrimitiveType(type);
20.686 - if (w.isSubwordOrInt()) return int.class;
20.687 - return type;
20.688 - }
20.689 - */
20.690 -
20.691 - static void traceInterpreter(String event, Object obj, Object... args) {
20.692 - if (TRACE_INTERPRETER) {
20.693 - System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
20.694 - }
20.695 - }
20.696 - static void traceInterpreter(String event, Object obj) {
20.697 - traceInterpreter(event, obj, (Object[])null);
20.698 - }
20.699 - private boolean arityCheck(Object[] argumentValues) {
20.700 - assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
20.701 - // also check that the leading (receiver) argument is somehow bound to this LF:
20.702 - assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
20.703 - assert(((MethodHandle)argumentValues[0]).internalForm() == this);
20.704 - // note: argument #0 could also be an interface wrapper, in the future
20.705 - return true;
20.706 - }
20.707 -
20.708 - private boolean isEmpty() {
20.709 - if (result < 0)
20.710 - return (names.length == arity);
20.711 - else if (result == arity && names.length == arity + 1)
20.712 - return names[arity].isConstantZero();
20.713 - else
20.714 - return false;
20.715 - }
20.716 -
20.717 - public String toString() {
20.718 - StringBuilder buf = new StringBuilder(debugName+"=Lambda(");
20.719 - for (int i = 0; i < names.length; i++) {
20.720 - if (i == arity) buf.append(")=>{");
20.721 - Name n = names[i];
20.722 - if (i >= arity) buf.append("\n ");
20.723 - buf.append(n);
20.724 - if (i < arity) {
20.725 - if (i+1 < arity) buf.append(",");
20.726 - continue;
20.727 - }
20.728 - buf.append("=").append(n.exprString());
20.729 - buf.append(";");
20.730 - }
20.731 - buf.append(result < 0 ? "void" : names[result]).append("}");
20.732 - if (TRACE_INTERPRETER) {
20.733 - // Extra verbosity:
20.734 - buf.append(":").append(basicTypeSignature());
20.735 - buf.append("/").append(vmentry);
20.736 - }
20.737 - return buf.toString();
20.738 - }
20.739 -
20.740 - /**
20.741 - * Apply immediate binding for a Name in this form indicated by its position relative to the form.
20.742 - * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not
20.743 - * accepted as valid.
20.744 - */
20.745 - LambdaForm bindImmediate(int pos, char basicType, Object value) {
20.746 - // must be an argument, and the types must match
20.747 - assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value);
20.748 -
20.749 - int arity2 = arity - 1;
20.750 - Name[] names2 = new Name[names.length - 1];
20.751 - for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2
20.752 - Name n = names[r];
20.753 - if (n.isParam()) {
20.754 - if (n.index == pos) {
20.755 - // do not copy over the argument that is to be replaced with a literal,
20.756 - // but adjust the write index
20.757 - --w;
20.758 - } else {
20.759 - names2[w] = new Name(w, n.type);
20.760 - }
20.761 - } else {
20.762 - Object[] arguments2 = new Object[n.arguments.length];
20.763 - for (int i = 0; i < n.arguments.length; ++i) {
20.764 - Object arg = n.arguments[i];
20.765 - if (arg instanceof Name) {
20.766 - int ni = ((Name) arg).index;
20.767 - if (ni == pos) {
20.768 - arguments2[i] = value;
20.769 - } else if (ni < pos) {
20.770 - // replacement position not yet passed
20.771 - arguments2[i] = names2[ni];
20.772 - } else {
20.773 - // replacement position passed
20.774 - arguments2[i] = names2[ni - 1];
20.775 - }
20.776 - } else {
20.777 - arguments2[i] = arg;
20.778 - }
20.779 - }
20.780 - names2[w] = new Name(n.function, arguments2);
20.781 - names2[w].initIndex(w);
20.782 - }
20.783 - }
20.784 -
20.785 - int result2 = result == -1 ? -1 : result - 1;
20.786 - return new LambdaForm(debugName, arity2, names2, result2);
20.787 - }
20.788 -
20.789 - LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) {
20.790 - Name name = names[namePos];
20.791 - BoundMethodHandle.SpeciesData newData = oldData.extendWithType(name.type);
20.792 - return bind(name, newData.getterName(names[0], oldData.fieldCount()), oldData, newData);
20.793 - }
20.794 - LambdaForm bind(Name name, Name binding,
20.795 - BoundMethodHandle.SpeciesData oldData,
20.796 - BoundMethodHandle.SpeciesData newData) {
20.797 - int pos = name.index;
20.798 - assert(name.isParam());
20.799 - assert(!binding.isParam());
20.800 - assert(name.type == binding.type);
20.801 - assert(0 <= pos && pos < arity && names[pos] == name);
20.802 - assert(binding.function.memberDeclaringClassOrNull() == newData.clazz);
20.803 - assert(oldData.getters.length == newData.getters.length-1);
20.804 - if (bindCache != null) {
20.805 - LambdaForm form = bindCache[pos];
20.806 - if (form != null) {
20.807 - assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>";
20.808 - return form;
20.809 - }
20.810 - } else {
20.811 - bindCache = new LambdaForm[arity];
20.812 - }
20.813 - assert(nameRefsAreLegal());
20.814 - int arity2 = arity-1;
20.815 - Name[] names2 = names.clone();
20.816 - names2[pos] = binding; // we might move this in a moment
20.817 -
20.818 - // The newly created LF will run with a different BMH.
20.819 - // Switch over any pre-existing BMH field references to the new BMH class.
20.820 - int firstOldRef = -1;
20.821 - for (int i = 0; i < names2.length; i++) {
20.822 - Name n = names[i];
20.823 - if (n.function != null &&
20.824 - n.function.memberDeclaringClassOrNull() == oldData.clazz) {
20.825 - MethodHandle oldGetter = n.function.resolvedHandle;
20.826 - MethodHandle newGetter = null;
20.827 - for (int j = 0; j < oldData.getters.length; j++) {
20.828 - if (oldGetter == oldData.getters[j])
20.829 - newGetter = newData.getters[j];
20.830 - }
20.831 - if (newGetter != null) {
20.832 - if (firstOldRef < 0) firstOldRef = i;
20.833 - Name n2 = new Name(newGetter, n.arguments);
20.834 - names2[i] = n2;
20.835 - }
20.836 - }
20.837 - }
20.838 -
20.839 - // Walk over the new list of names once, in forward order.
20.840 - // Replace references to 'name' with 'binding'.
20.841 - // Replace data structure references to the old BMH species with the new.
20.842 - // This might cause a ripple effect, but it will settle in one pass.
20.843 - assert(firstOldRef < 0 || firstOldRef > pos);
20.844 - for (int i = pos+1; i < names2.length; i++) {
20.845 - if (i <= arity2) continue;
20.846 - names2[i] = names2[i].replaceNames(names, names2, pos, i);
20.847 - }
20.848 -
20.849 - // (a0, a1, name=a2, a3, a4) => (a0, a1, a3, a4, binding)
20.850 - int insPos = pos;
20.851 - for (; insPos+1 < names2.length; insPos++) {
20.852 - Name n = names2[insPos+1];
20.853 - if (n.isSiblingBindingBefore(binding)) {
20.854 - names2[insPos] = n;
20.855 - } else {
20.856 - break;
20.857 - }
20.858 - }
20.859 - names2[insPos] = binding;
20.860 -
20.861 - // Since we moved some stuff, maybe update the result reference:
20.862 - int result2 = result;
20.863 - if (result2 == pos)
20.864 - result2 = insPos;
20.865 - else if (result2 > pos && result2 <= insPos)
20.866 - result2 -= 1;
20.867 -
20.868 - return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2);
20.869 - }
20.870 -
20.871 - boolean contains(Name name) {
20.872 - int pos = name.index();
20.873 - if (pos >= 0) {
20.874 - return pos < names.length && name.equals(names[pos]);
20.875 - }
20.876 - for (int i = arity; i < names.length; i++) {
20.877 - if (name.equals(names[i]))
20.878 - return true;
20.879 - }
20.880 - return false;
20.881 - }
20.882 -
20.883 - LambdaForm addArguments(int pos, char... types) {
20.884 - assert(pos <= arity);
20.885 - int length = names.length;
20.886 - int inTypes = types.length;
20.887 - Name[] names2 = Arrays.copyOf(names, length + inTypes);
20.888 - int arity2 = arity + inTypes;
20.889 - int result2 = result;
20.890 - if (result2 >= arity)
20.891 - result2 += inTypes;
20.892 - // names array has MH in slot 0; skip it.
20.893 - int argpos = pos + 1;
20.894 - // Note: The LF constructor will rename names2[argpos...].
20.895 - // Make space for new arguments (shift temporaries).
20.896 - System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos);
20.897 - for (int i = 0; i < inTypes; i++) {
20.898 - names2[argpos + i] = new Name(types[i]);
20.899 - }
20.900 - return new LambdaForm(debugName, arity2, names2, result2);
20.901 - }
20.902 -
20.903 - LambdaForm addArguments(int pos, List<Class<?>> types) {
20.904 - char[] basicTypes = new char[types.size()];
20.905 - for (int i = 0; i < basicTypes.length; i++)
20.906 - basicTypes[i] = basicType(types.get(i));
20.907 - return addArguments(pos, basicTypes);
20.908 - }
20.909 -
20.910 - LambdaForm permuteArguments(int skip, int[] reorder, char[] types) {
20.911 - // Note: When inArg = reorder[outArg], outArg is fed by a copy of inArg.
20.912 - // The types are the types of the new (incoming) arguments.
20.913 - int length = names.length;
20.914 - int inTypes = types.length;
20.915 - int outArgs = reorder.length;
20.916 - assert(skip+outArgs == arity);
20.917 - assert(permutedTypesMatch(reorder, types, names, skip));
20.918 - int pos = 0;
20.919 - // skip trivial first part of reordering:
20.920 - while (pos < outArgs && reorder[pos] == pos) pos += 1;
20.921 - Name[] names2 = new Name[length - outArgs + inTypes];
20.922 - System.arraycopy(names, 0, names2, 0, skip+pos);
20.923 - // copy the body:
20.924 - int bodyLength = length - arity;
20.925 - System.arraycopy(names, skip+outArgs, names2, skip+inTypes, bodyLength);
20.926 - int arity2 = names2.length - bodyLength;
20.927 - int result2 = result;
20.928 - if (result2 >= 0) {
20.929 - if (result2 < skip+outArgs) {
20.930 - // return the corresponding inArg
20.931 - result2 = reorder[result2-skip];
20.932 - } else {
20.933 - result2 = result2 - outArgs + inTypes;
20.934 - }
20.935 - }
20.936 - // rework names in the body:
20.937 - for (int j = pos; j < outArgs; j++) {
20.938 - Name n = names[skip+j];
20.939 - int i = reorder[j];
20.940 - // replace names[skip+j] by names2[skip+i]
20.941 - Name n2 = names2[skip+i];
20.942 - if (n2 == null)
20.943 - names2[skip+i] = n2 = new Name(types[i]);
20.944 - else
20.945 - assert(n2.type == types[i]);
20.946 - for (int k = arity2; k < names2.length; k++) {
20.947 - names2[k] = names2[k].replaceName(n, n2);
20.948 - }
20.949 - }
20.950 - // some names are unused, but must be filled in
20.951 - for (int i = skip+pos; i < arity2; i++) {
20.952 - if (names2[i] == null)
20.953 - names2[i] = argument(i, types[i - skip]);
20.954 - }
20.955 - for (int j = arity; j < names.length; j++) {
20.956 - int i = j - arity + arity2;
20.957 - // replace names2[i] by names[j]
20.958 - Name n = names[j];
20.959 - Name n2 = names2[i];
20.960 - if (n != n2) {
20.961 - for (int k = i+1; k < names2.length; k++) {
20.962 - names2[k] = names2[k].replaceName(n, n2);
20.963 - }
20.964 - }
20.965 - }
20.966 - return new LambdaForm(debugName, arity2, names2, result2);
20.967 - }
20.968 -
20.969 - static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
20.970 - int inTypes = types.length;
20.971 - int outArgs = reorder.length;
20.972 - for (int i = 0; i < outArgs; i++) {
20.973 - assert(names[skip+i].isParam());
20.974 - assert(names[skip+i].type == types[reorder[i]]);
20.975 - }
20.976 - return true;
20.977 - }
20.978 -
20.979 - static class NamedFunction {
20.980 - final MemberName member;
20.981 - @Stable MethodHandle resolvedHandle;
20.982 - @Stable MethodHandle invoker;
20.983 -
20.984 - NamedFunction(MethodHandle resolvedHandle) {
20.985 - this(resolvedHandle.internalMemberName(), resolvedHandle);
20.986 - }
20.987 - NamedFunction(MemberName member, MethodHandle resolvedHandle) {
20.988 - this.member = member;
20.989 - //resolvedHandle = eraseSubwordTypes(resolvedHandle);
20.990 - this.resolvedHandle = resolvedHandle;
20.991 - }
20.992 - NamedFunction(MethodType basicInvokerType) {
20.993 - assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
20.994 - if (basicInvokerType.parameterSlotCount() < MethodType.MAX_MH_INVOKER_ARITY) {
20.995 - this.resolvedHandle = basicInvokerType.invokers().basicInvoker();
20.996 - this.member = resolvedHandle.internalMemberName();
20.997 - } else {
20.998 - // necessary to pass BigArityTest
20.999 - this.member = Invokers.invokeBasicMethod(basicInvokerType);
20.1000 - }
20.1001 - }
20.1002 -
20.1003 - // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
20.1004 - // Any LambdaForm containing such a member is not interpretable.
20.1005 - // This is OK, since all such LFs are prepared with special primitive vmentry points.
20.1006 - // And even without the resolvedHandle, the name can still be compiled and optimized.
20.1007 - NamedFunction(Method method) {
20.1008 - this(new MemberName(method));
20.1009 - }
20.1010 - NamedFunction(Field field) {
20.1011 - this(new MemberName(field));
20.1012 - }
20.1013 - NamedFunction(MemberName member) {
20.1014 - this.member = member;
20.1015 - this.resolvedHandle = null;
20.1016 - }
20.1017 -
20.1018 - MethodHandle resolvedHandle() {
20.1019 - if (resolvedHandle == null) resolve();
20.1020 - return resolvedHandle;
20.1021 - }
20.1022 -
20.1023 - void resolve() {
20.1024 - resolvedHandle = DirectMethodHandle.make(member);
20.1025 - }
20.1026 -
20.1027 - @Override
20.1028 - public boolean equals(Object other) {
20.1029 - if (this == other) return true;
20.1030 - if (other == null) return false;
20.1031 - if (!(other instanceof NamedFunction)) return false;
20.1032 - NamedFunction that = (NamedFunction) other;
20.1033 - return this.member != null && this.member.equals(that.member);
20.1034 - }
20.1035 -
20.1036 - @Override
20.1037 - public int hashCode() {
20.1038 - if (member != null)
20.1039 - return member.hashCode();
20.1040 - return super.hashCode();
20.1041 - }
20.1042 -
20.1043 - // Put the predefined NamedFunction invokers into the table.
20.1044 - static void initializeInvokers() {
20.1045 - for (MemberName m : MemberName.getFactory().getMethods(NamedFunction.class, false, null, null, null)) {
20.1046 - if (!m.isStatic() || !m.isPackage()) continue;
20.1047 - MethodType type = m.getMethodType();
20.1048 - if (type.equals(INVOKER_METHOD_TYPE) &&
20.1049 - m.getName().startsWith("invoke_")) {
20.1050 - String sig = m.getName().substring("invoke_".length());
20.1051 - int arity = LambdaForm.signatureArity(sig);
20.1052 - MethodType srcType = MethodType.genericMethodType(arity);
20.1053 - if (LambdaForm.signatureReturn(sig) == 'V')
20.1054 - srcType = srcType.changeReturnType(void.class);
20.1055 - MethodTypeForm typeForm = srcType.form();
20.1056 - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m);
20.1057 - }
20.1058 - }
20.1059 - }
20.1060 -
20.1061 - // The following are predefined NamedFunction invokers. The system must build
20.1062 - // a separate invoker for each distinct signature.
20.1063 - /** void return type invokers. */
20.1064 - @Hidden
20.1065 - static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable {
20.1066 - assert(a.length == 0);
20.1067 - mh.invokeBasic();
20.1068 - return null;
20.1069 - }
20.1070 - @Hidden
20.1071 - static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable {
20.1072 - assert(a.length == 1);
20.1073 - mh.invokeBasic(a[0]);
20.1074 - return null;
20.1075 - }
20.1076 - @Hidden
20.1077 - static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable {
20.1078 - assert(a.length == 2);
20.1079 - mh.invokeBasic(a[0], a[1]);
20.1080 - return null;
20.1081 - }
20.1082 - @Hidden
20.1083 - static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable {
20.1084 - assert(a.length == 3);
20.1085 - mh.invokeBasic(a[0], a[1], a[2]);
20.1086 - return null;
20.1087 - }
20.1088 - @Hidden
20.1089 - static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable {
20.1090 - assert(a.length == 4);
20.1091 - mh.invokeBasic(a[0], a[1], a[2], a[3]);
20.1092 - return null;
20.1093 - }
20.1094 - @Hidden
20.1095 - static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable {
20.1096 - assert(a.length == 5);
20.1097 - mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
20.1098 - return null;
20.1099 - }
20.1100 - /** Object return type invokers. */
20.1101 - @Hidden
20.1102 - static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable {
20.1103 - assert(a.length == 0);
20.1104 - return mh.invokeBasic();
20.1105 - }
20.1106 - @Hidden
20.1107 - static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable {
20.1108 - assert(a.length == 1);
20.1109 - return mh.invokeBasic(a[0]);
20.1110 - }
20.1111 - @Hidden
20.1112 - static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable {
20.1113 - assert(a.length == 2);
20.1114 - return mh.invokeBasic(a[0], a[1]);
20.1115 - }
20.1116 - @Hidden
20.1117 - static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable {
20.1118 - assert(a.length == 3);
20.1119 - return mh.invokeBasic(a[0], a[1], a[2]);
20.1120 - }
20.1121 - @Hidden
20.1122 - static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable {
20.1123 - assert(a.length == 4);
20.1124 - return mh.invokeBasic(a[0], a[1], a[2], a[3]);
20.1125 - }
20.1126 - @Hidden
20.1127 - static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable {
20.1128 - assert(a.length == 5);
20.1129 - return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]);
20.1130 - }
20.1131 -
20.1132 - static final MethodType INVOKER_METHOD_TYPE =
20.1133 - MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
20.1134 -
20.1135 - private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
20.1136 - MethodHandle mh = typeForm.namedFunctionInvoker;
20.1137 - if (mh != null) return mh;
20.1138 -// MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while
20.1139 - if (true) throw new IllegalStateException();
20.1140 -// mh = DirectMethodHandle.make(invoker);
20.1141 - MethodHandle mh2 = typeForm.namedFunctionInvoker;
20.1142 - if (mh2 != null) return mh2; // benign race
20.1143 - if (!mh.type().equals(INVOKER_METHOD_TYPE))
20.1144 - throw new InternalError(mh.debugString());
20.1145 - return typeForm.namedFunctionInvoker = mh;
20.1146 - }
20.1147 -
20.1148 - @Hidden
20.1149 - Object invokeWithArguments(Object... arguments) throws Throwable {
20.1150 - // If we have a cached invoker, call it right away.
20.1151 - // NOTE: The invoker always returns a reference value.
20.1152 - if (TRACE_INTERPRETER) return invokeWithArgumentsTracing(arguments);
20.1153 - assert(checkArgumentTypes(arguments, methodType()));
20.1154 - return invoker().invokeBasic(resolvedHandle(), arguments);
20.1155 - }
20.1156 -
20.1157 - @Hidden
20.1158 - Object invokeWithArgumentsTracing(Object[] arguments) throws Throwable {
20.1159 - Object rval;
20.1160 - try {
20.1161 - traceInterpreter("[ call", this, arguments);
20.1162 - if (invoker == null) {
20.1163 - traceInterpreter("| getInvoker", this);
20.1164 - invoker();
20.1165 - }
20.1166 - if (resolvedHandle == null) {
20.1167 - traceInterpreter("| resolve", this);
20.1168 - resolvedHandle();
20.1169 - }
20.1170 - assert(checkArgumentTypes(arguments, methodType()));
20.1171 - rval = invoker().invokeBasic(resolvedHandle(), arguments);
20.1172 - } catch (Throwable ex) {
20.1173 - traceInterpreter("] throw =>", ex);
20.1174 - throw ex;
20.1175 - }
20.1176 - traceInterpreter("] return =>", rval);
20.1177 - return rval;
20.1178 - }
20.1179 -
20.1180 - private MethodHandle invoker() {
20.1181 - if (invoker != null) return invoker;
20.1182 - // Get an invoker and cache it.
20.1183 - return invoker = computeInvoker(methodType().form());
20.1184 - }
20.1185 -
20.1186 - private static boolean checkArgumentTypes(Object[] arguments, MethodType methodType) {
20.1187 - if (true) return true; // FIXME
20.1188 - MethodType dstType = methodType.form().erasedType();
20.1189 - MethodType srcType = dstType.basicType().wrap();
20.1190 - Class<?>[] ptypes = new Class<?>[arguments.length];
20.1191 - for (int i = 0; i < arguments.length; i++) {
20.1192 - Object arg = arguments[i];
20.1193 - Class<?> ptype = arg == null ? Object.class : arg.getClass();
20.1194 - // If the dest. type is a primitive we keep the
20.1195 - // argument type.
20.1196 - ptypes[i] = dstType.parameterType(i).isPrimitive() ? ptype : Object.class;
20.1197 - }
20.1198 - MethodType argType = MethodType.methodType(srcType.returnType(), ptypes).wrap();
20.1199 - assert(argType.isConvertibleTo(srcType)) : "wrong argument types: cannot convert " + argType + " to " + srcType;
20.1200 - return true;
20.1201 - }
20.1202 -
20.1203 - String basicTypeSignature() {
20.1204 - //return LambdaForm.basicTypeSignature(resolvedHandle.type());
20.1205 - return LambdaForm.basicTypeSignature(methodType());
20.1206 - }
20.1207 -
20.1208 - MethodType methodType() {
20.1209 - if (resolvedHandle != null)
20.1210 - return resolvedHandle.type();
20.1211 - else
20.1212 - // only for certain internal LFs during bootstrapping
20.1213 - return member.getInvocationType();
20.1214 - }
20.1215 -
20.1216 - MemberName member() {
20.1217 - assert(assertMemberIsConsistent());
20.1218 - return member;
20.1219 - }
20.1220 -
20.1221 - // Called only from assert.
20.1222 - private boolean assertMemberIsConsistent() {
20.1223 - if (resolvedHandle instanceof DirectMethodHandle) {
20.1224 - MemberName m = resolvedHandle.internalMemberName();
20.1225 - assert(m.equals(member));
20.1226 - }
20.1227 - return true;
20.1228 - }
20.1229 -
20.1230 - Class<?> memberDeclaringClassOrNull() {
20.1231 - return (member == null) ? null : member.getDeclaringClass();
20.1232 - }
20.1233 -
20.1234 - char returnType() {
20.1235 - return basicType(methodType().returnType());
20.1236 - }
20.1237 -
20.1238 - char parameterType(int n) {
20.1239 - return basicType(methodType().parameterType(n));
20.1240 - }
20.1241 -
20.1242 - int arity() {
20.1243 - //int siglen = member.getMethodType().parameterCount();
20.1244 - //if (!member.isStatic()) siglen += 1;
20.1245 - //return siglen;
20.1246 - return methodType().parameterCount();
20.1247 - }
20.1248 -
20.1249 - public String toString() {
20.1250 - if (member == null) return String.valueOf(resolvedHandle);
20.1251 - return member.getDeclaringClass().getSimpleName()+"."+member.getName();
20.1252 - }
20.1253 - }
20.1254 -
20.1255 - void resolve() {
20.1256 - for (Name n : names) n.resolve();
20.1257 - }
20.1258 -
20.1259 - public static char basicType(Class<?> type) {
20.1260 - char c = Wrapper.basicTypeChar(type);
20.1261 - if ("ZBSC".indexOf(c) >= 0) c = 'I';
20.1262 - assert("LIJFDV".indexOf(c) >= 0);
20.1263 - return c;
20.1264 - }
20.1265 - public static char[] basicTypes(List<Class<?>> types) {
20.1266 - char[] btypes = new char[types.size()];
20.1267 - for (int i = 0; i < btypes.length; i++) {
20.1268 - btypes[i] = basicType(types.get(i));
20.1269 - }
20.1270 - return btypes;
20.1271 - }
20.1272 - public static String basicTypeSignature(MethodType type) {
20.1273 - char[] sig = new char[type.parameterCount() + 2];
20.1274 - int sigp = 0;
20.1275 - for (Class<?> pt : type.parameterList()) {
20.1276 - sig[sigp++] = basicType(pt);
20.1277 - }
20.1278 - sig[sigp++] = '_';
20.1279 - sig[sigp++] = basicType(type.returnType());
20.1280 - assert(sigp == sig.length);
20.1281 - return String.valueOf(sig);
20.1282 - }
20.1283 -
20.1284 - static final class Name {
20.1285 - final char type;
20.1286 - private short index;
20.1287 - final NamedFunction function;
20.1288 - @Stable final Object[] arguments;
20.1289 -
20.1290 - private Name(int index, char type, NamedFunction function, Object[] arguments) {
20.1291 - this.index = (short)index;
20.1292 - this.type = type;
20.1293 - this.function = function;
20.1294 - this.arguments = arguments;
20.1295 - assert(this.index == index);
20.1296 - }
20.1297 - Name(MethodHandle function, Object... arguments) {
20.1298 - this(new NamedFunction(function), arguments);
20.1299 - }
20.1300 - Name(MethodType functionType, Object... arguments) {
20.1301 - this(new NamedFunction(functionType), arguments);
20.1302 - assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == 'L');
20.1303 - }
20.1304 - Name(MemberName function, Object... arguments) {
20.1305 - this(new NamedFunction(function), arguments);
20.1306 - }
20.1307 - Name(NamedFunction function, Object... arguments) {
20.1308 - this(-1, function.returnType(), function, arguments = arguments.clone());
20.1309 - assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
20.1310 - for (int i = 0; i < arguments.length; i++)
20.1311 - assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
20.1312 - }
20.1313 - Name(int index, char type) {
20.1314 - this(index, type, null, null);
20.1315 - }
20.1316 - Name(char type) {
20.1317 - this(-1, type);
20.1318 - }
20.1319 -
20.1320 - char type() { return type; }
20.1321 - int index() { return index; }
20.1322 - boolean initIndex(int i) {
20.1323 - if (index != i) {
20.1324 - if (index != -1) return false;
20.1325 - index = (short)i;
20.1326 - }
20.1327 - return true;
20.1328 - }
20.1329 -
20.1330 -
20.1331 - void resolve() {
20.1332 - if (function != null)
20.1333 - function.resolve();
20.1334 - }
20.1335 -
20.1336 - Name newIndex(int i) {
20.1337 - if (initIndex(i)) return this;
20.1338 - return cloneWithIndex(i);
20.1339 - }
20.1340 - Name cloneWithIndex(int i) {
20.1341 - Object[] newArguments = (arguments == null) ? null : arguments.clone();
20.1342 - return new Name(i, type, function, newArguments);
20.1343 - }
20.1344 - Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly
20.1345 - if (oldName == newName) return this;
20.1346 - @SuppressWarnings("LocalVariableHidesMemberVariable")
20.1347 - Object[] arguments = this.arguments;
20.1348 - if (arguments == null) return this;
20.1349 - boolean replaced = false;
20.1350 - for (int j = 0; j < arguments.length; j++) {
20.1351 - if (arguments[j] == oldName) {
20.1352 - if (!replaced) {
20.1353 - replaced = true;
20.1354 - arguments = arguments.clone();
20.1355 - }
20.1356 - arguments[j] = newName;
20.1357 - }
20.1358 - }
20.1359 - if (!replaced) return this;
20.1360 - return new Name(function, arguments);
20.1361 - }
20.1362 - Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
20.1363 - @SuppressWarnings("LocalVariableHidesMemberVariable")
20.1364 - Object[] arguments = this.arguments;
20.1365 - boolean replaced = false;
20.1366 - eachArg:
20.1367 - for (int j = 0; j < arguments.length; j++) {
20.1368 - if (arguments[j] instanceof Name) {
20.1369 - Name n = (Name) arguments[j];
20.1370 - int check = n.index;
20.1371 - // harmless check to see if the thing is already in newNames:
20.1372 - if (check >= 0 && check < newNames.length && n == newNames[check])
20.1373 - continue eachArg;
20.1374 - // n might not have the correct index: n != oldNames[n.index].
20.1375 - for (int i = start; i < end; i++) {
20.1376 - if (n == oldNames[i]) {
20.1377 - if (n == newNames[i])
20.1378 - continue eachArg;
20.1379 - if (!replaced) {
20.1380 - replaced = true;
20.1381 - arguments = arguments.clone();
20.1382 - }
20.1383 - arguments[j] = newNames[i];
20.1384 - continue eachArg;
20.1385 - }
20.1386 - }
20.1387 - }
20.1388 - }
20.1389 - if (!replaced) return this;
20.1390 - return new Name(function, arguments);
20.1391 - }
20.1392 - void internArguments() {
20.1393 - @SuppressWarnings("LocalVariableHidesMemberVariable")
20.1394 - Object[] arguments = this.arguments;
20.1395 - for (int j = 0; j < arguments.length; j++) {
20.1396 - if (arguments[j] instanceof Name) {
20.1397 - Name n = (Name) arguments[j];
20.1398 - if (n.isParam() && n.index < INTERNED_ARGUMENT_LIMIT)
20.1399 - arguments[j] = internArgument(n);
20.1400 - }
20.1401 - }
20.1402 - }
20.1403 - boolean isParam() {
20.1404 - return function == null;
20.1405 - }
20.1406 - boolean isConstantZero() {
20.1407 - return !isParam() && arguments.length == 0 && function.equals(constantZero(0, type).function);
20.1408 - }
20.1409 -
20.1410 - public String toString() {
20.1411 - return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+type;
20.1412 - }
20.1413 - public String debugString() {
20.1414 - String s = toString();
20.1415 - return (function == null) ? s : s + "=" + exprString();
20.1416 - }
20.1417 - public String exprString() {
20.1418 - if (function == null) return "null";
20.1419 - StringBuilder buf = new StringBuilder(function.toString());
20.1420 - buf.append("(");
20.1421 - String cma = "";
20.1422 - for (Object a : arguments) {
20.1423 - buf.append(cma); cma = ",";
20.1424 - if (a instanceof Name || a instanceof Integer)
20.1425 - buf.append(a);
20.1426 - else
20.1427 - buf.append("(").append(a).append(")");
20.1428 - }
20.1429 - buf.append(")");
20.1430 - return buf.toString();
20.1431 - }
20.1432 -
20.1433 - private static boolean typesMatch(char parameterType, Object object) {
20.1434 - if (object instanceof Name) {
20.1435 - return ((Name)object).type == parameterType;
20.1436 - }
20.1437 - switch (parameterType) {
20.1438 - case 'I': return object instanceof Integer;
20.1439 - case 'J': return object instanceof Long;
20.1440 - case 'F': return object instanceof Float;
20.1441 - case 'D': return object instanceof Double;
20.1442 - }
20.1443 - assert(parameterType == 'L');
20.1444 - return true;
20.1445 - }
20.1446 -
20.1447 - /**
20.1448 - * Does this Name precede the given binding node in some canonical order?
20.1449 - * This predicate is used to order data bindings (via insertion sort)
20.1450 - * with some stability.
20.1451 - */
20.1452 - boolean isSiblingBindingBefore(Name binding) {
20.1453 - assert(!binding.isParam());
20.1454 - if (isParam()) return true;
20.1455 - if (function.equals(binding.function) &&
20.1456 - arguments.length == binding.arguments.length) {
20.1457 - boolean sawInt = false;
20.1458 - for (int i = 0; i < arguments.length; i++) {
20.1459 - Object a1 = arguments[i];
20.1460 - Object a2 = binding.arguments[i];
20.1461 - if (!a1.equals(a2)) {
20.1462 - if (a1 instanceof Integer && a2 instanceof Integer) {
20.1463 - if (sawInt) continue;
20.1464 - sawInt = true;
20.1465 - if ((int)a1 < (int)a2) continue; // still might be true
20.1466 - }
20.1467 - return false;
20.1468 - }
20.1469 - }
20.1470 - return sawInt;
20.1471 - }
20.1472 - return false;
20.1473 - }
20.1474 -
20.1475 - public boolean equals(Name that) {
20.1476 - if (this == that) return true;
20.1477 - if (isParam())
20.1478 - // each parameter is a unique atom
20.1479 - return false; // this != that
20.1480 - return
20.1481 - //this.index == that.index &&
20.1482 - this.type == that.type &&
20.1483 - this.function.equals(that.function) &&
20.1484 - Arrays.equals(this.arguments, that.arguments);
20.1485 - }
20.1486 - @Override
20.1487 - public boolean equals(Object x) {
20.1488 - return x instanceof Name && equals((Name)x);
20.1489 - }
20.1490 - @Override
20.1491 - public int hashCode() {
20.1492 - if (isParam())
20.1493 - return index | (type << 8);
20.1494 - return function.hashCode() ^ Arrays.hashCode(arguments);
20.1495 - }
20.1496 - }
20.1497 -
20.1498 - static Name argument(int which, char type) {
20.1499 - int tn = ALL_TYPES.indexOf(type);
20.1500 - if (tn < 0 || which >= INTERNED_ARGUMENT_LIMIT)
20.1501 - return new Name(which, type);
20.1502 - return INTERNED_ARGUMENTS[tn][which];
20.1503 - }
20.1504 - static Name internArgument(Name n) {
20.1505 - assert(n.isParam()) : "not param: " + n;
20.1506 - assert(n.index < INTERNED_ARGUMENT_LIMIT);
20.1507 - return argument(n.index, n.type);
20.1508 - }
20.1509 - static Name[] arguments(int extra, String types) {
20.1510 - int length = types.length();
20.1511 - Name[] names = new Name[length + extra];
20.1512 - for (int i = 0; i < length; i++)
20.1513 - names[i] = argument(i, types.charAt(i));
20.1514 - return names;
20.1515 - }
20.1516 - static Name[] arguments(int extra, char... types) {
20.1517 - int length = types.length;
20.1518 - Name[] names = new Name[length + extra];
20.1519 - for (int i = 0; i < length; i++)
20.1520 - names[i] = argument(i, types[i]);
20.1521 - return names;
20.1522 - }
20.1523 - static Name[] arguments(int extra, List<Class<?>> types) {
20.1524 - int length = types.size();
20.1525 - Name[] names = new Name[length + extra];
20.1526 - for (int i = 0; i < length; i++)
20.1527 - names[i] = argument(i, basicType(types.get(i)));
20.1528 - return names;
20.1529 - }
20.1530 - static Name[] arguments(int extra, Class<?>... types) {
20.1531 - int length = types.length;
20.1532 - Name[] names = new Name[length + extra];
20.1533 - for (int i = 0; i < length; i++)
20.1534 - names[i] = argument(i, basicType(types[i]));
20.1535 - return names;
20.1536 - }
20.1537 - static Name[] arguments(int extra, MethodType types) {
20.1538 - int length = types.parameterCount();
20.1539 - Name[] names = new Name[length + extra];
20.1540 - for (int i = 0; i < length; i++)
20.1541 - names[i] = argument(i, basicType(types.parameterType(i)));
20.1542 - return names;
20.1543 - }
20.1544 - static final String ALL_TYPES = "LIJFD"; // omit V, not an argument type
20.1545 - static final int INTERNED_ARGUMENT_LIMIT = 10;
20.1546 - private static final Name[][] INTERNED_ARGUMENTS
20.1547 - = new Name[ALL_TYPES.length()][INTERNED_ARGUMENT_LIMIT];
20.1548 - static {
20.1549 - for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
20.1550 - for (int i = 0; i < INTERNED_ARGUMENTS[tn].length; i++) {
20.1551 - char type = ALL_TYPES.charAt(tn);
20.1552 - INTERNED_ARGUMENTS[tn][i] = new Name(i, type);
20.1553 - }
20.1554 - }
20.1555 - }
20.1556 -
20.1557 - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
20.1558 -
20.1559 - static Name constantZero(int which, char type) {
20.1560 - return CONSTANT_ZERO[ALL_TYPES.indexOf(type)].newIndex(which);
20.1561 - }
20.1562 - private static final Name[] CONSTANT_ZERO
20.1563 - = new Name[ALL_TYPES.length()];
20.1564 - static {
20.1565 - for (int tn = 0; tn < ALL_TYPES.length(); tn++) {
20.1566 - char bt = ALL_TYPES.charAt(tn);
20.1567 - Wrapper wrap = Wrapper.forBasicType(bt);
20.1568 - MemberName zmem = new MemberName(LambdaForm.class, "zero"+bt, MethodType.methodType(wrap.primitiveType()), REF_invokeStatic);
20.1569 - try {
20.1570 - zmem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zmem, null, NoSuchMethodException.class);
20.1571 - } catch (IllegalAccessException|NoSuchMethodException ex) {
20.1572 - throw newInternalError(ex);
20.1573 - }
20.1574 - NamedFunction zcon = new NamedFunction(zmem);
20.1575 - Name n = new Name(zcon).newIndex(0);
20.1576 - assert(n.type == ALL_TYPES.charAt(tn));
20.1577 - CONSTANT_ZERO[tn] = n;
20.1578 - assert(n.isConstantZero());
20.1579 - }
20.1580 - }
20.1581 -
20.1582 - // Avoid appealing to ValueConversions at bootstrap time:
20.1583 - private static int zeroI() { return 0; }
20.1584 - private static long zeroJ() { return 0; }
20.1585 - private static float zeroF() { return 0; }
20.1586 - private static double zeroD() { return 0; }
20.1587 - private static Object zeroL() { return null; }
20.1588 -
20.1589 - // Put this last, so that previous static inits can run before.
20.1590 - static {
20.1591 - if (USE_PREDEFINED_INTERPRET_METHODS)
20.1592 - PREPARED_FORMS.putAll(computeInitialPreparedForms());
20.1593 - }
20.1594 -
20.1595 - /**
20.1596 - * Internal marker for byte-compiled LambdaForms.
20.1597 - */
20.1598 - /*non-public*/
20.1599 - @Target(ElementType.METHOD)
20.1600 - @Retention(RetentionPolicy.RUNTIME)
20.1601 - @interface Compiled {
20.1602 - }
20.1603 -
20.1604 - /**
20.1605 - * Internal marker for LambdaForm interpreter frames.
20.1606 - */
20.1607 - /*non-public*/
20.1608 - @Target(ElementType.METHOD)
20.1609 - @Retention(RetentionPolicy.RUNTIME)
20.1610 - @interface Hidden {
20.1611 - }
20.1612 -
20.1613 -
20.1614 -/*
20.1615 - // Smoke-test for the invokers used in this file.
20.1616 - static void testMethodHandleLinkers() throws Throwable {
20.1617 - MemberName.Factory lookup = MemberName.getFactory();
20.1618 - MemberName asList_MN = new MemberName(Arrays.class, "asList",
20.1619 - MethodType.methodType(List.class, Object[].class),
20.1620 - REF_invokeStatic);
20.1621 - //MethodHandleNatives.resolve(asList_MN, null);
20.1622 - asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class);
20.1623 - System.out.println("about to call "+asList_MN);
20.1624 - Object[] abc = { "a", "bc" };
20.1625 - List<?> lst = (List<?>) MethodHandle.linkToStatic(abc, asList_MN);
20.1626 - System.out.println("lst="+lst);
20.1627 - MemberName toString_MN = new MemberName(Object.class.getMethod("toString"));
20.1628 - String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN);
20.1629 - toString_MN = new MemberName(Object.class.getMethod("toString"), true);
20.1630 - String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN);
20.1631 - System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString()));
20.1632 - MemberName toArray_MN = new MemberName(List.class.getMethod("toArray"));
20.1633 - Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN);
20.1634 - System.out.println("toArray="+Arrays.toString(arr));
20.1635 - }
20.1636 - static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } }
20.1637 - // Requires these definitions in MethodHandle:
20.1638 - static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable;
20.1639 - static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable;
20.1640 - static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable;
20.1641 - static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable;
20.1642 - */
20.1643 -
20.1644 - static { NamedFunction.initializeInvokers(); }
20.1645 -
20.1646 - // The following hack is necessary in order to suppress TRACE_INTERPRETER
20.1647 - // during execution of the static initializes of this class.
20.1648 - // Turning on TRACE_INTERPRETER too early will cause
20.1649 - // stack overflows and other misbehavior during attempts to trace events
20.1650 - // that occur during LambdaForm.<clinit>.
20.1651 - // Therefore, do not move this line higher in this file, and do not remove.
20.1652 - private static final boolean TRACE_INTERPRETER = MethodHandleStatics.TRACE_INTERPRETER;
20.1653 -}
21.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/LambdaMetafactory.java Sun Aug 17 20:09:05 2014 +0200
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,477 +0,0 @@
21.4 -/*
21.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
21.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
21.7 - *
21.8 - * This code is free software; you can redistribute it and/or modify it
21.9 - * under the terms of the GNU General Public License version 2 only, as
21.10 - * published by the Free Software Foundation. Oracle designates this
21.11 - * particular file as subject to the "Classpath" exception as provided
21.12 - * by Oracle in the LICENSE file that accompanied this code.
21.13 - *
21.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
21.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21.17 - * version 2 for more details (a copy is included in the LICENSE file that
21.18 - * accompanied this code).
21.19 - *
21.20 - * You should have received a copy of the GNU General Public License version
21.21 - * 2 along with this work; if not, write to the Free Software Foundation,
21.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21.23 - *
21.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21.25 - * or visit www.oracle.com if you need additional information or have any
21.26 - * questions.
21.27 - */
21.28 -
21.29 -package java.lang.invoke;
21.30 -
21.31 -import java.io.Serializable;
21.32 -import java.util.Arrays;
21.33 -
21.34 -/**
21.35 - * <p>Methods to facilitate the creation of simple "function objects" that
21.36 - * implement one or more interfaces by delegation to a provided {@link MethodHandle},
21.37 - * possibly after type adaptation and partial evaluation of arguments. These
21.38 - * methods are typically used as <em>bootstrap methods</em> for {@code invokedynamic}
21.39 - * call sites, to support the <em>lambda expression</em> and <em>method
21.40 - * reference expression</em> features of the Java Programming Language.
21.41 - *
21.42 - * <p>Indirect access to the behavior specified by the provided {@code MethodHandle}
21.43 - * proceeds in order through three phases:
21.44 - * <ul>
21.45 - * <li><em>Linkage</em> occurs when the methods in this class are invoked.
21.46 - * They take as arguments an interface to be implemented (typically a
21.47 - * <em>functional interface</em>, one with a single abstract method), a
21.48 - * name and signature of a method from that interface to be implemented, a
21.49 - * method handle describing the desired implementation behavior
21.50 - * for that method, and possibly other additional metadata, and produce a
21.51 - * {@link CallSite} whose target can be used to create suitable function
21.52 - * objects. Linkage may involve dynamically loading a new class that
21.53 - * implements the target interface. The {@code CallSite} can be considered a
21.54 - * "factory" for function objects and so these linkage methods are referred
21.55 - * to as "metafactories".</li>
21.56 - *
21.57 - * <li><em>Capture</em> occurs when the {@code CallSite}'s target is
21.58 - * invoked, typically through an {@code invokedynamic} call site,
21.59 - * producing a function object. This may occur many times for
21.60 - * a single factory {@code CallSite}. Capture may involve allocation of a
21.61 - * new function object, or may return an existing function object. The
21.62 - * behavior {@code MethodHandle} may have additional parameters beyond those
21.63 - * of the specified interface method; these are referred to as <em>captured
21.64 - * parameters</em>, which must be provided as arguments to the
21.65 - * {@code CallSite} target, and which may be early-bound to the behavior
21.66 - * {@code MethodHandle}. The number of captured parameters and their types
21.67 - * are determined during linkage.</li>
21.68 - *
21.69 - * <li><em>Invocation</em> occurs when an implemented interface method
21.70 - * is invoked on a function object. This may occur many times for a single
21.71 - * function object. The method referenced by the behavior {@code MethodHandle}
21.72 - * is invoked with the captured arguments and any additional arguments
21.73 - * provided on invocation, as if by {@link MethodHandle#invoke(Object...)}.</li>
21.74 - * </ul>
21.75 - *
21.76 - * <p>It is sometimes useful to restrict the set of inputs or results permitted
21.77 - * at invocation. For example, when the generic interface {@code Predicate<T>}
21.78 - * is parameterized as {@code Predicate<String>}, the input must be a
21.79 - * {@code String}, even though the method to implement allows any {@code Object}.
21.80 - * At linkage time, an additional {@link MethodType} parameter describes the
21.81 - * "instantiated" method type; on invocation, the arguments and eventual result
21.82 - * are checked against this {@code MethodType}.
21.83 - *
21.84 - * <p>This class provides two forms of linkage methods: a standard version
21.85 - * ({@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)})
21.86 - * using an optimized protocol, and an alternate version
21.87 - * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}).
21.88 - * The alternate version is a generalization of the standard version, providing
21.89 - * additional control over the behavior of the generated function objects via
21.90 - * flags and additional arguments. The alternate version adds the ability to
21.91 - * manage the following attributes of function objects:
21.92 - *
21.93 - * <ul>
21.94 - * <li><em>Bridging.</em> It is sometimes useful to implement multiple
21.95 - * variations of the method signature, involving argument or return type
21.96 - * adaptation. This occurs when multiple distinct VM signatures for a method
21.97 - * are logically considered to be the same method by the language. The
21.98 - * flag {@code FLAG_BRIDGES} indicates that a list of additional
21.99 - * {@code MethodType}s will be provided, each of which will be implemented
21.100 - * by the resulting function object. These methods will share the same
21.101 - * name and instantiated type.</li>
21.102 - *
21.103 - * <li><em>Multiple interfaces.</em> If needed, more than one interface
21.104 - * can be implemented by the function object. (These additional interfaces
21.105 - * are typically marker interfaces with no methods.) The flag {@code FLAG_MARKERS}
21.106 - * indicates that a list of additional interfaces will be provided, each of
21.107 - * which should be implemented by the resulting function object.</li>
21.108 - *
21.109 - * <li><em>Serializability.</em> The generated function objects do not
21.110 - * generally support serialization. If desired, {@code FLAG_SERIALIZABLE}
21.111 - * can be used to indicate that the function objects should be serializable.
21.112 - * Serializable function objects will use, as their serialized form,
21.113 - * instances of the class {@code SerializedLambda}, which requires additional
21.114 - * assistance from the capturing class (the class described by the
21.115 - * {@link MethodHandles.Lookup} parameter {@code caller}); see
21.116 - * {@link SerializedLambda} for details.</li>
21.117 - * </ul>
21.118 - *
21.119 - * <p>Assume the linkage arguments are as follows:
21.120 - * <ul>
21.121 - * <li>{@code invokedType} (describing the {@code CallSite} signature) has
21.122 - * K parameters of types (D1..Dk) and return type Rd;</li>
21.123 - * <li>{@code samMethodType} (describing the implemented method type) has N
21.124 - * parameters, of types (U1..Un) and return type Ru;</li>
21.125 - * <li>{@code implMethod} (the {@code MethodHandle} providing the
21.126 - * implementation has M parameters, of types (A1..Am) and return type Ra
21.127 - * (if the method describes an instance method, the method type of this
21.128 - * method handle already includes an extra first argument corresponding to
21.129 - * the receiver);</li>
21.130 - * <li>{@code instantiatedMethodType} (allowing restrictions on invocation)
21.131 - * has N parameters, of types (T1..Tn) and return type Rt.</li>
21.132 - * </ul>
21.133 - *
21.134 - * <p>Then the following linkage invariants must hold:
21.135 - * <ul>
21.136 - * <li>Rd is an interface</li>
21.137 - * <li>{@code implMethod} is a <em>direct method handle</em></li>
21.138 - * <li>{@code samMethodType} and {@code instantiatedMethodType} have the same
21.139 - * arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
21.140 - * both reference types and Ti is a subtype of Ui</li>
21.141 - * <li>Either Rt and Ru are the same type, or both are reference types and
21.142 - * Rt is a subtype of Ru</li>
21.143 - * <li>K + N = M</li>
21.144 - * <li>For i=1..K, Di = Ai</li>
21.145 - * <li>For i=1..N, Ti is adaptable to Aj, where j=i+k</li>
21.146 - * <li>The return type Rt is void, or the return type Ra is not void and is
21.147 - * adaptable to Rt</li>
21.148 - * </ul>
21.149 - *
21.150 - * <p>Further, at capture time, if {@code implMethod} corresponds to an instance
21.151 - * method, and there are any capture arguments ({@code K > 0}), then the first
21.152 - * capture argument (corresponding to the receiver) must be non-null.
21.153 - *
21.154 - * <p>A type Q is considered adaptable to S as follows:
21.155 - * <table summary="adaptable types">
21.156 - * <tr><th>Q</th><th>S</th><th>Link-time checks</th><th>Invocation-time checks</th></tr>
21.157 - * <tr>
21.158 - * <td>Primitive</td><td>Primitive</td>
21.159 - * <td>Q can be converted to S via a primitive widening conversion</td>
21.160 - * <td>None</td>
21.161 - * </tr>
21.162 - * <tr>
21.163 - * <td>Primitive</td><td>Reference</td>
21.164 - * <td>S is a supertype of the Wrapper(Q)</td>
21.165 - * <td>Cast from Wrapper(Q) to S</td>
21.166 - * </tr>
21.167 - * <tr>
21.168 - * <td>Reference</td><td>Primitive</td>
21.169 - * <td>for parameter types: Q is a primitive wrapper and Primitive(Q)
21.170 - * can be widened to S
21.171 - * <br>for return types: If Q is a primitive wrapper, check that
21.172 - * Primitive(Q) can be widened to S</td>
21.173 - * <td>If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
21.174 - * for example Number for numeric types</td>
21.175 - * </tr>
21.176 - * <tr>
21.177 - * <td>Reference</td><td>Reference</td>
21.178 - * <td>for parameter types: S is a supertype of Q
21.179 - * <br>for return types: none</td>
21.180 - * <td>Cast from Q to S</td>
21.181 - * </tr>
21.182 - * </table>
21.183 - *
21.184 - * @apiNote These linkage methods are designed to support the evaluation
21.185 - * of <em>lambda expressions</em> and <em>method references</em> in the Java
21.186 - * Language. For every lambda expressions or method reference in the source code,
21.187 - * there is a target type which is a functional interface. Evaluating a lambda
21.188 - * expression produces an object of its target type. The recommended mechanism
21.189 - * for evaluating lambda expressions is to desugar the lambda body to a method,
21.190 - * invoke an invokedynamic call site whose static argument list describes the
21.191 - * sole method of the functional interface and the desugared implementation
21.192 - * method, and returns an object (the lambda object) that implements the target
21.193 - * type. (For method references, the implementation method is simply the
21.194 - * referenced method; no desugaring is needed.)
21.195 - *
21.196 - * <p>The argument list of the implementation method and the argument list of
21.197 - * the interface method(s) may differ in several ways. The implementation
21.198 - * methods may have additional arguments to accommodate arguments captured by
21.199 - * the lambda expression; there may also be differences resulting from permitted
21.200 - * adaptations of arguments, such as casting, boxing, unboxing, and primitive
21.201 - * widening. (Varargs adaptations are not handled by the metafactories; these are
21.202 - * expected to be handled by the caller.)
21.203 - *
21.204 - * <p>Invokedynamic call sites have two argument lists: a static argument list
21.205 - * and a dynamic argument list. The static argument list is stored in the
21.206 - * constant pool; the dynamic argument is pushed on the operand stack at capture
21.207 - * time. The bootstrap method has access to the entire static argument list
21.208 - * (which in this case, includes information describing the implementation method,
21.209 - * the target interface, and the target interface method(s)), as well as a
21.210 - * method signature describing the number and static types (but not the values)
21.211 - * of the dynamic arguments and the static return type of the invokedynamic site.
21.212 - *
21.213 - * @implNote The implementation method is described with a method handle. In
21.214 - * theory, any method handle could be used. Currently supported are direct method
21.215 - * handles representing invocation of virtual, interface, constructor and static
21.216 - * methods.
21.217 - */
21.218 -public class LambdaMetafactory {
21.219 -
21.220 - /** Flag for alternate metafactories indicating the lambda object
21.221 - * must be serializable */
21.222 - public static final int FLAG_SERIALIZABLE = 1 << 0;
21.223 -
21.224 - /**
21.225 - * Flag for alternate metafactories indicating the lambda object implements
21.226 - * other marker interfaces
21.227 - * besides Serializable
21.228 - */
21.229 - public static final int FLAG_MARKERS = 1 << 1;
21.230 -
21.231 - /**
21.232 - * Flag for alternate metafactories indicating the lambda object requires
21.233 - * additional bridge methods
21.234 - */
21.235 - public static final int FLAG_BRIDGES = 1 << 2;
21.236 -
21.237 - private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
21.238 - private static final MethodType[] EMPTY_MT_ARRAY = new MethodType[0];
21.239 -
21.240 - /**
21.241 - * Facilitates the creation of simple "function objects" that implement one
21.242 - * or more interfaces by delegation to a provided {@link MethodHandle},
21.243 - * after appropriate type adaptation and partial evaluation of arguments.
21.244 - * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
21.245 - * call sites, to support the <em>lambda expression</em> and <em>method
21.246 - * reference expression</em> features of the Java Programming Language.
21.247 - *
21.248 - * <p>This is the standard, streamlined metafactory; additional flexibility
21.249 - * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
21.250 - * A general description of the behavior of this method is provided
21.251 - * {@link LambdaMetafactory above}.
21.252 - *
21.253 - * <p>When the target of the {@code CallSite} returned from this method is
21.254 - * invoked, the resulting function objects are instances of a class which
21.255 - * implements the interface named by the return type of {@code invokedType},
21.256 - * declares a method with the name given by {@code invokedName} and the
21.257 - * signature given by {@code samMethodType}. It may also override additional
21.258 - * methods from {@code Object}.
21.259 - *
21.260 - * @param caller Represents a lookup context with the accessibility
21.261 - * privileges of the caller. When used with {@code invokedynamic},
21.262 - * this is stacked automatically by the VM.
21.263 - * @param invokedName The name of the method to implement. When used with
21.264 - * {@code invokedynamic}, this is provided by the
21.265 - * {@code NameAndType} of the {@code InvokeDynamic}
21.266 - * structure and is stacked automatically by the VM.
21.267 - * @param invokedType The expected signature of the {@code CallSite}. The
21.268 - * parameter types represent the types of capture variables;
21.269 - * the return type is the interface to implement. When
21.270 - * used with {@code invokedynamic}, this is provided by
21.271 - * the {@code NameAndType} of the {@code InvokeDynamic}
21.272 - * structure and is stacked automatically by the VM.
21.273 - * In the event that the implementation method is an
21.274 - * instance method and this signature has any parameters,
21.275 - * the first parameter in the invocation signature must
21.276 - * correspond to the receiver.
21.277 - * @param samMethodType Signature and return type of method to be implemented
21.278 - * by the function object.
21.279 - * @param implMethod A direct method handle describing the implementation
21.280 - * method which should be called (with suitable adaptation
21.281 - * of argument types, return types, and with captured
21.282 - * arguments prepended to the invocation arguments) at
21.283 - * invocation time.
21.284 - * @param instantiatedMethodType The signature and return type that should
21.285 - * be enforced dynamically at invocation time.
21.286 - * This may be the same as {@code samMethodType},
21.287 - * or may be a specialization of it.
21.288 - * @return a CallSite whose target can be used to perform capture, generating
21.289 - * instances of the interface named by {@code invokedType}
21.290 - * @throws LambdaConversionException If any of the linkage invariants
21.291 - * described {@link LambdaMetafactory above}
21.292 - * are violated
21.293 - */
21.294 - public static CallSite metafactory(MethodHandles.Lookup caller,
21.295 - String invokedName,
21.296 - MethodType invokedType,
21.297 - MethodType samMethodType,
21.298 - MethodHandle implMethod,
21.299 - MethodType instantiatedMethodType)
21.300 - throws LambdaConversionException {
21.301 - AbstractValidatingLambdaMetafactory mf;
21.302 -// mf = new InnerClassLambdaMetafactory(caller, invokedType,
21.303 -// invokedName, samMethodType,
21.304 -// implMethod, instantiatedMethodType,
21.305 -// false, EMPTY_CLASS_ARRAY, EMPTY_MT_ARRAY);
21.306 -// mf.validateMetafactoryArgs();
21.307 -// return mf.buildCallSite();
21.308 - throw new IllegalStateException();
21.309 - }
21.310 -
21.311 - /**
21.312 - * Facilitates the creation of simple "function objects" that implement one
21.313 - * or more interfaces by delegation to a provided {@link MethodHandle},
21.314 - * after appropriate type adaptation and partial evaluation of arguments.
21.315 - * Typically used as a <em>bootstrap method</em> for {@code invokedynamic}
21.316 - * call sites, to support the <em>lambda expression</em> and <em>method
21.317 - * reference expression</em> features of the Java Programming Language.
21.318 - *
21.319 - * <p>This is the general, more flexible metafactory; a streamlined version
21.320 - * is provided by {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)}.
21.321 - * A general description of the behavior of this method is provided
21.322 - * {@link LambdaMetafactory above}.
21.323 - *
21.324 - * <p>The argument list for this method includes three fixed parameters,
21.325 - * corresponding to the parameters automatically stacked by the VM for the
21.326 - * bootstrap method in an {@code invokedynamic} invocation, and an {@code Object[]}
21.327 - * parameter that contains additional parameters. The declared argument
21.328 - * list for this method is:
21.329 - *
21.330 - * <pre>{@code
21.331 - * CallSite altMetafactory(MethodHandles.Lookup caller,
21.332 - * String invokedName,
21.333 - * MethodType invokedType,
21.334 - * Object... args)
21.335 - * }</pre>
21.336 - *
21.337 - * <p>but it behaves as if the argument list is as follows:
21.338 - *
21.339 - * <pre>{@code
21.340 - * CallSite altMetafactory(MethodHandles.Lookup caller,
21.341 - * String invokedName,
21.342 - * MethodType invokedType,
21.343 - * MethodType samMethodType,
21.344 - * MethodHandle implMethod,
21.345 - * MethodType instantiatedMethodType,
21.346 - * int flags,
21.347 - * int markerInterfaceCount, // IF flags has MARKERS set
21.348 - * Class... markerInterfaces, // IF flags has MARKERS set
21.349 - * int bridgeCount, // IF flags has BRIDGES set
21.350 - * MethodType... bridges // IF flags has BRIDGES set
21.351 - * )
21.352 - * }</pre>
21.353 - *
21.354 - * <p>Arguments that appear in the argument list for
21.355 - * {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
21.356 - * have the same specification as in that method. The additional arguments
21.357 - * are interpreted as follows:
21.358 - * <ul>
21.359 - * <li>{@code flags} indicates additional options; this is a bitwise
21.360 - * OR of desired flags. Defined flags are {@link #FLAG_BRIDGES},
21.361 - * {@link #FLAG_MARKERS}, and {@link #FLAG_SERIALIZABLE}.</li>
21.362 - * <li>{@code markerInterfaceCount} is the number of additional interfaces
21.363 - * the function object should implement, and is present if and only if the
21.364 - * {@code FLAG_MARKERS} flag is set.</li>
21.365 - * <li>{@code markerInterfaces} is a variable-length list of additional
21.366 - * interfaces to implement, whose length equals {@code markerInterfaceCount},
21.367 - * and is present if and only if the {@code FLAG_MARKERS} flag is set.</li>
21.368 - * <li>{@code bridgeCount} is the number of additional method signatures
21.369 - * the function object should implement, and is present if and only if
21.370 - * the {@code FLAG_BRIDGES} flag is set.</li>
21.371 - * <li>{@code bridges} is a variable-length list of additional
21.372 - * methods signatures to implement, whose length equals {@code bridgeCount},
21.373 - * and is present if and only if the {@code FLAG_BRIDGES} flag is set.</li>
21.374 - * </ul>
21.375 - *
21.376 - * <p>Each class named by {@code markerInterfaces} is subject to the same
21.377 - * restrictions as {@code Rd}, the return type of {@code invokedType},
21.378 - * as described {@link LambdaMetafactory above}. Each {@code MethodType}
21.379 - * named by {@code bridges} is subject to the same restrictions as
21.380 - * {@code samMethodType}, as described {@link LambdaMetafactory above}.
21.381 - *
21.382 - * <p>When FLAG_SERIALIZABLE is set in {@code flags}, the function objects
21.383 - * will implement {@code Serializable}, and will have a {@code writeReplace}
21.384 - * method that returns an appropriate {@link SerializedLambda}. The
21.385 - * {@code caller} class must have an appropriate {@code $deserializeLambda$}
21.386 - * method, as described in {@link SerializedLambda}.
21.387 - *
21.388 - * <p>When the target of the {@code CallSite} returned from this method is
21.389 - * invoked, the resulting function objects are instances of a class with
21.390 - * the following properties:
21.391 - * <ul>
21.392 - * <li>The class implements the interface named by the return type
21.393 - * of {@code invokedType} and any interfaces named by {@code markerInterfaces}</li>
21.394 - * <li>The class declares methods with the name given by {@code invokedName},
21.395 - * and the signature given by {@code samMethodType} and additional signatures
21.396 - * given by {@code bridges}</li>
21.397 - * <li>The class may override methods from {@code Object}, and may
21.398 - * implement methods related to serialization.</li>
21.399 - * </ul>
21.400 - *
21.401 - * @param caller Represents a lookup context with the accessibility
21.402 - * privileges of the caller. When used with {@code invokedynamic},
21.403 - * this is stacked automatically by the VM.
21.404 - * @param invokedName The name of the method to implement. When used with
21.405 - * {@code invokedynamic}, this is provided by the
21.406 - * {@code NameAndType} of the {@code InvokeDynamic}
21.407 - * structure and is stacked automatically by the VM.
21.408 - * @param invokedType The expected signature of the {@code CallSite}. The
21.409 - * parameter types represent the types of capture variables;
21.410 - * the return type is the interface to implement. When
21.411 - * used with {@code invokedynamic}, this is provided by
21.412 - * the {@code NameAndType} of the {@code InvokeDynamic}
21.413 - * structure and is stacked automatically by the VM.
21.414 - * In the event that the implementation method is an
21.415 - * instance method and this signature has any parameters,
21.416 - * the first parameter in the invocation signature must
21.417 - * correspond to the receiver.
21.418 - * @param args An {@code Object[]} array containing the required
21.419 - * arguments {@code samMethodType}, {@code implMethod},
21.420 - * {@code instantiatedMethodType}, {@code flags}, and any
21.421 - * optional arguments, as described
21.422 - * {@link #altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)} above}
21.423 - * @return a CallSite whose target can be used to perform capture, generating
21.424 - * instances of the interface named by {@code invokedType}
21.425 - * @throws LambdaConversionException If any of the linkage invariants
21.426 - * described {@link LambdaMetafactory above}
21.427 - * are violated
21.428 - */
21.429 - public static CallSite altMetafactory(MethodHandles.Lookup caller,
21.430 - String invokedName,
21.431 - MethodType invokedType,
21.432 - Object... args)
21.433 - throws LambdaConversionException {
21.434 - MethodType samMethodType = (MethodType)args[0];
21.435 - MethodHandle implMethod = (MethodHandle)args[1];
21.436 - MethodType instantiatedMethodType = (MethodType)args[2];
21.437 - int flags = (Integer) args[3];
21.438 - Class<?>[] markerInterfaces;
21.439 - MethodType[] bridges;
21.440 - int argIndex = 4;
21.441 - if ((flags & FLAG_MARKERS) != 0) {
21.442 - int markerCount = (Integer) args[argIndex++];
21.443 - markerInterfaces = new Class<?>[markerCount];
21.444 - System.arraycopy(args, argIndex, markerInterfaces, 0, markerCount);
21.445 - argIndex += markerCount;
21.446 - }
21.447 - else
21.448 - markerInterfaces = EMPTY_CLASS_ARRAY;
21.449 - if ((flags & FLAG_BRIDGES) != 0) {
21.450 - int bridgeCount = (Integer) args[argIndex++];
21.451 - bridges = new MethodType[bridgeCount];
21.452 - System.arraycopy(args, argIndex, bridges, 0, bridgeCount);
21.453 - argIndex += bridgeCount;
21.454 - }
21.455 - else
21.456 - bridges = EMPTY_MT_ARRAY;
21.457 -
21.458 - boolean isSerializable = ((flags & FLAG_SERIALIZABLE) != 0);
21.459 - if (isSerializable) {
21.460 - boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(invokedType.returnType());
21.461 - for (Class<?> c : markerInterfaces)
21.462 - foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
21.463 - if (!foundSerializableSupertype) {
21.464 - markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
21.465 - markerInterfaces[markerInterfaces.length-1] = Serializable.class;
21.466 - }
21.467 - }
21.468 -
21.469 -// AbstractValidatingLambdaMetafactory mf
21.470 -// = new InnerClassLambdaMetafactory(caller, invokedType,
21.471 -// invokedName, samMethodType,
21.472 -// implMethod,
21.473 -// instantiatedMethodType,
21.474 -// isSerializable,
21.475 -// markerInterfaces, bridges);
21.476 -// mf.validateMetafactoryArgs();
21.477 -// return mf.buildCallSite();
21.478 - throw new IllegalStateException();
21.479 - }
21.480 -}
22.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MemberName.java Sun Aug 17 20:09:05 2014 +0200
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,1080 +0,0 @@
22.4 -/*
22.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
22.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
22.7 - *
22.8 - * This code is free software; you can redistribute it and/or modify it
22.9 - * under the terms of the GNU General Public License version 2 only, as
22.10 - * published by the Free Software Foundation. Oracle designates this
22.11 - * particular file as subject to the "Classpath" exception as provided
22.12 - * by Oracle in the LICENSE file that accompanied this code.
22.13 - *
22.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
22.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22.17 - * version 2 for more details (a copy is included in the LICENSE file that
22.18 - * accompanied this code).
22.19 - *
22.20 - * You should have received a copy of the GNU General Public License version
22.21 - * 2 along with this work; if not, write to the Free Software Foundation,
22.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22.23 - *
22.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22.25 - * or visit www.oracle.com if you need additional information or have any
22.26 - * questions.
22.27 - */
22.28 -
22.29 -package java.lang.invoke;
22.30 -
22.31 -import sun.invoke.util.BytecodeDescriptor;
22.32 -import sun.invoke.util.VerifyAccess;
22.33 -
22.34 -import java.lang.reflect.Constructor;
22.35 -import java.lang.reflect.Field;
22.36 -import java.lang.reflect.Method;
22.37 -import java.lang.reflect.Member;
22.38 -import java.lang.reflect.Modifier;
22.39 -import java.util.ArrayList;
22.40 -import java.util.Arrays;
22.41 -import java.util.Collections;
22.42 -import java.util.Iterator;
22.43 -import java.util.List;
22.44 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
22.45 -import static java.lang.invoke.MethodHandleStatics.*;
22.46 -import java.util.Objects;
22.47 -
22.48 -/**
22.49 - * A {@code MemberName} is a compact symbolic datum which fully characterizes
22.50 - * a method or field reference.
22.51 - * A member name refers to a field, method, constructor, or member type.
22.52 - * Every member name has a simple name (a string) and a type (either a Class or MethodType).
22.53 - * A member name may also have a non-null declaring class, or it may be simply
22.54 - * a naked name/type pair.
22.55 - * A member name may also have non-zero modifier flags.
22.56 - * Finally, a member name may be either resolved or unresolved.
22.57 - * If it is resolved, the existence of the named
22.58 - * <p>
22.59 - * Whether resolved or not, a member name provides no access rights or
22.60 - * invocation capability to its possessor. It is merely a compact
22.61 - * representation of all symbolic information necessary to link to
22.62 - * and properly use the named member.
22.63 - * <p>
22.64 - * When resolved, a member name's internal implementation may include references to JVM metadata.
22.65 - * This representation is stateless and only decriptive.
22.66 - * It provides no private information and no capability to use the member.
22.67 - * <p>
22.68 - * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information
22.69 - * about the internals of a method (except its bytecodes) and also
22.70 - * allows invocation. A MemberName is much lighter than a Method,
22.71 - * since it contains about 7 fields to the 16 of Method (plus its sub-arrays),
22.72 - * and those seven fields omit much of the information in Method.
22.73 - * @author jrose
22.74 - */
22.75 -/*non-public*/ final class MemberName implements Member, Cloneable {
22.76 - Class<?> clazz; // class in which the method is defined
22.77 - private String name; // may be null if not yet materialized
22.78 - private Object type; // may be null if not yet materialized
22.79 - int flags; // modifier bits; see reflect.Modifier
22.80 - //@Injected JVM_Method* vmtarget;
22.81 - //@Injected int vmindex;
22.82 - private Object resolution; // if null, this guy is resolved
22.83 -
22.84 - /** Return the declaring class of this member.
22.85 - * In the case of a bare name and type, the declaring class will be null.
22.86 - */
22.87 - public Class<?> getDeclaringClass() {
22.88 - return clazz;
22.89 - }
22.90 -
22.91 - /** Utility method producing the class loader of the declaring class. */
22.92 - public ClassLoader getClassLoader() {
22.93 - return clazz.getClassLoader();
22.94 - }
22.95 -
22.96 - /** Return the simple name of this member.
22.97 - * For a type, it is the same as {@link Class#getSimpleName}.
22.98 - * For a method or field, it is the simple name of the member.
22.99 - * For a constructor, it is always {@code "<init>"}.
22.100 - */
22.101 - public String getName() {
22.102 - if (name == null) {
22.103 - expandFromVM();
22.104 - if (name == null) {
22.105 - return null;
22.106 - }
22.107 - }
22.108 - return name;
22.109 - }
22.110 -
22.111 - public MethodType getMethodOrFieldType() {
22.112 - if (isInvocable())
22.113 - return getMethodType();
22.114 - if (isGetter())
22.115 - return MethodType.methodType(getFieldType());
22.116 - if (isSetter())
22.117 - return MethodType.methodType(void.class, getFieldType());
22.118 - throw new InternalError("not a method or field: "+this);
22.119 - }
22.120 -
22.121 - /** Return the declared type of this member, which
22.122 - * must be a method or constructor.
22.123 - */
22.124 - public MethodType getMethodType() {
22.125 - if (type == null) {
22.126 - expandFromVM();
22.127 - if (type == null) {
22.128 - return null;
22.129 - }
22.130 - }
22.131 - if (!isInvocable()) {
22.132 - throw newIllegalArgumentException("not invocable, no method type");
22.133 - }
22.134 -
22.135 - {
22.136 - // Get a snapshot of type which doesn't get changed by racing threads.
22.137 - final Object type = this.type;
22.138 - if (type instanceof MethodType) {
22.139 - return (MethodType) type;
22.140 - }
22.141 - }
22.142 -
22.143 - // type is not a MethodType yet. Convert it thread-safely.
22.144 - synchronized (this) {
22.145 - if (type instanceof String) {
22.146 - String sig = (String) type;
22.147 - MethodType res = MethodType.fromMethodDescriptorString(sig, getClassLoader());
22.148 - type = res;
22.149 - } else if (type instanceof Object[]) {
22.150 - Object[] typeInfo = (Object[]) type;
22.151 - Class<?>[] ptypes = (Class<?>[]) typeInfo[1];
22.152 - Class<?> rtype = (Class<?>) typeInfo[0];
22.153 - MethodType res = MethodType.methodType(rtype, ptypes);
22.154 - type = res;
22.155 - }
22.156 - // Make sure type is a MethodType for racing threads.
22.157 - assert type instanceof MethodType : "bad method type " + type;
22.158 - }
22.159 - return (MethodType) type;
22.160 - }
22.161 -
22.162 - /** Return the actual type under which this method or constructor must be invoked.
22.163 - * For non-static methods or constructors, this is the type with a leading parameter,
22.164 - * a reference to declaring class. For static methods, it is the same as the declared type.
22.165 - */
22.166 - public MethodType getInvocationType() {
22.167 - MethodType itype = getMethodOrFieldType();
22.168 - if (isConstructor() && getReferenceKind() == REF_newInvokeSpecial)
22.169 - return itype.changeReturnType(clazz);
22.170 - if (!isStatic())
22.171 - return itype.insertParameterTypes(0, clazz);
22.172 - return itype;
22.173 - }
22.174 -
22.175 - /** Utility method producing the parameter types of the method type. */
22.176 - public Class<?>[] getParameterTypes() {
22.177 - return getMethodType().parameterArray();
22.178 - }
22.179 -
22.180 - /** Utility method producing the return type of the method type. */
22.181 - public Class<?> getReturnType() {
22.182 - return getMethodType().returnType();
22.183 - }
22.184 -
22.185 - /** Return the declared type of this member, which
22.186 - * must be a field or type.
22.187 - * If it is a type member, that type itself is returned.
22.188 - */
22.189 - public Class<?> getFieldType() {
22.190 - if (type == null) {
22.191 - expandFromVM();
22.192 - if (type == null) {
22.193 - return null;
22.194 - }
22.195 - }
22.196 - if (isInvocable()) {
22.197 - throw newIllegalArgumentException("not a field or nested class, no simple type");
22.198 - }
22.199 -
22.200 - {
22.201 - // Get a snapshot of type which doesn't get changed by racing threads.
22.202 - final Object type = this.type;
22.203 - if (type instanceof Class<?>) {
22.204 - return (Class<?>) type;
22.205 - }
22.206 - }
22.207 -
22.208 - // type is not a Class yet. Convert it thread-safely.
22.209 - synchronized (this) {
22.210 - if (type instanceof String) {
22.211 - String sig = (String) type;
22.212 - MethodType mtype = MethodType.fromMethodDescriptorString("()"+sig, getClassLoader());
22.213 - Class<?> res = mtype.returnType();
22.214 - type = res;
22.215 - }
22.216 - // Make sure type is a Class for racing threads.
22.217 - assert type instanceof Class<?> : "bad field type " + type;
22.218 - }
22.219 - return (Class<?>) type;
22.220 - }
22.221 -
22.222 - /** Utility method to produce either the method type or field type of this member. */
22.223 - public Object getType() {
22.224 - return (isInvocable() ? getMethodType() : getFieldType());
22.225 - }
22.226 -
22.227 - /** Utility method to produce the signature of this member,
22.228 - * used within the class file format to describe its type.
22.229 - */
22.230 - public String getSignature() {
22.231 - if (type == null) {
22.232 - expandFromVM();
22.233 - if (type == null) {
22.234 - return null;
22.235 - }
22.236 - }
22.237 - if (isInvocable())
22.238 - return BytecodeDescriptor.unparse(getMethodType());
22.239 - else
22.240 - return BytecodeDescriptor.unparse(getFieldType());
22.241 - }
22.242 -
22.243 - /** Return the modifier flags of this member.
22.244 - * @see java.lang.reflect.Modifier
22.245 - */
22.246 - public int getModifiers() {
22.247 - return (flags & RECOGNIZED_MODIFIERS);
22.248 - }
22.249 -
22.250 - /** Return the reference kind of this member, or zero if none.
22.251 - */
22.252 - public byte getReferenceKind() {
22.253 - return (byte) ((flags >>> MN_REFERENCE_KIND_SHIFT) & MN_REFERENCE_KIND_MASK);
22.254 - }
22.255 - private boolean referenceKindIsConsistent() {
22.256 - byte refKind = getReferenceKind();
22.257 - if (refKind == REF_NONE) return isType();
22.258 - if (isField()) {
22.259 - assert(staticIsConsistent());
22.260 - assert(MethodHandleNatives.refKindIsField(refKind));
22.261 - } else if (isConstructor()) {
22.262 - assert(refKind == REF_newInvokeSpecial || refKind == REF_invokeSpecial);
22.263 - } else if (isMethod()) {
22.264 - assert(staticIsConsistent());
22.265 - assert(MethodHandleNatives.refKindIsMethod(refKind));
22.266 - if (clazz.isInterface())
22.267 - assert(refKind == REF_invokeInterface ||
22.268 - refKind == REF_invokeStatic ||
22.269 - refKind == REF_invokeSpecial ||
22.270 - refKind == REF_invokeVirtual && isObjectPublicMethod());
22.271 - } else {
22.272 - assert(false);
22.273 - }
22.274 - return true;
22.275 - }
22.276 - private boolean isObjectPublicMethod() {
22.277 - if (clazz == Object.class) return true;
22.278 - MethodType mtype = getMethodType();
22.279 - if (name.equals("toString") && mtype.returnType() == String.class && mtype.parameterCount() == 0)
22.280 - return true;
22.281 - if (name.equals("hashCode") && mtype.returnType() == int.class && mtype.parameterCount() == 0)
22.282 - return true;
22.283 - if (name.equals("equals") && mtype.returnType() == boolean.class && mtype.parameterCount() == 1 && mtype.parameterType(0) == Object.class)
22.284 - return true;
22.285 - return false;
22.286 - }
22.287 - /*non-public*/ boolean referenceKindIsConsistentWith(int originalRefKind) {
22.288 - int refKind = getReferenceKind();
22.289 - if (refKind == originalRefKind) return true;
22.290 - switch (originalRefKind) {
22.291 - case REF_invokeInterface:
22.292 - // Looking up an interface method, can get (e.g.) Object.hashCode
22.293 - assert(refKind == REF_invokeVirtual ||
22.294 - refKind == REF_invokeSpecial) : this;
22.295 - return true;
22.296 - case REF_invokeVirtual:
22.297 - case REF_newInvokeSpecial:
22.298 - // Looked up a virtual, can get (e.g.) final String.hashCode.
22.299 - assert(refKind == REF_invokeSpecial) : this;
22.300 - return true;
22.301 - }
22.302 - assert(false) : this+" != "+MethodHandleNatives.refKindName((byte)originalRefKind);
22.303 - return true;
22.304 - }
22.305 - private boolean staticIsConsistent() {
22.306 - byte refKind = getReferenceKind();
22.307 - return MethodHandleNatives.refKindIsStatic(refKind) == isStatic() || getModifiers() == 0;
22.308 - }
22.309 - private boolean vminfoIsConsistent() {
22.310 - byte refKind = getReferenceKind();
22.311 - assert(isResolved()); // else don't call
22.312 - Object vminfo = MethodHandleNatives.getMemberVMInfo(this);
22.313 - assert(vminfo instanceof Object[]);
22.314 - long vmindex = (Long) ((Object[])vminfo)[0];
22.315 - Object vmtarget = ((Object[])vminfo)[1];
22.316 - if (MethodHandleNatives.refKindIsField(refKind)) {
22.317 - assert(vmindex >= 0) : vmindex + ":" + this;
22.318 - assert(vmtarget instanceof Class);
22.319 - } else {
22.320 - if (MethodHandleNatives.refKindDoesDispatch(refKind))
22.321 - assert(vmindex >= 0) : vmindex + ":" + this;
22.322 - else
22.323 - assert(vmindex < 0) : vmindex;
22.324 - assert(vmtarget instanceof MemberName) : vmtarget + " in " + this;
22.325 - }
22.326 - return true;
22.327 - }
22.328 -
22.329 - private MemberName changeReferenceKind(byte refKind, byte oldKind) {
22.330 - assert(getReferenceKind() == oldKind);
22.331 - assert(MethodHandleNatives.refKindIsValid(refKind));
22.332 - flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT);
22.333 -// if (isConstructor() && refKind != REF_newInvokeSpecial)
22.334 -// flags += (IS_METHOD - IS_CONSTRUCTOR);
22.335 -// else if (refKind == REF_newInvokeSpecial && isMethod())
22.336 -// flags += (IS_CONSTRUCTOR - IS_METHOD);
22.337 - return this;
22.338 - }
22.339 -
22.340 - private boolean testFlags(int mask, int value) {
22.341 - return (flags & mask) == value;
22.342 - }
22.343 - private boolean testAllFlags(int mask) {
22.344 - return testFlags(mask, mask);
22.345 - }
22.346 - private boolean testAnyFlags(int mask) {
22.347 - return !testFlags(mask, 0);
22.348 - }
22.349 -
22.350 - /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */
22.351 - public boolean isMethodHandleInvoke() {
22.352 - final int bits = MH_INVOKE_MODS;
22.353 - final int negs = Modifier.STATIC;
22.354 - if (testFlags(bits | negs, bits) &&
22.355 - clazz == MethodHandle.class) {
22.356 - return isMethodHandleInvokeName(name);
22.357 - }
22.358 - return false;
22.359 - }
22.360 - public static boolean isMethodHandleInvokeName(String name) {
22.361 - return name.equals("invoke") || name.equals("invokeExact");
22.362 - }
22.363 - private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC;
22.364 -
22.365 - /** Utility method to query the modifier flags of this member. */
22.366 - public boolean isStatic() {
22.367 - return Modifier.isStatic(flags);
22.368 - }
22.369 - /** Utility method to query the modifier flags of this member. */
22.370 - public boolean isPublic() {
22.371 - return Modifier.isPublic(flags);
22.372 - }
22.373 - /** Utility method to query the modifier flags of this member. */
22.374 - public boolean isPrivate() {
22.375 - return Modifier.isPrivate(flags);
22.376 - }
22.377 - /** Utility method to query the modifier flags of this member. */
22.378 - public boolean isProtected() {
22.379 - return Modifier.isProtected(flags);
22.380 - }
22.381 - /** Utility method to query the modifier flags of this member. */
22.382 - public boolean isFinal() {
22.383 - return Modifier.isFinal(flags);
22.384 - }
22.385 - /** Utility method to query whether this member or its defining class is final. */
22.386 - public boolean canBeStaticallyBound() {
22.387 - return Modifier.isFinal(flags | clazz.getModifiers());
22.388 - }
22.389 - /** Utility method to query the modifier flags of this member. */
22.390 - public boolean isVolatile() {
22.391 - return Modifier.isVolatile(flags);
22.392 - }
22.393 - /** Utility method to query the modifier flags of this member. */
22.394 - public boolean isAbstract() {
22.395 - return Modifier.isAbstract(flags);
22.396 - }
22.397 - /** Utility method to query the modifier flags of this member. */
22.398 - public boolean isNative() {
22.399 - return Modifier.isNative(flags);
22.400 - }
22.401 - // let the rest (native, volatile, transient, etc.) be tested via Modifier.isFoo
22.402 -
22.403 - // unofficial modifier flags, used by HotSpot:
22.404 - static final int BRIDGE = 0x00000040;
22.405 - static final int VARARGS = 0x00000080;
22.406 - static final int SYNTHETIC = 0x00001000;
22.407 - static final int ANNOTATION= 0x00002000;
22.408 - static final int ENUM = 0x00004000;
22.409 - /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
22.410 - public boolean isBridge() {
22.411 - return testAllFlags(IS_METHOD | BRIDGE);
22.412 - }
22.413 - /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
22.414 - public boolean isVarargs() {
22.415 - return testAllFlags(VARARGS) && isInvocable();
22.416 - }
22.417 - /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */
22.418 - public boolean isSynthetic() {
22.419 - return testAllFlags(SYNTHETIC);
22.420 - }
22.421 -
22.422 - static final String CONSTRUCTOR_NAME = "<init>"; // the ever-popular
22.423 -
22.424 - // modifiers exported by the JVM:
22.425 - static final int RECOGNIZED_MODIFIERS = 0xFFFF;
22.426 -
22.427 - // private flags, not part of RECOGNIZED_MODIFIERS:
22.428 - static final int
22.429 - IS_METHOD = MN_IS_METHOD, // method (not constructor)
22.430 - IS_CONSTRUCTOR = MN_IS_CONSTRUCTOR, // constructor
22.431 - IS_FIELD = MN_IS_FIELD, // field
22.432 - IS_TYPE = MN_IS_TYPE, // nested type
22.433 - CALLER_SENSITIVE = MN_CALLER_SENSITIVE; // @CallerSensitive annotation detected
22.434 -
22.435 - static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED;
22.436 - static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE;
22.437 - static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR;
22.438 - static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD;
22.439 - static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES;
22.440 -
22.441 - /** Utility method to query whether this member is a method or constructor. */
22.442 - public boolean isInvocable() {
22.443 - return testAnyFlags(IS_INVOCABLE);
22.444 - }
22.445 - /** Utility method to query whether this member is a method, constructor, or field. */
22.446 - public boolean isFieldOrMethod() {
22.447 - return testAnyFlags(IS_FIELD_OR_METHOD);
22.448 - }
22.449 - /** Query whether this member is a method. */
22.450 - public boolean isMethod() {
22.451 - return testAllFlags(IS_METHOD);
22.452 - }
22.453 - /** Query whether this member is a constructor. */
22.454 - public boolean isConstructor() {
22.455 - return testAllFlags(IS_CONSTRUCTOR);
22.456 - }
22.457 - /** Query whether this member is a field. */
22.458 - public boolean isField() {
22.459 - return testAllFlags(IS_FIELD);
22.460 - }
22.461 - /** Query whether this member is a type. */
22.462 - public boolean isType() {
22.463 - return testAllFlags(IS_TYPE);
22.464 - }
22.465 - /** Utility method to query whether this member is neither public, private, nor protected. */
22.466 - public boolean isPackage() {
22.467 - return !testAnyFlags(ALL_ACCESS);
22.468 - }
22.469 - /** Query whether this member has a CallerSensitive annotation. */
22.470 - public boolean isCallerSensitive() {
22.471 - return testAllFlags(CALLER_SENSITIVE);
22.472 - }
22.473 -
22.474 - /** Utility method to query whether this member is accessible from a given lookup class. */
22.475 - public boolean isAccessibleFrom(Class<?> lookupClass) {
22.476 - return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags,
22.477 - lookupClass, ALL_ACCESS|MethodHandles.Lookup.PACKAGE);
22.478 - }
22.479 -
22.480 - /** Initialize a query. It is not resolved. */
22.481 - private void init(Class<?> defClass, String name, Object type, int flags) {
22.482 - // defining class is allowed to be null (for a naked name/type pair)
22.483 - //name.toString(); // null check
22.484 - //type.equals(type); // null check
22.485 - // fill in fields:
22.486 - this.clazz = defClass;
22.487 - this.name = name;
22.488 - this.type = type;
22.489 - this.flags = flags;
22.490 - assert(testAnyFlags(ALL_KINDS));
22.491 - assert(this.resolution == null); // nobody should have touched this yet
22.492 - //assert(referenceKindIsConsistent()); // do this after resolution
22.493 - }
22.494 -
22.495 - /**
22.496 - * Calls down to the VM to fill in the fields. This method is
22.497 - * synchronized to avoid racing calls.
22.498 - */
22.499 - private void expandFromVM() {
22.500 - if (type != null) {
22.501 - return;
22.502 - }
22.503 - if (!isResolved()) {
22.504 - return;
22.505 - }
22.506 - MethodHandleNatives.expand(this);
22.507 - }
22.508 -
22.509 - // Capturing information from the Core Reflection API:
22.510 - private static int flagsMods(int flags, int mods, byte refKind) {
22.511 - assert((flags & RECOGNIZED_MODIFIERS) == 0);
22.512 - assert((mods & ~RECOGNIZED_MODIFIERS) == 0);
22.513 - assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0);
22.514 - return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT);
22.515 - }
22.516 - /** Create a name for the given reflected method. The resulting name will be in a resolved state. */
22.517 - public MemberName(Method m) {
22.518 - this(m, false);
22.519 - }
22.520 - @SuppressWarnings("LeakingThisInConstructor")
22.521 - public MemberName(Method m, boolean wantSpecial) {
22.522 - m.getClass(); // NPE check
22.523 - // fill in vmtarget, vmindex while we have m in hand:
22.524 - MethodHandleNatives.init(this, m);
22.525 - if (clazz == null) { // MHN.init failed
22.526 - if (m.getDeclaringClass() == MethodHandle.class &&
22.527 - isMethodHandleInvokeName(m.getName())) {
22.528 - // The JVM did not reify this signature-polymorphic instance.
22.529 - // Need a special case here.
22.530 - // See comments on MethodHandleNatives.linkMethod.
22.531 - MethodType type = MethodType.methodType(m.getReturnType(), m.getParameterTypes());
22.532 - int flags = flagsMods(IS_METHOD, m.getModifiers(), REF_invokeVirtual);
22.533 - init(MethodHandle.class, m.getName(), type, flags);
22.534 - if (isMethodHandleInvoke())
22.535 - return;
22.536 - }
22.537 - throw new LinkageError(m.toString());
22.538 - }
22.539 - assert(isResolved() && this.clazz != null);
22.540 - this.name = m.getName();
22.541 - if (this.type == null)
22.542 - this.type = new Object[] { m.getReturnType(), m.getParameterTypes() };
22.543 - if (wantSpecial) {
22.544 - if (isAbstract())
22.545 - throw new AbstractMethodError(this.toString());
22.546 - if (getReferenceKind() == REF_invokeVirtual)
22.547 - changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
22.548 - else if (getReferenceKind() == REF_invokeInterface)
22.549 - // invokeSpecial on a default method
22.550 - changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
22.551 - }
22.552 - }
22.553 - public MemberName asSpecial() {
22.554 - switch (getReferenceKind()) {
22.555 - case REF_invokeSpecial: return this;
22.556 - case REF_invokeVirtual: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeVirtual);
22.557 - case REF_invokeInterface: return clone().changeReferenceKind(REF_invokeSpecial, REF_invokeInterface);
22.558 - case REF_newInvokeSpecial: return clone().changeReferenceKind(REF_invokeSpecial, REF_newInvokeSpecial);
22.559 - }
22.560 - throw new IllegalArgumentException(this.toString());
22.561 - }
22.562 - /** If this MN is not REF_newInvokeSpecial, return a clone with that ref. kind.
22.563 - * In that case it must already be REF_invokeSpecial.
22.564 - */
22.565 - public MemberName asConstructor() {
22.566 - switch (getReferenceKind()) {
22.567 - case REF_invokeSpecial: return clone().changeReferenceKind(REF_newInvokeSpecial, REF_invokeSpecial);
22.568 - case REF_newInvokeSpecial: return this;
22.569 - }
22.570 - throw new IllegalArgumentException(this.toString());
22.571 - }
22.572 - /** If this MN is a REF_invokeSpecial, return a clone with the "normal" kind
22.573 - * REF_invokeVirtual; also switch either to REF_invokeInterface if clazz.isInterface.
22.574 - * The end result is to get a fully virtualized version of the MN.
22.575 - * (Note that resolving in the JVM will sometimes devirtualize, changing
22.576 - * REF_invokeVirtual of a final to REF_invokeSpecial, and REF_invokeInterface
22.577 - * in some corner cases to either of the previous two; this transform
22.578 - * undoes that change under the assumption that it occurred.)
22.579 - */
22.580 - public MemberName asNormalOriginal() {
22.581 - byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual;
22.582 - byte refKind = getReferenceKind();
22.583 - byte newRefKind = refKind;
22.584 - MemberName result = this;
22.585 - switch (refKind) {
22.586 - case REF_invokeInterface:
22.587 - case REF_invokeVirtual:
22.588 - case REF_invokeSpecial:
22.589 - newRefKind = normalVirtual;
22.590 - break;
22.591 - }
22.592 - if (newRefKind == refKind)
22.593 - return this;
22.594 - result = clone().changeReferenceKind(newRefKind, refKind);
22.595 - assert(this.referenceKindIsConsistentWith(result.getReferenceKind()));
22.596 - return result;
22.597 - }
22.598 - /** Create a name for the given reflected constructor. The resulting name will be in a resolved state. */
22.599 - @SuppressWarnings("LeakingThisInConstructor")
22.600 - public MemberName(Constructor<?> ctor) {
22.601 - ctor.getClass(); // NPE check
22.602 - // fill in vmtarget, vmindex while we have ctor in hand:
22.603 - MethodHandleNatives.init(this, ctor);
22.604 - assert(isResolved() && this.clazz != null);
22.605 - this.name = CONSTRUCTOR_NAME;
22.606 - if (this.type == null)
22.607 - this.type = new Object[] { void.class, ctor.getParameterTypes() };
22.608 - }
22.609 - /** Create a name for the given reflected field. The resulting name will be in a resolved state.
22.610 - */
22.611 - public MemberName(Field fld) {
22.612 - this(fld, false);
22.613 - }
22.614 - @SuppressWarnings("LeakingThisInConstructor")
22.615 - public MemberName(Field fld, boolean makeSetter) {
22.616 - fld.getClass(); // NPE check
22.617 - // fill in vmtarget, vmindex while we have fld in hand:
22.618 - MethodHandleNatives.init(this, fld);
22.619 - assert(isResolved() && this.clazz != null);
22.620 - this.name = fld.getName();
22.621 - this.type = fld.getType();
22.622 - assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
22.623 - byte refKind = this.getReferenceKind();
22.624 - assert(refKind == (isStatic() ? REF_getStatic : REF_getField));
22.625 - if (makeSetter) {
22.626 - changeReferenceKind((byte)(refKind + (REF_putStatic - REF_getStatic)), refKind);
22.627 - }
22.628 - }
22.629 - public boolean isGetter() {
22.630 - return MethodHandleNatives.refKindIsGetter(getReferenceKind());
22.631 - }
22.632 - public boolean isSetter() {
22.633 - return MethodHandleNatives.refKindIsSetter(getReferenceKind());
22.634 - }
22.635 - public MemberName asSetter() {
22.636 - byte refKind = getReferenceKind();
22.637 - assert(MethodHandleNatives.refKindIsGetter(refKind));
22.638 - assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField));
22.639 - byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField));
22.640 - return clone().changeReferenceKind(setterRefKind, refKind);
22.641 - }
22.642 - /** Create a name for the given class. The resulting name will be in a resolved state. */
22.643 - public MemberName(Class<?> type) {
22.644 - init(type.getDeclaringClass(), type.getSimpleName(), type,
22.645 - flagsMods(IS_TYPE, type.getModifiers(), REF_NONE));
22.646 - initResolved(true);
22.647 - }
22.648 -
22.649 - /**
22.650 - * Create a name for a signature-polymorphic invoker.
22.651 - * This is a placeholder for a signature-polymorphic instance
22.652 - * (of MH.invokeExact, etc.) that the JVM does not reify.
22.653 - * See comments on {@link MethodHandleNatives#linkMethod}.
22.654 - */
22.655 - static MemberName makeMethodHandleInvoke(String name, MethodType type) {
22.656 - return makeMethodHandleInvoke(name, type, MH_INVOKE_MODS | SYNTHETIC);
22.657 - }
22.658 - static MemberName makeMethodHandleInvoke(String name, MethodType type, int mods) {
22.659 - MemberName mem = new MemberName(MethodHandle.class, name, type, REF_invokeVirtual);
22.660 - mem.flags |= mods; // it's not resolved, but add these modifiers anyway
22.661 - assert(mem.isMethodHandleInvoke()) : mem;
22.662 - return mem;
22.663 - }
22.664 -
22.665 - // bare-bones constructor; the JVM will fill it in
22.666 - MemberName() { }
22.667 -
22.668 - // locally useful cloner
22.669 - @Override protected MemberName clone() {
22.670 - try {
22.671 - return (MemberName) super.clone();
22.672 - } catch (CloneNotSupportedException ex) {
22.673 - throw newInternalError(ex);
22.674 - }
22.675 - }
22.676 -
22.677 - /** Get the definition of this member name.
22.678 - * This may be in a super-class of the declaring class of this member.
22.679 - */
22.680 - public MemberName getDefinition() {
22.681 - if (!isResolved()) throw new IllegalStateException("must be resolved: "+this);
22.682 - if (isType()) return this;
22.683 - MemberName res = this.clone();
22.684 - res.clazz = null;
22.685 - res.type = null;
22.686 - res.name = null;
22.687 - res.resolution = res;
22.688 - res.expandFromVM();
22.689 - assert(res.getName().equals(this.getName()));
22.690 - return res;
22.691 - }
22.692 -
22.693 - @Override
22.694 - public int hashCode() {
22.695 - return Objects.hash(clazz, getReferenceKind(), name, getType());
22.696 - }
22.697 - @Override
22.698 - public boolean equals(Object that) {
22.699 - return (that instanceof MemberName && this.equals((MemberName)that));
22.700 - }
22.701 -
22.702 - /** Decide if two member names have exactly the same symbolic content.
22.703 - * Does not take into account any actual class members, so even if
22.704 - * two member names resolve to the same actual member, they may
22.705 - * be distinct references.
22.706 - */
22.707 - public boolean equals(MemberName that) {
22.708 - if (this == that) return true;
22.709 - if (that == null) return false;
22.710 - return this.clazz == that.clazz
22.711 - && this.getReferenceKind() == that.getReferenceKind()
22.712 - && Objects.equals(this.name, that.name)
22.713 - && Objects.equals(this.getType(), that.getType());
22.714 - }
22.715 -
22.716 - // Construction from symbolic parts, for queries:
22.717 - /** Create a field or type name from the given components:
22.718 - * Declaring class, name, type, reference kind.
22.719 - * The declaring class may be supplied as null if this is to be a bare name and type.
22.720 - * The resulting name will in an unresolved state.
22.721 - */
22.722 - public MemberName(Class<?> defClass, String name, Class<?> type, byte refKind) {
22.723 - init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind));
22.724 - initResolved(false);
22.725 - }
22.726 - /** Create a field or type name from the given components: Declaring class, name, type.
22.727 - * The declaring class may be supplied as null if this is to be a bare name and type.
22.728 - * The modifier flags default to zero.
22.729 - * The resulting name will in an unresolved state.
22.730 - */
22.731 - public MemberName(Class<?> defClass, String name, Class<?> type, Void unused) {
22.732 - this(defClass, name, type, REF_NONE);
22.733 - initResolved(false);
22.734 - }
22.735 - /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers.
22.736 - * It will be a constructor if and only if the name is {@code "<init>"}.
22.737 - * The declaring class may be supplied as null if this is to be a bare name and type.
22.738 - * The last argument is optional, a boolean which requests REF_invokeSpecial.
22.739 - * The resulting name will in an unresolved state.
22.740 - */
22.741 - public MemberName(Class<?> defClass, String name, MethodType type, byte refKind) {
22.742 - int initFlags = (name != null && name.equals(CONSTRUCTOR_NAME) ? IS_CONSTRUCTOR : IS_METHOD);
22.743 - init(defClass, name, type, flagsMods(initFlags, 0, refKind));
22.744 - initResolved(false);
22.745 - }
22.746 - /** Create a method, constructor, or field name from the given components:
22.747 - * Reference kind, declaring class, name, type.
22.748 - */
22.749 - public MemberName(byte refKind, Class<?> defClass, String name, Object type) {
22.750 - int kindFlags;
22.751 - if (MethodHandleNatives.refKindIsField(refKind)) {
22.752 - kindFlags = IS_FIELD;
22.753 - if (!(type instanceof Class))
22.754 - throw newIllegalArgumentException("not a field type");
22.755 - } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
22.756 - kindFlags = IS_METHOD;
22.757 - if (!(type instanceof MethodType))
22.758 - throw newIllegalArgumentException("not a method type");
22.759 - } else if (refKind == REF_newInvokeSpecial) {
22.760 - kindFlags = IS_CONSTRUCTOR;
22.761 - if (!(type instanceof MethodType) ||
22.762 - !CONSTRUCTOR_NAME.equals(name))
22.763 - throw newIllegalArgumentException("not a constructor type or name");
22.764 - } else {
22.765 - throw newIllegalArgumentException("bad reference kind "+refKind);
22.766 - }
22.767 - init(defClass, name, type, flagsMods(kindFlags, 0, refKind));
22.768 - initResolved(false);
22.769 - }
22.770 - /** Query whether this member name is resolved to a non-static, non-final method.
22.771 - */
22.772 - public boolean hasReceiverTypeDispatch() {
22.773 - return MethodHandleNatives.refKindDoesDispatch(getReferenceKind());
22.774 - }
22.775 -
22.776 - /** Query whether this member name is resolved.
22.777 - * A resolved member name is one for which the JVM has found
22.778 - * a method, constructor, field, or type binding corresponding exactly to the name.
22.779 - * (Document?)
22.780 - */
22.781 - public boolean isResolved() {
22.782 - return resolution == null;
22.783 - }
22.784 -
22.785 - private void initResolved(boolean isResolved) {
22.786 - assert(this.resolution == null); // not initialized yet!
22.787 - if (!isResolved)
22.788 - this.resolution = this;
22.789 - assert(isResolved() == isResolved);
22.790 - }
22.791 -
22.792 - void checkForTypeAlias() {
22.793 - if (isInvocable()) {
22.794 - MethodType type;
22.795 - if (this.type instanceof MethodType)
22.796 - type = (MethodType) this.type;
22.797 - else
22.798 - this.type = type = getMethodType();
22.799 - if (type.erase() == type) return;
22.800 - if (VerifyAccess.isTypeVisible(type, clazz)) return;
22.801 - throw new LinkageError("bad method type alias: "+type+" not visible from "+clazz);
22.802 - } else {
22.803 - Class<?> type;
22.804 - if (this.type instanceof Class<?>)
22.805 - type = (Class<?>) this.type;
22.806 - else
22.807 - this.type = type = getFieldType();
22.808 - if (VerifyAccess.isTypeVisible(type, clazz)) return;
22.809 - throw new LinkageError("bad field type alias: "+type+" not visible from "+clazz);
22.810 - }
22.811 - }
22.812 -
22.813 -
22.814 - /** Produce a string form of this member name.
22.815 - * For types, it is simply the type's own string (as reported by {@code toString}).
22.816 - * For fields, it is {@code "DeclaringClass.name/type"}.
22.817 - * For methods and constructors, it is {@code "DeclaringClass.name(ptype...)rtype"}.
22.818 - * If the declaring class is null, the prefix {@code "DeclaringClass."} is omitted.
22.819 - * If the member is unresolved, a prefix {@code "*."} is prepended.
22.820 - */
22.821 - @SuppressWarnings("LocalVariableHidesMemberVariable")
22.822 - @Override
22.823 - public String toString() {
22.824 - if (isType())
22.825 - return type.toString(); // class java.lang.String
22.826 - // else it is a field, method, or constructor
22.827 - StringBuilder buf = new StringBuilder();
22.828 - if (getDeclaringClass() != null) {
22.829 - buf.append(getName(clazz));
22.830 - buf.append('.');
22.831 - }
22.832 - String name = getName();
22.833 - buf.append(name == null ? "*" : name);
22.834 - Object type = getType();
22.835 - if (!isInvocable()) {
22.836 - buf.append('/');
22.837 - buf.append(type == null ? "*" : getName(type));
22.838 - } else {
22.839 - buf.append(type == null ? "(*)*" : getName(type));
22.840 - }
22.841 - byte refKind = getReferenceKind();
22.842 - if (refKind != REF_NONE) {
22.843 - buf.append('/');
22.844 - buf.append(MethodHandleNatives.refKindName(refKind));
22.845 - }
22.846 - //buf.append("#").append(System.identityHashCode(this));
22.847 - return buf.toString();
22.848 - }
22.849 - private static String getName(Object obj) {
22.850 - if (obj instanceof Class<?>)
22.851 - return ((Class<?>)obj).getName();
22.852 - return String.valueOf(obj);
22.853 - }
22.854 -
22.855 - public IllegalAccessException makeAccessException(String message, Object from) {
22.856 - message = message + ": "+ toString();
22.857 - if (from != null) message += ", from " + from;
22.858 - return new IllegalAccessException(message);
22.859 - }
22.860 - private String message() {
22.861 - if (isResolved())
22.862 - return "no access";
22.863 - else if (isConstructor())
22.864 - return "no such constructor";
22.865 - else if (isMethod())
22.866 - return "no such method";
22.867 - else
22.868 - return "no such field";
22.869 - }
22.870 - public ReflectiveOperationException makeAccessException() {
22.871 - String message = message() + ": "+ toString();
22.872 - ReflectiveOperationException ex;
22.873 - if (isResolved() || !(resolution instanceof NoSuchMethodError ||
22.874 - resolution instanceof NoSuchFieldError))
22.875 - ex = new IllegalAccessException(message);
22.876 - else if (isConstructor())
22.877 - ex = new NoSuchMethodException(message);
22.878 - else if (isMethod())
22.879 - ex = new NoSuchMethodException(message);
22.880 - else
22.881 - ex = new NoSuchFieldException(message);
22.882 - if (resolution instanceof Throwable)
22.883 - ex.initCause((Throwable) resolution);
22.884 - return ex;
22.885 - }
22.886 -
22.887 - /** Actually making a query requires an access check. */
22.888 - /*non-public*/ static Factory getFactory() {
22.889 - return Factory.INSTANCE;
22.890 - }
22.891 - /** A factory type for resolving member names with the help of the VM.
22.892 - * TBD: Define access-safe public constructors for this factory.
22.893 - */
22.894 - /*non-public*/ static class Factory {
22.895 - private Factory() { } // singleton pattern
22.896 - static Factory INSTANCE = new Factory();
22.897 -
22.898 - private static int ALLOWED_FLAGS = ALL_KINDS;
22.899 -
22.900 - /// Queries
22.901 - List<MemberName> getMembers(Class<?> defc,
22.902 - String matchName, Object matchType,
22.903 - int matchFlags, Class<?> lookupClass) {
22.904 - matchFlags &= ALLOWED_FLAGS;
22.905 - String matchSig = null;
22.906 - if (matchType != null) {
22.907 - matchSig = BytecodeDescriptor.unparse(matchType);
22.908 - if (matchSig.startsWith("("))
22.909 - matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE);
22.910 - else
22.911 - matchFlags &= ~(ALL_KINDS & ~IS_FIELD);
22.912 - }
22.913 - final int BUF_MAX = 0x2000;
22.914 - int len1 = matchName == null ? 10 : matchType == null ? 4 : 1;
22.915 - MemberName[] buf = newMemberBuffer(len1);
22.916 - int totalCount = 0;
22.917 - ArrayList<MemberName[]> bufs = null;
22.918 - int bufCount = 0;
22.919 - for (;;) {
22.920 - bufCount = MethodHandleNatives.getMembers(defc,
22.921 - matchName, matchSig, matchFlags,
22.922 - lookupClass,
22.923 - totalCount, buf);
22.924 - if (bufCount <= buf.length) {
22.925 - if (bufCount < 0) bufCount = 0;
22.926 - totalCount += bufCount;
22.927 - break;
22.928 - }
22.929 - // JVM returned to us with an intentional overflow!
22.930 - totalCount += buf.length;
22.931 - int excess = bufCount - buf.length;
22.932 - if (bufs == null) bufs = new ArrayList<>(1);
22.933 - bufs.add(buf);
22.934 - int len2 = buf.length;
22.935 - len2 = Math.max(len2, excess);
22.936 - len2 = Math.max(len2, totalCount / 4);
22.937 - buf = newMemberBuffer(Math.min(BUF_MAX, len2));
22.938 - }
22.939 - ArrayList<MemberName> result = new ArrayList<>(totalCount);
22.940 - if (bufs != null) {
22.941 - for (MemberName[] buf0 : bufs) {
22.942 - Collections.addAll(result, buf0);
22.943 - }
22.944 - }
22.945 - result.addAll(Arrays.asList(buf).subList(0, bufCount));
22.946 - // Signature matching is not the same as type matching, since
22.947 - // one signature might correspond to several types.
22.948 - // So if matchType is a Class or MethodType, refilter the results.
22.949 - if (matchType != null && matchType != matchSig) {
22.950 - for (Iterator<MemberName> it = result.iterator(); it.hasNext();) {
22.951 - MemberName m = it.next();
22.952 - if (!matchType.equals(m.getType()))
22.953 - it.remove();
22.954 - }
22.955 - }
22.956 - return result;
22.957 - }
22.958 - /** Produce a resolved version of the given member.
22.959 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.960 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.961 - * If lookup fails or access is not permitted, null is returned.
22.962 - * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
22.963 - */
22.964 - private MemberName resolve(byte refKind, MemberName ref, Class<?> lookupClass) {
22.965 - MemberName m = ref.clone(); // JVM will side-effect the ref
22.966 - assert(refKind == m.getReferenceKind());
22.967 - try {
22.968 - m = MethodHandleNatives.resolve(m, lookupClass);
22.969 - m.checkForTypeAlias();
22.970 - m.resolution = null;
22.971 - } catch (LinkageError ex) {
22.972 - // JVM reports that the "bytecode behavior" would get an error
22.973 - assert(!m.isResolved());
22.974 - m.resolution = ex;
22.975 - return m;
22.976 - }
22.977 - assert(m.referenceKindIsConsistent());
22.978 - m.initResolved(true);
22.979 - assert(m.vminfoIsConsistent());
22.980 - return m;
22.981 - }
22.982 - /** Produce a resolved version of the given member.
22.983 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.984 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.985 - * If lookup fails or access is not permitted, a {@linkplain ReflectiveOperationException} is thrown.
22.986 - * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
22.987 - */
22.988 - public
22.989 - <NoSuchMemberException extends ReflectiveOperationException>
22.990 - MemberName resolveOrFail(byte refKind, MemberName m, Class<?> lookupClass,
22.991 - Class<NoSuchMemberException> nsmClass)
22.992 - throws IllegalAccessException, NoSuchMemberException {
22.993 - MemberName result = resolve(refKind, m, lookupClass);
22.994 - if (result.isResolved())
22.995 - return result;
22.996 - ReflectiveOperationException ex = result.makeAccessException();
22.997 - if (ex instanceof IllegalAccessException) throw (IllegalAccessException) ex;
22.998 - throw nsmClass.cast(ex);
22.999 - }
22.1000 - /** Produce a resolved version of the given member.
22.1001 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1002 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1003 - * If lookup fails or access is not permitted, return null.
22.1004 - * Otherwise a fresh copy of the given member is returned, with modifier bits filled in.
22.1005 - */
22.1006 - public
22.1007 - MemberName resolveOrNull(byte refKind, MemberName m, Class<?> lookupClass) {
22.1008 - MemberName result = resolve(refKind, m, lookupClass);
22.1009 - if (result.isResolved())
22.1010 - return result;
22.1011 - return null;
22.1012 - }
22.1013 - /** Return a list of all methods defined by the given class.
22.1014 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1015 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1016 - * Inaccessible members are not added to the last.
22.1017 - */
22.1018 - public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
22.1019 - Class<?> lookupClass) {
22.1020 - return getMethods(defc, searchSupers, null, null, lookupClass);
22.1021 - }
22.1022 - /** Return a list of matching methods defined by the given class.
22.1023 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1024 - * Returned methods will match the name (if not null) and the type (if not null).
22.1025 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1026 - * Inaccessible members are not added to the last.
22.1027 - */
22.1028 - public List<MemberName> getMethods(Class<?> defc, boolean searchSupers,
22.1029 - String name, MethodType type, Class<?> lookupClass) {
22.1030 - int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
22.1031 - return getMembers(defc, name, type, matchFlags, lookupClass);
22.1032 - }
22.1033 - /** Return a list of all constructors defined by the given class.
22.1034 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1035 - * Inaccessible members are not added to the last.
22.1036 - */
22.1037 - public List<MemberName> getConstructors(Class<?> defc, Class<?> lookupClass) {
22.1038 - return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass);
22.1039 - }
22.1040 - /** Return a list of all fields defined by the given class.
22.1041 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1042 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1043 - * Inaccessible members are not added to the last.
22.1044 - */
22.1045 - public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
22.1046 - Class<?> lookupClass) {
22.1047 - return getFields(defc, searchSupers, null, null, lookupClass);
22.1048 - }
22.1049 - /** Return a list of all fields defined by the given class.
22.1050 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1051 - * Returned fields will match the name (if not null) and the type (if not null).
22.1052 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1053 - * Inaccessible members are not added to the last.
22.1054 - */
22.1055 - public List<MemberName> getFields(Class<?> defc, boolean searchSupers,
22.1056 - String name, Class<?> type, Class<?> lookupClass) {
22.1057 - int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0);
22.1058 - return getMembers(defc, name, type, matchFlags, lookupClass);
22.1059 - }
22.1060 - /** Return a list of all nested types defined by the given class.
22.1061 - * Super types are searched (for inherited members) if {@code searchSupers} is true.
22.1062 - * Access checking is performed on behalf of the given {@code lookupClass}.
22.1063 - * Inaccessible members are not added to the last.
22.1064 - */
22.1065 - public List<MemberName> getNestedTypes(Class<?> defc, boolean searchSupers,
22.1066 - Class<?> lookupClass) {
22.1067 - int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0);
22.1068 - return getMembers(defc, null, null, matchFlags, lookupClass);
22.1069 - }
22.1070 - private static MemberName[] newMemberBuffer(int length) {
22.1071 - MemberName[] buf = new MemberName[length];
22.1072 - // fill the buffer with dummy structs for the JVM to fill in
22.1073 - for (int i = 0; i < length; i++)
22.1074 - buf[i] = new MemberName();
22.1075 - return buf;
22.1076 - }
22.1077 - }
22.1078 -
22.1079 -// static {
22.1080 -// System.out.println("Hello world! My methods are:");
22.1081 -// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
22.1082 -// }
22.1083 -}
23.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandle.java Sun Aug 17 20:09:05 2014 +0200
23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
23.3 @@ -1,1494 +0,0 @@
23.4 -/*
23.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
23.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
23.7 - *
23.8 - * This code is free software; you can redistribute it and/or modify it
23.9 - * under the terms of the GNU General Public License version 2 only, as
23.10 - * published by the Free Software Foundation. Oracle designates this
23.11 - * particular file as subject to the "Classpath" exception as provided
23.12 - * by Oracle in the LICENSE file that accompanied this code.
23.13 - *
23.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
23.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23.17 - * version 2 for more details (a copy is included in the LICENSE file that
23.18 - * accompanied this code).
23.19 - *
23.20 - * You should have received a copy of the GNU General Public License version
23.21 - * 2 along with this work; if not, write to the Free Software Foundation,
23.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23.23 - *
23.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23.25 - * or visit www.oracle.com if you need additional information or have any
23.26 - * questions.
23.27 - */
23.28 -
23.29 -package java.lang.invoke;
23.30 -
23.31 -
23.32 -import java.util.*;
23.33 -import sun.invoke.util.*;
23.34 -
23.35 -import static java.lang.invoke.MethodHandleStatics.*;
23.36 -import java.util.logging.Level;
23.37 -import java.util.logging.Logger;
23.38 -
23.39 -/**
23.40 - * A method handle is a typed, directly executable reference to an underlying method,
23.41 - * constructor, field, or similar low-level operation, with optional
23.42 - * transformations of arguments or return values.
23.43 - * These transformations are quite general, and include such patterns as
23.44 - * {@linkplain #asType conversion},
23.45 - * {@linkplain #bindTo insertion},
23.46 - * {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
23.47 - * and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
23.48 - *
23.49 - * <h1>Method handle contents</h1>
23.50 - * Method handles are dynamically and strongly typed according to their parameter and return types.
23.51 - * They are not distinguished by the name or the defining class of their underlying methods.
23.52 - * A method handle must be invoked using a symbolic type descriptor which matches
23.53 - * the method handle's own {@linkplain #type type descriptor}.
23.54 - * <p>
23.55 - * Every method handle reports its type descriptor via the {@link #type type} accessor.
23.56 - * This type descriptor is a {@link java.lang.invoke.MethodType MethodType} object,
23.57 - * whose structure is a series of classes, one of which is
23.58 - * the return type of the method (or {@code void.class} if none).
23.59 - * <p>
23.60 - * A method handle's type controls the types of invocations it accepts,
23.61 - * and the kinds of transformations that apply to it.
23.62 - * <p>
23.63 - * A method handle contains a pair of special invoker methods
23.64 - * called {@link #invokeExact invokeExact} and {@link #invoke invoke}.
23.65 - * Both invoker methods provide direct access to the method handle's
23.66 - * underlying method, constructor, field, or other operation,
23.67 - * as modified by transformations of arguments and return values.
23.68 - * Both invokers accept calls which exactly match the method handle's own type.
23.69 - * The plain, inexact invoker also accepts a range of other call types.
23.70 - * <p>
23.71 - * Method handles are immutable and have no visible state.
23.72 - * Of course, they can be bound to underlying methods or data which exhibit state.
23.73 - * With respect to the Java Memory Model, any method handle will behave
23.74 - * as if all of its (internal) fields are final variables. This means that any method
23.75 - * handle made visible to the application will always be fully formed.
23.76 - * This is true even if the method handle is published through a shared
23.77 - * variable in a data race.
23.78 - * <p>
23.79 - * Method handles cannot be subclassed by the user.
23.80 - * Implementations may (or may not) create internal subclasses of {@code MethodHandle}
23.81 - * which may be visible via the {@link java.lang.Object#getClass Object.getClass}
23.82 - * operation. The programmer should not draw conclusions about a method handle
23.83 - * from its specific class, as the method handle class hierarchy (if any)
23.84 - * may change from time to time or across implementations from different vendors.
23.85 - *
23.86 - * <h1>Method handle compilation</h1>
23.87 - * A Java method call expression naming {@code invokeExact} or {@code invoke}
23.88 - * can invoke a method handle from Java source code.
23.89 - * From the viewpoint of source code, these methods can take any arguments
23.90 - * and their result can be cast to any return type.
23.91 - * Formally this is accomplished by giving the invoker methods
23.92 - * {@code Object} return types and variable arity {@code Object} arguments,
23.93 - * but they have an additional quality called <em>signature polymorphism</em>
23.94 - * which connects this freedom of invocation directly to the JVM execution stack.
23.95 - * <p>
23.96 - * As is usual with virtual methods, source-level calls to {@code invokeExact}
23.97 - * and {@code invoke} compile to an {@code invokevirtual} instruction.
23.98 - * More unusually, the compiler must record the actual argument types,
23.99 - * and may not perform method invocation conversions on the arguments.
23.100 - * Instead, it must push them on the stack according to their own unconverted types.
23.101 - * The method handle object itself is pushed on the stack before the arguments.
23.102 - * The compiler then calls the method handle with a symbolic type descriptor which
23.103 - * describes the argument and return types.
23.104 - * <p>
23.105 - * To issue a complete symbolic type descriptor, the compiler must also determine
23.106 - * the return type. This is based on a cast on the method invocation expression,
23.107 - * if there is one, or else {@code Object} if the invocation is an expression
23.108 - * or else {@code void} if the invocation is a statement.
23.109 - * The cast may be to a primitive type (but not {@code void}).
23.110 - * <p>
23.111 - * As a corner case, an uncasted {@code null} argument is given
23.112 - * a symbolic type descriptor of {@code java.lang.Void}.
23.113 - * The ambiguity with the type {@code Void} is harmless, since there are no references of type
23.114 - * {@code Void} except the null reference.
23.115 - *
23.116 - * <h1>Method handle invocation</h1>
23.117 - * The first time a {@code invokevirtual} instruction is executed
23.118 - * it is linked, by symbolically resolving the names in the instruction
23.119 - * and verifying that the method call is statically legal.
23.120 - * This is true of calls to {@code invokeExact} and {@code invoke}.
23.121 - * In this case, the symbolic type descriptor emitted by the compiler is checked for
23.122 - * correct syntax and names it contains are resolved.
23.123 - * Thus, an {@code invokevirtual} instruction which invokes
23.124 - * a method handle will always link, as long
23.125 - * as the symbolic type descriptor is syntactically well-formed
23.126 - * and the types exist.
23.127 - * <p>
23.128 - * When the {@code invokevirtual} is executed after linking,
23.129 - * the receiving method handle's type is first checked by the JVM
23.130 - * to ensure that it matches the symbolic type descriptor.
23.131 - * If the type match fails, it means that the method which the
23.132 - * caller is invoking is not present on the individual
23.133 - * method handle being invoked.
23.134 - * <p>
23.135 - * In the case of {@code invokeExact}, the type descriptor of the invocation
23.136 - * (after resolving symbolic type names) must exactly match the method type
23.137 - * of the receiving method handle.
23.138 - * In the case of plain, inexact {@code invoke}, the resolved type descriptor
23.139 - * must be a valid argument to the receiver's {@link #asType asType} method.
23.140 - * Thus, plain {@code invoke} is more permissive than {@code invokeExact}.
23.141 - * <p>
23.142 - * After type matching, a call to {@code invokeExact} directly
23.143 - * and immediately invoke the method handle's underlying method
23.144 - * (or other behavior, as the case may be).
23.145 - * <p>
23.146 - * A call to plain {@code invoke} works the same as a call to
23.147 - * {@code invokeExact}, if the symbolic type descriptor specified by the caller
23.148 - * exactly matches the method handle's own type.
23.149 - * If there is a type mismatch, {@code invoke} attempts
23.150 - * to adjust the type of the receiving method handle,
23.151 - * as if by a call to {@link #asType asType},
23.152 - * to obtain an exactly invokable method handle {@code M2}.
23.153 - * This allows a more powerful negotiation of method type
23.154 - * between caller and callee.
23.155 - * <p>
23.156 - * (<em>Note:</em> The adjusted method handle {@code M2} is not directly observable,
23.157 - * and implementations are therefore not required to materialize it.)
23.158 - *
23.159 - * <h1>Invocation checking</h1>
23.160 - * In typical programs, method handle type matching will usually succeed.
23.161 - * But if a match fails, the JVM will throw a {@link WrongMethodTypeException},
23.162 - * either directly (in the case of {@code invokeExact}) or indirectly as if
23.163 - * by a failed call to {@code asType} (in the case of {@code invoke}).
23.164 - * <p>
23.165 - * Thus, a method type mismatch which might show up as a linkage error
23.166 - * in a statically typed program can show up as
23.167 - * a dynamic {@code WrongMethodTypeException}
23.168 - * in a program which uses method handles.
23.169 - * <p>
23.170 - * Because method types contain "live" {@code Class} objects,
23.171 - * method type matching takes into account both types names and class loaders.
23.172 - * Thus, even if a method handle {@code M} is created in one
23.173 - * class loader {@code L1} and used in another {@code L2},
23.174 - * method handle calls are type-safe, because the caller's symbolic type
23.175 - * descriptor, as resolved in {@code L2},
23.176 - * is matched against the original callee method's symbolic type descriptor,
23.177 - * as resolved in {@code L1}.
23.178 - * The resolution in {@code L1} happens when {@code M} is created
23.179 - * and its type is assigned, while the resolution in {@code L2} happens
23.180 - * when the {@code invokevirtual} instruction is linked.
23.181 - * <p>
23.182 - * Apart from the checking of type descriptors,
23.183 - * a method handle's capability to call its underlying method is unrestricted.
23.184 - * If a method handle is formed on a non-public method by a class
23.185 - * that has access to that method, the resulting handle can be used
23.186 - * in any place by any caller who receives a reference to it.
23.187 - * <p>
23.188 - * Unlike with the Core Reflection API, where access is checked every time
23.189 - * a reflective method is invoked,
23.190 - * method handle access checking is performed
23.191 - * <a href="MethodHandles.Lookup.html#access">when the method handle is created</a>.
23.192 - * In the case of {@code ldc} (see below), access checking is performed as part of linking
23.193 - * the constant pool entry underlying the constant method handle.
23.194 - * <p>
23.195 - * Thus, handles to non-public methods, or to methods in non-public classes,
23.196 - * should generally be kept secret.
23.197 - * They should not be passed to untrusted code unless their use from
23.198 - * the untrusted code would be harmless.
23.199 - *
23.200 - * <h1>Method handle creation</h1>
23.201 - * Java code can create a method handle that directly accesses
23.202 - * any method, constructor, or field that is accessible to that code.
23.203 - * This is done via a reflective, capability-based API called
23.204 - * {@link java.lang.invoke.MethodHandles.Lookup MethodHandles.Lookup}
23.205 - * For example, a static method handle can be obtained
23.206 - * from {@link java.lang.invoke.MethodHandles.Lookup#findStatic Lookup.findStatic}.
23.207 - * There are also conversion methods from Core Reflection API objects,
23.208 - * such as {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
23.209 - * <p>
23.210 - * Like classes and strings, method handles that correspond to accessible
23.211 - * fields, methods, and constructors can also be represented directly
23.212 - * in a class file's constant pool as constants to be loaded by {@code ldc} bytecodes.
23.213 - * A new type of constant pool entry, {@code CONSTANT_MethodHandle},
23.214 - * refers directly to an associated {@code CONSTANT_Methodref},
23.215 - * {@code CONSTANT_InterfaceMethodref}, or {@code CONSTANT_Fieldref}
23.216 - * constant pool entry.
23.217 - * (For full details on method handle constants,
23.218 - * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
23.219 - * <p>
23.220 - * Method handles produced by lookups or constant loads from methods or
23.221 - * constructors with the variable arity modifier bit ({@code 0x0080})
23.222 - * have a corresponding variable arity, as if they were defined with
23.223 - * the help of {@link #asVarargsCollector asVarargsCollector}.
23.224 - * <p>
23.225 - * A method reference may refer either to a static or non-static method.
23.226 - * In the non-static case, the method handle type includes an explicit
23.227 - * receiver argument, prepended before any other arguments.
23.228 - * In the method handle's type, the initial receiver argument is typed
23.229 - * according to the class under which the method was initially requested.
23.230 - * (E.g., if a non-static method handle is obtained via {@code ldc},
23.231 - * the type of the receiver is the class named in the constant pool entry.)
23.232 - * <p>
23.233 - * Method handle constants are subject to the same link-time access checks
23.234 - * their corresponding bytecode instructions, and the {@code ldc} instruction
23.235 - * will throw corresponding linkage errors if the bytecode behaviors would
23.236 - * throw such errors.
23.237 - * <p>
23.238 - * As a corollary of this, access to protected members is restricted
23.239 - * to receivers only of the accessing class, or one of its subclasses,
23.240 - * and the accessing class must in turn be a subclass (or package sibling)
23.241 - * of the protected member's defining class.
23.242 - * If a method reference refers to a protected non-static method or field
23.243 - * of a class outside the current package, the receiver argument will
23.244 - * be narrowed to the type of the accessing class.
23.245 - * <p>
23.246 - * When a method handle to a virtual method is invoked, the method is
23.247 - * always looked up in the receiver (that is, the first argument).
23.248 - * <p>
23.249 - * A non-virtual method handle to a specific virtual method implementation
23.250 - * can also be created. These do not perform virtual lookup based on
23.251 - * receiver type. Such a method handle simulates the effect of
23.252 - * an {@code invokespecial} instruction to the same method.
23.253 - *
23.254 - * <h1>Usage examples</h1>
23.255 - * Here are some examples of usage:
23.256 - * <blockquote><pre>{@code
23.257 -Object x, y; String s; int i;
23.258 -MethodType mt; MethodHandle mh;
23.259 -MethodHandles.Lookup lookup = MethodHandles.lookup();
23.260 -// mt is (char,char)String
23.261 -mt = MethodType.methodType(String.class, char.class, char.class);
23.262 -mh = lookup.findVirtual(String.class, "replace", mt);
23.263 -s = (String) mh.invokeExact("daddy",'d','n');
23.264 -// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
23.265 -assertEquals(s, "nanny");
23.266 -// weakly typed invocation (using MHs.invoke)
23.267 -s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
23.268 -assertEquals(s, "savvy");
23.269 -// mt is (Object[])List
23.270 -mt = MethodType.methodType(java.util.List.class, Object[].class);
23.271 -mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
23.272 -assert(mh.isVarargsCollector());
23.273 -x = mh.invoke("one", "two");
23.274 -// invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
23.275 -assertEquals(x, java.util.Arrays.asList("one","two"));
23.276 -// mt is (Object,Object,Object)Object
23.277 -mt = MethodType.genericMethodType(3);
23.278 -mh = mh.asType(mt);
23.279 -x = mh.invokeExact((Object)1, (Object)2, (Object)3);
23.280 -// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
23.281 -assertEquals(x, java.util.Arrays.asList(1,2,3));
23.282 -// mt is ()int
23.283 -mt = MethodType.methodType(int.class);
23.284 -mh = lookup.findVirtual(java.util.List.class, "size", mt);
23.285 -i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
23.286 -// invokeExact(Ljava/util/List;)I
23.287 -assert(i == 3);
23.288 -mt = MethodType.methodType(void.class, String.class);
23.289 -mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
23.290 -mh.invokeExact(System.out, "Hello, world.");
23.291 -// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
23.292 - * }</pre></blockquote>
23.293 - * Each of the above calls to {@code invokeExact} or plain {@code invoke}
23.294 - * generates a single invokevirtual instruction with
23.295 - * the symbolic type descriptor indicated in the following comment.
23.296 - * In these examples, the helper method {@code assertEquals} is assumed to
23.297 - * be a method which calls {@link java.util.Objects#equals(Object,Object) Objects.equals}
23.298 - * on its arguments, and asserts that the result is true.
23.299 - *
23.300 - * <h1>Exceptions</h1>
23.301 - * The methods {@code invokeExact} and {@code invoke} are declared
23.302 - * to throw {@link java.lang.Throwable Throwable},
23.303 - * which is to say that there is no static restriction on what a method handle
23.304 - * can throw. Since the JVM does not distinguish between checked
23.305 - * and unchecked exceptions (other than by their class, of course),
23.306 - * there is no particular effect on bytecode shape from ascribing
23.307 - * checked exceptions to method handle invocations. But in Java source
23.308 - * code, methods which perform method handle calls must either explicitly
23.309 - * throw {@code Throwable}, or else must catch all
23.310 - * throwables locally, rethrowing only those which are legal in the context,
23.311 - * and wrapping ones which are illegal.
23.312 - *
23.313 - * <h1><a name="sigpoly"></a>Signature polymorphism</h1>
23.314 - * The unusual compilation and linkage behavior of
23.315 - * {@code invokeExact} and plain {@code invoke}
23.316 - * is referenced by the term <em>signature polymorphism</em>.
23.317 - * As defined in the Java Language Specification,
23.318 - * a signature polymorphic method is one which can operate with
23.319 - * any of a wide range of call signatures and return types.
23.320 - * <p>
23.321 - * In source code, a call to a signature polymorphic method will
23.322 - * compile, regardless of the requested symbolic type descriptor.
23.323 - * As usual, the Java compiler emits an {@code invokevirtual}
23.324 - * instruction with the given symbolic type descriptor against the named method.
23.325 - * The unusual part is that the symbolic type descriptor is derived from
23.326 - * the actual argument and return types, not from the method declaration.
23.327 - * <p>
23.328 - * When the JVM processes bytecode containing signature polymorphic calls,
23.329 - * it will successfully link any such call, regardless of its symbolic type descriptor.
23.330 - * (In order to retain type safety, the JVM will guard such calls with suitable
23.331 - * dynamic type checks, as described elsewhere.)
23.332 - * <p>
23.333 - * Bytecode generators, including the compiler back end, are required to emit
23.334 - * untransformed symbolic type descriptors for these methods.
23.335 - * Tools which determine symbolic linkage are required to accept such
23.336 - * untransformed descriptors, without reporting linkage errors.
23.337 - *
23.338 - * <h1>Interoperation between method handles and the Core Reflection API</h1>
23.339 - * Using factory methods in the {@link java.lang.invoke.MethodHandles.Lookup Lookup} API,
23.340 - * any class member represented by a Core Reflection API object
23.341 - * can be converted to a behaviorally equivalent method handle.
23.342 - * For example, a reflective {@link java.lang.reflect.Method Method} can
23.343 - * be converted to a method handle using
23.344 - * {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect}.
23.345 - * The resulting method handles generally provide more direct and efficient
23.346 - * access to the underlying class members.
23.347 - * <p>
23.348 - * As a special case,
23.349 - * when the Core Reflection API is used to view the signature polymorphic
23.350 - * methods {@code invokeExact} or plain {@code invoke} in this class,
23.351 - * they appear as ordinary non-polymorphic methods.
23.352 - * Their reflective appearance, as viewed by
23.353 - * {@link java.lang.Class#getDeclaredMethod Class.getDeclaredMethod},
23.354 - * is unaffected by their special status in this API.
23.355 - * For example, {@link java.lang.reflect.Method#getModifiers Method.getModifiers}
23.356 - * will report exactly those modifier bits required for any similarly
23.357 - * declared method, including in this case {@code native} and {@code varargs} bits.
23.358 - * <p>
23.359 - * As with any reflected method, these methods (when reflected) may be
23.360 - * invoked via {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.
23.361 - * However, such reflective calls do not result in method handle invocations.
23.362 - * Such a call, if passed the required argument
23.363 - * (a single one, of type {@code Object[]}), will ignore the argument and
23.364 - * will throw an {@code UnsupportedOperationException}.
23.365 - * <p>
23.366 - * Since {@code invokevirtual} instructions can natively
23.367 - * invoke method handles under any symbolic type descriptor, this reflective view conflicts
23.368 - * with the normal presentation of these methods via bytecodes.
23.369 - * Thus, these two native methods, when reflectively viewed by
23.370 - * {@code Class.getDeclaredMethod}, may be regarded as placeholders only.
23.371 - * <p>
23.372 - * In order to obtain an invoker method for a particular type descriptor,
23.373 - * use {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker},
23.374 - * or {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}.
23.375 - * The {@link java.lang.invoke.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
23.376 - * API is also able to return a method handle
23.377 - * to call {@code invokeExact} or plain {@code invoke},
23.378 - * for any specified type descriptor .
23.379 - *
23.380 - * <h1>Interoperation between method handles and Java generics</h1>
23.381 - * A method handle can be obtained on a method, constructor, or field
23.382 - * which is declared with Java generic types.
23.383 - * As with the Core Reflection API, the type of the method handle
23.384 - * will constructed from the erasure of the source-level type.
23.385 - * When a method handle is invoked, the types of its arguments
23.386 - * or the return value cast type may be generic types or type instances.
23.387 - * If this occurs, the compiler will replace those
23.388 - * types by their erasures when it constructs the symbolic type descriptor
23.389 - * for the {@code invokevirtual} instruction.
23.390 - * <p>
23.391 - * Method handles do not represent
23.392 - * their function-like types in terms of Java parameterized (generic) types,
23.393 - * because there are three mismatches between function-like types and parameterized
23.394 - * Java types.
23.395 - * <ul>
23.396 - * <li>Method types range over all possible arities,
23.397 - * from no arguments to up to the <a href="MethodHandle.html#maxarity">maximum number</a> of allowed arguments.
23.398 - * Generics are not variadic, and so cannot represent this.</li>
23.399 - * <li>Method types can specify arguments of primitive types,
23.400 - * which Java generic types cannot range over.</li>
23.401 - * <li>Higher order functions over method handles (combinators) are
23.402 - * often generic across a wide range of function types, including
23.403 - * those of multiple arities. It is impossible to represent such
23.404 - * genericity with a Java type parameter.</li>
23.405 - * </ul>
23.406 - *
23.407 - * <h1><a name="maxarity"></a>Arity limits</h1>
23.408 - * The JVM imposes on all methods and constructors of any kind an absolute
23.409 - * limit of 255 stacked arguments. This limit can appear more restrictive
23.410 - * in certain cases:
23.411 - * <ul>
23.412 - * <li>A {@code long} or {@code double} argument counts (for purposes of arity limits) as two argument slots.
23.413 - * <li>A non-static method consumes an extra argument for the object on which the method is called.
23.414 - * <li>A constructor consumes an extra argument for the object which is being constructed.
23.415 - * <li>Since a method handle’s {@code invoke} method (or other signature-polymorphic method) is non-virtual,
23.416 - * it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object.
23.417 - * </ul>
23.418 - * These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments.
23.419 - * For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it.
23.420 - * Attempts to create method handles with impossible method types lead to an {@link IllegalArgumentException}.
23.421 - * In particular, a method handle’s type must not have an arity of the exact maximum 255.
23.422 - *
23.423 - * @see MethodType
23.424 - * @see MethodHandles
23.425 - * @author John Rose, JSR 292 EG
23.426 - */
23.427 -public abstract class MethodHandle {
23.428 - static { MethodHandleImpl.initStatics(); }
23.429 -
23.430 - /**
23.431 - * Internal marker interface which distinguishes (to the Java compiler)
23.432 - * those methods which are <a href="MethodHandle.html#sigpoly">signature polymorphic</a>.
23.433 - */
23.434 - @java.lang.annotation.Target({java.lang.annotation.ElementType.METHOD})
23.435 - @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
23.436 - @interface PolymorphicSignature { }
23.437 -
23.438 - private final MethodType type;
23.439 - /*private*/ LambdaForm form;
23.440 - // form is not private so that invokers can easily fetch it
23.441 - /*private*/ MethodHandle asTypeCache;
23.442 - // asTypeCache is not private so that invokers can easily fetch it
23.443 -
23.444 - /**
23.445 - * Reports the type of this method handle.
23.446 - * Every invocation of this method handle via {@code invokeExact} must exactly match this type.
23.447 - * @return the method handle type
23.448 - */
23.449 - public MethodType type() {
23.450 - return type;
23.451 - }
23.452 -
23.453 - /**
23.454 - * Package-private constructor for the method handle implementation hierarchy.
23.455 - * Method handle inheritance will be contained completely within
23.456 - * the {@code java.lang.invoke} package.
23.457 - */
23.458 - // @param type type (permanently assigned) of the new method handle
23.459 - /*non-public*/ MethodHandle(MethodType type, LambdaForm form) {
23.460 - type.getClass(); // explicit NPE
23.461 - form.getClass(); // explicit NPE
23.462 - this.type = type;
23.463 - this.form = form;
23.464 -
23.465 - form.prepare(); // TO DO: Try to delay this step until just before invocation.
23.466 - }
23.467 -
23.468 - /**
23.469 - * Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match.
23.470 - * The symbolic type descriptor at the call site of {@code invokeExact} must
23.471 - * exactly match this method handle's {@link #type type}.
23.472 - * No conversions are allowed on arguments or return values.
23.473 - * <p>
23.474 - * When this method is observed via the Core Reflection API,
23.475 - * it will appear as a single native method, taking an object array and returning an object.
23.476 - * If this native method is invoked directly via
23.477 - * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
23.478 - * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
23.479 - * it will throw an {@code UnsupportedOperationException}.
23.480 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.481 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.482 - * @throws WrongMethodTypeException if the target's type is not identical with the caller's symbolic type descriptor
23.483 - * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
23.484 - */
23.485 - public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;
23.486 -
23.487 - /**
23.488 - * Invokes the method handle, allowing any caller type descriptor,
23.489 - * and optionally performing conversions on arguments and return values.
23.490 - * <p>
23.491 - * If the call site's symbolic type descriptor exactly matches this method handle's {@link #type type},
23.492 - * the call proceeds as if by {@link #invokeExact invokeExact}.
23.493 - * <p>
23.494 - * Otherwise, the call proceeds as if this method handle were first
23.495 - * adjusted by calling {@link #asType asType} to adjust this method handle
23.496 - * to the required type, and then the call proceeds as if by
23.497 - * {@link #invokeExact invokeExact} on the adjusted method handle.
23.498 - * <p>
23.499 - * There is no guarantee that the {@code asType} call is actually made.
23.500 - * If the JVM can predict the results of making the call, it may perform
23.501 - * adaptations directly on the caller's arguments,
23.502 - * and call the target method handle according to its own exact type.
23.503 - * <p>
23.504 - * The resolved type descriptor at the call site of {@code invoke} must
23.505 - * be a valid argument to the receivers {@code asType} method.
23.506 - * In particular, the caller must specify the same argument arity
23.507 - * as the callee's type,
23.508 - * if the callee is not a {@linkplain #asVarargsCollector variable arity collector}.
23.509 - * <p>
23.510 - * When this method is observed via the Core Reflection API,
23.511 - * it will appear as a single native method, taking an object array and returning an object.
23.512 - * If this native method is invoked directly via
23.513 - * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}, via JNI,
23.514 - * or indirectly via {@link java.lang.invoke.MethodHandles.Lookup#unreflect Lookup.unreflect},
23.515 - * it will throw an {@code UnsupportedOperationException}.
23.516 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.517 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.518 - * @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's symbolic type descriptor
23.519 - * @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
23.520 - * @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
23.521 - */
23.522 - public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;
23.523 -
23.524 - /**
23.525 - * Private method for trusted invocation of a method handle respecting simplified signatures.
23.526 - * Type mismatches will not throw {@code WrongMethodTypeException}, but could crash the JVM.
23.527 - * <p>
23.528 - * The caller signature is restricted to the following basic types:
23.529 - * Object, int, long, float, double, and void return.
23.530 - * <p>
23.531 - * The caller is responsible for maintaining type correctness by ensuring
23.532 - * that the each outgoing argument value is a member of the range of the corresponding
23.533 - * callee argument type.
23.534 - * (The caller should therefore issue appropriate casts and integer narrowing
23.535 - * operations on outgoing argument values.)
23.536 - * The caller can assume that the incoming result value is part of the range
23.537 - * of the callee's return type.
23.538 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.539 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.540 - */
23.541 - /*non-public*/ final native @PolymorphicSignature Object invokeBasic(Object... args) throws Throwable;
23.542 -
23.543 - /**
23.544 - * Private method for trusted invocation of a MemberName of kind {@code REF_invokeVirtual}.
23.545 - * The caller signature is restricted to basic types as with {@code invokeBasic}.
23.546 - * The trailing (not leading) argument must be a MemberName.
23.547 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.548 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.549 - */
23.550 - /*non-public*/ static native @PolymorphicSignature Object linkToVirtual(Object... args) throws Throwable;
23.551 -
23.552 - /**
23.553 - * Private method for trusted invocation of a MemberName of kind {@code REF_invokeStatic}.
23.554 - * The caller signature is restricted to basic types as with {@code invokeBasic}.
23.555 - * The trailing (not leading) argument must be a MemberName.
23.556 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.557 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.558 - */
23.559 - /*non-public*/ static native @PolymorphicSignature Object linkToStatic(Object... args) throws Throwable;
23.560 -
23.561 - /**
23.562 - * Private method for trusted invocation of a MemberName of kind {@code REF_invokeSpecial}.
23.563 - * The caller signature is restricted to basic types as with {@code invokeBasic}.
23.564 - * The trailing (not leading) argument must be a MemberName.
23.565 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.566 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.567 - */
23.568 - /*non-public*/ static native @PolymorphicSignature Object linkToSpecial(Object... args) throws Throwable;
23.569 -
23.570 - /**
23.571 - * Private method for trusted invocation of a MemberName of kind {@code REF_invokeInterface}.
23.572 - * The caller signature is restricted to basic types as with {@code invokeBasic}.
23.573 - * The trailing (not leading) argument must be a MemberName.
23.574 - * @param args the signature-polymorphic parameter list, statically represented using varargs
23.575 - * @return the signature-polymorphic result, statically represented using {@code Object}
23.576 - */
23.577 - /*non-public*/ static native @PolymorphicSignature Object linkToInterface(Object... args) throws Throwable;
23.578 -
23.579 - /**
23.580 - * Performs a variable arity invocation, passing the arguments in the given list
23.581 - * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
23.582 - * which mentions only the type {@code Object}, and whose arity is the length
23.583 - * of the argument list.
23.584 - * <p>
23.585 - * Specifically, execution proceeds as if by the following steps,
23.586 - * although the methods are not guaranteed to be called if the JVM
23.587 - * can predict their effects.
23.588 - * <ul>
23.589 - * <li>Determine the length of the argument array as {@code N}.
23.590 - * For a null reference, {@code N=0}. </li>
23.591 - * <li>Determine the general type {@code TN} of {@code N} arguments as
23.592 - * as {@code TN=MethodType.genericMethodType(N)}.</li>
23.593 - * <li>Force the original target method handle {@code MH0} to the
23.594 - * required type, as {@code MH1 = MH0.asType(TN)}. </li>
23.595 - * <li>Spread the array into {@code N} separate arguments {@code A0, ...}. </li>
23.596 - * <li>Invoke the type-adjusted method handle on the unpacked arguments:
23.597 - * MH1.invokeExact(A0, ...). </li>
23.598 - * <li>Take the return value as an {@code Object} reference. </li>
23.599 - * </ul>
23.600 - * <p>
23.601 - * Because of the action of the {@code asType} step, the following argument
23.602 - * conversions are applied as necessary:
23.603 - * <ul>
23.604 - * <li>reference casting
23.605 - * <li>unboxing
23.606 - * <li>widening primitive conversions
23.607 - * </ul>
23.608 - * <p>
23.609 - * The result returned by the call is boxed if it is a primitive,
23.610 - * or forced to null if the return type is void.
23.611 - * <p>
23.612 - * This call is equivalent to the following code:
23.613 - * <blockquote><pre>{@code
23.614 - * MethodHandle invoker = MethodHandles.spreadInvoker(this.type(), 0);
23.615 - * Object result = invoker.invokeExact(this, arguments);
23.616 - * }</pre></blockquote>
23.617 - * <p>
23.618 - * Unlike the signature polymorphic methods {@code invokeExact} and {@code invoke},
23.619 - * {@code invokeWithArguments} can be accessed normally via the Core Reflection API and JNI.
23.620 - * It can therefore be used as a bridge between native or reflective code and method handles.
23.621 - *
23.622 - * @param arguments the arguments to pass to the target
23.623 - * @return the result returned by the target
23.624 - * @throws ClassCastException if an argument cannot be converted by reference casting
23.625 - * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
23.626 - * @throws Throwable anything thrown by the target method invocation
23.627 - * @see MethodHandles#spreadInvoker
23.628 - */
23.629 - public Object invokeWithArguments(Object... arguments) throws Throwable {
23.630 - int argc = arguments == null ? 0 : arguments.length;
23.631 - @SuppressWarnings("LocalVariableHidesMemberVariable")
23.632 - MethodType type = type();
23.633 - if (type.parameterCount() != argc || isVarargsCollector()) {
23.634 - // simulate invoke
23.635 - return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments);
23.636 - }
23.637 - MethodHandle invoker = type.invokers().varargsInvoker();
23.638 - return invoker.invokeExact(this, arguments);
23.639 - }
23.640 -
23.641 - /**
23.642 - * Performs a variable arity invocation, passing the arguments in the given array
23.643 - * to the method handle, as if via an inexact {@link #invoke invoke} from a call site
23.644 - * which mentions only the type {@code Object}, and whose arity is the length
23.645 - * of the argument array.
23.646 - * <p>
23.647 - * This method is also equivalent to the following code:
23.648 - * <blockquote><pre>{@code
23.649 - * invokeWithArguments(arguments.toArray()
23.650 - * }</pre></blockquote>
23.651 - *
23.652 - * @param arguments the arguments to pass to the target
23.653 - * @return the result returned by the target
23.654 - * @throws NullPointerException if {@code arguments} is a null reference
23.655 - * @throws ClassCastException if an argument cannot be converted by reference casting
23.656 - * @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
23.657 - * @throws Throwable anything thrown by the target method invocation
23.658 - */
23.659 - public Object invokeWithArguments(java.util.List<?> arguments) throws Throwable {
23.660 - return invokeWithArguments(arguments.toArray());
23.661 - }
23.662 -
23.663 - /**
23.664 - * Produces an adapter method handle which adapts the type of the
23.665 - * current method handle to a new type.
23.666 - * The resulting method handle is guaranteed to report a type
23.667 - * which is equal to the desired new type.
23.668 - * <p>
23.669 - * If the original type and new type are equal, returns {@code this}.
23.670 - * <p>
23.671 - * The new method handle, when invoked, will perform the following
23.672 - * steps:
23.673 - * <ul>
23.674 - * <li>Convert the incoming argument list to match the original
23.675 - * method handle's argument list.
23.676 - * <li>Invoke the original method handle on the converted argument list.
23.677 - * <li>Convert any result returned by the original method handle
23.678 - * to the return type of new method handle.
23.679 - * </ul>
23.680 - * <p>
23.681 - * This method provides the crucial behavioral difference between
23.682 - * {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}.
23.683 - * The two methods
23.684 - * perform the same steps when the caller's type descriptor exactly m atches
23.685 - * the callee's, but when the types differ, plain {@link #invoke invoke}
23.686 - * also calls {@code asType} (or some internal equivalent) in order
23.687 - * to match up the caller's and callee's types.
23.688 - * <p>
23.689 - * If the current method is a variable arity method handle
23.690 - * argument list conversion may involve the conversion and collection
23.691 - * of several arguments into an array, as
23.692 - * {@linkplain #asVarargsCollector described elsewhere}.
23.693 - * In every other case, all conversions are applied <em>pairwise</em>,
23.694 - * which means that each argument or return value is converted to
23.695 - * exactly one argument or return value (or no return value).
23.696 - * The applied conversions are defined by consulting the
23.697 - * the corresponding component types of the old and new
23.698 - * method handle types.
23.699 - * <p>
23.700 - * Let <em>T0</em> and <em>T1</em> be corresponding new and old parameter types,
23.701 - * or old and new return types. Specifically, for some valid index {@code i}, let
23.702 - * <em>T0</em>{@code =newType.parameterType(i)} and <em>T1</em>{@code =this.type().parameterType(i)}.
23.703 - * Or else, going the other way for return values, let
23.704 - * <em>T0</em>{@code =this.type().returnType()} and <em>T1</em>{@code =newType.returnType()}.
23.705 - * If the types are the same, the new method handle makes no change
23.706 - * to the corresponding argument or return value (if any).
23.707 - * Otherwise, one of the following conversions is applied
23.708 - * if possible:
23.709 - * <ul>
23.710 - * <li>If <em>T0</em> and <em>T1</em> are references, then a cast to <em>T1</em> is applied.
23.711 - * (The types do not need to be related in any particular way.
23.712 - * This is because a dynamic value of null can convert to any reference type.)
23.713 - * <li>If <em>T0</em> and <em>T1</em> are primitives, then a Java method invocation
23.714 - * conversion (JLS 5.3) is applied, if one exists.
23.715 - * (Specifically, <em>T0</em> must convert to <em>T1</em> by a widening primitive conversion.)
23.716 - * <li>If <em>T0</em> is a primitive and <em>T1</em> a reference,
23.717 - * a Java casting conversion (JLS 5.5) is applied if one exists.
23.718 - * (Specifically, the value is boxed from <em>T0</em> to its wrapper class,
23.719 - * which is then widened as needed to <em>T1</em>.)
23.720 - * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
23.721 - * conversion will be applied at runtime, possibly followed
23.722 - * by a Java method invocation conversion (JLS 5.3)
23.723 - * on the primitive value. (These are the primitive widening conversions.)
23.724 - * <em>T0</em> must be a wrapper class or a supertype of one.
23.725 - * (In the case where <em>T0</em> is Object, these are the conversions
23.726 - * allowed by {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}.)
23.727 - * The unboxing conversion must have a possibility of success, which means that
23.728 - * if <em>T0</em> is not itself a wrapper class, there must exist at least one
23.729 - * wrapper class <em>TW</em> which is a subtype of <em>T0</em> and whose unboxed
23.730 - * primitive value can be widened to <em>T1</em>.
23.731 - * <li>If the return type <em>T1</em> is marked as void, any returned value is discarded
23.732 - * <li>If the return type <em>T0</em> is void and <em>T1</em> a reference, a null value is introduced.
23.733 - * <li>If the return type <em>T0</em> is void and <em>T1</em> a primitive,
23.734 - * a zero value is introduced.
23.735 - * </ul>
23.736 - * (<em>Note:</em> Both <em>T0</em> and <em>T1</em> may be regarded as static types,
23.737 - * because neither corresponds specifically to the <em>dynamic type</em> of any
23.738 - * actual argument or return value.)
23.739 - * <p>
23.740 - * The method handle conversion cannot be made if any one of the required
23.741 - * pairwise conversions cannot be made.
23.742 - * <p>
23.743 - * At runtime, the conversions applied to reference arguments
23.744 - * or return values may require additional runtime checks which can fail.
23.745 - * An unboxing operation may fail because the original reference is null,
23.746 - * causing a {@link java.lang.NullPointerException NullPointerException}.
23.747 - * An unboxing operation or a reference cast may also fail on a reference
23.748 - * to an object of the wrong type,
23.749 - * causing a {@link java.lang.ClassCastException ClassCastException}.
23.750 - * Although an unboxing operation may accept several kinds of wrappers,
23.751 - * if none are available, a {@code ClassCastException} will be thrown.
23.752 - *
23.753 - * @param newType the expected type of the new method handle
23.754 - * @return a method handle which delegates to {@code this} after performing
23.755 - * any necessary argument conversions, and arranges for any
23.756 - * necessary return value conversions
23.757 - * @throws NullPointerException if {@code newType} is a null reference
23.758 - * @throws WrongMethodTypeException if the conversion cannot be made
23.759 - * @see MethodHandles#explicitCastArguments
23.760 - */
23.761 - public MethodHandle asType(MethodType newType) {
23.762 - // Fast path alternative to a heavyweight {@code asType} call.
23.763 - // Return 'this' if the conversion will be a no-op.
23.764 - if (newType == type) {
23.765 - return this;
23.766 - }
23.767 - // Return 'this.asTypeCache' if the conversion is already memoized.
23.768 - MethodHandle atc = asTypeCache;
23.769 - if (atc != null && newType == atc.type) {
23.770 - return atc;
23.771 - }
23.772 - return asTypeUncached(newType);
23.773 - }
23.774 -
23.775 - /** Override this to change asType behavior. */
23.776 - /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
23.777 - if (!type.isConvertibleTo(newType))
23.778 - throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
23.779 - return asTypeCache = convertArguments(newType);
23.780 - }
23.781 -
23.782 - /**
23.783 - * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
23.784 - * and spreads its elements as positional arguments.
23.785 - * The new method handle adapts, as its <i>target</i>,
23.786 - * the current method handle. The type of the adapter will be
23.787 - * the same as the type of the target, except that the final
23.788 - * {@code arrayLength} parameters of the target's type are replaced
23.789 - * by a single array parameter of type {@code arrayType}.
23.790 - * <p>
23.791 - * If the array element type differs from any of the corresponding
23.792 - * argument types on the original target,
23.793 - * the original target is adapted to take the array elements directly,
23.794 - * as if by a call to {@link #asType asType}.
23.795 - * <p>
23.796 - * When called, the adapter replaces a trailing array argument
23.797 - * by the array's elements, each as its own argument to the target.
23.798 - * (The order of the arguments is preserved.)
23.799 - * They are converted pairwise by casting and/or unboxing
23.800 - * to the types of the trailing parameters of the target.
23.801 - * Finally the target is called.
23.802 - * What the target eventually returns is returned unchanged by the adapter.
23.803 - * <p>
23.804 - * Before calling the target, the adapter verifies that the array
23.805 - * contains exactly enough elements to provide a correct argument count
23.806 - * to the target method handle.
23.807 - * (The array may also be null when zero elements are required.)
23.808 - * <p>
23.809 - * If, when the adapter is called, the supplied array argument does
23.810 - * not have the correct number of elements, the adapter will throw
23.811 - * an {@link IllegalArgumentException} instead of invoking the target.
23.812 - * <p>
23.813 - * Here are some simple examples of array-spreading method handles:
23.814 - * <blockquote><pre>{@code
23.815 -MethodHandle equals = publicLookup()
23.816 - .findVirtual(String.class, "equals", methodType(boolean.class, Object.class));
23.817 -assert( (boolean) equals.invokeExact("me", (Object)"me"));
23.818 -assert(!(boolean) equals.invokeExact("me", (Object)"thee"));
23.819 -// spread both arguments from a 2-array:
23.820 -MethodHandle eq2 = equals.asSpreader(Object[].class, 2);
23.821 -assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" }));
23.822 -assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" }));
23.823 -// try to spread from anything but a 2-array:
23.824 -for (int n = 0; n <= 10; n++) {
23.825 - Object[] badArityArgs = (n == 2 ? null : new Object[n]);
23.826 - try { assert((boolean) eq2.invokeExact(badArityArgs) && false); }
23.827 - catch (IllegalArgumentException ex) { } // OK
23.828 -}
23.829 -// spread both arguments from a String array:
23.830 -MethodHandle eq2s = equals.asSpreader(String[].class, 2);
23.831 -assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));
23.832 -assert(!(boolean) eq2s.invokeExact(new String[]{ "me", "thee" }));
23.833 -// spread second arguments from a 1-array:
23.834 -MethodHandle eq1 = equals.asSpreader(Object[].class, 1);
23.835 -assert( (boolean) eq1.invokeExact("me", new Object[]{ "me" }));
23.836 -assert(!(boolean) eq1.invokeExact("me", new Object[]{ "thee" }));
23.837 -// spread no arguments from a 0-array or null:
23.838 -MethodHandle eq0 = equals.asSpreader(Object[].class, 0);
23.839 -assert( (boolean) eq0.invokeExact("me", (Object)"me", new Object[0]));
23.840 -assert(!(boolean) eq0.invokeExact("me", (Object)"thee", (Object[])null));
23.841 -// asSpreader and asCollector are approximate inverses:
23.842 -for (int n = 0; n <= 2; n++) {
23.843 - for (Class<?> a : new Class<?>[]{Object[].class, String[].class, CharSequence[].class}) {
23.844 - MethodHandle equals2 = equals.asSpreader(a, n).asCollector(a, n);
23.845 - assert( (boolean) equals2.invokeWithArguments("me", "me"));
23.846 - assert(!(boolean) equals2.invokeWithArguments("me", "thee"));
23.847 - }
23.848 -}
23.849 -MethodHandle caToString = publicLookup()
23.850 - .findStatic(Arrays.class, "toString", methodType(String.class, char[].class));
23.851 -assertEquals("[A, B, C]", (String) caToString.invokeExact("ABC".toCharArray()));
23.852 -MethodHandle caString3 = caToString.asCollector(char[].class, 3);
23.853 -assertEquals("[A, B, C]", (String) caString3.invokeExact('A', 'B', 'C'));
23.854 -MethodHandle caToString2 = caString3.asSpreader(char[].class, 2);
23.855 -assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray()));
23.856 - * }</pre></blockquote>
23.857 - * @param arrayType usually {@code Object[]}, the type of the array argument from which to extract the spread arguments
23.858 - * @param arrayLength the number of arguments to spread from an incoming array argument
23.859 - * @return a new method handle which spreads its final array argument,
23.860 - * before calling the original method handle
23.861 - * @throws NullPointerException if {@code arrayType} is a null reference
23.862 - * @throws IllegalArgumentException if {@code arrayType} is not an array type,
23.863 - * or if target does not have at least
23.864 - * {@code arrayLength} parameter types,
23.865 - * or if {@code arrayLength} is negative,
23.866 - * or if the resulting method handle's type would have
23.867 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
23.868 - * @throws WrongMethodTypeException if the implied {@code asType} call fails
23.869 - * @see #asCollector
23.870 - */
23.871 - public MethodHandle asSpreader(Class<?> arrayType, int arrayLength) {
23.872 - asSpreaderChecks(arrayType, arrayLength);
23.873 - int spreadArgPos = type.parameterCount() - arrayLength;
23.874 - return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength);
23.875 - }
23.876 -
23.877 - private void asSpreaderChecks(Class<?> arrayType, int arrayLength) {
23.878 - spreadArrayChecks(arrayType, arrayLength);
23.879 - int nargs = type().parameterCount();
23.880 - if (nargs < arrayLength || arrayLength < 0)
23.881 - throw newIllegalArgumentException("bad spread array length");
23.882 - if (arrayType != Object[].class && arrayLength != 0) {
23.883 - boolean sawProblem = false;
23.884 - Class<?> arrayElement = arrayType.getComponentType();
23.885 - for (int i = nargs - arrayLength; i < nargs; i++) {
23.886 - if (!MethodType.canConvert(arrayElement, type().parameterType(i))) {
23.887 - sawProblem = true;
23.888 - break;
23.889 - }
23.890 - }
23.891 - if (sawProblem) {
23.892 - ArrayList<Class<?>> ptypes = new ArrayList<>(type().parameterList());
23.893 - for (int i = nargs - arrayLength; i < nargs; i++) {
23.894 - ptypes.set(i, arrayElement);
23.895 - }
23.896 - // elicit an error:
23.897 - this.asType(MethodType.methodType(type().returnType(), ptypes));
23.898 - }
23.899 - }
23.900 - }
23.901 -
23.902 - private void spreadArrayChecks(Class<?> arrayType, int arrayLength) {
23.903 - Class<?> arrayElement = arrayType.getComponentType();
23.904 - if (arrayElement == null)
23.905 - throw newIllegalArgumentException("not an array type", arrayType);
23.906 - if ((arrayLength & 0x7F) != arrayLength) {
23.907 - if ((arrayLength & 0xFF) != arrayLength)
23.908 - throw newIllegalArgumentException("array length is not legal", arrayLength);
23.909 - assert(arrayLength >= 128);
23.910 - if (arrayElement == long.class ||
23.911 - arrayElement == double.class)
23.912 - throw newIllegalArgumentException("array length is not legal for long[] or double[]", arrayLength);
23.913 - }
23.914 - }
23.915 -
23.916 - /**
23.917 - * Makes an <em>array-collecting</em> method handle, which accepts a given number of trailing
23.918 - * positional arguments and collects them into an array argument.
23.919 - * The new method handle adapts, as its <i>target</i>,
23.920 - * the current method handle. The type of the adapter will be
23.921 - * the same as the type of the target, except that a single trailing
23.922 - * parameter (usually of type {@code arrayType}) is replaced by
23.923 - * {@code arrayLength} parameters whose type is element type of {@code arrayType}.
23.924 - * <p>
23.925 - * If the array type differs from the final argument type on the original target,
23.926 - * the original target is adapted to take the array type directly,
23.927 - * as if by a call to {@link #asType asType}.
23.928 - * <p>
23.929 - * When called, the adapter replaces its trailing {@code arrayLength}
23.930 - * arguments by a single new array of type {@code arrayType}, whose elements
23.931 - * comprise (in order) the replaced arguments.
23.932 - * Finally the target is called.
23.933 - * What the target eventually returns is returned unchanged by the adapter.
23.934 - * <p>
23.935 - * (The array may also be a shared constant when {@code arrayLength} is zero.)
23.936 - * <p>
23.937 - * (<em>Note:</em> The {@code arrayType} is often identical to the last
23.938 - * parameter type of the original target.
23.939 - * It is an explicit argument for symmetry with {@code asSpreader}, and also
23.940 - * to allow the target to use a simple {@code Object} as its last parameter type.)
23.941 - * <p>
23.942 - * In order to create a collecting adapter which is not restricted to a particular
23.943 - * number of collected arguments, use {@link #asVarargsCollector asVarargsCollector} instead.
23.944 - * <p>
23.945 - * Here are some examples of array-collecting method handles:
23.946 - * <blockquote><pre>{@code
23.947 -MethodHandle deepToString = publicLookup()
23.948 - .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
23.949 -assertEquals("[won]", (String) deepToString.invokeExact(new Object[]{"won"}));
23.950 -MethodHandle ts1 = deepToString.asCollector(Object[].class, 1);
23.951 -assertEquals(methodType(String.class, Object.class), ts1.type());
23.952 -//assertEquals("[won]", (String) ts1.invokeExact( new Object[]{"won"})); //FAIL
23.953 -assertEquals("[[won]]", (String) ts1.invokeExact((Object) new Object[]{"won"}));
23.954 -// arrayType can be a subtype of Object[]
23.955 -MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
23.956 -assertEquals(methodType(String.class, String.class, String.class), ts2.type());
23.957 -assertEquals("[two, too]", (String) ts2.invokeExact("two", "too"));
23.958 -MethodHandle ts0 = deepToString.asCollector(Object[].class, 0);
23.959 -assertEquals("[]", (String) ts0.invokeExact());
23.960 -// collectors can be nested, Lisp-style
23.961 -MethodHandle ts22 = deepToString.asCollector(Object[].class, 3).asCollector(String[].class, 2);
23.962 -assertEquals("[A, B, [C, D]]", ((String) ts22.invokeExact((Object)'A', (Object)"B", "C", "D")));
23.963 -// arrayType can be any primitive array type
23.964 -MethodHandle bytesToString = publicLookup()
23.965 - .findStatic(Arrays.class, "toString", methodType(String.class, byte[].class))
23.966 - .asCollector(byte[].class, 3);
23.967 -assertEquals("[1, 2, 3]", (String) bytesToString.invokeExact((byte)1, (byte)2, (byte)3));
23.968 -MethodHandle longsToString = publicLookup()
23.969 - .findStatic(Arrays.class, "toString", methodType(String.class, long[].class))
23.970 - .asCollector(long[].class, 1);
23.971 -assertEquals("[123]", (String) longsToString.invokeExact((long)123));
23.972 - * }</pre></blockquote>
23.973 - * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
23.974 - * @param arrayLength the number of arguments to collect into a new array argument
23.975 - * @return a new method handle which collects some trailing argument
23.976 - * into an array, before calling the original method handle
23.977 - * @throws NullPointerException if {@code arrayType} is a null reference
23.978 - * @throws IllegalArgumentException if {@code arrayType} is not an array type
23.979 - * or {@code arrayType} is not assignable to this method handle's trailing parameter type,
23.980 - * or {@code arrayLength} is not a legal array size,
23.981 - * or the resulting method handle's type would have
23.982 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
23.983 - * @throws WrongMethodTypeException if the implied {@code asType} call fails
23.984 - * @see #asSpreader
23.985 - * @see #asVarargsCollector
23.986 - */
23.987 - public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
23.988 - asCollectorChecks(arrayType, arrayLength);
23.989 - int collectArgPos = type().parameterCount()-1;
23.990 - MethodHandle target = this;
23.991 - if (arrayType != type().parameterType(collectArgPos))
23.992 - target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
23.993 - MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength);
23.994 - return MethodHandles.collectArguments(target, collectArgPos, collector);
23.995 - }
23.996 -
23.997 - // private API: return true if last param exactly matches arrayType
23.998 - private boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
23.999 - spreadArrayChecks(arrayType, arrayLength);
23.1000 - int nargs = type().parameterCount();
23.1001 - if (nargs != 0) {
23.1002 - Class<?> lastParam = type().parameterType(nargs-1);
23.1003 - if (lastParam == arrayType) return true;
23.1004 - if (lastParam.isAssignableFrom(arrayType)) return false;
23.1005 - }
23.1006 - throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
23.1007 - }
23.1008 -
23.1009 - /**
23.1010 - * Makes a <em>variable arity</em> adapter which is able to accept
23.1011 - * any number of trailing positional arguments and collect them
23.1012 - * into an array argument.
23.1013 - * <p>
23.1014 - * The type and behavior of the adapter will be the same as
23.1015 - * the type and behavior of the target, except that certain
23.1016 - * {@code invoke} and {@code asType} requests can lead to
23.1017 - * trailing positional arguments being collected into target's
23.1018 - * trailing parameter.
23.1019 - * Also, the last parameter type of the adapter will be
23.1020 - * {@code arrayType}, even if the target has a different
23.1021 - * last parameter type.
23.1022 - * <p>
23.1023 - * This transformation may return {@code this} if the method handle is
23.1024 - * already of variable arity and its trailing parameter type
23.1025 - * is identical to {@code arrayType}.
23.1026 - * <p>
23.1027 - * When called with {@link #invokeExact invokeExact}, the adapter invokes
23.1028 - * the target with no argument changes.
23.1029 - * (<em>Note:</em> This behavior is different from a
23.1030 - * {@linkplain #asCollector fixed arity collector},
23.1031 - * since it accepts a whole array of indeterminate length,
23.1032 - * rather than a fixed number of arguments.)
23.1033 - * <p>
23.1034 - * When called with plain, inexact {@link #invoke invoke}, if the caller
23.1035 - * type is the same as the adapter, the adapter invokes the target as with
23.1036 - * {@code invokeExact}.
23.1037 - * (This is the normal behavior for {@code invoke} when types match.)
23.1038 - * <p>
23.1039 - * Otherwise, if the caller and adapter arity are the same, and the
23.1040 - * trailing parameter type of the caller is a reference type identical to
23.1041 - * or assignable to the trailing parameter type of the adapter,
23.1042 - * the arguments and return values are converted pairwise,
23.1043 - * as if by {@link #asType asType} on a fixed arity
23.1044 - * method handle.
23.1045 - * <p>
23.1046 - * Otherwise, the arities differ, or the adapter's trailing parameter
23.1047 - * type is not assignable from the corresponding caller type.
23.1048 - * In this case, the adapter replaces all trailing arguments from
23.1049 - * the original trailing argument position onward, by
23.1050 - * a new array of type {@code arrayType}, whose elements
23.1051 - * comprise (in order) the replaced arguments.
23.1052 - * <p>
23.1053 - * The caller type must provides as least enough arguments,
23.1054 - * and of the correct type, to satisfy the target's requirement for
23.1055 - * positional arguments before the trailing array argument.
23.1056 - * Thus, the caller must supply, at a minimum, {@code N-1} arguments,
23.1057 - * where {@code N} is the arity of the target.
23.1058 - * Also, there must exist conversions from the incoming arguments
23.1059 - * to the target's arguments.
23.1060 - * As with other uses of plain {@code invoke}, if these basic
23.1061 - * requirements are not fulfilled, a {@code WrongMethodTypeException}
23.1062 - * may be thrown.
23.1063 - * <p>
23.1064 - * In all cases, what the target eventually returns is returned unchanged by the adapter.
23.1065 - * <p>
23.1066 - * In the final case, it is exactly as if the target method handle were
23.1067 - * temporarily adapted with a {@linkplain #asCollector fixed arity collector}
23.1068 - * to the arity required by the caller type.
23.1069 - * (As with {@code asCollector}, if the array length is zero,
23.1070 - * a shared constant may be used instead of a new array.
23.1071 - * If the implied call to {@code asCollector} would throw
23.1072 - * an {@code IllegalArgumentException} or {@code WrongMethodTypeException},
23.1073 - * the call to the variable arity adapter must throw
23.1074 - * {@code WrongMethodTypeException}.)
23.1075 - * <p>
23.1076 - * The behavior of {@link #asType asType} is also specialized for
23.1077 - * variable arity adapters, to maintain the invariant that
23.1078 - * plain, inexact {@code invoke} is always equivalent to an {@code asType}
23.1079 - * call to adjust the target type, followed by {@code invokeExact}.
23.1080 - * Therefore, a variable arity adapter responds
23.1081 - * to an {@code asType} request by building a fixed arity collector,
23.1082 - * if and only if the adapter and requested type differ either
23.1083 - * in arity or trailing argument type.
23.1084 - * The resulting fixed arity collector has its type further adjusted
23.1085 - * (if necessary) to the requested type by pairwise conversion,
23.1086 - * as if by another application of {@code asType}.
23.1087 - * <p>
23.1088 - * When a method handle is obtained by executing an {@code ldc} instruction
23.1089 - * of a {@code CONSTANT_MethodHandle} constant, and the target method is marked
23.1090 - * as a variable arity method (with the modifier bit {@code 0x0080}),
23.1091 - * the method handle will accept multiple arities, as if the method handle
23.1092 - * constant were created by means of a call to {@code asVarargsCollector}.
23.1093 - * <p>
23.1094 - * In order to create a collecting adapter which collects a predetermined
23.1095 - * number of arguments, and whose type reflects this predetermined number,
23.1096 - * use {@link #asCollector asCollector} instead.
23.1097 - * <p>
23.1098 - * No method handle transformations produce new method handles with
23.1099 - * variable arity, unless they are documented as doing so.
23.1100 - * Therefore, besides {@code asVarargsCollector},
23.1101 - * all methods in {@code MethodHandle} and {@code MethodHandles}
23.1102 - * will return a method handle with fixed arity,
23.1103 - * except in the cases where they are specified to return their original
23.1104 - * operand (e.g., {@code asType} of the method handle's own type).
23.1105 - * <p>
23.1106 - * Calling {@code asVarargsCollector} on a method handle which is already
23.1107 - * of variable arity will produce a method handle with the same type and behavior.
23.1108 - * It may (or may not) return the original variable arity method handle.
23.1109 - * <p>
23.1110 - * Here is an example, of a list-making variable arity method handle:
23.1111 - * <blockquote><pre>{@code
23.1112 -MethodHandle deepToString = publicLookup()
23.1113 - .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
23.1114 -MethodHandle ts1 = deepToString.asVarargsCollector(Object[].class);
23.1115 -assertEquals("[won]", (String) ts1.invokeExact( new Object[]{"won"}));
23.1116 -assertEquals("[won]", (String) ts1.invoke( new Object[]{"won"}));
23.1117 -assertEquals("[won]", (String) ts1.invoke( "won" ));
23.1118 -assertEquals("[[won]]", (String) ts1.invoke((Object) new Object[]{"won"}));
23.1119 -// findStatic of Arrays.asList(...) produces a variable arity method handle:
23.1120 -MethodHandle asList = publicLookup()
23.1121 - .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class));
23.1122 -assertEquals(methodType(List.class, Object[].class), asList.type());
23.1123 -assert(asList.isVarargsCollector());
23.1124 -assertEquals("[]", asList.invoke().toString());
23.1125 -assertEquals("[1]", asList.invoke(1).toString());
23.1126 -assertEquals("[two, too]", asList.invoke("two", "too").toString());
23.1127 -String[] argv = { "three", "thee", "tee" };
23.1128 -assertEquals("[three, thee, tee]", asList.invoke(argv).toString());
23.1129 -assertEquals("[three, thee, tee]", asList.invoke((Object[])argv).toString());
23.1130 -List ls = (List) asList.invoke((Object)argv);
23.1131 -assertEquals(1, ls.size());
23.1132 -assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0)));
23.1133 - * }</pre></blockquote>
23.1134 - * <p style="font-size:smaller;">
23.1135 - * <em>Discussion:</em>
23.1136 - * These rules are designed as a dynamically-typed variation
23.1137 - * of the Java rules for variable arity methods.
23.1138 - * In both cases, callers to a variable arity method or method handle
23.1139 - * can either pass zero or more positional arguments, or else pass
23.1140 - * pre-collected arrays of any length. Users should be aware of the
23.1141 - * special role of the final argument, and of the effect of a
23.1142 - * type match on that final argument, which determines whether
23.1143 - * or not a single trailing argument is interpreted as a whole
23.1144 - * array or a single element of an array to be collected.
23.1145 - * Note that the dynamic type of the trailing argument has no
23.1146 - * effect on this decision, only a comparison between the symbolic
23.1147 - * type descriptor of the call site and the type descriptor of the method handle.)
23.1148 - *
23.1149 - * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
23.1150 - * @return a new method handle which can collect any number of trailing arguments
23.1151 - * into an array, before calling the original method handle
23.1152 - * @throws NullPointerException if {@code arrayType} is a null reference
23.1153 - * @throws IllegalArgumentException if {@code arrayType} is not an array type
23.1154 - * or {@code arrayType} is not assignable to this method handle's trailing parameter type
23.1155 - * @see #asCollector
23.1156 - * @see #isVarargsCollector
23.1157 - * @see #asFixedArity
23.1158 - */
23.1159 - public MethodHandle asVarargsCollector(Class<?> arrayType) {
23.1160 - Class<?> arrayElement = arrayType.getComponentType();
23.1161 - boolean lastMatch = asCollectorChecks(arrayType, 0);
23.1162 - if (isVarargsCollector() && lastMatch)
23.1163 - return this;
23.1164 - return MethodHandleImpl.makeVarargsCollector(this, arrayType);
23.1165 - }
23.1166 -
23.1167 - /**
23.1168 - * Determines if this method handle
23.1169 - * supports {@linkplain #asVarargsCollector variable arity} calls.
23.1170 - * Such method handles arise from the following sources:
23.1171 - * <ul>
23.1172 - * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
23.1173 - * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
23.1174 - * which resolves to a variable arity Java method or constructor
23.1175 - * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
23.1176 - * which resolves to a variable arity Java method or constructor
23.1177 - * </ul>
23.1178 - * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
23.1179 - * @see #asVarargsCollector
23.1180 - * @see #asFixedArity
23.1181 - */
23.1182 - public boolean isVarargsCollector() {
23.1183 - return false;
23.1184 - }
23.1185 -
23.1186 - /**
23.1187 - * Makes a <em>fixed arity</em> method handle which is otherwise
23.1188 - * equivalent to the current method handle.
23.1189 - * <p>
23.1190 - * If the current method handle is not of
23.1191 - * {@linkplain #asVarargsCollector variable arity},
23.1192 - * the current method handle is returned.
23.1193 - * This is true even if the current method handle
23.1194 - * could not be a valid input to {@code asVarargsCollector}.
23.1195 - * <p>
23.1196 - * Otherwise, the resulting fixed-arity method handle has the same
23.1197 - * type and behavior of the current method handle,
23.1198 - * except that {@link #isVarargsCollector isVarargsCollector}
23.1199 - * will be false.
23.1200 - * The fixed-arity method handle may (or may not) be the
23.1201 - * a previous argument to {@code asVarargsCollector}.
23.1202 - * <p>
23.1203 - * Here is an example, of a list-making variable arity method handle:
23.1204 - * <blockquote><pre>{@code
23.1205 -MethodHandle asListVar = publicLookup()
23.1206 - .findStatic(Arrays.class, "asList", methodType(List.class, Object[].class))
23.1207 - .asVarargsCollector(Object[].class);
23.1208 -MethodHandle asListFix = asListVar.asFixedArity();
23.1209 -assertEquals("[1]", asListVar.invoke(1).toString());
23.1210 -Exception caught = null;
23.1211 -try { asListFix.invoke((Object)1); }
23.1212 -catch (Exception ex) { caught = ex; }
23.1213 -assert(caught instanceof ClassCastException);
23.1214 -assertEquals("[two, too]", asListVar.invoke("two", "too").toString());
23.1215 -try { asListFix.invoke("two", "too"); }
23.1216 -catch (Exception ex) { caught = ex; }
23.1217 -assert(caught instanceof WrongMethodTypeException);
23.1218 -Object[] argv = { "three", "thee", "tee" };
23.1219 -assertEquals("[three, thee, tee]", asListVar.invoke(argv).toString());
23.1220 -assertEquals("[three, thee, tee]", asListFix.invoke(argv).toString());
23.1221 -assertEquals(1, ((List) asListVar.invoke((Object)argv)).size());
23.1222 -assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
23.1223 - * }</pre></blockquote>
23.1224 - *
23.1225 - * @return a new method handle which accepts only a fixed number of arguments
23.1226 - * @see #asVarargsCollector
23.1227 - * @see #isVarargsCollector
23.1228 - */
23.1229 - public MethodHandle asFixedArity() {
23.1230 - assert(!isVarargsCollector());
23.1231 - return this;
23.1232 - }
23.1233 -
23.1234 - /**
23.1235 - * Binds a value {@code x} to the first argument of a method handle, without invoking it.
23.1236 - * The new method handle adapts, as its <i>target</i>,
23.1237 - * the current method handle by binding it to the given argument.
23.1238 - * The type of the bound handle will be
23.1239 - * the same as the type of the target, except that a single leading
23.1240 - * reference parameter will be omitted.
23.1241 - * <p>
23.1242 - * When called, the bound handle inserts the given value {@code x}
23.1243 - * as a new leading argument to the target. The other arguments are
23.1244 - * also passed unchanged.
23.1245 - * What the target eventually returns is returned unchanged by the bound handle.
23.1246 - * <p>
23.1247 - * The reference {@code x} must be convertible to the first parameter
23.1248 - * type of the target.
23.1249 - * <p>
23.1250 - * (<em>Note:</em> Because method handles are immutable, the target method handle
23.1251 - * retains its original type and behavior.)
23.1252 - * @param x the value to bind to the first argument of the target
23.1253 - * @return a new method handle which prepends the given value to the incoming
23.1254 - * argument list, before calling the original method handle
23.1255 - * @throws IllegalArgumentException if the target does not have a
23.1256 - * leading parameter type that is a reference type
23.1257 - * @throws ClassCastException if {@code x} cannot be converted
23.1258 - * to the leading parameter type of the target
23.1259 - * @see MethodHandles#insertArguments
23.1260 - */
23.1261 - public MethodHandle bindTo(Object x) {
23.1262 - Class<?> ptype;
23.1263 - @SuppressWarnings("LocalVariableHidesMemberVariable")
23.1264 - MethodType type = type();
23.1265 - if (type.parameterCount() == 0 ||
23.1266 - (ptype = type.parameterType(0)).isPrimitive())
23.1267 - throw newIllegalArgumentException("no leading reference parameter", x);
23.1268 - x = ptype.cast(x); // throw CCE if needed
23.1269 - return bindReceiver(x);
23.1270 - }
23.1271 -
23.1272 - /**
23.1273 - * Returns a string representation of the method handle,
23.1274 - * starting with the string {@code "MethodHandle"} and
23.1275 - * ending with the string representation of the method handle's type.
23.1276 - * In other words, this method returns a string equal to the value of:
23.1277 - * <blockquote><pre>{@code
23.1278 - * "MethodHandle" + type().toString()
23.1279 - * }</pre></blockquote>
23.1280 - * <p>
23.1281 - * (<em>Note:</em> Future releases of this API may add further information
23.1282 - * to the string representation.
23.1283 - * Therefore, the present syntax should not be parsed by applications.)
23.1284 - *
23.1285 - * @return a string representation of the method handle
23.1286 - */
23.1287 - @Override
23.1288 - public String toString() {
23.1289 - if (DEBUG_METHOD_HANDLE_NAMES) return debugString();
23.1290 - return standardString();
23.1291 - }
23.1292 - String standardString() {
23.1293 - return "MethodHandle"+type;
23.1294 - }
23.1295 - String debugString() {
23.1296 - return standardString()+"/LF="+internalForm()+internalProperties();
23.1297 - }
23.1298 -
23.1299 - //// Implementation methods.
23.1300 - //// Sub-classes can override these default implementations.
23.1301 - //// All these methods assume arguments are already validated.
23.1302 -
23.1303 - // Other transforms to do: convert, explicitCast, permute, drop, filter, fold, GWT, catch
23.1304 -
23.1305 - /*non-public*/
23.1306 - MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
23.1307 - if (!member.isVarargs()) return this;
23.1308 - int argc = type().parameterCount();
23.1309 - if (argc != 0) {
23.1310 - Class<?> arrayType = type().parameterType(argc-1);
23.1311 - if (arrayType.isArray()) {
23.1312 - return MethodHandleImpl.makeVarargsCollector(this, arrayType);
23.1313 - }
23.1314 - }
23.1315 - throw member.makeAccessException("cannot make variable arity", null);
23.1316 - }
23.1317 - /*non-public*/
23.1318 - MethodHandle viewAsType(MethodType newType) {
23.1319 - // No actual conversions, just a new view of the same method.
23.1320 - return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
23.1321 - }
23.1322 -
23.1323 - // Decoding
23.1324 -
23.1325 - /*non-public*/
23.1326 - LambdaForm internalForm() {
23.1327 - return form;
23.1328 - }
23.1329 -
23.1330 - /*non-public*/
23.1331 - MemberName internalMemberName() {
23.1332 - return null; // DMH returns DMH.member
23.1333 - }
23.1334 -
23.1335 - /*non-public*/
23.1336 - Class<?> internalCallerClass() {
23.1337 - return null; // caller-bound MH for @CallerSensitive method returns caller
23.1338 - }
23.1339 -
23.1340 - /*non-public*/
23.1341 - MethodHandle withInternalMemberName(MemberName member) {
23.1342 - if (member != null) {
23.1343 - return MethodHandleImpl.makeWrappedMember(this, member);
23.1344 - } else if (internalMemberName() == null) {
23.1345 - // The required internaMemberName is null, and this MH (like most) doesn't have one.
23.1346 - return this;
23.1347 - } else {
23.1348 - // The following case is rare. Mask the internalMemberName by wrapping the MH in a BMH.
23.1349 - MethodHandle result = rebind();
23.1350 - assert (result.internalMemberName() == null);
23.1351 - return result;
23.1352 - }
23.1353 - }
23.1354 -
23.1355 - /*non-public*/
23.1356 - boolean isInvokeSpecial() {
23.1357 - return false; // DMH.Special returns true
23.1358 - }
23.1359 -
23.1360 - /*non-public*/
23.1361 - Object internalValues() {
23.1362 - return null;
23.1363 - }
23.1364 -
23.1365 - /*non-public*/
23.1366 - Object internalProperties() {
23.1367 - // Override to something like "/FOO=bar"
23.1368 - return "";
23.1369 - }
23.1370 -
23.1371 - //// Method handle implementation methods.
23.1372 - //// Sub-classes can override these default implementations.
23.1373 - //// All these methods assume arguments are already validated.
23.1374 -
23.1375 - /*non-public*/ MethodHandle convertArguments(MethodType newType) {
23.1376 - // Override this if it can be improved.
23.1377 - return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
23.1378 - }
23.1379 -
23.1380 - /*non-public*/
23.1381 - MethodHandle bindArgument(int pos, char basicType, Object value) {
23.1382 - // Override this if it can be improved.
23.1383 - return rebind().bindArgument(pos, basicType, value);
23.1384 - }
23.1385 -
23.1386 - /*non-public*/
23.1387 - MethodHandle bindReceiver(Object receiver) {
23.1388 - // Override this if it can be improved.
23.1389 - return bindArgument(0, 'L', receiver);
23.1390 - }
23.1391 -
23.1392 - /*non-public*/
23.1393 - MethodHandle bindImmediate(int pos, char basicType, Object value) {
23.1394 - // Bind an immediate value to a position in the arguments.
23.1395 - // This means, elide the respective argument,
23.1396 - // and replace all references to it in NamedFunction args with the specified value.
23.1397 -
23.1398 - // CURRENT RESTRICTIONS
23.1399 - // * only for pos 0 and UNSAFE (position is adjusted in MHImpl to make API usable for others)
23.1400 -// assert pos == 0 && basicType == 'L' && value instanceof Unsafe;
23.1401 - MethodType type2 = type.dropParameterTypes(pos, pos + 1); // adjustment: ignore receiver!
23.1402 - LambdaForm form2 = form.bindImmediate(pos + 1, basicType, value); // adjust pos to form-relative pos
23.1403 - return copyWith(type2, form2);
23.1404 - }
23.1405 -
23.1406 - /*non-public*/
23.1407 - MethodHandle copyWith(MethodType mt, LambdaForm lf) {
23.1408 - throw new InternalError("copyWith: " + this.getClass());
23.1409 - }
23.1410 -
23.1411 - /*non-public*/
23.1412 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
23.1413 - // Override this if it can be improved.
23.1414 - return rebind().dropArguments(srcType, pos, drops);
23.1415 - }
23.1416 -
23.1417 - /*non-public*/
23.1418 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
23.1419 - // Override this if it can be improved.
23.1420 - return rebind().permuteArguments(newType, reorder);
23.1421 - }
23.1422 -
23.1423 - /*non-public*/
23.1424 - MethodHandle rebind() {
23.1425 - // Bind 'this' into a new invoker, of the known class BMH.
23.1426 - MethodType type2 = type();
23.1427 - LambdaForm form2 = reinvokerForm(this);
23.1428 - // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
23.1429 - return BoundMethodHandle.bindSingle(type2, form2, this);
23.1430 - }
23.1431 -
23.1432 - /*non-public*/
23.1433 - MethodHandle reinvokerTarget() {
23.1434 - throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this);
23.1435 - }
23.1436 -
23.1437 - /** Create a LF which simply reinvokes a target of the given basic type.
23.1438 - * The target MH must override {@link #reinvokerTarget} to provide the target.
23.1439 - */
23.1440 - static LambdaForm reinvokerForm(MethodHandle target) {
23.1441 - MethodType mtype = target.type().basicType();
23.1442 - LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
23.1443 - if (reinvoker != null) return reinvoker;
23.1444 - if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)
23.1445 - return makeReinvokerForm(target.type(), target); // cannot cache this
23.1446 - reinvoker = makeReinvokerForm(mtype, null);
23.1447 - return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker);
23.1448 - }
23.1449 - private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) {
23.1450 - boolean customized = (customTargetOrNull != null);
23.1451 - MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype);
23.1452 - final int THIS_BMH = 0;
23.1453 - final int ARG_BASE = 1;
23.1454 - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount();
23.1455 - int nameCursor = ARG_LIMIT;
23.1456 - final int NEXT_MH = customized ? -1 : nameCursor++;
23.1457 - final int REINVOKE = nameCursor++;
23.1458 - LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
23.1459 - Object[] targetArgs;
23.1460 - MethodHandle targetMH;
23.1461 - if (customized) {
23.1462 - targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
23.1463 - targetMH = customTargetOrNull;
23.1464 - } else {
23.1465 - names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]);
23.1466 - targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class);
23.1467 - targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH
23.1468 - targetMH = MethodHandles.basicInvoker(mtype);
23.1469 - }
23.1470 - names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs);
23.1471 - return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names);
23.1472 - }
23.1473 -
23.1474 - private static final LambdaForm.NamedFunction NF_reinvokerTarget;
23.1475 - static {
23.1476 - try {
23.1477 - NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class
23.1478 - .getDeclaredMethod("reinvokerTarget"));
23.1479 - } catch (ReflectiveOperationException ex) {
23.1480 - throw newInternalError(ex);
23.1481 - }
23.1482 - }
23.1483 -
23.1484 - /**
23.1485 - * Replace the old lambda form of this method handle with a new one.
23.1486 - * The new one must be functionally equivalent to the old one.
23.1487 - * Threads may continue running the old form indefinitely,
23.1488 - * but it is likely that the new one will be preferred for new executions.
23.1489 - * Use with discretion.
23.1490 - */
23.1491 - /*non-public*/
23.1492 - void updateForm(LambdaForm newForm) {
23.1493 - if (form == newForm) return;
23.1494 - this.form = newForm;
23.1495 - this.form.prepare(); // as in MethodHandle.<init>
23.1496 - }
23.1497 -}
24.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleImpl.java Sun Aug 17 20:09:05 2014 +0200
24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
24.3 @@ -1,1014 +0,0 @@
24.4 -/*
24.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
24.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
24.7 - *
24.8 - * This code is free software; you can redistribute it and/or modify it
24.9 - * under the terms of the GNU General Public License version 2 only, as
24.10 - * published by the Free Software Foundation. Oracle designates this
24.11 - * particular file as subject to the "Classpath" exception as provided
24.12 - * by Oracle in the LICENSE file that accompanied this code.
24.13 - *
24.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
24.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24.17 - * version 2 for more details (a copy is included in the LICENSE file that
24.18 - * accompanied this code).
24.19 - *
24.20 - * You should have received a copy of the GNU General Public License version
24.21 - * 2 along with this work; if not, write to the Free Software Foundation,
24.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24.23 - *
24.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24.25 - * or visit www.oracle.com if you need additional information or have any
24.26 - * questions.
24.27 - */
24.28 -
24.29 -package java.lang.invoke;
24.30 -
24.31 -import java.security.AccessController;
24.32 -import java.security.PrivilegedAction;
24.33 -import java.util.ArrayList;
24.34 -import java.util.Arrays;
24.35 -import java.util.HashMap;
24.36 -import sun.invoke.empty.Empty;
24.37 -import sun.invoke.util.ValueConversions;
24.38 -import sun.invoke.util.VerifyType;
24.39 -import sun.invoke.util.Wrapper;
24.40 -import static java.lang.invoke.LambdaForm.*;
24.41 -import static java.lang.invoke.MethodHandleStatics.*;
24.42 -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
24.43 -
24.44 -/**
24.45 - * Trusted implementation code for MethodHandle.
24.46 - * @author jrose
24.47 - */
24.48 -/*non-public*/ abstract class MethodHandleImpl {
24.49 - /// Factory methods to create method handles:
24.50 -
24.51 - static void initStatics() {
24.52 - // Trigger selected static initializations.
24.53 - MemberName.Factory.INSTANCE.getClass();
24.54 - }
24.55 -
24.56 - static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
24.57 - if (!arrayClass.isArray())
24.58 - throw newIllegalArgumentException("not an array: "+arrayClass);
24.59 - MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
24.60 - MethodType srcType = accessor.type().erase();
24.61 - MethodType lambdaType = srcType.invokerType();
24.62 - Name[] names = arguments(1, lambdaType);
24.63 - Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
24.64 - names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
24.65 - LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
24.66 - MethodHandle mh = SimpleMethodHandle.make(srcType, form);
24.67 - if (ArrayAccessor.needCast(arrayClass)) {
24.68 - mh = mh.bindTo(arrayClass);
24.69 - }
24.70 - mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
24.71 - return mh;
24.72 - }
24.73 -
24.74 - static final class ArrayAccessor {
24.75 - /// Support for array element access
24.76 - static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>(); // TODO use it
24.77 - static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>(); // TODO use it
24.78 -
24.79 - static int getElementI(int[] a, int i) { return a[i]; }
24.80 - static long getElementJ(long[] a, int i) { return a[i]; }
24.81 - static float getElementF(float[] a, int i) { return a[i]; }
24.82 - static double getElementD(double[] a, int i) { return a[i]; }
24.83 - static boolean getElementZ(boolean[] a, int i) { return a[i]; }
24.84 - static byte getElementB(byte[] a, int i) { return a[i]; }
24.85 - static short getElementS(short[] a, int i) { return a[i]; }
24.86 - static char getElementC(char[] a, int i) { return a[i]; }
24.87 - static Object getElementL(Object[] a, int i) { return a[i]; }
24.88 -
24.89 - static void setElementI(int[] a, int i, int x) { a[i] = x; }
24.90 - static void setElementJ(long[] a, int i, long x) { a[i] = x; }
24.91 - static void setElementF(float[] a, int i, float x) { a[i] = x; }
24.92 - static void setElementD(double[] a, int i, double x) { a[i] = x; }
24.93 - static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
24.94 - static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
24.95 - static void setElementS(short[] a, int i, short x) { a[i] = x; }
24.96 - static void setElementC(char[] a, int i, char x) { a[i] = x; }
24.97 - static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
24.98 -
24.99 - static Object getElementL(Class<?> arrayClass, Object[] a, int i) { arrayClass.cast(a); return a[i]; }
24.100 - static void setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
24.101 -
24.102 - // Weakly typed wrappers of Object[] accessors:
24.103 - static Object getElementL(Object a, int i) { return getElementL((Object[])a, i); }
24.104 - static void setElementL(Object a, int i, Object x) { setElementL((Object[]) a, i, x); }
24.105 - static Object getElementL(Object arrayClass, Object a, int i) { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
24.106 - static void setElementL(Object arrayClass, Object a, int i, Object x) { setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
24.107 -
24.108 - static boolean needCast(Class<?> arrayClass) {
24.109 - Class<?> elemClass = arrayClass.getComponentType();
24.110 - return !elemClass.isPrimitive() && elemClass != Object.class;
24.111 - }
24.112 - static String name(Class<?> arrayClass, boolean isSetter) {
24.113 - Class<?> elemClass = arrayClass.getComponentType();
24.114 - if (elemClass == null) throw new IllegalArgumentException();
24.115 - return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
24.116 - }
24.117 - static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false; // FIXME: decide
24.118 - static MethodType type(Class<?> arrayClass, boolean isSetter) {
24.119 - Class<?> elemClass = arrayClass.getComponentType();
24.120 - Class<?> arrayArgClass = arrayClass;
24.121 - if (!elemClass.isPrimitive()) {
24.122 - arrayArgClass = Object[].class;
24.123 - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
24.124 - arrayArgClass = Object.class;
24.125 - }
24.126 - if (!needCast(arrayClass)) {
24.127 - return !isSetter ?
24.128 - MethodType.methodType(elemClass, arrayArgClass, int.class) :
24.129 - MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
24.130 - } else {
24.131 - Class<?> classArgClass = Class.class;
24.132 - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
24.133 - classArgClass = Object.class;
24.134 - return !isSetter ?
24.135 - MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
24.136 - MethodType.methodType(void.class, classArgClass, arrayArgClass, int.class, Object.class);
24.137 - }
24.138 - }
24.139 - static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
24.140 - Class<?> elemClass = arrayClass.getComponentType();
24.141 - return !isSetter ?
24.142 - MethodType.methodType(elemClass, arrayClass, int.class) :
24.143 - MethodType.methodType(void.class, arrayClass, int.class, elemClass);
24.144 - }
24.145 - static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
24.146 - String name = name(arrayClass, isSetter);
24.147 - MethodType type = type(arrayClass, isSetter);
24.148 - try {
24.149 - return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
24.150 - } catch (ReflectiveOperationException ex) {
24.151 - throw uncaughtException(ex);
24.152 - }
24.153 - }
24.154 - }
24.155 -
24.156 - /**
24.157 - * Create a JVM-level adapter method handle to conform the given method
24.158 - * handle to the similar newType, using only pairwise argument conversions.
24.159 - * For each argument, convert incoming argument to the exact type needed.
24.160 - * The argument conversions allowed are casting, boxing and unboxing,
24.161 - * integral widening or narrowing, and floating point widening or narrowing.
24.162 - * @param srcType required call type
24.163 - * @param target original method handle
24.164 - * @param level which strength of conversion is allowed
24.165 - * @return an adapter to the original handle with the desired new type,
24.166 - * or the original target if the types are already identical
24.167 - * or null if the adaptation cannot be made
24.168 - */
24.169 - static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
24.170 - assert(level >= 0 && level <= 2);
24.171 - MethodType dstType = target.type();
24.172 - assert(dstType.parameterCount() == target.type().parameterCount());
24.173 - if (srcType == dstType)
24.174 - return target;
24.175 -
24.176 - // Calculate extra arguments (temporaries) required in the names array.
24.177 - // FIXME: Use an ArrayList<Name>. Some arguments require more than one conversion step.
24.178 - final int INARG_COUNT = srcType.parameterCount();
24.179 - int conversions = 0;
24.180 - boolean[] needConv = new boolean[1+INARG_COUNT];
24.181 - for (int i = 0; i <= INARG_COUNT; i++) {
24.182 - Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
24.183 - Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
24.184 - if (!VerifyType.isNullConversion(src, dst) ||
24.185 - level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
24.186 - needConv[i] = true;
24.187 - conversions++;
24.188 - }
24.189 - }
24.190 - boolean retConv = needConv[INARG_COUNT];
24.191 -
24.192 - final int IN_MH = 0;
24.193 - final int INARG_BASE = 1;
24.194 - final int INARG_LIMIT = INARG_BASE + INARG_COUNT;
24.195 - final int NAME_LIMIT = INARG_LIMIT + conversions + 1;
24.196 - final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1);
24.197 - final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
24.198 -
24.199 - // Now build a LambdaForm.
24.200 - MethodType lambdaType = srcType.basicType().invokerType();
24.201 - Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
24.202 -
24.203 - // Collect the arguments to the outgoing call, maybe with conversions:
24.204 - final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0]
24.205 - Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
24.206 -
24.207 - int nameCursor = INARG_LIMIT;
24.208 - for (int i = 0; i < INARG_COUNT; i++) {
24.209 - Class<?> src = srcType.parameterType(i);
24.210 - Class<?> dst = dstType.parameterType(i);
24.211 -
24.212 - if (!needConv[i]) {
24.213 - // do nothing: difference is trivial
24.214 - outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
24.215 - continue;
24.216 - }
24.217 -
24.218 - // Tricky case analysis follows.
24.219 - MethodHandle fn = null;
24.220 - if (src.isPrimitive()) {
24.221 - if (dst.isPrimitive()) {
24.222 - fn = ValueConversions.convertPrimitive(src, dst);
24.223 - } else {
24.224 - Wrapper w = Wrapper.forPrimitiveType(src);
24.225 - MethodHandle boxMethod = ValueConversions.box(w);
24.226 - if (dst == w.wrapperType())
24.227 - fn = boxMethod;
24.228 - else
24.229 - fn = boxMethod.asType(MethodType.methodType(dst, src));
24.230 - }
24.231 - } else {
24.232 - if (dst.isPrimitive()) {
24.233 - // Caller has boxed a primitive. Unbox it for the target.
24.234 - Wrapper w = Wrapper.forPrimitiveType(dst);
24.235 - if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
24.236 - fn = ValueConversions.unbox(dst);
24.237 - } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
24.238 - // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int
24.239 - // must include additional conversions
24.240 - // src must be examined at runtime, to detect Byte, Character, etc.
24.241 - MethodHandle unboxMethod = (level == 1
24.242 - ? ValueConversions.unbox(dst)
24.243 - : ValueConversions.unboxCast(dst));
24.244 - fn = unboxMethod;
24.245 - } else {
24.246 - // Example: Byte->int
24.247 - // Do this by reformulating the problem to Byte->byte.
24.248 - Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
24.249 - MethodHandle unbox = ValueConversions.unbox(srcPrim);
24.250 - // Compose the two conversions. FIXME: should make two Names for this job
24.251 - fn = unbox.asType(MethodType.methodType(dst, src));
24.252 - }
24.253 - } else {
24.254 - // Simple reference conversion.
24.255 - // Note: Do not check for a class hierarchy relation
24.256 - // between src and dst. In all cases a 'null' argument
24.257 - // will pass the cast conversion.
24.258 - fn = ValueConversions.cast(dst);
24.259 - }
24.260 - }
24.261 - Name conv = new Name(fn, names[INARG_BASE + i]);
24.262 - assert(names[nameCursor] == null);
24.263 - names[nameCursor++] = conv;
24.264 - assert(outArgs[OUTARG_BASE + i] == null);
24.265 - outArgs[OUTARG_BASE + i] = conv;
24.266 - }
24.267 -
24.268 - // Build argument array for the call.
24.269 - assert(nameCursor == OUT_CALL);
24.270 - names[OUT_CALL] = new Name(target, outArgs);
24.271 -
24.272 - if (RETURN_CONV < 0) {
24.273 - assert(OUT_CALL == names.length-1);
24.274 - } else {
24.275 - Class<?> needReturn = srcType.returnType();
24.276 - Class<?> haveReturn = dstType.returnType();
24.277 - MethodHandle fn;
24.278 - Object[] arg = { names[OUT_CALL] };
24.279 - if (haveReturn == void.class) {
24.280 - // synthesize a zero value for the given void
24.281 - Object zero = Wrapper.forBasicType(needReturn).zero();
24.282 - fn = MethodHandles.constant(needReturn, zero);
24.283 - arg = new Object[0]; // don't pass names[OUT_CALL] to conversion
24.284 - } else {
24.285 - MethodHandle identity = MethodHandles.identity(needReturn);
24.286 - MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
24.287 - fn = makePairwiseConvert(identity, needConversion, level);
24.288 - }
24.289 - assert(names[RETURN_CONV] == null);
24.290 - names[RETURN_CONV] = new Name(fn, arg);
24.291 - assert(RETURN_CONV == names.length-1);
24.292 - }
24.293 -
24.294 - LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
24.295 - return SimpleMethodHandle.make(srcType, form);
24.296 - }
24.297 -
24.298 - static MethodHandle makeReferenceIdentity(Class<?> refType) {
24.299 - MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
24.300 - Name[] names = arguments(1, lambdaType);
24.301 - names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
24.302 - LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
24.303 - return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
24.304 - }
24.305 -
24.306 - static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
24.307 - MethodType type = target.type();
24.308 - int last = type.parameterCount() - 1;
24.309 - if (type.parameterType(last) != arrayType)
24.310 - target = target.asType(type.changeParameterType(last, arrayType));
24.311 - target = target.asFixedArity(); // make sure this attribute is turned off
24.312 - return new AsVarargsCollector(target, target.type(), arrayType);
24.313 - }
24.314 -
24.315 - static class AsVarargsCollector extends MethodHandle {
24.316 - private final MethodHandle target;
24.317 - private final Class<?> arrayType;
24.318 - private /*@Stable*/ MethodHandle asCollectorCache;
24.319 -
24.320 - AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
24.321 - super(type, reinvokerForm(target));
24.322 - this.target = target;
24.323 - this.arrayType = arrayType;
24.324 - this.asCollectorCache = target.asCollector(arrayType, 0);
24.325 - }
24.326 -
24.327 - @Override MethodHandle reinvokerTarget() { return target; }
24.328 -
24.329 - @Override
24.330 - public boolean isVarargsCollector() {
24.331 - return true;
24.332 - }
24.333 -
24.334 - @Override
24.335 - public MethodHandle asFixedArity() {
24.336 - return target;
24.337 - }
24.338 -
24.339 - @Override
24.340 - public MethodHandle asTypeUncached(MethodType newType) {
24.341 - MethodType type = this.type();
24.342 - int collectArg = type.parameterCount() - 1;
24.343 - int newArity = newType.parameterCount();
24.344 - if (newArity == collectArg+1 &&
24.345 - type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
24.346 - // if arity and trailing parameter are compatible, do normal thing
24.347 - return asTypeCache = asFixedArity().asType(newType);
24.348 - }
24.349 - // check cache
24.350 - MethodHandle acc = asCollectorCache;
24.351 - if (acc != null && acc.type().parameterCount() == newArity)
24.352 - return asTypeCache = acc.asType(newType);
24.353 - // build and cache a collector
24.354 - int arrayLength = newArity - collectArg;
24.355 - MethodHandle collector;
24.356 - try {
24.357 - collector = asFixedArity().asCollector(arrayType, arrayLength);
24.358 - assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
24.359 - } catch (IllegalArgumentException ex) {
24.360 - throw new WrongMethodTypeException("cannot build collector", ex);
24.361 - }
24.362 - asCollectorCache = collector;
24.363 - return asTypeCache = collector.asType(newType);
24.364 - }
24.365 -
24.366 - @Override
24.367 - MethodHandle setVarargs(MemberName member) {
24.368 - if (member.isVarargs()) return this;
24.369 - return asFixedArity();
24.370 - }
24.371 -
24.372 - @Override
24.373 - MethodHandle viewAsType(MethodType newType) {
24.374 - if (newType.lastParameterType() != type().lastParameterType())
24.375 - throw new InternalError();
24.376 - MethodHandle newTarget = asFixedArity().viewAsType(newType);
24.377 - // put back the varargs bit:
24.378 - return new AsVarargsCollector(newTarget, newType, arrayType);
24.379 - }
24.380 -
24.381 - @Override
24.382 - MemberName internalMemberName() {
24.383 - return asFixedArity().internalMemberName();
24.384 - }
24.385 - @Override
24.386 - Class<?> internalCallerClass() {
24.387 - return asFixedArity().internalCallerClass();
24.388 - }
24.389 -
24.390 - /*non-public*/
24.391 - @Override
24.392 - boolean isInvokeSpecial() {
24.393 - return asFixedArity().isInvokeSpecial();
24.394 - }
24.395 -
24.396 -
24.397 - @Override
24.398 - MethodHandle bindArgument(int pos, char basicType, Object value) {
24.399 - return asFixedArity().bindArgument(pos, basicType, value);
24.400 - }
24.401 -
24.402 - @Override
24.403 - MethodHandle bindReceiver(Object receiver) {
24.404 - return asFixedArity().bindReceiver(receiver);
24.405 - }
24.406 -
24.407 - @Override
24.408 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
24.409 - return asFixedArity().dropArguments(srcType, pos, drops);
24.410 - }
24.411 -
24.412 - @Override
24.413 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
24.414 - return asFixedArity().permuteArguments(newType, reorder);
24.415 - }
24.416 - }
24.417 -
24.418 - /** Factory method: Spread selected argument. */
24.419 - static MethodHandle makeSpreadArguments(MethodHandle target,
24.420 - Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
24.421 - MethodType targetType = target.type();
24.422 -
24.423 - for (int i = 0; i < spreadArgCount; i++) {
24.424 - Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
24.425 - if (arg == null) arg = Object.class;
24.426 - targetType = targetType.changeParameterType(spreadArgPos + i, arg);
24.427 - }
24.428 - target = target.asType(targetType);
24.429 -
24.430 - MethodType srcType = targetType
24.431 - .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
24.432 - // Now build a LambdaForm.
24.433 - MethodType lambdaType = srcType.invokerType();
24.434 - Name[] names = arguments(spreadArgCount + 2, lambdaType);
24.435 - int nameCursor = lambdaType.parameterCount();
24.436 - int[] indexes = new int[targetType.parameterCount()];
24.437 -
24.438 - for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
24.439 - Class<?> src = lambdaType.parameterType(i);
24.440 - if (i == spreadArgPos) {
24.441 - // Spread the array.
24.442 - MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
24.443 - Name array = names[argIndex];
24.444 - names[nameCursor++] = new Name(Lazy.NF_checkSpreadArgument, array, spreadArgCount);
24.445 - for (int j = 0; j < spreadArgCount; i++, j++) {
24.446 - indexes[i] = nameCursor;
24.447 - names[nameCursor++] = new Name(aload, array, j);
24.448 - }
24.449 - } else if (i < indexes.length) {
24.450 - indexes[i] = argIndex;
24.451 - }
24.452 - }
24.453 - assert(nameCursor == names.length-1); // leave room for the final call
24.454 -
24.455 - // Build argument array for the call.
24.456 - Name[] targetArgs = new Name[targetType.parameterCount()];
24.457 - for (int i = 0; i < targetType.parameterCount(); i++) {
24.458 - int idx = indexes[i];
24.459 - targetArgs[i] = names[idx];
24.460 - }
24.461 - names[names.length - 1] = new Name(target, (Object[]) targetArgs);
24.462 -
24.463 - LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
24.464 - return SimpleMethodHandle.make(srcType, form);
24.465 - }
24.466 -
24.467 - static void checkSpreadArgument(Object av, int n) {
24.468 - if (av == null) {
24.469 - if (n == 0) return;
24.470 - } else if (av instanceof Object[]) {
24.471 - int len = ((Object[])av).length;
24.472 - if (len == n) return;
24.473 - } else {
24.474 - int len = java.lang.reflect.Array.getLength(av);
24.475 - if (len == n) return;
24.476 - }
24.477 - // fall through to error:
24.478 - throw newIllegalArgumentException("array is not of length "+n);
24.479 - }
24.480 -
24.481 - /**
24.482 - * Pre-initialized NamedFunctions for bootstrapping purposes.
24.483 - * Factored in an inner class to delay initialization until first usage.
24.484 - */
24.485 - private static class Lazy {
24.486 - static final NamedFunction NF_checkSpreadArgument;
24.487 - static {
24.488 - try {
24.489 - NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
24.490 - .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
24.491 - NF_checkSpreadArgument.resolve();
24.492 - } catch (ReflectiveOperationException ex) {
24.493 - throw newInternalError(ex);
24.494 - }
24.495 - }
24.496 - }
24.497 -
24.498 - /** Factory method: Collect or filter selected argument(s). */
24.499 - static MethodHandle makeCollectArguments(MethodHandle target,
24.500 - MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
24.501 - MethodType targetType = target.type(); // (a..., c, [b...])=>r
24.502 - MethodType collectorType = collector.type(); // (b...)=>c
24.503 - int collectArgCount = collectorType.parameterCount();
24.504 - Class<?> collectValType = collectorType.returnType();
24.505 - int collectValCount = (collectValType == void.class ? 0 : 1);
24.506 - MethodType srcType = targetType // (a..., [b...])=>r
24.507 - .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
24.508 - if (!retainOriginalArgs) { // (a..., b...)=>r
24.509 - srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
24.510 - }
24.511 - // in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ]
24.512 - // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
24.513 - // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
24.514 -
24.515 - // Now build a LambdaForm.
24.516 - MethodType lambdaType = srcType.invokerType();
24.517 - Name[] names = arguments(2, lambdaType);
24.518 - final int collectNamePos = names.length - 2;
24.519 - final int targetNamePos = names.length - 1;
24.520 -
24.521 - Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
24.522 - names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
24.523 -
24.524 - // Build argument array for the target.
24.525 - // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ].
24.526 - // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ].
24.527 - Name[] targetArgs = new Name[targetType.parameterCount()];
24.528 - int inputArgPos = 1; // incoming LF args to copy to target
24.529 - int targetArgPos = 0; // fill pointer for targetArgs
24.530 - int chunk = collectArgPos; // |headArgs|
24.531 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
24.532 - inputArgPos += chunk;
24.533 - targetArgPos += chunk;
24.534 - if (collectValType != void.class) {
24.535 - targetArgs[targetArgPos++] = names[collectNamePos];
24.536 - }
24.537 - chunk = collectArgCount;
24.538 - if (retainOriginalArgs) {
24.539 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
24.540 - targetArgPos += chunk; // optionally pass on the collected chunk
24.541 - }
24.542 - inputArgPos += chunk;
24.543 - chunk = targetArgs.length - targetArgPos; // all the rest
24.544 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
24.545 - assert(inputArgPos + chunk == collectNamePos); // use of rest of input args also
24.546 - names[targetNamePos] = new Name(target, (Object[]) targetArgs);
24.547 -
24.548 - LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
24.549 - return SimpleMethodHandle.make(srcType, form);
24.550 - }
24.551 -
24.552 - static
24.553 - MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
24.554 - return testResult ? target : fallback;
24.555 - }
24.556 -
24.557 - static MethodHandle SELECT_ALTERNATIVE;
24.558 - static MethodHandle selectAlternative() {
24.559 - if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE;
24.560 - try {
24.561 - SELECT_ALTERNATIVE
24.562 - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
24.563 - MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
24.564 - } catch (ReflectiveOperationException ex) {
24.565 - throw new RuntimeException(ex);
24.566 - }
24.567 - return SELECT_ALTERNATIVE;
24.568 - }
24.569 -
24.570 - static
24.571 - MethodHandle makeGuardWithTest(MethodHandle test,
24.572 - MethodHandle target,
24.573 - MethodHandle fallback) {
24.574 - MethodType basicType = target.type().basicType();
24.575 - MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
24.576 - int arity = basicType.parameterCount();
24.577 - int extraNames = 3;
24.578 - MethodType lambdaType = basicType.invokerType();
24.579 - Name[] names = arguments(extraNames, lambdaType);
24.580 -
24.581 - Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
24.582 - Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
24.583 -
24.584 - // call test
24.585 - names[arity + 1] = new Name(test, testArgs);
24.586 -
24.587 - // call selectAlternative
24.588 - Object[] selectArgs = { names[arity + 1], target, fallback };
24.589 - names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
24.590 - targetArgs[0] = names[arity + 2];
24.591 -
24.592 - // call target or fallback
24.593 - names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
24.594 -
24.595 - LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
24.596 - return SimpleMethodHandle.make(target.type(), form);
24.597 - }
24.598 -
24.599 - private static class GuardWithCatch {
24.600 - private final MethodHandle target;
24.601 - private final Class<? extends Throwable> exType;
24.602 - private final MethodHandle catcher;
24.603 - // FIXME: Build the control flow out of foldArguments.
24.604 - GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
24.605 - this.target = target;
24.606 - this.exType = exType;
24.607 - this.catcher = catcher;
24.608 - }
24.609 - @LambdaForm.Hidden
24.610 - private Object invoke_V(Object... av) throws Throwable {
24.611 - try {
24.612 - return target.invokeExact(av);
24.613 - } catch (Throwable t) {
24.614 - if (!exType.isInstance(t)) throw t;
24.615 - return catcher.invokeExact(t, av);
24.616 - }
24.617 - }
24.618 - @LambdaForm.Hidden
24.619 - private Object invoke_L0() throws Throwable {
24.620 - try {
24.621 - return target.invokeExact();
24.622 - } catch (Throwable t) {
24.623 - if (!exType.isInstance(t)) throw t;
24.624 - return catcher.invokeExact(t);
24.625 - }
24.626 - }
24.627 - @LambdaForm.Hidden
24.628 - private Object invoke_L1(Object a0) throws Throwable {
24.629 - try {
24.630 - return target.invokeExact(a0);
24.631 - } catch (Throwable t) {
24.632 - if (!exType.isInstance(t)) throw t;
24.633 - return catcher.invokeExact(t, a0);
24.634 - }
24.635 - }
24.636 - @LambdaForm.Hidden
24.637 - private Object invoke_L2(Object a0, Object a1) throws Throwable {
24.638 - try {
24.639 - return target.invokeExact(a0, a1);
24.640 - } catch (Throwable t) {
24.641 - if (!exType.isInstance(t)) throw t;
24.642 - return catcher.invokeExact(t, a0, a1);
24.643 - }
24.644 - }
24.645 - @LambdaForm.Hidden
24.646 - private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
24.647 - try {
24.648 - return target.invokeExact(a0, a1, a2);
24.649 - } catch (Throwable t) {
24.650 - if (!exType.isInstance(t)) throw t;
24.651 - return catcher.invokeExact(t, a0, a1, a2);
24.652 - }
24.653 - }
24.654 - @LambdaForm.Hidden
24.655 - private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
24.656 - try {
24.657 - return target.invokeExact(a0, a1, a2, a3);
24.658 - } catch (Throwable t) {
24.659 - if (!exType.isInstance(t)) throw t;
24.660 - return catcher.invokeExact(t, a0, a1, a2, a3);
24.661 - }
24.662 - }
24.663 - @LambdaForm.Hidden
24.664 - private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
24.665 - try {
24.666 - return target.invokeExact(a0, a1, a2, a3, a4);
24.667 - } catch (Throwable t) {
24.668 - if (!exType.isInstance(t)) throw t;
24.669 - return catcher.invokeExact(t, a0, a1, a2, a3, a4);
24.670 - }
24.671 - }
24.672 - @LambdaForm.Hidden
24.673 - private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
24.674 - try {
24.675 - return target.invokeExact(a0, a1, a2, a3, a4, a5);
24.676 - } catch (Throwable t) {
24.677 - if (!exType.isInstance(t)) throw t;
24.678 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
24.679 - }
24.680 - }
24.681 - @LambdaForm.Hidden
24.682 - private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
24.683 - try {
24.684 - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
24.685 - } catch (Throwable t) {
24.686 - if (!exType.isInstance(t)) throw t;
24.687 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
24.688 - }
24.689 - }
24.690 - @LambdaForm.Hidden
24.691 - private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
24.692 - try {
24.693 - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
24.694 - } catch (Throwable t) {
24.695 - if (!exType.isInstance(t)) throw t;
24.696 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
24.697 - }
24.698 - }
24.699 - static MethodHandle[] makeInvokes() {
24.700 - ArrayList<MethodHandle> invokes = new ArrayList<>();
24.701 - MethodHandles.Lookup lookup = IMPL_LOOKUP;
24.702 - for (;;) {
24.703 - int nargs = invokes.size();
24.704 - String name = "invoke_L"+nargs;
24.705 - MethodHandle invoke = null;
24.706 - try {
24.707 - invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
24.708 - } catch (ReflectiveOperationException ex) {
24.709 - }
24.710 - if (invoke == null) break;
24.711 - invokes.add(invoke);
24.712 - }
24.713 - assert(invokes.size() == 9); // current number of methods
24.714 - return invokes.toArray(new MethodHandle[0]);
24.715 - };
24.716 - static final MethodHandle[] INVOKES = makeInvokes();
24.717 - // For testing use this:
24.718 - //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
24.719 - static final MethodHandle VARARGS_INVOKE;
24.720 - static {
24.721 - try {
24.722 - VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
24.723 - } catch (ReflectiveOperationException ex) {
24.724 - throw uncaughtException(ex);
24.725 - }
24.726 - }
24.727 - }
24.728 -
24.729 -
24.730 - static
24.731 - MethodHandle makeGuardWithCatch(MethodHandle target,
24.732 - Class<? extends Throwable> exType,
24.733 - MethodHandle catcher) {
24.734 - MethodType type = target.type();
24.735 - MethodType ctype = catcher.type();
24.736 - int nargs = type.parameterCount();
24.737 - if (nargs < GuardWithCatch.INVOKES.length) {
24.738 - MethodType gtype = type.generic();
24.739 - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
24.740 - // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
24.741 - MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
24.742 - MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
24.743 - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
24.744 - if (gtarget == null || gcatcher == null) throw new InternalError();
24.745 - MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
24.746 - return makePairwiseConvert(ginvoker, type, 2);
24.747 - } else {
24.748 - target = target.asType(type.changeReturnType(Object.class));
24.749 - MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
24.750 - MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
24.751 - .changeReturnType(Object.class);
24.752 - catcher = catcher.asType(catcherType);
24.753 - MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
24.754 - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
24.755 - if (gtarget == null || gcatcher == null) throw new InternalError();
24.756 - MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
24.757 - MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
24.758 - return makePairwiseConvert(gcollect, type, 2);
24.759 - }
24.760 - }
24.761 -
24.762 - static
24.763 - MethodHandle throwException(MethodType type) {
24.764 - assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
24.765 - int arity = type.parameterCount();
24.766 - if (arity > 1) {
24.767 - return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
24.768 - }
24.769 - return makePairwiseConvert(throwException(), type, 2);
24.770 - }
24.771 -
24.772 - static MethodHandle THROW_EXCEPTION;
24.773 - static MethodHandle throwException() {
24.774 - MethodHandle mh = THROW_EXCEPTION;
24.775 - if (mh != null) return mh;
24.776 - try {
24.777 - mh
24.778 - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
24.779 - MethodType.methodType(Empty.class, Throwable.class));
24.780 - } catch (ReflectiveOperationException ex) {
24.781 - throw new RuntimeException(ex);
24.782 - }
24.783 - THROW_EXCEPTION = mh;
24.784 - return mh;
24.785 - }
24.786 - static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
24.787 -
24.788 - static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
24.789 - static MethodHandle fakeMethodHandleInvoke(MemberName method) {
24.790 - int idx;
24.791 - assert(method.isMethodHandleInvoke());
24.792 - switch (method.getName()) {
24.793 - case "invoke": idx = 0; break;
24.794 - case "invokeExact": idx = 1; break;
24.795 - default: throw new InternalError(method.getName());
24.796 - }
24.797 - MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
24.798 - if (mh != null) return mh;
24.799 - MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
24.800 - MethodHandle.class, Object[].class);
24.801 - mh = throwException(type);
24.802 - mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
24.803 - if (!method.getInvocationType().equals(mh.type()))
24.804 - throw new InternalError(method.toString());
24.805 - mh = mh.withInternalMemberName(method);
24.806 - mh = mh.asVarargsCollector(Object[].class);
24.807 - assert(method.isVarargs());
24.808 - FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
24.809 - return mh;
24.810 - }
24.811 -
24.812 - /**
24.813 - * Create an alias for the method handle which, when called,
24.814 - * appears to be called from the same class loader and protection domain
24.815 - * as hostClass.
24.816 - * This is an expensive no-op unless the method which is called
24.817 - * is sensitive to its caller. A small number of system methods
24.818 - * are in this category, including Class.forName and Method.invoke.
24.819 - */
24.820 - static
24.821 - MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
24.822 - return BindCaller.bindCaller(mh, hostClass);
24.823 - }
24.824 -
24.825 - // Put the whole mess into its own nested class.
24.826 - // That way we can lazily load the code and set up the constants.
24.827 - private static class BindCaller {
24.828 - static
24.829 - MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
24.830 - // Do not use this function to inject calls into system classes.
24.831 - if (hostClass == null
24.832 - || (hostClass.isArray() ||
24.833 - hostClass.isPrimitive() ||
24.834 - hostClass.getName().startsWith("java.") ||
24.835 - hostClass.getName().startsWith("sun."))) {
24.836 - throw new InternalError(); // does not happen, and should not anyway
24.837 - }
24.838 - // For simplicity, convert mh to a varargs-like method.
24.839 - MethodHandle vamh = prepareForInvoker(mh);
24.840 - // Cache the result of makeInjectedInvoker once per argument class.
24.841 - MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
24.842 - return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
24.843 - }
24.844 -
24.845 - private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
24.846 - throw new IllegalStateException("Implement me too!");
24.847 - /*
24.848 - Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null);
24.849 - if (hostClass.getClassLoader() != bcc.getClassLoader())
24.850 - throw new InternalError(hostClass.getName()+" (CL)");
24.851 - try {
24.852 - if (hostClass.getProtectionDomain() != bcc.getProtectionDomain())
24.853 - throw new InternalError(hostClass.getName()+" (PD)");
24.854 - } catch (SecurityException ex) {
24.855 - // Self-check was blocked by security manager. This is OK.
24.856 - // In fact the whole try body could be turned into an assertion.
24.857 - }
24.858 - try {
24.859 - MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class));
24.860 - init.invokeExact(); // force initialization of the class
24.861 - } catch (Throwable ex) {
24.862 - throw uncaughtException(ex);
24.863 - }
24.864 - MethodHandle bccInvoker;
24.865 - try {
24.866 - MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
24.867 - bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT);
24.868 - } catch (ReflectiveOperationException ex) {
24.869 - throw uncaughtException(ex);
24.870 - }
24.871 - // Test the invoker, to ensure that it really injects into the right place.
24.872 - try {
24.873 - MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
24.874 - Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc});
24.875 - } catch (Throwable ex) {
24.876 - throw new InternalError(ex);
24.877 - }
24.878 - return bccInvoker;
24.879 - */
24.880 - }
24.881 - private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
24.882 - @Override protected MethodHandle computeValue(Class<?> hostClass) {
24.883 - return makeInjectedInvoker(hostClass);
24.884 - }
24.885 - };
24.886 -
24.887 - // Adapt mh so that it can be called directly from an injected invoker:
24.888 - private static MethodHandle prepareForInvoker(MethodHandle mh) {
24.889 - mh = mh.asFixedArity();
24.890 - MethodType mt = mh.type();
24.891 - int arity = mt.parameterCount();
24.892 - MethodHandle vamh = mh.asType(mt.generic());
24.893 - vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
24.894 - vamh = vamh.asSpreader(Object[].class, arity);
24.895 - vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
24.896 - return vamh;
24.897 - }
24.898 -
24.899 - // Undo the adapter effect of prepareForInvoker:
24.900 - private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
24.901 - MemberName member,
24.902 - Class<?> hostClass) {
24.903 - MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
24.904 - mh = mh.asType(type);
24.905 - mh = new WrappedMember(mh, type, member, hostClass);
24.906 - return mh;
24.907 - }
24.908 -
24.909 - private static final MethodHandle MH_checkCallerClass;
24.910 - static {
24.911 - final Class<?> THIS_CLASS = BindCaller.class;
24.912 -// assert(checkCallerClass(THIS_CLASS, THIS_CLASS));
24.913 - try {
24.914 - MH_checkCallerClass = IMPL_LOOKUP
24.915 - .findStatic(THIS_CLASS, "checkCallerClass",
24.916 - MethodType.methodType(boolean.class, Class.class, Class.class));
24.917 - assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS));
24.918 - } catch (Throwable ex) {
24.919 - throw new InternalError(ex);
24.920 - }
24.921 - }
24.922 -
24.923 -// @CallerSensitive
24.924 -// private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
24.925 -// // This method is called via MH_checkCallerClass and so it's
24.926 -// // correct to ask for the immediate caller here.
24.927 -// Class<?> actual = Reflection.getCallerClass();
24.928 -// if (actual != expected && actual != expected2)
24.929 -// throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
24.930 -// +(expected == expected2 ? "" : ", or else "+expected2.getName()));
24.931 -// return true;
24.932 -// }
24.933 -
24.934 - private static final byte[] T_BYTES;
24.935 - static {
24.936 - final Object[] values = {null};
24.937 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
24.938 - public Void run() {
24.939 - try {
24.940 - Class<T> tClass = T.class;
24.941 - String tName = tClass.getName();
24.942 - String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class";
24.943 - java.net.URLConnection uconn = tClass.getResource(tResource).openConnection();
24.944 - int len = uconn.getContentLength();
24.945 - byte[] bytes = new byte[len];
24.946 - try (java.io.InputStream str = uconn.getInputStream()) {
24.947 - int nr = str.read(bytes);
24.948 - if (nr != len) throw new java.io.IOException(tResource);
24.949 - }
24.950 - values[0] = bytes;
24.951 - } catch (java.io.IOException ex) {
24.952 - throw new InternalError(ex);
24.953 - }
24.954 - return null;
24.955 - }
24.956 - });
24.957 - T_BYTES = (byte[]) values[0];
24.958 - }
24.959 -
24.960 - // The following class is used as a template for Unsafe.defineAnonymousClass:
24.961 - private static class T {
24.962 - static void init() { } // side effect: initializes this class
24.963 - static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
24.964 - return vamh.invokeExact(args);
24.965 - }
24.966 - }
24.967 - }
24.968 -
24.969 -
24.970 - /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
24.971 - static class WrappedMember extends MethodHandle {
24.972 - private final MethodHandle target;
24.973 - private final MemberName member;
24.974 - private final Class<?> callerClass;
24.975 -
24.976 - private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
24.977 - super(type, reinvokerForm(target));
24.978 - this.target = target;
24.979 - this.member = member;
24.980 - this.callerClass = callerClass;
24.981 - }
24.982 -
24.983 - @Override
24.984 - MethodHandle reinvokerTarget() {
24.985 - return target;
24.986 - }
24.987 - @Override
24.988 - public MethodHandle asTypeUncached(MethodType newType) {
24.989 - // This MH is an alias for target, except for the MemberName
24.990 - // Drop the MemberName if there is any conversion.
24.991 - return asTypeCache = target.asType(newType);
24.992 - }
24.993 - @Override
24.994 - MemberName internalMemberName() {
24.995 - return member;
24.996 - }
24.997 - @Override
24.998 - Class<?> internalCallerClass() {
24.999 - return callerClass;
24.1000 - }
24.1001 - @Override
24.1002 - boolean isInvokeSpecial() {
24.1003 - return target.isInvokeSpecial();
24.1004 - }
24.1005 - @Override
24.1006 - MethodHandle viewAsType(MethodType newType) {
24.1007 - return new WrappedMember(target, newType, member, callerClass);
24.1008 - }
24.1009 - }
24.1010 -
24.1011 - static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
24.1012 - if (member.equals(target.internalMemberName()))
24.1013 - return target;
24.1014 - return new WrappedMember(target, target.type(), member, null);
24.1015 - }
24.1016 -
24.1017 -}
25.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleInfo.java Sun Aug 17 20:09:05 2014 +0200
25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
25.3 @@ -1,284 +0,0 @@
25.4 -/*
25.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
25.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
25.7 - *
25.8 - * This code is free software; you can redistribute it and/or modify it
25.9 - * under the terms of the GNU General Public License version 2 only, as
25.10 - * published by the Free Software Foundation. Oracle designates this
25.11 - * particular file as subject to the "Classpath" exception as provided
25.12 - * by Oracle in the LICENSE file that accompanied this code.
25.13 - *
25.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
25.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25.17 - * version 2 for more details (a copy is included in the LICENSE file that
25.18 - * accompanied this code).
25.19 - *
25.20 - * You should have received a copy of the GNU General Public License version
25.21 - * 2 along with this work; if not, write to the Free Software Foundation,
25.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25.23 - *
25.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
25.25 - * or visit www.oracle.com if you need additional information or have any
25.26 - * questions.
25.27 - */
25.28 -
25.29 -package java.lang.invoke;
25.30 -
25.31 -import java.lang.reflect.*;
25.32 -import java.util.*;
25.33 -import java.lang.invoke.MethodHandleNatives.Constants;
25.34 -import java.lang.invoke.MethodHandles.Lookup;
25.35 -import static java.lang.invoke.MethodHandleStatics.*;
25.36 -
25.37 -/**
25.38 - * A symbolic reference obtained by cracking a direct method handle
25.39 - * into its consitutent symbolic parts.
25.40 - * To crack a direct method handle, call {@link Lookup#revealDirect Lookup.revealDirect}.
25.41 - * <h1><a name="directmh"></a>Direct Method Handles</h1>
25.42 - * A <em>direct method handle</em> represents a method, constructor, or field without
25.43 - * any intervening argument bindings or other transformations.
25.44 - * The method, constructor, or field referred to by a direct method handle is called
25.45 - * its <em>underlying member</em>.
25.46 - * Direct method handles may be obtained in any of these ways:
25.47 - * <ul>
25.48 - * <li>By executing an {@code ldc} instruction on a {@code CONSTANT_MethodHandle} constant.
25.49 - * (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.)
25.50 - * <li>By calling one of the <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>,
25.51 - * such as {@link Lookup#findVirtual Lookup.findVirtual},
25.52 - * to resolve a symbolic reference into a method handle.
25.53 - * A symbolic reference consists of a class, name string, and type.
25.54 - * <li>By calling the factory method {@link Lookup#unreflect Lookup.unreflect}
25.55 - * or {@link Lookup#unreflectSpecial Lookup.unreflectSpecial}
25.56 - * to convert a {@link Method} into a method handle.
25.57 - * <li>By calling the factory method {@link Lookup#unreflectConstructor Lookup.unreflectConstructor}
25.58 - * to convert a {@link Constructor} into a method handle.
25.59 - * <li>By calling the factory method {@link Lookup#unreflectGetter Lookup.unreflectGetter}
25.60 - * or {@link Lookup#unreflectSetter Lookup.unreflectSetter}
25.61 - * to convert a {@link Field} into a method handle.
25.62 - * </ul>
25.63 - *
25.64 - * <h1>Restrictions on Cracking</h1>
25.65 - * Given a suitable {@code Lookup} object, it is possible to crack any direct method handle
25.66 - * to recover a symbolic reference for the underlying method, constructor, or field.
25.67 - * Cracking must be done via a {@code Lookup} object equivalent to that which created
25.68 - * the target method handle, or which has enough access permissions to recreate
25.69 - * an equivalent method handle.
25.70 - * <p>
25.71 - * If the underlying method is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>,
25.72 - * the direct method handle will have been "bound" to a particular caller class, the
25.73 - * {@linkplain java.lang.invoke.MethodHandles.Lookup#lookupClass() lookup class}
25.74 - * of the lookup object used to create it.
25.75 - * Cracking this method handle with a different lookup class will fail
25.76 - * even if the underlying method is public (like {@code Class.forName}).
25.77 - * <p>
25.78 - * The requirement of lookup object matching provides a "fast fail" behavior
25.79 - * for programs which may otherwise trust erroneous revelation of a method
25.80 - * handle with symbolic information (or caller binding) from an unexpected scope.
25.81 - * Use {@link java.lang.invoke.MethodHandles#reflectAs} to override this limitation.
25.82 - *
25.83 - * <h1><a name="refkinds"></a>Reference kinds</h1>
25.84 - * The <a href="MethodHandles.Lookup.html#lookups">Lookup Factory Methods</a>
25.85 - * correspond to all major use cases for methods, constructors, and fields.
25.86 - * These use cases may be distinguished using small integers as follows:
25.87 - * <table border=1 cellpadding=5 summary="reference kinds">
25.88 - * <tr><th>reference kind</th><th>descriptive name</th><th>scope</th><th>member</th><th>behavior</th></tr>
25.89 - * <tr>
25.90 - * <td>{@code 1}</td><td>{@code REF_getField}</td><td>{@code class}</td>
25.91 - * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
25.92 - * </tr>
25.93 - * <tr>
25.94 - * <td>{@code 2}</td><td>{@code REF_getStatic}</td><td>{@code class} or {@code interface}</td>
25.95 - * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
25.96 - * </tr>
25.97 - * <tr>
25.98 - * <td>{@code 3}</td><td>{@code REF_putField}</td><td>{@code class}</td>
25.99 - * <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
25.100 - * </tr>
25.101 - * <tr>
25.102 - * <td>{@code 4}</td><td>{@code REF_putStatic}</td><td>{@code class}</td>
25.103 - * <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
25.104 - * </tr>
25.105 - * <tr>
25.106 - * <td>{@code 5}</td><td>{@code REF_invokeVirtual}</td><td>{@code class}</td>
25.107 - * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
25.108 - * </tr>
25.109 - * <tr>
25.110 - * <td>{@code 6}</td><td>{@code REF_invokeStatic}</td><td>{@code class} or {@code interface}</td>
25.111 - * <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
25.112 - * </tr>
25.113 - * <tr>
25.114 - * <td>{@code 7}</td><td>{@code REF_invokeSpecial}</td><td>{@code class} or {@code interface}</td>
25.115 - * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
25.116 - * </tr>
25.117 - * <tr>
25.118 - * <td>{@code 8}</td><td>{@code REF_newInvokeSpecial}</td><td>{@code class}</td>
25.119 - * <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
25.120 - * </tr>
25.121 - * <tr>
25.122 - * <td>{@code 9}</td><td>{@code REF_invokeInterface}</td><td>{@code interface}</td>
25.123 - * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
25.124 - * </tr>
25.125 - * </table>
25.126 - * @since 1.8
25.127 - */
25.128 -public
25.129 -interface MethodHandleInfo {
25.130 - /**
25.131 - * A direct method handle reference kind,
25.132 - * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
25.133 - */
25.134 - public static final int
25.135 - REF_getField = Constants.REF_getField,
25.136 - REF_getStatic = Constants.REF_getStatic,
25.137 - REF_putField = Constants.REF_putField,
25.138 - REF_putStatic = Constants.REF_putStatic,
25.139 - REF_invokeVirtual = Constants.REF_invokeVirtual,
25.140 - REF_invokeStatic = Constants.REF_invokeStatic,
25.141 - REF_invokeSpecial = Constants.REF_invokeSpecial,
25.142 - REF_newInvokeSpecial = Constants.REF_newInvokeSpecial,
25.143 - REF_invokeInterface = Constants.REF_invokeInterface;
25.144 -
25.145 - /**
25.146 - * Returns the reference kind of the cracked method handle, which in turn
25.147 - * determines whether the method handle's underlying member was a constructor, method, or field.
25.148 - * See the <a href="MethodHandleInfo.html#refkinds">table above</a> for definitions.
25.149 - * @return the integer code for the kind of reference used to access the underlying member
25.150 - */
25.151 - public int getReferenceKind();
25.152 -
25.153 - /**
25.154 - * Returns the class in which the cracked method handle's underlying member was defined.
25.155 - * @return the declaring class of the underlying member
25.156 - */
25.157 - public Class<?> getDeclaringClass();
25.158 -
25.159 - /**
25.160 - * Returns the name of the cracked method handle's underlying member.
25.161 - * This is {@code "<init>"} if the underlying member was a constructor,
25.162 - * else it is a simple method name or field name.
25.163 - * @return the simple name of the underlying member
25.164 - */
25.165 - public String getName();
25.166 -
25.167 - /**
25.168 - * Returns the nominal type of the cracked symbolic reference, expressed as a method type.
25.169 - * If the reference is to a constructor, the return type will be {@code void}.
25.170 - * If it is to a non-static method, the method type will not mention the {@code this} parameter.
25.171 - * If it is to a field and the requested access is to read the field,
25.172 - * the method type will have no parameters and return the field type.
25.173 - * If it is to a field and the requested access is to write the field,
25.174 - * the method type will have one parameter of the field type and return {@code void}.
25.175 - * <p>
25.176 - * Note that original direct method handle may include a leading {@code this} parameter,
25.177 - * or (in the case of a constructor) will replace the {@code void} return type
25.178 - * with the constructed class.
25.179 - * The nominal type does not include any {@code this} parameter,
25.180 - * and (in the case of a constructor) will return {@code void}.
25.181 - * @return the type of the underlying member, expressed as a method type
25.182 - */
25.183 - public MethodType getMethodType();
25.184 -
25.185 - // Utility methods.
25.186 - // NOTE: class/name/type and reference kind constitute a symbolic reference
25.187 - // member and modifiers are an add-on, derived from Core Reflection (or the equivalent)
25.188 -
25.189 - /**
25.190 - * Reflects the underlying member as a method, constructor, or field object.
25.191 - * If the underlying member is public, it is reflected as if by
25.192 - * {@code getMethod}, {@code getConstructor}, or {@code getField}.
25.193 - * Otherwise, it is reflected as if by
25.194 - * {@code getDeclaredMethod}, {@code getDeclaredConstructor}, or {@code getDeclaredField}.
25.195 - * The underlying member must be accessible to the given lookup object.
25.196 - * @param <T> the desired type of the result, either {@link Member} or a subtype
25.197 - * @param expected a class object representing the desired result type {@code T}
25.198 - * @param lookup the lookup object that created this MethodHandleInfo, or one with equivalent access privileges
25.199 - * @return a reference to the method, constructor, or field object
25.200 - * @exception ClassCastException if the member is not of the expected type
25.201 - * @exception NullPointerException if either argument is {@code null}
25.202 - * @exception IllegalArgumentException if the underlying member is not accessible to the given lookup object
25.203 - */
25.204 - public <T extends Member> T reflectAs(Class<T> expected, Lookup lookup);
25.205 -
25.206 - /**
25.207 - * Returns the access modifiers of the underlying member.
25.208 - * @return the Java language modifiers for underlying member,
25.209 - * or -1 if the member cannot be accessed
25.210 - * @see Modifier
25.211 - * @see #reflectAs
25.212 - */
25.213 - public int getModifiers();
25.214 -
25.215 - /**
25.216 - * Determines if the underlying member was a variable arity method or constructor.
25.217 - * Such members are represented by method handles that are varargs collectors.
25.218 - * @implSpec
25.219 - * This produces a result equivalent to:
25.220 - * <pre>{@code
25.221 - * getReferenceKind() >= REF_invokeVirtual && Modifier.isTransient(getModifiers())
25.222 - * }</pre>
25.223 - *
25.224 - *
25.225 - * @return {@code true} if and only if the underlying member was declared with variable arity.
25.226 - */
25.227 - // spelling derived from java.lang.reflect.Executable, not MethodHandle.isVarargsCollector
25.228 - public default boolean isVarArgs() {
25.229 - // fields are never varargs:
25.230 - if (MethodHandleNatives.refKindIsField((byte) getReferenceKind()))
25.231 - return false;
25.232 - // not in the public API: Modifier.VARARGS
25.233 - final int ACC_VARARGS = 0x00000080; // from JVMS 4.6 (Table 4.20)
25.234 - assert(ACC_VARARGS == Modifier.TRANSIENT);
25.235 - return Modifier.isTransient(getModifiers());
25.236 - }
25.237 -
25.238 - /**
25.239 - * Returns the descriptive name of the given reference kind,
25.240 - * as defined in the <a href="MethodHandleInfo.html#refkinds">table above</a>.
25.241 - * The conventional prefix "REF_" is omitted.
25.242 - * @param referenceKind an integer code for a kind of reference used to access a class member
25.243 - * @return a mixed-case string such as {@code "getField"}
25.244 - * @exception IllegalArgumentException if the argument is not a valid
25.245 - * <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
25.246 - */
25.247 - public static String referenceKindToString(int referenceKind) {
25.248 - if (!MethodHandleNatives.refKindIsValid(referenceKind))
25.249 - throw newIllegalArgumentException("invalid reference kind", referenceKind);
25.250 - return MethodHandleNatives.refKindName((byte)referenceKind);
25.251 - }
25.252 -
25.253 - /**
25.254 - * Returns a string representation for a {@code MethodHandleInfo},
25.255 - * given the four parts of its symbolic reference.
25.256 - * This is defined to be of the form {@code "RK C.N:MT"}, where {@code RK} is the
25.257 - * {@linkplain #referenceKindToString reference kind string} for {@code kind},
25.258 - * {@code C} is the {@linkplain java.lang.Class#getName name} of {@code defc}
25.259 - * {@code N} is the {@code name}, and
25.260 - * {@code MT} is the {@code type}.
25.261 - * These four values may be obtained from the
25.262 - * {@linkplain #getReferenceKind reference kind},
25.263 - * {@linkplain #getDeclaringClass declaring class},
25.264 - * {@linkplain #getName member name},
25.265 - * and {@linkplain #getMethodType method type}
25.266 - * of a {@code MethodHandleInfo} object.
25.267 - *
25.268 - * @implSpec
25.269 - * This produces a result equivalent to:
25.270 - * <pre>{@code
25.271 - * String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type)
25.272 - * }</pre>
25.273 - *
25.274 - * @param kind the {@linkplain #getReferenceKind reference kind} part of the symbolic reference
25.275 - * @param defc the {@linkplain #getDeclaringClass declaring class} part of the symbolic reference
25.276 - * @param name the {@linkplain #getName member name} part of the symbolic reference
25.277 - * @param type the {@linkplain #getMethodType method type} part of the symbolic reference
25.278 - * @return a string of the form {@code "RK C.N:MT"}
25.279 - * @exception IllegalArgumentException if the first argument is not a valid
25.280 - * <a href="MethodHandleInfo.html#refkinds">reference kind number</a>
25.281 - * @exception NullPointerException if any reference argument is {@code null}
25.282 - */
25.283 - public static String toString(int kind, Class<?> defc, String name, MethodType type) {
25.284 - Objects.requireNonNull(name); Objects.requireNonNull(type);
25.285 - return String.format("%s %s.%s:%s", referenceKindToString(kind), defc.getName(), name, type);
25.286 - }
25.287 -}
26.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleNatives.java Sun Aug 17 20:09:05 2014 +0200
26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
26.3 @@ -1,536 +0,0 @@
26.4 -/*
26.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
26.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
26.7 - *
26.8 - * This code is free software; you can redistribute it and/or modify it
26.9 - * under the terms of the GNU General Public License version 2 only, as
26.10 - * published by the Free Software Foundation. Oracle designates this
26.11 - * particular file as subject to the "Classpath" exception as provided
26.12 - * by Oracle in the LICENSE file that accompanied this code.
26.13 - *
26.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
26.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
26.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26.17 - * version 2 for more details (a copy is included in the LICENSE file that
26.18 - * accompanied this code).
26.19 - *
26.20 - * You should have received a copy of the GNU General Public License version
26.21 - * 2 along with this work; if not, write to the Free Software Foundation,
26.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26.23 - *
26.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
26.25 - * or visit www.oracle.com if you need additional information or have any
26.26 - * questions.
26.27 - */
26.28 -
26.29 -package java.lang.invoke;
26.30 -
26.31 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
26.32 -import static java.lang.invoke.MethodHandleStatics.*;
26.33 -import java.lang.invoke.MethodHandles.Lookup;
26.34 -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
26.35 -import java.lang.reflect.Constructor;
26.36 -import java.lang.reflect.Field;
26.37 -import java.lang.reflect.Member;
26.38 -import java.lang.reflect.Method;
26.39 -
26.40 -/**
26.41 - * The JVM interface for the method handles package is all here.
26.42 - * This is an interface internal and private to an implementation of JSR 292.
26.43 - * <em>This class is not part of the JSR 292 standard.</em>
26.44 - * @author jrose
26.45 - */
26.46 -class MethodHandleNatives {
26.47 -
26.48 - private MethodHandleNatives() { } // static only
26.49 -
26.50 - /// MemberName support
26.51 -
26.52 - static void init(MemberName self, Object ref) {
26.53 - final Member mem = (Member)ref;
26.54 - self.clazz = mem.getDeclaringClass();
26.55 - int mod = mem.getModifiers();
26.56 - if (ref instanceof Method) {
26.57 - mod |= MemberName.IS_METHOD;
26.58 - }
26.59 - if (ref instanceof Constructor) {
26.60 - mod |= MemberName.IS_CONSTRUCTOR;
26.61 - }
26.62 - self.flags = mod;
26.63 - }
26.64 -
26.65 - static void expand(MemberName self) {
26.66 - }
26.67 -
26.68 - static MemberName resolve(MemberName self, Class<?> caller) throws LinkageError {
26.69 - return self;
26.70 - }
26.71 - static int getMembers(Class<?> defc, String matchName, String matchSig,
26.72 - int matchFlags, Class<?> caller, int skip, MemberName[] results) {
26.73 - int orig = skip;
26.74 - for (Method m : defc.getMethods()) {
26.75 - if (skip == results.length) {
26.76 - break;
26.77 - }
26.78 - MemberName mn = new MemberName(m);
26.79 - results[skip++] = mn;
26.80 - }
26.81 - for (Constructor m : defc.getConstructors()) {
26.82 - if (skip == results.length) {
26.83 - break;
26.84 - }
26.85 - MemberName mn = new MemberName(m);
26.86 - results[skip++] = mn;
26.87 - }
26.88 -// for (Field m : defc.getFields()) {
26.89 -// if (skip == results.length) {
26.90 -// break;
26.91 -// }
26.92 -// MemberName mn = new MemberName(m);
26.93 -// results[skip++] = mn;
26.94 -// }
26.95 - return skip - orig;
26.96 - }
26.97 -
26.98 - /// Field layout queries parallel to sun.misc.Unsafe:
26.99 - static native long objectFieldOffset(MemberName self); // e.g., returns vmindex
26.100 - static native long staticFieldOffset(MemberName self); // e.g., returns vmindex
26.101 - static native Object staticFieldBase(MemberName self); // e.g., returns clazz
26.102 - static native Object getMemberVMInfo(MemberName self); // returns {vmindex,vmtarget}
26.103 -
26.104 - /// MethodHandle support
26.105 -
26.106 - /// CallSite support
26.107 -
26.108 - /** Tell the JVM that we need to change the target of a CallSite. */
26.109 - static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
26.110 - static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
26.111 -
26.112 - static {
26.113 - // The JVM calls MethodHandleNatives.<clinit>. Cascade the <clinit> calls as needed:
26.114 - MethodHandleImpl.initStatics();
26.115 -}
26.116 -
26.117 - // All compile-time constants go here.
26.118 - // There is an opportunity to check them against the JVM's idea of them.
26.119 - static class Constants {
26.120 - Constants() { } // static only
26.121 - // MethodHandleImpl
26.122 - static final int // for getConstant
26.123 - GC_COUNT_GWT = 4,
26.124 - GC_LAMBDA_SUPPORT = 5;
26.125 -
26.126 - // MemberName
26.127 - // The JVM uses values of -2 and above for vtable indexes.
26.128 - // Field values are simple positive offsets.
26.129 - // Ref: src/share/vm/oops/methodOop.hpp
26.130 - // This value is negative enough to avoid such numbers,
26.131 - // but not too negative.
26.132 - static final int
26.133 - MN_IS_METHOD = 0x00010000, // method (not constructor)
26.134 - MN_IS_CONSTRUCTOR = 0x00020000, // constructor
26.135 - MN_IS_FIELD = 0x00040000, // field
26.136 - MN_IS_TYPE = 0x00080000, // nested type
26.137 - MN_CALLER_SENSITIVE = 0x00100000, // @CallerSensitive annotation detected
26.138 - MN_REFERENCE_KIND_SHIFT = 24, // refKind
26.139 - MN_REFERENCE_KIND_MASK = 0x0F000000 >> MN_REFERENCE_KIND_SHIFT,
26.140 - // The SEARCH_* bits are not for MN.flags but for the matchFlags argument of MHN.getMembers:
26.141 - MN_SEARCH_SUPERCLASSES = 0x00100000,
26.142 - MN_SEARCH_INTERFACES = 0x00200000;
26.143 -
26.144 - /**
26.145 - * Basic types as encoded in the JVM. These code values are not
26.146 - * intended for use outside this class. They are used as part of
26.147 - * a private interface between the JVM and this class.
26.148 - */
26.149 - static final int
26.150 - T_BOOLEAN = 4,
26.151 - T_CHAR = 5,
26.152 - T_FLOAT = 6,
26.153 - T_DOUBLE = 7,
26.154 - T_BYTE = 8,
26.155 - T_SHORT = 9,
26.156 - T_INT = 10,
26.157 - T_LONG = 11,
26.158 - T_OBJECT = 12,
26.159 - //T_ARRAY = 13
26.160 - T_VOID = 14,
26.161 - //T_ADDRESS = 15
26.162 - T_ILLEGAL = 99;
26.163 -
26.164 - /**
26.165 - * Constant pool entry types.
26.166 - */
26.167 - static final byte
26.168 - CONSTANT_Utf8 = 1,
26.169 - CONSTANT_Integer = 3,
26.170 - CONSTANT_Float = 4,
26.171 - CONSTANT_Long = 5,
26.172 - CONSTANT_Double = 6,
26.173 - CONSTANT_Class = 7,
26.174 - CONSTANT_String = 8,
26.175 - CONSTANT_Fieldref = 9,
26.176 - CONSTANT_Methodref = 10,
26.177 - CONSTANT_InterfaceMethodref = 11,
26.178 - CONSTANT_NameAndType = 12,
26.179 - CONSTANT_MethodHandle = 15, // JSR 292
26.180 - CONSTANT_MethodType = 16, // JSR 292
26.181 - CONSTANT_InvokeDynamic = 18,
26.182 - CONSTANT_LIMIT = 19; // Limit to tags found in classfiles
26.183 -
26.184 - /**
26.185 - * Access modifier flags.
26.186 - */
26.187 - static final char
26.188 - ACC_PUBLIC = 0x0001,
26.189 - ACC_PRIVATE = 0x0002,
26.190 - ACC_PROTECTED = 0x0004,
26.191 - ACC_STATIC = 0x0008,
26.192 - ACC_FINAL = 0x0010,
26.193 - ACC_SYNCHRONIZED = 0x0020,
26.194 - ACC_VOLATILE = 0x0040,
26.195 - ACC_TRANSIENT = 0x0080,
26.196 - ACC_NATIVE = 0x0100,
26.197 - ACC_INTERFACE = 0x0200,
26.198 - ACC_ABSTRACT = 0x0400,
26.199 - ACC_STRICT = 0x0800,
26.200 - ACC_SYNTHETIC = 0x1000,
26.201 - ACC_ANNOTATION = 0x2000,
26.202 - ACC_ENUM = 0x4000,
26.203 - // aliases:
26.204 - ACC_SUPER = ACC_SYNCHRONIZED,
26.205 - ACC_BRIDGE = ACC_VOLATILE,
26.206 - ACC_VARARGS = ACC_TRANSIENT;
26.207 -
26.208 - /**
26.209 - * Constant pool reference-kind codes, as used by CONSTANT_MethodHandle CP entries.
26.210 - */
26.211 - static final byte
26.212 - REF_NONE = 0, // null value
26.213 - REF_getField = 1,
26.214 - REF_getStatic = 2,
26.215 - REF_putField = 3,
26.216 - REF_putStatic = 4,
26.217 - REF_invokeVirtual = 5,
26.218 - REF_invokeStatic = 6,
26.219 - REF_invokeSpecial = 7,
26.220 - REF_newInvokeSpecial = 8,
26.221 - REF_invokeInterface = 9,
26.222 - REF_LIMIT = 10;
26.223 - }
26.224 -
26.225 - static boolean refKindIsValid(int refKind) {
26.226 - return (refKind > REF_NONE && refKind < REF_LIMIT);
26.227 - }
26.228 - static boolean refKindIsField(byte refKind) {
26.229 - assert(refKindIsValid(refKind));
26.230 - return (refKind <= REF_putStatic);
26.231 - }
26.232 - static boolean refKindIsGetter(byte refKind) {
26.233 - assert(refKindIsValid(refKind));
26.234 - return (refKind <= REF_getStatic);
26.235 - }
26.236 - static boolean refKindIsSetter(byte refKind) {
26.237 - return refKindIsField(refKind) && !refKindIsGetter(refKind);
26.238 - }
26.239 - static boolean refKindIsMethod(byte refKind) {
26.240 - return !refKindIsField(refKind) && (refKind != REF_newInvokeSpecial);
26.241 - }
26.242 - static boolean refKindIsConstructor(byte refKind) {
26.243 - return (refKind == REF_newInvokeSpecial);
26.244 - }
26.245 - static boolean refKindHasReceiver(byte refKind) {
26.246 - assert(refKindIsValid(refKind));
26.247 - return (refKind & 1) != 0;
26.248 - }
26.249 - static boolean refKindIsStatic(byte refKind) {
26.250 - return !refKindHasReceiver(refKind) && (refKind != REF_newInvokeSpecial);
26.251 - }
26.252 - static boolean refKindDoesDispatch(byte refKind) {
26.253 - assert(refKindIsValid(refKind));
26.254 - return (refKind == REF_invokeVirtual ||
26.255 - refKind == REF_invokeInterface);
26.256 - }
26.257 - static {
26.258 - final int HR_MASK = ((1 << REF_getField) |
26.259 - (1 << REF_putField) |
26.260 - (1 << REF_invokeVirtual) |
26.261 - (1 << REF_invokeSpecial) |
26.262 - (1 << REF_invokeInterface)
26.263 - );
26.264 - for (byte refKind = REF_NONE+1; refKind < REF_LIMIT; refKind++) {
26.265 - assert(refKindHasReceiver(refKind) == (((1<<refKind) & HR_MASK) != 0)) : refKind;
26.266 - }
26.267 - }
26.268 - static String refKindName(byte refKind) {
26.269 - assert(refKindIsValid(refKind));
26.270 - switch (refKind) {
26.271 - case REF_getField: return "getField";
26.272 - case REF_getStatic: return "getStatic";
26.273 - case REF_putField: return "putField";
26.274 - case REF_putStatic: return "putStatic";
26.275 - case REF_invokeVirtual: return "invokeVirtual";
26.276 - case REF_invokeStatic: return "invokeStatic";
26.277 - case REF_invokeSpecial: return "invokeSpecial";
26.278 - case REF_newInvokeSpecial: return "newInvokeSpecial";
26.279 - case REF_invokeInterface: return "invokeInterface";
26.280 - default: return "REF_???";
26.281 - }
26.282 - }
26.283 -
26.284 - private static native int getNamedCon(int which, Object[] name);
26.285 - static boolean verifyConstants() {
26.286 - Object[] box = { null };
26.287 - for (int i = 0; ; i++) {
26.288 - box[0] = null;
26.289 - int vmval = getNamedCon(i, box);
26.290 - if (box[0] == null) break;
26.291 - String name = (String) box[0];
26.292 - try {
26.293 - Field con = Constants.class.getDeclaredField(name);
26.294 - int jval = con.getInt(null);
26.295 - if (jval == vmval) continue;
26.296 - String err = (name+": JVM has "+vmval+" while Java has "+jval);
26.297 - if (name.equals("CONV_OP_LIMIT")) {
26.298 - System.err.println("warning: "+err);
26.299 - continue;
26.300 - }
26.301 - throw new InternalError(err);
26.302 - } catch (IllegalAccessException ex) {
26.303 - String err = (name+": JVM has "+vmval+" which Java does not define");
26.304 - // ignore exotic ops the JVM cares about; we just wont issue them
26.305 - //System.err.println("warning: "+err);
26.306 - continue;
26.307 - }
26.308 - }
26.309 - return true;
26.310 - }
26.311 - static {
26.312 - assert(verifyConstants());
26.313 - }
26.314 -
26.315 - // Up-calls from the JVM.
26.316 - // These must NOT be public.
26.317 -
26.318 - /**
26.319 - * The JVM is linking an invokedynamic instruction. Create a reified call site for it.
26.320 - */
26.321 - static MemberName linkCallSite(Object callerObj,
26.322 - Object bootstrapMethodObj,
26.323 - Object nameObj, Object typeObj,
26.324 - Object staticArguments,
26.325 - Object[] appendixResult) {
26.326 - MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
26.327 - Class<?> caller = (Class<?>)callerObj;
26.328 - String name = nameObj.toString().intern();
26.329 - MethodType type = (MethodType)typeObj;
26.330 - CallSite callSite = CallSite.makeSite(bootstrapMethod,
26.331 - name,
26.332 - type,
26.333 - staticArguments,
26.334 - caller);
26.335 - if (callSite instanceof ConstantCallSite) {
26.336 - appendixResult[0] = callSite.dynamicInvoker();
26.337 - return Invokers.linkToTargetMethod(type);
26.338 - } else {
26.339 - appendixResult[0] = callSite;
26.340 - return Invokers.linkToCallSiteMethod(type);
26.341 - }
26.342 - }
26.343 -
26.344 - /**
26.345 - * The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
26.346 - */
26.347 - static MethodType findMethodHandleType(Class<?> rtype, Class<?>[] ptypes) {
26.348 - return MethodType.makeImpl(rtype, ptypes, true);
26.349 - }
26.350 -
26.351 - /**
26.352 - * The JVM wants to link a call site that requires a dynamic type check.
26.353 - * Name is a type-checking invoker, invokeExact or invoke.
26.354 - * Return a JVM method (MemberName) to handle the invoking.
26.355 - * The method assumes the following arguments on the stack:
26.356 - * 0: the method handle being invoked
26.357 - * 1-N: the arguments to the method handle invocation
26.358 - * N+1: an optional, implicitly added argument (typically the given MethodType)
26.359 - * <p>
26.360 - * The nominal method at such a call site is an instance of
26.361 - * a signature-polymorphic method (see @PolymorphicSignature).
26.362 - * Such method instances are user-visible entities which are
26.363 - * "split" from the generic placeholder method in {@code MethodHandle}.
26.364 - * (Note that the placeholder method is not identical with any of
26.365 - * its instances. If invoked reflectively, is guaranteed to throw an
26.366 - * {@code UnsupportedOperationException}.)
26.367 - * If the signature-polymorphic method instance is ever reified,
26.368 - * it appears as a "copy" of the original placeholder
26.369 - * (a native final member of {@code MethodHandle}) except
26.370 - * that its type descriptor has shape required by the instance,
26.371 - * and the method instance is <em>not</em> varargs.
26.372 - * The method instance is also marked synthetic, since the
26.373 - * method (by definition) does not appear in Java source code.
26.374 - * <p>
26.375 - * The JVM is allowed to reify this method as instance metadata.
26.376 - * For example, {@code invokeBasic} is always reified.
26.377 - * But the JVM may instead call {@code linkMethod}.
26.378 - * If the result is an * ordered pair of a {@code (method, appendix)},
26.379 - * the method gets all the arguments (0..N inclusive)
26.380 - * plus the appendix (N+1), and uses the appendix to complete the call.
26.381 - * In this way, one reusable method (called a "linker method")
26.382 - * can perform the function of any number of polymorphic instance
26.383 - * methods.
26.384 - * <p>
26.385 - * Linker methods are allowed to be weakly typed, with any or
26.386 - * all references rewritten to {@code Object} and any primitives
26.387 - * (except {@code long}/{@code float}/{@code double})
26.388 - * rewritten to {@code int}.
26.389 - * A linker method is trusted to return a strongly typed result,
26.390 - * according to the specific method type descriptor of the
26.391 - * signature-polymorphic instance it is emulating.
26.392 - * This can involve (as necessary) a dynamic check using
26.393 - * data extracted from the appendix argument.
26.394 - * <p>
26.395 - * The JVM does not inspect the appendix, other than to pass
26.396 - * it verbatim to the linker method at every call.
26.397 - * This means that the JDK runtime has wide latitude
26.398 - * for choosing the shape of each linker method and its
26.399 - * corresponding appendix.
26.400 - * Linker methods should be generated from {@code LambdaForm}s
26.401 - * so that they do not become visible on stack traces.
26.402 - * <p>
26.403 - * The {@code linkMethod} call is free to omit the appendix
26.404 - * (returning null) and instead emulate the required function
26.405 - * completely in the linker method.
26.406 - * As a corner case, if N==255, no appendix is possible.
26.407 - * In this case, the method returned must be custom-generated to
26.408 - * to perform any needed type checking.
26.409 - * <p>
26.410 - * If the JVM does not reify a method at a call site, but instead
26.411 - * calls {@code linkMethod}, the corresponding call represented
26.412 - * in the bytecodes may mention a valid method which is not
26.413 - * representable with a {@code MemberName}.
26.414 - * Therefore, use cases for {@code linkMethod} tend to correspond to
26.415 - * special cases in reflective code such as {@code findVirtual}
26.416 - * or {@code revealDirect}.
26.417 - */
26.418 - static MemberName linkMethod(Class<?> callerClass, int refKind,
26.419 - Class<?> defc, String name, Object type,
26.420 - Object[] appendixResult) {
26.421 - if (!TRACE_METHOD_LINKAGE)
26.422 - return linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
26.423 - return linkMethodTracing(callerClass, refKind, defc, name, type, appendixResult);
26.424 - }
26.425 - static MemberName linkMethodImpl(Class<?> callerClass, int refKind,
26.426 - Class<?> defc, String name, Object type,
26.427 - Object[] appendixResult) {
26.428 - try {
26.429 - if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
26.430 - return Invokers.methodHandleInvokeLinkerMethod(name, fixMethodType(callerClass, type), appendixResult);
26.431 - }
26.432 - } catch (Throwable ex) {
26.433 - if (ex instanceof LinkageError)
26.434 - throw (LinkageError) ex;
26.435 - else
26.436 - throw new LinkageError(ex.getMessage(), ex);
26.437 - }
26.438 - throw new LinkageError("no such method "+defc.getName()+"."+name+type);
26.439 - }
26.440 - private static MethodType fixMethodType(Class<?> callerClass, Object type) {
26.441 - if (type instanceof MethodType)
26.442 - return (MethodType) type;
26.443 - else
26.444 - return MethodType.fromMethodDescriptorString((String)type, callerClass.getClassLoader());
26.445 - }
26.446 - // Tracing logic:
26.447 - static MemberName linkMethodTracing(Class<?> callerClass, int refKind,
26.448 - Class<?> defc, String name, Object type,
26.449 - Object[] appendixResult) {
26.450 - System.out.println("linkMethod "+defc.getName()+"."+
26.451 - name+type+"/"+Integer.toHexString(refKind));
26.452 - try {
26.453 - MemberName res = linkMethodImpl(callerClass, refKind, defc, name, type, appendixResult);
26.454 - System.out.println("linkMethod => "+res+" + "+appendixResult[0]);
26.455 - return res;
26.456 - } catch (Throwable ex) {
26.457 - System.out.println("linkMethod => throw "+ex);
26.458 - throw ex;
26.459 - }
26.460 - }
26.461 -
26.462 -
26.463 - /**
26.464 - * The JVM is resolving a CONSTANT_MethodHandle CP entry. And it wants our help.
26.465 - * It will make an up-call to this method. (Do not change the name or signature.)
26.466 - * The type argument is a Class for field requests and a MethodType for non-fields.
26.467 - * <p>
26.468 - * Recent versions of the JVM may also pass a resolved MemberName for the type.
26.469 - * In that case, the name is ignored and may be null.
26.470 - */
26.471 - static MethodHandle linkMethodHandleConstant(Class<?> callerClass, int refKind,
26.472 - Class<?> defc, String name, Object type) {
26.473 - try {
26.474 - Lookup lookup = IMPL_LOOKUP.in(callerClass);
26.475 - assert(refKindIsValid(refKind));
26.476 - return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
26.477 - } catch (IllegalAccessException ex) {
26.478 - Throwable cause = ex.getCause();
26.479 - if (cause instanceof AbstractMethodError) {
26.480 - throw (AbstractMethodError) cause;
26.481 - } else {
26.482 - Error err = new IllegalAccessError(ex.getMessage());
26.483 - throw initCauseFrom(err, ex);
26.484 - }
26.485 - } catch (NoSuchMethodException ex) {
26.486 - Error err = new NoSuchMethodError(ex.getMessage());
26.487 - throw initCauseFrom(err, ex);
26.488 - } catch (NoSuchFieldException ex) {
26.489 - Error err = new NoSuchFieldError(ex.getMessage());
26.490 - throw initCauseFrom(err, ex);
26.491 - } catch (ReflectiveOperationException ex) {
26.492 - Error err = new IncompatibleClassChangeError();
26.493 - throw initCauseFrom(err, ex);
26.494 - }
26.495 - }
26.496 -
26.497 - /**
26.498 - * Use best possible cause for err.initCause(), substituting the
26.499 - * cause for err itself if the cause has the same (or better) type.
26.500 - */
26.501 - static private Error initCauseFrom(Error err, Exception ex) {
26.502 - Throwable th = ex.getCause();
26.503 - if (err.getClass().isInstance(th))
26.504 - return (Error) th;
26.505 - err.initCause(th == null ? ex : th);
26.506 - return err;
26.507 - }
26.508 -
26.509 - /**
26.510 - * Is this method a caller-sensitive method?
26.511 - * I.e., does it call Reflection.getCallerClass or a similer method
26.512 - * to ask about the identity of its caller?
26.513 - */
26.514 - static boolean isCallerSensitive(MemberName mem) {
26.515 - if (!mem.isInvocable()) return false; // fields are not caller sensitive
26.516 -
26.517 - return mem.isCallerSensitive() || canBeCalledVirtual(mem);
26.518 - }
26.519 -
26.520 - static boolean canBeCalledVirtual(MemberName mem) {
26.521 - assert(mem.isInvocable());
26.522 - Class<?> defc = mem.getDeclaringClass();
26.523 - switch (mem.getName()) {
26.524 - case "checkMemberAccess":
26.525 - return true; //canBeCalledVirtual(mem, java.lang.SecurityManager.class);
26.526 - case "getContextClassLoader":
26.527 - return canBeCalledVirtual(mem, java.lang.Thread.class);
26.528 - }
26.529 - return false;
26.530 - }
26.531 -
26.532 - static boolean canBeCalledVirtual(MemberName symbolicRef, Class<?> definingClass) {
26.533 - Class<?> symbolicRefClass = symbolicRef.getDeclaringClass();
26.534 - if (symbolicRefClass == definingClass) return true;
26.535 - if (symbolicRef.isStatic() || symbolicRef.isPrivate()) return false;
26.536 - return (definingClass.isAssignableFrom(symbolicRefClass) || // Msym overrides Mdef
26.537 - symbolicRefClass.isInterface()); // Mdef implements Msym
26.538 - }
26.539 -}
27.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleProxies.java Sun Aug 17 20:09:05 2014 +0200
27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
27.3 @@ -1,321 +0,0 @@
27.4 -/*
27.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
27.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
27.7 - *
27.8 - * This code is free software; you can redistribute it and/or modify it
27.9 - * under the terms of the GNU General Public License version 2 only, as
27.10 - * published by the Free Software Foundation. Oracle designates this
27.11 - * particular file as subject to the "Classpath" exception as provided
27.12 - * by Oracle in the LICENSE file that accompanied this code.
27.13 - *
27.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
27.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
27.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27.17 - * version 2 for more details (a copy is included in the LICENSE file that
27.18 - * accompanied this code).
27.19 - *
27.20 - * You should have received a copy of the GNU General Public License version
27.21 - * 2 along with this work; if not, write to the Free Software Foundation,
27.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27.23 - *
27.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
27.25 - * or visit www.oracle.com if you need additional information or have any
27.26 - * questions.
27.27 - */
27.28 -
27.29 -package java.lang.invoke;
27.30 -
27.31 -import java.lang.reflect.*;
27.32 -import java.security.AccessController;
27.33 -import java.security.PrivilegedAction;
27.34 -import sun.invoke.WrapperInstance;
27.35 -import java.util.ArrayList;
27.36 -//import sun.reflect.CallerSensitive;
27.37 -//import sun.reflect.Reflection;
27.38 -//import sun.reflect.misc.ReflectUtil;
27.39 -
27.40 -/**
27.41 - * This class consists exclusively of static methods that help adapt
27.42 - * method handles to other JVM types, such as interfaces.
27.43 - */
27.44 -public class MethodHandleProxies {
27.45 -
27.46 - private MethodHandleProxies() { } // do not instantiate
27.47 -
27.48 - /**
27.49 - * Produces an instance of the given single-method interface which redirects
27.50 - * its calls to the given method handle.
27.51 - * <p>
27.52 - * A single-method interface is an interface which declares a uniquely named method.
27.53 - * When determining the uniquely named method of a single-method interface,
27.54 - * the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
27.55 - * are disregarded. For example, {@link java.util.Comparator} is a single-method interface,
27.56 - * even though it re-declares the {@code Object.equals} method.
27.57 - * <p>
27.58 - * The interface must be public. No additional access checks are performed.
27.59 - * <p>
27.60 - * The resulting instance of the required type will respond to
27.61 - * invocation of the type's uniquely named method by calling
27.62 - * the given target on the incoming arguments,
27.63 - * and returning or throwing whatever the target
27.64 - * returns or throws. The invocation will be as if by
27.65 - * {@code target.invoke}.
27.66 - * The target's type will be checked before the
27.67 - * instance is created, as if by a call to {@code asType},
27.68 - * which may result in a {@code WrongMethodTypeException}.
27.69 - * <p>
27.70 - * The uniquely named method is allowed to be multiply declared,
27.71 - * with distinct type descriptors. (E.g., it can be overloaded,
27.72 - * or can possess bridge methods.) All such declarations are
27.73 - * connected directly to the target method handle.
27.74 - * Argument and return types are adjusted by {@code asType}
27.75 - * for each individual declaration.
27.76 - * <p>
27.77 - * The wrapper instance will implement the requested interface
27.78 - * and its super-types, but no other single-method interfaces.
27.79 - * This means that the instance will not unexpectedly
27.80 - * pass an {@code instanceof} test for any unrequested type.
27.81 - * <p style="font-size:smaller;">
27.82 - * <em>Implementation Note:</em>
27.83 - * Therefore, each instance must implement a unique single-method interface.
27.84 - * Implementations may not bundle together
27.85 - * multiple single-method interfaces onto single implementation classes
27.86 - * in the style of {@link java.awt.AWTEventMulticaster}.
27.87 - * <p>
27.88 - * The method handle may throw an <em>undeclared exception</em>,
27.89 - * which means any checked exception (or other checked throwable)
27.90 - * not declared by the requested type's single abstract method.
27.91 - * If this happens, the throwable will be wrapped in an instance of
27.92 - * {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
27.93 - * and thrown in that wrapped form.
27.94 - * <p>
27.95 - * Like {@link java.lang.Integer#valueOf Integer.valueOf},
27.96 - * {@code asInterfaceInstance} is a factory method whose results are defined
27.97 - * by their behavior.
27.98 - * It is not guaranteed to return a new instance for every call.
27.99 - * <p>
27.100 - * Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
27.101 - * and other corner cases, the interface may also have several abstract methods
27.102 - * with the same name but having distinct descriptors (types of returns and parameters).
27.103 - * In this case, all the methods are bound in common to the one given target.
27.104 - * The type check and effective {@code asType} conversion is applied to each
27.105 - * method type descriptor, and all abstract methods are bound to the target in common.
27.106 - * Beyond this type check, no further checks are made to determine that the
27.107 - * abstract methods are related in any way.
27.108 - * <p>
27.109 - * Future versions of this API may accept additional types,
27.110 - * such as abstract classes with single abstract methods.
27.111 - * Future versions of this API may also equip wrapper instances
27.112 - * with one or more additional public "marker" interfaces.
27.113 - * <p>
27.114 - * If a security manager is installed, this method is caller sensitive.
27.115 - * During any invocation of the target method handle via the returned wrapper,
27.116 - * the original creator of the wrapper (the caller) will be visible
27.117 - * to context checks requested by the security manager.
27.118 - *
27.119 - * @param <T> the desired type of the wrapper, a single-method interface
27.120 - * @param intfc a class object representing {@code T}
27.121 - * @param target the method handle to invoke from the wrapper
27.122 - * @return a correctly-typed wrapper for the given target
27.123 - * @throws NullPointerException if either argument is null
27.124 - * @throws IllegalArgumentException if the {@code intfc} is not a
27.125 - * valid argument to this method
27.126 - * @throws WrongMethodTypeException if the target cannot
27.127 - * be converted to the type required by the requested interface
27.128 - */
27.129 - // Other notes to implementors:
27.130 - // <p>
27.131 - // No stable mapping is promised between the single-method interface and
27.132 - // the implementation class C. Over time, several implementation
27.133 - // classes might be used for the same type.
27.134 - // <p>
27.135 - // If the implementation is able
27.136 - // to prove that a wrapper of the required type
27.137 - // has already been created for a given
27.138 - // method handle, or for another method handle with the
27.139 - // same behavior, the implementation may return that wrapper in place of
27.140 - // a new wrapper.
27.141 - // <p>
27.142 - // This method is designed to apply to common use cases
27.143 - // where a single method handle must interoperate with
27.144 - // an interface that implements a function-like
27.145 - // API. Additional variations, such as single-abstract-method classes with
27.146 - // private constructors, or interfaces with multiple but related
27.147 - // entry points, must be covered by hand-written or automatically
27.148 - // generated adapter classes.
27.149 - //
27.150 -// @CallerSensitive
27.151 - public static
27.152 - <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
27.153 - if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
27.154 - throw new IllegalArgumentException("not a public interface: "+intfc.getName());
27.155 - final MethodHandle mh;
27.156 - if (false) {//System.getSecurityManager() != null) {
27.157 -// final Class<?> caller = Reflection.getCallerClass();
27.158 -// final ClassLoader ccl = caller != null ? caller.getClassLoader() : null;
27.159 -// ReflectUtil.checkProxyPackageAccess(ccl, intfc);
27.160 -// mh = ccl != null ? bindCaller(target, caller) : target;
27.161 - } else {
27.162 - mh = target;
27.163 - }
27.164 - ClassLoader proxyLoader = intfc.getClassLoader();
27.165 - if (proxyLoader == null) {
27.166 - ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
27.167 - proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader();
27.168 - }
27.169 - final Method[] methods = getSingleNameMethods(intfc);
27.170 - if (methods == null)
27.171 - throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
27.172 - final MethodHandle[] vaTargets = new MethodHandle[methods.length];
27.173 - for (int i = 0; i < methods.length; i++) {
27.174 - Method sm = methods[i];
27.175 - MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
27.176 - MethodHandle checkTarget = mh.asType(smMT); // make throw WMT
27.177 - checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
27.178 - vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
27.179 - }
27.180 - final InvocationHandler ih = new InvocationHandler() {
27.181 - private Object getArg(String name) {
27.182 - if ((Object)name == "getWrapperInstanceTarget") return target;
27.183 - if ((Object)name == "getWrapperInstanceType") return intfc;
27.184 - throw new AssertionError();
27.185 - }
27.186 - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
27.187 - for (int i = 0; i < methods.length; i++) {
27.188 - if (method.equals(methods[i]))
27.189 - return vaTargets[i].invokeExact(args);
27.190 - }
27.191 - if (method.getDeclaringClass() == WrapperInstance.class)
27.192 - return getArg(method.getName());
27.193 - if (isObjectMethod(method))
27.194 - return callObjectMethod(proxy, method, args);
27.195 - throw new InternalError("bad proxy method: "+method);
27.196 - }
27.197 - };
27.198 -
27.199 - final Object proxy;
27.200 - if (false) { // System.getSecurityManager() != null) {
27.201 - // sun.invoke.WrapperInstance is a restricted interface not accessible
27.202 - // by any non-null class loader.
27.203 - final ClassLoader loader = proxyLoader;
27.204 - proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
27.205 - public Object run() {
27.206 - return Proxy.newProxyInstance(
27.207 - loader,
27.208 - new Class<?>[]{ intfc, WrapperInstance.class },
27.209 - ih);
27.210 - }
27.211 - });
27.212 - } else {
27.213 - proxy = Proxy.newProxyInstance(proxyLoader,
27.214 - new Class<?>[]{ intfc, WrapperInstance.class },
27.215 - ih);
27.216 - }
27.217 - return intfc.cast(proxy);
27.218 - }
27.219 -
27.220 - private static MethodHandle bindCaller(MethodHandle target, Class<?> hostClass) {
27.221 - MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass);
27.222 - if (target.isVarargsCollector()) {
27.223 - MethodType type = cbmh.type();
27.224 - int arity = type.parameterCount();
27.225 - return cbmh.asVarargsCollector(type.parameterType(arity-1));
27.226 - }
27.227 - return cbmh;
27.228 - }
27.229 -
27.230 - /**
27.231 - * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
27.232 - * @param x any reference
27.233 - * @return true if the reference is not null and points to an object produced by {@code asInterfaceInstance}
27.234 - */
27.235 - public static
27.236 - boolean isWrapperInstance(Object x) {
27.237 - return x instanceof WrapperInstance;
27.238 - }
27.239 -
27.240 - private static WrapperInstance asWrapperInstance(Object x) {
27.241 - try {
27.242 - if (x != null)
27.243 - return (WrapperInstance) x;
27.244 - } catch (ClassCastException ex) {
27.245 - }
27.246 - throw new IllegalArgumentException("not a wrapper instance");
27.247 - }
27.248 -
27.249 - /**
27.250 - * Produces or recovers a target method handle which is behaviorally
27.251 - * equivalent to the unique method of this wrapper instance.
27.252 - * The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
27.253 - * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
27.254 - * @param x any reference
27.255 - * @return a method handle implementing the unique method
27.256 - * @throws IllegalArgumentException if the reference x is not to a wrapper instance
27.257 - */
27.258 - public static
27.259 - MethodHandle wrapperInstanceTarget(Object x) {
27.260 - return asWrapperInstance(x).getWrapperInstanceTarget();
27.261 - }
27.262 -
27.263 - /**
27.264 - * Recovers the unique single-method interface type for which this wrapper instance was created.
27.265 - * The object {@code x} must have been produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
27.266 - * This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
27.267 - * @param x any reference
27.268 - * @return the single-method interface type for which the wrapper was created
27.269 - * @throws IllegalArgumentException if the reference x is not to a wrapper instance
27.270 - */
27.271 - public static
27.272 - Class<?> wrapperInstanceType(Object x) {
27.273 - return asWrapperInstance(x).getWrapperInstanceType();
27.274 - }
27.275 -
27.276 - private static
27.277 - boolean isObjectMethod(Method m) {
27.278 - switch (m.getName()) {
27.279 - case "toString":
27.280 - return (m.getReturnType() == String.class
27.281 - && m.getParameterTypes().length == 0);
27.282 - case "hashCode":
27.283 - return (m.getReturnType() == int.class
27.284 - && m.getParameterTypes().length == 0);
27.285 - case "equals":
27.286 - return (m.getReturnType() == boolean.class
27.287 - && m.getParameterTypes().length == 1
27.288 - && m.getParameterTypes()[0] == Object.class);
27.289 - }
27.290 - return false;
27.291 - }
27.292 -
27.293 - private static
27.294 - Object callObjectMethod(Object self, Method m, Object[] args) {
27.295 - assert(isObjectMethod(m)) : m;
27.296 - switch (m.getName()) {
27.297 - case "toString":
27.298 - return self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
27.299 - case "hashCode":
27.300 - return System.identityHashCode(self);
27.301 - case "equals":
27.302 - return (self == args[0]);
27.303 - }
27.304 - return null;
27.305 - }
27.306 -
27.307 - private static
27.308 - Method[] getSingleNameMethods(Class<?> intfc) {
27.309 - ArrayList<Method> methods = new ArrayList<Method>();
27.310 - String uniqueName = null;
27.311 - for (Method m : intfc.getMethods()) {
27.312 - if (isObjectMethod(m)) continue;
27.313 - if (!Modifier.isAbstract(m.getModifiers())) continue;
27.314 - String mname = m.getName();
27.315 - if (uniqueName == null)
27.316 - uniqueName = mname;
27.317 - else if (!uniqueName.equals(mname))
27.318 - return null; // too many abstract methods
27.319 - methods.add(m);
27.320 - }
27.321 - if (uniqueName == null) return null;
27.322 - return methods.toArray(new Method[methods.size()]);
27.323 - }
27.324 -}
28.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleStatics.java Sun Aug 17 20:09:05 2014 +0200
28.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
28.3 @@ -1,131 +0,0 @@
28.4 -/*
28.5 - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
28.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
28.7 - *
28.8 - * This code is free software; you can redistribute it and/or modify it
28.9 - * under the terms of the GNU General Public License version 2 only, as
28.10 - * published by the Free Software Foundation. Oracle designates this
28.11 - * particular file as subject to the "Classpath" exception as provided
28.12 - * by Oracle in the LICENSE file that accompanied this code.
28.13 - *
28.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
28.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
28.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28.17 - * version 2 for more details (a copy is included in the LICENSE file that
28.18 - * accompanied this code).
28.19 - *
28.20 - * You should have received a copy of the GNU General Public License version
28.21 - * 2 along with this work; if not, write to the Free Software Foundation,
28.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28.23 - *
28.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28.25 - * or visit www.oracle.com if you need additional information or have any
28.26 - * questions.
28.27 - */
28.28 -
28.29 -package java.lang.invoke;
28.30 -
28.31 -import java.security.AccessController;
28.32 -import java.security.PrivilegedAction;
28.33 -//import sun.misc.Unsafe;
28.34 -
28.35 -/**
28.36 - * This class consists exclusively of static names internal to the
28.37 - * method handle implementation.
28.38 - * Usage: {@code import static java.lang.invoke.MethodHandleStatics.*}
28.39 - * @author John Rose, JSR 292 EG
28.40 - */
28.41 -/*non-public*/ class MethodHandleStatics {
28.42 -
28.43 - private MethodHandleStatics() { } // do not instantiate
28.44 -
28.45 -// static final Unsafe UNSAFE = Unsafe.getUnsafe();
28.46 -
28.47 - static final boolean DEBUG_METHOD_HANDLE_NAMES;
28.48 - static final boolean DUMP_CLASS_FILES;
28.49 - static final boolean TRACE_INTERPRETER;
28.50 - static final boolean TRACE_METHOD_LINKAGE;
28.51 - static final Integer COMPILE_THRESHOLD;
28.52 - static {
28.53 - final Object[] values = { false, false, false, false, null };
28.54 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
28.55 - public Void run() {
28.56 - values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
28.57 - values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
28.58 - values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
28.59 - values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
28.60 - values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD");
28.61 - return null;
28.62 - }
28.63 - });
28.64 - DEBUG_METHOD_HANDLE_NAMES = (Boolean) values[0];
28.65 - DUMP_CLASS_FILES = (Boolean) values[1];
28.66 - TRACE_INTERPRETER = (Boolean) values[2];
28.67 - TRACE_METHOD_LINKAGE = (Boolean) values[3];
28.68 - COMPILE_THRESHOLD = (Integer) values[4];
28.69 - }
28.70 -
28.71 - /*non-public*/ static String getNameString(MethodHandle target, MethodType type) {
28.72 - if (type == null)
28.73 - type = target.type();
28.74 - MemberName name = null;
28.75 - if (target != null)
28.76 - name = target.internalMemberName();
28.77 - if (name == null)
28.78 - return "invoke" + type;
28.79 - return name.getName() + type;
28.80 - }
28.81 -
28.82 - /*non-public*/ static String getNameString(MethodHandle target, MethodHandle typeHolder) {
28.83 - return getNameString(target, typeHolder == null ? (MethodType) null : typeHolder.type());
28.84 - }
28.85 -
28.86 - /*non-public*/ static String getNameString(MethodHandle target) {
28.87 - return getNameString(target, (MethodType) null);
28.88 - }
28.89 -
28.90 - /*non-public*/ static String addTypeString(Object obj, MethodHandle target) {
28.91 - String str = String.valueOf(obj);
28.92 - if (target == null) return str;
28.93 - int paren = str.indexOf('(');
28.94 - if (paren >= 0) str = str.substring(0, paren);
28.95 - return str + target.type();
28.96 - }
28.97 -
28.98 - // handy shared exception makers (they simplify the common case code)
28.99 - /*non-public*/ static InternalError newInternalError(String message, Throwable cause) {
28.100 - return new InternalError(message, cause);
28.101 - }
28.102 - /*non-public*/ static InternalError newInternalError(Throwable cause) {
28.103 - return new InternalError(cause);
28.104 - }
28.105 - /*non-public*/ static RuntimeException newIllegalStateException(String message) {
28.106 - return new IllegalStateException(message);
28.107 - }
28.108 - /*non-public*/ static RuntimeException newIllegalStateException(String message, Object obj) {
28.109 - return new IllegalStateException(message(message, obj));
28.110 - }
28.111 - /*non-public*/ static RuntimeException newIllegalArgumentException(String message) {
28.112 - return new IllegalArgumentException(message);
28.113 - }
28.114 - /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj) {
28.115 - return new IllegalArgumentException(message(message, obj));
28.116 - }
28.117 - /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) {
28.118 - return new IllegalArgumentException(message(message, obj, obj2));
28.119 - }
28.120 - /*non-public*/ static Error uncaughtException(Throwable ex) {
28.121 - throw newInternalError("uncaught exception", ex);
28.122 - }
28.123 - static Error NYI() {
28.124 - throw new AssertionError("NYI");
28.125 - }
28.126 - private static String message(String message, Object obj) {
28.127 - if (obj != null) message = message + ": " + obj;
28.128 - return message;
28.129 - }
28.130 - private static String message(String message, Object obj, Object obj2) {
28.131 - if (obj != null || obj2 != null) message = message + ": " + obj + ", " + obj2;
28.132 - return message;
28.133 - }
28.134 -}
29.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandles.java Sun Aug 17 20:09:05 2014 +0200
29.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
29.3 @@ -1,2852 +0,0 @@
29.4 -/*
29.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
29.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
29.7 - *
29.8 - * This code is free software; you can redistribute it and/or modify it
29.9 - * under the terms of the GNU General Public License version 2 only, as
29.10 - * published by the Free Software Foundation. Oracle designates this
29.11 - * particular file as subject to the "Classpath" exception as provided
29.12 - * by Oracle in the LICENSE file that accompanied this code.
29.13 - *
29.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
29.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
29.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29.17 - * version 2 for more details (a copy is included in the LICENSE file that
29.18 - * accompanied this code).
29.19 - *
29.20 - * You should have received a copy of the GNU General Public License version
29.21 - * 2 along with this work; if not, write to the Free Software Foundation,
29.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29.23 - *
29.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
29.25 - * or visit www.oracle.com if you need additional information or have any
29.26 - * questions.
29.27 - */
29.28 -
29.29 -package java.lang.invoke;
29.30 -
29.31 -import java.lang.reflect.*;
29.32 -import java.util.List;
29.33 -import java.util.ArrayList;
29.34 -import java.util.Arrays;
29.35 -
29.36 -import sun.invoke.util.ValueConversions;
29.37 -import sun.invoke.util.VerifyAccess;
29.38 -import sun.invoke.util.Wrapper;
29.39 -import static java.lang.invoke.MethodHandleStatics.*;
29.40 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
29.41 -import java.util.concurrent.ConcurrentHashMap;
29.42 -
29.43 -/**
29.44 - * This class consists exclusively of static methods that operate on or return
29.45 - * method handles. They fall into several categories:
29.46 - * <ul>
29.47 - * <li>Lookup methods which help create method handles for methods and fields.
29.48 - * <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
29.49 - * <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
29.50 - * </ul>
29.51 - * <p>
29.52 - * @author John Rose, JSR 292 EG
29.53 - * @since 1.7
29.54 - */
29.55 -public class MethodHandles {
29.56 -
29.57 - private MethodHandles() { } // do not instantiate
29.58 -
29.59 - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
29.60 - static { MethodHandleImpl.initStatics(); }
29.61 - // See IMPL_LOOKUP below.
29.62 -
29.63 - //// Method handle creation from ordinary methods.
29.64 -
29.65 - /**
29.66 - * Returns a {@link Lookup lookup object} with
29.67 - * full capabilities to emulate all supported bytecode behaviors of the caller.
29.68 - * These capabilities include <a href="MethodHandles.Lookup.html#privacc">private access</a> to the caller.
29.69 - * Factory methods on the lookup object can create
29.70 - * <a href="MethodHandleInfo.html#directmh">direct method handles</a>
29.71 - * for any member that the caller has access to via bytecodes,
29.72 - * including protected and private fields and methods.
29.73 - * This lookup object is a <em>capability</em> which may be delegated to trusted agents.
29.74 - * Do not store it in place where untrusted code can access it.
29.75 - * <p>
29.76 - * This method is caller sensitive, which means that it may return different
29.77 - * values to different callers.
29.78 - * <p>
29.79 - * For any given caller class {@code C}, the lookup object returned by this call
29.80 - * has equivalent capabilities to any lookup object
29.81 - * supplied by the JVM to the bootstrap method of an
29.82 - * <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
29.83 - * executing in the same caller class {@code C}.
29.84 - * @return a lookup object for the caller of this method, with private access
29.85 - */
29.86 -// @CallerSensitive
29.87 - public static Lookup lookup() {
29.88 - throw new IllegalStateException("Implement me!");
29.89 -// return new Lookup(Reflection.getCallerClass());
29.90 - }
29.91 -
29.92 - /**
29.93 - * Returns a {@link Lookup lookup object} which is trusted minimally.
29.94 - * It can only be used to create method handles to
29.95 - * publicly accessible fields and methods.
29.96 - * <p>
29.97 - * As a matter of pure convention, the {@linkplain Lookup#lookupClass lookup class}
29.98 - * of this lookup object will be {@link java.lang.Object}.
29.99 - *
29.100 - * <p style="font-size:smaller;">
29.101 - * <em>Discussion:</em>
29.102 - * The lookup class can be changed to any other class {@code C} using an expression of the form
29.103 - * {@link Lookup#in publicLookup().in(C.class)}.
29.104 - * Since all classes have equal access to public names,
29.105 - * such a change would confer no new access rights.
29.106 - * A public lookup object is always subject to
29.107 - * <a href="MethodHandles.Lookup.html#secmgr">security manager checks</a>.
29.108 - * Also, it cannot access
29.109 - * <a href="MethodHandles.Lookup.html#callsens">caller sensitive methods</a>.
29.110 - * @return a lookup object which is trusted minimally
29.111 - */
29.112 - public static Lookup publicLookup() {
29.113 - return Lookup.PUBLIC_LOOKUP;
29.114 - }
29.115 -
29.116 - /**
29.117 - * Performs an unchecked "crack" of a
29.118 - * <a href="MethodHandleInfo.html#directmh">direct method handle</a>.
29.119 - * The result is as if the user had obtained a lookup object capable enough
29.120 - * to crack the target method handle, called
29.121 - * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect}
29.122 - * on the target to obtain its symbolic reference, and then called
29.123 - * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs}
29.124 - * to resolve the symbolic reference to a member.
29.125 - * <p>
29.126 - * If there is a security manager, its {@code checkPermission} method
29.127 - * is called with a {@code ReflectPermission("suppressAccessChecks")} permission.
29.128 - * @param <T> the desired type of the result, either {@link Member} or a subtype
29.129 - * @param target a direct method handle to crack into symbolic reference components
29.130 - * @param expected a class object representing the desired result type {@code T}
29.131 - * @return a reference to the method, constructor, or field object
29.132 - * @exception SecurityException if the caller is not privileged to call {@code setAccessible}
29.133 - * @exception NullPointerException if either argument is {@code null}
29.134 - * @exception IllegalArgumentException if the target is not a direct method handle
29.135 - * @exception ClassCastException if the member is not of the expected type
29.136 - * @since 1.8
29.137 - */
29.138 - public static <T extends Member> T
29.139 - reflectAs(Class<T> expected, MethodHandle target) {
29.140 -// SecurityManager smgr = System.getSecurityManager();
29.141 -// if (smgr != null) smgr.checkPermission(ACCESS_PERMISSION);
29.142 - Lookup lookup = Lookup.IMPL_LOOKUP; // use maximally privileged lookup
29.143 - return lookup.revealDirect(target).reflectAs(expected, lookup);
29.144 - }
29.145 - // Copied from AccessibleObject, as used by Method.setAccessible, etc.:
29.146 -// static final private java.security.Permission ACCESS_PERMISSION =
29.147 -// new ReflectPermission("suppressAccessChecks");
29.148 -
29.149 - static Lookup findFor(Class<?> clazz) {
29.150 - Object o = clazz;
29.151 - if (o instanceof Class) {
29.152 - return new Lookup(clazz, Lookup.ALL_MODES);
29.153 - }
29.154 - throw new IllegalArgumentException("Expecting class: " + o);
29.155 - }
29.156 -
29.157 - /**
29.158 - * A <em>lookup object</em> is a factory for creating method handles,
29.159 - * when the creation requires access checking.
29.160 - * Method handles do not perform
29.161 - * access checks when they are called, but rather when they are created.
29.162 - * Therefore, method handle access
29.163 - * restrictions must be enforced when a method handle is created.
29.164 - * The caller class against which those restrictions are enforced
29.165 - * is known as the {@linkplain #lookupClass lookup class}.
29.166 - * <p>
29.167 - * A lookup class which needs to create method handles will call
29.168 - * {@link MethodHandles#lookup MethodHandles.lookup} to create a factory for itself.
29.169 - * When the {@code Lookup} factory object is created, the identity of the lookup class is
29.170 - * determined, and securely stored in the {@code Lookup} object.
29.171 - * The lookup class (or its delegates) may then use factory methods
29.172 - * on the {@code Lookup} object to create method handles for access-checked members.
29.173 - * This includes all methods, constructors, and fields which are allowed to the lookup class,
29.174 - * even private ones.
29.175 - *
29.176 - * <h1><a name="lookups"></a>Lookup Factory Methods</h1>
29.177 - * The factory methods on a {@code Lookup} object correspond to all major
29.178 - * use cases for methods, constructors, and fields.
29.179 - * Each method handle created by a factory method is the functional
29.180 - * equivalent of a particular <em>bytecode behavior</em>.
29.181 - * (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.)
29.182 - * Here is a summary of the correspondence between these factory methods and
29.183 - * the behavior the resulting method handles:
29.184 - * <table border=1 cellpadding=5 summary="lookup method behaviors">
29.185 - * <tr>
29.186 - * <th><a name="equiv"></a>lookup expression</th>
29.187 - * <th>member</th>
29.188 - * <th>bytecode behavior</th>
29.189 - * </tr>
29.190 - * <tr>
29.191 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
29.192 - * <td>{@code FT f;}</td><td>{@code (T) this.f;}</td>
29.193 - * </tr>
29.194 - * <tr>
29.195 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
29.196 - * <td>{@code static}<br>{@code FT f;}</td><td>{@code (T) C.f;}</td>
29.197 - * </tr>
29.198 - * <tr>
29.199 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
29.200 - * <td>{@code FT f;}</td><td>{@code this.f = x;}</td>
29.201 - * </tr>
29.202 - * <tr>
29.203 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
29.204 - * <td>{@code static}<br>{@code FT f;}</td><td>{@code C.f = arg;}</td>
29.205 - * </tr>
29.206 - * <tr>
29.207 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
29.208 - * <td>{@code T m(A*);}</td><td>{@code (T) this.m(arg*);}</td>
29.209 - * </tr>
29.210 - * <tr>
29.211 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
29.212 - * <td>{@code static}<br>{@code T m(A*);}</td><td>{@code (T) C.m(arg*);}</td>
29.213 - * </tr>
29.214 - * <tr>
29.215 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
29.216 - * <td>{@code T m(A*);}</td><td>{@code (T) super.m(arg*);}</td>
29.217 - * </tr>
29.218 - * <tr>
29.219 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
29.220 - * <td>{@code C(A*);}</td><td>{@code new C(arg*);}</td>
29.221 - * </tr>
29.222 - * <tr>
29.223 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
29.224 - * <td>({@code static})?<br>{@code FT f;}</td><td>{@code (FT) aField.get(thisOrNull);}</td>
29.225 - * </tr>
29.226 - * <tr>
29.227 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
29.228 - * <td>({@code static})?<br>{@code FT f;}</td><td>{@code aField.set(thisOrNull, arg);}</td>
29.229 - * </tr>
29.230 - * <tr>
29.231 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
29.232 - * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
29.233 - * </tr>
29.234 - * <tr>
29.235 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
29.236 - * <td>{@code C(A*);}</td><td>{@code (C) aConstructor.newInstance(arg*);}</td>
29.237 - * </tr>
29.238 - * <tr>
29.239 - * <td>{@link java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
29.240 - * <td>({@code static})?<br>{@code T m(A*);}</td><td>{@code (T) aMethod.invoke(thisOrNull, arg*);}</td>
29.241 - * </tr>
29.242 - * </table>
29.243 - *
29.244 - * Here, the type {@code C} is the class or interface being searched for a member,
29.245 - * documented as a parameter named {@code refc} in the lookup methods.
29.246 - * The method type {@code MT} is composed from the return type {@code T}
29.247 - * and the sequence of argument types {@code A*}.
29.248 - * The constructor also has a sequence of argument types {@code A*} and
29.249 - * is deemed to return the newly-created object of type {@code C}.
29.250 - * Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}.
29.251 - * The formal parameter {@code this} stands for the self-reference of type {@code C};
29.252 - * if it is present, it is always the leading argument to the method handle invocation.
29.253 - * (In the case of some {@code protected} members, {@code this} may be
29.254 - * restricted in type to the lookup class; see below.)
29.255 - * The name {@code arg} stands for all the other method handle arguments.
29.256 - * In the code examples for the Core Reflection API, the name {@code thisOrNull}
29.257 - * stands for a null reference if the accessed method or field is static,
29.258 - * and {@code this} otherwise.
29.259 - * The names {@code aMethod}, {@code aField}, and {@code aConstructor} stand
29.260 - * for reflective objects corresponding to the given members.
29.261 - * <p>
29.262 - * In cases where the given member is of variable arity (i.e., a method or constructor)
29.263 - * the returned method handle will also be of {@linkplain MethodHandle#asVarargsCollector variable arity}.
29.264 - * In all other cases, the returned method handle will be of fixed arity.
29.265 - * <p style="font-size:smaller;">
29.266 - * <em>Discussion:</em>
29.267 - * The equivalence between looked-up method handles and underlying
29.268 - * class members and bytecode behaviors
29.269 - * can break down in a few ways:
29.270 - * <ul style="font-size:smaller;">
29.271 - * <li>If {@code C} is not symbolically accessible from the lookup class's loader,
29.272 - * the lookup can still succeed, even when there is no equivalent
29.273 - * Java expression or bytecoded constant.
29.274 - * <li>Likewise, if {@code T} or {@code MT}
29.275 - * is not symbolically accessible from the lookup class's loader,
29.276 - * the lookup can still succeed.
29.277 - * For example, lookups for {@code MethodHandle.invokeExact} and
29.278 - * {@code MethodHandle.invoke} will always succeed, regardless of requested type.
29.279 - * <li>If there is a security manager installed, it can forbid the lookup
29.280 - * on various grounds (<a href="MethodHandles.Lookup.html#secmgr">see below</a>).
29.281 - * By contrast, the {@code ldc} instruction on a {@code CONSTANT_MethodHandle}
29.282 - * constant is not subject to security manager checks.
29.283 - * <li>If the looked-up method has a
29.284 - * <a href="MethodHandle.html#maxarity">very large arity</a>,
29.285 - * the method handle creation may fail, due to the method handle
29.286 - * type having too many parameters.
29.287 - * </ul>
29.288 - *
29.289 - * <h1><a name="access"></a>Access checking</h1>
29.290 - * Access checks are applied in the factory methods of {@code Lookup},
29.291 - * when a method handle is created.
29.292 - * This is a key difference from the Core Reflection API, since
29.293 - * {@link java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
29.294 - * performs access checking against every caller, on every call.
29.295 - * <p>
29.296 - * All access checks start from a {@code Lookup} object, which
29.297 - * compares its recorded lookup class against all requests to
29.298 - * create method handles.
29.299 - * A single {@code Lookup} object can be used to create any number
29.300 - * of access-checked method handles, all checked against a single
29.301 - * lookup class.
29.302 - * <p>
29.303 - * A {@code Lookup} object can be shared with other trusted code,
29.304 - * such as a metaobject protocol.
29.305 - * A shared {@code Lookup} object delegates the capability
29.306 - * to create method handles on private members of the lookup class.
29.307 - * Even if privileged code uses the {@code Lookup} object,
29.308 - * the access checking is confined to the privileges of the
29.309 - * original lookup class.
29.310 - * <p>
29.311 - * A lookup can fail, because
29.312 - * the containing class is not accessible to the lookup class, or
29.313 - * because the desired class member is missing, or because the
29.314 - * desired class member is not accessible to the lookup class, or
29.315 - * because the lookup object is not trusted enough to access the member.
29.316 - * In any of these cases, a {@code ReflectiveOperationException} will be
29.317 - * thrown from the attempted lookup. The exact class will be one of
29.318 - * the following:
29.319 - * <ul>
29.320 - * <li>NoSuchMethodException — if a method is requested but does not exist
29.321 - * <li>NoSuchFieldException — if a field is requested but does not exist
29.322 - * <li>IllegalAccessException — if the member exists but an access check fails
29.323 - * </ul>
29.324 - * <p>
29.325 - * In general, the conditions under which a method handle may be
29.326 - * looked up for a method {@code M} are no more restrictive than the conditions
29.327 - * under which the lookup class could have compiled, verified, and resolved a call to {@code M}.
29.328 - * Where the JVM would raise exceptions like {@code NoSuchMethodError},
29.329 - * a method handle lookup will generally raise a corresponding
29.330 - * checked exception, such as {@code NoSuchMethodException}.
29.331 - * And the effect of invoking the method handle resulting from the lookup
29.332 - * is <a href="MethodHandles.Lookup.html#equiv">exactly equivalent</a>
29.333 - * to executing the compiled, verified, and resolved call to {@code M}.
29.334 - * The same point is true of fields and constructors.
29.335 - * <p style="font-size:smaller;">
29.336 - * <em>Discussion:</em>
29.337 - * Access checks only apply to named and reflected methods,
29.338 - * constructors, and fields.
29.339 - * Other method handle creation methods, such as
29.340 - * {@link MethodHandle#asType MethodHandle.asType},
29.341 - * do not require any access checks, and are used
29.342 - * independently of any {@code Lookup} object.
29.343 - * <p>
29.344 - * If the desired member is {@code protected}, the usual JVM rules apply,
29.345 - * including the requirement that the lookup class must be either be in the
29.346 - * same package as the desired member, or must inherit that member.
29.347 - * (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.)
29.348 - * In addition, if the desired member is a non-static field or method
29.349 - * in a different package, the resulting method handle may only be applied
29.350 - * to objects of the lookup class or one of its subclasses.
29.351 - * This requirement is enforced by narrowing the type of the leading
29.352 - * {@code this} parameter from {@code C}
29.353 - * (which will necessarily be a superclass of the lookup class)
29.354 - * to the lookup class itself.
29.355 - * <p>
29.356 - * The JVM imposes a similar requirement on {@code invokespecial} instruction,
29.357 - * that the receiver argument must match both the resolved method <em>and</em>
29.358 - * the current class. Again, this requirement is enforced by narrowing the
29.359 - * type of the leading parameter to the resulting method handle.
29.360 - * (See the Java Virtual Machine Specification, section 4.10.1.9.)
29.361 - * <p>
29.362 - * The JVM represents constructors and static initializer blocks as internal methods
29.363 - * with special names ({@code "<init>"} and {@code "<clinit>"}).
29.364 - * The internal syntax of invocation instructions allows them to refer to such internal
29.365 - * methods as if they were normal methods, but the JVM bytecode verifier rejects them.
29.366 - * A lookup of such an internal method will produce a {@code NoSuchMethodException}.
29.367 - * <p>
29.368 - * In some cases, access between nested classes is obtained by the Java compiler by creating
29.369 - * an wrapper method to access a private method of another class
29.370 - * in the same top-level declaration.
29.371 - * For example, a nested class {@code C.D}
29.372 - * can access private members within other related classes such as
29.373 - * {@code C}, {@code C.D.E}, or {@code C.B},
29.374 - * but the Java compiler may need to generate wrapper methods in
29.375 - * those related classes. In such cases, a {@code Lookup} object on
29.376 - * {@code C.E} would be unable to those private members.
29.377 - * A workaround for this limitation is the {@link Lookup#in Lookup.in} method,
29.378 - * which can transform a lookup on {@code C.E} into one on any of those other
29.379 - * classes, without special elevation of privilege.
29.380 - * <p>
29.381 - * The accesses permitted to a given lookup object may be limited,
29.382 - * according to its set of {@link #lookupModes lookupModes},
29.383 - * to a subset of members normally accessible to the lookup class.
29.384 - * For example, the {@link MethodHandles#publicLookup publicLookup}
29.385 - * method produces a lookup object which is only allowed to access
29.386 - * public members in public classes.
29.387 - * The caller sensitive method {@link MethodHandles#lookup lookup}
29.388 - * produces a lookup object with full capabilities relative to
29.389 - * its caller class, to emulate all supported bytecode behaviors.
29.390 - * Also, the {@link Lookup#in Lookup.in} method may produce a lookup object
29.391 - * with fewer access modes than the original lookup object.
29.392 - *
29.393 - * <p style="font-size:smaller;">
29.394 - * <a name="privacc"></a>
29.395 - * <em>Discussion of private access:</em>
29.396 - * We say that a lookup has <em>private access</em>
29.397 - * if its {@linkplain #lookupModes lookup modes}
29.398 - * include the possibility of accessing {@code private} members.
29.399 - * As documented in the relevant methods elsewhere,
29.400 - * only lookups with private access possess the following capabilities:
29.401 - * <ul style="font-size:smaller;">
29.402 - * <li>access private fields, methods, and constructors of the lookup class
29.403 - * <li>create method handles which invoke <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a> methods,
29.404 - * such as {@code Class.forName}
29.405 - * <li>create method handles which {@link Lookup#findSpecial emulate invokespecial} instructions
29.406 - * <li>avoid <a href="MethodHandles.Lookup.html#secmgr">package access checks</a>
29.407 - * for classes accessible to the lookup class
29.408 - * <li>create {@link Lookup#in delegated lookup objects} which have private access to other classes
29.409 - * within the same package member
29.410 - * </ul>
29.411 - * <p style="font-size:smaller;">
29.412 - * Each of these permissions is a consequence of the fact that a lookup object
29.413 - * with private access can be securely traced back to an originating class,
29.414 - * whose <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> and Java language access permissions
29.415 - * can be reliably determined and emulated by method handles.
29.416 - *
29.417 - * <h1><a name="secmgr"></a>Security manager interactions</h1>
29.418 - * Although bytecode instructions can only refer to classes in
29.419 - * a related class loader, this API can search for methods in any
29.420 - * class, as long as a reference to its {@code Class} object is
29.421 - * available. Such cross-loader references are also possible with the
29.422 - * Core Reflection API, and are impossible to bytecode instructions
29.423 - * such as {@code invokestatic} or {@code getfield}.
29.424 - * There is a {@linkplain java.lang.SecurityManager security manager API}
29.425 - * to allow applications to check such cross-loader references.
29.426 - * These checks apply to both the {@code MethodHandles.Lookup} API
29.427 - * and the Core Reflection API
29.428 - * (as found on {@link java.lang.Class Class}).
29.429 - * <p>
29.430 - * If a security manager is present, member lookups are subject to
29.431 - * additional checks.
29.432 - * From one to three calls are made to the security manager.
29.433 - * Any of these calls can refuse access by throwing a
29.434 - * {@link java.lang.SecurityException SecurityException}.
29.435 - * Define {@code smgr} as the security manager,
29.436 - * {@code lookc} as the lookup class of the current lookup object,
29.437 - * {@code refc} as the containing class in which the member
29.438 - * is being sought, and {@code defc} as the class in which the
29.439 - * member is actually defined.
29.440 - * The value {@code lookc} is defined as <em>not present</em>
29.441 - * if the current lookup object does not have
29.442 - * <a href="MethodHandles.Lookup.html#privacc">private access</a>.
29.443 - * The calls are made according to the following rules:
29.444 - * <ul>
29.445 - * <li><b>Step 1:</b>
29.446 - * If {@code lookc} is not present, or if its class loader is not
29.447 - * the same as or an ancestor of the class loader of {@code refc},
29.448 - * then {@link SecurityManager#checkPackageAccess
29.449 - * smgr.checkPackageAccess(refcPkg)} is called,
29.450 - * where {@code refcPkg} is the package of {@code refc}.
29.451 - * <li><b>Step 2:</b>
29.452 - * If the retrieved member is not public and
29.453 - * {@code lookc} is not present, then
29.454 - * {@link SecurityManager#checkPermission smgr.checkPermission}
29.455 - * with {@code RuntimePermission("accessDeclaredMembers")} is called.
29.456 - * <li><b>Step 3:</b>
29.457 - * If the retrieved member is not public,
29.458 - * and if {@code lookc} is not present,
29.459 - * and if {@code defc} and {@code refc} are different,
29.460 - * then {@link SecurityManager#checkPackageAccess
29.461 - * smgr.checkPackageAccess(defcPkg)} is called,
29.462 - * where {@code defcPkg} is the package of {@code defc}.
29.463 - * </ul>
29.464 - * Security checks are performed after other access checks have passed.
29.465 - * Therefore, the above rules presuppose a member that is public,
29.466 - * or else that is being accessed from a lookup class that has
29.467 - * rights to access the member.
29.468 - *
29.469 - * <h1><a name="callsens"></a>Caller sensitive methods</h1>
29.470 - * A small number of Java methods have a special property called caller sensitivity.
29.471 - * A <em>caller-sensitive</em> method can behave differently depending on the
29.472 - * identity of its immediate caller.
29.473 - * <p>
29.474 - * If a method handle for a caller-sensitive method is requested,
29.475 - * the general rules for <a href="MethodHandles.Lookup.html#equiv">bytecode behaviors</a> apply,
29.476 - * but they take account of the lookup class in a special way.
29.477 - * The resulting method handle behaves as if it were called
29.478 - * from an instruction contained in the lookup class,
29.479 - * so that the caller-sensitive method detects the lookup class.
29.480 - * (By contrast, the invoker of the method handle is disregarded.)
29.481 - * Thus, in the case of caller-sensitive methods,
29.482 - * different lookup classes may give rise to
29.483 - * differently behaving method handles.
29.484 - * <p>
29.485 - * In cases where the lookup object is
29.486 - * {@link MethodHandles#publicLookup() publicLookup()},
29.487 - * or some other lookup object without
29.488 - * <a href="MethodHandles.Lookup.html#privacc">private access</a>,
29.489 - * the lookup class is disregarded.
29.490 - * In such cases, no caller-sensitive method handle can be created,
29.491 - * access is forbidden, and the lookup fails with an
29.492 - * {@code IllegalAccessException}.
29.493 - * <p style="font-size:smaller;">
29.494 - * <em>Discussion:</em>
29.495 - * For example, the caller-sensitive method
29.496 - * {@link java.lang.Class#forName(String) Class.forName(x)}
29.497 - * can return varying classes or throw varying exceptions,
29.498 - * depending on the class loader of the class that calls it.
29.499 - * A public lookup of {@code Class.forName} will fail, because
29.500 - * there is no reasonable way to determine its bytecode behavior.
29.501 - * <p style="font-size:smaller;">
29.502 - * If an application caches method handles for broad sharing,
29.503 - * it should use {@code publicLookup()} to create them.
29.504 - * If there is a lookup of {@code Class.forName}, it will fail,
29.505 - * and the application must take appropriate action in that case.
29.506 - * It may be that a later lookup, perhaps during the invocation of a
29.507 - * bootstrap method, can incorporate the specific identity
29.508 - * of the caller, making the method accessible.
29.509 - * <p style="font-size:smaller;">
29.510 - * The function {@code MethodHandles.lookup} is caller sensitive
29.511 - * so that there can be a secure foundation for lookups.
29.512 - * Nearly all other methods in the JSR 292 API rely on lookup
29.513 - * objects to check access requests.
29.514 - */
29.515 - public static final
29.516 - class Lookup {
29.517 - /** The class on behalf of whom the lookup is being performed. */
29.518 - private final Class<?> lookupClass;
29.519 -
29.520 - /** The allowed sorts of members which may be looked up (PUBLIC, etc.). */
29.521 - private final int allowedModes;
29.522 -
29.523 - /** A single-bit mask representing {@code public} access,
29.524 - * which may contribute to the result of {@link #lookupModes lookupModes}.
29.525 - * The value, {@code 0x01}, happens to be the same as the value of the
29.526 - * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}.
29.527 - */
29.528 - public static final int PUBLIC = Modifier.PUBLIC;
29.529 -
29.530 - /** A single-bit mask representing {@code private} access,
29.531 - * which may contribute to the result of {@link #lookupModes lookupModes}.
29.532 - * The value, {@code 0x02}, happens to be the same as the value of the
29.533 - * {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}.
29.534 - */
29.535 - public static final int PRIVATE = Modifier.PRIVATE;
29.536 -
29.537 - /** A single-bit mask representing {@code protected} access,
29.538 - * which may contribute to the result of {@link #lookupModes lookupModes}.
29.539 - * The value, {@code 0x04}, happens to be the same as the value of the
29.540 - * {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}.
29.541 - */
29.542 - public static final int PROTECTED = Modifier.PROTECTED;
29.543 -
29.544 - /** A single-bit mask representing {@code package} access (default access),
29.545 - * which may contribute to the result of {@link #lookupModes lookupModes}.
29.546 - * The value is {@code 0x08}, which does not correspond meaningfully to
29.547 - * any particular {@linkplain java.lang.reflect.Modifier modifier bit}.
29.548 - */
29.549 - public static final int PACKAGE = Modifier.STATIC;
29.550 -
29.551 - private static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE);
29.552 - private static final int TRUSTED = -1;
29.553 -
29.554 - private static int fixmods(int mods) {
29.555 - mods &= (ALL_MODES - PACKAGE);
29.556 - return (mods != 0) ? mods : PACKAGE;
29.557 - }
29.558 -
29.559 - /** Tells which class is performing the lookup. It is this class against
29.560 - * which checks are performed for visibility and access permissions.
29.561 - * <p>
29.562 - * The class implies a maximum level of access permission,
29.563 - * but the permissions may be additionally limited by the bitmask
29.564 - * {@link #lookupModes lookupModes}, which controls whether non-public members
29.565 - * can be accessed.
29.566 - * @return the lookup class, on behalf of which this lookup object finds members
29.567 - */
29.568 - public Class<?> lookupClass() {
29.569 - return lookupClass;
29.570 - }
29.571 -
29.572 - // This is just for calling out to MethodHandleImpl.
29.573 - private Class<?> lookupClassOrNull() {
29.574 - return (allowedModes == TRUSTED) ? null : lookupClass;
29.575 - }
29.576 -
29.577 - /** Tells which access-protection classes of members this lookup object can produce.
29.578 - * The result is a bit-mask of the bits
29.579 - * {@linkplain #PUBLIC PUBLIC (0x01)},
29.580 - * {@linkplain #PRIVATE PRIVATE (0x02)},
29.581 - * {@linkplain #PROTECTED PROTECTED (0x04)},
29.582 - * and {@linkplain #PACKAGE PACKAGE (0x08)}.
29.583 - * <p>
29.584 - * A freshly-created lookup object
29.585 - * on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class}
29.586 - * has all possible bits set, since the caller class can access all its own members.
29.587 - * A lookup object on a new lookup class
29.588 - * {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
29.589 - * may have some mode bits set to zero.
29.590 - * The purpose of this is to restrict access via the new lookup object,
29.591 - * so that it can access only names which can be reached by the original
29.592 - * lookup object, and also by the new lookup class.
29.593 - * @return the lookup modes, which limit the kinds of access performed by this lookup object
29.594 - */
29.595 - public int lookupModes() {
29.596 - return allowedModes & ALL_MODES;
29.597 - }
29.598 -
29.599 - /** Embody the current class (the lookupClass) as a lookup class
29.600 - * for method handle creation.
29.601 - * Must be called by from a method in this package,
29.602 - * which in turn is called by a method not in this package.
29.603 - */
29.604 - Lookup(Class<?> lookupClass) {
29.605 - this(lookupClass, ALL_MODES);
29.606 - // make sure we haven't accidentally picked up a privileged class:
29.607 - checkUnprivilegedlookupClass(lookupClass, ALL_MODES);
29.608 - }
29.609 -
29.610 - private Lookup(Class<?> lookupClass, int allowedModes) {
29.611 - this.lookupClass = lookupClass;
29.612 - this.allowedModes = allowedModes;
29.613 - }
29.614 -
29.615 - /**
29.616 - * Creates a lookup on the specified new lookup class.
29.617 - * The resulting object will report the specified
29.618 - * class as its own {@link #lookupClass lookupClass}.
29.619 - * <p>
29.620 - * However, the resulting {@code Lookup} object is guaranteed
29.621 - * to have no more access capabilities than the original.
29.622 - * In particular, access capabilities can be lost as follows:<ul>
29.623 - * <li>If the new lookup class differs from the old one,
29.624 - * protected members will not be accessible by virtue of inheritance.
29.625 - * (Protected members may continue to be accessible because of package sharing.)
29.626 - * <li>If the new lookup class is in a different package
29.627 - * than the old one, protected and default (package) members will not be accessible.
29.628 - * <li>If the new lookup class is not within the same package member
29.629 - * as the old one, private members will not be accessible.
29.630 - * <li>If the new lookup class is not accessible to the old lookup class,
29.631 - * then no members, not even public members, will be accessible.
29.632 - * (In all other cases, public members will continue to be accessible.)
29.633 - * </ul>
29.634 - *
29.635 - * @param requestedLookupClass the desired lookup class for the new lookup object
29.636 - * @return a lookup object which reports the desired lookup class
29.637 - * @throws NullPointerException if the argument is null
29.638 - */
29.639 - public Lookup in(Class<?> requestedLookupClass) {
29.640 - requestedLookupClass.getClass(); // null check
29.641 - if (allowedModes == TRUSTED) // IMPL_LOOKUP can make any lookup at all
29.642 - return new Lookup(requestedLookupClass, ALL_MODES);
29.643 - if (requestedLookupClass == this.lookupClass)
29.644 - return this; // keep same capabilities
29.645 - int newModes = (allowedModes & (ALL_MODES & ~PROTECTED));
29.646 - if ((newModes & PACKAGE) != 0
29.647 - && !VerifyAccess.isSamePackage(this.lookupClass, requestedLookupClass)) {
29.648 - newModes &= ~(PACKAGE|PRIVATE);
29.649 - }
29.650 - // Allow nestmate lookups to be created without special privilege:
29.651 - if ((newModes & PRIVATE) != 0
29.652 - && !VerifyAccess.isSamePackageMember(this.lookupClass, requestedLookupClass)) {
29.653 - newModes &= ~PRIVATE;
29.654 - }
29.655 - if ((newModes & PUBLIC) != 0
29.656 - && !VerifyAccess.isClassAccessible(requestedLookupClass, this.lookupClass, allowedModes)) {
29.657 - // The requested class it not accessible from the lookup class.
29.658 - // No permissions.
29.659 - newModes = 0;
29.660 - }
29.661 - checkUnprivilegedlookupClass(requestedLookupClass, newModes);
29.662 - return new Lookup(requestedLookupClass, newModes);
29.663 - }
29.664 -
29.665 - // Make sure outer class is initialized first.
29.666 - static { IMPL_NAMES.getClass(); }
29.667 -
29.668 - /** Version of lookup which is trusted minimally.
29.669 - * It can only be used to create method handles to
29.670 - * publicly accessible members.
29.671 - */
29.672 - static final Lookup PUBLIC_LOOKUP = new Lookup(Object.class, PUBLIC);
29.673 -
29.674 - /** Package-private version of lookup which is trusted. */
29.675 - static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED);
29.676 -
29.677 - private static void checkUnprivilegedlookupClass(Class<?> lookupClass, int allowedModes) {
29.678 - String name = lookupClass.getName();
29.679 - if (name.startsWith("java.lang.invoke."))
29.680 - throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
29.681 -
29.682 - // For caller-sensitive MethodHandles.lookup()
29.683 - // disallow lookup more restricted packages
29.684 - if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
29.685 - if (name.startsWith("java.") ||
29.686 - (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
29.687 - throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
29.688 - }
29.689 - }
29.690 - }
29.691 -
29.692 - /**
29.693 - * Displays the name of the class from which lookups are to be made.
29.694 - * (The name is the one reported by {@link java.lang.Class#getName() Class.getName}.)
29.695 - * If there are restrictions on the access permitted to this lookup,
29.696 - * this is indicated by adding a suffix to the class name, consisting
29.697 - * of a slash and a keyword. The keyword represents the strongest
29.698 - * allowed access, and is chosen as follows:
29.699 - * <ul>
29.700 - * <li>If no access is allowed, the suffix is "/noaccess".
29.701 - * <li>If only public access is allowed, the suffix is "/public".
29.702 - * <li>If only public and package access are allowed, the suffix is "/package".
29.703 - * <li>If only public, package, and private access are allowed, the suffix is "/private".
29.704 - * </ul>
29.705 - * If none of the above cases apply, it is the case that full
29.706 - * access (public, package, private, and protected) is allowed.
29.707 - * In this case, no suffix is added.
29.708 - * This is true only of an object obtained originally from
29.709 - * {@link java.lang.invoke.MethodHandles#lookup MethodHandles.lookup}.
29.710 - * Objects created by {@link java.lang.invoke.MethodHandles.Lookup#in Lookup.in}
29.711 - * always have restricted access, and will display a suffix.
29.712 - * <p>
29.713 - * (It may seem strange that protected access should be
29.714 - * stronger than private access. Viewed independently from
29.715 - * package access, protected access is the first to be lost,
29.716 - * because it requires a direct subclass relationship between
29.717 - * caller and callee.)
29.718 - * @see #in
29.719 - */
29.720 - @Override
29.721 - public String toString() {
29.722 - String cname = lookupClass.getName();
29.723 - switch (allowedModes) {
29.724 - case 0: // no privileges
29.725 - return cname + "/noaccess";
29.726 - case PUBLIC:
29.727 - return cname + "/public";
29.728 - case PUBLIC|PACKAGE:
29.729 - return cname + "/package";
29.730 - case ALL_MODES & ~PROTECTED:
29.731 - return cname + "/private";
29.732 - case ALL_MODES:
29.733 - return cname;
29.734 - case TRUSTED:
29.735 - return "/trusted"; // internal only; not exported
29.736 - default: // Should not happen, but it's a bitfield...
29.737 - cname = cname + "/" + Integer.toHexString(allowedModes);
29.738 - assert(false) : cname;
29.739 - return cname;
29.740 - }
29.741 - }
29.742 -
29.743 - /**
29.744 - * Produces a method handle for a static method.
29.745 - * The type of the method handle will be that of the method.
29.746 - * (Since static methods do not take receivers, there is no
29.747 - * additional receiver argument inserted into the method handle type,
29.748 - * as there would be with {@link #findVirtual findVirtual} or {@link #findSpecial findSpecial}.)
29.749 - * The method and all its argument types must be accessible to the lookup object.
29.750 - * <p>
29.751 - * The returned method handle will have
29.752 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.753 - * the method's variable arity modifier bit ({@code 0x0080}) is set.
29.754 - * <p>
29.755 - * If the returned method handle is invoked, the method's class will
29.756 - * be initialized, if it has not already been initialized.
29.757 - * <p><b>Example:</b>
29.758 - * <blockquote><pre>{@code
29.759 -import static java.lang.invoke.MethodHandles.*;
29.760 -import static java.lang.invoke.MethodType.*;
29.761 -...
29.762 -MethodHandle MH_asList = publicLookup().findStatic(Arrays.class,
29.763 - "asList", methodType(List.class, Object[].class));
29.764 -assertEquals("[x, y]", MH_asList.invoke("x", "y").toString());
29.765 - * }</pre></blockquote>
29.766 - * @param refc the class from which the method is accessed
29.767 - * @param name the name of the method
29.768 - * @param type the type of the method
29.769 - * @return the desired method handle
29.770 - * @throws NoSuchMethodException if the method does not exist
29.771 - * @throws IllegalAccessException if access checking fails,
29.772 - * or if the method is not {@code static},
29.773 - * or if the method's variable arity modifier bit
29.774 - * is set and {@code asVarargsCollector} fails
29.775 - * @exception SecurityException if a security manager is present and it
29.776 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.777 - * @throws NullPointerException if any argument is null
29.778 - */
29.779 - public
29.780 - MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
29.781 - MemberName method = resolveOrFail(REF_invokeStatic, refc, name, type);
29.782 - return getDirectMethod(REF_invokeStatic, refc, method, findBoundCallerClass(method));
29.783 - }
29.784 -
29.785 - /**
29.786 - * Produces a method handle for a virtual method.
29.787 - * The type of the method handle will be that of the method,
29.788 - * with the receiver type (usually {@code refc}) prepended.
29.789 - * The method and all its argument types must be accessible to the lookup object.
29.790 - * <p>
29.791 - * When called, the handle will treat the first argument as a receiver
29.792 - * and dispatch on the receiver's type to determine which method
29.793 - * implementation to enter.
29.794 - * (The dispatching action is identical with that performed by an
29.795 - * {@code invokevirtual} or {@code invokeinterface} instruction.)
29.796 - * <p>
29.797 - * The first argument will be of type {@code refc} if the lookup
29.798 - * class has full privileges to access the member. Otherwise
29.799 - * the member must be {@code protected} and the first argument
29.800 - * will be restricted in type to the lookup class.
29.801 - * <p>
29.802 - * The returned method handle will have
29.803 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.804 - * the method's variable arity modifier bit ({@code 0x0080}) is set.
29.805 - * <p>
29.806 - * Because of the general <a href="MethodHandles.Lookup.html#equiv">equivalence</a> between {@code invokevirtual}
29.807 - * instructions and method handles produced by {@code findVirtual},
29.808 - * if the class is {@code MethodHandle} and the name string is
29.809 - * {@code invokeExact} or {@code invoke}, the resulting
29.810 - * method handle is equivalent to one produced by
29.811 - * {@link java.lang.invoke.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
29.812 - * {@link java.lang.invoke.MethodHandles#invoker MethodHandles.invoker}
29.813 - * with the same {@code type} argument.
29.814 - *
29.815 - * <b>Example:</b>
29.816 - * <blockquote><pre>{@code
29.817 -import static java.lang.invoke.MethodHandles.*;
29.818 -import static java.lang.invoke.MethodType.*;
29.819 -...
29.820 -MethodHandle MH_concat = publicLookup().findVirtual(String.class,
29.821 - "concat", methodType(String.class, String.class));
29.822 -MethodHandle MH_hashCode = publicLookup().findVirtual(Object.class,
29.823 - "hashCode", methodType(int.class));
29.824 -MethodHandle MH_hashCode_String = publicLookup().findVirtual(String.class,
29.825 - "hashCode", methodType(int.class));
29.826 -assertEquals("xy", (String) MH_concat.invokeExact("x", "y"));
29.827 -assertEquals("xy".hashCode(), (int) MH_hashCode.invokeExact((Object)"xy"));
29.828 -assertEquals("xy".hashCode(), (int) MH_hashCode_String.invokeExact("xy"));
29.829 -// interface method:
29.830 -MethodHandle MH_subSequence = publicLookup().findVirtual(CharSequence.class,
29.831 - "subSequence", methodType(CharSequence.class, int.class, int.class));
29.832 -assertEquals("def", MH_subSequence.invoke("abcdefghi", 3, 6).toString());
29.833 -// constructor "internal method" must be accessed differently:
29.834 -MethodType MT_newString = methodType(void.class); //()V for new String()
29.835 -try { assertEquals("impossible", lookup()
29.836 - .findVirtual(String.class, "<init>", MT_newString));
29.837 - } catch (NoSuchMethodException ex) { } // OK
29.838 -MethodHandle MH_newString = publicLookup()
29.839 - .findConstructor(String.class, MT_newString);
29.840 -assertEquals("", (String) MH_newString.invokeExact());
29.841 - * }</pre></blockquote>
29.842 - *
29.843 - * @param refc the class or interface from which the method is accessed
29.844 - * @param name the name of the method
29.845 - * @param type the type of the method, with the receiver argument omitted
29.846 - * @return the desired method handle
29.847 - * @throws NoSuchMethodException if the method does not exist
29.848 - * @throws IllegalAccessException if access checking fails,
29.849 - * or if the method is {@code static}
29.850 - * or if the method's variable arity modifier bit
29.851 - * is set and {@code asVarargsCollector} fails
29.852 - * @exception SecurityException if a security manager is present and it
29.853 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.854 - * @throws NullPointerException if any argument is null
29.855 - */
29.856 - public MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
29.857 - if (refc == MethodHandle.class) {
29.858 - MethodHandle mh = findVirtualForMH(name, type);
29.859 - if (mh != null) return mh;
29.860 - }
29.861 - byte refKind = (refc.isInterface() ? REF_invokeInterface : REF_invokeVirtual);
29.862 - MemberName method = resolveOrFail(refKind, refc, name, type);
29.863 - return getDirectMethod(refKind, refc, method, findBoundCallerClass(method));
29.864 - }
29.865 - private MethodHandle findVirtualForMH(String name, MethodType type) {
29.866 - // these names require special lookups because of the implicit MethodType argument
29.867 - if ("invoke".equals(name))
29.868 - return invoker(type);
29.869 - if ("invokeExact".equals(name))
29.870 - return exactInvoker(type);
29.871 - assert(!MemberName.isMethodHandleInvokeName(name));
29.872 - return null;
29.873 - }
29.874 -
29.875 - /**
29.876 - * Produces a method handle which creates an object and initializes it, using
29.877 - * the constructor of the specified type.
29.878 - * The parameter types of the method handle will be those of the constructor,
29.879 - * while the return type will be a reference to the constructor's class.
29.880 - * The constructor and all its argument types must be accessible to the lookup object.
29.881 - * <p>
29.882 - * The requested type must have a return type of {@code void}.
29.883 - * (This is consistent with the JVM's treatment of constructor type descriptors.)
29.884 - * <p>
29.885 - * The returned method handle will have
29.886 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.887 - * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
29.888 - * <p>
29.889 - * If the returned method handle is invoked, the constructor's class will
29.890 - * be initialized, if it has not already been initialized.
29.891 - * <p><b>Example:</b>
29.892 - * <blockquote><pre>{@code
29.893 -import static java.lang.invoke.MethodHandles.*;
29.894 -import static java.lang.invoke.MethodType.*;
29.895 -...
29.896 -MethodHandle MH_newArrayList = publicLookup().findConstructor(
29.897 - ArrayList.class, methodType(void.class, Collection.class));
29.898 -Collection orig = Arrays.asList("x", "y");
29.899 -Collection copy = (ArrayList) MH_newArrayList.invokeExact(orig);
29.900 -assert(orig != copy);
29.901 -assertEquals(orig, copy);
29.902 -// a variable-arity constructor:
29.903 -MethodHandle MH_newProcessBuilder = publicLookup().findConstructor(
29.904 - ProcessBuilder.class, methodType(void.class, String[].class));
29.905 -ProcessBuilder pb = (ProcessBuilder)
29.906 - MH_newProcessBuilder.invoke("x", "y", "z");
29.907 -assertEquals("[x, y, z]", pb.command().toString());
29.908 - * }</pre></blockquote>
29.909 - * @param refc the class or interface from which the method is accessed
29.910 - * @param type the type of the method, with the receiver argument omitted, and a void return type
29.911 - * @return the desired method handle
29.912 - * @throws NoSuchMethodException if the constructor does not exist
29.913 - * @throws IllegalAccessException if access checking fails
29.914 - * or if the method's variable arity modifier bit
29.915 - * is set and {@code asVarargsCollector} fails
29.916 - * @exception SecurityException if a security manager is present and it
29.917 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.918 - * @throws NullPointerException if any argument is null
29.919 - */
29.920 - public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
29.921 - String name = "<init>";
29.922 - MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
29.923 - return getDirectConstructor(refc, ctor);
29.924 - }
29.925 -
29.926 - /**
29.927 - * Produces an early-bound method handle for a virtual method.
29.928 - * It will bypass checks for overriding methods on the receiver,
29.929 - * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
29.930 - * instruction from within the explicitly specified {@code specialCaller}.
29.931 - * The type of the method handle will be that of the method,
29.932 - * with a suitably restricted receiver type prepended.
29.933 - * (The receiver type will be {@code specialCaller} or a subtype.)
29.934 - * The method and all its argument types must be accessible
29.935 - * to the lookup object.
29.936 - * <p>
29.937 - * Before method resolution,
29.938 - * if the explicitly specified caller class is not identical with the
29.939 - * lookup class, or if this lookup object does not have
29.940 - * <a href="MethodHandles.Lookup.html#privacc">private access</a>
29.941 - * privileges, the access fails.
29.942 - * <p>
29.943 - * The returned method handle will have
29.944 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.945 - * the method's variable arity modifier bit ({@code 0x0080}) is set.
29.946 - * <p style="font-size:smaller;">
29.947 - * <em>(Note: JVM internal methods named {@code "<init>"} are not visible to this API,
29.948 - * even though the {@code invokespecial} instruction can refer to them
29.949 - * in special circumstances. Use {@link #findConstructor findConstructor}
29.950 - * to access instance initialization methods in a safe manner.)</em>
29.951 - * <p><b>Example:</b>
29.952 - * <blockquote><pre>{@code
29.953 -import static java.lang.invoke.MethodHandles.*;
29.954 -import static java.lang.invoke.MethodType.*;
29.955 -...
29.956 -static class Listie extends ArrayList {
29.957 - public String toString() { return "[wee Listie]"; }
29.958 - static Lookup lookup() { return MethodHandles.lookup(); }
29.959 -}
29.960 -...
29.961 -// no access to constructor via invokeSpecial:
29.962 -MethodHandle MH_newListie = Listie.lookup()
29.963 - .findConstructor(Listie.class, methodType(void.class));
29.964 -Listie l = (Listie) MH_newListie.invokeExact();
29.965 -try { assertEquals("impossible", Listie.lookup().findSpecial(
29.966 - Listie.class, "<init>", methodType(void.class), Listie.class));
29.967 - } catch (NoSuchMethodException ex) { } // OK
29.968 -// access to super and self methods via invokeSpecial:
29.969 -MethodHandle MH_super = Listie.lookup().findSpecial(
29.970 - ArrayList.class, "toString" , methodType(String.class), Listie.class);
29.971 -MethodHandle MH_this = Listie.lookup().findSpecial(
29.972 - Listie.class, "toString" , methodType(String.class), Listie.class);
29.973 -MethodHandle MH_duper = Listie.lookup().findSpecial(
29.974 - Object.class, "toString" , methodType(String.class), Listie.class);
29.975 -assertEquals("[]", (String) MH_super.invokeExact(l));
29.976 -assertEquals(""+l, (String) MH_this.invokeExact(l));
29.977 -assertEquals("[]", (String) MH_duper.invokeExact(l)); // ArrayList method
29.978 -try { assertEquals("inaccessible", Listie.lookup().findSpecial(
29.979 - String.class, "toString", methodType(String.class), Listie.class));
29.980 - } catch (IllegalAccessException ex) { } // OK
29.981 -Listie subl = new Listie() { public String toString() { return "[subclass]"; } };
29.982 -assertEquals(""+l, (String) MH_this.invokeExact(subl)); // Listie method
29.983 - * }</pre></blockquote>
29.984 - *
29.985 - * @param refc the class or interface from which the method is accessed
29.986 - * @param name the name of the method (which must not be "<init>")
29.987 - * @param type the type of the method, with the receiver argument omitted
29.988 - * @param specialCaller the proposed calling class to perform the {@code invokespecial}
29.989 - * @return the desired method handle
29.990 - * @throws NoSuchMethodException if the method does not exist
29.991 - * @throws IllegalAccessException if access checking fails
29.992 - * or if the method's variable arity modifier bit
29.993 - * is set and {@code asVarargsCollector} fails
29.994 - * @exception SecurityException if a security manager is present and it
29.995 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.996 - * @throws NullPointerException if any argument is null
29.997 - */
29.998 - public MethodHandle findSpecial(Class<?> refc, String name, MethodType type,
29.999 - Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException {
29.1000 - checkSpecialCaller(specialCaller);
29.1001 - Lookup specialLookup = this.in(specialCaller);
29.1002 - MemberName method = specialLookup.resolveOrFail(REF_invokeSpecial, refc, name, type);
29.1003 - return specialLookup.getDirectMethod(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
29.1004 - }
29.1005 -
29.1006 - /**
29.1007 - * Produces a method handle giving read access to a non-static field.
29.1008 - * The type of the method handle will have a return type of the field's
29.1009 - * value type.
29.1010 - * The method handle's single argument will be the instance containing
29.1011 - * the field.
29.1012 - * Access checking is performed immediately on behalf of the lookup class.
29.1013 - * @param refc the class or interface from which the method is accessed
29.1014 - * @param name the field's name
29.1015 - * @param type the field's type
29.1016 - * @return a method handle which can load values from the field
29.1017 - * @throws NoSuchFieldException if the field does not exist
29.1018 - * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
29.1019 - * @exception SecurityException if a security manager is present and it
29.1020 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1021 - * @throws NullPointerException if any argument is null
29.1022 - */
29.1023 - public MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
29.1024 - MemberName field = resolveOrFail(REF_getField, refc, name, type);
29.1025 - return getDirectField(REF_getField, refc, field);
29.1026 - }
29.1027 -
29.1028 - /**
29.1029 - * Produces a method handle giving write access to a non-static field.
29.1030 - * The type of the method handle will have a void return type.
29.1031 - * The method handle will take two arguments, the instance containing
29.1032 - * the field, and the value to be stored.
29.1033 - * The second argument will be of the field's value type.
29.1034 - * Access checking is performed immediately on behalf of the lookup class.
29.1035 - * @param refc the class or interface from which the method is accessed
29.1036 - * @param name the field's name
29.1037 - * @param type the field's type
29.1038 - * @return a method handle which can store values into the field
29.1039 - * @throws NoSuchFieldException if the field does not exist
29.1040 - * @throws IllegalAccessException if access checking fails, or if the field is {@code static}
29.1041 - * @exception SecurityException if a security manager is present and it
29.1042 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1043 - * @throws NullPointerException if any argument is null
29.1044 - */
29.1045 - public MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
29.1046 - MemberName field = resolveOrFail(REF_putField, refc, name, type);
29.1047 - return getDirectField(REF_putField, refc, field);
29.1048 - }
29.1049 -
29.1050 - /**
29.1051 - * Produces a method handle giving read access to a static field.
29.1052 - * The type of the method handle will have a return type of the field's
29.1053 - * value type.
29.1054 - * The method handle will take no arguments.
29.1055 - * Access checking is performed immediately on behalf of the lookup class.
29.1056 - * <p>
29.1057 - * If the returned method handle is invoked, the field's class will
29.1058 - * be initialized, if it has not already been initialized.
29.1059 - * @param refc the class or interface from which the method is accessed
29.1060 - * @param name the field's name
29.1061 - * @param type the field's type
29.1062 - * @return a method handle which can load values from the field
29.1063 - * @throws NoSuchFieldException if the field does not exist
29.1064 - * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
29.1065 - * @exception SecurityException if a security manager is present and it
29.1066 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1067 - * @throws NullPointerException if any argument is null
29.1068 - */
29.1069 - public MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
29.1070 - MemberName field = resolveOrFail(REF_getStatic, refc, name, type);
29.1071 - return getDirectField(REF_getStatic, refc, field);
29.1072 - }
29.1073 -
29.1074 - /**
29.1075 - * Produces a method handle giving write access to a static field.
29.1076 - * The type of the method handle will have a void return type.
29.1077 - * The method handle will take a single
29.1078 - * argument, of the field's value type, the value to be stored.
29.1079 - * Access checking is performed immediately on behalf of the lookup class.
29.1080 - * <p>
29.1081 - * If the returned method handle is invoked, the field's class will
29.1082 - * be initialized, if it has not already been initialized.
29.1083 - * @param refc the class or interface from which the method is accessed
29.1084 - * @param name the field's name
29.1085 - * @param type the field's type
29.1086 - * @return a method handle which can store values into the field
29.1087 - * @throws NoSuchFieldException if the field does not exist
29.1088 - * @throws IllegalAccessException if access checking fails, or if the field is not {@code static}
29.1089 - * @exception SecurityException if a security manager is present and it
29.1090 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1091 - * @throws NullPointerException if any argument is null
29.1092 - */
29.1093 - public MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
29.1094 - MemberName field = resolveOrFail(REF_putStatic, refc, name, type);
29.1095 - return getDirectField(REF_putStatic, refc, field);
29.1096 - }
29.1097 -
29.1098 - /**
29.1099 - * Produces an early-bound method handle for a non-static method.
29.1100 - * The receiver must have a supertype {@code defc} in which a method
29.1101 - * of the given name and type is accessible to the lookup class.
29.1102 - * The method and all its argument types must be accessible to the lookup object.
29.1103 - * The type of the method handle will be that of the method,
29.1104 - * without any insertion of an additional receiver parameter.
29.1105 - * The given receiver will be bound into the method handle,
29.1106 - * so that every call to the method handle will invoke the
29.1107 - * requested method on the given receiver.
29.1108 - * <p>
29.1109 - * The returned method handle will have
29.1110 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.1111 - * the method's variable arity modifier bit ({@code 0x0080}) is set
29.1112 - * <em>and</em> the trailing array argument is not the only argument.
29.1113 - * (If the trailing array argument is the only argument,
29.1114 - * the given receiver value will be bound to it.)
29.1115 - * <p>
29.1116 - * This is equivalent to the following code:
29.1117 - * <blockquote><pre>{@code
29.1118 -import static java.lang.invoke.MethodHandles.*;
29.1119 -import static java.lang.invoke.MethodType.*;
29.1120 -...
29.1121 -MethodHandle mh0 = lookup().findVirtual(defc, name, type);
29.1122 -MethodHandle mh1 = mh0.bindTo(receiver);
29.1123 -MethodType mt1 = mh1.type();
29.1124 -if (mh0.isVarargsCollector())
29.1125 - mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
29.1126 -return mh1;
29.1127 - * }</pre></blockquote>
29.1128 - * where {@code defc} is either {@code receiver.getClass()} or a super
29.1129 - * type of that class, in which the requested method is accessible
29.1130 - * to the lookup class.
29.1131 - * (Note that {@code bindTo} does not preserve variable arity.)
29.1132 - * @param receiver the object from which the method is accessed
29.1133 - * @param name the name of the method
29.1134 - * @param type the type of the method, with the receiver argument omitted
29.1135 - * @return the desired method handle
29.1136 - * @throws NoSuchMethodException if the method does not exist
29.1137 - * @throws IllegalAccessException if access checking fails
29.1138 - * or if the method's variable arity modifier bit
29.1139 - * is set and {@code asVarargsCollector} fails
29.1140 - * @exception SecurityException if a security manager is present and it
29.1141 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1142 - * @throws NullPointerException if any argument is null
29.1143 - * @see MethodHandle#bindTo
29.1144 - * @see #findVirtual
29.1145 - */
29.1146 - public MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
29.1147 - Class<? extends Object> refc = receiver.getClass(); // may get NPE
29.1148 - MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
29.1149 - MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
29.1150 - return mh.bindReceiver(receiver).setVarargs(method);
29.1151 - }
29.1152 -
29.1153 - /**
29.1154 - * Makes a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
29.1155 - * to <i>m</i>, if the lookup class has permission.
29.1156 - * If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
29.1157 - * If <i>m</i> is virtual, overriding is respected on every call.
29.1158 - * Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
29.1159 - * The type of the method handle will be that of the method,
29.1160 - * with the receiver type prepended (but only if it is non-static).
29.1161 - * If the method's {@code accessible} flag is not set,
29.1162 - * access checking is performed immediately on behalf of the lookup class.
29.1163 - * If <i>m</i> is not public, do not share the resulting handle with untrusted parties.
29.1164 - * <p>
29.1165 - * The returned method handle will have
29.1166 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.1167 - * the method's variable arity modifier bit ({@code 0x0080}) is set.
29.1168 - * <p>
29.1169 - * If <i>m</i> is static, and
29.1170 - * if the returned method handle is invoked, the method's class will
29.1171 - * be initialized, if it has not already been initialized.
29.1172 - * @param m the reflected method
29.1173 - * @return a method handle which can invoke the reflected method
29.1174 - * @throws IllegalAccessException if access checking fails
29.1175 - * or if the method's variable arity modifier bit
29.1176 - * is set and {@code asVarargsCollector} fails
29.1177 - * @throws NullPointerException if the argument is null
29.1178 - */
29.1179 - public MethodHandle unreflect(Method m) throws IllegalAccessException {
29.1180 - if (m.getDeclaringClass() == MethodHandle.class) {
29.1181 - MethodHandle mh = unreflectForMH(m);
29.1182 - if (mh != null) return mh;
29.1183 - }
29.1184 - MemberName method = new MemberName(m);
29.1185 - byte refKind = method.getReferenceKind();
29.1186 - if (refKind == REF_invokeSpecial)
29.1187 - refKind = REF_invokeVirtual;
29.1188 - assert(method.isMethod());
29.1189 - Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this;
29.1190 - return lookup.getDirectMethodNoSecurityManager(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method));
29.1191 - }
29.1192 - private MethodHandle unreflectForMH(Method m) {
29.1193 - // these names require special lookups because they throw UnsupportedOperationException
29.1194 - if (MemberName.isMethodHandleInvokeName(m.getName()))
29.1195 - return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m));
29.1196 - return null;
29.1197 - }
29.1198 -
29.1199 - /**
29.1200 - * Produces a method handle for a reflected method.
29.1201 - * It will bypass checks for overriding methods on the receiver,
29.1202 - * <a href="MethodHandles.Lookup.html#equiv">as if called</a> from an {@code invokespecial}
29.1203 - * instruction from within the explicitly specified {@code specialCaller}.
29.1204 - * The type of the method handle will be that of the method,
29.1205 - * with a suitably restricted receiver type prepended.
29.1206 - * (The receiver type will be {@code specialCaller} or a subtype.)
29.1207 - * If the method's {@code accessible} flag is not set,
29.1208 - * access checking is performed immediately on behalf of the lookup class,
29.1209 - * as if {@code invokespecial} instruction were being linked.
29.1210 - * <p>
29.1211 - * Before method resolution,
29.1212 - * if the explicitly specified caller class is not identical with the
29.1213 - * lookup class, or if this lookup object does not have
29.1214 - * <a href="MethodHandles.Lookup.html#privacc">private access</a>
29.1215 - * privileges, the access fails.
29.1216 - * <p>
29.1217 - * The returned method handle will have
29.1218 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.1219 - * the method's variable arity modifier bit ({@code 0x0080}) is set.
29.1220 - * @param m the reflected method
29.1221 - * @param specialCaller the class nominally calling the method
29.1222 - * @return a method handle which can invoke the reflected method
29.1223 - * @throws IllegalAccessException if access checking fails
29.1224 - * or if the method's variable arity modifier bit
29.1225 - * is set and {@code asVarargsCollector} fails
29.1226 - * @throws NullPointerException if any argument is null
29.1227 - */
29.1228 - public MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException {
29.1229 - checkSpecialCaller(specialCaller);
29.1230 - Lookup specialLookup = this.in(specialCaller);
29.1231 - MemberName method = new MemberName(m, true);
29.1232 - assert(method.isMethod());
29.1233 - // ignore m.isAccessible: this is a new kind of access
29.1234 - return specialLookup.getDirectMethodNoSecurityManager(REF_invokeSpecial, method.getDeclaringClass(), method, findBoundCallerClass(method));
29.1235 - }
29.1236 -
29.1237 - /**
29.1238 - * Produces a method handle for a reflected constructor.
29.1239 - * The type of the method handle will be that of the constructor,
29.1240 - * with the return type changed to the declaring class.
29.1241 - * The method handle will perform a {@code newInstance} operation,
29.1242 - * creating a new instance of the constructor's class on the
29.1243 - * arguments passed to the method handle.
29.1244 - * <p>
29.1245 - * If the constructor's {@code accessible} flag is not set,
29.1246 - * access checking is performed immediately on behalf of the lookup class.
29.1247 - * <p>
29.1248 - * The returned method handle will have
29.1249 - * {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if
29.1250 - * the constructor's variable arity modifier bit ({@code 0x0080}) is set.
29.1251 - * <p>
29.1252 - * If the returned method handle is invoked, the constructor's class will
29.1253 - * be initialized, if it has not already been initialized.
29.1254 - * @param c the reflected constructor
29.1255 - * @return a method handle which can invoke the reflected constructor
29.1256 - * @throws IllegalAccessException if access checking fails
29.1257 - * or if the method's variable arity modifier bit
29.1258 - * is set and {@code asVarargsCollector} fails
29.1259 - * @throws NullPointerException if the argument is null
29.1260 - */
29.1261 - public MethodHandle unreflectConstructor(Constructor<?> c) throws IllegalAccessException {
29.1262 - MemberName ctor = new MemberName(c);
29.1263 - assert(ctor.isConstructor());
29.1264 - Lookup lookup = c.isAccessible() ? IMPL_LOOKUP : this;
29.1265 - return lookup.getDirectConstructorNoSecurityManager(ctor.getDeclaringClass(), ctor);
29.1266 - }
29.1267 -
29.1268 - /**
29.1269 - * Produces a method handle giving read access to a reflected field.
29.1270 - * The type of the method handle will have a return type of the field's
29.1271 - * value type.
29.1272 - * If the field is static, the method handle will take no arguments.
29.1273 - * Otherwise, its single argument will be the instance containing
29.1274 - * the field.
29.1275 - * If the field's {@code accessible} flag is not set,
29.1276 - * access checking is performed immediately on behalf of the lookup class.
29.1277 - * <p>
29.1278 - * If the field is static, and
29.1279 - * if the returned method handle is invoked, the field's class will
29.1280 - * be initialized, if it has not already been initialized.
29.1281 - * @param f the reflected field
29.1282 - * @return a method handle which can load values from the reflected field
29.1283 - * @throws IllegalAccessException if access checking fails
29.1284 - * @throws NullPointerException if the argument is null
29.1285 - */
29.1286 - public MethodHandle unreflectGetter(Field f) throws IllegalAccessException {
29.1287 - return unreflectField(f, false);
29.1288 - }
29.1289 - private MethodHandle unreflectField(Field f, boolean isSetter) throws IllegalAccessException {
29.1290 - MemberName field = new MemberName(f, isSetter);
29.1291 - assert(isSetter
29.1292 - ? MethodHandleNatives.refKindIsSetter(field.getReferenceKind())
29.1293 - : MethodHandleNatives.refKindIsGetter(field.getReferenceKind()));
29.1294 - Lookup lookup = f.isAccessible() ? IMPL_LOOKUP : this;
29.1295 - return lookup.getDirectFieldNoSecurityManager(field.getReferenceKind(), f.getDeclaringClass(), field);
29.1296 - }
29.1297 -
29.1298 - /**
29.1299 - * Produces a method handle giving write access to a reflected field.
29.1300 - * The type of the method handle will have a void return type.
29.1301 - * If the field is static, the method handle will take a single
29.1302 - * argument, of the field's value type, the value to be stored.
29.1303 - * Otherwise, the two arguments will be the instance containing
29.1304 - * the field, and the value to be stored.
29.1305 - * If the field's {@code accessible} flag is not set,
29.1306 - * access checking is performed immediately on behalf of the lookup class.
29.1307 - * <p>
29.1308 - * If the field is static, and
29.1309 - * if the returned method handle is invoked, the field's class will
29.1310 - * be initialized, if it has not already been initialized.
29.1311 - * @param f the reflected field
29.1312 - * @return a method handle which can store values into the reflected field
29.1313 - * @throws IllegalAccessException if access checking fails
29.1314 - * @throws NullPointerException if the argument is null
29.1315 - */
29.1316 - public MethodHandle unreflectSetter(Field f) throws IllegalAccessException {
29.1317 - return unreflectField(f, true);
29.1318 - }
29.1319 -
29.1320 - /**
29.1321 - * Cracks a <a href="MethodHandleInfo.html#directmh">direct method handle</a>
29.1322 - * created by this lookup object or a similar one.
29.1323 - * Security and access checks are performed to ensure that this lookup object
29.1324 - * is capable of reproducing the target method handle.
29.1325 - * This means that the cracking may fail if target is a direct method handle
29.1326 - * but was created by an unrelated lookup object.
29.1327 - * This can happen if the method handle is <a href="MethodHandles.Lookup.html#callsens">caller sensitive</a>
29.1328 - * and was created by a lookup object for a different class.
29.1329 - * @param target a direct method handle to crack into symbolic reference components
29.1330 - * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object
29.1331 - * @exception SecurityException if a security manager is present and it
29.1332 - * <a href="MethodHandles.Lookup.html#secmgr">refuses access</a>
29.1333 - * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails
29.1334 - * @exception NullPointerException if the target is {@code null}
29.1335 - * @see MethodHandleInfo
29.1336 - * @since 1.8
29.1337 - */
29.1338 - public MethodHandleInfo revealDirect(MethodHandle target) {
29.1339 - MemberName member = target.internalMemberName();
29.1340 - if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke()))
29.1341 - throw newIllegalArgumentException("not a direct method handle");
29.1342 - Class<?> defc = member.getDeclaringClass();
29.1343 - byte refKind = member.getReferenceKind();
29.1344 - assert(MethodHandleNatives.refKindIsValid(refKind));
29.1345 - if (refKind == REF_invokeSpecial && !target.isInvokeSpecial())
29.1346 - // Devirtualized method invocation is usually formally virtual.
29.1347 - // To avoid creating extra MemberName objects for this common case,
29.1348 - // we encode this extra degree of freedom using MH.isInvokeSpecial.
29.1349 - refKind = REF_invokeVirtual;
29.1350 - if (refKind == REF_invokeVirtual && defc.isInterface())
29.1351 - // Symbolic reference is through interface but resolves to Object method (toString, etc.)
29.1352 - refKind = REF_invokeInterface;
29.1353 - // Check SM permissions and member access before cracking.
29.1354 - try {
29.1355 - checkAccess(refKind, defc, member);
29.1356 - checkSecurityManager(defc, member);
29.1357 - } catch (IllegalAccessException ex) {
29.1358 - throw new IllegalArgumentException(ex);
29.1359 - }
29.1360 - if (allowedModes != TRUSTED && member.isCallerSensitive()) {
29.1361 - Class<?> callerClass = target.internalCallerClass();
29.1362 - if (!hasPrivateAccess() || callerClass != lookupClass())
29.1363 - throw new IllegalArgumentException("method handle is caller sensitive: "+callerClass);
29.1364 - }
29.1365 - // Produce the handle to the results.
29.1366 - return new InfoFromMemberName(this, member, refKind);
29.1367 - }
29.1368 -
29.1369 - /// Helper methods, all package-private.
29.1370 -
29.1371 - MemberName resolveOrFail(byte refKind, Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException {
29.1372 - checkSymbolicClass(refc); // do this before attempting to resolve
29.1373 - name.getClass(); // NPE
29.1374 - type.getClass(); // NPE
29.1375 - return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
29.1376 - NoSuchFieldException.class);
29.1377 - }
29.1378 -
29.1379 - MemberName resolveOrFail(byte refKind, Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException {
29.1380 - checkSymbolicClass(refc); // do this before attempting to resolve
29.1381 - name.getClass(); // NPE
29.1382 - type.getClass(); // NPE
29.1383 - checkMethodName(refKind, name); // NPE check on name
29.1384 - return IMPL_NAMES.resolveOrFail(refKind, new MemberName(refc, name, type, refKind), lookupClassOrNull(),
29.1385 - NoSuchMethodException.class);
29.1386 - }
29.1387 -
29.1388 - MemberName resolveOrFail(byte refKind, MemberName member) throws ReflectiveOperationException {
29.1389 - checkSymbolicClass(member.getDeclaringClass()); // do this before attempting to resolve
29.1390 - member.getName().getClass(); // NPE
29.1391 - member.getType().getClass(); // NPE
29.1392 - return IMPL_NAMES.resolveOrFail(refKind, member, lookupClassOrNull(),
29.1393 - ReflectiveOperationException.class);
29.1394 - }
29.1395 -
29.1396 - void checkSymbolicClass(Class<?> refc) throws IllegalAccessException {
29.1397 - refc.getClass(); // NPE
29.1398 - Class<?> caller = lookupClassOrNull();
29.1399 - if (caller != null && !VerifyAccess.isClassAccessible(refc, caller, allowedModes))
29.1400 - throw new MemberName(refc).makeAccessException("symbolic reference class is not public", this);
29.1401 - }
29.1402 -
29.1403 - /** Check name for an illegal leading "<" character. */
29.1404 - void checkMethodName(byte refKind, String name) throws NoSuchMethodException {
29.1405 - if (name.startsWith("<") && refKind != REF_newInvokeSpecial)
29.1406 - throw new NoSuchMethodException("illegal method name: "+name);
29.1407 - }
29.1408 -
29.1409 -
29.1410 - /**
29.1411 - * Find my trustable caller class if m is a caller sensitive method.
29.1412 - * If this lookup object has private access, then the caller class is the lookupClass.
29.1413 - * Otherwise, if m is caller-sensitive, throw IllegalAccessException.
29.1414 - */
29.1415 - Class<?> findBoundCallerClass(MemberName m) throws IllegalAccessException {
29.1416 - Class<?> callerClass = null;
29.1417 - if (MethodHandleNatives.isCallerSensitive(m)) {
29.1418 - // Only lookups with private access are allowed to resolve caller-sensitive methods
29.1419 - if (hasPrivateAccess()) {
29.1420 - callerClass = lookupClass;
29.1421 - } else {
29.1422 - throw new IllegalAccessException("Attempt to lookup caller-sensitive method using restricted lookup object");
29.1423 - }
29.1424 - }
29.1425 - return callerClass;
29.1426 - }
29.1427 -
29.1428 - private boolean hasPrivateAccess() {
29.1429 - return (allowedModes & PRIVATE) != 0;
29.1430 - }
29.1431 -
29.1432 - /**
29.1433 - * Perform necessary <a href="MethodHandles.Lookup.html#secmgr">access checks</a>.
29.1434 - * Determines a trustable caller class to compare with refc, the symbolic reference class.
29.1435 - * If this lookup object has private access, then the caller class is the lookupClass.
29.1436 - */
29.1437 - void checkSecurityManager(Class<?> refc, MemberName m) {
29.1438 -// SecurityManager smgr = System.getSecurityManager();
29.1439 -// if (smgr == null) return;
29.1440 -// if (allowedModes == TRUSTED) return;
29.1441 -//
29.1442 -// // Step 1:
29.1443 -// boolean fullPowerLookup = hasPrivateAccess();
29.1444 -// if (!fullPowerLookup ||
29.1445 -// !VerifyAccess.classLoaderIsAncestor(lookupClass, refc)) {
29.1446 -// ReflectUtil.checkPackageAccess(refc);
29.1447 -// }
29.1448 -//
29.1449 -// // Step 2:
29.1450 -// if (m.isPublic()) return;
29.1451 -// if (!fullPowerLookup) {
29.1452 -// smgr.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
29.1453 -// }
29.1454 -//
29.1455 -// // Step 3:
29.1456 -// Class<?> defc = m.getDeclaringClass();
29.1457 -// if (!fullPowerLookup && defc != refc) {
29.1458 -// ReflectUtil.checkPackageAccess(defc);
29.1459 -// }
29.1460 - }
29.1461 -
29.1462 - void checkMethod(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
29.1463 - boolean wantStatic = (refKind == REF_invokeStatic);
29.1464 - String message;
29.1465 - if (m.isConstructor())
29.1466 - message = "expected a method, not a constructor";
29.1467 - else if (!m.isMethod())
29.1468 - message = "expected a method";
29.1469 - else if (wantStatic != m.isStatic())
29.1470 - message = wantStatic ? "expected a static method" : "expected a non-static method";
29.1471 - else
29.1472 - { checkAccess(refKind, refc, m); return; }
29.1473 - throw m.makeAccessException(message, this);
29.1474 - }
29.1475 -
29.1476 - void checkField(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
29.1477 - boolean wantStatic = !MethodHandleNatives.refKindHasReceiver(refKind);
29.1478 - String message;
29.1479 - if (wantStatic != m.isStatic())
29.1480 - message = wantStatic ? "expected a static field" : "expected a non-static field";
29.1481 - else
29.1482 - { checkAccess(refKind, refc, m); return; }
29.1483 - throw m.makeAccessException(message, this);
29.1484 - }
29.1485 -
29.1486 - /** Check public/protected/private bits on the symbolic reference class and its member. */
29.1487 - void checkAccess(byte refKind, Class<?> refc, MemberName m) throws IllegalAccessException {
29.1488 - assert(m.referenceKindIsConsistentWith(refKind) &&
29.1489 - MethodHandleNatives.refKindIsValid(refKind) &&
29.1490 - (MethodHandleNatives.refKindIsField(refKind) == m.isField()));
29.1491 - int allowedModes = this.allowedModes;
29.1492 - if (allowedModes == TRUSTED) return;
29.1493 - int mods = m.getModifiers();
29.1494 - if (Modifier.isProtected(mods) &&
29.1495 - refKind == REF_invokeVirtual &&
29.1496 - m.getDeclaringClass() == Object.class &&
29.1497 - m.getName().equals("clone") &&
29.1498 - refc.isArray()) {
29.1499 - // The JVM does this hack also.
29.1500 - // (See ClassVerifier::verify_invoke_instructions
29.1501 - // and LinkResolver::check_method_accessability.)
29.1502 - // Because the JVM does not allow separate methods on array types,
29.1503 - // there is no separate method for int[].clone.
29.1504 - // All arrays simply inherit Object.clone.
29.1505 - // But for access checking logic, we make Object.clone
29.1506 - // (normally protected) appear to be public.
29.1507 - // Later on, when the DirectMethodHandle is created,
29.1508 - // its leading argument will be restricted to the
29.1509 - // requested array type.
29.1510 - // N.B. The return type is not adjusted, because
29.1511 - // that is *not* the bytecode behavior.
29.1512 - mods ^= Modifier.PROTECTED | Modifier.PUBLIC;
29.1513 - }
29.1514 - if (Modifier.isFinal(mods) &&
29.1515 - MethodHandleNatives.refKindIsSetter(refKind))
29.1516 - throw m.makeAccessException("unexpected set of a final field", this);
29.1517 - if (Modifier.isPublic(mods) && Modifier.isPublic(refc.getModifiers()) && allowedModes != 0)
29.1518 - return; // common case
29.1519 - int requestedModes = fixmods(mods); // adjust 0 => PACKAGE
29.1520 - if ((requestedModes & allowedModes) != 0) {
29.1521 - if (VerifyAccess.isMemberAccessible(refc, m.getDeclaringClass(),
29.1522 - mods, lookupClass(), allowedModes))
29.1523 - return;
29.1524 - } else {
29.1525 - // Protected members can also be checked as if they were package-private.
29.1526 - if ((requestedModes & PROTECTED) != 0 && (allowedModes & PACKAGE) != 0
29.1527 - && VerifyAccess.isSamePackage(m.getDeclaringClass(), lookupClass()))
29.1528 - return;
29.1529 - }
29.1530 - throw m.makeAccessException(accessFailedMessage(refc, m), this);
29.1531 - }
29.1532 -
29.1533 - String accessFailedMessage(Class<?> refc, MemberName m) {
29.1534 - Class<?> defc = m.getDeclaringClass();
29.1535 - int mods = m.getModifiers();
29.1536 - // check the class first:
29.1537 - boolean classOK = (Modifier.isPublic(defc.getModifiers()) &&
29.1538 - (defc == refc ||
29.1539 - Modifier.isPublic(refc.getModifiers())));
29.1540 - if (!classOK && (allowedModes & PACKAGE) != 0) {
29.1541 - classOK = (VerifyAccess.isClassAccessible(defc, lookupClass(), ALL_MODES) &&
29.1542 - (defc == refc ||
29.1543 - VerifyAccess.isClassAccessible(refc, lookupClass(), ALL_MODES)));
29.1544 - }
29.1545 - if (!classOK)
29.1546 - return "class is not public";
29.1547 - if (Modifier.isPublic(mods))
29.1548 - return "access to public member failed"; // (how?)
29.1549 - if (Modifier.isPrivate(mods))
29.1550 - return "member is private";
29.1551 - if (Modifier.isProtected(mods))
29.1552 - return "member is protected";
29.1553 - return "member is private to package";
29.1554 - }
29.1555 -
29.1556 - private static final boolean ALLOW_NESTMATE_ACCESS = false;
29.1557 -
29.1558 - private void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException {
29.1559 - int allowedModes = this.allowedModes;
29.1560 - if (allowedModes == TRUSTED) return;
29.1561 - if (!hasPrivateAccess()
29.1562 - || (specialCaller != lookupClass()
29.1563 - && !(ALLOW_NESTMATE_ACCESS &&
29.1564 - VerifyAccess.isSamePackageMember(specialCaller, lookupClass()))))
29.1565 - throw new MemberName(specialCaller).
29.1566 - makeAccessException("no private access for invokespecial", this);
29.1567 - }
29.1568 -
29.1569 - private boolean restrictProtectedReceiver(MemberName method) {
29.1570 - // The accessing class only has the right to use a protected member
29.1571 - // on itself or a subclass. Enforce that restriction, from JVMS 5.4.4, etc.
29.1572 - if (!method.isProtected() || method.isStatic()
29.1573 - || allowedModes == TRUSTED
29.1574 - || method.getDeclaringClass() == lookupClass()
29.1575 - || VerifyAccess.isSamePackage(method.getDeclaringClass(), lookupClass())
29.1576 - || (ALLOW_NESTMATE_ACCESS &&
29.1577 - VerifyAccess.isSamePackageMember(method.getDeclaringClass(), lookupClass())))
29.1578 - return false;
29.1579 - return true;
29.1580 - }
29.1581 - private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class<?> caller) throws IllegalAccessException {
29.1582 - assert(!method.isStatic());
29.1583 - // receiver type of mh is too wide; narrow to caller
29.1584 - if (!method.getDeclaringClass().isAssignableFrom(caller)) {
29.1585 - throw method.makeAccessException("caller class must be a subclass below the method", caller);
29.1586 - }
29.1587 - MethodType rawType = mh.type();
29.1588 - if (rawType.parameterType(0) == caller) return mh;
29.1589 - MethodType narrowType = rawType.changeParameterType(0, caller);
29.1590 - return mh.viewAsType(narrowType);
29.1591 - }
29.1592 -
29.1593 - /** Check access and get the requested method. */
29.1594 - private MethodHandle getDirectMethod(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
29.1595 - final boolean doRestrict = true;
29.1596 - final boolean checkSecurity = true;
29.1597 - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
29.1598 - }
29.1599 - /** Check access and get the requested method, eliding receiver narrowing rules. */
29.1600 - private MethodHandle getDirectMethodNoRestrict(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
29.1601 - final boolean doRestrict = false;
29.1602 - final boolean checkSecurity = true;
29.1603 - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
29.1604 - }
29.1605 - /** Check access and get the requested method, eliding security manager checks. */
29.1606 - private MethodHandle getDirectMethodNoSecurityManager(byte refKind, Class<?> refc, MemberName method, Class<?> callerClass) throws IllegalAccessException {
29.1607 - final boolean doRestrict = true;
29.1608 - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants
29.1609 - return getDirectMethodCommon(refKind, refc, method, checkSecurity, doRestrict, callerClass);
29.1610 - }
29.1611 - /** Common code for all methods; do not call directly except from immediately above. */
29.1612 - private MethodHandle getDirectMethodCommon(byte refKind, Class<?> refc, MemberName method,
29.1613 - boolean checkSecurity,
29.1614 - boolean doRestrict, Class<?> callerClass) throws IllegalAccessException {
29.1615 - checkMethod(refKind, refc, method);
29.1616 - // Optionally check with the security manager; this isn't needed for unreflect* calls.
29.1617 - if (checkSecurity)
29.1618 - checkSecurityManager(refc, method);
29.1619 - assert(!method.isMethodHandleInvoke());
29.1620 -
29.1621 - Class<?> refcAsSuper;
29.1622 - if (refKind == REF_invokeSpecial &&
29.1623 - refc != lookupClass() &&
29.1624 - !refc.isInterface() &&
29.1625 - refc != (refcAsSuper = lookupClass().getSuperclass()) &&
29.1626 - refc.isAssignableFrom(lookupClass())) {
29.1627 - assert(!method.getName().equals("<init>")); // not this code path
29.1628 - // Per JVMS 6.5, desc. of invokespecial instruction:
29.1629 - // If the method is in a superclass of the LC,
29.1630 - // and if our original search was above LC.super,
29.1631 - // repeat the search (symbolic lookup) from LC.super.
29.1632 - // FIXME: MemberName.resolve should handle this instead.
29.1633 - MemberName m2 = new MemberName(refcAsSuper,
29.1634 - method.getName(),
29.1635 - method.getMethodType(),
29.1636 - REF_invokeSpecial);
29.1637 - m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
29.1638 - if (m2 == null) throw new InternalError(method.toString());
29.1639 - method = m2;
29.1640 - refc = refcAsSuper;
29.1641 - // redo basic checks
29.1642 - checkMethod(refKind, refc, method);
29.1643 - }
29.1644 -
29.1645 - MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
29.1646 - mh = maybeBindCaller(method, mh, callerClass);
29.1647 - mh = mh.setVarargs(method);
29.1648 - // Optionally narrow the receiver argument to refc using restrictReceiver.
29.1649 - if (doRestrict &&
29.1650 - (refKind == REF_invokeSpecial ||
29.1651 - (MethodHandleNatives.refKindHasReceiver(refKind) &&
29.1652 - restrictProtectedReceiver(method))))
29.1653 - mh = restrictReceiver(method, mh, lookupClass());
29.1654 - return mh;
29.1655 - }
29.1656 - private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
29.1657 - Class<?> callerClass)
29.1658 - throws IllegalAccessException {
29.1659 - if (allowedModes == TRUSTED || !MethodHandleNatives.isCallerSensitive(method))
29.1660 - return mh;
29.1661 - Class<?> hostClass = lookupClass;
29.1662 - if (!hasPrivateAccess()) // caller must have private access
29.1663 - hostClass = callerClass; // callerClass came from a security manager style stack walk
29.1664 - MethodHandle cbmh = MethodHandleImpl.bindCaller(mh, hostClass);
29.1665 - // Note: caller will apply varargs after this step happens.
29.1666 - return cbmh;
29.1667 - }
29.1668 - /** Check access and get the requested field. */
29.1669 - private MethodHandle getDirectField(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
29.1670 - final boolean checkSecurity = true;
29.1671 - return getDirectFieldCommon(refKind, refc, field, checkSecurity);
29.1672 - }
29.1673 - /** Check access and get the requested field, eliding security manager checks. */
29.1674 - private MethodHandle getDirectFieldNoSecurityManager(byte refKind, Class<?> refc, MemberName field) throws IllegalAccessException {
29.1675 - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants
29.1676 - return getDirectFieldCommon(refKind, refc, field, checkSecurity);
29.1677 - }
29.1678 - /** Common code for all fields; do not call directly except from immediately above. */
29.1679 - private MethodHandle getDirectFieldCommon(byte refKind, Class<?> refc, MemberName field,
29.1680 - boolean checkSecurity) throws IllegalAccessException {
29.1681 - checkField(refKind, refc, field);
29.1682 - // Optionally check with the security manager; this isn't needed for unreflect* calls.
29.1683 - if (checkSecurity)
29.1684 - checkSecurityManager(refc, field);
29.1685 - MethodHandle mh = DirectMethodHandle.make(refc, field);
29.1686 - boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
29.1687 - restrictProtectedReceiver(field));
29.1688 - if (doRestrict)
29.1689 - mh = restrictReceiver(field, mh, lookupClass());
29.1690 - return mh;
29.1691 - }
29.1692 - /** Check access and get the requested constructor. */
29.1693 - private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
29.1694 - final boolean checkSecurity = true;
29.1695 - return getDirectConstructorCommon(refc, ctor, checkSecurity);
29.1696 - }
29.1697 - /** Check access and get the requested constructor, eliding security manager checks. */
29.1698 - private MethodHandle getDirectConstructorNoSecurityManager(Class<?> refc, MemberName ctor) throws IllegalAccessException {
29.1699 - final boolean checkSecurity = false; // not needed for reflection or for linking CONSTANT_MH constants
29.1700 - return getDirectConstructorCommon(refc, ctor, checkSecurity);
29.1701 - }
29.1702 - /** Common code for all constructors; do not call directly except from immediately above. */
29.1703 - private MethodHandle getDirectConstructorCommon(Class<?> refc, MemberName ctor,
29.1704 - boolean checkSecurity) throws IllegalAccessException {
29.1705 - assert(ctor.isConstructor());
29.1706 - checkAccess(REF_newInvokeSpecial, refc, ctor);
29.1707 - // Optionally check with the security manager; this isn't needed for unreflect* calls.
29.1708 - if (checkSecurity)
29.1709 - checkSecurityManager(refc, ctor);
29.1710 - assert(!MethodHandleNatives.isCallerSensitive(ctor)); // maybeBindCaller not relevant here
29.1711 - return DirectMethodHandle.make(ctor).setVarargs(ctor);
29.1712 - }
29.1713 -
29.1714 - /** Hook called from the JVM (via MethodHandleNatives) to link MH constants:
29.1715 - */
29.1716 - /*non-public*/
29.1717 - MethodHandle linkMethodHandleConstant(byte refKind, Class<?> defc, String name, Object type) throws ReflectiveOperationException {
29.1718 - if (!(type instanceof Class || type instanceof MethodType))
29.1719 - throw new InternalError("unresolved MemberName");
29.1720 - MemberName member = new MemberName(refKind, defc, name, type);
29.1721 - MethodHandle mh = LOOKASIDE_TABLE.get(member);
29.1722 - if (mh != null) {
29.1723 - checkSymbolicClass(defc);
29.1724 - return mh;
29.1725 - }
29.1726 - // Treat MethodHandle.invoke and invokeExact specially.
29.1727 - if (defc == MethodHandle.class && refKind == REF_invokeVirtual) {
29.1728 - mh = findVirtualForMH(member.getName(), member.getMethodType());
29.1729 - if (mh != null) {
29.1730 - return mh;
29.1731 - }
29.1732 - }
29.1733 - MemberName resolved = resolveOrFail(refKind, member);
29.1734 - mh = getDirectMethodForConstant(refKind, defc, resolved);
29.1735 - if (mh instanceof DirectMethodHandle
29.1736 - && canBeCached(refKind, defc, resolved)) {
29.1737 - MemberName key = mh.internalMemberName();
29.1738 - if (key != null) {
29.1739 - key = key.asNormalOriginal();
29.1740 - }
29.1741 - if (member.equals(key)) { // better safe than sorry
29.1742 - LOOKASIDE_TABLE.put(key, (DirectMethodHandle) mh);
29.1743 - }
29.1744 - }
29.1745 - return mh;
29.1746 - }
29.1747 - private
29.1748 - boolean canBeCached(byte refKind, Class<?> defc, MemberName member) {
29.1749 - if (refKind == REF_invokeSpecial) {
29.1750 - return false;
29.1751 - }
29.1752 - if (!Modifier.isPublic(defc.getModifiers()) ||
29.1753 - !Modifier.isPublic(member.getDeclaringClass().getModifiers()) ||
29.1754 - !member.isPublic() ||
29.1755 - member.isCallerSensitive()) {
29.1756 - return false;
29.1757 - }
29.1758 - ClassLoader loader = defc.getClassLoader();
29.1759 -// if (!sun.misc.VM.isSystemDomainLoader(loader)) {
29.1760 -// ClassLoader sysl = ClassLoader.getSystemClassLoader();
29.1761 -// boolean found = false;
29.1762 -// while (sysl != null) {
29.1763 -// if (loader == sysl) { found = true; break; }
29.1764 -// sysl = sysl.getParent();
29.1765 -// }
29.1766 -// if (!found) {
29.1767 -// return false;
29.1768 -// }
29.1769 -// }
29.1770 - try {
29.1771 - MemberName resolved2 = publicLookup().resolveOrFail(refKind,
29.1772 - new MemberName(refKind, defc, member.getName(), member.getType()));
29.1773 - checkSecurityManager(defc, resolved2);
29.1774 - } catch (ReflectiveOperationException | SecurityException ex) {
29.1775 - return false;
29.1776 - }
29.1777 - return true;
29.1778 - }
29.1779 - private
29.1780 - MethodHandle getDirectMethodForConstant(byte refKind, Class<?> defc, MemberName member)
29.1781 - throws ReflectiveOperationException {
29.1782 - if (MethodHandleNatives.refKindIsField(refKind)) {
29.1783 - return getDirectFieldNoSecurityManager(refKind, defc, member);
29.1784 - } else if (MethodHandleNatives.refKindIsMethod(refKind)) {
29.1785 - return getDirectMethodNoSecurityManager(refKind, defc, member, lookupClass);
29.1786 - } else if (refKind == REF_newInvokeSpecial) {
29.1787 - return getDirectConstructorNoSecurityManager(defc, member);
29.1788 - }
29.1789 - // oops
29.1790 - throw newIllegalArgumentException("bad MethodHandle constant #"+member);
29.1791 - }
29.1792 -
29.1793 - static ConcurrentHashMap<MemberName, DirectMethodHandle> LOOKASIDE_TABLE = new ConcurrentHashMap<>();
29.1794 - }
29.1795 -
29.1796 - /**
29.1797 - * Produces a method handle giving read access to elements of an array.
29.1798 - * The type of the method handle will have a return type of the array's
29.1799 - * element type. Its first argument will be the array type,
29.1800 - * and the second will be {@code int}.
29.1801 - * @param arrayClass an array type
29.1802 - * @return a method handle which can load values from the given array type
29.1803 - * @throws NullPointerException if the argument is null
29.1804 - * @throws IllegalArgumentException if arrayClass is not an array type
29.1805 - */
29.1806 - public static
29.1807 - MethodHandle arrayElementGetter(Class<?> arrayClass) throws IllegalArgumentException {
29.1808 - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, false);
29.1809 - }
29.1810 -
29.1811 - /**
29.1812 - * Produces a method handle giving write access to elements of an array.
29.1813 - * The type of the method handle will have a void return type.
29.1814 - * Its last argument will be the array's element type.
29.1815 - * The first and second arguments will be the array type and int.
29.1816 - * @param arrayClass the class of an array
29.1817 - * @return a method handle which can store values into the array type
29.1818 - * @throws NullPointerException if the argument is null
29.1819 - * @throws IllegalArgumentException if arrayClass is not an array type
29.1820 - */
29.1821 - public static
29.1822 - MethodHandle arrayElementSetter(Class<?> arrayClass) throws IllegalArgumentException {
29.1823 - return MethodHandleImpl.makeArrayElementAccessor(arrayClass, true);
29.1824 - }
29.1825 -
29.1826 - /// method handle invocation (reflective style)
29.1827 -
29.1828 - /**
29.1829 - * Produces a method handle which will invoke any method handle of the
29.1830 - * given {@code type}, with a given number of trailing arguments replaced by
29.1831 - * a single trailing {@code Object[]} array.
29.1832 - * The resulting invoker will be a method handle with the following
29.1833 - * arguments:
29.1834 - * <ul>
29.1835 - * <li>a single {@code MethodHandle} target
29.1836 - * <li>zero or more leading values (counted by {@code leadingArgCount})
29.1837 - * <li>an {@code Object[]} array containing trailing arguments
29.1838 - * </ul>
29.1839 - * <p>
29.1840 - * The invoker will invoke its target like a call to {@link MethodHandle#invoke invoke} with
29.1841 - * the indicated {@code type}.
29.1842 - * That is, if the target is exactly of the given {@code type}, it will behave
29.1843 - * like {@code invokeExact}; otherwise it behave as if {@link MethodHandle#asType asType}
29.1844 - * is used to convert the target to the required {@code type}.
29.1845 - * <p>
29.1846 - * The type of the returned invoker will not be the given {@code type}, but rather
29.1847 - * will have all parameters except the first {@code leadingArgCount}
29.1848 - * replaced by a single array of type {@code Object[]}, which will be
29.1849 - * the final parameter.
29.1850 - * <p>
29.1851 - * Before invoking its target, the invoker will spread the final array, apply
29.1852 - * reference casts as necessary, and unbox and widen primitive arguments.
29.1853 - * If, when the invoker is called, the supplied array argument does
29.1854 - * not have the correct number of elements, the invoker will throw
29.1855 - * an {@link IllegalArgumentException} instead of invoking the target.
29.1856 - * <p>
29.1857 - * This method is equivalent to the following code (though it may be more efficient):
29.1858 - * <blockquote><pre>{@code
29.1859 -MethodHandle invoker = MethodHandles.invoker(type);
29.1860 -int spreadArgCount = type.parameterCount() - leadingArgCount;
29.1861 -invoker = invoker.asSpreader(Object[].class, spreadArgCount);
29.1862 -return invoker;
29.1863 - * }</pre></blockquote>
29.1864 - * This method throws no reflective or security exceptions.
29.1865 - * @param type the desired target type
29.1866 - * @param leadingArgCount number of fixed arguments, to be passed unchanged to the target
29.1867 - * @return a method handle suitable for invoking any method handle of the given type
29.1868 - * @throws NullPointerException if {@code type} is null
29.1869 - * @throws IllegalArgumentException if {@code leadingArgCount} is not in
29.1870 - * the range from 0 to {@code type.parameterCount()} inclusive,
29.1871 - * or if the resulting method handle's type would have
29.1872 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.1873 - */
29.1874 - static public
29.1875 - MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
29.1876 - if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
29.1877 - throw new IllegalArgumentException("bad argument count "+leadingArgCount);
29.1878 - return type.invokers().spreadInvoker(leadingArgCount);
29.1879 - }
29.1880 -
29.1881 - /**
29.1882 - * Produces a special <em>invoker method handle</em> which can be used to
29.1883 - * invoke any method handle of the given type, as if by {@link MethodHandle#invokeExact invokeExact}.
29.1884 - * The resulting invoker will have a type which is
29.1885 - * exactly equal to the desired type, except that it will accept
29.1886 - * an additional leading argument of type {@code MethodHandle}.
29.1887 - * <p>
29.1888 - * This method is equivalent to the following code (though it may be more efficient):
29.1889 - * {@code publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)}
29.1890 - *
29.1891 - * <p style="font-size:smaller;">
29.1892 - * <em>Discussion:</em>
29.1893 - * Invoker method handles can be useful when working with variable method handles
29.1894 - * of unknown types.
29.1895 - * For example, to emulate an {@code invokeExact} call to a variable method
29.1896 - * handle {@code M}, extract its type {@code T},
29.1897 - * look up the invoker method {@code X} for {@code T},
29.1898 - * and call the invoker method, as {@code X.invoke(T, A...)}.
29.1899 - * (It would not work to call {@code X.invokeExact}, since the type {@code T}
29.1900 - * is unknown.)
29.1901 - * If spreading, collecting, or other argument transformations are required,
29.1902 - * they can be applied once to the invoker {@code X} and reused on many {@code M}
29.1903 - * method handle values, as long as they are compatible with the type of {@code X}.
29.1904 - * <p style="font-size:smaller;">
29.1905 - * <em>(Note: The invoker method is not available via the Core Reflection API.
29.1906 - * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
29.1907 - * on the declared {@code invokeExact} or {@code invoke} method will raise an
29.1908 - * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
29.1909 - * <p>
29.1910 - * This method throws no reflective or security exceptions.
29.1911 - * @param type the desired target type
29.1912 - * @return a method handle suitable for invoking any method handle of the given type
29.1913 - * @throws IllegalArgumentException if the resulting method handle's type would have
29.1914 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.1915 - */
29.1916 - static public
29.1917 - MethodHandle exactInvoker(MethodType type) {
29.1918 - return type.invokers().exactInvoker();
29.1919 - }
29.1920 -
29.1921 - /**
29.1922 - * Produces a special <em>invoker method handle</em> which can be used to
29.1923 - * invoke any method handle compatible with the given type, as if by {@link MethodHandle#invoke invoke}.
29.1924 - * The resulting invoker will have a type which is
29.1925 - * exactly equal to the desired type, except that it will accept
29.1926 - * an additional leading argument of type {@code MethodHandle}.
29.1927 - * <p>
29.1928 - * Before invoking its target, if the target differs from the expected type,
29.1929 - * the invoker will apply reference casts as
29.1930 - * necessary and box, unbox, or widen primitive values, as if by {@link MethodHandle#asType asType}.
29.1931 - * Similarly, the return value will be converted as necessary.
29.1932 - * If the target is a {@linkplain MethodHandle#asVarargsCollector variable arity method handle},
29.1933 - * the required arity conversion will be made, again as if by {@link MethodHandle#asType asType}.
29.1934 - * <p>
29.1935 - * This method is equivalent to the following code (though it may be more efficient):
29.1936 - * {@code publicLookup().findVirtual(MethodHandle.class, "invoke", type)}
29.1937 - * <p style="font-size:smaller;">
29.1938 - * <em>Discussion:</em>
29.1939 - * A {@linkplain MethodType#genericMethodType general method type} is one which
29.1940 - * mentions only {@code Object} arguments and return values.
29.1941 - * An invoker for such a type is capable of calling any method handle
29.1942 - * of the same arity as the general type.
29.1943 - * <p style="font-size:smaller;">
29.1944 - * <em>(Note: The invoker method is not available via the Core Reflection API.
29.1945 - * An attempt to call {@linkplain java.lang.reflect.Method#invoke java.lang.reflect.Method.invoke}
29.1946 - * on the declared {@code invokeExact} or {@code invoke} method will raise an
29.1947 - * {@link java.lang.UnsupportedOperationException UnsupportedOperationException}.)</em>
29.1948 - * <p>
29.1949 - * This method throws no reflective or security exceptions.
29.1950 - * @param type the desired target type
29.1951 - * @return a method handle suitable for invoking any method handle convertible to the given type
29.1952 - * @throws IllegalArgumentException if the resulting method handle's type would have
29.1953 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.1954 - */
29.1955 - static public
29.1956 - MethodHandle invoker(MethodType type) {
29.1957 - return type.invokers().generalInvoker();
29.1958 - }
29.1959 -
29.1960 - static /*non-public*/
29.1961 - MethodHandle basicInvoker(MethodType type) {
29.1962 - return type.form().basicInvoker();
29.1963 - }
29.1964 -
29.1965 - /// method handle modification (creation from other method handles)
29.1966 -
29.1967 - /**
29.1968 - * Produces a method handle which adapts the type of the
29.1969 - * given method handle to a new type by pairwise argument and return type conversion.
29.1970 - * The original type and new type must have the same number of arguments.
29.1971 - * The resulting method handle is guaranteed to report a type
29.1972 - * which is equal to the desired new type.
29.1973 - * <p>
29.1974 - * If the original type and new type are equal, returns target.
29.1975 - * <p>
29.1976 - * The same conversions are allowed as for {@link MethodHandle#asType MethodHandle.asType},
29.1977 - * and some additional conversions are also applied if those conversions fail.
29.1978 - * Given types <em>T0</em>, <em>T1</em>, one of the following conversions is applied
29.1979 - * if possible, before or instead of any conversions done by {@code asType}:
29.1980 - * <ul>
29.1981 - * <li>If <em>T0</em> and <em>T1</em> are references, and <em>T1</em> is an interface type,
29.1982 - * then the value of type <em>T0</em> is passed as a <em>T1</em> without a cast.
29.1983 - * (This treatment of interfaces follows the usage of the bytecode verifier.)
29.1984 - * <li>If <em>T0</em> is boolean and <em>T1</em> is another primitive,
29.1985 - * the boolean is converted to a byte value, 1 for true, 0 for false.
29.1986 - * (This treatment follows the usage of the bytecode verifier.)
29.1987 - * <li>If <em>T1</em> is boolean and <em>T0</em> is another primitive,
29.1988 - * <em>T0</em> is converted to byte via Java casting conversion (JLS 5.5),
29.1989 - * and the low order bit of the result is tested, as if by {@code (x & 1) != 0}.
29.1990 - * <li>If <em>T0</em> and <em>T1</em> are primitives other than boolean,
29.1991 - * then a Java casting conversion (JLS 5.5) is applied.
29.1992 - * (Specifically, <em>T0</em> will convert to <em>T1</em> by
29.1993 - * widening and/or narrowing.)
29.1994 - * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive, an unboxing
29.1995 - * conversion will be applied at runtime, possibly followed
29.1996 - * by a Java casting conversion (JLS 5.5) on the primitive value,
29.1997 - * possibly followed by a conversion from byte to boolean by testing
29.1998 - * the low-order bit.
29.1999 - * <li>If <em>T0</em> is a reference and <em>T1</em> a primitive,
29.2000 - * and if the reference is null at runtime, a zero value is introduced.
29.2001 - * </ul>
29.2002 - * @param target the method handle to invoke after arguments are retyped
29.2003 - * @param newType the expected type of the new method handle
29.2004 - * @return a method handle which delegates to the target after performing
29.2005 - * any necessary argument conversions, and arranges for any
29.2006 - * necessary return value conversions
29.2007 - * @throws NullPointerException if either argument is null
29.2008 - * @throws WrongMethodTypeException if the conversion cannot be made
29.2009 - * @see MethodHandle#asType
29.2010 - */
29.2011 - public static
29.2012 - MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
29.2013 - if (!target.type().isCastableTo(newType)) {
29.2014 - throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType);
29.2015 - }
29.2016 - return MethodHandleImpl.makePairwiseConvert(target, newType, 2);
29.2017 - }
29.2018 -
29.2019 - /**
29.2020 - * Produces a method handle which adapts the calling sequence of the
29.2021 - * given method handle to a new type, by reordering the arguments.
29.2022 - * The resulting method handle is guaranteed to report a type
29.2023 - * which is equal to the desired new type.
29.2024 - * <p>
29.2025 - * The given array controls the reordering.
29.2026 - * Call {@code #I} the number of incoming parameters (the value
29.2027 - * {@code newType.parameterCount()}, and call {@code #O} the number
29.2028 - * of outgoing parameters (the value {@code target.type().parameterCount()}).
29.2029 - * Then the length of the reordering array must be {@code #O},
29.2030 - * and each element must be a non-negative number less than {@code #I}.
29.2031 - * For every {@code N} less than {@code #O}, the {@code N}-th
29.2032 - * outgoing argument will be taken from the {@code I}-th incoming
29.2033 - * argument, where {@code I} is {@code reorder[N]}.
29.2034 - * <p>
29.2035 - * No argument or return value conversions are applied.
29.2036 - * The type of each incoming argument, as determined by {@code newType},
29.2037 - * must be identical to the type of the corresponding outgoing parameter
29.2038 - * or parameters in the target method handle.
29.2039 - * The return type of {@code newType} must be identical to the return
29.2040 - * type of the original target.
29.2041 - * <p>
29.2042 - * The reordering array need not specify an actual permutation.
29.2043 - * An incoming argument will be duplicated if its index appears
29.2044 - * more than once in the array, and an incoming argument will be dropped
29.2045 - * if its index does not appear in the array.
29.2046 - * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
29.2047 - * incoming arguments which are not mentioned in the reordering array
29.2048 - * are may be any type, as determined only by {@code newType}.
29.2049 - * <blockquote><pre>{@code
29.2050 -import static java.lang.invoke.MethodHandles.*;
29.2051 -import static java.lang.invoke.MethodType.*;
29.2052 -...
29.2053 -MethodType intfn1 = methodType(int.class, int.class);
29.2054 -MethodType intfn2 = methodType(int.class, int.class, int.class);
29.2055 -MethodHandle sub = ... (int x, int y) -> (x-y) ...;
29.2056 -assert(sub.type().equals(intfn2));
29.2057 -MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
29.2058 -MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
29.2059 -assert((int)rsub.invokeExact(1, 100) == 99);
29.2060 -MethodHandle add = ... (int x, int y) -> (x+y) ...;
29.2061 -assert(add.type().equals(intfn2));
29.2062 -MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
29.2063 -assert(twice.type().equals(intfn1));
29.2064 -assert((int)twice.invokeExact(21) == 42);
29.2065 - * }</pre></blockquote>
29.2066 - * @param target the method handle to invoke after arguments are reordered
29.2067 - * @param newType the expected type of the new method handle
29.2068 - * @param reorder an index array which controls the reordering
29.2069 - * @return a method handle which delegates to the target after it
29.2070 - * drops unused arguments and moves and/or duplicates the other arguments
29.2071 - * @throws NullPointerException if any argument is null
29.2072 - * @throws IllegalArgumentException if the index array length is not equal to
29.2073 - * the arity of the target, or if any index array element
29.2074 - * not a valid index for a parameter of {@code newType},
29.2075 - * or if two corresponding parameter types in
29.2076 - * {@code target.type()} and {@code newType} are not identical,
29.2077 - */
29.2078 - public static
29.2079 - MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
29.2080 - checkReorder(reorder, newType, target.type());
29.2081 - return target.permuteArguments(newType, reorder);
29.2082 - }
29.2083 -
29.2084 - private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
29.2085 - if (newType.returnType() != oldType.returnType())
29.2086 - throw newIllegalArgumentException("return types do not match",
29.2087 - oldType, newType);
29.2088 - if (reorder.length == oldType.parameterCount()) {
29.2089 - int limit = newType.parameterCount();
29.2090 - boolean bad = false;
29.2091 - for (int j = 0; j < reorder.length; j++) {
29.2092 - int i = reorder[j];
29.2093 - if (i < 0 || i >= limit) {
29.2094 - bad = true; break;
29.2095 - }
29.2096 - Class<?> src = newType.parameterType(i);
29.2097 - Class<?> dst = oldType.parameterType(j);
29.2098 - if (src != dst)
29.2099 - throw newIllegalArgumentException("parameter types do not match after reorder",
29.2100 - oldType, newType);
29.2101 - }
29.2102 - if (!bad) return;
29.2103 - }
29.2104 - throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
29.2105 - }
29.2106 -
29.2107 - /**
29.2108 - * Produces a method handle of the requested return type which returns the given
29.2109 - * constant value every time it is invoked.
29.2110 - * <p>
29.2111 - * Before the method handle is returned, the passed-in value is converted to the requested type.
29.2112 - * If the requested type is primitive, widening primitive conversions are attempted,
29.2113 - * else reference conversions are attempted.
29.2114 - * <p>The returned method handle is equivalent to {@code identity(type).bindTo(value)}.
29.2115 - * @param type the return type of the desired method handle
29.2116 - * @param value the value to return
29.2117 - * @return a method handle of the given return type and no arguments, which always returns the given value
29.2118 - * @throws NullPointerException if the {@code type} argument is null
29.2119 - * @throws ClassCastException if the value cannot be converted to the required return type
29.2120 - * @throws IllegalArgumentException if the given type is {@code void.class}
29.2121 - */
29.2122 - public static
29.2123 - MethodHandle constant(Class<?> type, Object value) {
29.2124 - if (type.isPrimitive()) {
29.2125 - if (type == void.class)
29.2126 - throw newIllegalArgumentException("void type");
29.2127 - Wrapper w = Wrapper.forPrimitiveType(type);
29.2128 - return insertArguments(identity(type), 0, w.convert(value, type));
29.2129 - } else {
29.2130 - return identity(type).bindTo(type.cast(value));
29.2131 - }
29.2132 - }
29.2133 -
29.2134 - /**
29.2135 - * Produces a method handle which returns its sole argument when invoked.
29.2136 - * @param type the type of the sole parameter and return value of the desired method handle
29.2137 - * @return a unary method handle which accepts and returns the given type
29.2138 - * @throws NullPointerException if the argument is null
29.2139 - * @throws IllegalArgumentException if the given type is {@code void.class}
29.2140 - */
29.2141 - public static
29.2142 - MethodHandle identity(Class<?> type) {
29.2143 - if (type == void.class)
29.2144 - throw newIllegalArgumentException("void type");
29.2145 - else if (type == Object.class)
29.2146 - return ValueConversions.identity();
29.2147 - else if (type.isPrimitive())
29.2148 - return ValueConversions.identity(Wrapper.forPrimitiveType(type));
29.2149 - else
29.2150 - return MethodHandleImpl.makeReferenceIdentity(type);
29.2151 - }
29.2152 -
29.2153 - /**
29.2154 - * Provides a target method handle with one or more <em>bound arguments</em>
29.2155 - * in advance of the method handle's invocation.
29.2156 - * The formal parameters to the target corresponding to the bound
29.2157 - * arguments are called <em>bound parameters</em>.
29.2158 - * Returns a new method handle which saves away the bound arguments.
29.2159 - * When it is invoked, it receives arguments for any non-bound parameters,
29.2160 - * binds the saved arguments to their corresponding parameters,
29.2161 - * and calls the original target.
29.2162 - * <p>
29.2163 - * The type of the new method handle will drop the types for the bound
29.2164 - * parameters from the original target type, since the new method handle
29.2165 - * will no longer require those arguments to be supplied by its callers.
29.2166 - * <p>
29.2167 - * Each given argument object must match the corresponding bound parameter type.
29.2168 - * If a bound parameter type is a primitive, the argument object
29.2169 - * must be a wrapper, and will be unboxed to produce the primitive value.
29.2170 - * <p>
29.2171 - * The {@code pos} argument selects which parameters are to be bound.
29.2172 - * It may range between zero and <i>N-L</i> (inclusively),
29.2173 - * where <i>N</i> is the arity of the target method handle
29.2174 - * and <i>L</i> is the length of the values array.
29.2175 - * @param target the method handle to invoke after the argument is inserted
29.2176 - * @param pos where to insert the argument (zero for the first)
29.2177 - * @param values the series of arguments to insert
29.2178 - * @return a method handle which inserts an additional argument,
29.2179 - * before calling the original method handle
29.2180 - * @throws NullPointerException if the target or the {@code values} array is null
29.2181 - * @see MethodHandle#bindTo
29.2182 - */
29.2183 - public static
29.2184 - MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
29.2185 - int insCount = values.length;
29.2186 - MethodType oldType = target.type();
29.2187 - int outargs = oldType.parameterCount();
29.2188 - int inargs = outargs - insCount;
29.2189 - if (inargs < 0)
29.2190 - throw newIllegalArgumentException("too many values to insert");
29.2191 - if (pos < 0 || pos > inargs)
29.2192 - throw newIllegalArgumentException("no argument type to append");
29.2193 - MethodHandle result = target;
29.2194 - for (int i = 0; i < insCount; i++) {
29.2195 - Object value = values[i];
29.2196 - Class<?> ptype = oldType.parameterType(pos+i);
29.2197 - if (ptype.isPrimitive()) {
29.2198 - char btype = 'I';
29.2199 - Wrapper w = Wrapper.forPrimitiveType(ptype);
29.2200 - switch (w) {
29.2201 - case LONG: btype = 'J'; break;
29.2202 - case FLOAT: btype = 'F'; break;
29.2203 - case DOUBLE: btype = 'D'; break;
29.2204 - }
29.2205 - // perform unboxing and/or primitive conversion
29.2206 - value = w.convert(value, ptype);
29.2207 - result = result.bindArgument(pos, btype, value);
29.2208 - continue;
29.2209 - }
29.2210 - value = ptype.cast(value); // throw CCE if needed
29.2211 - if (pos == 0) {
29.2212 - result = result.bindReceiver(value);
29.2213 - } else {
29.2214 - result = result.bindArgument(pos, 'L', value);
29.2215 - }
29.2216 - }
29.2217 - return result;
29.2218 - }
29.2219 -
29.2220 - /**
29.2221 - * Produces a method handle which will discard some dummy arguments
29.2222 - * before calling some other specified <i>target</i> method handle.
29.2223 - * The type of the new method handle will be the same as the target's type,
29.2224 - * except it will also include the dummy argument types,
29.2225 - * at some given position.
29.2226 - * <p>
29.2227 - * The {@code pos} argument may range between zero and <i>N</i>,
29.2228 - * where <i>N</i> is the arity of the target.
29.2229 - * If {@code pos} is zero, the dummy arguments will precede
29.2230 - * the target's real arguments; if {@code pos} is <i>N</i>
29.2231 - * they will come after.
29.2232 - * <p>
29.2233 - * <b>Example:</b>
29.2234 - * <blockquote><pre>{@code
29.2235 -import static java.lang.invoke.MethodHandles.*;
29.2236 -import static java.lang.invoke.MethodType.*;
29.2237 -...
29.2238 -MethodHandle cat = lookup().findVirtual(String.class,
29.2239 - "concat", methodType(String.class, String.class));
29.2240 -assertEquals("xy", (String) cat.invokeExact("x", "y"));
29.2241 -MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
29.2242 -MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
29.2243 -assertEquals(bigType, d0.type());
29.2244 -assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
29.2245 - * }</pre></blockquote>
29.2246 - * <p>
29.2247 - * This method is also equivalent to the following code:
29.2248 - * <blockquote><pre>
29.2249 - * {@link #dropArguments(MethodHandle,int,Class...) dropArguments}{@code (target, pos, valueTypes.toArray(new Class[0]))}
29.2250 - * </pre></blockquote>
29.2251 - * @param target the method handle to invoke after the arguments are dropped
29.2252 - * @param valueTypes the type(s) of the argument(s) to drop
29.2253 - * @param pos position of first argument to drop (zero for the leftmost)
29.2254 - * @return a method handle which drops arguments of the given types,
29.2255 - * before calling the original method handle
29.2256 - * @throws NullPointerException if the target is null,
29.2257 - * or if the {@code valueTypes} list or any of its elements is null
29.2258 - * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
29.2259 - * or if {@code pos} is negative or greater than the arity of the target,
29.2260 - * or if the new method handle's type would have too many parameters
29.2261 - */
29.2262 - public static
29.2263 - MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes) {
29.2264 - MethodType oldType = target.type(); // get NPE
29.2265 - int dropped = valueTypes.size();
29.2266 - MethodType.checkSlotCount(dropped);
29.2267 - if (dropped == 0) return target;
29.2268 - int outargs = oldType.parameterCount();
29.2269 - int inargs = outargs + dropped;
29.2270 - if (pos < 0 || pos >= inargs)
29.2271 - throw newIllegalArgumentException("no argument type to remove");
29.2272 - ArrayList<Class<?>> ptypes = new ArrayList<>(oldType.parameterList());
29.2273 - ptypes.addAll(pos, valueTypes);
29.2274 - MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
29.2275 - return target.dropArguments(newType, pos, dropped);
29.2276 - }
29.2277 -
29.2278 - /**
29.2279 - * Produces a method handle which will discard some dummy arguments
29.2280 - * before calling some other specified <i>target</i> method handle.
29.2281 - * The type of the new method handle will be the same as the target's type,
29.2282 - * except it will also include the dummy argument types,
29.2283 - * at some given position.
29.2284 - * <p>
29.2285 - * The {@code pos} argument may range between zero and <i>N</i>,
29.2286 - * where <i>N</i> is the arity of the target.
29.2287 - * If {@code pos} is zero, the dummy arguments will precede
29.2288 - * the target's real arguments; if {@code pos} is <i>N</i>
29.2289 - * they will come after.
29.2290 - * <p>
29.2291 - * <b>Example:</b>
29.2292 - * <blockquote><pre>{@code
29.2293 -import static java.lang.invoke.MethodHandles.*;
29.2294 -import static java.lang.invoke.MethodType.*;
29.2295 -...
29.2296 -MethodHandle cat = lookup().findVirtual(String.class,
29.2297 - "concat", methodType(String.class, String.class));
29.2298 -assertEquals("xy", (String) cat.invokeExact("x", "y"));
29.2299 -MethodHandle d0 = dropArguments(cat, 0, String.class);
29.2300 -assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
29.2301 -MethodHandle d1 = dropArguments(cat, 1, String.class);
29.2302 -assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
29.2303 -MethodHandle d2 = dropArguments(cat, 2, String.class);
29.2304 -assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
29.2305 -MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
29.2306 -assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
29.2307 - * }</pre></blockquote>
29.2308 - * <p>
29.2309 - * This method is also equivalent to the following code:
29.2310 - * <blockquote><pre>
29.2311 - * {@link #dropArguments(MethodHandle,int,List) dropArguments}{@code (target, pos, Arrays.asList(valueTypes))}
29.2312 - * </pre></blockquote>
29.2313 - * @param target the method handle to invoke after the arguments are dropped
29.2314 - * @param valueTypes the type(s) of the argument(s) to drop
29.2315 - * @param pos position of first argument to drop (zero for the leftmost)
29.2316 - * @return a method handle which drops arguments of the given types,
29.2317 - * before calling the original method handle
29.2318 - * @throws NullPointerException if the target is null,
29.2319 - * or if the {@code valueTypes} array or any of its elements is null
29.2320 - * @throws IllegalArgumentException if any element of {@code valueTypes} is {@code void.class},
29.2321 - * or if {@code pos} is negative or greater than the arity of the target,
29.2322 - * or if the new method handle's type would have
29.2323 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.2324 - */
29.2325 - public static
29.2326 - MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes) {
29.2327 - return dropArguments(target, pos, Arrays.asList(valueTypes));
29.2328 - }
29.2329 -
29.2330 - /**
29.2331 - * Adapts a target method handle by pre-processing
29.2332 - * one or more of its arguments, each with its own unary filter function,
29.2333 - * and then calling the target with each pre-processed argument
29.2334 - * replaced by the result of its corresponding filter function.
29.2335 - * <p>
29.2336 - * The pre-processing is performed by one or more method handles,
29.2337 - * specified in the elements of the {@code filters} array.
29.2338 - * The first element of the filter array corresponds to the {@code pos}
29.2339 - * argument of the target, and so on in sequence.
29.2340 - * <p>
29.2341 - * Null arguments in the array are treated as identity functions,
29.2342 - * and the corresponding arguments left unchanged.
29.2343 - * (If there are no non-null elements in the array, the original target is returned.)
29.2344 - * Each filter is applied to the corresponding argument of the adapter.
29.2345 - * <p>
29.2346 - * If a filter {@code F} applies to the {@code N}th argument of
29.2347 - * the target, then {@code F} must be a method handle which
29.2348 - * takes exactly one argument. The type of {@code F}'s sole argument
29.2349 - * replaces the corresponding argument type of the target
29.2350 - * in the resulting adapted method handle.
29.2351 - * The return type of {@code F} must be identical to the corresponding
29.2352 - * parameter type of the target.
29.2353 - * <p>
29.2354 - * It is an error if there are elements of {@code filters}
29.2355 - * (null or not)
29.2356 - * which do not correspond to argument positions in the target.
29.2357 - * <p><b>Example:</b>
29.2358 - * <blockquote><pre>{@code
29.2359 -import static java.lang.invoke.MethodHandles.*;
29.2360 -import static java.lang.invoke.MethodType.*;
29.2361 -...
29.2362 -MethodHandle cat = lookup().findVirtual(String.class,
29.2363 - "concat", methodType(String.class, String.class));
29.2364 -MethodHandle upcase = lookup().findVirtual(String.class,
29.2365 - "toUpperCase", methodType(String.class));
29.2366 -assertEquals("xy", (String) cat.invokeExact("x", "y"));
29.2367 -MethodHandle f0 = filterArguments(cat, 0, upcase);
29.2368 -assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
29.2369 -MethodHandle f1 = filterArguments(cat, 1, upcase);
29.2370 -assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
29.2371 -MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
29.2372 -assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
29.2373 - * }</pre></blockquote>
29.2374 - * <p> Here is pseudocode for the resulting adapter:
29.2375 - * <blockquote><pre>{@code
29.2376 - * V target(P... p, A[i]... a[i], B... b);
29.2377 - * A[i] filter[i](V[i]);
29.2378 - * T adapter(P... p, V[i]... v[i], B... b) {
29.2379 - * return target(p..., f[i](v[i])..., b...);
29.2380 - * }
29.2381 - * }</pre></blockquote>
29.2382 - *
29.2383 - * @param target the method handle to invoke after arguments are filtered
29.2384 - * @param pos the position of the first argument to filter
29.2385 - * @param filters method handles to call initially on filtered arguments
29.2386 - * @return method handle which incorporates the specified argument filtering logic
29.2387 - * @throws NullPointerException if the target is null
29.2388 - * or if the {@code filters} array is null
29.2389 - * @throws IllegalArgumentException if a non-null element of {@code filters}
29.2390 - * does not match a corresponding argument type of target as described above,
29.2391 - * or if the {@code pos+filters.length} is greater than {@code target.type().parameterCount()},
29.2392 - * or if the resulting method handle's type would have
29.2393 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.2394 - */
29.2395 - public static
29.2396 - MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
29.2397 - MethodType targetType = target.type();
29.2398 - MethodHandle adapter = target;
29.2399 - MethodType adapterType = null;
29.2400 - assert((adapterType = targetType) != null);
29.2401 - int maxPos = targetType.parameterCount();
29.2402 - if (pos + filters.length > maxPos)
29.2403 - throw newIllegalArgumentException("too many filters");
29.2404 - int curPos = pos-1; // pre-incremented
29.2405 - for (MethodHandle filter : filters) {
29.2406 - curPos += 1;
29.2407 - if (filter == null) continue; // ignore null elements of filters
29.2408 - adapter = filterArgument(adapter, curPos, filter);
29.2409 - assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
29.2410 - }
29.2411 - assert(adapterType.equals(adapter.type()));
29.2412 - return adapter;
29.2413 - }
29.2414 -
29.2415 - /*non-public*/ static
29.2416 - MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
29.2417 - MethodType targetType = target.type();
29.2418 - MethodType filterType = filter.type();
29.2419 - if (filterType.parameterCount() != 1
29.2420 - || filterType.returnType() != targetType.parameterType(pos))
29.2421 - throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
29.2422 - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
29.2423 - }
29.2424 -
29.2425 - /**
29.2426 - * Adapts a target method handle by pre-processing
29.2427 - * a sub-sequence of its arguments with a filter (another method handle).
29.2428 - * The pre-processed arguments are replaced by the result (if any) of the
29.2429 - * filter function.
29.2430 - * The target is then called on the modified (usually shortened) argument list.
29.2431 - * <p>
29.2432 - * If the filter returns a value, the target must accept that value as
29.2433 - * its argument in position {@code pos}, preceded and/or followed by
29.2434 - * any arguments not passed to the filter.
29.2435 - * If the filter returns void, the target must accept all arguments
29.2436 - * not passed to the filter.
29.2437 - * No arguments are reordered, and a result returned from the filter
29.2438 - * replaces (in order) the whole subsequence of arguments originally
29.2439 - * passed to the adapter.
29.2440 - * <p>
29.2441 - * The argument types (if any) of the filter
29.2442 - * replace zero or one argument types of the target, at position {@code pos},
29.2443 - * in the resulting adapted method handle.
29.2444 - * The return type of the filter (if any) must be identical to the
29.2445 - * argument type of the target at position {@code pos}, and that target argument
29.2446 - * is supplied by the return value of the filter.
29.2447 - * <p>
29.2448 - * In all cases, {@code pos} must be greater than or equal to zero, and
29.2449 - * {@code pos} must also be less than or equal to the target's arity.
29.2450 - * <p><b>Example:</b>
29.2451 - * <blockquote><pre>{@code
29.2452 -import static java.lang.invoke.MethodHandles.*;
29.2453 -import static java.lang.invoke.MethodType.*;
29.2454 -...
29.2455 -MethodHandle deepToString = publicLookup()
29.2456 - .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));
29.2457 -
29.2458 -MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
29.2459 -assertEquals("[strange]", (String) ts1.invokeExact("strange"));
29.2460 -
29.2461 -MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
29.2462 -assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));
29.2463 -
29.2464 -MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
29.2465 -MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
29.2466 -assertEquals("[top, [up, down], strange]",
29.2467 - (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));
29.2468 -
29.2469 -MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
29.2470 -assertEquals("[top, [up, down], [strange]]",
29.2471 - (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));
29.2472 -
29.2473 -MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
29.2474 -assertEquals("[top, [[up, down, strange], charm], bottom]",
29.2475 - (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
29.2476 - * }</pre></blockquote>
29.2477 - * <p> Here is pseudocode for the resulting adapter:
29.2478 - * <blockquote><pre>{@code
29.2479 - * T target(A...,V,C...);
29.2480 - * V filter(B...);
29.2481 - * T adapter(A... a,B... b,C... c) {
29.2482 - * V v = filter(b...);
29.2483 - * return target(a...,v,c...);
29.2484 - * }
29.2485 - * // and if the filter has no arguments:
29.2486 - * T target2(A...,V,C...);
29.2487 - * V filter2();
29.2488 - * T adapter2(A... a,C... c) {
29.2489 - * V v = filter2();
29.2490 - * return target2(a...,v,c...);
29.2491 - * }
29.2492 - * // and if the filter has a void return:
29.2493 - * T target3(A...,C...);
29.2494 - * void filter3(B...);
29.2495 - * void adapter3(A... a,B... b,C... c) {
29.2496 - * filter3(b...);
29.2497 - * return target3(a...,c...);
29.2498 - * }
29.2499 - * }</pre></blockquote>
29.2500 - * <p>
29.2501 - * A collection adapter {@code collectArguments(mh, 0, coll)} is equivalent to
29.2502 - * one which first "folds" the affected arguments, and then drops them, in separate
29.2503 - * steps as follows:
29.2504 - * <blockquote><pre>{@code
29.2505 - * mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
29.2506 - * mh = MethodHandles.foldArguments(mh, coll); //step 1
29.2507 - * }</pre></blockquote>
29.2508 - * If the target method handle consumes no arguments besides than the result
29.2509 - * (if any) of the filter {@code coll}, then {@code collectArguments(mh, 0, coll)}
29.2510 - * is equivalent to {@code filterReturnValue(coll, mh)}.
29.2511 - * If the filter method handle {@code coll} consumes one argument and produces
29.2512 - * a non-void result, then {@code collectArguments(mh, N, coll)}
29.2513 - * is equivalent to {@code filterArguments(mh, N, coll)}.
29.2514 - * Other equivalences are possible but would require argument permutation.
29.2515 - *
29.2516 - * @param target the method handle to invoke after filtering the subsequence of arguments
29.2517 - * @param pos the position of the first adapter argument to pass to the filter,
29.2518 - * and/or the target argument which receives the result of the filter
29.2519 - * @param filter method handle to call on the subsequence of arguments
29.2520 - * @return method handle which incorporates the specified argument subsequence filtering logic
29.2521 - * @throws NullPointerException if either argument is null
29.2522 - * @throws IllegalArgumentException if the return type of {@code filter}
29.2523 - * is non-void and is not the same as the {@code pos} argument of the target,
29.2524 - * or if {@code pos} is not between 0 and the target's arity, inclusive,
29.2525 - * or if the resulting method handle's type would have
29.2526 - * <a href="MethodHandle.html#maxarity">too many parameters</a>
29.2527 - * @see MethodHandles#foldArguments
29.2528 - * @see MethodHandles#filterArguments
29.2529 - * @see MethodHandles#filterReturnValue
29.2530 - */
29.2531 - public static
29.2532 - MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
29.2533 - MethodType targetType = target.type();
29.2534 - MethodType filterType = filter.type();
29.2535 - if (filterType.returnType() != void.class &&
29.2536 - filterType.returnType() != targetType.parameterType(pos))
29.2537 - throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
29.2538 - return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
29.2539 - }
29.2540 -
29.2541 - /**
29.2542 - * Adapts a target method handle by post-processing
29.2543 - * its return value (if any) with a filter (another method handle).
29.2544 - * The result of the filter is returned from the adapter.
29.2545 - * <p>
29.2546 - * If the target returns a value, the filter must accept that value as
29.2547 - * its only argument.
29.2548 - * If the target returns void, the filter must accept no arguments.
29.2549 - * <p>
29.2550 - * The return type of the filter
29.2551 - * replaces the return type of the target
29.2552 - * in the resulting adapted method handle.
29.2553 - * The argument type of the filter (if any) must be identical to the
29.2554 - * return type of the target.
29.2555 - * <p><b>Example:</b>
29.2556 - * <blockquote><pre>{@code
29.2557 -import static java.lang.invoke.MethodHandles.*;
29.2558 -import static java.lang.invoke.MethodType.*;
29.2559 -...
29.2560 -MethodHandle cat = lookup().findVirtual(String.class,
29.2561 - "concat", methodType(String.class, String.class));
29.2562 -MethodHandle length = lookup().findVirtual(String.class,
29.2563 - "length", methodType(int.class));
29.2564 -System.out.println((String) cat.invokeExact("x", "y")); // xy
29.2565 -MethodHandle f0 = filterReturnValue(cat, length);
29.2566 -System.out.println((int) f0.invokeExact("x", "y")); // 2
29.2567 - * }</pre></blockquote>
29.2568 - * <p> Here is pseudocode for the resulting adapter:
29.2569 - * <blockquote><pre>{@code
29.2570 - * V target(A...);
29.2571 - * T filter(V);
29.2572 - * T adapter(A... a) {
29.2573 - * V v = target(a...);
29.2574 - * return filter(v);
29.2575 - * }
29.2576 - * // and if the target has a void return:
29.2577 - * void target2(A...);
29.2578 - * T filter2();
29.2579 - * T adapter2(A... a) {
29.2580 - * target2(a...);
29.2581 - * return filter2();
29.2582 - * }
29.2583 - * // and if the filter has a void return:
29.2584 - * V target3(A...);
29.2585 - * void filter3(V);
29.2586 - * void adapter3(A... a) {
29.2587 - * V v = target3(a...);
29.2588 - * filter3(v);
29.2589 - * }
29.2590 - * }</pre></blockquote>
29.2591 - * @param target the method handle to invoke before filtering the return value
29.2592 - * @param filter method handle to call on the return value
29.2593 - * @return method handle which incorporates the specified return value filtering logic
29.2594 - * @throws NullPointerException if either argument is null
29.2595 - * @throws IllegalArgumentException if the argument list of {@code filter}
29.2596 - * does not match the return type of target as described above
29.2597 - */
29.2598 - public static
29.2599 - MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
29.2600 - MethodType targetType = target.type();
29.2601 - MethodType filterType = filter.type();
29.2602 - Class<?> rtype = targetType.returnType();
29.2603 - int filterValues = filterType.parameterCount();
29.2604 - if (filterValues == 0
29.2605 - ? (rtype != void.class)
29.2606 - : (rtype != filterType.parameterType(0)))
29.2607 - throw newIllegalArgumentException("target and filter types do not match", target, filter);
29.2608 - // result = fold( lambda(retval, arg...) { filter(retval) },
29.2609 - // lambda( arg...) { target(arg...) } )
29.2610 - return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
29.2611 - }
29.2612 -
29.2613 - /**
29.2614 - * Adapts a target method handle by pre-processing
29.2615 - * some of its arguments, and then calling the target with
29.2616 - * the result of the pre-processing, inserted into the original
29.2617 - * sequence of arguments.
29.2618 - * <p>
29.2619 - * The pre-processing is performed by {@code combiner}, a second method handle.
29.2620 - * Of the arguments passed to the adapter, the first {@code N} arguments
29.2621 - * are copied to the combiner, which is then called.
29.2622 - * (Here, {@code N} is defined as the parameter count of the combiner.)
29.2623 - * After this, control passes to the target, with any result
29.2624 - * from the combiner inserted before the original {@code N} incoming
29.2625 - * arguments.
29.2626 - * <p>
29.2627 - * If the combiner returns a value, the first parameter type of the target
29.2628 - * must be identical with the return type of the combiner, and the next
29.2629 - * {@code N} parameter types of the target must exactly match the parameters
29.2630 - * of the combiner.
29.2631 - * <p>
29.2632 - * If the combiner has a void return, no result will be inserted,
29.2633 - * and the first {@code N} parameter types of the target
29.2634 - * must exactly match the parameters of the combiner.
29.2635 - * <p>
29.2636 - * The resulting adapter is the same type as the target, except that the
29.2637 - * first parameter type is dropped,
29.2638 - * if it corresponds to the result of the combiner.
29.2639 - * <p>
29.2640 - * (Note that {@link #dropArguments(MethodHandle,int,List) dropArguments} can be used to remove any arguments
29.2641 - * that either the combiner or the target does not wish to receive.
29.2642 - * If some of the incoming arguments are destined only for the combiner,
29.2643 - * consider using {@link MethodHandle#asCollector asCollector} instead, since those
29.2644 - * arguments will not need to be live on the stack on entry to the
29.2645 - * target.)
29.2646 - * <p><b>Example:</b>
29.2647 - * <blockquote><pre>{@code
29.2648 -import static java.lang.invoke.MethodHandles.*;
29.2649 -import static java.lang.invoke.MethodType.*;
29.2650 -...
29.2651 -MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
29.2652 - "println", methodType(void.class, String.class))
29.2653 - .bindTo(System.out);
29.2654 -MethodHandle cat = lookup().findVirtual(String.class,
29.2655 - "concat", methodType(String.class, String.class));
29.2656 -assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
29.2657 -MethodHandle catTrace = foldArguments(cat, trace);
29.2658 -// also prints "boo":
29.2659 -assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
29.2660 - * }</pre></blockquote>
29.2661 - * <p> Here is pseudocode for the resulting adapter:
29.2662 - * <blockquote><pre>{@code
29.2663 - * // there are N arguments in A...
29.2664 - * T target(V, A[N]..., B...);
29.2665 - * V combiner(A...);
29.2666 - * T adapter(A... a, B... b) {
29.2667 - * V v = combiner(a...);
29.2668 - * return target(v, a..., b...);
29.2669 - * }
29.2670 - * // and if the combiner has a void return:
29.2671 - * T target2(A[N]..., B...);
29.2672 - * void combiner2(A...);
29.2673 - * T adapter2(A... a, B... b) {
29.2674 - * combiner2(a...);
29.2675 - * return target2(a..., b...);
29.2676 - * }
29.2677 - * }</pre></blockquote>
29.2678 - * @param target the method handle to invoke after arguments are combined
29.2679 - * @param combiner method handle to call initially on the incoming arguments
29.2680 - * @return method handle which incorporates the specified argument folding logic
29.2681 - * @throws NullPointerException if either argument is null
29.2682 - * @throws IllegalArgumentException if {@code combiner}'s return type
29.2683 - * is non-void and not the same as the first argument type of
29.2684 - * the target, or if the initial {@code N} argument types
29.2685 - * of the target
29.2686 - * (skipping one matching the {@code combiner}'s return type)
29.2687 - * are not identical with the argument types of {@code combiner}
29.2688 - */
29.2689 - public static
29.2690 - MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
29.2691 - int pos = 0;
29.2692 - MethodType targetType = target.type();
29.2693 - MethodType combinerType = combiner.type();
29.2694 - int foldPos = pos;
29.2695 - int foldArgs = combinerType.parameterCount();
29.2696 - int foldVals = combinerType.returnType() == void.class ? 0 : 1;
29.2697 - int afterInsertPos = foldPos + foldVals;
29.2698 - boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
29.2699 - if (ok && !(combinerType.parameterList()
29.2700 - .equals(targetType.parameterList().subList(afterInsertPos,
29.2701 - afterInsertPos + foldArgs))))
29.2702 - ok = false;
29.2703 - if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
29.2704 - ok = false;
29.2705 - if (!ok)
29.2706 - throw misMatchedTypes("target and combiner types", targetType, combinerType);
29.2707 - MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
29.2708 - return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
29.2709 - }
29.2710 -
29.2711 - /**
29.2712 - * Makes a method handle which adapts a target method handle,
29.2713 - * by guarding it with a test, a boolean-valued method handle.
29.2714 - * If the guard fails, a fallback handle is called instead.
29.2715 - * All three method handles must have the same corresponding
29.2716 - * argument and return types, except that the return type
29.2717 - * of the test must be boolean, and the test is allowed
29.2718 - * to have fewer arguments than the other two method handles.
29.2719 - * <p> Here is pseudocode for the resulting adapter:
29.2720 - * <blockquote><pre>{@code
29.2721 - * boolean test(A...);
29.2722 - * T target(A...,B...);
29.2723 - * T fallback(A...,B...);
29.2724 - * T adapter(A... a,B... b) {
29.2725 - * if (test(a...))
29.2726 - * return target(a..., b...);
29.2727 - * else
29.2728 - * return fallback(a..., b...);
29.2729 - * }
29.2730 - * }</pre></blockquote>
29.2731 - * Note that the test arguments ({@code a...} in the pseudocode) cannot
29.2732 - * be modified by execution of the test, and so are passed unchanged
29.2733 - * from the caller to the target or fallback as appropriate.
29.2734 - * @param test method handle used for test, must return boolean
29.2735 - * @param target method handle to call if test passes
29.2736 - * @param fallback method handle to call if test fails
29.2737 - * @return method handle which incorporates the specified if/then/else logic
29.2738 - * @throws NullPointerException if any argument is null
29.2739 - * @throws IllegalArgumentException if {@code test} does not return boolean,
29.2740 - * or if all three method types do not match (with the return
29.2741 - * type of {@code test} changed to match that of the target).
29.2742 - */
29.2743 - public static
29.2744 - MethodHandle guardWithTest(MethodHandle test,
29.2745 - MethodHandle target,
29.2746 - MethodHandle fallback) {
29.2747 - MethodType gtype = test.type();
29.2748 - MethodType ttype = target.type();
29.2749 - MethodType ftype = fallback.type();
29.2750 - if (!ttype.equals(ftype))
29.2751 - throw misMatchedTypes("target and fallback types", ttype, ftype);
29.2752 - if (gtype.returnType() != boolean.class)
29.2753 - throw newIllegalArgumentException("guard type is not a predicate "+gtype);
29.2754 - List<Class<?>> targs = ttype.parameterList();
29.2755 - List<Class<?>> gargs = gtype.parameterList();
29.2756 - if (!targs.equals(gargs)) {
29.2757 - int gpc = gargs.size(), tpc = targs.size();
29.2758 - if (gpc >= tpc || !targs.subList(0, gpc).equals(gargs))
29.2759 - throw misMatchedTypes("target and test types", ttype, gtype);
29.2760 - test = dropArguments(test, gpc, targs.subList(gpc, tpc));
29.2761 - gtype = test.type();
29.2762 - }
29.2763 - return MethodHandleImpl.makeGuardWithTest(test, target, fallback);
29.2764 - }
29.2765 -
29.2766 - static RuntimeException misMatchedTypes(String what, MethodType t1, MethodType t2) {
29.2767 - return newIllegalArgumentException(what + " must match: " + t1 + " != " + t2);
29.2768 - }
29.2769 -
29.2770 - /**
29.2771 - * Makes a method handle which adapts a target method handle,
29.2772 - * by running it inside an exception handler.
29.2773 - * If the target returns normally, the adapter returns that value.
29.2774 - * If an exception matching the specified type is thrown, the fallback
29.2775 - * handle is called instead on the exception, plus the original arguments.
29.2776 - * <p>
29.2777 - * The target and handler must have the same corresponding
29.2778 - * argument and return types, except that handler may omit trailing arguments
29.2779 - * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
29.2780 - * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
29.2781 - * <p> Here is pseudocode for the resulting adapter:
29.2782 - * <blockquote><pre>{@code
29.2783 - * T target(A..., B...);
29.2784 - * T handler(ExType, A...);
29.2785 - * T adapter(A... a, B... b) {
29.2786 - * try {
29.2787 - * return target(a..., b...);
29.2788 - * } catch (ExType ex) {
29.2789 - * return handler(ex, a...);
29.2790 - * }
29.2791 - * }
29.2792 - * }</pre></blockquote>
29.2793 - * Note that the saved arguments ({@code a...} in the pseudocode) cannot
29.2794 - * be modified by execution of the target, and so are passed unchanged
29.2795 - * from the caller to the handler, if the handler is invoked.
29.2796 - * <p>
29.2797 - * The target and handler must return the same type, even if the handler
29.2798 - * always throws. (This might happen, for instance, because the handler
29.2799 - * is simulating a {@code finally} clause).
29.2800 - * To create such a throwing handler, compose the handler creation logic
29.2801 - * with {@link #throwException throwException},
29.2802 - * in order to create a method handle of the correct return type.
29.2803 - * @param target method handle to call
29.2804 - * @param exType the type of exception which the handler will catch
29.2805 - * @param handler method handle to call if a matching exception is thrown
29.2806 - * @return method handle which incorporates the specified try/catch logic
29.2807 - * @throws NullPointerException if any argument is null
29.2808 - * @throws IllegalArgumentException if {@code handler} does not accept
29.2809 - * the given exception type, or if the method handle types do
29.2810 - * not match in their return types and their
29.2811 - * corresponding parameters
29.2812 - */
29.2813 - public static
29.2814 - MethodHandle catchException(MethodHandle target,
29.2815 - Class<? extends Throwable> exType,
29.2816 - MethodHandle handler) {
29.2817 - MethodType ttype = target.type();
29.2818 - MethodType htype = handler.type();
29.2819 - if (htype.parameterCount() < 1 ||
29.2820 - !htype.parameterType(0).isAssignableFrom(exType))
29.2821 - throw newIllegalArgumentException("handler does not accept exception type "+exType);
29.2822 - if (htype.returnType() != ttype.returnType())
29.2823 - throw misMatchedTypes("target and handler return types", ttype, htype);
29.2824 - List<Class<?>> targs = ttype.parameterList();
29.2825 - List<Class<?>> hargs = htype.parameterList();
29.2826 - hargs = hargs.subList(1, hargs.size()); // omit leading parameter from handler
29.2827 - if (!targs.equals(hargs)) {
29.2828 - int hpc = hargs.size(), tpc = targs.size();
29.2829 - if (hpc >= tpc || !targs.subList(0, hpc).equals(hargs))
29.2830 - throw misMatchedTypes("target and handler types", ttype, htype);
29.2831 - handler = dropArguments(handler, 1+hpc, targs.subList(hpc, tpc));
29.2832 - htype = handler.type();
29.2833 - }
29.2834 - return MethodHandleImpl.makeGuardWithCatch(target, exType, handler);
29.2835 - }
29.2836 -
29.2837 - /**
29.2838 - * Produces a method handle which will throw exceptions of the given {@code exType}.
29.2839 - * The method handle will accept a single argument of {@code exType},
29.2840 - * and immediately throw it as an exception.
29.2841 - * The method type will nominally specify a return of {@code returnType}.
29.2842 - * The return type may be anything convenient: It doesn't matter to the
29.2843 - * method handle's behavior, since it will never return normally.
29.2844 - * @param returnType the return type of the desired method handle
29.2845 - * @param exType the parameter type of the desired method handle
29.2846 - * @return method handle which can throw the given exceptions
29.2847 - * @throws NullPointerException if either argument is null
29.2848 - */
29.2849 - public static
29.2850 - MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
29.2851 - if (!Throwable.class.isAssignableFrom(exType))
29.2852 - throw new ClassCastException(exType.getName());
29.2853 - return MethodHandleImpl.throwException(MethodType.methodType(returnType, exType));
29.2854 - }
29.2855 -}
30.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodType.java Sun Aug 17 20:09:05 2014 +0200
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,1149 +0,0 @@
30.4 -/*
30.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
30.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30.7 - *
30.8 - * This code is free software; you can redistribute it and/or modify it
30.9 - * under the terms of the GNU General Public License version 2 only, as
30.10 - * published by the Free Software Foundation. Oracle designates this
30.11 - * particular file as subject to the "Classpath" exception as provided
30.12 - * by Oracle in the LICENSE file that accompanied this code.
30.13 - *
30.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
30.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30.17 - * version 2 for more details (a copy is included in the LICENSE file that
30.18 - * accompanied this code).
30.19 - *
30.20 - * You should have received a copy of the GNU General Public License version
30.21 - * 2 along with this work; if not, write to the Free Software Foundation,
30.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30.23 - *
30.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
30.25 - * or visit www.oracle.com if you need additional information or have any
30.26 - * questions.
30.27 - */
30.28 -
30.29 -package java.lang.invoke;
30.30 -
30.31 -import sun.invoke.util.Wrapper;
30.32 -import java.lang.ref.WeakReference;
30.33 -import java.lang.ref.Reference;
30.34 -import java.lang.ref.ReferenceQueue;
30.35 -import java.util.Arrays;
30.36 -import java.util.Collections;
30.37 -import java.util.List;
30.38 -import java.util.Objects;
30.39 -import java.util.concurrent.ConcurrentMap;
30.40 -import java.util.concurrent.ConcurrentHashMap;
30.41 -import sun.invoke.util.BytecodeDescriptor;
30.42 -import static java.lang.invoke.MethodHandleStatics.*;
30.43 -import sun.invoke.util.VerifyType;
30.44 -
30.45 -/**
30.46 - * A method type represents the arguments and return type accepted and
30.47 - * returned by a method handle, or the arguments and return type passed
30.48 - * and expected by a method handle caller. Method types must be properly
30.49 - * matched between a method handle and all its callers,
30.50 - * and the JVM's operations enforce this matching at, specifically
30.51 - * during calls to {@link MethodHandle#invokeExact MethodHandle.invokeExact}
30.52 - * and {@link MethodHandle#invoke MethodHandle.invoke}, and during execution
30.53 - * of {@code invokedynamic} instructions.
30.54 - * <p>
30.55 - * The structure is a return type accompanied by any number of parameter types.
30.56 - * The types (primitive, {@code void}, and reference) are represented by {@link Class} objects.
30.57 - * (For ease of exposition, we treat {@code void} as if it were a type.
30.58 - * In fact, it denotes the absence of a return type.)
30.59 - * <p>
30.60 - * All instances of {@code MethodType} are immutable.
30.61 - * Two instances are completely interchangeable if they compare equal.
30.62 - * Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
30.63 - * <p>
30.64 - * This type can be created only by factory methods.
30.65 - * All factory methods may cache values, though caching is not guaranteed.
30.66 - * Some factory methods are static, while others are virtual methods which
30.67 - * modify precursor method types, e.g., by changing a selected parameter.
30.68 - * <p>
30.69 - * Factory methods which operate on groups of parameter types
30.70 - * are systematically presented in two versions, so that both Java arrays and
30.71 - * Java lists can be used to work with groups of parameter types.
30.72 - * The query methods {@code parameterArray} and {@code parameterList}
30.73 - * also provide a choice between arrays and lists.
30.74 - * <p>
30.75 - * {@code MethodType} objects are sometimes derived from bytecode instructions
30.76 - * such as {@code invokedynamic}, specifically from the type descriptor strings associated
30.77 - * with the instructions in a class file's constant pool.
30.78 - * <p>
30.79 - * Like classes and strings, method types can also be represented directly
30.80 - * in a class file's constant pool as constants.
30.81 - * A method type may be loaded by an {@code ldc} instruction which refers
30.82 - * to a suitable {@code CONSTANT_MethodType} constant pool entry.
30.83 - * The entry refers to a {@code CONSTANT_Utf8} spelling for the descriptor string.
30.84 - * (For full details on method type constants,
30.85 - * see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
30.86 - * <p>
30.87 - * When the JVM materializes a {@code MethodType} from a descriptor string,
30.88 - * all classes named in the descriptor must be accessible, and will be loaded.
30.89 - * (But the classes need not be initialized, as is the case with a {@code CONSTANT_Class}.)
30.90 - * This loading may occur at any time before the {@code MethodType} object is first derived.
30.91 - * @author John Rose, JSR 292 EG
30.92 - */
30.93 -public final
30.94 -class MethodType implements java.io.Serializable {
30.95 - private static final long serialVersionUID = 292L; // {rtype, {ptype...}}
30.96 -
30.97 - // The rtype and ptypes fields define the structural identity of the method type:
30.98 - private final Class<?> rtype;
30.99 - private final Class<?>[] ptypes;
30.100 -
30.101 - // The remaining fields are caches of various sorts:
30.102 - private @Stable MethodTypeForm form; // erased form, plus cached data about primitives
30.103 - private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version
30.104 - private @Stable Invokers invokers; // cache of handy higher-order adapters
30.105 - private @Stable String methodDescriptor; // cache for toMethodDescriptorString
30.106 -
30.107 - /**
30.108 - * Check the given parameters for validity and store them into the final fields.
30.109 - */
30.110 - private MethodType(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
30.111 - checkRtype(rtype);
30.112 - checkPtypes(ptypes);
30.113 - this.rtype = rtype;
30.114 - // defensively copy the array passed in by the user
30.115 - this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
30.116 - }
30.117 -
30.118 - /**
30.119 - * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
30.120 - * Does not check the given parameters for validity, and must be discarded after it is used as a searching key.
30.121 - * The parameters are reversed for this constructor, so that is is not accidentally used.
30.122 - */
30.123 - private MethodType(Class<?>[] ptypes, Class<?> rtype) {
30.124 - this.rtype = rtype;
30.125 - this.ptypes = ptypes;
30.126 - }
30.127 -
30.128 - /*trusted*/ MethodTypeForm form() { return form; }
30.129 - /*trusted*/ Class<?> rtype() { return rtype; }
30.130 - /*trusted*/ Class<?>[] ptypes() { return ptypes; }
30.131 -
30.132 - void setForm(MethodTypeForm f) { form = f; }
30.133 -
30.134 - /** This number, mandated by the JVM spec as 255,
30.135 - * is the maximum number of <em>slots</em>
30.136 - * that any Java method can receive in its argument list.
30.137 - * It limits both JVM signatures and method type objects.
30.138 - * The longest possible invocation will look like
30.139 - * {@code staticMethod(arg1, arg2, ..., arg255)} or
30.140 - * {@code x.virtualMethod(arg1, arg2, ..., arg254)}.
30.141 - */
30.142 - /*non-public*/ static final int MAX_JVM_ARITY = 255; // this is mandated by the JVM spec.
30.143 -
30.144 - /** This number is the maximum arity of a method handle, 254.
30.145 - * It is derived from the absolute JVM-imposed arity by subtracting one,
30.146 - * which is the slot occupied by the method handle itself at the
30.147 - * beginning of the argument list used to invoke the method handle.
30.148 - * The longest possible invocation will look like
30.149 - * {@code mh.invoke(arg1, arg2, ..., arg254)}.
30.150 - */
30.151 - // Issue: Should we allow MH.invokeWithArguments to go to the full 255?
30.152 - /*non-public*/ static final int MAX_MH_ARITY = MAX_JVM_ARITY-1; // deduct one for mh receiver
30.153 -
30.154 - /** This number is the maximum arity of a method handle invoker, 253.
30.155 - * It is derived from the absolute JVM-imposed arity by subtracting two,
30.156 - * which are the slots occupied by invoke method handle, and the
30.157 - * target method handle, which are both at the beginning of the argument
30.158 - * list used to invoke the target method handle.
30.159 - * The longest possible invocation will look like
30.160 - * {@code invokermh.invoke(targetmh, arg1, arg2, ..., arg253)}.
30.161 - */
30.162 - /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker
30.163 -
30.164 - private static void checkRtype(Class<?> rtype) {
30.165 - Objects.requireNonNull(rtype);
30.166 - }
30.167 - private static void checkPtype(Class<?> ptype) {
30.168 - Objects.requireNonNull(ptype);
30.169 - if (ptype == void.class)
30.170 - throw newIllegalArgumentException("parameter type cannot be void");
30.171 - }
30.172 - /** Return number of extra slots (count of long/double args). */
30.173 - private static int checkPtypes(Class<?>[] ptypes) {
30.174 - int slots = 0;
30.175 - for (Class<?> ptype : ptypes) {
30.176 - checkPtype(ptype);
30.177 - if (ptype == double.class || ptype == long.class) {
30.178 - slots++;
30.179 - }
30.180 - }
30.181 - checkSlotCount(ptypes.length + slots);
30.182 - return slots;
30.183 - }
30.184 - static void checkSlotCount(int count) {
30.185 - assert((MAX_JVM_ARITY & (MAX_JVM_ARITY+1)) == 0);
30.186 - // MAX_JVM_ARITY must be power of 2 minus 1 for following code trick to work:
30.187 - if ((count & MAX_JVM_ARITY) != count)
30.188 - throw newIllegalArgumentException("bad parameter count "+count);
30.189 - }
30.190 - private static IndexOutOfBoundsException newIndexOutOfBoundsException(Object num) {
30.191 - if (num instanceof Integer) num = "bad index: "+num;
30.192 - return new IndexOutOfBoundsException(num.toString());
30.193 - }
30.194 -
30.195 - static final ConcurrentWeakInternSet<MethodType> internTable = new ConcurrentWeakInternSet<>();
30.196 -
30.197 - static final Class<?>[] NO_PTYPES = {};
30.198 -
30.199 - /**
30.200 - * Finds or creates an instance of the given method type.
30.201 - * @param rtype the return type
30.202 - * @param ptypes the parameter types
30.203 - * @return a method type with the given components
30.204 - * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
30.205 - * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
30.206 - */
30.207 - public static
30.208 - MethodType methodType(Class<?> rtype, Class<?>[] ptypes) {
30.209 - return makeImpl(rtype, ptypes, false);
30.210 - }
30.211 -
30.212 - /**
30.213 - * Finds or creates a method type with the given components.
30.214 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.215 - * @param rtype the return type
30.216 - * @param ptypes the parameter types
30.217 - * @return a method type with the given components
30.218 - * @throws NullPointerException if {@code rtype} or {@code ptypes} or any element of {@code ptypes} is null
30.219 - * @throws IllegalArgumentException if any element of {@code ptypes} is {@code void.class}
30.220 - */
30.221 - public static
30.222 - MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) {
30.223 - boolean notrust = false; // random List impl. could return evil ptypes array
30.224 - return makeImpl(rtype, listToArray(ptypes), notrust);
30.225 - }
30.226 -
30.227 - private static Class<?>[] listToArray(List<Class<?>> ptypes) {
30.228 - // sanity check the size before the toArray call, since size might be huge
30.229 - checkSlotCount(ptypes.size());
30.230 - return ptypes.toArray(NO_PTYPES);
30.231 - }
30.232 -
30.233 - /**
30.234 - * Finds or creates a method type with the given components.
30.235 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.236 - * The leading parameter type is prepended to the remaining array.
30.237 - * @param rtype the return type
30.238 - * @param ptype0 the first parameter type
30.239 - * @param ptypes the remaining parameter types
30.240 - * @return a method type with the given components
30.241 - * @throws NullPointerException if {@code rtype} or {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is null
30.242 - * @throws IllegalArgumentException if {@code ptype0} or {@code ptypes} or any element of {@code ptypes} is {@code void.class}
30.243 - */
30.244 - public static
30.245 - MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
30.246 - Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
30.247 - ptypes1[0] = ptype0;
30.248 - System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
30.249 - return makeImpl(rtype, ptypes1, true);
30.250 - }
30.251 -
30.252 - /**
30.253 - * Finds or creates a method type with the given components.
30.254 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.255 - * The resulting method has no parameter types.
30.256 - * @param rtype the return type
30.257 - * @return a method type with the given return value
30.258 - * @throws NullPointerException if {@code rtype} is null
30.259 - */
30.260 - public static
30.261 - MethodType methodType(Class<?> rtype) {
30.262 - return makeImpl(rtype, NO_PTYPES, true);
30.263 - }
30.264 -
30.265 - /**
30.266 - * Finds or creates a method type with the given components.
30.267 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.268 - * The resulting method has the single given parameter type.
30.269 - * @param rtype the return type
30.270 - * @param ptype0 the parameter type
30.271 - * @return a method type with the given return value and parameter type
30.272 - * @throws NullPointerException if {@code rtype} or {@code ptype0} is null
30.273 - * @throws IllegalArgumentException if {@code ptype0} is {@code void.class}
30.274 - */
30.275 - public static
30.276 - MethodType methodType(Class<?> rtype, Class<?> ptype0) {
30.277 - return makeImpl(rtype, new Class<?>[]{ ptype0 }, true);
30.278 - }
30.279 -
30.280 - /**
30.281 - * Finds or creates a method type with the given components.
30.282 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.283 - * The resulting method has the same parameter types as {@code ptypes},
30.284 - * and the specified return type.
30.285 - * @param rtype the return type
30.286 - * @param ptypes the method type which supplies the parameter types
30.287 - * @return a method type with the given components
30.288 - * @throws NullPointerException if {@code rtype} or {@code ptypes} is null
30.289 - */
30.290 - public static
30.291 - MethodType methodType(Class<?> rtype, MethodType ptypes) {
30.292 - return makeImpl(rtype, ptypes.ptypes, true);
30.293 - }
30.294 -
30.295 - /**
30.296 - * Sole factory method to find or create an interned method type.
30.297 - * @param rtype desired return type
30.298 - * @param ptypes desired parameter types
30.299 - * @param trusted whether the ptypes can be used without cloning
30.300 - * @return the unique method type of the desired structure
30.301 - */
30.302 - /*trusted*/ static
30.303 - MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
30.304 - MethodType mt = internTable.get(new MethodType(ptypes, rtype));
30.305 - if (mt != null)
30.306 - return mt;
30.307 - if (ptypes.length == 0) {
30.308 - ptypes = NO_PTYPES; trusted = true;
30.309 - }
30.310 - mt = new MethodType(rtype, ptypes, trusted);
30.311 - // promote the object to the Real Thing, and reprobe
30.312 - mt.form = MethodTypeForm.findForm(mt);
30.313 - return internTable.add(mt);
30.314 - }
30.315 - private static final MethodType[] objectOnlyTypes = new MethodType[20];
30.316 -
30.317 - /**
30.318 - * Finds or creates a method type whose components are {@code Object} with an optional trailing {@code Object[]} array.
30.319 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.320 - * All parameters and the return type will be {@code Object},
30.321 - * except the final array parameter if any, which will be {@code Object[]}.
30.322 - * @param objectArgCount number of parameters (excluding the final array parameter if any)
30.323 - * @param finalArray whether there will be a trailing array parameter, of type {@code Object[]}
30.324 - * @return a generally applicable method type, for all calls of the given fixed argument count and a collected array of further arguments
30.325 - * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255 (or 254, if {@code finalArray} is true)
30.326 - * @see #genericMethodType(int)
30.327 - */
30.328 - public static
30.329 - MethodType genericMethodType(int objectArgCount, boolean finalArray) {
30.330 - MethodType mt;
30.331 - checkSlotCount(objectArgCount);
30.332 - int ivarargs = (!finalArray ? 0 : 1);
30.333 - int ootIndex = objectArgCount*2 + ivarargs;
30.334 - if (ootIndex < objectOnlyTypes.length) {
30.335 - mt = objectOnlyTypes[ootIndex];
30.336 - if (mt != null) return mt;
30.337 - }
30.338 - Class<?>[] ptypes = new Class<?>[objectArgCount + ivarargs];
30.339 - Arrays.fill(ptypes, Object.class);
30.340 - if (ivarargs != 0) ptypes[objectArgCount] = Object[].class;
30.341 - mt = makeImpl(Object.class, ptypes, true);
30.342 - if (ootIndex < objectOnlyTypes.length) {
30.343 - objectOnlyTypes[ootIndex] = mt; // cache it here also!
30.344 - }
30.345 - return mt;
30.346 - }
30.347 -
30.348 - /**
30.349 - * Finds or creates a method type whose components are all {@code Object}.
30.350 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.351 - * All parameters and the return type will be Object.
30.352 - * @param objectArgCount number of parameters
30.353 - * @return a generally applicable method type, for all calls of the given argument count
30.354 - * @throws IllegalArgumentException if {@code objectArgCount} is negative or greater than 255
30.355 - * @see #genericMethodType(int, boolean)
30.356 - */
30.357 - public static
30.358 - MethodType genericMethodType(int objectArgCount) {
30.359 - return genericMethodType(objectArgCount, false);
30.360 - }
30.361 -
30.362 - /**
30.363 - * Finds or creates a method type with a single different parameter type.
30.364 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.365 - * @param num the index (zero-based) of the parameter type to change
30.366 - * @param nptype a new parameter type to replace the old one with
30.367 - * @return the same type, except with the selected parameter changed
30.368 - * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
30.369 - * @throws IllegalArgumentException if {@code nptype} is {@code void.class}
30.370 - * @throws NullPointerException if {@code nptype} is null
30.371 - */
30.372 - public MethodType changeParameterType(int num, Class<?> nptype) {
30.373 - if (parameterType(num) == nptype) return this;
30.374 - checkPtype(nptype);
30.375 - Class<?>[] nptypes = ptypes.clone();
30.376 - nptypes[num] = nptype;
30.377 - return makeImpl(rtype, nptypes, true);
30.378 - }
30.379 -
30.380 - /**
30.381 - * Finds or creates a method type with additional parameter types.
30.382 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.383 - * @param num the position (zero-based) of the inserted parameter type(s)
30.384 - * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
30.385 - * @return the same type, except with the selected parameter(s) inserted
30.386 - * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
30.387 - * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
30.388 - * or if the resulting method type would have more than 255 parameter slots
30.389 - * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
30.390 - */
30.391 - public MethodType insertParameterTypes(int num, Class<?>... ptypesToInsert) {
30.392 - int len = ptypes.length;
30.393 - if (num < 0 || num > len)
30.394 - throw newIndexOutOfBoundsException(num);
30.395 - int ins = checkPtypes(ptypesToInsert);
30.396 - checkSlotCount(parameterSlotCount() + ptypesToInsert.length + ins);
30.397 - int ilen = ptypesToInsert.length;
30.398 - if (ilen == 0) return this;
30.399 - Class<?>[] nptypes = Arrays.copyOfRange(ptypes, 0, len+ilen);
30.400 - System.arraycopy(nptypes, num, nptypes, num+ilen, len-num);
30.401 - System.arraycopy(ptypesToInsert, 0, nptypes, num, ilen);
30.402 - return makeImpl(rtype, nptypes, true);
30.403 - }
30.404 -
30.405 - /**
30.406 - * Finds or creates a method type with additional parameter types.
30.407 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.408 - * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
30.409 - * @return the same type, except with the selected parameter(s) appended
30.410 - * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
30.411 - * or if the resulting method type would have more than 255 parameter slots
30.412 - * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
30.413 - */
30.414 - public MethodType appendParameterTypes(Class<?>... ptypesToInsert) {
30.415 - return insertParameterTypes(parameterCount(), ptypesToInsert);
30.416 - }
30.417 -
30.418 - /**
30.419 - * Finds or creates a method type with additional parameter types.
30.420 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.421 - * @param num the position (zero-based) of the inserted parameter type(s)
30.422 - * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
30.423 - * @return the same type, except with the selected parameter(s) inserted
30.424 - * @throws IndexOutOfBoundsException if {@code num} is negative or greater than {@code parameterCount()}
30.425 - * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
30.426 - * or if the resulting method type would have more than 255 parameter slots
30.427 - * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
30.428 - */
30.429 - public MethodType insertParameterTypes(int num, List<Class<?>> ptypesToInsert) {
30.430 - return insertParameterTypes(num, listToArray(ptypesToInsert));
30.431 - }
30.432 -
30.433 - /**
30.434 - * Finds or creates a method type with additional parameter types.
30.435 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.436 - * @param ptypesToInsert zero or more new parameter types to insert after the end of the parameter list
30.437 - * @return the same type, except with the selected parameter(s) appended
30.438 - * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
30.439 - * or if the resulting method type would have more than 255 parameter slots
30.440 - * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
30.441 - */
30.442 - public MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) {
30.443 - return insertParameterTypes(parameterCount(), ptypesToInsert);
30.444 - }
30.445 -
30.446 - /**
30.447 - * Finds or creates a method type with modified parameter types.
30.448 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.449 - * @param start the position (zero-based) of the first replaced parameter type(s)
30.450 - * @param end the position (zero-based) after the last replaced parameter type(s)
30.451 - * @param ptypesToInsert zero or more new parameter types to insert into the parameter list
30.452 - * @return the same type, except with the selected parameter(s) replaced
30.453 - * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
30.454 - * or if {@code end} is negative or greater than {@code parameterCount()}
30.455 - * or if {@code start} is greater than {@code end}
30.456 - * @throws IllegalArgumentException if any element of {@code ptypesToInsert} is {@code void.class}
30.457 - * or if the resulting method type would have more than 255 parameter slots
30.458 - * @throws NullPointerException if {@code ptypesToInsert} or any of its elements is null
30.459 - */
30.460 - /*non-public*/ MethodType replaceParameterTypes(int start, int end, Class<?>... ptypesToInsert) {
30.461 - if (start == end)
30.462 - return insertParameterTypes(start, ptypesToInsert);
30.463 - int len = ptypes.length;
30.464 - if (!(0 <= start && start <= end && end <= len))
30.465 - throw newIndexOutOfBoundsException("start="+start+" end="+end);
30.466 - int ilen = ptypesToInsert.length;
30.467 - if (ilen == 0)
30.468 - return dropParameterTypes(start, end);
30.469 - return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
30.470 - }
30.471 -
30.472 - /**
30.473 - * Finds or creates a method type with some parameter types omitted.
30.474 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.475 - * @param start the index (zero-based) of the first parameter type to remove
30.476 - * @param end the index (greater than {@code start}) of the first parameter type after not to remove
30.477 - * @return the same type, except with the selected parameter(s) removed
30.478 - * @throws IndexOutOfBoundsException if {@code start} is negative or greater than {@code parameterCount()}
30.479 - * or if {@code end} is negative or greater than {@code parameterCount()}
30.480 - * or if {@code start} is greater than {@code end}
30.481 - */
30.482 - public MethodType dropParameterTypes(int start, int end) {
30.483 - int len = ptypes.length;
30.484 - if (!(0 <= start && start <= end && end <= len))
30.485 - throw newIndexOutOfBoundsException("start="+start+" end="+end);
30.486 - if (start == end) return this;
30.487 - Class<?>[] nptypes;
30.488 - if (start == 0) {
30.489 - if (end == len) {
30.490 - // drop all parameters
30.491 - nptypes = NO_PTYPES;
30.492 - } else {
30.493 - // drop initial parameter(s)
30.494 - nptypes = Arrays.copyOfRange(ptypes, end, len);
30.495 - }
30.496 - } else {
30.497 - if (end == len) {
30.498 - // drop trailing parameter(s)
30.499 - nptypes = Arrays.copyOfRange(ptypes, 0, start);
30.500 - } else {
30.501 - int tail = len - end;
30.502 - nptypes = Arrays.copyOfRange(ptypes, 0, start + tail);
30.503 - System.arraycopy(ptypes, end, nptypes, start, tail);
30.504 - }
30.505 - }
30.506 - return makeImpl(rtype, nptypes, true);
30.507 - }
30.508 -
30.509 - /**
30.510 - * Finds or creates a method type with a different return type.
30.511 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.512 - * @param nrtype a return parameter type to replace the old one with
30.513 - * @return the same type, except with the return type change
30.514 - * @throws NullPointerException if {@code nrtype} is null
30.515 - */
30.516 - public MethodType changeReturnType(Class<?> nrtype) {
30.517 - if (returnType() == nrtype) return this;
30.518 - return makeImpl(nrtype, ptypes, true);
30.519 - }
30.520 -
30.521 - /**
30.522 - * Reports if this type contains a primitive argument or return value.
30.523 - * The return type {@code void} counts as a primitive.
30.524 - * @return true if any of the types are primitives
30.525 - */
30.526 - public boolean hasPrimitives() {
30.527 - return form.hasPrimitives();
30.528 - }
30.529 -
30.530 - /**
30.531 - * Reports if this type contains a wrapper argument or return value.
30.532 - * Wrappers are types which box primitive values, such as {@link Integer}.
30.533 - * The reference type {@code java.lang.Void} counts as a wrapper,
30.534 - * if it occurs as a return type.
30.535 - * @return true if any of the types are wrappers
30.536 - */
30.537 - public boolean hasWrappers() {
30.538 - return unwrap() != this;
30.539 - }
30.540 -
30.541 - /**
30.542 - * Erases all reference types to {@code Object}.
30.543 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.544 - * All primitive types (including {@code void}) will remain unchanged.
30.545 - * @return a version of the original type with all reference types replaced
30.546 - */
30.547 - public MethodType erase() {
30.548 - return form.erasedType();
30.549 - }
30.550 -
30.551 - /**
30.552 - * Erases all reference types to {@code Object}, and all subword types to {@code int}.
30.553 - * This is the reduced type polymorphism used by private methods
30.554 - * such as {@link MethodHandle#invokeBasic invokeBasic}.
30.555 - * @return a version of the original type with all reference and subword types replaced
30.556 - */
30.557 - /*non-public*/ MethodType basicType() {
30.558 - return form.basicType();
30.559 - }
30.560 -
30.561 - /**
30.562 - * @return a version of the original type with MethodHandle prepended as the first argument
30.563 - */
30.564 - /*non-public*/ MethodType invokerType() {
30.565 - return insertParameterTypes(0, MethodHandle.class);
30.566 - }
30.567 -
30.568 - /**
30.569 - * Converts all types, both reference and primitive, to {@code Object}.
30.570 - * Convenience method for {@link #genericMethodType(int) genericMethodType}.
30.571 - * The expression {@code type.wrap().erase()} produces the same value
30.572 - * as {@code type.generic()}.
30.573 - * @return a version of the original type with all types replaced
30.574 - */
30.575 - public MethodType generic() {
30.576 - return genericMethodType(parameterCount());
30.577 - }
30.578 -
30.579 - /**
30.580 - * Converts all primitive types to their corresponding wrapper types.
30.581 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.582 - * All reference types (including wrapper types) will remain unchanged.
30.583 - * A {@code void} return type is changed to the type {@code java.lang.Void}.
30.584 - * The expression {@code type.wrap().erase()} produces the same value
30.585 - * as {@code type.generic()}.
30.586 - * @return a version of the original type with all primitive types replaced
30.587 - */
30.588 - public MethodType wrap() {
30.589 - return hasPrimitives() ? wrapWithPrims(this) : this;
30.590 - }
30.591 -
30.592 - /**
30.593 - * Converts all wrapper types to their corresponding primitive types.
30.594 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.595 - * All primitive types (including {@code void}) will remain unchanged.
30.596 - * A return type of {@code java.lang.Void} is changed to {@code void}.
30.597 - * @return a version of the original type with all wrapper types replaced
30.598 - */
30.599 - public MethodType unwrap() {
30.600 - MethodType noprims = !hasPrimitives() ? this : wrapWithPrims(this);
30.601 - return unwrapWithNoPrims(noprims);
30.602 - }
30.603 -
30.604 - private static MethodType wrapWithPrims(MethodType pt) {
30.605 - assert(pt.hasPrimitives());
30.606 - MethodType wt = pt.wrapAlt;
30.607 - if (wt == null) {
30.608 - // fill in lazily
30.609 - wt = MethodTypeForm.canonicalize(pt, MethodTypeForm.WRAP, MethodTypeForm.WRAP);
30.610 - assert(wt != null);
30.611 - pt.wrapAlt = wt;
30.612 - }
30.613 - return wt;
30.614 - }
30.615 -
30.616 - private static MethodType unwrapWithNoPrims(MethodType wt) {
30.617 - assert(!wt.hasPrimitives());
30.618 - MethodType uwt = wt.wrapAlt;
30.619 - if (uwt == null) {
30.620 - // fill in lazily
30.621 - uwt = MethodTypeForm.canonicalize(wt, MethodTypeForm.UNWRAP, MethodTypeForm.UNWRAP);
30.622 - if (uwt == null)
30.623 - uwt = wt; // type has no wrappers or prims at all
30.624 - wt.wrapAlt = uwt;
30.625 - }
30.626 - return uwt;
30.627 - }
30.628 -
30.629 - /**
30.630 - * Returns the parameter type at the specified index, within this method type.
30.631 - * @param num the index (zero-based) of the desired parameter type
30.632 - * @return the selected parameter type
30.633 - * @throws IndexOutOfBoundsException if {@code num} is not a valid index into {@code parameterArray()}
30.634 - */
30.635 - public Class<?> parameterType(int num) {
30.636 - return ptypes[num];
30.637 - }
30.638 - /**
30.639 - * Returns the number of parameter types in this method type.
30.640 - * @return the number of parameter types
30.641 - */
30.642 - public int parameterCount() {
30.643 - return ptypes.length;
30.644 - }
30.645 - /**
30.646 - * Returns the return type of this method type.
30.647 - * @return the return type
30.648 - */
30.649 - public Class<?> returnType() {
30.650 - return rtype;
30.651 - }
30.652 -
30.653 - /**
30.654 - * Presents the parameter types as a list (a convenience method).
30.655 - * The list will be immutable.
30.656 - * @return the parameter types (as an immutable list)
30.657 - */
30.658 - public List<Class<?>> parameterList() {
30.659 - return Collections.unmodifiableList(Arrays.asList(ptypes));
30.660 - }
30.661 -
30.662 - /*non-public*/ Class<?> lastParameterType() {
30.663 - int len = ptypes.length;
30.664 - return len == 0 ? void.class : ptypes[len-1];
30.665 - }
30.666 -
30.667 - /**
30.668 - * Presents the parameter types as an array (a convenience method).
30.669 - * Changes to the array will not result in changes to the type.
30.670 - * @return the parameter types (as a fresh copy if necessary)
30.671 - */
30.672 - public Class<?>[] parameterArray() {
30.673 - return ptypes.clone();
30.674 - }
30.675 -
30.676 - /**
30.677 - * Compares the specified object with this type for equality.
30.678 - * That is, it returns <tt>true</tt> if and only if the specified object
30.679 - * is also a method type with exactly the same parameters and return type.
30.680 - * @param x object to compare
30.681 - * @see Object#equals(Object)
30.682 - */
30.683 - @Override
30.684 - public boolean equals(Object x) {
30.685 - return this == x || x instanceof MethodType && equals((MethodType)x);
30.686 - }
30.687 -
30.688 - private boolean equals(MethodType that) {
30.689 - return this.rtype == that.rtype
30.690 - && Arrays.equals(this.ptypes, that.ptypes);
30.691 - }
30.692 -
30.693 - /**
30.694 - * Returns the hash code value for this method type.
30.695 - * It is defined to be the same as the hashcode of a List
30.696 - * whose elements are the return type followed by the
30.697 - * parameter types.
30.698 - * @return the hash code value for this method type
30.699 - * @see Object#hashCode()
30.700 - * @see #equals(Object)
30.701 - * @see List#hashCode()
30.702 - */
30.703 - @Override
30.704 - public int hashCode() {
30.705 - int hashCode = 31 + rtype.hashCode();
30.706 - for (Class<?> ptype : ptypes)
30.707 - hashCode = 31*hashCode + ptype.hashCode();
30.708 - return hashCode;
30.709 - }
30.710 -
30.711 - /**
30.712 - * Returns a string representation of the method type,
30.713 - * of the form {@code "(PT0,PT1...)RT"}.
30.714 - * The string representation of a method type is a
30.715 - * parenthesis enclosed, comma separated list of type names,
30.716 - * followed immediately by the return type.
30.717 - * <p>
30.718 - * Each type is represented by its
30.719 - * {@link java.lang.Class#getSimpleName simple name}.
30.720 - */
30.721 - @Override
30.722 - public String toString() {
30.723 - StringBuilder sb = new StringBuilder();
30.724 - sb.append("(");
30.725 - for (int i = 0; i < ptypes.length; i++) {
30.726 - if (i > 0) sb.append(",");
30.727 - sb.append(ptypes[i].getSimpleName());
30.728 - }
30.729 - sb.append(")");
30.730 - sb.append(rtype.getSimpleName());
30.731 - return sb.toString();
30.732 - }
30.733 -
30.734 -
30.735 - /*non-public*/
30.736 - boolean isViewableAs(MethodType newType) {
30.737 - if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
30.738 - return false;
30.739 - int argc = parameterCount();
30.740 - if (argc != newType.parameterCount())
30.741 - return false;
30.742 - for (int i = 0; i < argc; i++) {
30.743 - if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
30.744 - return false;
30.745 - }
30.746 - return true;
30.747 - }
30.748 - /*non-public*/
30.749 - boolean isCastableTo(MethodType newType) {
30.750 - int argc = parameterCount();
30.751 - if (argc != newType.parameterCount())
30.752 - return false;
30.753 - return true;
30.754 - }
30.755 - /*non-public*/
30.756 - boolean isConvertibleTo(MethodType newType) {
30.757 - if (!canConvert(returnType(), newType.returnType()))
30.758 - return false;
30.759 - int argc = parameterCount();
30.760 - if (argc != newType.parameterCount())
30.761 - return false;
30.762 - for (int i = 0; i < argc; i++) {
30.763 - if (!canConvert(newType.parameterType(i), parameterType(i)))
30.764 - return false;
30.765 - }
30.766 - return true;
30.767 - }
30.768 - /*non-public*/
30.769 - static boolean canConvert(Class<?> src, Class<?> dst) {
30.770 - // short-circuit a few cases:
30.771 - if (src == dst || dst == Object.class) return true;
30.772 - // the remainder of this logic is documented in MethodHandle.asType
30.773 - if (src.isPrimitive()) {
30.774 - // can force void to an explicit null, a la reflect.Method.invoke
30.775 - // can also force void to a primitive zero, by analogy
30.776 - if (src == void.class) return true; //or !dst.isPrimitive()?
30.777 - Wrapper sw = Wrapper.forPrimitiveType(src);
30.778 - if (dst.isPrimitive()) {
30.779 - // P->P must widen
30.780 - return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
30.781 - } else {
30.782 - // P->R must box and widen
30.783 - return dst.isAssignableFrom(sw.wrapperType());
30.784 - }
30.785 - } else if (dst.isPrimitive()) {
30.786 - // any value can be dropped
30.787 - if (dst == void.class) return true;
30.788 - Wrapper dw = Wrapper.forPrimitiveType(dst);
30.789 - // R->P must be able to unbox (from a dynamically chosen type) and widen
30.790 - // For example:
30.791 - // Byte/Number/Comparable/Object -> dw:Byte -> byte.
30.792 - // Character/Comparable/Object -> dw:Character -> char
30.793 - // Boolean/Comparable/Object -> dw:Boolean -> boolean
30.794 - // This means that dw must be cast-compatible with src.
30.795 - if (src.isAssignableFrom(dw.wrapperType())) {
30.796 - return true;
30.797 - }
30.798 - // The above does not work if the source reference is strongly typed
30.799 - // to a wrapper whose primitive must be widened. For example:
30.800 - // Byte -> unbox:byte -> short/int/long/float/double
30.801 - // Character -> unbox:char -> int/long/float/double
30.802 - if (Wrapper.isWrapperType(src) &&
30.803 - dw.isConvertibleFrom(Wrapper.forWrapperType(src))) {
30.804 - // can unbox from src and then widen to dst
30.805 - return true;
30.806 - }
30.807 - // We have already covered cases which arise due to runtime unboxing
30.808 - // of a reference type which covers several wrapper types:
30.809 - // Object -> cast:Integer -> unbox:int -> long/float/double
30.810 - // Serializable -> cast:Byte -> unbox:byte -> byte/short/int/long/float/double
30.811 - // An marginal case is Number -> dw:Character -> char, which would be OK if there were a
30.812 - // subclass of Number which wraps a value that can convert to char.
30.813 - // Since there is none, we don't need an extra check here to cover char or boolean.
30.814 - return false;
30.815 - } else {
30.816 - // R->R always works, since null is always valid dynamically
30.817 - return true;
30.818 - }
30.819 - }
30.820 -
30.821 - /// Queries which have to do with the bytecode architecture
30.822 -
30.823 - /** Reports the number of JVM stack slots required to invoke a method
30.824 - * of this type. Note that (for historical reasons) the JVM requires
30.825 - * a second stack slot to pass long and double arguments.
30.826 - * So this method returns {@link #parameterCount() parameterCount} plus the
30.827 - * number of long and double parameters (if any).
30.828 - * <p>
30.829 - * This method is included for the benefit of applications that must
30.830 - * generate bytecodes that process method handles and invokedynamic.
30.831 - * @return the number of JVM stack slots for this type's parameters
30.832 - */
30.833 - /*non-public*/ int parameterSlotCount() {
30.834 - return form.parameterSlotCount();
30.835 - }
30.836 -
30.837 - /*non-public*/ Invokers invokers() {
30.838 - Invokers inv = invokers;
30.839 - if (inv != null) return inv;
30.840 - invokers = inv = new Invokers(this);
30.841 - return inv;
30.842 - }
30.843 -
30.844 - /** Reports the number of JVM stack slots which carry all parameters including and after
30.845 - * the given position, which must be in the range of 0 to
30.846 - * {@code parameterCount} inclusive. Successive parameters are
30.847 - * more shallowly stacked, and parameters are indexed in the bytecodes
30.848 - * according to their trailing edge. Thus, to obtain the depth
30.849 - * in the outgoing call stack of parameter {@code N}, obtain
30.850 - * the {@code parameterSlotDepth} of its trailing edge
30.851 - * at position {@code N+1}.
30.852 - * <p>
30.853 - * Parameters of type {@code long} and {@code double} occupy
30.854 - * two stack slots (for historical reasons) and all others occupy one.
30.855 - * Therefore, the number returned is the number of arguments
30.856 - * <em>including</em> and <em>after</em> the given parameter,
30.857 - * <em>plus</em> the number of long or double arguments
30.858 - * at or after after the argument for the given parameter.
30.859 - * <p>
30.860 - * This method is included for the benefit of applications that must
30.861 - * generate bytecodes that process method handles and invokedynamic.
30.862 - * @param num an index (zero-based, inclusive) within the parameter types
30.863 - * @return the index of the (shallowest) JVM stack slot transmitting the
30.864 - * given parameter
30.865 - * @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
30.866 - */
30.867 - /*non-public*/ int parameterSlotDepth(int num) {
30.868 - if (num < 0 || num > ptypes.length)
30.869 - parameterType(num); // force a range check
30.870 - return form.parameterToArgSlot(num-1);
30.871 - }
30.872 -
30.873 - /** Reports the number of JVM stack slots required to receive a return value
30.874 - * from a method of this type.
30.875 - * If the {@link #returnType() return type} is void, it will be zero,
30.876 - * else if the return type is long or double, it will be two, else one.
30.877 - * <p>
30.878 - * This method is included for the benefit of applications that must
30.879 - * generate bytecodes that process method handles and invokedynamic.
30.880 - * @return the number of JVM stack slots (0, 1, or 2) for this type's return value
30.881 - * Will be removed for PFD.
30.882 - */
30.883 - /*non-public*/ int returnSlotCount() {
30.884 - return form.returnSlotCount();
30.885 - }
30.886 -
30.887 - /**
30.888 - * Finds or creates an instance of a method type, given the spelling of its bytecode descriptor.
30.889 - * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
30.890 - * Any class or interface name embedded in the descriptor string
30.891 - * will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
30.892 - * on the given loader (or if it is null, on the system class loader).
30.893 - * <p>
30.894 - * Note that it is possible to encounter method types which cannot be
30.895 - * constructed by this method, because their component types are
30.896 - * not all reachable from a common class loader.
30.897 - * <p>
30.898 - * This method is included for the benefit of applications that must
30.899 - * generate bytecodes that process method handles and {@code invokedynamic}.
30.900 - * @param descriptor a bytecode-level type descriptor string "(T...)T"
30.901 - * @param loader the class loader in which to look up the types
30.902 - * @return a method type matching the bytecode-level type descriptor
30.903 - * @throws NullPointerException if the string is null
30.904 - * @throws IllegalArgumentException if the string is not well-formed
30.905 - * @throws TypeNotPresentException if a named type cannot be found
30.906 - */
30.907 - public static MethodType fromMethodDescriptorString(String descriptor, ClassLoader loader)
30.908 - throws IllegalArgumentException, TypeNotPresentException
30.909 - {
30.910 - if (!descriptor.startsWith("(") || // also generates NPE if needed
30.911 - descriptor.indexOf(')') < 0 ||
30.912 - descriptor.indexOf('.') >= 0)
30.913 - throw new IllegalArgumentException("not a method descriptor: "+descriptor);
30.914 - List<Class<?>> types = BytecodeDescriptor.parseMethod(descriptor, loader);
30.915 - Class<?> rtype = types.remove(types.size() - 1);
30.916 - checkSlotCount(types.size());
30.917 - Class<?>[] ptypes = listToArray(types);
30.918 - return makeImpl(rtype, ptypes, true);
30.919 - }
30.920 -
30.921 - /**
30.922 - * Produces a bytecode descriptor representation of the method type.
30.923 - * <p>
30.924 - * Note that this is not a strict inverse of {@link #fromMethodDescriptorString fromMethodDescriptorString}.
30.925 - * Two distinct classes which share a common name but have different class loaders
30.926 - * will appear identical when viewed within descriptor strings.
30.927 - * <p>
30.928 - * This method is included for the benefit of applications that must
30.929 - * generate bytecodes that process method handles and {@code invokedynamic}.
30.930 - * {@link #fromMethodDescriptorString(java.lang.String, java.lang.ClassLoader) fromMethodDescriptorString},
30.931 - * because the latter requires a suitable class loader argument.
30.932 - * @return the bytecode type descriptor representation
30.933 - */
30.934 - public String toMethodDescriptorString() {
30.935 - String desc = methodDescriptor;
30.936 - if (desc == null) {
30.937 - desc = BytecodeDescriptor.unparse(this);
30.938 - methodDescriptor = desc;
30.939 - }
30.940 - return desc;
30.941 - }
30.942 -
30.943 - /*non-public*/ static String toFieldDescriptorString(Class<?> cls) {
30.944 - return BytecodeDescriptor.unparse(cls);
30.945 - }
30.946 -
30.947 - /// Serialization.
30.948 -
30.949 - /**
30.950 - * There are no serializable fields for {@code MethodType}.
30.951 - */
30.952 - private static final java.io.ObjectStreamField[] serialPersistentFields = { };
30.953 -
30.954 -// /**
30.955 -// * Save the {@code MethodType} instance to a stream.
30.956 -// *
30.957 -// * @serialData
30.958 -// * For portability, the serialized format does not refer to named fields.
30.959 -// * Instead, the return type and parameter type arrays are written directly
30.960 -// * from the {@code writeObject} method, using two calls to {@code s.writeObject}
30.961 -// * as follows:
30.962 -// * <blockquote><pre>{@code
30.963 -//s.writeObject(this.returnType());
30.964 -//s.writeObject(this.parameterArray());
30.965 -// * }</pre></blockquote>
30.966 -// * <p>
30.967 -// * The deserialized field values are checked as if they were
30.968 -// * provided to the factory method {@link #methodType(Class,Class[]) methodType}.
30.969 -// * For example, null values, or {@code void} parameter types,
30.970 -// * will lead to exceptions during deserialization.
30.971 -// * @param s the stream to write the object to
30.972 -// * @throws java.io.IOException if there is a problem writing the object
30.973 -// */
30.974 -// private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
30.975 -// s.defaultWriteObject(); // requires serialPersistentFields to be an empty array
30.976 -// s.writeObject(returnType());
30.977 -// s.writeObject(parameterArray());
30.978 -// }
30.979 -//
30.980 -// /**
30.981 -// * Reconstitute the {@code MethodType} instance from a stream (that is,
30.982 -// * deserialize it).
30.983 -// * This instance is a scratch object with bogus final fields.
30.984 -// * It provides the parameters to the factory method called by
30.985 -// * {@link #readResolve readResolve}.
30.986 -// * After that call it is discarded.
30.987 -// * @param s the stream to read the object from
30.988 -// * @throws java.io.IOException if there is a problem reading the object
30.989 -// * @throws ClassNotFoundException if one of the component classes cannot be resolved
30.990 -// * @see #MethodType()
30.991 -// * @see #readResolve
30.992 -// * @see #writeObject
30.993 -// */
30.994 -// private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
30.995 -// s.defaultReadObject(); // requires serialPersistentFields to be an empty array
30.996 -//
30.997 -// Class<?> returnType = (Class<?>) s.readObject();
30.998 -// Class<?>[] parameterArray = (Class<?>[]) s.readObject();
30.999 -//
30.1000 -// // Probably this object will never escape, but let's check
30.1001 -// // the field values now, just to be sure.
30.1002 -// checkRtype(returnType);
30.1003 -// checkPtypes(parameterArray);
30.1004 -//
30.1005 -// parameterArray = parameterArray.clone(); // make sure it is unshared
30.1006 -// MethodType_init(returnType, parameterArray);
30.1007 -// }
30.1008 -
30.1009 - /**
30.1010 - * For serialization only.
30.1011 - * Sets the final fields to null, pending {@code Unsafe.putObject}.
30.1012 - */
30.1013 - private MethodType() {
30.1014 - this.rtype = null;
30.1015 - this.ptypes = null;
30.1016 - }
30.1017 -// private void MethodType_init(Class<?> rtype, Class<?>[] ptypes) {
30.1018 -// // In order to communicate these values to readResolve, we must
30.1019 -// // store them into the implementation-specific final fields.
30.1020 -// checkRtype(rtype);
30.1021 -// checkPtypes(ptypes);
30.1022 -// UNSAFE.putObject(this, rtypeOffset, rtype);
30.1023 -// UNSAFE.putObject(this, ptypesOffset, ptypes);
30.1024 -// }
30.1025 -
30.1026 - // Support for resetting final fields while deserializing
30.1027 -// private static final long rtypeOffset, ptypesOffset;
30.1028 -// static {
30.1029 -// try {
30.1030 -// rtypeOffset = UNSAFE.objectFieldOffset
30.1031 -// (MethodType.class.getDeclaredField("rtype"));
30.1032 -// ptypesOffset = UNSAFE.objectFieldOffset
30.1033 -// (MethodType.class.getDeclaredField("ptypes"));
30.1034 -// } catch (Exception ex) {
30.1035 -// throw new Error(ex);
30.1036 -// }
30.1037 -// }
30.1038 -
30.1039 - /**
30.1040 - * Resolves and initializes a {@code MethodType} object
30.1041 - * after serialization.
30.1042 - * @return the fully initialized {@code MethodType} object
30.1043 - */
30.1044 - private Object readResolve() {
30.1045 - // Do not use a trusted path for deserialization:
30.1046 - //return makeImpl(rtype, ptypes, true);
30.1047 - // Verify all operands, and make sure ptypes is unshared:
30.1048 - return methodType(rtype, ptypes);
30.1049 - }
30.1050 -
30.1051 - /**
30.1052 - * Simple implementation of weak concurrent intern set.
30.1053 - *
30.1054 - * @param <T> interned type
30.1055 - */
30.1056 - private static class ConcurrentWeakInternSet<T> {
30.1057 -
30.1058 - private final ConcurrentMap<WeakEntry<T>, WeakEntry<T>> map;
30.1059 - private final ReferenceQueue<T> stale;
30.1060 -
30.1061 - public ConcurrentWeakInternSet() {
30.1062 - this.map = new ConcurrentHashMap<>();
30.1063 - this.stale = new ReferenceQueue<>();
30.1064 - }
30.1065 -
30.1066 - /**
30.1067 - * Get the existing interned element.
30.1068 - * This method returns null if no element is interned.
30.1069 - *
30.1070 - * @param elem element to look up
30.1071 - * @return the interned element
30.1072 - */
30.1073 - public T get(T elem) {
30.1074 - if (elem == null) throw new NullPointerException();
30.1075 - expungeStaleElements();
30.1076 -
30.1077 - WeakEntry<T> value = map.get(new WeakEntry<>(elem));
30.1078 - if (value != null) {
30.1079 - T res = value.get();
30.1080 - if (res != null) {
30.1081 - return res;
30.1082 - }
30.1083 - }
30.1084 - return null;
30.1085 - }
30.1086 -
30.1087 - /**
30.1088 - * Interns the element.
30.1089 - * Always returns non-null element, matching the one in the intern set.
30.1090 - * Under the race against another add(), it can return <i>different</i>
30.1091 - * element, if another thread beats us to interning it.
30.1092 - *
30.1093 - * @param elem element to add
30.1094 - * @return element that was actually added
30.1095 - */
30.1096 - public T add(T elem) {
30.1097 - if (elem == null) throw new NullPointerException();
30.1098 -
30.1099 - // Playing double race here, and so spinloop is required.
30.1100 - // First race is with two concurrent updaters.
30.1101 - // Second race is with GC purging weak ref under our feet.
30.1102 - // Hopefully, we almost always end up with a single pass.
30.1103 - T interned;
30.1104 - WeakEntry<T> e = new WeakEntry<>(elem, stale);
30.1105 - do {
30.1106 - expungeStaleElements();
30.1107 - WeakEntry<T> exist = map.putIfAbsent(e, e);
30.1108 - interned = (exist == null) ? elem : exist.get();
30.1109 - } while (interned == null);
30.1110 - return interned;
30.1111 - }
30.1112 -
30.1113 - private void expungeStaleElements() {
30.1114 - Reference<? extends T> reference;
30.1115 - while ((reference = stale.poll()) != null) {
30.1116 - map.remove(reference);
30.1117 - }
30.1118 - }
30.1119 -
30.1120 - private static class WeakEntry<T> extends WeakReference<T> {
30.1121 -
30.1122 - public final int hashcode;
30.1123 -
30.1124 - public WeakEntry(T key, ReferenceQueue<T> queue) {
30.1125 - super(key, queue);
30.1126 - hashcode = key.hashCode();
30.1127 - }
30.1128 -
30.1129 - public WeakEntry(T key) {
30.1130 - super(key);
30.1131 - hashcode = key.hashCode();
30.1132 - }
30.1133 -
30.1134 - @Override
30.1135 - public boolean equals(Object obj) {
30.1136 - if (obj instanceof WeakEntry) {
30.1137 - Object that = ((WeakEntry) obj).get();
30.1138 - Object mine = get();
30.1139 - return (that == null || mine == null) ? (this == obj) : mine.equals(that);
30.1140 - }
30.1141 - return false;
30.1142 - }
30.1143 -
30.1144 - @Override
30.1145 - public int hashCode() {
30.1146 - return hashcode;
30.1147 - }
30.1148 -
30.1149 - }
30.1150 - }
30.1151 -
30.1152 -}
31.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodTypeForm.java Sun Aug 17 20:09:05 2014 +0200
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,388 +0,0 @@
31.4 -/*
31.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
31.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 - *
31.8 - * This code is free software; you can redistribute it and/or modify it
31.9 - * under the terms of the GNU General Public License version 2 only, as
31.10 - * published by the Free Software Foundation. Oracle designates this
31.11 - * particular file as subject to the "Classpath" exception as provided
31.12 - * by Oracle in the LICENSE file that accompanied this code.
31.13 - *
31.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 - * version 2 for more details (a copy is included in the LICENSE file that
31.18 - * accompanied this code).
31.19 - *
31.20 - * You should have received a copy of the GNU General Public License version
31.21 - * 2 along with this work; if not, write to the Free Software Foundation,
31.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 - *
31.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
31.25 - * or visit www.oracle.com if you need additional information or have any
31.26 - * questions.
31.27 - */
31.28 -
31.29 -package java.lang.invoke;
31.30 -
31.31 -import sun.invoke.util.Wrapper;
31.32 -import static java.lang.invoke.MethodHandleStatics.*;
31.33 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
31.34 - import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
31.35 -
31.36 -/**
31.37 - * Shared information for a group of method types, which differ
31.38 - * only by reference types, and therefore share a common erasure
31.39 - * and wrapping.
31.40 - * <p>
31.41 - * For an empirical discussion of the structure of method types,
31.42 - * see <a href="http://groups.google.com/group/jvm-languages/browse_thread/thread/ac9308ae74da9b7e/">
31.43 - * the thread "Avoiding Boxing" on jvm-languages</a>.
31.44 - * There are approximately 2000 distinct erased method types in the JDK.
31.45 - * There are a little over 10 times that number of unerased types.
31.46 - * No more than half of these are likely to be loaded at once.
31.47 - * @author John Rose
31.48 - */
31.49 -final class MethodTypeForm {
31.50 - final int[] argToSlotTable, slotToArgTable;
31.51 - final long argCounts; // packed slot & value counts
31.52 - final long primCounts; // packed prim & double counts
31.53 - final int vmslots; // total number of parameter slots
31.54 - final MethodType erasedType; // the canonical erasure
31.55 - final MethodType basicType; // the canonical erasure, with primitives simplified
31.56 -
31.57 - // Cached adapter information:
31.58 - @Stable String typeString; // argument type signature characters
31.59 - @Stable MethodHandle genericInvoker; // JVM hook for inexact invoke
31.60 - @Stable MethodHandle basicInvoker; // cached instance of MH.invokeBasic
31.61 - @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction
31.62 -
31.63 - // Cached lambda form information, for basic types only:
31.64 - final @Stable LambdaForm[] lambdaForms;
31.65 - // Indexes into lambdaForms:
31.66 - static final int
31.67 - LF_INVVIRTUAL = 0, // DMH invokeVirtual
31.68 - LF_INVSTATIC = 1,
31.69 - LF_INVSPECIAL = 2,
31.70 - LF_NEWINVSPECIAL = 3,
31.71 - LF_INVINTERFACE = 4,
31.72 - LF_INVSTATIC_INIT = 5, // DMH invokeStatic with <clinit> barrier
31.73 - LF_INTERPRET = 6, // LF interpreter
31.74 - LF_COUNTER = 7, // CMH wrapper
31.75 - LF_REINVOKE = 8, // other wrapper
31.76 - LF_EX_LINKER = 9, // invokeExact_MT
31.77 - LF_EX_INVOKER = 10, // invokeExact MH
31.78 - LF_GEN_LINKER = 11,
31.79 - LF_GEN_INVOKER = 12,
31.80 - LF_CS_LINKER = 13, // linkToCallSite_CS
31.81 - LF_MH_LINKER = 14, // linkToCallSite_MH
31.82 - LF_LIMIT = 15;
31.83 -
31.84 - public MethodType erasedType() {
31.85 - return erasedType;
31.86 - }
31.87 -
31.88 - public MethodType basicType() {
31.89 - return basicType;
31.90 - }
31.91 -
31.92 - public LambdaForm cachedLambdaForm(int which) {
31.93 - return lambdaForms[which];
31.94 - }
31.95 -
31.96 - public LambdaForm setCachedLambdaForm(int which, LambdaForm form) {
31.97 - // Should we perform some sort of CAS, to avoid racy duplication?
31.98 - return lambdaForms[which] = form;
31.99 - }
31.100 -
31.101 - public MethodHandle basicInvoker() {
31.102 - assert(erasedType == basicType) : "erasedType: " + erasedType + " != basicType: " + basicType; // primitives must be flattened also
31.103 - MethodHandle invoker = basicInvoker;
31.104 - if (invoker != null) return invoker;
31.105 - invoker = DirectMethodHandle.make(invokeBasicMethod(basicType));
31.106 - basicInvoker = invoker;
31.107 - return invoker;
31.108 - }
31.109 -
31.110 - // This next one is called from LambdaForm.NamedFunction.<init>.
31.111 - /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
31.112 - assert(basicType == basicType.basicType());
31.113 - try {
31.114 - // Do approximately the same as this public API call:
31.115 - // Lookup.findVirtual(MethodHandle.class, name, type);
31.116 - // But bypass access and corner case checks, since we know exactly what we need.
31.117 - return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
31.118 - } catch (ReflectiveOperationException ex) {
31.119 - throw newInternalError("JVM cannot find invoker for "+basicType, ex);
31.120 - }
31.121 - }
31.122 -
31.123 - /**
31.124 - * Build an MTF for a given type, which must have all references erased to Object.
31.125 - * This MTF will stand for that type and all un-erased variations.
31.126 - * Eagerly compute some basic properties of the type, common to all variations.
31.127 - */
31.128 - protected MethodTypeForm(MethodType erasedType) {
31.129 - this.erasedType = erasedType;
31.130 -
31.131 - Class<?>[] ptypes = erasedType.ptypes();
31.132 - int ptypeCount = ptypes.length;
31.133 - int pslotCount = ptypeCount; // temp. estimate
31.134 - int rtypeCount = 1; // temp. estimate
31.135 - int rslotCount = 1; // temp. estimate
31.136 -
31.137 - int[] argToSlotTab = null, slotToArgTab = null;
31.138 -
31.139 - // Walk the argument types, looking for primitives.
31.140 - int pac = 0, lac = 0, prc = 0, lrc = 0;
31.141 - Class<?>[] epts = ptypes;
31.142 - Class<?>[] bpts = epts;
31.143 - for (int i = 0; i < epts.length; i++) {
31.144 - Class<?> pt = epts[i];
31.145 - if (pt != Object.class) {
31.146 - ++pac;
31.147 - Wrapper w = Wrapper.forPrimitiveType(pt);
31.148 - if (w.isDoubleWord()) ++lac;
31.149 - if (w.isSubwordOrInt() && pt != int.class) {
31.150 - if (bpts == epts)
31.151 - bpts = bpts.clone();
31.152 - bpts[i] = int.class;
31.153 - }
31.154 - }
31.155 - }
31.156 - pslotCount += lac; // #slots = #args + #longs
31.157 - Class<?> rt = erasedType.returnType();
31.158 - Class<?> bt = rt;
31.159 - if (rt != Object.class) {
31.160 - ++prc; // even void.class counts as a prim here
31.161 - Wrapper w = Wrapper.forPrimitiveType(rt);
31.162 - if (w.isDoubleWord()) ++lrc;
31.163 - if (w.isSubwordOrInt() && rt != int.class)
31.164 - bt = int.class;
31.165 - // adjust #slots, #args
31.166 - if (rt == void.class)
31.167 - rtypeCount = rslotCount = 0;
31.168 - else
31.169 - rslotCount += lrc;
31.170 - }
31.171 - if (epts == bpts && bt == rt) {
31.172 - this.basicType = erasedType;
31.173 - } else {
31.174 - this.basicType = MethodType.makeImpl(bt, bpts, true);
31.175 - }
31.176 - if (lac != 0) {
31.177 - int slot = ptypeCount + lac;
31.178 - slotToArgTab = new int[slot+1];
31.179 - argToSlotTab = new int[1+ptypeCount];
31.180 - argToSlotTab[0] = slot; // argument "-1" is past end of slots
31.181 - for (int i = 0; i < epts.length; i++) {
31.182 - Class<?> pt = epts[i];
31.183 - Wrapper w = Wrapper.forBasicType(pt);
31.184 - if (w.isDoubleWord()) --slot;
31.185 - --slot;
31.186 - slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
31.187 - argToSlotTab[1+i] = slot;
31.188 - }
31.189 - assert(slot == 0); // filled the table
31.190 - }
31.191 - this.primCounts = pack(lrc, prc, lac, pac);
31.192 - this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
31.193 - if (slotToArgTab == null) {
31.194 - int slot = ptypeCount; // first arg is deepest in stack
31.195 - slotToArgTab = new int[slot+1];
31.196 - argToSlotTab = new int[1+ptypeCount];
31.197 - argToSlotTab[0] = slot; // argument "-1" is past end of slots
31.198 - for (int i = 0; i < ptypeCount; i++) {
31.199 - --slot;
31.200 - slotToArgTab[slot] = i+1; // "+1" see argSlotToParameter note
31.201 - argToSlotTab[1+i] = slot;
31.202 - }
31.203 - }
31.204 - this.argToSlotTable = argToSlotTab;
31.205 - this.slotToArgTable = slotToArgTab;
31.206 -
31.207 - if (pslotCount >= 256) throw newIllegalArgumentException("too many arguments");
31.208 -
31.209 - // send a few bits down to the JVM:
31.210 - this.vmslots = parameterSlotCount();
31.211 -
31.212 - if (basicType == erasedType) {
31.213 - lambdaForms = new LambdaForm[LF_LIMIT];
31.214 - } else {
31.215 - lambdaForms = null; // could be basicType.form().lambdaForms;
31.216 - }
31.217 - }
31.218 -
31.219 - private static long pack(int a, int b, int c, int d) {
31.220 - assert(((a|b|c|d) & ~0xFFFF) == 0);
31.221 - long hw = ((a << 16) | b), lw = ((c << 16) | d);
31.222 - return (hw << 32) | lw;
31.223 - }
31.224 - private static char unpack(long packed, int word) { // word==0 => return a, ==3 => return d
31.225 - assert(word <= 3);
31.226 - return (char)(packed >> ((3-word) * 16));
31.227 - }
31.228 -
31.229 - public int parameterCount() { // # outgoing values
31.230 - return unpack(argCounts, 3);
31.231 - }
31.232 - public int parameterSlotCount() { // # outgoing interpreter slots
31.233 - return unpack(argCounts, 2);
31.234 - }
31.235 - public int returnCount() { // = 0 (V), or 1
31.236 - return unpack(argCounts, 1);
31.237 - }
31.238 - public int returnSlotCount() { // = 0 (V), 2 (J/D), or 1
31.239 - return unpack(argCounts, 0);
31.240 - }
31.241 - public int primitiveParameterCount() {
31.242 - return unpack(primCounts, 3);
31.243 - }
31.244 - public int longPrimitiveParameterCount() {
31.245 - return unpack(primCounts, 2);
31.246 - }
31.247 - public int primitiveReturnCount() { // = 0 (obj), or 1
31.248 - return unpack(primCounts, 1);
31.249 - }
31.250 - public int longPrimitiveReturnCount() { // = 1 (J/D), or 0
31.251 - return unpack(primCounts, 0);
31.252 - }
31.253 - public boolean hasPrimitives() {
31.254 - return primCounts != 0;
31.255 - }
31.256 - public boolean hasNonVoidPrimitives() {
31.257 - if (primCounts == 0) return false;
31.258 - if (primitiveParameterCount() != 0) return true;
31.259 - return (primitiveReturnCount() != 0 && returnCount() != 0);
31.260 - }
31.261 - public boolean hasLongPrimitives() {
31.262 - return (longPrimitiveParameterCount() | longPrimitiveReturnCount()) != 0;
31.263 - }
31.264 - public int parameterToArgSlot(int i) {
31.265 - return argToSlotTable[1+i];
31.266 - }
31.267 - public int argSlotToParameter(int argSlot) {
31.268 - // Note: Empty slots are represented by zero in this table.
31.269 - // Valid arguments slots contain incremented entries, so as to be non-zero.
31.270 - // We return -1 the caller to mean an empty slot.
31.271 - return slotToArgTable[argSlot] - 1;
31.272 - }
31.273 -
31.274 - static MethodTypeForm findForm(MethodType mt) {
31.275 - MethodType erased = canonicalize(mt, ERASE, ERASE);
31.276 - if (erased == null) {
31.277 - // It is already erased. Make a new MethodTypeForm.
31.278 - return new MethodTypeForm(mt);
31.279 - } else {
31.280 - // Share the MethodTypeForm with the erased version.
31.281 - return erased.form();
31.282 - }
31.283 - }
31.284 -
31.285 - /** Codes for {@link #canonicalize(java.lang.Class, int)}.
31.286 - * ERASE means change every reference to {@code Object}.
31.287 - * WRAP means convert primitives (including {@code void} to their
31.288 - * corresponding wrapper types. UNWRAP means the reverse of WRAP.
31.289 - * INTS means convert all non-void primitive types to int or long,
31.290 - * according to size. LONGS means convert all non-void primitives
31.291 - * to long, regardless of size. RAW_RETURN means convert a type
31.292 - * (assumed to be a return type) to int if it is smaller than an int,
31.293 - * or if it is void.
31.294 - */
31.295 - public static final int NO_CHANGE = 0, ERASE = 1, WRAP = 2, UNWRAP = 3, INTS = 4, LONGS = 5, RAW_RETURN = 6;
31.296 -
31.297 - /** Canonicalize the types in the given method type.
31.298 - * If any types change, intern the new type, and return it.
31.299 - * Otherwise return null.
31.300 - */
31.301 - public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
31.302 - Class<?>[] ptypes = mt.ptypes();
31.303 - Class<?>[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
31.304 - Class<?> rtype = mt.returnType();
31.305 - Class<?> rtc = MethodTypeForm.canonicalize(rtype, howRet);
31.306 - if (ptc == null && rtc == null) {
31.307 - // It is already canonical.
31.308 - return null;
31.309 - }
31.310 - // Find the erased version of the method type:
31.311 - if (rtc == null) rtc = rtype;
31.312 - if (ptc == null) ptc = ptypes;
31.313 - return MethodType.makeImpl(rtc, ptc, true);
31.314 - }
31.315 -
31.316 - /** Canonicalize the given return or param type.
31.317 - * Return null if the type is already canonicalized.
31.318 - */
31.319 - static Class<?> canonicalize(Class<?> t, int how) {
31.320 - Class<?> ct;
31.321 - if (t == Object.class) {
31.322 - // no change, ever
31.323 - } else if (!t.isPrimitive()) {
31.324 - switch (how) {
31.325 - case UNWRAP:
31.326 - ct = Wrapper.asPrimitiveType(t);
31.327 - if (ct != t) return ct;
31.328 - break;
31.329 - case RAW_RETURN:
31.330 - case ERASE:
31.331 - return Object.class;
31.332 - }
31.333 - } else if (t == void.class) {
31.334 - // no change, usually
31.335 - switch (how) {
31.336 - case RAW_RETURN:
31.337 - return int.class;
31.338 - case WRAP:
31.339 - return Void.class;
31.340 - }
31.341 - } else {
31.342 - // non-void primitive
31.343 - switch (how) {
31.344 - case WRAP:
31.345 - return Wrapper.asWrapperType(t);
31.346 - case INTS:
31.347 - if (t == int.class || t == long.class)
31.348 - return null; // no change
31.349 - if (t == double.class)
31.350 - return long.class;
31.351 - return int.class;
31.352 - case LONGS:
31.353 - if (t == long.class)
31.354 - return null; // no change
31.355 - return long.class;
31.356 - case RAW_RETURN:
31.357 - if (t == int.class || t == long.class ||
31.358 - t == float.class || t == double.class)
31.359 - return null; // no change
31.360 - // everything else returns as an int
31.361 - return int.class;
31.362 - }
31.363 - }
31.364 - // no change; return null to signify
31.365 - return null;
31.366 - }
31.367 -
31.368 - /** Canonicalize each param type in the given array.
31.369 - * Return null if all types are already canonicalized.
31.370 - */
31.371 - static Class<?>[] canonicalizes(Class<?>[] ts, int how) {
31.372 - Class<?>[] cs = null;
31.373 - for (int imax = ts.length, i = 0; i < imax; i++) {
31.374 - Class<?> c = canonicalize(ts[i], how);
31.375 - if (c == void.class)
31.376 - c = null; // a Void parameter was unwrapped to void; ignore
31.377 - if (c != null) {
31.378 - if (cs == null)
31.379 - cs = ts.clone();
31.380 - cs[i] = c;
31.381 - }
31.382 - }
31.383 - return cs;
31.384 - }
31.385 -
31.386 - @Override
31.387 - public String toString() {
31.388 - return "Form"+erasedType;
31.389 - }
31.390 -
31.391 -}
32.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MutableCallSite.java Sun Aug 17 20:09:05 2014 +0200
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,283 +0,0 @@
32.4 -/*
32.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
32.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
32.7 - *
32.8 - * This code is free software; you can redistribute it and/or modify it
32.9 - * under the terms of the GNU General Public License version 2 only, as
32.10 - * published by the Free Software Foundation. Oracle designates this
32.11 - * particular file as subject to the "Classpath" exception as provided
32.12 - * by Oracle in the LICENSE file that accompanied this code.
32.13 - *
32.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
32.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32.17 - * version 2 for more details (a copy is included in the LICENSE file that
32.18 - * accompanied this code).
32.19 - *
32.20 - * You should have received a copy of the GNU General Public License version
32.21 - * 2 along with this work; if not, write to the Free Software Foundation,
32.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32.23 - *
32.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
32.25 - * or visit www.oracle.com if you need additional information or have any
32.26 - * questions.
32.27 - */
32.28 -
32.29 -package java.lang.invoke;
32.30 -
32.31 -import java.util.concurrent.atomic.AtomicInteger;
32.32 -
32.33 -/**
32.34 - * A {@code MutableCallSite} is a {@link CallSite} whose target variable
32.35 - * behaves like an ordinary field.
32.36 - * An {@code invokedynamic} instruction linked to a {@code MutableCallSite} delegates
32.37 - * all calls to the site's current target.
32.38 - * The {@linkplain CallSite#dynamicInvoker dynamic invoker} of a mutable call site
32.39 - * also delegates each call to the site's current target.
32.40 - * <p>
32.41 - * Here is an example of a mutable call site which introduces a
32.42 - * state variable into a method handle chain.
32.43 - * <!-- JavaDocExamplesTest.testMutableCallSite -->
32.44 - * <blockquote><pre>{@code
32.45 -MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class));
32.46 -MethodHandle MH_name = name.dynamicInvoker();
32.47 -MethodType MT_str1 = MethodType.methodType(String.class);
32.48 -MethodHandle MH_upcase = MethodHandles.lookup()
32.49 - .findVirtual(String.class, "toUpperCase", MT_str1);
32.50 -MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase);
32.51 -name.setTarget(MethodHandles.constant(String.class, "Rocky"));
32.52 -assertEquals("ROCKY", (String) worker1.invokeExact());
32.53 -name.setTarget(MethodHandles.constant(String.class, "Fred"));
32.54 -assertEquals("FRED", (String) worker1.invokeExact());
32.55 -// (mutation can be continued indefinitely)
32.56 - * }</pre></blockquote>
32.57 - * <p>
32.58 - * The same call site may be used in several places at once.
32.59 - * <blockquote><pre>{@code
32.60 -MethodType MT_str2 = MethodType.methodType(String.class, String.class);
32.61 -MethodHandle MH_cat = lookup().findVirtual(String.class,
32.62 - "concat", methodType(String.class, String.class));
32.63 -MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?");
32.64 -MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear);
32.65 -assertEquals("Fred, dear?", (String) worker2.invokeExact());
32.66 -name.setTarget(MethodHandles.constant(String.class, "Wilma"));
32.67 -assertEquals("WILMA", (String) worker1.invokeExact());
32.68 -assertEquals("Wilma, dear?", (String) worker2.invokeExact());
32.69 - * }</pre></blockquote>
32.70 - * <p>
32.71 - * <em>Non-synchronization of target values:</em>
32.72 - * A write to a mutable call site's target does not force other threads
32.73 - * to become aware of the updated value. Threads which do not perform
32.74 - * suitable synchronization actions relative to the updated call site
32.75 - * may cache the old target value and delay their use of the new target
32.76 - * value indefinitely.
32.77 - * (This is a normal consequence of the Java Memory Model as applied
32.78 - * to object fields.)
32.79 - * <p>
32.80 - * The {@link #syncAll syncAll} operation provides a way to force threads
32.81 - * to accept a new target value, even if there is no other synchronization.
32.82 - * <p>
32.83 - * For target values which will be frequently updated, consider using
32.84 - * a {@linkplain VolatileCallSite volatile call site} instead.
32.85 - * @author John Rose, JSR 292 EG
32.86 - */
32.87 -public class MutableCallSite extends CallSite {
32.88 - /**
32.89 - * Creates a blank call site object with the given method type.
32.90 - * The initial target is set to a method handle of the given type
32.91 - * which will throw an {@link IllegalStateException} if called.
32.92 - * <p>
32.93 - * The type of the call site is permanently set to the given type.
32.94 - * <p>
32.95 - * Before this {@code CallSite} object is returned from a bootstrap method,
32.96 - * or invoked in some other manner,
32.97 - * it is usually provided with a more useful target method,
32.98 - * via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
32.99 - * @param type the method type that this call site will have
32.100 - * @throws NullPointerException if the proposed type is null
32.101 - */
32.102 - public MutableCallSite(MethodType type) {
32.103 - super(type);
32.104 - }
32.105 -
32.106 - /**
32.107 - * Creates a call site object with an initial target method handle.
32.108 - * The type of the call site is permanently set to the initial target's type.
32.109 - * @param target the method handle that will be the initial target of the call site
32.110 - * @throws NullPointerException if the proposed target is null
32.111 - */
32.112 - public MutableCallSite(MethodHandle target) {
32.113 - super(target);
32.114 - }
32.115 -
32.116 - /**
32.117 - * Returns the target method of the call site, which behaves
32.118 - * like a normal field of the {@code MutableCallSite}.
32.119 - * <p>
32.120 - * The interactions of {@code getTarget} with memory are the same
32.121 - * as of a read from an ordinary variable, such as an array element or a
32.122 - * non-volatile, non-final field.
32.123 - * <p>
32.124 - * In particular, the current thread may choose to reuse the result
32.125 - * of a previous read of the target from memory, and may fail to see
32.126 - * a recent update to the target by another thread.
32.127 - *
32.128 - * @return the linkage state of this call site, a method handle which can change over time
32.129 - * @see #setTarget
32.130 - */
32.131 - @Override public final MethodHandle getTarget() {
32.132 - return target;
32.133 - }
32.134 -
32.135 - /**
32.136 - * Updates the target method of this call site, as a normal variable.
32.137 - * The type of the new target must agree with the type of the old target.
32.138 - * <p>
32.139 - * The interactions with memory are the same
32.140 - * as of a write to an ordinary variable, such as an array element or a
32.141 - * non-volatile, non-final field.
32.142 - * <p>
32.143 - * In particular, unrelated threads may fail to see the updated target
32.144 - * until they perform a read from memory.
32.145 - * Stronger guarantees can be created by putting appropriate operations
32.146 - * into the bootstrap method and/or the target methods used
32.147 - * at any given call site.
32.148 - *
32.149 - * @param newTarget the new target
32.150 - * @throws NullPointerException if the proposed new target is null
32.151 - * @throws WrongMethodTypeException if the proposed new target
32.152 - * has a method type that differs from the previous target
32.153 - * @see #getTarget
32.154 - */
32.155 - @Override public void setTarget(MethodHandle newTarget) {
32.156 - checkTargetChange(this.target, newTarget);
32.157 - setTargetNormal(newTarget);
32.158 - }
32.159 -
32.160 - /**
32.161 - * {@inheritDoc}
32.162 - */
32.163 - @Override
32.164 - public final MethodHandle dynamicInvoker() {
32.165 - return makeDynamicInvoker();
32.166 - }
32.167 -
32.168 - /**
32.169 - * Performs a synchronization operation on each call site in the given array,
32.170 - * forcing all other threads to throw away any cached values previously
32.171 - * loaded from the target of any of the call sites.
32.172 - * <p>
32.173 - * This operation does not reverse any calls that have already started
32.174 - * on an old target value.
32.175 - * (Java supports {@linkplain java.lang.Object#wait() forward time travel} only.)
32.176 - * <p>
32.177 - * The overall effect is to force all future readers of each call site's target
32.178 - * to accept the most recently stored value.
32.179 - * ("Most recently" is reckoned relative to the {@code syncAll} itself.)
32.180 - * Conversely, the {@code syncAll} call may block until all readers have
32.181 - * (somehow) decached all previous versions of each call site's target.
32.182 - * <p>
32.183 - * To avoid race conditions, calls to {@code setTarget} and {@code syncAll}
32.184 - * should generally be performed under some sort of mutual exclusion.
32.185 - * Note that reader threads may observe an updated target as early
32.186 - * as the {@code setTarget} call that install the value
32.187 - * (and before the {@code syncAll} that confirms the value).
32.188 - * On the other hand, reader threads may observe previous versions of
32.189 - * the target until the {@code syncAll} call returns
32.190 - * (and after the {@code setTarget} that attempts to convey the updated version).
32.191 - * <p>
32.192 - * This operation is likely to be expensive and should be used sparingly.
32.193 - * If possible, it should be buffered for batch processing on sets of call sites.
32.194 - * <p>
32.195 - * If {@code sites} contains a null element,
32.196 - * a {@code NullPointerException} will be raised.
32.197 - * In this case, some non-null elements in the array may be
32.198 - * processed before the method returns abnormally.
32.199 - * Which elements these are (if any) is implementation-dependent.
32.200 - *
32.201 - * <h1>Java Memory Model details</h1>
32.202 - * In terms of the Java Memory Model, this operation performs a synchronization
32.203 - * action which is comparable in effect to the writing of a volatile variable
32.204 - * by the current thread, and an eventual volatile read by every other thread
32.205 - * that may access one of the affected call sites.
32.206 - * <p>
32.207 - * The following effects are apparent, for each individual call site {@code S}:
32.208 - * <ul>
32.209 - * <li>A new volatile variable {@code V} is created, and written by the current thread.
32.210 - * As defined by the JMM, this write is a global synchronization event.
32.211 - * <li>As is normal with thread-local ordering of write events,
32.212 - * every action already performed by the current thread is
32.213 - * taken to happen before the volatile write to {@code V}.
32.214 - * (In some implementations, this means that the current thread
32.215 - * performs a global release operation.)
32.216 - * <li>Specifically, the write to the current target of {@code S} is
32.217 - * taken to happen before the volatile write to {@code V}.
32.218 - * <li>The volatile write to {@code V} is placed
32.219 - * (in an implementation specific manner)
32.220 - * in the global synchronization order.
32.221 - * <li>Consider an arbitrary thread {@code T} (other than the current thread).
32.222 - * If {@code T} executes a synchronization action {@code A}
32.223 - * after the volatile write to {@code V} (in the global synchronization order),
32.224 - * it is therefore required to see either the current target
32.225 - * of {@code S}, or a later write to that target,
32.226 - * if it executes a read on the target of {@code S}.
32.227 - * (This constraint is called "synchronization-order consistency".)
32.228 - * <li>The JMM specifically allows optimizing compilers to elide
32.229 - * reads or writes of variables that are known to be useless.
32.230 - * Such elided reads and writes have no effect on the happens-before
32.231 - * relation. Regardless of this fact, the volatile {@code V}
32.232 - * will not be elided, even though its written value is
32.233 - * indeterminate and its read value is not used.
32.234 - * </ul>
32.235 - * Because of the last point, the implementation behaves as if a
32.236 - * volatile read of {@code V} were performed by {@code T}
32.237 - * immediately after its action {@code A}. In the local ordering
32.238 - * of actions in {@code T}, this read happens before any future
32.239 - * read of the target of {@code S}. It is as if the
32.240 - * implementation arbitrarily picked a read of {@code S}'s target
32.241 - * by {@code T}, and forced a read of {@code V} to precede it,
32.242 - * thereby ensuring communication of the new target value.
32.243 - * <p>
32.244 - * As long as the constraints of the Java Memory Model are obeyed,
32.245 - * implementations may delay the completion of a {@code syncAll}
32.246 - * operation while other threads ({@code T} above) continue to
32.247 - * use previous values of {@code S}'s target.
32.248 - * However, implementations are (as always) encouraged to avoid
32.249 - * livelock, and to eventually require all threads to take account
32.250 - * of the updated target.
32.251 - *
32.252 - * <p style="font-size:smaller;">
32.253 - * <em>Discussion:</em>
32.254 - * For performance reasons, {@code syncAll} is not a virtual method
32.255 - * on a single call site, but rather applies to a set of call sites.
32.256 - * Some implementations may incur a large fixed overhead cost
32.257 - * for processing one or more synchronization operations,
32.258 - * but a small incremental cost for each additional call site.
32.259 - * In any case, this operation is likely to be costly, since
32.260 - * other threads may have to be somehow interrupted
32.261 - * in order to make them notice the updated target value.
32.262 - * However, it may be observed that a single call to synchronize
32.263 - * several sites has the same formal effect as many calls,
32.264 - * each on just one of the sites.
32.265 - *
32.266 - * <p style="font-size:smaller;">
32.267 - * <em>Implementation Note:</em>
32.268 - * Simple implementations of {@code MutableCallSite} may use
32.269 - * a volatile variable for the target of a mutable call site.
32.270 - * In such an implementation, the {@code syncAll} method can be a no-op,
32.271 - * and yet it will conform to the JMM behavior documented above.
32.272 - *
32.273 - * @param sites an array of call sites to be synchronized
32.274 - * @throws NullPointerException if the {@code sites} array reference is null
32.275 - * or the array contains a null
32.276 - */
32.277 - public static void syncAll(MutableCallSite[] sites) {
32.278 - if (sites.length == 0) return;
32.279 - STORE_BARRIER.lazySet(0);
32.280 - for (int i = 0; i < sites.length; i++) {
32.281 - sites[i].getClass(); // trigger NPE on first null
32.282 - }
32.283 - // FIXME: NYI
32.284 - }
32.285 - private static final AtomicInteger STORE_BARRIER = new AtomicInteger();
32.286 -}
33.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/SerializedLambda.java Sun Aug 17 20:09:05 2014 +0200
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,258 +0,0 @@
33.4 -/*
33.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
33.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33.7 - *
33.8 - * This code is free software; you can redistribute it and/or modify it
33.9 - * under the terms of the GNU General Public License version 2 only, as
33.10 - * published by the Free Software Foundation. Oracle designates this
33.11 - * particular file as subject to the "Classpath" exception as provided
33.12 - * by Oracle in the LICENSE file that accompanied this code.
33.13 - *
33.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
33.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33.17 - * version 2 for more details (a copy is included in the LICENSE file that
33.18 - * accompanied this code).
33.19 - *
33.20 - * You should have received a copy of the GNU General Public License version
33.21 - * 2 along with this work; if not, write to the Free Software Foundation,
33.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
33.23 - *
33.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
33.25 - * or visit www.oracle.com if you need additional information or have any
33.26 - * questions.
33.27 - */
33.28 -package java.lang.invoke;
33.29 -
33.30 -import java.io.Serializable;
33.31 -import java.lang.reflect.Method;
33.32 -import java.security.AccessController;
33.33 -import java.security.PrivilegedActionException;
33.34 -import java.security.PrivilegedExceptionAction;
33.35 -import java.util.Objects;
33.36 -
33.37 -/**
33.38 - * Serialized form of a lambda expression. The properties of this class
33.39 - * represent the information that is present at the lambda factory site, including
33.40 - * static metafactory arguments such as the identity of the primary functional
33.41 - * interface method and the identity of the implementation method, as well as
33.42 - * dynamic metafactory arguments such as values captured from the lexical scope
33.43 - * at the time of lambda capture.
33.44 - *
33.45 - * <p>Implementors of serializable lambdas, such as compilers or language
33.46 - * runtime libraries, are expected to ensure that instances deserialize properly.
33.47 - * One means to do so is to ensure that the {@code writeReplace} method returns
33.48 - * an instance of {@code SerializedLambda}, rather than allowing default
33.49 - * serialization to proceed.
33.50 - *
33.51 - * <p>{@code SerializedLambda} has a {@code readResolve} method that looks for
33.52 - * a (possibly private) static method called
33.53 - * {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
33.54 - * that with itself as the first argument, and returns the result. Lambda classes
33.55 - * implementing {@code $deserializeLambda$} are responsible for validating
33.56 - * that the properties of the {@code SerializedLambda} are consistent with a
33.57 - * lambda actually captured by that class.
33.58 - *
33.59 - * @see LambdaMetafactory
33.60 - */
33.61 -public final class SerializedLambda implements Serializable {
33.62 - private static final long serialVersionUID = 8025925345765570181L;
33.63 - private final Class<?> capturingClass;
33.64 - private final String functionalInterfaceClass;
33.65 - private final String functionalInterfaceMethodName;
33.66 - private final String functionalInterfaceMethodSignature;
33.67 - private final String implClass;
33.68 - private final String implMethodName;
33.69 - private final String implMethodSignature;
33.70 - private final int implMethodKind;
33.71 - private final String instantiatedMethodType;
33.72 - private final Object[] capturedArgs;
33.73 -
33.74 - /**
33.75 - * Create a {@code SerializedLambda} from the low-level information present
33.76 - * at the lambda factory site.
33.77 - *
33.78 - * @param capturingClass The class in which the lambda expression appears
33.79 - * @param functionalInterfaceClass Name, in slash-delimited form, of static
33.80 - * type of the returned lambda object
33.81 - * @param functionalInterfaceMethodName Name of the functional interface
33.82 - * method for the present at the
33.83 - * lambda factory site
33.84 - * @param functionalInterfaceMethodSignature Signature of the functional
33.85 - * interface method present at
33.86 - * the lambda factory site
33.87 - * @param implMethodKind Method handle kind for the implementation method
33.88 - * @param implClass Name, in slash-delimited form, for the class holding
33.89 - * the implementation method
33.90 - * @param implMethodName Name of the implementation method
33.91 - * @param implMethodSignature Signature of the implementation method
33.92 - * @param instantiatedMethodType The signature of the primary functional
33.93 - * interface method after type variables
33.94 - * are substituted with their instantiation
33.95 - * from the capture site
33.96 - * @param capturedArgs The dynamic arguments to the lambda factory site,
33.97 - * which represent variables captured by
33.98 - * the lambda
33.99 - */
33.100 - public SerializedLambda(Class<?> capturingClass,
33.101 - String functionalInterfaceClass,
33.102 - String functionalInterfaceMethodName,
33.103 - String functionalInterfaceMethodSignature,
33.104 - int implMethodKind,
33.105 - String implClass,
33.106 - String implMethodName,
33.107 - String implMethodSignature,
33.108 - String instantiatedMethodType,
33.109 - Object[] capturedArgs) {
33.110 - this.capturingClass = capturingClass;
33.111 - this.functionalInterfaceClass = functionalInterfaceClass;
33.112 - this.functionalInterfaceMethodName = functionalInterfaceMethodName;
33.113 - this.functionalInterfaceMethodSignature = functionalInterfaceMethodSignature;
33.114 - this.implMethodKind = implMethodKind;
33.115 - this.implClass = implClass;
33.116 - this.implMethodName = implMethodName;
33.117 - this.implMethodSignature = implMethodSignature;
33.118 - this.instantiatedMethodType = instantiatedMethodType;
33.119 - this.capturedArgs = Objects.requireNonNull(capturedArgs).clone();
33.120 - }
33.121 -
33.122 - /**
33.123 - * Get the name of the class that captured this lambda.
33.124 - * @return the name of the class that captured this lambda
33.125 - */
33.126 - public String getCapturingClass() {
33.127 - return capturingClass.getName().replace('.', '/');
33.128 - }
33.129 -
33.130 - /**
33.131 - * Get the name of the invoked type to which this
33.132 - * lambda has been converted
33.133 - * @return the name of the functional interface class to which
33.134 - * this lambda has been converted
33.135 - */
33.136 - public String getFunctionalInterfaceClass() {
33.137 - return functionalInterfaceClass;
33.138 - }
33.139 -
33.140 - /**
33.141 - * Get the name of the primary method for the functional interface
33.142 - * to which this lambda has been converted.
33.143 - * @return the name of the primary methods of the functional interface
33.144 - */
33.145 - public String getFunctionalInterfaceMethodName() {
33.146 - return functionalInterfaceMethodName;
33.147 - }
33.148 -
33.149 - /**
33.150 - * Get the signature of the primary method for the functional
33.151 - * interface to which this lambda has been converted.
33.152 - * @return the signature of the primary method of the functional
33.153 - * interface
33.154 - */
33.155 - public String getFunctionalInterfaceMethodSignature() {
33.156 - return functionalInterfaceMethodSignature;
33.157 - }
33.158 -
33.159 - /**
33.160 - * Get the name of the class containing the implementation
33.161 - * method.
33.162 - * @return the name of the class containing the implementation
33.163 - * method
33.164 - */
33.165 - public String getImplClass() {
33.166 - return implClass;
33.167 - }
33.168 -
33.169 - /**
33.170 - * Get the name of the implementation method.
33.171 - * @return the name of the implementation method
33.172 - */
33.173 - public String getImplMethodName() {
33.174 - return implMethodName;
33.175 - }
33.176 -
33.177 - /**
33.178 - * Get the signature of the implementation method.
33.179 - * @return the signature of the implementation method
33.180 - */
33.181 - public String getImplMethodSignature() {
33.182 - return implMethodSignature;
33.183 - }
33.184 -
33.185 - /**
33.186 - * Get the method handle kind (see {@link MethodHandleInfo}) of
33.187 - * the implementation method.
33.188 - * @return the method handle kind of the implementation method
33.189 - */
33.190 - public int getImplMethodKind() {
33.191 - return implMethodKind;
33.192 - }
33.193 -
33.194 - /**
33.195 - * Get the signature of the primary functional interface method
33.196 - * after type variables are substituted with their instantiation
33.197 - * from the capture site.
33.198 - * @return the signature of the primary functional interface method
33.199 - * after type variable processing
33.200 - */
33.201 - public final String getInstantiatedMethodType() {
33.202 - return instantiatedMethodType;
33.203 - }
33.204 -
33.205 - /**
33.206 - * Get the count of dynamic arguments to the lambda capture site.
33.207 - * @return the count of dynamic arguments to the lambda capture site
33.208 - */
33.209 - public int getCapturedArgCount() {
33.210 - return capturedArgs.length;
33.211 - }
33.212 -
33.213 - /**
33.214 - * Get a dynamic argument to the lambda capture site.
33.215 - * @param i the argument to capture
33.216 - * @return a dynamic argument to the lambda capture site
33.217 - */
33.218 - public Object getCapturedArg(int i) {
33.219 - return capturedArgs[i];
33.220 - }
33.221 -
33.222 - private Object readResolve() throws ReflectiveOperationException {
33.223 - try {
33.224 - Method deserialize = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
33.225 - @Override
33.226 - public Method run() throws Exception {
33.227 - Method m = capturingClass.getDeclaredMethod("$deserializeLambda$", SerializedLambda.class);
33.228 - m.setAccessible(true);
33.229 - return m;
33.230 - }
33.231 - });
33.232 -
33.233 - return deserialize.invoke(null, this);
33.234 - }
33.235 - catch (PrivilegedActionException e) {
33.236 - Exception cause = e.getException();
33.237 - if (cause instanceof ReflectiveOperationException)
33.238 - throw (ReflectiveOperationException) cause;
33.239 - else if (cause instanceof RuntimeException)
33.240 - throw (RuntimeException) cause;
33.241 - else
33.242 - throw new RuntimeException("Exception in SerializedLambda.readResolve", e);
33.243 - }
33.244 - }
33.245 -
33.246 - @Override
33.247 - public String toString() {
33.248 - String implKind=MethodHandleInfo.referenceKindToString(implMethodKind);
33.249 - return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " +
33.250 - "%s=%s %s.%s:%s, %s=%s, %s=%d]",
33.251 - "capturingClass", capturingClass,
33.252 - "functionalInterfaceMethod", functionalInterfaceClass,
33.253 - functionalInterfaceMethodName,
33.254 - functionalInterfaceMethodSignature,
33.255 - "implementation",
33.256 - implKind,
33.257 - implClass, implMethodName, implMethodSignature,
33.258 - "instantiatedMethodType", instantiatedMethodType,
33.259 - "numCaptured", capturedArgs.length);
33.260 - }
33.261 -}
34.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/SimpleMethodHandle.java Sun Aug 17 20:09:05 2014 +0200
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,70 +0,0 @@
34.4 -/*
34.5 - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
34.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
34.7 - *
34.8 - * This code is free software; you can redistribute it and/or modify it
34.9 - * under the terms of the GNU General Public License version 2 only, as
34.10 - * published by the Free Software Foundation. Oracle designates this
34.11 - * particular file as subject to the "Classpath" exception as provided
34.12 - * by Oracle in the LICENSE file that accompanied this code.
34.13 - *
34.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
34.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34.17 - * version 2 for more details (a copy is included in the LICENSE file that
34.18 - * accompanied this code).
34.19 - *
34.20 - * You should have received a copy of the GNU General Public License version
34.21 - * 2 along with this work; if not, write to the Free Software Foundation,
34.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34.23 - *
34.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
34.25 - * or visit www.oracle.com if you need additional information or have any
34.26 - * questions.
34.27 - */
34.28 -
34.29 -package java.lang.invoke;
34.30 -
34.31 -import static java.lang.invoke.LambdaForm.*;
34.32 -import static java.lang.invoke.MethodHandleNatives.Constants.*;
34.33 -import java.util.logging.Level;
34.34 -import java.util.logging.Logger;
34.35 -
34.36 -/**
34.37 - * A method handle whose behavior is determined only by its LambdaForm.
34.38 - * @author jrose
34.39 - */
34.40 -final class SimpleMethodHandle extends MethodHandle {
34.41 - private SimpleMethodHandle(MethodType type, LambdaForm form) {
34.42 - super(type, form);
34.43 - }
34.44 -
34.45 - /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
34.46 - return new SimpleMethodHandle(type, form);
34.47 - }
34.48 -
34.49 - @Override
34.50 - MethodHandle bindArgument(int pos, char basicType, Object value) {
34.51 - MethodType type2 = type().dropParameterTypes(pos, pos+1);
34.52 - LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
34.53 - return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
34.54 - }
34.55 -
34.56 - @Override
34.57 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
34.58 - LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
34.59 - return new SimpleMethodHandle(srcType, newForm);
34.60 - }
34.61 -
34.62 - @Override
34.63 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
34.64 - LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList()));
34.65 - return new SimpleMethodHandle(newType, form2);
34.66 - }
34.67 -
34.68 - @Override
34.69 - MethodHandle copyWith(MethodType mt, LambdaForm lf) {
34.70 - return new SimpleMethodHandle(mt, lf);
34.71 - }
34.72 -
34.73 -}
35.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/Stable.java Sun Aug 17 20:09:05 2014 +0200
35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
35.3 @@ -1,73 +0,0 @@
35.4 -/*
35.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
35.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
35.7 - *
35.8 - * This code is free software; you can redistribute it and/or modify it
35.9 - * under the terms of the GNU General Public License version 2 only, as
35.10 - * published by the Free Software Foundation. Oracle designates this
35.11 - * particular file as subject to the "Classpath" exception as provided
35.12 - * by Oracle in the LICENSE file that accompanied this code.
35.13 - *
35.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
35.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35.17 - * version 2 for more details (a copy is included in the LICENSE file that
35.18 - * accompanied this code).
35.19 - *
35.20 - * You should have received a copy of the GNU General Public License version
35.21 - * 2 along with this work; if not, write to the Free Software Foundation,
35.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
35.23 - *
35.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
35.25 - * or visit www.oracle.com if you need additional information or have any
35.26 - * questions.
35.27 - */
35.28 -
35.29 -package java.lang.invoke;
35.30 -
35.31 -import java.lang.annotation.*;
35.32 -
35.33 -/**
35.34 - * A field may be annotated as stable if all of its component variables
35.35 - * changes value at most once.
35.36 - * A field's value counts as its component value.
35.37 - * If the field is typed as an array, then all the non-null components
35.38 - * of the array, of depth up to the rank of the field's array type,
35.39 - * also count as component values.
35.40 - * By extension, any variable (either array or field) which has annotated
35.41 - * as stable is called a stable variable, and its non-null or non-zero
35.42 - * value is called a stable value.
35.43 - * <p>
35.44 - * Since all fields begin with a default value of null for references
35.45 - * (resp., zero for primitives), it follows that this annotation indicates
35.46 - * that the first non-null (resp., non-zero) value stored in the field
35.47 - * will never be changed.
35.48 - * <p>
35.49 - * If the field is not of an array type, there are no array elements,
35.50 - * then the value indicated as stable is simply the value of the field.
35.51 - * If the dynamic type of the field value is an array but the static type
35.52 - * is not, the components of the array are <em>not</em> regarded as stable.
35.53 - * <p>
35.54 - * If the field is an array type, then both the field value and
35.55 - * all the components of the field value (if the field value is non-null)
35.56 - * are indicated to be stable.
35.57 - * If the field type is an array type with rank {@code N > 1},
35.58 - * then each component of the field value (if the field value is non-null),
35.59 - * is regarded as a stable array of rank {@code N-1}.
35.60 - * <p>
35.61 - * Fields which are declared {@code final} may also be annotated as stable.
35.62 - * Since final fields already behave as stable values, such an annotation
35.63 - * indicates no additional information, unless the type of the field is
35.64 - * an array type.
35.65 - * <p>
35.66 - * It is (currently) undefined what happens if a field annotated as stable
35.67 - * is given a third value. In practice, if the JVM relies on this annotation
35.68 - * to promote a field reference to a constant, it may be that the Java memory
35.69 - * model would appear to be broken, if such a constant (the second value of the field)
35.70 - * is used as the value of the field even after the field value has changed.
35.71 - */
35.72 -/* package-private */
35.73 -@Target(ElementType.FIELD)
35.74 -@Retention(RetentionPolicy.RUNTIME)
35.75 -@interface Stable {
35.76 -}
36.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/SwitchPoint.java Sun Aug 17 20:09:05 2014 +0200
36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
36.3 @@ -1,228 +0,0 @@
36.4 -/*
36.5 - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
36.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
36.7 - *
36.8 - * This code is free software; you can redistribute it and/or modify it
36.9 - * under the terms of the GNU General Public License version 2 only, as
36.10 - * published by the Free Software Foundation. Oracle designates this
36.11 - * particular file as subject to the "Classpath" exception as provided
36.12 - * by Oracle in the LICENSE file that accompanied this code.
36.13 - *
36.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
36.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36.17 - * version 2 for more details (a copy is included in the LICENSE file that
36.18 - * accompanied this code).
36.19 - *
36.20 - * You should have received a copy of the GNU General Public License version
36.21 - * 2 along with this work; if not, write to the Free Software Foundation,
36.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
36.23 - *
36.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
36.25 - * or visit www.oracle.com if you need additional information or have any
36.26 - * questions.
36.27 - */
36.28 -
36.29 -package java.lang.invoke;
36.30 -
36.31 -/**
36.32 - * <p>
36.33 - * A {@code SwitchPoint} is an object which can publish state transitions to other threads.
36.34 - * A switch point is initially in the <em>valid</em> state, but may at any time be
36.35 - * changed to the <em>invalid</em> state. Invalidation cannot be reversed.
36.36 - * A switch point can combine a <em>guarded pair</em> of method handles into a
36.37 - * <em>guarded delegator</em>.
36.38 - * The guarded delegator is a method handle which delegates to one of the old method handles.
36.39 - * The state of the switch point determines which of the two gets the delegation.
36.40 - * <p>
36.41 - * A single switch point may be used to control any number of method handles.
36.42 - * (Indirectly, therefore, it can control any number of call sites.)
36.43 - * This is done by using the single switch point as a factory for combining
36.44 - * any number of guarded method handle pairs into guarded delegators.
36.45 - * <p>
36.46 - * When a guarded delegator is created from a guarded pair, the pair
36.47 - * is wrapped in a new method handle {@code M},
36.48 - * which is permanently associated with the switch point that created it.
36.49 - * Each pair consists of a target {@code T} and a fallback {@code F}.
36.50 - * While the switch point is valid, invocations to {@code M} are delegated to {@code T}.
36.51 - * After it is invalidated, invocations are delegated to {@code F}.
36.52 - * <p>
36.53 - * Invalidation is global and immediate, as if the switch point contained a
36.54 - * volatile boolean variable consulted on every call to {@code M}.
36.55 - * The invalidation is also permanent, which means the switch point
36.56 - * can change state only once.
36.57 - * The switch point will always delegate to {@code F} after being invalidated.
36.58 - * At that point {@code guardWithTest} may ignore {@code T} and return {@code F}.
36.59 - * <p>
36.60 - * Here is an example of a switch point in action:
36.61 - * <blockquote><pre>{@code
36.62 -MethodHandle MH_strcat = MethodHandles.lookup()
36.63 - .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
36.64 -SwitchPoint spt = new SwitchPoint();
36.65 -assert(!spt.hasBeenInvalidated());
36.66 -// the following steps may be repeated to re-use the same switch point:
36.67 -MethodHandle worker1 = MH_strcat;
36.68 -MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0);
36.69 -MethodHandle worker = spt.guardWithTest(worker1, worker2);
36.70 -assertEquals("method", (String) worker.invokeExact("met", "hod"));
36.71 -SwitchPoint.invalidateAll(new SwitchPoint[]{ spt });
36.72 -assert(spt.hasBeenInvalidated());
36.73 -assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
36.74 - * }</pre></blockquote>
36.75 - * <p style="font-size:smaller;">
36.76 - * <em>Discussion:</em>
36.77 - * Switch points are useful without subclassing. They may also be subclassed.
36.78 - * This may be useful in order to associate application-specific invalidation logic
36.79 - * with the switch point.
36.80 - * Notice that there is no permanent association between a switch point and
36.81 - * the method handles it produces and consumes.
36.82 - * The garbage collector may collect method handles produced or consumed
36.83 - * by a switch point independently of the lifetime of the switch point itself.
36.84 - * <p style="font-size:smaller;">
36.85 - * <em>Implementation Note:</em>
36.86 - * A switch point behaves as if implemented on top of {@link MutableCallSite},
36.87 - * approximately as follows:
36.88 - * <blockquote><pre>{@code
36.89 -public class SwitchPoint {
36.90 - private static final MethodHandle
36.91 - K_true = MethodHandles.constant(boolean.class, true),
36.92 - K_false = MethodHandles.constant(boolean.class, false);
36.93 - private final MutableCallSite mcs;
36.94 - private final MethodHandle mcsInvoker;
36.95 - public SwitchPoint() {
36.96 - this.mcs = new MutableCallSite(K_true);
36.97 - this.mcsInvoker = mcs.dynamicInvoker();
36.98 - }
36.99 - public MethodHandle guardWithTest(
36.100 - MethodHandle target, MethodHandle fallback) {
36.101 - // Note: mcsInvoker is of type ()boolean.
36.102 - // Target and fallback may take any arguments, but must have the same type.
36.103 - return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback);
36.104 - }
36.105 - public static void invalidateAll(SwitchPoint[] spts) {
36.106 - List<MutableCallSite> mcss = new ArrayList<>();
36.107 - for (SwitchPoint spt : spts) mcss.add(spt.mcs);
36.108 - for (MutableCallSite mcs : mcss) mcs.setTarget(K_false);
36.109 - MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0]));
36.110 - }
36.111 -}
36.112 - * }</pre></blockquote>
36.113 - * @author Remi Forax, JSR 292 EG
36.114 - */
36.115 -public class SwitchPoint {
36.116 - private static final MethodHandle
36.117 - K_true = MethodHandles.constant(boolean.class, true),
36.118 - K_false = MethodHandles.constant(boolean.class, false);
36.119 -
36.120 - private final MutableCallSite mcs;
36.121 - private final MethodHandle mcsInvoker;
36.122 -
36.123 - /**
36.124 - * Creates a new switch point.
36.125 - */
36.126 - public SwitchPoint() {
36.127 - this.mcs = new MutableCallSite(K_true);
36.128 - this.mcsInvoker = mcs.dynamicInvoker();
36.129 - }
36.130 -
36.131 - /**
36.132 - * Determines if this switch point has been invalidated yet.
36.133 - *
36.134 - * <p style="font-size:smaller;">
36.135 - * <em>Discussion:</em>
36.136 - * Because of the one-way nature of invalidation, once a switch point begins
36.137 - * to return true for {@code hasBeenInvalidated},
36.138 - * it will always do so in the future.
36.139 - * On the other hand, a valid switch point visible to other threads may
36.140 - * be invalidated at any moment, due to a request by another thread.
36.141 - * <p style="font-size:smaller;">
36.142 - * Since invalidation is a global and immediate operation,
36.143 - * the execution of this query, on a valid switchpoint,
36.144 - * must be internally sequenced with any
36.145 - * other threads that could cause invalidation.
36.146 - * This query may therefore be expensive.
36.147 - * The recommended way to build a boolean-valued method handle
36.148 - * which queries the invalidation state of a switch point {@code s} is
36.149 - * to call {@code s.guardWithTest} on
36.150 - * {@link MethodHandles#constant constant} true and false method handles.
36.151 - *
36.152 - * @return true if this switch point has been invalidated
36.153 - */
36.154 - public boolean hasBeenInvalidated() {
36.155 - return (mcs.getTarget() != K_true);
36.156 - }
36.157 -
36.158 - /**
36.159 - * Returns a method handle which always delegates either to the target or the fallback.
36.160 - * The method handle will delegate to the target exactly as long as the switch point is valid.
36.161 - * After that, it will permanently delegate to the fallback.
36.162 - * <p>
36.163 - * The target and fallback must be of exactly the same method type,
36.164 - * and the resulting combined method handle will also be of this type.
36.165 - *
36.166 - * @param target the method handle selected by the switch point as long as it is valid
36.167 - * @param fallback the method handle selected by the switch point after it is invalidated
36.168 - * @return a combined method handle which always calls either the target or fallback
36.169 - * @throws NullPointerException if either argument is null
36.170 - * @throws IllegalArgumentException if the two method types do not match
36.171 - * @see MethodHandles#guardWithTest
36.172 - */
36.173 - public MethodHandle guardWithTest(MethodHandle target, MethodHandle fallback) {
36.174 - if (mcs.getTarget() == K_false)
36.175 - return fallback; // already invalid
36.176 - return MethodHandles.guardWithTest(mcsInvoker, target, fallback);
36.177 - }
36.178 -
36.179 - /**
36.180 - * Sets all of the given switch points into the invalid state.
36.181 - * After this call executes, no thread will observe any of the
36.182 - * switch points to be in a valid state.
36.183 - * <p>
36.184 - * This operation is likely to be expensive and should be used sparingly.
36.185 - * If possible, it should be buffered for batch processing on sets of switch points.
36.186 - * <p>
36.187 - * If {@code switchPoints} contains a null element,
36.188 - * a {@code NullPointerException} will be raised.
36.189 - * In this case, some non-null elements in the array may be
36.190 - * processed before the method returns abnormally.
36.191 - * Which elements these are (if any) is implementation-dependent.
36.192 - *
36.193 - * <p style="font-size:smaller;">
36.194 - * <em>Discussion:</em>
36.195 - * For performance reasons, {@code invalidateAll} is not a virtual method
36.196 - * on a single switch point, but rather applies to a set of switch points.
36.197 - * Some implementations may incur a large fixed overhead cost
36.198 - * for processing one or more invalidation operations,
36.199 - * but a small incremental cost for each additional invalidation.
36.200 - * In any case, this operation is likely to be costly, since
36.201 - * other threads may have to be somehow interrupted
36.202 - * in order to make them notice the updated switch point state.
36.203 - * However, it may be observed that a single call to invalidate
36.204 - * several switch points has the same formal effect as many calls,
36.205 - * each on just one of the switch points.
36.206 - *
36.207 - * <p style="font-size:smaller;">
36.208 - * <em>Implementation Note:</em>
36.209 - * Simple implementations of {@code SwitchPoint} may use
36.210 - * a private {@link MutableCallSite} to publish the state of a switch point.
36.211 - * In such an implementation, the {@code invalidateAll} method can
36.212 - * simply change the call site's target, and issue one call to
36.213 - * {@linkplain MutableCallSite#syncAll synchronize} all the
36.214 - * private call sites.
36.215 - *
36.216 - * @param switchPoints an array of call sites to be synchronized
36.217 - * @throws NullPointerException if the {@code switchPoints} array reference is null
36.218 - * or the array contains a null
36.219 - */
36.220 - public static void invalidateAll(SwitchPoint[] switchPoints) {
36.221 - if (switchPoints.length == 0) return;
36.222 - MutableCallSite[] sites = new MutableCallSite[switchPoints.length];
36.223 - for (int i = 0; i < switchPoints.length; i++) {
36.224 - SwitchPoint spt = switchPoints[i];
36.225 - if (spt == null) break; // MSC.syncAll will trigger a NPE
36.226 - sites[i] = spt.mcs;
36.227 - spt.mcs.setTarget(K_false);
36.228 - }
36.229 - MutableCallSite.syncAll(sites);
36.230 - }
36.231 -}
37.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/VolatileCallSite.java Sun Aug 17 20:09:05 2014 +0200
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,109 +0,0 @@
37.4 -/*
37.5 - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
37.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
37.7 - *
37.8 - * This code is free software; you can redistribute it and/or modify it
37.9 - * under the terms of the GNU General Public License version 2 only, as
37.10 - * published by the Free Software Foundation. Oracle designates this
37.11 - * particular file as subject to the "Classpath" exception as provided
37.12 - * by Oracle in the LICENSE file that accompanied this code.
37.13 - *
37.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
37.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
37.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37.17 - * version 2 for more details (a copy is included in the LICENSE file that
37.18 - * accompanied this code).
37.19 - *
37.20 - * You should have received a copy of the GNU General Public License version
37.21 - * 2 along with this work; if not, write to the Free Software Foundation,
37.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
37.23 - *
37.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
37.25 - * or visit www.oracle.com if you need additional information or have any
37.26 - * questions.
37.27 - */
37.28 -
37.29 -package java.lang.invoke;
37.30 -
37.31 -/**
37.32 - * A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
37.33 - * An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
37.34 - * to its call site target immediately, even if the update occurs in another thread.
37.35 - * There may be a performance penalty for such tight coupling between threads.
37.36 - * <p>
37.37 - * Unlike {@code MutableCallSite}, there is no
37.38 - * {@linkplain MutableCallSite#syncAll syncAll operation} on volatile
37.39 - * call sites, since every write to a volatile variable is implicitly
37.40 - * synchronized with reader threads.
37.41 - * <p>
37.42 - * In other respects, a {@code VolatileCallSite} is interchangeable
37.43 - * with {@code MutableCallSite}.
37.44 - * @see MutableCallSite
37.45 - * @author John Rose, JSR 292 EG
37.46 - */
37.47 -public class VolatileCallSite extends CallSite {
37.48 - /**
37.49 - * Creates a call site with a volatile binding to its target.
37.50 - * The initial target is set to a method handle
37.51 - * of the given type which will throw an {@code IllegalStateException} if called.
37.52 - * @param type the method type that this call site will have
37.53 - * @throws NullPointerException if the proposed type is null
37.54 - */
37.55 - public VolatileCallSite(MethodType type) {
37.56 - super(type);
37.57 - }
37.58 -
37.59 - /**
37.60 - * Creates a call site with a volatile binding to its target.
37.61 - * The target is set to the given value.
37.62 - * @param target the method handle that will be the initial target of the call site
37.63 - * @throws NullPointerException if the proposed target is null
37.64 - */
37.65 - public VolatileCallSite(MethodHandle target) {
37.66 - super(target);
37.67 - }
37.68 -
37.69 - /**
37.70 - * Returns the target method of the call site, which behaves
37.71 - * like a {@code volatile} field of the {@code VolatileCallSite}.
37.72 - * <p>
37.73 - * The interactions of {@code getTarget} with memory are the same
37.74 - * as of a read from a {@code volatile} field.
37.75 - * <p>
37.76 - * In particular, the current thread is required to issue a fresh
37.77 - * read of the target from memory, and must not fail to see
37.78 - * a recent update to the target by another thread.
37.79 - *
37.80 - * @return the linkage state of this call site, a method handle which can change over time
37.81 - * @see #setTarget
37.82 - */
37.83 - @Override public final MethodHandle getTarget() {
37.84 - return getTargetVolatile();
37.85 - }
37.86 -
37.87 - /**
37.88 - * Updates the target method of this call site, as a volatile variable.
37.89 - * The type of the new target must agree with the type of the old target.
37.90 - * <p>
37.91 - * The interactions with memory are the same as of a write to a volatile field.
37.92 - * In particular, any threads is guaranteed to see the updated target
37.93 - * the next time it calls {@code getTarget}.
37.94 - * @param newTarget the new target
37.95 - * @throws NullPointerException if the proposed new target is null
37.96 - * @throws WrongMethodTypeException if the proposed new target
37.97 - * has a method type that differs from the previous target
37.98 - * @see #getTarget
37.99 - */
37.100 - @Override public void setTarget(MethodHandle newTarget) {
37.101 - checkTargetChange(getTargetVolatile(), newTarget);
37.102 - setTargetVolatile(newTarget);
37.103 - }
37.104 -
37.105 - /**
37.106 - * {@inheritDoc}
37.107 - */
37.108 - @Override
37.109 - public final MethodHandle dynamicInvoker() {
37.110 - return makeDynamicInvoker();
37.111 - }
37.112 -}
38.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/WrongMethodTypeException.java Sun Aug 17 20:09:05 2014 +0200
38.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
38.3 @@ -1,85 +0,0 @@
38.4 -/*
38.5 - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
38.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
38.7 - *
38.8 - * This code is free software; you can redistribute it and/or modify it
38.9 - * under the terms of the GNU General Public License version 2 only, as
38.10 - * published by the Free Software Foundation. Oracle designates this
38.11 - * particular file as subject to the "Classpath" exception as provided
38.12 - * by Oracle in the LICENSE file that accompanied this code.
38.13 - *
38.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
38.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
38.17 - * version 2 for more details (a copy is included in the LICENSE file that
38.18 - * accompanied this code).
38.19 - *
38.20 - * You should have received a copy of the GNU General Public License version
38.21 - * 2 along with this work; if not, write to the Free Software Foundation,
38.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
38.23 - *
38.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
38.25 - * or visit www.oracle.com if you need additional information or have any
38.26 - * questions.
38.27 - */
38.28 -
38.29 -package java.lang.invoke;
38.30 -
38.31 -/**
38.32 - * Thrown to indicate that code has attempted to call a method handle
38.33 - * via the wrong method type. As with the bytecode representation of
38.34 - * normal Java method calls, method handle calls are strongly typed
38.35 - * to a specific type descriptor associated with a call site.
38.36 - * <p>
38.37 - * This exception may also be thrown when two method handles are
38.38 - * composed, and the system detects that their types cannot be
38.39 - * matched up correctly. This amounts to an early evaluation
38.40 - * of the type mismatch, at method handle construction time,
38.41 - * instead of when the mismatched method handle is called.
38.42 - *
38.43 - * @author John Rose, JSR 292 EG
38.44 - * @since 1.7
38.45 - */
38.46 -public class WrongMethodTypeException extends RuntimeException {
38.47 - private static final long serialVersionUID = 292L;
38.48 -
38.49 - /**
38.50 - * Constructs a {@code WrongMethodTypeException} with no detail message.
38.51 - */
38.52 - public WrongMethodTypeException() {
38.53 - super();
38.54 - }
38.55 -
38.56 - /**
38.57 - * Constructs a {@code WrongMethodTypeException} with the specified
38.58 - * detail message.
38.59 - *
38.60 - * @param s the detail message.
38.61 - */
38.62 - public WrongMethodTypeException(String s) {
38.63 - super(s);
38.64 - }
38.65 -
38.66 - /**
38.67 - * Constructs a {@code WrongMethodTypeException} with the specified
38.68 - * detail message and cause.
38.69 - *
38.70 - * @param s the detail message.
38.71 - * @param cause the cause of the exception, or null.
38.72 - */
38.73 - //FIXME: make this public in MR1
38.74 - /*non-public*/ WrongMethodTypeException(String s, Throwable cause) {
38.75 - super(s, cause);
38.76 - }
38.77 -
38.78 - /**
38.79 - * Constructs a {@code WrongMethodTypeException} with the specified
38.80 - * cause.
38.81 - *
38.82 - * @param cause the cause of the exception, or null.
38.83 - */
38.84 - //FIXME: make this public in MR1
38.85 - /*non-public*/ WrongMethodTypeException(Throwable cause) {
38.86 - super(cause);
38.87 - }
38.88 -}
39.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/package-info.java Sun Aug 17 20:09:05 2014 +0200
39.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
39.3 @@ -1,211 +0,0 @@
39.4 -/*
39.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
39.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
39.7 - *
39.8 - * This code is free software; you can redistribute it and/or modify it
39.9 - * under the terms of the GNU General Public License version 2 only, as
39.10 - * published by the Free Software Foundation. Oracle designates this
39.11 - * particular file as subject to the "Classpath" exception as provided
39.12 - * by Oracle in the LICENSE file that accompanied this code.
39.13 - *
39.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
39.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
39.17 - * version 2 for more details (a copy is included in the LICENSE file that
39.18 - * accompanied this code).
39.19 - *
39.20 - * You should have received a copy of the GNU General Public License version
39.21 - * 2 along with this work; if not, write to the Free Software Foundation,
39.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
39.23 - *
39.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
39.25 - * or visit www.oracle.com if you need additional information or have any
39.26 - * questions.
39.27 - */
39.28 -
39.29 -/**
39.30 - * The {@code java.lang.invoke} package contains dynamic language support provided directly by
39.31 - * the Java core class libraries and virtual machine.
39.32 - *
39.33 - * <p>
39.34 - * As described in the Java Virtual Machine Specification,
39.35 - * certain types in this package have special relations to dynamic
39.36 - * language support in the virtual machine:
39.37 - * <ul>
39.38 - * <li>The class {@link java.lang.invoke.MethodHandle MethodHandle} contains
39.39 - * <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
39.40 - * which can be linked regardless of their type descriptor.
39.41 - * Normally, method linkage requires exact matching of type descriptors.
39.42 - * </li>
39.43 - *
39.44 - * <li>The JVM bytecode format supports immediate constants of
39.45 - * the classes {@link java.lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke.MethodType MethodType}.
39.46 - * </li>
39.47 - * </ul>
39.48 - *
39.49 - * <h1><a name="jvm_mods"></a>Summary of relevant Java Virtual Machine changes</h1>
39.50 - * The following low-level information summarizes relevant parts of the
39.51 - * Java Virtual Machine specification. For full details, please see the
39.52 - * current version of that specification.
39.53 - *
39.54 - * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
39.55 - * <h2><a name="indyinsn"></a>{@code invokedynamic} instructions</h2>
39.56 - * A dynamic call site is originally in an unlinked state. In this state, there is
39.57 - * no target method for the call site to invoke.
39.58 - * <p>
39.59 - * Before the JVM can execute a dynamic call site (an {@code invokedynamic} instruction),
39.60 - * the call site must first be <em>linked</em>.
39.61 - * Linking is accomplished by calling a <em>bootstrap method</em>
39.62 - * which is given the static information content of the call site,
39.63 - * and which must produce a {@link java.lang.invoke.MethodHandle method handle}
39.64 - * that gives the behavior of the call site.
39.65 - * <p>
39.66 - * Each {@code invokedynamic} instruction statically specifies its own
39.67 - * bootstrap method as a constant pool reference.
39.68 - * The constant pool reference also specifies the call site's name and type descriptor,
39.69 - * just like {@code invokevirtual} and the other invoke instructions.
39.70 - * <p>
39.71 - * Linking starts with resolving the constant pool entry for the
39.72 - * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
39.73 - * the type descriptor of the dynamic call site.
39.74 - * This resolution process may trigger class loading.
39.75 - * It may therefore throw an error if a class fails to load.
39.76 - * This error becomes the abnormal termination of the dynamic
39.77 - * call site execution.
39.78 - * Linkage does not trigger class initialization.
39.79 - * <p>
39.80 - * The bootstrap method is invoked on at least three values:
39.81 - * <ul>
39.82 - * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em> in which dynamic call site occurs </li>
39.83 - * <li>a {@code String}, the method name mentioned in the call site </li>
39.84 - * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
39.85 - * <li>optionally, between 1 and 251 additional static arguments taken from the constant pool </li>
39.86 - * </ul>
39.87 - * Invocation is as if by
39.88 - * {@link java.lang.invoke.MethodHandle#invoke MethodHandle.invoke}.
39.89 - * The returned result must be a {@link java.lang.invoke.CallSite CallSite} (or a subclass).
39.90 - * The type of the call site's target must be exactly equal to the type
39.91 - * derived from the dynamic call site's type descriptor and passed to
39.92 - * the bootstrap method.
39.93 - * The call site then becomes permanently linked to the dynamic call site.
39.94 - * <p>
39.95 - * As documented in the JVM specification, all failures arising from
39.96 - * the linkage of a dynamic call site are reported
39.97 - * by a {@link java.lang.BootstrapMethodError BootstrapMethodError},
39.98 - * which is thrown as the abnormal termination of the dynamic call
39.99 - * site execution.
39.100 - * If this happens, the same error will the thrown for all subsequent
39.101 - * attempts to execute the dynamic call site.
39.102 - *
39.103 - * <h2>timing of linkage</h2>
39.104 - * A dynamic call site is linked just before its first execution.
39.105 - * The bootstrap method call implementing the linkage occurs within
39.106 - * a thread that is attempting a first execution.
39.107 - * <p>
39.108 - * If there are several such threads, the bootstrap method may be
39.109 - * invoked in several threads concurrently.
39.110 - * Therefore, bootstrap methods which access global application
39.111 - * data must take the usual precautions against race conditions.
39.112 - * In any case, every {@code invokedynamic} instruction is either
39.113 - * unlinked or linked to a unique {@code CallSite} object.
39.114 - * <p>
39.115 - * In an application which requires dynamic call sites with individually
39.116 - * mutable behaviors, their bootstrap methods should produce distinct
39.117 - * {@link java.lang.invoke.CallSite CallSite} objects, one for each linkage request.
39.118 - * Alternatively, an application can link a single {@code CallSite} object
39.119 - * to several {@code invokedynamic} instructions, in which case
39.120 - * a change to the target method will become visible at each of
39.121 - * the instructions.
39.122 - * <p>
39.123 - * If several threads simultaneously execute a bootstrap method for a single dynamic
39.124 - * call site, the JVM must choose one {@code CallSite} object and install it visibly to
39.125 - * all threads. Any other bootstrap method calls are allowed to complete, but their
39.126 - * results are ignored, and their dynamic call site invocations proceed with the originally
39.127 - * chosen target object.
39.128 -
39.129 - * <p style="font-size:smaller;">
39.130 - * <em>Discussion:</em>
39.131 - * These rules do not enable the JVM to duplicate dynamic call sites,
39.132 - * or to issue “causeless” bootstrap method calls.
39.133 - * Every dynamic call site transitions at most once from unlinked to linked,
39.134 - * just before its first invocation.
39.135 - * There is no way to undo the effect of a completed bootstrap method call.
39.136 - *
39.137 - * <h2>types of bootstrap methods</h2>
39.138 - * As long as each bootstrap method can be correctly invoked
39.139 - * by {@code MethodHandle.invoke}, its detailed type is arbitrary.
39.140 - * For example, the first argument could be {@code Object}
39.141 - * instead of {@code MethodHandles.Lookup}, and the return type
39.142 - * could also be {@code Object} instead of {@code CallSite}.
39.143 - * (Note that the types and number of the stacked arguments limit
39.144 - * the legal kinds of bootstrap methods to appropriately typed
39.145 - * static methods and constructors of {@code CallSite} subclasses.)
39.146 - * <p>
39.147 - * If a given {@code invokedynamic} instruction specifies no static arguments,
39.148 - * the instruction's bootstrap method will be invoked on three arguments,
39.149 - * conveying the instruction's caller class, name, and method type.
39.150 - * If the {@code invokedynamic} instruction specifies one or more static arguments,
39.151 - * those values will be passed as additional arguments to the method handle.
39.152 - * (Note that because there is a limit of 255 arguments to any method,
39.153 - * at most 251 extra arguments can be supplied, since the bootstrap method
39.154 - * handle itself and its first three arguments must also be stacked.)
39.155 - * The bootstrap method will be invoked as if by either {@code MethodHandle.invoke}
39.156 - * or {@code invokeWithArguments}. (There is no way to tell the difference.)
39.157 - * <p>
39.158 - * The normal argument conversion rules for {@code MethodHandle.invoke} apply to all stacked arguments.
39.159 - * For example, if a pushed value is a primitive type, it may be converted to a reference by boxing conversion.
39.160 - * If the bootstrap method is a variable arity method (its modifier bit {@code 0x0080} is set),
39.161 - * then some or all of the arguments specified here may be collected into a trailing array parameter.
39.162 - * (This is not a special rule, but rather a useful consequence of the interaction
39.163 - * between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
39.164 - * and the {@link java.lang.invoke.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
39.165 - * <p>
39.166 - * Given these rules, here are examples of legal bootstrap method declarations,
39.167 - * given various numbers {@code N} of extra arguments.
39.168 - * The first rows (marked {@code *}) will work for any number of extra arguments.
39.169 - * <table border=1 cellpadding=5 summary="Static argument types">
39.170 - * <tr><th>N</th><th>sample bootstrap method</th></tr>
39.171 - * <tr><td>*</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
39.172 - * <tr><td>*</td><td><code>CallSite bootstrap(Object... args)</code></td></tr>
39.173 - * <tr><td>*</td><td><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code></td></tr>
39.174 - * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type)</code></td></tr>
39.175 - * <tr><td>0</td><td><code>CallSite bootstrap(Lookup caller, Object... nameAndType)</code></td></tr>
39.176 - * <tr><td>1</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object arg)</code></td></tr>
39.177 - * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code></td></tr>
39.178 - * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String... args)</code></td></tr>
39.179 - * <tr><td>2</td><td><code>CallSite bootstrap(Lookup caller, String name, MethodType type, String x, int y)</code></td></tr>
39.180 - * </table>
39.181 - * The last example assumes that the extra arguments are of type
39.182 - * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
39.183 - * The second-to-last example assumes that all extra arguments are of type
39.184 - * {@code CONSTANT_String}.
39.185 - * The other examples work with all types of extra arguments.
39.186 - * <p>
39.187 - * As noted above, the actual method type of the bootstrap method can vary.
39.188 - * For example, the fourth argument could be {@code MethodHandle},
39.189 - * if that is the type of the corresponding constant in
39.190 - * the {@code CONSTANT_InvokeDynamic} entry.
39.191 - * In that case, the {@code MethodHandle.invoke} call will pass the extra method handle
39.192 - * constant as an {@code Object}, but the type matching machinery of {@code MethodHandle.invoke}
39.193 - * will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
39.194 - * (If a string constant were passed instead, by badly generated code, that cast would then fail,
39.195 - * resulting in a {@code BootstrapMethodError}.)
39.196 - * <p>
39.197 - * Note that, as a consequence of the above rules, the bootstrap method may accept a primitive
39.198 - * argument, if it can be represented by a constant pool entry.
39.199 - * However, arguments of type {@code boolean}, {@code byte}, {@code short}, or {@code char}
39.200 - * cannot be created for bootstrap methods, since such constants cannot be directly
39.201 - * represented in the constant pool, and the invocation of the bootstrap method will
39.202 - * not perform the necessary narrowing primitive conversions.
39.203 - * <p>
39.204 - * Extra bootstrap method arguments are intended to allow language implementors
39.205 - * to safely and compactly encode metadata.
39.206 - * In principle, the name and extra arguments are redundant,
39.207 - * since each call site could be given its own unique bootstrap method.
39.208 - * Such a practice is likely to produce large class files and constant pools.
39.209 - *
39.210 - * @author John Rose, JSR 292 EG
39.211 - * @since 1.7
39.212 - */
39.213 -
39.214 -package java.lang.invoke;
40.1 --- a/rt/emul/compact/src/main/java/sun/invoke/WrapperInstance.java Sun Aug 17 20:09:05 2014 +0200
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,48 +0,0 @@
40.4 -/*
40.5 - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
40.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
40.7 - *
40.8 - * This code is free software; you can redistribute it and/or modify it
40.9 - * under the terms of the GNU General Public License version 2 only, as
40.10 - * published by the Free Software Foundation. Oracle designates this
40.11 - * particular file as subject to the "Classpath" exception as provided
40.12 - * by Oracle in the LICENSE file that accompanied this code.
40.13 - *
40.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
40.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40.17 - * version 2 for more details (a copy is included in the LICENSE file that
40.18 - * accompanied this code).
40.19 - *
40.20 - * You should have received a copy of the GNU General Public License version
40.21 - * 2 along with this work; if not, write to the Free Software Foundation,
40.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
40.23 - *
40.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
40.25 - * or visit www.oracle.com if you need additional information or have any
40.26 - * questions.
40.27 - */
40.28 -
40.29 -package sun.invoke;
40.30 -
40.31 -import java.lang.invoke.MethodHandle;
40.32 -
40.33 -/**
40.34 - * Private API used inside of java.lang.invoke.MethodHandles.
40.35 - * Interface implemented by every object which is produced by
40.36 - * {@link java.lang.invoke.MethodHandleProxies#asInterfaceInstance MethodHandleProxies.asInterfaceInstance}.
40.37 - * The methods of this interface allow a caller to recover the parameters
40.38 - * to {@code asInstance}.
40.39 - * This allows applications to repeatedly convert between method handles
40.40 - * and SAM objects, without the risk of creating unbounded delegation chains.
40.41 - */
40.42 -public interface WrapperInstance {
40.43 - /** Produce or recover a target method handle which is behaviorally
40.44 - * equivalent to the SAM method of this object.
40.45 - */
40.46 - public MethodHandle getWrapperInstanceTarget();
40.47 - /** Recover the SAM type for which this object was created.
40.48 - */
40.49 - public Class<?> getWrapperInstanceType();
40.50 -}
40.51 -
41.1 --- a/rt/emul/compact/src/main/java/sun/invoke/empty/Empty.java Sun Aug 17 20:09:05 2014 +0200
41.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
41.3 @@ -1,40 +0,0 @@
41.4 -/*
41.5 - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
41.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41.7 - *
41.8 - * This code is free software; you can redistribute it and/or modify it
41.9 - * under the terms of the GNU General Public License version 2 only, as
41.10 - * published by the Free Software Foundation. Oracle designates this
41.11 - * particular file as subject to the "Classpath" exception as provided
41.12 - * by Oracle in the LICENSE file that accompanied this code.
41.13 - *
41.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
41.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
41.17 - * version 2 for more details (a copy is included in the LICENSE file that
41.18 - * accompanied this code).
41.19 - *
41.20 - * You should have received a copy of the GNU General Public License version
41.21 - * 2 along with this work; if not, write to the Free Software Foundation,
41.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
41.23 - *
41.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
41.25 - * or visit www.oracle.com if you need additional information or have any
41.26 - * questions.
41.27 - */
41.28 -
41.29 -package sun.invoke.empty;
41.30 -
41.31 -/**
41.32 - * An empty class in an empty package.
41.33 - * Used as a proxy for unprivileged code, since making access checks
41.34 - * against it will only succeed against public methods in public types.
41.35 - * <p>
41.36 - * This class also stands (internally to sun.invoke) for the type of a
41.37 - * value that cannot be produced, because the expression of this type
41.38 - * always returns abnormally. (Cf. Nothing in the closures proposal.)
41.39 - * @author jrose
41.40 - */
41.41 -public class Empty {
41.42 - private Empty() { throw new InternalError(); }
41.43 -}
42.1 --- a/rt/emul/compact/src/main/java/sun/invoke/package-info.java Sun Aug 17 20:09:05 2014 +0200
42.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
42.3 @@ -1,31 +0,0 @@
42.4 -/*
42.5 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
42.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42.7 - *
42.8 - * This code is free software; you can redistribute it and/or modify it
42.9 - * under the terms of the GNU General Public License version 2 only, as
42.10 - * published by the Free Software Foundation. Oracle designates this
42.11 - * particular file as subject to the "Classpath" exception as provided
42.12 - * by Oracle in the LICENSE file that accompanied this code.
42.13 - *
42.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
42.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42.17 - * version 2 for more details (a copy is included in the LICENSE file that
42.18 - * accompanied this code).
42.19 - *
42.20 - * You should have received a copy of the GNU General Public License version
42.21 - * 2 along with this work; if not, write to the Free Software Foundation,
42.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
42.23 - *
42.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
42.25 - * or visit www.oracle.com if you need additional information or have any
42.26 - * questions.
42.27 - */
42.28 -
42.29 -/**
42.30 - * Implementation details for JSR 292 RI, package java.lang.invoke.
42.31 - * @author jrose
42.32 - */
42.33 -
42.34 -package sun.invoke;
43.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/BytecodeDescriptor.java Sun Aug 17 20:09:05 2014 +0200
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,137 +0,0 @@
43.4 -/*
43.5 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
43.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
43.7 - *
43.8 - * This code is free software; you can redistribute it and/or modify it
43.9 - * under the terms of the GNU General Public License version 2 only, as
43.10 - * published by the Free Software Foundation. Oracle designates this
43.11 - * particular file as subject to the "Classpath" exception as provided
43.12 - * by Oracle in the LICENSE file that accompanied this code.
43.13 - *
43.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
43.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43.17 - * version 2 for more details (a copy is included in the LICENSE file that
43.18 - * accompanied this code).
43.19 - *
43.20 - * You should have received a copy of the GNU General Public License version
43.21 - * 2 along with this work; if not, write to the Free Software Foundation,
43.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
43.23 - *
43.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
43.25 - * or visit www.oracle.com if you need additional information or have any
43.26 - * questions.
43.27 - */
43.28 -
43.29 -package sun.invoke.util;
43.30 -
43.31 -import java.lang.invoke.MethodType;
43.32 -import java.util.ArrayList;
43.33 -import java.util.List;
43.34 -
43.35 -/**
43.36 - * Utility routines for dealing with bytecode-level signatures.
43.37 - * @author jrose
43.38 - */
43.39 -public class BytecodeDescriptor {
43.40 -
43.41 - private BytecodeDescriptor() { } // cannot instantiate
43.42 -
43.43 - public static List<Class<?>> parseMethod(String bytecodeSignature, ClassLoader loader) {
43.44 - return parseMethod(bytecodeSignature, 0, bytecodeSignature.length(), loader);
43.45 - }
43.46 -
43.47 - static List<Class<?>> parseMethod(String bytecodeSignature,
43.48 - int start, int end, ClassLoader loader) {
43.49 - if (loader == null)
43.50 - loader = ClassLoader.getSystemClassLoader();
43.51 - String str = bytecodeSignature;
43.52 - int[] i = {start};
43.53 - ArrayList<Class<?>> ptypes = new ArrayList<Class<?>>();
43.54 - if (i[0] < end && str.charAt(i[0]) == '(') {
43.55 - ++i[0]; // skip '('
43.56 - while (i[0] < end && str.charAt(i[0]) != ')') {
43.57 - Class<?> pt = parseSig(str, i, end, loader);
43.58 - if (pt == null || pt == void.class)
43.59 - parseError(str, "bad argument type");
43.60 - ptypes.add(pt);
43.61 - }
43.62 - ++i[0]; // skip ')'
43.63 - } else {
43.64 - parseError(str, "not a method type");
43.65 - }
43.66 - Class<?> rtype = parseSig(str, i, end, loader);
43.67 - if (rtype == null || i[0] != end)
43.68 - parseError(str, "bad return type");
43.69 - ptypes.add(rtype);
43.70 - return ptypes;
43.71 - }
43.72 -
43.73 - static private void parseError(String str, String msg) {
43.74 - throw new IllegalArgumentException("bad signature: "+str+": "+msg);
43.75 - }
43.76 -
43.77 - static private Class<?> parseSig(String str, int[] i, int end, ClassLoader loader) {
43.78 - if (i[0] == end) return null;
43.79 - char c = str.charAt(i[0]++);
43.80 - if (c == 'L') {
43.81 - int begc = i[0], endc = str.indexOf(';', begc);
43.82 - if (endc < 0) return null;
43.83 - i[0] = endc+1;
43.84 - String name = str.substring(begc, endc).replace('/', '.');
43.85 - try {
43.86 - return loader.loadClass(name);
43.87 - } catch (ClassNotFoundException ex) {
43.88 - throw new TypeNotPresentException(name, ex);
43.89 - }
43.90 - } else if (c == '[') {
43.91 - Class<?> t = parseSig(str, i, end, loader);
43.92 - if (t != null)
43.93 - t = java.lang.reflect.Array.newInstance(t, 0).getClass();
43.94 - return t;
43.95 - } else {
43.96 - return Wrapper.forBasicType(c).primitiveType();
43.97 - }
43.98 - }
43.99 -
43.100 - public static String unparse(Class<?> type) {
43.101 - StringBuilder sb = new StringBuilder();
43.102 - unparseSig(type, sb);
43.103 - return sb.toString();
43.104 - }
43.105 -
43.106 - public static String unparse(MethodType type) {
43.107 - return unparseMethod(type.returnType(), type.parameterList());
43.108 - }
43.109 -
43.110 - public static String unparse(Object type) {
43.111 - if (type instanceof Class<?>)
43.112 - return unparse((Class<?>) type);
43.113 - if (type instanceof MethodType)
43.114 - return unparse((MethodType) type);
43.115 - return (String) type;
43.116 - }
43.117 -
43.118 - public static String unparseMethod(Class<?> rtype, List<Class<?>> ptypes) {
43.119 - StringBuilder sb = new StringBuilder();
43.120 - sb.append('(');
43.121 - for (Class<?> pt : ptypes)
43.122 - unparseSig(pt, sb);
43.123 - sb.append(')');
43.124 - unparseSig(rtype, sb);
43.125 - return sb.toString();
43.126 - }
43.127 -
43.128 - static private void unparseSig(Class<?> t, StringBuilder sb) {
43.129 - char c = Wrapper.forBasicType(t).basicTypeChar();
43.130 - if (c != 'L') {
43.131 - sb.append(c);
43.132 - } else {
43.133 - boolean lsemi = (!t.isArray());
43.134 - if (lsemi) sb.append('L');
43.135 - sb.append(t.getName().replace('.', '/'));
43.136 - if (lsemi) sb.append(';');
43.137 - }
43.138 - }
43.139 -
43.140 -}
44.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/BytecodeName.java Sun Aug 17 20:09:05 2014 +0200
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,627 +0,0 @@
44.4 -/*
44.5 - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
44.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44.7 - *
44.8 - * This code is free software; you can redistribute it and/or modify it
44.9 - * under the terms of the GNU General Public License version 2 only, as
44.10 - * published by the Free Software Foundation. Oracle designates this
44.11 - * particular file as subject to the "Classpath" exception as provided
44.12 - * by Oracle in the LICENSE file that accompanied this code.
44.13 - *
44.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
44.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
44.17 - * version 2 for more details (a copy is included in the LICENSE file that
44.18 - * accompanied this code).
44.19 - *
44.20 - * You should have received a copy of the GNU General Public License version
44.21 - * 2 along with this work; if not, write to the Free Software Foundation,
44.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
44.23 - *
44.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
44.25 - * or visit www.oracle.com if you need additional information or have any
44.26 - * questions.
44.27 - */
44.28 -
44.29 -package sun.invoke.util;
44.30 -
44.31 -/**
44.32 - * Utility routines for dealing with bytecode-level names.
44.33 - * Includes universal mangling rules for the JVM.
44.34 - *
44.35 - * <h3>Avoiding Dangerous Characters </h3>
44.36 - *
44.37 - * <p>
44.38 - * The JVM defines a very small set of characters which are illegal
44.39 - * in name spellings. We will slightly extend and regularize this set
44.40 - * into a group of <cite>dangerous characters</cite>.
44.41 - * These characters will then be replaced, in mangled names, by escape sequences.
44.42 - * In addition, accidental escape sequences must be further escaped.
44.43 - * Finally, a special prefix will be applied if and only if
44.44 - * the mangling would otherwise fail to begin with the escape character.
44.45 - * This happens to cover the corner case of the null string,
44.46 - * and also clearly marks symbols which need demangling.
44.47 - * </p>
44.48 - * <p>
44.49 - * Dangerous characters are the union of all characters forbidden
44.50 - * or otherwise restricted by the JVM specification,
44.51 - * plus their mates, if they are brackets
44.52 - * (<code><big><b>[</b></big></code> and <code><big><b>]</b></big></code>,
44.53 - * <code><big><b><</b></big></code> and <code><big><b>></b></big></code>),
44.54 - * plus, arbitrarily, the colon character <code><big><b>:</b></big></code>.
44.55 - * There is no distinction between type, method, and field names.
44.56 - * This makes it easier to convert between mangled names of different
44.57 - * types, since they do not need to be decoded (demangled).
44.58 - * </p>
44.59 - * <p>
44.60 - * The escape character is backslash <code><big><b>\</b></big></code>
44.61 - * (also known as reverse solidus).
44.62 - * This character is, until now, unheard of in bytecode names,
44.63 - * but traditional in the proposed role.
44.64 - *
44.65 - * </p>
44.66 - * <h3> Replacement Characters </h3>
44.67 - *
44.68 - *
44.69 - * <p>
44.70 - * Every escape sequence is two characters
44.71 - * (in fact, two UTF8 bytes) beginning with
44.72 - * the escape character and followed by a
44.73 - * <cite>replacement character</cite>.
44.74 - * (Since the replacement character is never a backslash,
44.75 - * iterated manglings do not double in size.)
44.76 - * </p>
44.77 - * <p>
44.78 - * Each dangerous character has some rough visual similarity
44.79 - * to its corresponding replacement character.
44.80 - * This makes mangled symbols easier to recognize by sight.
44.81 - * </p>
44.82 - * <p>
44.83 - * The dangerous characters are
44.84 - * <code><big><b>/</b></big></code> (forward slash, used to delimit package components),
44.85 - * <code><big><b>.</b></big></code> (dot, also a package delimiter),
44.86 - * <code><big><b>;</b></big></code> (semicolon, used in signatures),
44.87 - * <code><big><b>$</b></big></code> (dollar, used in inner classes and synthetic members),
44.88 - * <code><big><b><</b></big></code> (left angle),
44.89 - * <code><big><b>></b></big></code> (right angle),
44.90 - * <code><big><b>[</b></big></code> (left square bracket, used in array types),
44.91 - * <code><big><b>]</b></big></code> (right square bracket, reserved in this scheme for language use),
44.92 - * and <code><big><b>:</b></big></code> (colon, reserved in this scheme for language use).
44.93 - * Their replacements are, respectively,
44.94 - * <code><big><b>|</b></big></code> (vertical bar),
44.95 - * <code><big><b>,</b></big></code> (comma),
44.96 - * <code><big><b>?</b></big></code> (question mark),
44.97 - * <code><big><b>%</b></big></code> (percent),
44.98 - * <code><big><b>^</b></big></code> (caret),
44.99 - * <code><big><b>_</b></big></code> (underscore), and
44.100 - * <code><big><b>{</b></big></code> (left curly bracket),
44.101 - * <code><big><b>}</b></big></code> (right curly bracket),
44.102 - * <code><big><b>!</b></big></code> (exclamation mark).
44.103 - * In addition, the replacement character for the escape character itself is
44.104 - * <code><big><b>-</b></big></code> (hyphen),
44.105 - * and the replacement character for the null prefix is
44.106 - * <code><big><b>=</b></big></code> (equal sign).
44.107 - * </p>
44.108 - * <p>
44.109 - * An escape character <code><big><b>\</b></big></code>
44.110 - * followed by any of these replacement characters
44.111 - * is an escape sequence, and there are no other escape sequences.
44.112 - * An equal sign is only part of an escape sequence
44.113 - * if it is the second character in the whole string, following a backslash.
44.114 - * Two consecutive backslashes do <em>not</em> form an escape sequence.
44.115 - * </p>
44.116 - * <p>
44.117 - * Each escape sequence replaces a so-called <cite>original character</cite>
44.118 - * which is either one of the dangerous characters or the escape character.
44.119 - * A null prefix replaces an initial null string, not a character.
44.120 - * </p>
44.121 - * <p>
44.122 - * All this implies that escape sequences cannot overlap and may be
44.123 - * determined all at once for a whole string. Note that a spelling
44.124 - * string can contain <cite>accidental escapes</cite>, apparent escape
44.125 - * sequences which must not be interpreted as manglings.
44.126 - * These are disabled by replacing their leading backslash with an
44.127 - * escape sequence (<code><big><b>\-</b></big></code>). To mangle a string, three logical steps
44.128 - * are required, though they may be carried out in one pass:
44.129 - * </p>
44.130 - * <ol>
44.131 - * <li>In each accidental escape, replace the backslash with an escape sequence
44.132 - * (<code><big><b>\-</b></big></code>).</li>
44.133 - * <li>Replace each dangerous character with an escape sequence
44.134 - * (<code><big><b>\|</b></big></code> for <code><big><b>/</b></big></code>, etc.).</li>
44.135 - * <li>If the first two steps introduced any change, <em>and</em>
44.136 - * if the string does not already begin with a backslash, prepend a null prefix (<code><big><b>\=</b></big></code>).</li>
44.137 - * </ol>
44.138 - *
44.139 - * To demangle a mangled string that begins with an escape,
44.140 - * remove any null prefix, and then replace (in parallel)
44.141 - * each escape sequence by its original character.
44.142 - * <p>Spelling strings which contain accidental
44.143 - * escapes <em>must</em> have them replaced, even if those
44.144 - * strings do not contain dangerous characters.
44.145 - * This restriction means that mangling a string always
44.146 - * requires a scan of the string for escapes.
44.147 - * But then, a scan would be required anyway,
44.148 - * to check for dangerous characters.
44.149 - *
44.150 - * </p>
44.151 - * <h3> Nice Properties </h3>
44.152 - *
44.153 - * <p>
44.154 - * If a bytecode name does not contain any escape sequence,
44.155 - * demangling is a no-op: The string demangles to itself.
44.156 - * Such a string is called <cite>self-mangling</cite>.
44.157 - * Almost all strings are self-mangling.
44.158 - * In practice, to demangle almost any name “found in nature”,
44.159 - * simply verify that it does not begin with a backslash.
44.160 - * </p>
44.161 - * <p>
44.162 - * Mangling is a one-to-one function, while demangling
44.163 - * is a many-to-one function.
44.164 - * A mangled string is defined as <cite>validly mangled</cite> if
44.165 - * it is in fact the unique mangling of its spelling string.
44.166 - * Three examples of invalidly mangled strings are <code><big><b>\=foo</b></big></code>,
44.167 - * <code><big><b>\-bar</b></big></code>, and <code><big><b>baz\!</b></big></code>, which demangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and
44.168 - * <code><big><b>baz\!</b></big></code>, but then remangle to <code><big><b>foo</b></big></code>, <code><big><b>\bar</b></big></code>, and <code><big><b>\=baz\-!</b></big></code>.
44.169 - * If a language back-end or runtime is using mangled names,
44.170 - * it should never present an invalidly mangled bytecode
44.171 - * name to the JVM. If the runtime encounters one,
44.172 - * it should also report an error, since such an occurrence
44.173 - * probably indicates a bug in name encoding which
44.174 - * will lead to errors in linkage.
44.175 - * However, this note does not propose that the JVM verifier
44.176 - * detect invalidly mangled names.
44.177 - * </p>
44.178 - * <p>
44.179 - * As a result of these rules, it is a simple matter to
44.180 - * compute validly mangled substrings and concatenations
44.181 - * of validly mangled strings, and (with a little care)
44.182 - * these correspond to corresponding operations on their
44.183 - * spelling strings.
44.184 - * </p>
44.185 - * <ul>
44.186 - * <li>Any prefix of a validly mangled string is also validly mangled,
44.187 - * although a null prefix may need to be removed.</li>
44.188 - * <li>Any suffix of a validly mangled string is also validly mangled,
44.189 - * although a null prefix may need to be added.</li>
44.190 - * <li>Two validly mangled strings, when concatenated,
44.191 - * are also validly mangled, although any null prefix
44.192 - * must be removed from the second string,
44.193 - * and a trailing backslash on the first string may need escaping,
44.194 - * if it would participate in an accidental escape when followed
44.195 - * by the first character of the second string.</li>
44.196 - * </ul>
44.197 - * <p>If languages that include non-Java symbol spellings use this
44.198 - * mangling convention, they will enjoy the following advantages:
44.199 - * </p>
44.200 - * <ul>
44.201 - * <li>They can interoperate via symbols they share in common.</li>
44.202 - * <li>Low-level tools, such as backtrace printers, will have readable displays.</li>
44.203 - * <li>Future JVM and language extensions can safely use the dangerous characters
44.204 - * for structuring symbols, but will never interfere with valid spellings.</li>
44.205 - * <li>Runtimes and compilers can use standard libraries for mangling and demangling.</li>
44.206 - * <li>Occasional transliterations and name composition will be simple and regular,
44.207 - * for classes, methods, and fields.</li>
44.208 - * <li>Bytecode names will continue to be compact.
44.209 - * When mangled, spellings will at most double in length, either in
44.210 - * UTF8 or UTF16 format, and most will not change at all.</li>
44.211 - * </ul>
44.212 - *
44.213 - *
44.214 - * <h3> Suggestions for Human Readable Presentations </h3>
44.215 - *
44.216 - *
44.217 - * <p>
44.218 - * For human readable displays of symbols,
44.219 - * it will be better to present a string-like quoted
44.220 - * representation of the spelling, because JVM users
44.221 - * are generally familiar with such tokens.
44.222 - * We suggest using single or double quotes before and after
44.223 - * mangled symbols which are not valid Java identifiers,
44.224 - * with quotes, backslashes, and non-printing characters
44.225 - * escaped as if for literals in the Java language.
44.226 - * </p>
44.227 - * <p>
44.228 - * For example, an HTML-like spelling
44.229 - * <code><big><b><pre></b></big></code> mangles to
44.230 - * <code><big><b>\^pre\_</b></big></code> and could
44.231 - * display more cleanly as
44.232 - * <code><big><b>'<pre>'</b></big></code>,
44.233 - * with the quotes included.
44.234 - * Such string-like conventions are <em>not</em> suitable
44.235 - * for mangled bytecode names, in part because
44.236 - * dangerous characters must be eliminated, rather
44.237 - * than just quoted. Otherwise internally structured
44.238 - * strings like package prefixes and method signatures
44.239 - * could not be reliably parsed.
44.240 - * </p>
44.241 - * <p>
44.242 - * In such human-readable displays, invalidly mangled
44.243 - * names should <em>not</em> be demangled and quoted,
44.244 - * for this would be misleading. Likewise, JVM symbols
44.245 - * which contain dangerous characters (like dots in field
44.246 - * names or brackets in method names) should not be
44.247 - * simply quoted. The bytecode names
44.248 - * <code><big><b>\=phase\,1</b></big></code> and
44.249 - * <code><big><b>phase.1</b></big></code> are distinct,
44.250 - * and in demangled displays they should be presented as
44.251 - * <code><big><b>'phase.1'</b></big></code> and something like
44.252 - * <code><big><b>'phase'.1</b></big></code>, respectively.
44.253 - * </p>
44.254 - *
44.255 - * @author John Rose
44.256 - * @version 1.2, 02/06/2008
44.257 - * @see http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
44.258 - */
44.259 -public class BytecodeName {
44.260 - private BytecodeName() { } // static only class
44.261 -
44.262 - /** Given a source name, produce the corresponding bytecode name.
44.263 - * The source name should not be qualified, because any syntactic
44.264 - * markers (dots, slashes, dollar signs, colons, etc.) will be mangled.
44.265 - * @param s the source name
44.266 - * @return a valid bytecode name which represents the source name
44.267 - */
44.268 - public static String toBytecodeName(String s) {
44.269 - String bn = mangle(s);
44.270 - assert((Object)bn == s || looksMangled(bn)) : bn;
44.271 - assert(s.equals(toSourceName(bn))) : s;
44.272 - return bn;
44.273 - }
44.274 -
44.275 - /** Given an unqualified bytecode name, produce the corresponding source name.
44.276 - * The bytecode name must not contain dangerous characters.
44.277 - * In particular, it must not be qualified or segmented by colon {@code ':'}.
44.278 - * @param s the bytecode name
44.279 - * @return the source name, which may possibly have unsafe characters
44.280 - * @throws IllegalArgumentException if the bytecode name is not {@link #isSafeBytecodeName safe}
44.281 - * @see #isSafeBytecodeName(java.lang.String)
44.282 - */
44.283 - public static String toSourceName(String s) {
44.284 - checkSafeBytecodeName(s);
44.285 - String sn = s;
44.286 - if (looksMangled(s)) {
44.287 - sn = demangle(s);
44.288 - assert(s.equals(mangle(sn))) : s+" => "+sn+" => "+mangle(sn);
44.289 - }
44.290 - return sn;
44.291 - }
44.292 -
44.293 - /**
44.294 - * Given a bytecode name from a classfile, separate it into
44.295 - * components delimited by dangerous characters.
44.296 - * Each resulting array element will be either a dangerous character,
44.297 - * or else a safe bytecode name.
44.298 - * (The safe name might possibly be mangled to hide further dangerous characters.)
44.299 - * For example, the qualified class name {@code java/lang/String}
44.300 - * will be parsed into the array {@code {"java", '/', "lang", '/', "String"}}.
44.301 - * The name {@code <init>} will be parsed into { '<', "init", '>'}}
44.302 - * The name {@code foo/bar$:baz} will be parsed into
44.303 - * {@code {"foo", '/', "bar", '$', ':', "baz"}}.
44.304 - * The name {@code ::\=:foo:\=bar\!baz} will be parsed into
44.305 - * {@code {':', ':', "", ':', "foo", ':', "bar:baz"}}.
44.306 - */
44.307 - public static Object[] parseBytecodeName(String s) {
44.308 - int slen = s.length();
44.309 - Object[] res = null;
44.310 - for (int pass = 0; pass <= 1; pass++) {
44.311 - int fillp = 0;
44.312 - int lasti = 0;
44.313 - for (int i = 0; i <= slen; i++) {
44.314 - int whichDC = -1;
44.315 - if (i < slen) {
44.316 - whichDC = DANGEROUS_CHARS.indexOf(s.charAt(i));
44.317 - if (whichDC < DANGEROUS_CHAR_FIRST_INDEX) continue;
44.318 - }
44.319 - // got to end of string or next dangerous char
44.320 - if (lasti < i) {
44.321 - // normal component
44.322 - if (pass != 0)
44.323 - res[fillp] = toSourceName(s.substring(lasti, i));
44.324 - fillp++;
44.325 - lasti = i+1;
44.326 - }
44.327 - if (whichDC >= DANGEROUS_CHAR_FIRST_INDEX) {
44.328 - if (pass != 0)
44.329 - res[fillp] = DANGEROUS_CHARS_CA[whichDC];
44.330 - fillp++;
44.331 - lasti = i+1;
44.332 - }
44.333 - }
44.334 - if (pass != 0) break;
44.335 - // between passes, build the result array
44.336 - res = new Object[fillp];
44.337 - if (fillp <= 1 && lasti == 0) {
44.338 - if (fillp != 0) res[0] = toSourceName(s);
44.339 - break;
44.340 - }
44.341 - }
44.342 - return res;
44.343 - }
44.344 -
44.345 - /**
44.346 - * Given a series of components, create a bytecode name for a classfile.
44.347 - * This is the inverse of {@link #parseBytecodeName(java.lang.String)}.
44.348 - * Each component must either be an interned one-character string of
44.349 - * a dangerous character, or else a safe bytecode name.
44.350 - * @param components a series of name components
44.351 - * @return the concatenation of all components
44.352 - * @throws IllegalArgumentException if any component contains an unsafe
44.353 - * character, and is not an interned one-character string
44.354 - * @throws NullPointerException if any component is null
44.355 - */
44.356 - public static String unparseBytecodeName(Object[] components) {
44.357 - Object[] components0 = components;
44.358 - for (int i = 0; i < components.length; i++) {
44.359 - Object c = components[i];
44.360 - if (c instanceof String) {
44.361 - String mc = toBytecodeName((String) c);
44.362 - if (i == 0 && components.length == 1)
44.363 - return mc; // usual case
44.364 - if ((Object)mc != c) {
44.365 - if (components == components0)
44.366 - components = components.clone();
44.367 - components[i] = c = mc;
44.368 - }
44.369 - }
44.370 - }
44.371 - return appendAll(components);
44.372 - }
44.373 - private static String appendAll(Object[] components) {
44.374 - if (components.length <= 1) {
44.375 - if (components.length == 1) {
44.376 - return String.valueOf(components[0]);
44.377 - }
44.378 - return "";
44.379 - }
44.380 - int slen = 0;
44.381 - for (Object c : components) {
44.382 - if (c instanceof String)
44.383 - slen += String.valueOf(c).length();
44.384 - else
44.385 - slen += 1;
44.386 - }
44.387 - StringBuilder sb = new StringBuilder(slen);
44.388 - for (Object c : components) {
44.389 - sb.append(c);
44.390 - }
44.391 - return sb.toString();
44.392 - }
44.393 -
44.394 - /**
44.395 - * Given a bytecode name, produce the corresponding display name.
44.396 - * This is the source name, plus quotes if needed.
44.397 - * If the bytecode name contains dangerous characters,
44.398 - * assume that they are being used as punctuation,
44.399 - * and pass them through unchanged.
44.400 - * Non-empty runs of non-dangerous characters are demangled
44.401 - * if necessary, and the resulting names are quoted if
44.402 - * they are not already valid Java identifiers, or if
44.403 - * they contain a dangerous character (i.e., dollar sign "$").
44.404 - * Single quotes are used when quoting.
44.405 - * Within quoted names, embedded single quotes and backslashes
44.406 - * are further escaped by prepended backslashes.
44.407 - *
44.408 - * @param s the original bytecode name (which may be qualified)
44.409 - * @return a human-readable presentation
44.410 - */
44.411 - public static String toDisplayName(String s) {
44.412 - Object[] components = parseBytecodeName(s);
44.413 - for (int i = 0; i < components.length; i++) {
44.414 - if (!(components[i] instanceof String))
44.415 - continue;
44.416 - String sn = (String) components[i];
44.417 - // note that the name is already demangled!
44.418 - //sn = toSourceName(sn);
44.419 - if (!isJavaIdent(sn) || sn.indexOf('$') >=0 ) {
44.420 - components[i] = quoteDisplay(sn);
44.421 - }
44.422 - }
44.423 - return appendAll(components);
44.424 - }
44.425 - private static boolean isJavaIdent(String s) {
44.426 - int slen = s.length();
44.427 - if (slen == 0) return false;
44.428 - if (!Character.isJavaIdentifierStart(s.charAt(0)))
44.429 - return false;
44.430 - for (int i = 1; i < slen; i++) {
44.431 - if (!Character.isJavaIdentifierPart(s.charAt(i)))
44.432 - return false;
44.433 - }
44.434 - return true;
44.435 - }
44.436 - private static String quoteDisplay(String s) {
44.437 - // TO DO: Replace wierd characters in s by C-style escapes.
44.438 - return "'"+s.replaceAll("['\\\\]", "\\\\$0")+"'";
44.439 - }
44.440 -
44.441 - private static void checkSafeBytecodeName(String s)
44.442 - throws IllegalArgumentException {
44.443 - if (!isSafeBytecodeName(s)) {
44.444 - throw new IllegalArgumentException(s);
44.445 - }
44.446 - }
44.447 -
44.448 - /**
44.449 - * Report whether a simple name is safe as a bytecode name.
44.450 - * Such names are acceptable in class files as class, method, and field names.
44.451 - * Additionally, they are free of "dangerous" characters, even if those
44.452 - * characters are legal in some (or all) names in class files.
44.453 - * @param s the proposed bytecode name
44.454 - * @return true if the name is non-empty and all of its characters are safe
44.455 - */
44.456 - public static boolean isSafeBytecodeName(String s) {
44.457 - if (s.length() == 0) return false;
44.458 - // check occurrences of each DANGEROUS char
44.459 - for (char xc : DANGEROUS_CHARS_A) {
44.460 - if (xc == ESCAPE_C) continue; // not really that dangerous
44.461 - if (s.indexOf(xc) >= 0) return false;
44.462 - }
44.463 - return true;
44.464 - }
44.465 -
44.466 - /**
44.467 - * Report whether a character is safe in a bytecode name.
44.468 - * This is true of any unicode character except the following
44.469 - * <em>dangerous characters</em>: {@code ".;:$[]<>/"}.
44.470 - * @param s the proposed character
44.471 - * @return true if the character is safe to use in classfiles
44.472 - */
44.473 - public static boolean isSafeBytecodeChar(char c) {
44.474 - return DANGEROUS_CHARS.indexOf(c) < DANGEROUS_CHAR_FIRST_INDEX;
44.475 - }
44.476 -
44.477 - private static boolean looksMangled(String s) {
44.478 - return s.charAt(0) == ESCAPE_C;
44.479 - }
44.480 -
44.481 - private static String mangle(String s) {
44.482 - if (s.length() == 0)
44.483 - return NULL_ESCAPE;
44.484 -
44.485 - // build this lazily, when we first need an escape:
44.486 - StringBuilder sb = null;
44.487 -
44.488 - for (int i = 0, slen = s.length(); i < slen; i++) {
44.489 - char c = s.charAt(i);
44.490 -
44.491 - boolean needEscape = false;
44.492 - if (c == ESCAPE_C) {
44.493 - if (i+1 < slen) {
44.494 - char c1 = s.charAt(i+1);
44.495 - if ((i == 0 && c1 == NULL_ESCAPE_C)
44.496 - || c1 != originalOfReplacement(c1)) {
44.497 - // an accidental escape
44.498 - needEscape = true;
44.499 - }
44.500 - }
44.501 - } else {
44.502 - needEscape = isDangerous(c);
44.503 - }
44.504 -
44.505 - if (!needEscape) {
44.506 - if (sb != null) sb.append(c);
44.507 - continue;
44.508 - }
44.509 -
44.510 - // build sb if this is the first escape
44.511 - if (sb == null) {
44.512 - sb = new StringBuilder(s.length()+10);
44.513 - // mangled names must begin with a backslash:
44.514 - if (s.charAt(0) != ESCAPE_C && i > 0)
44.515 - sb.append(NULL_ESCAPE);
44.516 - // append the string so far, which is unremarkable:
44.517 - sb.append(s.substring(0, i));
44.518 - }
44.519 -
44.520 - // rewrite \ to \-, / to \|, etc.
44.521 - sb.append(ESCAPE_C);
44.522 - sb.append(replacementOf(c));
44.523 - }
44.524 -
44.525 - if (sb != null) return sb.toString();
44.526 -
44.527 - return s;
44.528 - }
44.529 -
44.530 - private static String demangle(String s) {
44.531 - // build this lazily, when we first meet an escape:
44.532 - StringBuilder sb = null;
44.533 -
44.534 - int stringStart = 0;
44.535 - if (s.startsWith(NULL_ESCAPE))
44.536 - stringStart = 2;
44.537 -
44.538 - for (int i = stringStart, slen = s.length(); i < slen; i++) {
44.539 - char c = s.charAt(i);
44.540 -
44.541 - if (c == ESCAPE_C && i+1 < slen) {
44.542 - // might be an escape sequence
44.543 - char rc = s.charAt(i+1);
44.544 - char oc = originalOfReplacement(rc);
44.545 - if (oc != rc) {
44.546 - // build sb if this is the first escape
44.547 - if (sb == null) {
44.548 - sb = new StringBuilder(s.length());
44.549 - // append the string so far, which is unremarkable:
44.550 - sb.append(s.substring(stringStart, i));
44.551 - }
44.552 - ++i; // skip both characters
44.553 - c = oc;
44.554 - }
44.555 - }
44.556 -
44.557 - if (sb != null)
44.558 - sb.append(c);
44.559 - }
44.560 -
44.561 - if (sb != null) return sb.toString();
44.562 -
44.563 - return s.substring(stringStart);
44.564 - }
44.565 -
44.566 - static char ESCAPE_C = '\\';
44.567 - // empty escape sequence to avoid a null name or illegal prefix
44.568 - static char NULL_ESCAPE_C = '=';
44.569 - static String NULL_ESCAPE = ESCAPE_C+""+NULL_ESCAPE_C;
44.570 -
44.571 - static final String DANGEROUS_CHARS = "\\/.;:$[]<>"; // \\ must be first
44.572 - static final String REPLACEMENT_CHARS = "-|,?!%{}^_";
44.573 - static final int DANGEROUS_CHAR_FIRST_INDEX = 1; // index after \\
44.574 - static char[] DANGEROUS_CHARS_A = DANGEROUS_CHARS.toCharArray();
44.575 - static char[] REPLACEMENT_CHARS_A = REPLACEMENT_CHARS.toCharArray();
44.576 - static final Character[] DANGEROUS_CHARS_CA;
44.577 - static {
44.578 - Character[] dcca = new Character[DANGEROUS_CHARS.length()];
44.579 - for (int i = 0; i < dcca.length; i++)
44.580 - dcca[i] = Character.valueOf(DANGEROUS_CHARS.charAt(i));
44.581 - DANGEROUS_CHARS_CA = dcca;
44.582 - }
44.583 -
44.584 - static final long[] SPECIAL_BITMAP = new long[2]; // 128 bits
44.585 - static {
44.586 - String SPECIAL = DANGEROUS_CHARS + REPLACEMENT_CHARS;
44.587 - //System.out.println("SPECIAL = "+SPECIAL);
44.588 - for (char c : SPECIAL.toCharArray()) {
44.589 - SPECIAL_BITMAP[c >>> 6] |= 1L << c;
44.590 - }
44.591 - }
44.592 - static boolean isSpecial(char c) {
44.593 - if ((c >>> 6) < SPECIAL_BITMAP.length)
44.594 - return ((SPECIAL_BITMAP[c >>> 6] >> c) & 1) != 0;
44.595 - else
44.596 - return false;
44.597 - }
44.598 - static char replacementOf(char c) {
44.599 - if (!isSpecial(c)) return c;
44.600 - int i = DANGEROUS_CHARS.indexOf(c);
44.601 - if (i < 0) return c;
44.602 - return REPLACEMENT_CHARS.charAt(i);
44.603 - }
44.604 - static char originalOfReplacement(char c) {
44.605 - if (!isSpecial(c)) return c;
44.606 - int i = REPLACEMENT_CHARS.indexOf(c);
44.607 - if (i < 0) return c;
44.608 - return DANGEROUS_CHARS.charAt(i);
44.609 - }
44.610 - static boolean isDangerous(char c) {
44.611 - if (!isSpecial(c)) return false;
44.612 - return (DANGEROUS_CHARS.indexOf(c) >= DANGEROUS_CHAR_FIRST_INDEX);
44.613 - }
44.614 - static int indexOfDangerousChar(String s, int from) {
44.615 - for (int i = from, slen = s.length(); i < slen; i++) {
44.616 - if (isDangerous(s.charAt(i)))
44.617 - return i;
44.618 - }
44.619 - return -1;
44.620 - }
44.621 - static int lastIndexOfDangerousChar(String s, int from) {
44.622 - for (int i = Math.min(from, s.length()-1); i >= 0; i--) {
44.623 - if (isDangerous(s.charAt(i)))
44.624 - return i;
44.625 - }
44.626 - return -1;
44.627 - }
44.628 -
44.629 -
44.630 -}
45.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/ValueConversions.java Sun Aug 17 20:09:05 2014 +0200
45.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
45.3 @@ -1,1188 +0,0 @@
45.4 -/*
45.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
45.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45.7 - *
45.8 - * This code is free software; you can redistribute it and/or modify it
45.9 - * under the terms of the GNU General Public License version 2 only, as
45.10 - * published by the Free Software Foundation. Oracle designates this
45.11 - * particular file as subject to the "Classpath" exception as provided
45.12 - * by Oracle in the LICENSE file that accompanied this code.
45.13 - *
45.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
45.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
45.17 - * version 2 for more details (a copy is included in the LICENSE file that
45.18 - * accompanied this code).
45.19 - *
45.20 - * You should have received a copy of the GNU General Public License version
45.21 - * 2 along with this work; if not, write to the Free Software Foundation,
45.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
45.23 - *
45.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
45.25 - * or visit www.oracle.com if you need additional information or have any
45.26 - * questions.
45.27 - */
45.28 -
45.29 -package sun.invoke.util;
45.30 -
45.31 -import java.lang.invoke.MethodHandle;
45.32 -import java.lang.invoke.MethodHandles;
45.33 -import java.lang.invoke.MethodHandles.Lookup;
45.34 -import java.lang.invoke.MethodType;
45.35 -import java.security.AccessController;
45.36 -import java.security.PrivilegedAction;
45.37 -import java.util.ArrayList;
45.38 -import java.util.Arrays;
45.39 -import java.util.Collections;
45.40 -import java.util.EnumMap;
45.41 -import java.util.List;
45.42 -
45.43 -public class ValueConversions {
45.44 - private static final Class<?> THIS_CLASS = ValueConversions.class;
45.45 - // Do not adjust this except for special platforms:
45.46 - private static final int MAX_ARITY;
45.47 - static {
45.48 - final Object[] values = { 255 };
45.49 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
45.50 - @Override
45.51 - public Void run() {
45.52 - values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255);
45.53 - return null;
45.54 - }
45.55 - });
45.56 - MAX_ARITY = (Integer) values[0];
45.57 - }
45.58 -
45.59 - private static final Lookup IMPL_LOOKUP = MethodHandles.lookup();
45.60 -
45.61 - private static EnumMap<Wrapper, MethodHandle>[] newWrapperCaches(int n) {
45.62 - @SuppressWarnings("unchecked") // generic array creation
45.63 - EnumMap<Wrapper, MethodHandle>[] caches
45.64 - = (EnumMap<Wrapper, MethodHandle>[]) new EnumMap<?,?>[n];
45.65 - for (int i = 0; i < n; i++)
45.66 - caches[i] = new EnumMap<>(Wrapper.class);
45.67 - return caches;
45.68 - }
45.69 -
45.70 - /// Converting references to values.
45.71 -
45.72 - // There are several levels of this unboxing conversions:
45.73 - // no conversions: exactly Integer.valueOf, etc.
45.74 - // implicit conversions sanctioned by JLS 5.1.2, etc.
45.75 - // explicit conversions as allowed by explicitCastArguments
45.76 -
45.77 - static int unboxInteger(Object x, boolean cast) {
45.78 - if (x instanceof Integer)
45.79 - return ((Integer) x).intValue();
45.80 - return primitiveConversion(Wrapper.INT, x, cast).intValue();
45.81 - }
45.82 -
45.83 - static byte unboxByte(Object x, boolean cast) {
45.84 - if (x instanceof Byte)
45.85 - return ((Byte) x).byteValue();
45.86 - return primitiveConversion(Wrapper.BYTE, x, cast).byteValue();
45.87 - }
45.88 -
45.89 - static short unboxShort(Object x, boolean cast) {
45.90 - if (x instanceof Short)
45.91 - return ((Short) x).shortValue();
45.92 - return primitiveConversion(Wrapper.SHORT, x, cast).shortValue();
45.93 - }
45.94 -
45.95 - static boolean unboxBoolean(Object x, boolean cast) {
45.96 - if (x instanceof Boolean)
45.97 - return ((Boolean) x).booleanValue();
45.98 - return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0;
45.99 - }
45.100 -
45.101 - static char unboxCharacter(Object x, boolean cast) {
45.102 - if (x instanceof Character)
45.103 - return ((Character) x).charValue();
45.104 - return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue();
45.105 - }
45.106 -
45.107 - static long unboxLong(Object x, boolean cast) {
45.108 - if (x instanceof Long)
45.109 - return ((Long) x).longValue();
45.110 - return primitiveConversion(Wrapper.LONG, x, cast).longValue();
45.111 - }
45.112 -
45.113 - static float unboxFloat(Object x, boolean cast) {
45.114 - if (x instanceof Float)
45.115 - return ((Float) x).floatValue();
45.116 - return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue();
45.117 - }
45.118 -
45.119 - static double unboxDouble(Object x, boolean cast) {
45.120 - if (x instanceof Double)
45.121 - return ((Double) x).doubleValue();
45.122 - return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue();
45.123 - }
45.124 -
45.125 - private static MethodType unboxType(Wrapper wrap) {
45.126 - return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class);
45.127 - }
45.128 -
45.129 - private static final EnumMap<Wrapper, MethodHandle>[]
45.130 - UNBOX_CONVERSIONS = newWrapperCaches(2);
45.131 -
45.132 - private static MethodHandle unbox(Wrapper wrap, boolean cast) {
45.133 - EnumMap<Wrapper, MethodHandle> cache = UNBOX_CONVERSIONS[(cast?1:0)];
45.134 - MethodHandle mh = cache.get(wrap);
45.135 - if (mh != null) {
45.136 - return mh;
45.137 - }
45.138 - // slow path
45.139 - switch (wrap) {
45.140 - case OBJECT:
45.141 - mh = IDENTITY; break;
45.142 - case VOID:
45.143 - mh = IGNORE; break;
45.144 - }
45.145 - if (mh != null) {
45.146 - cache.put(wrap, mh);
45.147 - return mh;
45.148 - }
45.149 - // look up the method
45.150 - String name = "unbox" + wrap.wrapperSimpleName();
45.151 - MethodType type = unboxType(wrap);
45.152 - try {
45.153 - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
45.154 - } catch (ReflectiveOperationException ex) {
45.155 - mh = null;
45.156 - }
45.157 - if (mh != null) {
45.158 - mh = MethodHandles.insertArguments(mh, 1, cast);
45.159 - cache.put(wrap, mh);
45.160 - return mh;
45.161 - }
45.162 - throw new IllegalArgumentException("cannot find unbox adapter for " + wrap
45.163 - + (cast ? " (cast)" : ""));
45.164 - }
45.165 -
45.166 - public static MethodHandle unboxCast(Wrapper type) {
45.167 - return unbox(type, true);
45.168 - }
45.169 -
45.170 - public static MethodHandle unbox(Class<?> type) {
45.171 - return unbox(Wrapper.forPrimitiveType(type), false);
45.172 - }
45.173 -
45.174 - public static MethodHandle unboxCast(Class<?> type) {
45.175 - return unbox(Wrapper.forPrimitiveType(type), true);
45.176 - }
45.177 -
45.178 - static private final Integer ZERO_INT = 0, ONE_INT = 1;
45.179 -
45.180 - /// Primitive conversions
45.181 - /**
45.182 - * Produce a Number which represents the given value {@code x}
45.183 - * according to the primitive type of the given wrapper {@code wrap}.
45.184 - * Caller must invoke intValue, byteValue, longValue (etc.) on the result
45.185 - * to retrieve the desired primitive value.
45.186 - */
45.187 - public static Number primitiveConversion(Wrapper wrap, Object x, boolean cast) {
45.188 - // Maybe merge this code with Wrapper.convert/cast.
45.189 - Number res;
45.190 - if (x == null) {
45.191 - if (!cast) return null;
45.192 - return ZERO_INT;
45.193 - }
45.194 - if (x instanceof Number) {
45.195 - res = (Number) x;
45.196 - } else if (x instanceof Boolean) {
45.197 - res = ((boolean)x ? ONE_INT : ZERO_INT);
45.198 - } else if (x instanceof Character) {
45.199 - res = (int)(char)x;
45.200 - } else {
45.201 - // this will fail with the required ClassCastException:
45.202 - res = (Number) x;
45.203 - }
45.204 - Wrapper xwrap = Wrapper.findWrapperType(x.getClass());
45.205 - if (xwrap == null || !cast && !wrap.isConvertibleFrom(xwrap))
45.206 - // this will fail with the required ClassCastException:
45.207 - return (Number) wrap.wrapperType().cast(x);
45.208 - return res;
45.209 - }
45.210 -
45.211 - /**
45.212 - * The JVM verifier allows boolean, byte, short, or char to widen to int.
45.213 - * Support exactly this conversion, from a boxed value type Boolean,
45.214 - * Byte, Short, Character, or Integer.
45.215 - */
45.216 - public static int widenSubword(Object x) {
45.217 - if (x instanceof Integer)
45.218 - return (int) x;
45.219 - else if (x instanceof Boolean)
45.220 - return fromBoolean((boolean) x);
45.221 - else if (x instanceof Character)
45.222 - return (char) x;
45.223 - else if (x instanceof Short)
45.224 - return (short) x;
45.225 - else if (x instanceof Byte)
45.226 - return (byte) x;
45.227 - else
45.228 - // Fail with a ClassCastException.
45.229 - return (int) x;
45.230 - }
45.231 -
45.232 - /// Converting primitives to references
45.233 -
45.234 - static Integer boxInteger(int x) {
45.235 - return x;
45.236 - }
45.237 -
45.238 - static Byte boxByte(byte x) {
45.239 - return x;
45.240 - }
45.241 -
45.242 - static Short boxShort(short x) {
45.243 - return x;
45.244 - }
45.245 -
45.246 - static Boolean boxBoolean(boolean x) {
45.247 - return x;
45.248 - }
45.249 -
45.250 - static Character boxCharacter(char x) {
45.251 - return x;
45.252 - }
45.253 -
45.254 - static Long boxLong(long x) {
45.255 - return x;
45.256 - }
45.257 -
45.258 - static Float boxFloat(float x) {
45.259 - return x;
45.260 - }
45.261 -
45.262 - static Double boxDouble(double x) {
45.263 - return x;
45.264 - }
45.265 -
45.266 - private static MethodType boxType(Wrapper wrap) {
45.267 - // be exact, since return casts are hard to compose
45.268 - Class<?> boxType = wrap.wrapperType();
45.269 - return MethodType.methodType(boxType, wrap.primitiveType());
45.270 - }
45.271 -
45.272 - private static final EnumMap<Wrapper, MethodHandle>[]
45.273 - BOX_CONVERSIONS = newWrapperCaches(2);
45.274 -
45.275 - private static MethodHandle box(Wrapper wrap, boolean exact) {
45.276 - EnumMap<Wrapper, MethodHandle> cache = BOX_CONVERSIONS[(exact?1:0)];
45.277 - MethodHandle mh = cache.get(wrap);
45.278 - if (mh != null) {
45.279 - return mh;
45.280 - }
45.281 - // slow path
45.282 - switch (wrap) {
45.283 - case OBJECT:
45.284 - mh = IDENTITY; break;
45.285 - case VOID:
45.286 - mh = ZERO_OBJECT;
45.287 - break;
45.288 - }
45.289 - if (mh != null) {
45.290 - cache.put(wrap, mh);
45.291 - return mh;
45.292 - }
45.293 - // look up the method
45.294 - String name = "box" + wrap.wrapperSimpleName();
45.295 - MethodType type = boxType(wrap);
45.296 - if (exact) {
45.297 - try {
45.298 - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
45.299 - } catch (ReflectiveOperationException ex) {
45.300 - mh = null;
45.301 - }
45.302 - } else {
45.303 - mh = box(wrap, !exact).asType(type.erase());
45.304 - }
45.305 - if (mh != null) {
45.306 - cache.put(wrap, mh);
45.307 - return mh;
45.308 - }
45.309 - throw new IllegalArgumentException("cannot find box adapter for "
45.310 - + wrap + (exact ? " (exact)" : ""));
45.311 - }
45.312 -
45.313 - public static MethodHandle box(Class<?> type) {
45.314 - boolean exact = false;
45.315 - // e.g., boxShort(short)Short if exact,
45.316 - // e.g., boxShort(short)Object if !exact
45.317 - return box(Wrapper.forPrimitiveType(type), exact);
45.318 - }
45.319 -
45.320 - public static MethodHandle box(Wrapper type) {
45.321 - boolean exact = false;
45.322 - return box(type, exact);
45.323 - }
45.324 -
45.325 - /// Constant functions
45.326 -
45.327 - static void ignore(Object x) {
45.328 - // no value to return; this is an unbox of null
45.329 - }
45.330 -
45.331 - static void empty() {
45.332 - }
45.333 -
45.334 - static Object zeroObject() {
45.335 - return null;
45.336 - }
45.337 -
45.338 - static int zeroInteger() {
45.339 - return 0;
45.340 - }
45.341 -
45.342 - static long zeroLong() {
45.343 - return 0;
45.344 - }
45.345 -
45.346 - static float zeroFloat() {
45.347 - return 0;
45.348 - }
45.349 -
45.350 - static double zeroDouble() {
45.351 - return 0;
45.352 - }
45.353 -
45.354 - private static final EnumMap<Wrapper, MethodHandle>[]
45.355 - CONSTANT_FUNCTIONS = newWrapperCaches(2);
45.356 -
45.357 - public static MethodHandle zeroConstantFunction(Wrapper wrap) {
45.358 - EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[0];
45.359 - MethodHandle mh = cache.get(wrap);
45.360 - if (mh != null) {
45.361 - return mh;
45.362 - }
45.363 - // slow path
45.364 - MethodType type = MethodType.methodType(wrap.primitiveType());
45.365 - switch (wrap) {
45.366 - case VOID:
45.367 - mh = EMPTY;
45.368 - break;
45.369 - case OBJECT:
45.370 - case INT: case LONG: case FLOAT: case DOUBLE:
45.371 - try {
45.372 - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type);
45.373 - } catch (ReflectiveOperationException ex) {
45.374 - mh = null;
45.375 - }
45.376 - break;
45.377 - }
45.378 - if (mh != null) {
45.379 - cache.put(wrap, mh);
45.380 - return mh;
45.381 - }
45.382 -
45.383 - // use zeroInt and cast the result
45.384 - if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) {
45.385 - mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type);
45.386 - cache.put(wrap, mh);
45.387 - return mh;
45.388 - }
45.389 - throw new IllegalArgumentException("cannot find zero constant for " + wrap);
45.390 - }
45.391 -
45.392 - /// Converting references to references.
45.393 -
45.394 - /**
45.395 - * Identity function.
45.396 - * @param x an arbitrary reference value
45.397 - * @return the same value x
45.398 - */
45.399 - static <T> T identity(T x) {
45.400 - return x;
45.401 - }
45.402 -
45.403 - static <T> T[] identity(T[] x) {
45.404 - return x;
45.405 - }
45.406 -
45.407 - /**
45.408 - * Identity function on ints.
45.409 - * @param x an arbitrary int value
45.410 - * @return the same value x
45.411 - */
45.412 - static int identity(int x) {
45.413 - return x;
45.414 - }
45.415 -
45.416 - static byte identity(byte x) {
45.417 - return x;
45.418 - }
45.419 -
45.420 - static short identity(short x) {
45.421 - return x;
45.422 - }
45.423 -
45.424 - static boolean identity(boolean x) {
45.425 - return x;
45.426 - }
45.427 -
45.428 - static char identity(char x) {
45.429 - return x;
45.430 - }
45.431 -
45.432 - /**
45.433 - * Identity function on longs.
45.434 - * @param x an arbitrary long value
45.435 - * @return the same value x
45.436 - */
45.437 - static long identity(long x) {
45.438 - return x;
45.439 - }
45.440 -
45.441 - static float identity(float x) {
45.442 - return x;
45.443 - }
45.444 -
45.445 - static double identity(double x) {
45.446 - return x;
45.447 - }
45.448 -
45.449 - /**
45.450 - * Identity function, with reference cast.
45.451 - * @param t an arbitrary reference type
45.452 - * @param x an arbitrary reference value
45.453 - * @return the same value x
45.454 - */
45.455 - @SuppressWarnings("unchecked")
45.456 - static <T,U> T castReference(Class<? extends T> t, U x) {
45.457 - // inlined Class.cast because we can't ForceInline it
45.458 - if (x != null && !t.isInstance(x))
45.459 - throw newClassCastException(t, x);
45.460 - return (T) x;
45.461 - }
45.462 -
45.463 - private static ClassCastException newClassCastException(Class<?> t, Object obj) {
45.464 - return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
45.465 - }
45.466 -
45.467 - private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY,
45.468 - ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY;
45.469 - static {
45.470 - try {
45.471 - MethodType idType = MethodType.genericMethodType(1);
45.472 - MethodType castType = idType.insertParameterTypes(0, Class.class);
45.473 - MethodType ignoreType = idType.changeReturnType(void.class);
45.474 - MethodType zeroObjectType = MethodType.genericMethodType(0);
45.475 - IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType);
45.476 - //CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType);
45.477 - CAST_REFERENCE = IMPL_LOOKUP.findStatic(THIS_CLASS, "castReference", castType);
45.478 - ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType);
45.479 - IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType);
45.480 - EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1));
45.481 - ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class));
45.482 - FILL_NEW_ARRAY = IMPL_LOOKUP
45.483 - .findStatic(THIS_CLASS, "fillNewArray",
45.484 - MethodType.methodType(Object[].class, Integer.class, Object[].class));
45.485 - FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP
45.486 - .findStatic(THIS_CLASS, "fillNewTypedArray",
45.487 - MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
45.488 - } catch (NoSuchMethodException | IllegalAccessException ex) {
45.489 - throw newInternalError("uncaught exception", ex);
45.490 - }
45.491 - }
45.492 -
45.493 - // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems.
45.494 - static class LazyStatics {
45.495 - private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST;
45.496 - static {
45.497 - try {
45.498 - //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class));
45.499 - COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class));
45.500 - COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class));
45.501 - MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class));
45.502 - } catch (ReflectiveOperationException ex) {
45.503 - throw newInternalError("uncaught exception", ex);
45.504 - }
45.505 - }
45.506 - }
45.507 -
45.508 - private static final EnumMap<Wrapper, MethodHandle>[] WRAPPER_CASTS
45.509 - = newWrapperCaches(1);
45.510 -
45.511 - /** Return a method that casts its sole argument (an Object) to the given type
45.512 - * and returns it as the given type.
45.513 - */
45.514 - public static MethodHandle cast(Class<?> type) {
45.515 - if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type);
45.516 - MethodHandle mh;
45.517 - Wrapper wrap = null;
45.518 - EnumMap<Wrapper, MethodHandle> cache = null;
45.519 - if (Wrapper.isWrapperType(type)) {
45.520 - wrap = Wrapper.forWrapperType(type);
45.521 - cache = WRAPPER_CASTS[0];
45.522 - mh = cache.get(wrap);
45.523 - if (mh != null) return mh;
45.524 - }
45.525 - mh = MethodHandles.insertArguments(CAST_REFERENCE, 0, type);
45.526 - if (cache != null)
45.527 - cache.put(wrap, mh);
45.528 - return mh;
45.529 - }
45.530 -
45.531 - public static MethodHandle identity() {
45.532 - return IDENTITY;
45.533 - }
45.534 -
45.535 - public static MethodHandle identity(Class<?> type) {
45.536 - if (!type.isPrimitive())
45.537 - // Reference identity has been moved into MethodHandles:
45.538 - return MethodHandles.identity(type);
45.539 - return identity(Wrapper.findPrimitiveType(type));
45.540 - }
45.541 -
45.542 - public static MethodHandle identity(Wrapper wrap) {
45.543 - EnumMap<Wrapper, MethodHandle> cache = CONSTANT_FUNCTIONS[1];
45.544 - MethodHandle mh = cache.get(wrap);
45.545 - if (mh != null) {
45.546 - return mh;
45.547 - }
45.548 - // slow path
45.549 - MethodType type = MethodType.methodType(wrap.primitiveType());
45.550 - if (wrap != Wrapper.VOID)
45.551 - type = type.appendParameterTypes(wrap.primitiveType());
45.552 - try {
45.553 - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type);
45.554 - } catch (ReflectiveOperationException ex) {
45.555 - mh = null;
45.556 - }
45.557 - if (mh == null && wrap == Wrapper.VOID) {
45.558 - mh = EMPTY; // #(){} : #()void
45.559 - }
45.560 - if (mh != null) {
45.561 - cache.put(wrap, mh);
45.562 - return mh;
45.563 - }
45.564 -
45.565 - if (mh != null) {
45.566 - cache.put(wrap, mh);
45.567 - return mh;
45.568 - }
45.569 - throw new IllegalArgumentException("cannot find identity for " + wrap);
45.570 - }
45.571 -
45.572 - /// Primitive conversions.
45.573 - // These are supported directly by the JVM, usually by a single instruction.
45.574 - // In the case of narrowing to a subword, there may be a pair of instructions.
45.575 - // In the case of booleans, there may be a helper routine to manage a 1-bit value.
45.576 - // This is the full 8x8 matrix (minus the diagonal).
45.577 -
45.578 - // narrow double to all other types:
45.579 - static float doubleToFloat(double x) { // bytecode: d2f
45.580 - return (float) x;
45.581 - }
45.582 - static long doubleToLong(double x) { // bytecode: d2l
45.583 - return (long) x;
45.584 - }
45.585 - static int doubleToInt(double x) { // bytecode: d2i
45.586 - return (int) x;
45.587 - }
45.588 - static short doubleToShort(double x) { // bytecodes: d2i, i2s
45.589 - return (short) x;
45.590 - }
45.591 - static char doubleToChar(double x) { // bytecodes: d2i, i2c
45.592 - return (char) x;
45.593 - }
45.594 - static byte doubleToByte(double x) { // bytecodes: d2i, i2b
45.595 - return (byte) x;
45.596 - }
45.597 - static boolean doubleToBoolean(double x) {
45.598 - return toBoolean((byte) x);
45.599 - }
45.600 -
45.601 - // widen float:
45.602 - static double floatToDouble(float x) { // bytecode: f2d
45.603 - return x;
45.604 - }
45.605 - // narrow float:
45.606 - static long floatToLong(float x) { // bytecode: f2l
45.607 - return (long) x;
45.608 - }
45.609 - static int floatToInt(float x) { // bytecode: f2i
45.610 - return (int) x;
45.611 - }
45.612 - static short floatToShort(float x) { // bytecodes: f2i, i2s
45.613 - return (short) x;
45.614 - }
45.615 - static char floatToChar(float x) { // bytecodes: f2i, i2c
45.616 - return (char) x;
45.617 - }
45.618 - static byte floatToByte(float x) { // bytecodes: f2i, i2b
45.619 - return (byte) x;
45.620 - }
45.621 - static boolean floatToBoolean(float x) {
45.622 - return toBoolean((byte) x);
45.623 - }
45.624 -
45.625 - // widen long:
45.626 - static double longToDouble(long x) { // bytecode: l2d
45.627 - return x;
45.628 - }
45.629 - static float longToFloat(long x) { // bytecode: l2f
45.630 - return x;
45.631 - }
45.632 - // narrow long:
45.633 - static int longToInt(long x) { // bytecode: l2i
45.634 - return (int) x;
45.635 - }
45.636 - static short longToShort(long x) { // bytecodes: f2i, i2s
45.637 - return (short) x;
45.638 - }
45.639 - static char longToChar(long x) { // bytecodes: f2i, i2c
45.640 - return (char) x;
45.641 - }
45.642 - static byte longToByte(long x) { // bytecodes: f2i, i2b
45.643 - return (byte) x;
45.644 - }
45.645 - static boolean longToBoolean(long x) {
45.646 - return toBoolean((byte) x);
45.647 - }
45.648 -
45.649 - // widen int:
45.650 - static double intToDouble(int x) { // bytecode: i2d
45.651 - return x;
45.652 - }
45.653 - static float intToFloat(int x) { // bytecode: i2f
45.654 - return x;
45.655 - }
45.656 - static long intToLong(int x) { // bytecode: i2l
45.657 - return x;
45.658 - }
45.659 - // narrow int:
45.660 - static short intToShort(int x) { // bytecode: i2s
45.661 - return (short) x;
45.662 - }
45.663 - static char intToChar(int x) { // bytecode: i2c
45.664 - return (char) x;
45.665 - }
45.666 - static byte intToByte(int x) { // bytecode: i2b
45.667 - return (byte) x;
45.668 - }
45.669 - static boolean intToBoolean(int x) {
45.670 - return toBoolean((byte) x);
45.671 - }
45.672 -
45.673 - // widen short:
45.674 - static double shortToDouble(short x) { // bytecode: i2d (implicit 's2i')
45.675 - return x;
45.676 - }
45.677 - static float shortToFloat(short x) { // bytecode: i2f (implicit 's2i')
45.678 - return x;
45.679 - }
45.680 - static long shortToLong(short x) { // bytecode: i2l (implicit 's2i')
45.681 - return x;
45.682 - }
45.683 - static int shortToInt(short x) { // (implicit 's2i')
45.684 - return x;
45.685 - }
45.686 - // narrow short:
45.687 - static char shortToChar(short x) { // bytecode: i2c (implicit 's2i')
45.688 - return (char)x;
45.689 - }
45.690 - static byte shortToByte(short x) { // bytecode: i2b (implicit 's2i')
45.691 - return (byte)x;
45.692 - }
45.693 - static boolean shortToBoolean(short x) {
45.694 - return toBoolean((byte) x);
45.695 - }
45.696 -
45.697 - // widen char:
45.698 - static double charToDouble(char x) { // bytecode: i2d (implicit 'c2i')
45.699 - return x;
45.700 - }
45.701 - static float charToFloat(char x) { // bytecode: i2f (implicit 'c2i')
45.702 - return x;
45.703 - }
45.704 - static long charToLong(char x) { // bytecode: i2l (implicit 'c2i')
45.705 - return x;
45.706 - }
45.707 - static int charToInt(char x) { // (implicit 'c2i')
45.708 - return x;
45.709 - }
45.710 - // narrow char:
45.711 - static short charToShort(char x) { // bytecode: i2s (implicit 'c2i')
45.712 - return (short)x;
45.713 - }
45.714 - static byte charToByte(char x) { // bytecode: i2b (implicit 'c2i')
45.715 - return (byte)x;
45.716 - }
45.717 - static boolean charToBoolean(char x) {
45.718 - return toBoolean((byte) x);
45.719 - }
45.720 -
45.721 - // widen byte:
45.722 - static double byteToDouble(byte x) { // bytecode: i2d (implicit 'b2i')
45.723 - return x;
45.724 - }
45.725 - static float byteToFloat(byte x) { // bytecode: i2f (implicit 'b2i')
45.726 - return x;
45.727 - }
45.728 - static long byteToLong(byte x) { // bytecode: i2l (implicit 'b2i')
45.729 - return x;
45.730 - }
45.731 - static int byteToInt(byte x) { // (implicit 'b2i')
45.732 - return x;
45.733 - }
45.734 - static short byteToShort(byte x) { // bytecode: i2s (implicit 'b2i')
45.735 - return (short)x;
45.736 - }
45.737 - static char byteToChar(byte x) { // bytecode: i2b (implicit 'b2i')
45.738 - return (char)x;
45.739 - }
45.740 - // narrow byte to boolean:
45.741 - static boolean byteToBoolean(byte x) {
45.742 - return toBoolean(x);
45.743 - }
45.744 -
45.745 - // widen boolean to all types:
45.746 - static double booleanToDouble(boolean x) {
45.747 - return fromBoolean(x);
45.748 - }
45.749 - static float booleanToFloat(boolean x) {
45.750 - return fromBoolean(x);
45.751 - }
45.752 - static long booleanToLong(boolean x) {
45.753 - return fromBoolean(x);
45.754 - }
45.755 - static int booleanToInt(boolean x) {
45.756 - return fromBoolean(x);
45.757 - }
45.758 - static short booleanToShort(boolean x) {
45.759 - return fromBoolean(x);
45.760 - }
45.761 - static char booleanToChar(boolean x) {
45.762 - return (char)fromBoolean(x);
45.763 - }
45.764 - static byte booleanToByte(boolean x) {
45.765 - return fromBoolean(x);
45.766 - }
45.767 -
45.768 - // helpers to force boolean into the conversion scheme:
45.769 - static boolean toBoolean(byte x) {
45.770 - // see javadoc for MethodHandles.explicitCastArguments
45.771 - return ((x & 1) != 0);
45.772 - }
45.773 - static byte fromBoolean(boolean x) {
45.774 - // see javadoc for MethodHandles.explicitCastArguments
45.775 - return (x ? (byte)1 : (byte)0);
45.776 - }
45.777 -
45.778 - private static final EnumMap<Wrapper, MethodHandle>[]
45.779 - CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length);
45.780 -
45.781 - public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) {
45.782 - EnumMap<Wrapper, MethodHandle> cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()];
45.783 - MethodHandle mh = cache.get(wdst);
45.784 - if (mh != null) {
45.785 - return mh;
45.786 - }
45.787 - // slow path
45.788 - Class<?> src = wsrc.primitiveType();
45.789 - Class<?> dst = wdst.primitiveType();
45.790 - MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src);
45.791 - if (wsrc == wdst) {
45.792 - mh = identity(src);
45.793 - } else if (wsrc == Wrapper.VOID) {
45.794 - mh = zeroConstantFunction(wdst);
45.795 - } else if (wdst == Wrapper.VOID) {
45.796 - mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles.
45.797 - } else if (wsrc == Wrapper.OBJECT) {
45.798 - mh = unboxCast(dst);
45.799 - } else if (wdst == Wrapper.OBJECT) {
45.800 - mh = box(src);
45.801 - } else {
45.802 - assert(src.isPrimitive() && dst.isPrimitive());
45.803 - try {
45.804 - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, src.getSimpleName()+"To"+capitalize(dst.getSimpleName()), type);
45.805 - } catch (ReflectiveOperationException ex) {
45.806 - mh = null;
45.807 - }
45.808 - }
45.809 - if (mh != null) {
45.810 - assert(mh.type() == type) : mh;
45.811 - cache.put(wdst, mh);
45.812 - return mh;
45.813 - }
45.814 -
45.815 - throw new IllegalArgumentException("cannot find primitive conversion function for " +
45.816 - src.getSimpleName()+" -> "+dst.getSimpleName());
45.817 - }
45.818 -
45.819 - public static MethodHandle convertPrimitive(Class<?> src, Class<?> dst) {
45.820 - return convertPrimitive(Wrapper.forPrimitiveType(src), Wrapper.forPrimitiveType(dst));
45.821 - }
45.822 -
45.823 - private static String capitalize(String x) {
45.824 - return Character.toUpperCase(x.charAt(0))+x.substring(1);
45.825 - }
45.826 -
45.827 - /// Collection of multiple arguments.
45.828 -
45.829 - public static Object convertArrayElements(Class<?> arrayType, Object array) {
45.830 - Class<?> src = array.getClass().getComponentType();
45.831 - Class<?> dst = arrayType.getComponentType();
45.832 - if (src == null || dst == null) throw new IllegalArgumentException("not array type");
45.833 - Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null);
45.834 - Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null);
45.835 - int length;
45.836 - if (sw == null) {
45.837 - Object[] a = (Object[]) array;
45.838 - length = a.length;
45.839 - if (dw == null)
45.840 - return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class));
45.841 - Object res = dw.makeArray(length);
45.842 - dw.copyArrayUnboxing(a, 0, res, 0, length);
45.843 - return res;
45.844 - }
45.845 - length = java.lang.reflect.Array.getLength(array);
45.846 - Object[] res;
45.847 - if (dw == null) {
45.848 - res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class));
45.849 - } else {
45.850 - res = new Object[length];
45.851 - }
45.852 - sw.copyArrayBoxing(array, 0, res, 0, length);
45.853 - if (dw == null) return res;
45.854 - Object a = dw.makeArray(length);
45.855 - dw.copyArrayUnboxing(res, 0, a, 0, length);
45.856 - return a;
45.857 - }
45.858 -
45.859 - private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
45.860 - MethodType type = MethodType.genericMethodType(nargs)
45.861 - .changeReturnType(rtype)
45.862 - .insertParameterTypes(0, ptypes);
45.863 - try {
45.864 - return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type);
45.865 - } catch (ReflectiveOperationException ex) {
45.866 - return null;
45.867 - }
45.868 - }
45.869 -
45.870 - private static final Object[] NO_ARGS_ARRAY = {};
45.871 - private static Object[] makeArray(Object... args) { return args; }
45.872 - private static Object[] array() { return NO_ARGS_ARRAY; }
45.873 - private static Object[] array(Object a0)
45.874 - { return makeArray(a0); }
45.875 - private static Object[] array(Object a0, Object a1)
45.876 - { return makeArray(a0, a1); }
45.877 - private static Object[] array(Object a0, Object a1, Object a2)
45.878 - { return makeArray(a0, a1, a2); }
45.879 - private static Object[] array(Object a0, Object a1, Object a2, Object a3)
45.880 - { return makeArray(a0, a1, a2, a3); }
45.881 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.882 - Object a4)
45.883 - { return makeArray(a0, a1, a2, a3, a4); }
45.884 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.885 - Object a4, Object a5)
45.886 - { return makeArray(a0, a1, a2, a3, a4, a5); }
45.887 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.888 - Object a4, Object a5, Object a6)
45.889 - { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
45.890 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.891 - Object a4, Object a5, Object a6, Object a7)
45.892 - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
45.893 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.894 - Object a4, Object a5, Object a6, Object a7,
45.895 - Object a8)
45.896 - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
45.897 - private static Object[] array(Object a0, Object a1, Object a2, Object a3,
45.898 - Object a4, Object a5, Object a6, Object a7,
45.899 - Object a8, Object a9)
45.900 - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
45.901 - private static MethodHandle[] makeArrays() {
45.902 - ArrayList<MethodHandle> mhs = new ArrayList<>();
45.903 - for (;;) {
45.904 - MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
45.905 - if (mh == null) break;
45.906 - mhs.add(mh);
45.907 - }
45.908 - assert(mhs.size() == 11); // current number of methods
45.909 - return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
45.910 - }
45.911 - private static final MethodHandle[] ARRAYS = makeArrays();
45.912 -
45.913 - // filling versions of the above:
45.914 - // using Integer len instead of int len and no varargs to avoid bootstrapping problems
45.915 - private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
45.916 - Object[] a = new Object[len];
45.917 - fillWithArguments(a, 0, args);
45.918 - return a;
45.919 - }
45.920 - private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
45.921 - Object[] a = Arrays.copyOf(example, len);
45.922 - fillWithArguments(a, 0, args);
45.923 - return a;
45.924 - }
45.925 - private static void fillWithArguments(Object[] a, int pos, Object... args) {
45.926 - System.arraycopy(args, 0, a, pos, args.length);
45.927 - }
45.928 - // using Integer pos instead of int pos to avoid bootstrapping problems
45.929 - private static Object[] fillArray(Integer pos, Object[] a, Object a0)
45.930 - { fillWithArguments(a, pos, a0); return a; }
45.931 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
45.932 - { fillWithArguments(a, pos, a0, a1); return a; }
45.933 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
45.934 - { fillWithArguments(a, pos, a0, a1, a2); return a; }
45.935 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
45.936 - { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
45.937 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.938 - Object a4)
45.939 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
45.940 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.941 - Object a4, Object a5)
45.942 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
45.943 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.944 - Object a4, Object a5, Object a6)
45.945 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
45.946 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.947 - Object a4, Object a5, Object a6, Object a7)
45.948 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
45.949 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.950 - Object a4, Object a5, Object a6, Object a7,
45.951 - Object a8)
45.952 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
45.953 - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
45.954 - Object a4, Object a5, Object a6, Object a7,
45.955 - Object a8, Object a9)
45.956 - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
45.957 - private static MethodHandle[] makeFillArrays() {
45.958 - ArrayList<MethodHandle> mhs = new ArrayList<>();
45.959 - mhs.add(null); // there is no empty fill; at least a0 is required
45.960 - for (;;) {
45.961 - MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
45.962 - if (mh == null) break;
45.963 - mhs.add(mh);
45.964 - }
45.965 - assert(mhs.size() == 11); // current number of methods
45.966 - return mhs.toArray(new MethodHandle[0]);
45.967 - }
45.968 - private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
45.969 -
45.970 - private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) {
45.971 - return Arrays.copyOf(a, a.length, arrayType);
45.972 - }
45.973 - private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
45.974 - Object a = w.makeArray(boxes.length);
45.975 - w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
45.976 - return a;
45.977 - }
45.978 -
45.979 - /** Return a method handle that takes the indicated number of Object
45.980 - * arguments and returns an Object array of them, as if for varargs.
45.981 - */
45.982 - public static MethodHandle varargsArray(int nargs) {
45.983 - MethodHandle mh = ARRAYS[nargs];
45.984 - if (mh != null) return mh;
45.985 - mh = findCollector("array", nargs, Object[].class);
45.986 - if (mh != null) return ARRAYS[nargs] = mh;
45.987 - mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs);
45.988 - assert(assertCorrectArity(mh, nargs));
45.989 - return ARRAYS[nargs] = mh;
45.990 - }
45.991 -
45.992 - private static boolean assertCorrectArity(MethodHandle mh, int arity) {
45.993 - assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
45.994 - return true;
45.995 - }
45.996 -
45.997 - private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
45.998 - // Build up the result mh as a sequence of fills like this:
45.999 - // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
45.1000 - // The various fill(_,10*I,___*[J]) are reusable.
45.1001 - int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately
45.1002 - int rightLen = nargs - leftLen;
45.1003 - MethodHandle leftCollector = newArray.bindTo(nargs);
45.1004 - leftCollector = leftCollector.asCollector(Object[].class, leftLen);
45.1005 - MethodHandle mh = finisher;
45.1006 - if (rightLen > 0) {
45.1007 - MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
45.1008 - if (mh == ARRAY_IDENTITY)
45.1009 - mh = rightFiller;
45.1010 - else
45.1011 - mh = MethodHandles.collectArguments(mh, 0, rightFiller);
45.1012 - }
45.1013 - if (mh == ARRAY_IDENTITY)
45.1014 - mh = leftCollector;
45.1015 - else
45.1016 - mh = MethodHandles.collectArguments(mh, 0, leftCollector);
45.1017 - return mh;
45.1018 - }
45.1019 -
45.1020 - private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
45.1021 - private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
45.1022 - /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
45.1023 - * fills a[L]..a[N-1] with corresponding arguments,
45.1024 - * and then returns a. The value L is a global constant (LEFT_ARGS).
45.1025 - */
45.1026 - private static MethodHandle fillToRight(int nargs) {
45.1027 - MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
45.1028 - if (filler != null) return filler;
45.1029 - filler = buildFiller(nargs);
45.1030 - assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
45.1031 - return FILL_ARRAY_TO_RIGHT[nargs] = filler;
45.1032 - }
45.1033 - private static MethodHandle buildFiller(int nargs) {
45.1034 - if (nargs <= LEFT_ARGS)
45.1035 - return ARRAY_IDENTITY; // no args to fill; return the array unchanged
45.1036 - // we need room for both mh and a in mh.invoke(a, arg*[nargs])
45.1037 - final int CHUNK = LEFT_ARGS;
45.1038 - int rightLen = nargs % CHUNK;
45.1039 - int midLen = nargs - rightLen;
45.1040 - if (rightLen == 0) {
45.1041 - midLen = nargs - (rightLen = CHUNK);
45.1042 - if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
45.1043 - // build some precursors from left to right
45.1044 - for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
45.1045 - if (j > LEFT_ARGS) fillToRight(j);
45.1046 - }
45.1047 - }
45.1048 - if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
45.1049 - assert(rightLen > 0);
45.1050 - MethodHandle midFill = fillToRight(midLen); // recursive fill
45.1051 - MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1]
45.1052 - assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS);
45.1053 - assert(rightFill.type().parameterCount() == 1 + rightLen);
45.1054 -
45.1055 - // Combine the two fills:
45.1056 - // right(mid(a, x10..x19), x20..x23)
45.1057 - // The final product will look like this:
45.1058 - // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
45.1059 - if (midLen == LEFT_ARGS)
45.1060 - return rightFill;
45.1061 - else
45.1062 - return MethodHandles.collectArguments(rightFill, 0, midFill);
45.1063 - }
45.1064 -
45.1065 - // Type-polymorphic version of varargs maker.
45.1066 - private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
45.1067 - = new ClassValue<MethodHandle[]>() {
45.1068 - @Override
45.1069 - protected MethodHandle[] computeValue(Class<?> type) {
45.1070 - return new MethodHandle[256];
45.1071 - }
45.1072 - };
45.1073 -
45.1074 - static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM
45.1075 -
45.1076 - /** Return a method handle that takes the indicated number of
45.1077 - * typed arguments and returns an array of them.
45.1078 - * The type argument is the array type.
45.1079 - */
45.1080 - public static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
45.1081 - Class<?> elemType = arrayType.getComponentType();
45.1082 - if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType);
45.1083 - // FIXME: Need more special casing and caching here.
45.1084 - if (nargs >= MAX_JVM_ARITY/2 - 1) {
45.1085 - int slots = nargs;
45.1086 - final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH
45.1087 - if (arrayType == double[].class || arrayType == long[].class)
45.1088 - slots *= 2;
45.1089 - if (slots > MAX_ARRAY_SLOTS)
45.1090 - throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
45.1091 - }
45.1092 - if (elemType == Object.class)
45.1093 - return varargsArray(nargs);
45.1094 - // other cases: primitive arrays, subtypes of Object[]
45.1095 - MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
45.1096 - MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
45.1097 - if (mh != null) return mh;
45.1098 - if (elemType.isPrimitive()) {
45.1099 - MethodHandle builder = FILL_NEW_ARRAY;
45.1100 - MethodHandle producer = buildArrayProducer(arrayType);
45.1101 - mh = buildVarargsArray(builder, producer, nargs);
45.1102 - } else {
45.1103 - @SuppressWarnings("unchecked")
45.1104 - Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType;
45.1105 - Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
45.1106 - MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example);
45.1107 - MethodHandle producer = ARRAY_IDENTITY;
45.1108 - mh = buildVarargsArray(builder, producer, nargs);
45.1109 - }
45.1110 - mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
45.1111 - assert(assertCorrectArity(mh, nargs));
45.1112 - if (nargs < cache.length)
45.1113 - cache[nargs] = mh;
45.1114 - return mh;
45.1115 - }
45.1116 -
45.1117 - private static MethodHandle buildArrayProducer(Class<?> arrayType) {
45.1118 - Class<?> elemType = arrayType.getComponentType();
45.1119 - if (elemType.isPrimitive())
45.1120 - return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType));
45.1121 - else
45.1122 - return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType);
45.1123 - }
45.1124 -
45.1125 - // List version of varargs maker.
45.1126 -
45.1127 - private static final List<Object> NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY);
45.1128 - private static List<Object> makeList(Object... args) { return Arrays.asList(args); }
45.1129 - private static List<Object> list() { return NO_ARGS_LIST; }
45.1130 - private static List<Object> list(Object a0)
45.1131 - { return makeList(a0); }
45.1132 - private static List<Object> list(Object a0, Object a1)
45.1133 - { return makeList(a0, a1); }
45.1134 - private static List<Object> list(Object a0, Object a1, Object a2)
45.1135 - { return makeList(a0, a1, a2); }
45.1136 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3)
45.1137 - { return makeList(a0, a1, a2, a3); }
45.1138 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1139 - Object a4)
45.1140 - { return makeList(a0, a1, a2, a3, a4); }
45.1141 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1142 - Object a4, Object a5)
45.1143 - { return makeList(a0, a1, a2, a3, a4, a5); }
45.1144 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1145 - Object a4, Object a5, Object a6)
45.1146 - { return makeList(a0, a1, a2, a3, a4, a5, a6); }
45.1147 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1148 - Object a4, Object a5, Object a6, Object a7)
45.1149 - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); }
45.1150 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1151 - Object a4, Object a5, Object a6, Object a7,
45.1152 - Object a8)
45.1153 - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
45.1154 - private static List<Object> list(Object a0, Object a1, Object a2, Object a3,
45.1155 - Object a4, Object a5, Object a6, Object a7,
45.1156 - Object a8, Object a9)
45.1157 - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
45.1158 - private static MethodHandle[] makeLists() {
45.1159 - ArrayList<MethodHandle> mhs = new ArrayList<>();
45.1160 - for (;;) {
45.1161 - MethodHandle mh = findCollector("list", mhs.size(), List.class);
45.1162 - if (mh == null) break;
45.1163 - mhs.add(mh);
45.1164 - }
45.1165 - assert(mhs.size() == 11); // current number of methods
45.1166 - return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
45.1167 - }
45.1168 - private static final MethodHandle[] LISTS = makeLists();
45.1169 -
45.1170 - /** Return a method handle that takes the indicated number of Object
45.1171 - * arguments and returns a List.
45.1172 - */
45.1173 - public static MethodHandle varargsList(int nargs) {
45.1174 - MethodHandle mh = LISTS[nargs];
45.1175 - if (mh != null) return mh;
45.1176 - mh = findCollector("list", nargs, List.class);
45.1177 - if (mh != null) return LISTS[nargs] = mh;
45.1178 - return LISTS[nargs] = buildVarargsList(nargs);
45.1179 - }
45.1180 - private static MethodHandle buildVarargsList(int nargs) {
45.1181 - return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST);
45.1182 - }
45.1183 -
45.1184 - // handy shared exception makers (they simplify the common case code)
45.1185 - private static InternalError newInternalError(String message, Throwable cause) {
45.1186 - return new InternalError(message, cause);
45.1187 - }
45.1188 - private static InternalError newInternalError(Throwable cause) {
45.1189 - return new InternalError(cause);
45.1190 - }
45.1191 -}
46.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/VerifyAccess.java Sun Aug 17 20:09:05 2014 +0200
46.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
46.3 @@ -1,302 +0,0 @@
46.4 -/*
46.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
46.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
46.7 - *
46.8 - * This code is free software; you can redistribute it and/or modify it
46.9 - * under the terms of the GNU General Public License version 2 only, as
46.10 - * published by the Free Software Foundation. Oracle designates this
46.11 - * particular file as subject to the "Classpath" exception as provided
46.12 - * by Oracle in the LICENSE file that accompanied this code.
46.13 - *
46.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
46.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
46.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
46.17 - * version 2 for more details (a copy is included in the LICENSE file that
46.18 - * accompanied this code).
46.19 - *
46.20 - * You should have received a copy of the GNU General Public License version
46.21 - * 2 along with this work; if not, write to the Free Software Foundation,
46.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
46.23 - *
46.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
46.25 - * or visit www.oracle.com if you need additional information or have any
46.26 - * questions.
46.27 - */
46.28 -
46.29 -package sun.invoke.util;
46.30 -
46.31 -import java.lang.reflect.Modifier;
46.32 -import static java.lang.reflect.Modifier.*;
46.33 -
46.34 -/**
46.35 - * This class centralizes information about the JVM's linkage access control.
46.36 - * @author jrose
46.37 - */
46.38 -public class VerifyAccess {
46.39 -
46.40 - private VerifyAccess() { } // cannot instantiate
46.41 -
46.42 - private static final int PACKAGE_ONLY = 0;
46.43 - private static final int PACKAGE_ALLOWED = java.lang.invoke.MethodHandles.Lookup.PACKAGE;
46.44 - private static final int PROTECTED_OR_PACKAGE_ALLOWED = (PACKAGE_ALLOWED|PROTECTED);
46.45 - private static final int ALL_ACCESS_MODES = (PUBLIC|PRIVATE|PROTECTED|PACKAGE_ONLY);
46.46 - private static final boolean ALLOW_NESTMATE_ACCESS = false;
46.47 -
46.48 - /**
46.49 - * Evaluate the JVM linkage rules for access to the given method
46.50 - * on behalf of a caller class which proposes to perform the access.
46.51 - * Return true if the caller class has privileges to invoke a method
46.52 - * or access a field with the given properties.
46.53 - * This requires an accessibility check of the referencing class,
46.54 - * plus an accessibility check of the member within the class,
46.55 - * which depends on the member's modifier flags.
46.56 - * <p>
46.57 - * The relevant properties include the defining class ({@code defc})
46.58 - * of the member, and its modifier flags ({@code mods}).
46.59 - * Also relevant is the class used to make the initial symbolic reference
46.60 - * to the member ({@code refc}). If this latter class is not distinguished,
46.61 - * the defining class should be passed for both arguments ({@code defc == refc}).
46.62 - * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
46.63 - * A field or method R is accessible to a class or interface D if
46.64 - * and only if any of the following conditions is true:<ul>
46.65 - * <li>R is public.
46.66 - * <li>R is protected and is declared in a class C, and D is either
46.67 - * a subclass of C or C itself. Furthermore, if R is not
46.68 - * static, then the symbolic reference to R must contain a
46.69 - * symbolic reference to a class T, such that T is either a
46.70 - * subclass of D, a superclass of D or D itself.
46.71 - * <li>R is either protected or has default access (that is,
46.72 - * neither public nor protected nor private), and is declared
46.73 - * by a class in the same runtime package as D.
46.74 - * <li>R is private and is declared in D.
46.75 - * </ul>
46.76 - * This discussion of access control omits a related restriction
46.77 - * on the target of a protected field access or method invocation
46.78 - * (the target must be of class D or a subtype of D). That
46.79 - * requirement is checked as part of the verification process
46.80 - * (5.4.1); it is not part of link-time access control.
46.81 - * @param refc the class used in the symbolic reference to the proposed member
46.82 - * @param defc the class in which the proposed member is actually defined
46.83 - * @param mods modifier flags for the proposed member
46.84 - * @param lookupClass the class for which the access check is being made
46.85 - * @return true iff the the accessing class can access such a member
46.86 - */
46.87 - public static boolean isMemberAccessible(Class<?> refc, // symbolic ref class
46.88 - Class<?> defc, // actual def class
46.89 - int mods, // actual member mods
46.90 - Class<?> lookupClass,
46.91 - int allowedModes) {
46.92 - if (allowedModes == 0) return false;
46.93 - assert((allowedModes & PUBLIC) != 0 &&
46.94 - (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
46.95 - // The symbolic reference class (refc) must always be fully verified.
46.96 - if (!isClassAccessible(refc, lookupClass, allowedModes)) {
46.97 - return false;
46.98 - }
46.99 - // Usually refc and defc are the same, but verify defc also in case they differ.
46.100 - if (defc == lookupClass &&
46.101 - (allowedModes & PRIVATE) != 0)
46.102 - return true; // easy check; all self-access is OK
46.103 - switch (mods & ALL_ACCESS_MODES) {
46.104 - case PUBLIC:
46.105 - return true; // already checked above
46.106 - case PROTECTED:
46.107 - if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 &&
46.108 - isSamePackage(defc, lookupClass))
46.109 - return true;
46.110 - if ((allowedModes & PROTECTED) == 0)
46.111 - return false;
46.112 - if ((mods & STATIC) != 0 &&
46.113 - !isRelatedClass(refc, lookupClass))
46.114 - return false;
46.115 - if ((allowedModes & PROTECTED) != 0 &&
46.116 - isSuperClass(defc, lookupClass))
46.117 - return true;
46.118 - return false;
46.119 - case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access.
46.120 - return ((allowedModes & PACKAGE_ALLOWED) != 0 &&
46.121 - isSamePackage(defc, lookupClass));
46.122 - case PRIVATE:
46.123 - // Loosened rules for privates follows access rules for inner classes.
46.124 - return (ALLOW_NESTMATE_ACCESS &&
46.125 - (allowedModes & PRIVATE) != 0 &&
46.126 - isSamePackageMember(defc, lookupClass));
46.127 - default:
46.128 - throw new IllegalArgumentException("bad modifiers: "+Modifier.toString(mods));
46.129 - }
46.130 - }
46.131 -
46.132 - static boolean isRelatedClass(Class<?> refc, Class<?> lookupClass) {
46.133 - return (refc == lookupClass ||
46.134 - refc.isAssignableFrom(lookupClass) ||
46.135 - lookupClass.isAssignableFrom(refc));
46.136 - }
46.137 -
46.138 - static boolean isSuperClass(Class<?> defc, Class<?> lookupClass) {
46.139 - return defc.isAssignableFrom(lookupClass);
46.140 - }
46.141 -
46.142 - static int getClassModifiers(Class<?> c) {
46.143 - // This would return the mask stored by javac for the source-level modifiers.
46.144 - // return c.getModifiers();
46.145 - // But what we need for JVM access checks are the actual bits from the class header.
46.146 - // ...But arrays and primitives are synthesized with their own odd flags:
46.147 - if (c.isArray() || c.isPrimitive())
46.148 - return c.getModifiers();
46.149 - return c.getModifiers();
46.150 -// return Reflection.getClassAccessFlags(c);
46.151 - }
46.152 -
46.153 - /**
46.154 - * Evaluate the JVM linkage rules for access to the given class on behalf of caller.
46.155 - * <h3>JVM Specification, 5.4.4 "Access Control"</h3>
46.156 - * A class or interface C is accessible to a class or interface D
46.157 - * if and only if either of the following conditions are true:<ul>
46.158 - * <li>C is public.
46.159 - * <li>C and D are members of the same runtime package.
46.160 - * </ul>
46.161 - * @param refc the symbolic reference class to which access is being checked (C)
46.162 - * @param lookupClass the class performing the lookup (D)
46.163 - */
46.164 - public static boolean isClassAccessible(Class<?> refc, Class<?> lookupClass,
46.165 - int allowedModes) {
46.166 - if (allowedModes == 0) return false;
46.167 - assert((allowedModes & PUBLIC) != 0 &&
46.168 - (allowedModes & ~(ALL_ACCESS_MODES|PACKAGE_ALLOWED)) == 0);
46.169 - int mods = getClassModifiers(refc);
46.170 - if (isPublic(mods))
46.171 - return true;
46.172 - if ((allowedModes & PACKAGE_ALLOWED) != 0 &&
46.173 - isSamePackage(lookupClass, refc))
46.174 - return true;
46.175 - return false;
46.176 - }
46.177 -
46.178 - /**
46.179 - * Decide if the given method type, attributed to a member or symbolic
46.180 - * reference of a given reference class, is really visible to that class.
46.181 - * @param type the supposed type of a member or symbolic reference of refc
46.182 - * @param refc the class attempting to make the reference
46.183 - */
46.184 - public static boolean isTypeVisible(Class<?> type, Class<?> refc) {
46.185 - if (type == refc) return true; // easy check
46.186 - while (type.isArray()) type = type.getComponentType();
46.187 - if (type.isPrimitive() || type == Object.class) return true;
46.188 - ClassLoader parent = type.getClassLoader();
46.189 - if (parent == null) return true;
46.190 - ClassLoader child = refc.getClassLoader();
46.191 - if (child == null) return false;
46.192 - if (parent == child || loadersAreRelated(parent, child, true))
46.193 - return true;
46.194 - // Do it the hard way: Look up the type name from the refc loader.
46.195 - try {
46.196 - Class<?> res = child.loadClass(type.getName());
46.197 - return (type == res);
46.198 - } catch (ClassNotFoundException ex) {
46.199 - return false;
46.200 - }
46.201 - }
46.202 -
46.203 - /**
46.204 - * Decide if the given method type, attributed to a member or symbolic
46.205 - * reference of a given reference class, is really visible to that class.
46.206 - * @param type the supposed type of a member or symbolic reference of refc
46.207 - * @param refc the class attempting to make the reference
46.208 - */
46.209 - public static boolean isTypeVisible(java.lang.invoke.MethodType type, Class<?> refc) {
46.210 - for (int n = -1, max = type.parameterCount(); n < max; n++) {
46.211 - Class<?> ptype = (n < 0 ? type.returnType() : type.parameterType(n));
46.212 - if (!isTypeVisible(ptype, refc))
46.213 - return false;
46.214 - }
46.215 - return true;
46.216 - }
46.217 -
46.218 - /**
46.219 - * Test if two classes have the same class loader and package qualifier.
46.220 - * @param class1 a class
46.221 - * @param class2 another class
46.222 - * @return whether they are in the same package
46.223 - */
46.224 - public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
46.225 - assert(!class1.isArray() && !class2.isArray());
46.226 - if (class1 == class2)
46.227 - return true;
46.228 - if (class1.getClassLoader() != class2.getClassLoader())
46.229 - return false;
46.230 - String name1 = class1.getName(), name2 = class2.getName();
46.231 - int dot = name1.lastIndexOf('.');
46.232 - if (dot != name2.lastIndexOf('.'))
46.233 - return false;
46.234 - for (int i = 0; i < dot; i++) {
46.235 - if (name1.charAt(i) != name2.charAt(i))
46.236 - return false;
46.237 - }
46.238 - return true;
46.239 - }
46.240 -
46.241 - /** Return the package name for this class.
46.242 - */
46.243 - public static String getPackageName(Class<?> cls) {
46.244 - assert(!cls.isArray());
46.245 - String name = cls.getName();
46.246 - int dot = name.lastIndexOf('.');
46.247 - if (dot < 0) return "";
46.248 - return name.substring(0, dot);
46.249 - }
46.250 -
46.251 - /**
46.252 - * Test if two classes are defined as part of the same package member (top-level class).
46.253 - * If this is true, they can share private access with each other.
46.254 - * @param class1 a class
46.255 - * @param class2 another class
46.256 - * @return whether they are identical or nested together
46.257 - */
46.258 - public static boolean isSamePackageMember(Class<?> class1, Class<?> class2) {
46.259 - if (class1 == class2)
46.260 - return true;
46.261 - if (!isSamePackage(class1, class2))
46.262 - return false;
46.263 - if (getOutermostEnclosingClass(class1) != getOutermostEnclosingClass(class2))
46.264 - return false;
46.265 - return true;
46.266 - }
46.267 -
46.268 - private static Class<?> getOutermostEnclosingClass(Class<?> c) {
46.269 - throw new IllegalStateException("Needed?");
46.270 -// Class<?> pkgmem = c;
46.271 -// for (Class<?> enc = c; (enc = enc.getEnclosingClass()) != null; )
46.272 -// pkgmem = enc;
46.273 -// return pkgmem;
46.274 - }
46.275 -
46.276 - private static boolean loadersAreRelated(ClassLoader loader1, ClassLoader loader2,
46.277 - boolean loader1MustBeParent) {
46.278 - if (loader1 == loader2 || loader1 == null
46.279 - || (loader2 == null && !loader1MustBeParent)) {
46.280 - return true;
46.281 - }
46.282 - for (ClassLoader scan2 = loader2;
46.283 - scan2 != null; scan2 = scan2.getParent()) {
46.284 - if (scan2 == loader1) return true;
46.285 - }
46.286 - if (loader1MustBeParent) return false;
46.287 - // see if loader2 is a parent of loader1:
46.288 - for (ClassLoader scan1 = loader1;
46.289 - scan1 != null; scan1 = scan1.getParent()) {
46.290 - if (scan1 == loader2) return true;
46.291 - }
46.292 - return false;
46.293 - }
46.294 -
46.295 - /**
46.296 - * Is the class loader of parentClass identical to, or an ancestor of,
46.297 - * the class loader of childClass?
46.298 - * @param parentClass a class
46.299 - * @param childClass another class, which may be a descendent of the first class
46.300 - * @return whether parentClass precedes or equals childClass in class loader order
46.301 - */
46.302 - public static boolean classLoaderIsAncestor(Class<?> parentClass, Class<?> childClass) {
46.303 - return loadersAreRelated(parentClass.getClassLoader(), childClass.getClassLoader(), true);
46.304 - }
46.305 -}
47.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/VerifyType.java Sun Aug 17 20:09:05 2014 +0200
47.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
47.3 @@ -1,194 +0,0 @@
47.4 -/*
47.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
47.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47.7 - *
47.8 - * This code is free software; you can redistribute it and/or modify it
47.9 - * under the terms of the GNU General Public License version 2 only, as
47.10 - * published by the Free Software Foundation. Oracle designates this
47.11 - * particular file as subject to the "Classpath" exception as provided
47.12 - * by Oracle in the LICENSE file that accompanied this code.
47.13 - *
47.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
47.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
47.17 - * version 2 for more details (a copy is included in the LICENSE file that
47.18 - * accompanied this code).
47.19 - *
47.20 - * You should have received a copy of the GNU General Public License version
47.21 - * 2 along with this work; if not, write to the Free Software Foundation,
47.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47.23 - *
47.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47.25 - * or visit www.oracle.com if you need additional information or have any
47.26 - * questions.
47.27 - */
47.28 -
47.29 -package sun.invoke.util;
47.30 -
47.31 -import java.lang.invoke.MethodType;
47.32 -import sun.invoke.empty.Empty;
47.33 -
47.34 -/**
47.35 - * This class centralizes information about the JVM verifier
47.36 - * and its requirements about type correctness.
47.37 - * @author jrose
47.38 - */
47.39 -public class VerifyType {
47.40 -
47.41 - private VerifyType() { } // cannot instantiate
47.42 -
47.43 - /**
47.44 - * True if a value can be stacked as the source type and unstacked as the
47.45 - * destination type, without violating the JVM's type consistency.
47.46 - *
47.47 - * @param src the type of a stacked value
47.48 - * @param dst the type by which we'd like to treat it
47.49 - * @return whether the retyping can be done without motion or reformatting
47.50 - */
47.51 - public static boolean isNullConversion(Class<?> src, Class<?> dst) {
47.52 - if (src == dst) return true;
47.53 - // Verifier allows any interface to be treated as Object:
47.54 - if (dst.isInterface()) dst = Object.class;
47.55 - if (src.isInterface()) src = Object.class;
47.56 - if (src == dst) return true; // check again
47.57 - if (dst == void.class) return true; // drop any return value
47.58 - if (isNullType(src)) return !dst.isPrimitive();
47.59 - if (!src.isPrimitive()) return dst.isAssignableFrom(src);
47.60 - if (!dst.isPrimitive()) return false;
47.61 - // Verifier allows an int to carry byte, short, char, or even boolean:
47.62 - Wrapper sw = Wrapper.forPrimitiveType(src);
47.63 - if (dst == int.class) return sw.isSubwordOrInt();
47.64 - Wrapper dw = Wrapper.forPrimitiveType(dst);
47.65 - if (!sw.isSubwordOrInt()) return false;
47.66 - if (!dw.isSubwordOrInt()) return false;
47.67 - if (!dw.isSigned() && sw.isSigned()) return false;
47.68 - return dw.bitWidth() > sw.bitWidth();
47.69 - }
47.70 -
47.71 - /**
47.72 - * Specialization of isNullConversion to reference types.
47.73 - * @param src the type of a stacked value
47.74 - * @param dst the reference type by which we'd like to treat it
47.75 - * @return whether the retyping can be done without a cast
47.76 - */
47.77 - public static boolean isNullReferenceConversion(Class<?> src, Class<?> dst) {
47.78 - assert(!dst.isPrimitive());
47.79 - if (dst.isInterface()) return true; // verifier allows this
47.80 - if (isNullType(src)) return true;
47.81 - return dst.isAssignableFrom(src);
47.82 - }
47.83 -
47.84 - /**
47.85 - * Is the given type java.lang.Null or an equivalent null-only type?
47.86 - */
47.87 - public static boolean isNullType(Class<?> type) {
47.88 - if (type == null) return false;
47.89 - return type == NULL_CLASS
47.90 - // This one may also be used as a null type.
47.91 - // TO DO: Decide if we really want to legitimize it here.
47.92 - // Probably we do, unless java.lang.Null really makes it into Java 7
47.93 - //|| type == Void.class
47.94 - // Locally known null-only class:
47.95 - || type == Empty.class
47.96 - ;
47.97 - }
47.98 - private static final Class<?> NULL_CLASS;
47.99 - static {
47.100 - Class<?> nullClass = null;
47.101 - try {
47.102 - nullClass = Class.forName("java.lang.Null");
47.103 - } catch (ClassNotFoundException ex) {
47.104 - // OK, we'll cope
47.105 - }
47.106 - NULL_CLASS = nullClass;
47.107 - }
47.108 -
47.109 - /**
47.110 - * True if a method handle can receive a call under a slightly different
47.111 - * method type, without moving or reformatting any stack elements.
47.112 - *
47.113 - * @param call the type of call being made
47.114 - * @param recv the type of the method handle receiving the call
47.115 - * @return whether the retyping can be done without motion or reformatting
47.116 - */
47.117 - public static boolean isNullConversion(MethodType call, MethodType recv) {
47.118 - if (call == recv) return true;
47.119 - int len = call.parameterCount();
47.120 - if (len != recv.parameterCount()) return false;
47.121 - for (int i = 0; i < len; i++)
47.122 - if (!isNullConversion(call.parameterType(i), recv.parameterType(i)))
47.123 - return false;
47.124 - return isNullConversion(recv.returnType(), call.returnType());
47.125 - }
47.126 -
47.127 - /**
47.128 - * Determine if the JVM verifier allows a value of type call to be
47.129 - * passed to a formal parameter (or return variable) of type recv.
47.130 - * Returns 1 if the verifier allows the types to match without conversion.
47.131 - * Returns -1 if the types can be made to match by a JVM-supported adapter.
47.132 - * Cases supported are:
47.133 - * <ul><li>checkcast
47.134 - * </li><li>conversion between any two integral types (but not floats)
47.135 - * </li><li>unboxing from a wrapper to its corresponding primitive type
47.136 - * </li><li>conversion in either direction between float and double
47.137 - * </li></ul>
47.138 - * (Autoboxing is not supported here; it must be done via Java code.)
47.139 - * Returns 0 otherwise.
47.140 - */
47.141 - public static int canPassUnchecked(Class<?> src, Class<?> dst) {
47.142 - if (src == dst)
47.143 - return 1;
47.144 -
47.145 - if (dst.isPrimitive()) {
47.146 - if (dst == void.class)
47.147 - // Return anything to a caller expecting void.
47.148 - // This is a property of the implementation, which links
47.149 - // return values via a register rather than via a stack push.
47.150 - // This makes it possible to ignore cleanly.
47.151 - return 1;
47.152 - if (src == void.class)
47.153 - return 0; // void-to-something?
47.154 - if (!src.isPrimitive())
47.155 - // Cannot pass a reference to any primitive type (exc. void).
47.156 - return 0;
47.157 - Wrapper sw = Wrapper.forPrimitiveType(src);
47.158 - Wrapper dw = Wrapper.forPrimitiveType(dst);
47.159 - if (sw.isSubwordOrInt() && dw.isSubwordOrInt()) {
47.160 - if (sw.bitWidth() >= dw.bitWidth())
47.161 - return -1; // truncation may be required
47.162 - if (!dw.isSigned() && sw.isSigned())
47.163 - return -1; // sign elimination may be required
47.164 - return 1;
47.165 - }
47.166 - if (src == float.class || dst == float.class) {
47.167 - if (src == double.class || dst == double.class)
47.168 - return -1; // floating conversion may be required
47.169 - else
47.170 - return 0; // other primitive conversions NYI
47.171 - } else {
47.172 - // all fixed-point conversions are supported
47.173 - return 0;
47.174 - }
47.175 - } else if (src.isPrimitive()) {
47.176 - // Cannot pass a primitive to any reference type.
47.177 - // (Maybe allow null.class?)
47.178 - return 0;
47.179 - }
47.180 -
47.181 - // Handle reference types in the rest of the block:
47.182 -
47.183 - // The verifier treats interfaces exactly like Object.
47.184 - if (isNullReferenceConversion(src, dst))
47.185 - // pass any reference to object or an arb. interface
47.186 - return 1;
47.187 - // else it's a definite "maybe" (cast is required)
47.188 - return -1;
47.189 - }
47.190 -
47.191 - public static boolean isSpreadArgType(Class<?> spreadArg) {
47.192 - return spreadArg.isArray();
47.193 - }
47.194 - public static Class<?> spreadArgElementType(Class<?> spreadArg, int i) {
47.195 - return spreadArg.getComponentType();
47.196 - }
47.197 -}
48.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/Wrapper.java Sun Aug 17 20:09:05 2014 +0200
48.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
48.3 @@ -1,614 +0,0 @@
48.4 -/*
48.5 - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
48.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
48.7 - *
48.8 - * This code is free software; you can redistribute it and/or modify it
48.9 - * under the terms of the GNU General Public License version 2 only, as
48.10 - * published by the Free Software Foundation. Oracle designates this
48.11 - * particular file as subject to the "Classpath" exception as provided
48.12 - * by Oracle in the LICENSE file that accompanied this code.
48.13 - *
48.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
48.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
48.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
48.17 - * version 2 for more details (a copy is included in the LICENSE file that
48.18 - * accompanied this code).
48.19 - *
48.20 - * You should have received a copy of the GNU General Public License version
48.21 - * 2 along with this work; if not, write to the Free Software Foundation,
48.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
48.23 - *
48.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
48.25 - * or visit www.oracle.com if you need additional information or have any
48.26 - * questions.
48.27 - */
48.28 -
48.29 -package sun.invoke.util;
48.30 -
48.31 -public enum Wrapper {
48.32 - BOOLEAN(Boolean.class, boolean.class, 'Z', (Boolean)false, new boolean[0], Format.unsigned(1)),
48.33 - // These must be in the order defined for widening primitive conversions in JLS 5.1.2
48.34 - BYTE(Byte.class, byte.class, 'B', (Byte)(byte)0, new byte[0], Format.signed(8)),
48.35 - SHORT(Short.class, short.class, 'S', (Short)(short)0, new short[0], Format.signed(16)),
48.36 - CHAR(Character.class, char.class, 'C', (Character)(char)0, new char[0], Format.unsigned(16)),
48.37 - INT(Integer.class, int.class, 'I', (Integer)/*(int)*/0, new int[0], Format.signed(32)),
48.38 - LONG(Long.class, long.class, 'J', (Long)(long)0, new long[0], Format.signed(64)),
48.39 - FLOAT(Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)),
48.40 - DOUBLE(Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)),
48.41 - //NULL(Null.class, null.class, 'N', null, null, Format.other(1)),
48.42 - OBJECT(Object.class, Object.class, 'L', null, new Object[0], Format.other(1)),
48.43 - // VOID must be the last type, since it is "assignable" from any other type:
48.44 - VOID(Void.class, void.class, 'V', null, null, Format.other(0)),
48.45 - ;
48.46 -
48.47 - private final Class<?> wrapperType;
48.48 - private final Class<?> primitiveType;
48.49 - private final char basicTypeChar;
48.50 - private final Object zero;
48.51 - private final Object emptyArray;
48.52 - private final int format;
48.53 - private final String wrapperSimpleName;
48.54 - private final String primitiveSimpleName;
48.55 -
48.56 - private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) {
48.57 - this.wrapperType = wtype;
48.58 - this.primitiveType = ptype;
48.59 - this.basicTypeChar = tchar;
48.60 - this.zero = zero;
48.61 - this.emptyArray = emptyArray;
48.62 - this.format = format;
48.63 - this.wrapperSimpleName = wtype.getSimpleName();
48.64 - this.primitiveSimpleName = ptype.getSimpleName();
48.65 - }
48.66 -
48.67 - /** For debugging, give the details of this wrapper. */
48.68 - public String detailString() {
48.69 - return wrapperSimpleName+
48.70 - java.util.Arrays.asList(wrapperType, primitiveType,
48.71 - basicTypeChar, zero,
48.72 - "0x"+Integer.toHexString(format));
48.73 - }
48.74 -
48.75 - private static abstract class Format {
48.76 - static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
48.77 - static final int
48.78 - SIGNED = (-1) << KIND_SHIFT,
48.79 - UNSIGNED = 0 << KIND_SHIFT,
48.80 - FLOATING = 1 << KIND_SHIFT;
48.81 - static final int
48.82 - SLOT_MASK = ((1<<(SIZE_SHIFT-SLOT_SHIFT))-1),
48.83 - SIZE_MASK = ((1<<(KIND_SHIFT-SIZE_SHIFT))-1);
48.84 - static int format(int kind, int size, int slots) {
48.85 - assert(((kind >> KIND_SHIFT) << KIND_SHIFT) == kind);
48.86 - assert((size & (size-1)) == 0); // power of two
48.87 - assert((kind == SIGNED) ? (size > 0) :
48.88 - (kind == UNSIGNED) ? (size > 0) :
48.89 - (kind == FLOATING) ? (size == 32 || size == 64) :
48.90 - false);
48.91 - assert((slots == 2) ? (size == 64) :
48.92 - (slots == 1) ? (size <= 32) :
48.93 - false);
48.94 - return kind | (size << SIZE_SHIFT) | (slots << SLOT_SHIFT);
48.95 - }
48.96 - static final int
48.97 - INT = SIGNED | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
48.98 - SHORT = SIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
48.99 - BOOLEAN = UNSIGNED | (1 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
48.100 - CHAR = UNSIGNED | (16 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
48.101 - FLOAT = FLOATING | (32 << SIZE_SHIFT) | (1 << SLOT_SHIFT),
48.102 - VOID = UNSIGNED | (0 << SIZE_SHIFT) | (0 << SLOT_SHIFT),
48.103 - NUM_MASK = (-1) << SIZE_SHIFT;
48.104 - static int signed(int size) { return format(SIGNED, size, (size > 32 ? 2 : 1)); }
48.105 - static int unsigned(int size) { return format(UNSIGNED, size, (size > 32 ? 2 : 1)); }
48.106 - static int floating(int size) { return format(FLOATING, size, (size > 32 ? 2 : 1)); }
48.107 - static int other(int slots) { return slots << SLOT_SHIFT; }
48.108 - }
48.109 -
48.110 - /// format queries:
48.111 -
48.112 - /** How many bits are in the wrapped value? Returns 0 for OBJECT or VOID. */
48.113 - public int bitWidth() { return (format >> Format.SIZE_SHIFT) & Format.SIZE_MASK; }
48.114 - /** How many JVM stack slots occupied by the wrapped value? Returns 0 for VOID. */
48.115 - public int stackSlots() { return (format >> Format.SLOT_SHIFT) & Format.SLOT_MASK; }
48.116 - /** Does the wrapped value occupy a single JVM stack slot? */
48.117 - public boolean isSingleWord() { return (format & (1 << Format.SLOT_SHIFT)) != 0; }
48.118 - /** Does the wrapped value occupy two JVM stack slots? */
48.119 - public boolean isDoubleWord() { return (format & (2 << Format.SLOT_SHIFT)) != 0; }
48.120 - /** Is the wrapped type numeric (not void or object)? */
48.121 - public boolean isNumeric() { return (format & Format.NUM_MASK) != 0; }
48.122 - /** Is the wrapped type a primitive other than float, double, or void? */
48.123 - public boolean isIntegral() { return isNumeric() && format < Format.FLOAT; }
48.124 - /** Is the wrapped type one of int, boolean, byte, char, or short? */
48.125 - public boolean isSubwordOrInt() { return isIntegral() && isSingleWord(); }
48.126 - /* Is the wrapped value a signed integral type (one of byte, short, int, or long)? */
48.127 - public boolean isSigned() { return format < Format.VOID; }
48.128 - /* Is the wrapped value an unsigned integral type (one of boolean or char)? */
48.129 - public boolean isUnsigned() { return format >= Format.BOOLEAN && format < Format.FLOAT; }
48.130 - /** Is the wrapped type either float or double? */
48.131 - public boolean isFloating() { return format >= Format.FLOAT; }
48.132 - /** Is the wrapped type either void or a reference? */
48.133 - public boolean isOther() { return (format & ~Format.SLOT_MASK) == 0; }
48.134 -
48.135 - /** Does the JLS 5.1.2 allow a variable of this wrapper's
48.136 - * primitive type to be assigned from a value of the given wrapper's primitive type?
48.137 - * Cases:
48.138 - * <ul>
48.139 - * <li>unboxing followed by widening primitive conversion
48.140 - * <li>any type converted to {@code void} (i.e., dropping a method call's value)
48.141 - * <li>boxing conversion followed by widening reference conversion to {@code Object}
48.142 - * </ul>
48.143 - * These are the cases allowed by MethodHandle.asType.
48.144 - */
48.145 - public boolean isConvertibleFrom(Wrapper source) {
48.146 - if (this == source) return true;
48.147 - if (this.compareTo(source) < 0) {
48.148 - // At best, this is a narrowing conversion.
48.149 - return false;
48.150 - }
48.151 - // All conversions are allowed in the enum order between floats and signed ints.
48.152 - // First detect non-signed non-float types (boolean, char, Object, void).
48.153 - boolean floatOrSigned = (((this.format & source.format) & Format.SIGNED) != 0);
48.154 - if (!floatOrSigned) {
48.155 - if (this.isOther()) return true;
48.156 - // can convert char to int or wider, but nothing else
48.157 - if (source.format == Format.CHAR) return true;
48.158 - // no other conversions are classified as widening
48.159 - return false;
48.160 - }
48.161 - // All signed and float conversions in the enum order are widening.
48.162 - assert(this.isFloating() || this.isSigned());
48.163 - assert(source.isFloating() || source.isSigned());
48.164 - return true;
48.165 - }
48.166 -
48.167 - static { assert(checkConvertibleFrom()); }
48.168 - private static boolean checkConvertibleFrom() {
48.169 - // Check the matrix for correct classification of widening conversions.
48.170 - for (Wrapper w : values()) {
48.171 - assert(w.isConvertibleFrom(w));
48.172 - assert(VOID.isConvertibleFrom(w));
48.173 - if (w != VOID) {
48.174 - assert(OBJECT.isConvertibleFrom(w));
48.175 - assert(!w.isConvertibleFrom(VOID));
48.176 - }
48.177 - // check relations with unsigned integral types:
48.178 - if (w != CHAR) {
48.179 - assert(!CHAR.isConvertibleFrom(w));
48.180 - if (!w.isConvertibleFrom(INT))
48.181 - assert(!w.isConvertibleFrom(CHAR));
48.182 - }
48.183 - if (w != BOOLEAN) {
48.184 - assert(!BOOLEAN.isConvertibleFrom(w));
48.185 - if (w != VOID && w != OBJECT)
48.186 - assert(!w.isConvertibleFrom(BOOLEAN));
48.187 - }
48.188 - // check relations with signed integral types:
48.189 - if (w.isSigned()) {
48.190 - for (Wrapper x : values()) {
48.191 - if (w == x) continue;
48.192 - if (x.isFloating())
48.193 - assert(!w.isConvertibleFrom(x));
48.194 - else if (x.isSigned()) {
48.195 - if (w.compareTo(x) < 0)
48.196 - assert(!w.isConvertibleFrom(x));
48.197 - else
48.198 - assert(w.isConvertibleFrom(x));
48.199 - }
48.200 - }
48.201 - }
48.202 - // check relations with floating types:
48.203 - if (w.isFloating()) {
48.204 - for (Wrapper x : values()) {
48.205 - if (w == x) continue;
48.206 - if (x.isSigned())
48.207 - assert(w.isConvertibleFrom(x));
48.208 - else if (x.isFloating()) {
48.209 - if (w.compareTo(x) < 0)
48.210 - assert(!w.isConvertibleFrom(x));
48.211 - else
48.212 - assert(w.isConvertibleFrom(x));
48.213 - }
48.214 - }
48.215 - }
48.216 - }
48.217 - return true; // i.e., assert(true)
48.218 - }
48.219 -
48.220 - /** Produce a zero value for the given wrapper type.
48.221 - * This will be a numeric zero for a number or character,
48.222 - * false for a boolean, and null for a reference or void.
48.223 - * The common thread is that this is what is contained
48.224 - * in a default-initialized variable of the given primitive
48.225 - * type. (For void, it is what a reflective method returns
48.226 - * instead of no value at all.)
48.227 - */
48.228 - public Object zero() { return zero; }
48.229 -
48.230 - /** Produce a zero value for the given wrapper type T.
48.231 - * The optional argument must a type compatible with this wrapper.
48.232 - * Equivalent to {@code this.cast(this.zero(), type)}.
48.233 - */
48.234 - public <T> T zero(Class<T> type) { return convert(zero, type); }
48.235 -
48.236 -// /** Produce a wrapper for the given wrapper or primitive type. */
48.237 -// public static Wrapper valueOf(Class<?> type) {
48.238 -// if (isPrimitiveType(type))
48.239 -// return forPrimitiveType(type);
48.240 -// else
48.241 -// return forWrapperType(type);
48.242 -// }
48.243 -
48.244 - /** Return the wrapper that wraps values of the given type.
48.245 - * The type may be {@code Object}, meaning the {@code OBJECT} wrapper.
48.246 - * Otherwise, the type must be a primitive.
48.247 - * @throws IllegalArgumentException for unexpected types
48.248 - */
48.249 - public static Wrapper forPrimitiveType(Class<?> type) {
48.250 - Wrapper w = findPrimitiveType(type);
48.251 - if (w != null) return w;
48.252 - if (type.isPrimitive())
48.253 - throw new InternalError(); // redo hash function
48.254 - throw newIllegalArgumentException("not primitive: "+type);
48.255 - }
48.256 -
48.257 - static Wrapper findPrimitiveType(Class<?> type) {
48.258 - Wrapper w = FROM_PRIM[hashPrim(type)];
48.259 - if (w != null && w.primitiveType == type) {
48.260 - return w;
48.261 - }
48.262 - return null;
48.263 - }
48.264 -
48.265 - /** Return the wrapper that wraps values into the given wrapper type.
48.266 - * If it is {@code Object}, return {@code OBJECT}.
48.267 - * Otherwise, it must be a wrapper type.
48.268 - * The type must not be a primitive type.
48.269 - * @throws IllegalArgumentException for unexpected types
48.270 - */
48.271 - public static Wrapper forWrapperType(Class<?> type) {
48.272 - Wrapper w = findWrapperType(type);
48.273 - if (w != null) return w;
48.274 - for (Wrapper x : values())
48.275 - if (x.wrapperType == type)
48.276 - throw new InternalError(); // redo hash function
48.277 - throw newIllegalArgumentException("not wrapper: "+type);
48.278 - }
48.279 -
48.280 - static Wrapper findWrapperType(Class<?> type) {
48.281 - Wrapper w = FROM_WRAP[hashWrap(type)];
48.282 - if (w != null && w.wrapperType == type) {
48.283 - return w;
48.284 - }
48.285 - return null;
48.286 - }
48.287 -
48.288 - /** Return the wrapper that corresponds to the given bytecode
48.289 - * signature character. Return {@code OBJECT} for the character 'L'.
48.290 - * @throws IllegalArgumentException for any non-signature character or {@code '['}.
48.291 - */
48.292 - public static Wrapper forBasicType(char type) {
48.293 - Wrapper w = FROM_CHAR[hashChar(type)];
48.294 - if (w != null && w.basicTypeChar == type) {
48.295 - return w;
48.296 - }
48.297 - for (Wrapper x : values())
48.298 - if (w.basicTypeChar == type)
48.299 - throw new InternalError(); // redo hash function
48.300 - throw newIllegalArgumentException("not basic type char: "+type);
48.301 - }
48.302 -
48.303 - /** Return the wrapper for the given type, if it is
48.304 - * a primitive type, else return {@code OBJECT}.
48.305 - */
48.306 - public static Wrapper forBasicType(Class<?> type) {
48.307 - if (type.isPrimitive())
48.308 - return forPrimitiveType(type);
48.309 - return OBJECT; // any reference, including wrappers or arrays
48.310 - }
48.311 -
48.312 - // Note on perfect hashes:
48.313 - // for signature chars c, do (c + (c >> 1)) % 16
48.314 - // for primitive type names n, do (n[0] + n[2]) % 16
48.315 - // The type name hash works for both primitive and wrapper names.
48.316 - // You can add "java/lang/Object" to the primitive names.
48.317 - // But you add the wrapper name Object, use (n[2] + (3*n[1])) % 16.
48.318 - private static final Wrapper[] FROM_PRIM = new Wrapper[16];
48.319 - private static final Wrapper[] FROM_WRAP = new Wrapper[16];
48.320 - private static final Wrapper[] FROM_CHAR = new Wrapper[16];
48.321 - private static int hashPrim(Class<?> x) {
48.322 - String xn = x.getName();
48.323 - if (xn.length() < 3) return 0;
48.324 - return (xn.charAt(0) + xn.charAt(2)) % 16;
48.325 - }
48.326 - private static int hashWrap(Class<?> x) {
48.327 - String xn = x.getName();
48.328 - final int offset = 10; assert(offset == "java.lang.".length());
48.329 - if (xn.length() < offset+3) return 0;
48.330 - return (3*xn.charAt(offset+1) + xn.charAt(offset+2)) % 16;
48.331 - }
48.332 - private static int hashChar(char x) {
48.333 - return (x + (x >> 1)) % 16;
48.334 - }
48.335 - static {
48.336 - for (Wrapper w : values()) {
48.337 - int pi = hashPrim(w.primitiveType);
48.338 - int wi = hashWrap(w.wrapperType);
48.339 - int ci = hashChar(w.basicTypeChar);
48.340 - assert(FROM_PRIM[pi] == null);
48.341 - assert(FROM_WRAP[wi] == null);
48.342 - assert(FROM_CHAR[ci] == null);
48.343 - FROM_PRIM[pi] = w;
48.344 - FROM_WRAP[wi] = w;
48.345 - FROM_CHAR[ci] = w;
48.346 - }
48.347 - //assert(jdk.sun.invoke.util.WrapperTest.test(false));
48.348 - }
48.349 -
48.350 - /** What is the primitive type wrapped by this wrapper? */
48.351 - public Class<?> primitiveType() { return primitiveType; }
48.352 -
48.353 - /** What is the wrapper type for this wrapper? */
48.354 - public Class<?> wrapperType() { return wrapperType; }
48.355 -
48.356 - /** What is the wrapper type for this wrapper?
48.357 - * Otherwise, the example type must be the wrapper type,
48.358 - * or the corresponding primitive type.
48.359 - * (For {@code OBJECT}, the example type can be any non-primitive,
48.360 - * and is normalized to {@code Object.class}.)
48.361 - * The resulting class type has the same type parameter.
48.362 - */
48.363 - public <T> Class<T> wrapperType(Class<T> exampleType) {
48.364 - if (exampleType == wrapperType) {
48.365 - return exampleType;
48.366 - } else if (exampleType == primitiveType ||
48.367 - wrapperType == Object.class ||
48.368 - exampleType.isInterface()) {
48.369 - return forceType(wrapperType, exampleType);
48.370 - }
48.371 - throw newClassCastException(exampleType, primitiveType);
48.372 - }
48.373 -
48.374 - private static ClassCastException newClassCastException(Class<?> actual, Class<?> expected) {
48.375 - return new ClassCastException(actual + " is not compatible with " + expected);
48.376 - }
48.377 -
48.378 - /** If {@code type} is a primitive type, return the corresponding
48.379 - * wrapper type, else return {@code type} unchanged.
48.380 - */
48.381 - public static <T> Class<T> asWrapperType(Class<T> type) {
48.382 - if (type.isPrimitive()) {
48.383 - return forPrimitiveType(type).wrapperType(type);
48.384 - }
48.385 - return type;
48.386 - }
48.387 -
48.388 - /** If {@code type} is a wrapper type, return the corresponding
48.389 - * primitive type, else return {@code type} unchanged.
48.390 - */
48.391 - public static <T> Class<T> asPrimitiveType(Class<T> type) {
48.392 - Wrapper w = findWrapperType(type);
48.393 - if (w != null) {
48.394 - return forceType(w.primitiveType(), type);
48.395 - }
48.396 - return type;
48.397 - }
48.398 -
48.399 - /** Query: Is the given type a wrapper, such as {@code Integer} or {@code Void}? */
48.400 - public static boolean isWrapperType(Class<?> type) {
48.401 - return findWrapperType(type) != null;
48.402 - }
48.403 -
48.404 - /** Query: Is the given type a primitive, such as {@code int} or {@code void}? */
48.405 - public static boolean isPrimitiveType(Class<?> type) {
48.406 - return type.isPrimitive();
48.407 - }
48.408 -
48.409 - /** What is the bytecode signature character for this type?
48.410 - * All non-primitives, including array types, report as 'L', the signature character for references.
48.411 - */
48.412 - public static char basicTypeChar(Class<?> type) {
48.413 - if (!type.isPrimitive())
48.414 - return 'L';
48.415 - else
48.416 - return forPrimitiveType(type).basicTypeChar();
48.417 - }
48.418 -
48.419 - /** What is the bytecode signature character for this wrapper's
48.420 - * primitive type?
48.421 - */
48.422 - public char basicTypeChar() { return basicTypeChar; }
48.423 -
48.424 - /** What is the simple name of the wrapper type?
48.425 - */
48.426 - public String wrapperSimpleName() { return wrapperSimpleName; }
48.427 -
48.428 - /** What is the simple name of the primitive type?
48.429 - */
48.430 - public String primitiveSimpleName() { return primitiveSimpleName; }
48.431 -
48.432 -// /** Wrap a value in the given type, which may be either a primitive or wrapper type.
48.433 -// * Performs standard primitive conversions, including truncation and float conversions.
48.434 -// */
48.435 -// public static <T> T wrap(Object x, Class<T> type) {
48.436 -// return Wrapper.valueOf(type).cast(x, type);
48.437 -// }
48.438 -
48.439 - /** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
48.440 - * The given target type must be this wrapper's primitive or wrapper type.
48.441 - * If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
48.442 - * Performs standard primitive conversions, including truncation and float conversions.
48.443 - * The given type must be compatible with this wrapper. That is, it must either
48.444 - * be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
48.445 - * it must be the wrapper's primitive type.
48.446 - * Primitive conversions are only performed if the given type is itself a primitive.
48.447 - * @throws ClassCastException if the given type is not compatible with this wrapper
48.448 - */
48.449 - public <T> T cast(Object x, Class<T> type) {
48.450 - return convert(x, type, true);
48.451 - }
48.452 -
48.453 - /** Convert a wrapped value to the given type.
48.454 - * The given target type must be this wrapper's primitive or wrapper type.
48.455 - * This is equivalent to {@link #cast}, except that it refuses to perform
48.456 - * narrowing primitive conversions.
48.457 - */
48.458 - public <T> T convert(Object x, Class<T> type) {
48.459 - return convert(x, type, false);
48.460 - }
48.461 -
48.462 - private <T> T convert(Object x, Class<T> type, boolean isCast) {
48.463 - if (this == OBJECT) {
48.464 - // If the target wrapper is OBJECT, just do a reference cast.
48.465 - // If the target type is an interface, perform no runtime check.
48.466 - // (This loophole is safe, and is allowed by the JVM verifier.)
48.467 - // If the target type is a primitive, change it to a wrapper.
48.468 - assert(!type.isPrimitive());
48.469 - if (!type.isInterface())
48.470 - type.cast(x);
48.471 - @SuppressWarnings("unchecked")
48.472 - T result = (T) x; // unchecked warning is expected here
48.473 - return result;
48.474 - }
48.475 - Class<T> wtype = wrapperType(type);
48.476 - if (wtype.isInstance(x)) {
48.477 - return wtype.cast(x);
48.478 - }
48.479 - if (!isCast) {
48.480 - Class<?> sourceType = x.getClass(); // throw NPE if x is null
48.481 - Wrapper source = findWrapperType(sourceType);
48.482 - if (source == null || !this.isConvertibleFrom(source)) {
48.483 - throw newClassCastException(wtype, sourceType);
48.484 - }
48.485 - } else if (x == null) {
48.486 - @SuppressWarnings("unchecked")
48.487 - T z = (T) zero;
48.488 - return z;
48.489 - }
48.490 - @SuppressWarnings("unchecked")
48.491 - T result = (T) wrap(x); // unchecked warning is expected here
48.492 - assert (result == null ? Void.class : result.getClass()) == wtype;
48.493 - return result;
48.494 - }
48.495 -
48.496 - /** Cast a reference type to another reference type.
48.497 - * If the target type is an interface, perform no runtime check.
48.498 - * (This loophole is safe, and is allowed by the JVM verifier.)
48.499 - * If the target type is a primitive, change it to a wrapper.
48.500 - */
48.501 - static <T> Class<T> forceType(Class<?> type, Class<T> exampleType) {
48.502 - boolean z = (type == exampleType ||
48.503 - type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
48.504 - exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
48.505 - type == Object.class && !exampleType.isPrimitive());
48.506 - if (!z)
48.507 - System.out.println(type+" <= "+exampleType);
48.508 - assert(type == exampleType ||
48.509 - type.isPrimitive() && forPrimitiveType(type) == findWrapperType(exampleType) ||
48.510 - exampleType.isPrimitive() && forPrimitiveType(exampleType) == findWrapperType(type) ||
48.511 - type == Object.class && !exampleType.isPrimitive());
48.512 - @SuppressWarnings("unchecked")
48.513 - Class<T> result = (Class<T>) type; // unchecked warning is expected here
48.514 - return result;
48.515 - }
48.516 -
48.517 - /** Wrap a value in this wrapper's type.
48.518 - * Performs standard primitive conversions, including truncation and float conversions.
48.519 - * Performs returns the unchanged reference for {@code OBJECT}.
48.520 - * Returns null for {@code VOID}.
48.521 - * Returns a zero value for a null input.
48.522 - * @throws ClassCastException if this wrapper is numeric and the operand
48.523 - * is not a number, character, boolean, or null
48.524 - */
48.525 - public Object wrap(Object x) {
48.526 - // do non-numeric wrappers first
48.527 - switch (basicTypeChar) {
48.528 - case 'L': return x;
48.529 - case 'V': return null;
48.530 - }
48.531 - Number xn = numberValue(x);
48.532 - switch (basicTypeChar) {
48.533 - case 'I': return Integer.valueOf(xn.intValue());
48.534 - case 'J': return Long.valueOf(xn.longValue());
48.535 - case 'F': return Float.valueOf(xn.floatValue());
48.536 - case 'D': return Double.valueOf(xn.doubleValue());
48.537 - case 'S': return Short.valueOf((short) xn.intValue());
48.538 - case 'B': return Byte.valueOf((byte) xn.intValue());
48.539 - case 'C': return Character.valueOf((char) xn.intValue());
48.540 - case 'Z': return Boolean.valueOf(boolValue(xn.byteValue()));
48.541 - }
48.542 - throw new InternalError("bad wrapper");
48.543 - }
48.544 -
48.545 - /** Wrap a value (an int or smaller value) in this wrapper's type.
48.546 - * Performs standard primitive conversions, including truncation and float conversions.
48.547 - * Produces an {@code Integer} for {@code OBJECT}, although the exact type
48.548 - * of the operand is not known.
48.549 - * Returns null for {@code VOID}.
48.550 - */
48.551 - public Object wrap(int x) {
48.552 - if (basicTypeChar == 'L') return (Integer)x;
48.553 - switch (basicTypeChar) {
48.554 - case 'L': throw newIllegalArgumentException("cannot wrap to object type");
48.555 - case 'V': return null;
48.556 - case 'I': return Integer.valueOf(x);
48.557 - case 'J': return Long.valueOf(x);
48.558 - case 'F': return Float.valueOf(x);
48.559 - case 'D': return Double.valueOf(x);
48.560 - case 'S': return Short.valueOf((short) x);
48.561 - case 'B': return Byte.valueOf((byte) x);
48.562 - case 'C': return Character.valueOf((char) x);
48.563 - case 'Z': return Boolean.valueOf(boolValue((byte) x));
48.564 - }
48.565 - throw new InternalError("bad wrapper");
48.566 - }
48.567 -
48.568 - private static Number numberValue(Object x) {
48.569 - if (x instanceof Number) return (Number)x;
48.570 - if (x instanceof Character) return (int)(Character)x;
48.571 - if (x instanceof Boolean) return (Boolean)x ? 1 : 0;
48.572 - // Remaining allowed case of void: Must be a null reference.
48.573 - return (Number)x;
48.574 - }
48.575 -
48.576 - // Parameter type of boolValue must be byte, because
48.577 - // MethodHandles.explicitCastArguments defines boolean
48.578 - // conversion as first converting to byte.
48.579 - private static boolean boolValue(byte bits) {
48.580 - bits &= 1; // simple 31-bit zero extension
48.581 - return (bits != 0);
48.582 - }
48.583 -
48.584 - private static RuntimeException newIllegalArgumentException(String message, Object x) {
48.585 - return newIllegalArgumentException(message + x);
48.586 - }
48.587 - private static RuntimeException newIllegalArgumentException(String message) {
48.588 - return new IllegalArgumentException(message);
48.589 - }
48.590 -
48.591 - // primitive array support
48.592 - public Object makeArray(int len) {
48.593 - return java.lang.reflect.Array.newInstance(primitiveType, len);
48.594 - }
48.595 - public Class<?> arrayType() {
48.596 - return emptyArray.getClass();
48.597 - }
48.598 - public void copyArrayUnboxing(Object[] values, int vpos, Object a, int apos, int length) {
48.599 - if (a.getClass() != arrayType())
48.600 - arrayType().cast(a); // throw NPE or CCE if bad type
48.601 - for (int i = 0; i < length; i++) {
48.602 - Object value = values[i+vpos];
48.603 - value = convert(value, primitiveType);
48.604 - java.lang.reflect.Array.set(a, i+apos, value);
48.605 - }
48.606 - }
48.607 - public void copyArrayBoxing(Object a, int apos, Object[] values, int vpos, int length) {
48.608 - if (a.getClass() != arrayType())
48.609 - arrayType().cast(a); // throw NPE or CCE if bad type
48.610 - for (int i = 0; i < length; i++) {
48.611 - Object value = java.lang.reflect.Array.get(a, i+apos);
48.612 - //Already done: value = convert(value, primitiveType);
48.613 - assert(value.getClass() == wrapperType);
48.614 - values[i+vpos] = value;
48.615 - }
48.616 - }
48.617 -}
49.1 --- a/rt/emul/compact/src/main/java/sun/invoke/util/package-info.java Sun Aug 17 20:09:05 2014 +0200
49.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
49.3 @@ -1,31 +0,0 @@
49.4 -/*
49.5 - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
49.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
49.7 - *
49.8 - * This code is free software; you can redistribute it and/or modify it
49.9 - * under the terms of the GNU General Public License version 2 only, as
49.10 - * published by the Free Software Foundation. Oracle designates this
49.11 - * particular file as subject to the "Classpath" exception as provided
49.12 - * by Oracle in the LICENSE file that accompanied this code.
49.13 - *
49.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
49.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
49.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
49.17 - * version 2 for more details (a copy is included in the LICENSE file that
49.18 - * accompanied this code).
49.19 - *
49.20 - * You should have received a copy of the GNU General Public License version
49.21 - * 2 along with this work; if not, write to the Free Software Foundation,
49.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
49.23 - *
49.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
49.25 - * or visit www.oracle.com if you need additional information or have any
49.26 - * questions.
49.27 - */
49.28 -
49.29 -/**
49.30 - * Extra support for using JSR 292 RI, package java.lang.invoke.
49.31 - * @author jrose
49.32 - */
49.33 -
49.34 -package sun.invoke.util;