1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/MethodHandleImpl.java Sun Aug 17 20:09:05 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1014 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.lang.invoke;
1.30 -
1.31 -import java.security.AccessController;
1.32 -import java.security.PrivilegedAction;
1.33 -import java.util.ArrayList;
1.34 -import java.util.Arrays;
1.35 -import java.util.HashMap;
1.36 -import sun.invoke.empty.Empty;
1.37 -import sun.invoke.util.ValueConversions;
1.38 -import sun.invoke.util.VerifyType;
1.39 -import sun.invoke.util.Wrapper;
1.40 -import static java.lang.invoke.LambdaForm.*;
1.41 -import static java.lang.invoke.MethodHandleStatics.*;
1.42 -import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
1.43 -
1.44 -/**
1.45 - * Trusted implementation code for MethodHandle.
1.46 - * @author jrose
1.47 - */
1.48 -/*non-public*/ abstract class MethodHandleImpl {
1.49 - /// Factory methods to create method handles:
1.50 -
1.51 - static void initStatics() {
1.52 - // Trigger selected static initializations.
1.53 - MemberName.Factory.INSTANCE.getClass();
1.54 - }
1.55 -
1.56 - static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
1.57 - if (!arrayClass.isArray())
1.58 - throw newIllegalArgumentException("not an array: "+arrayClass);
1.59 - MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter);
1.60 - MethodType srcType = accessor.type().erase();
1.61 - MethodType lambdaType = srcType.invokerType();
1.62 - Name[] names = arguments(1, lambdaType);
1.63 - Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount());
1.64 - names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args);
1.65 - LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names);
1.66 - MethodHandle mh = SimpleMethodHandle.make(srcType, form);
1.67 - if (ArrayAccessor.needCast(arrayClass)) {
1.68 - mh = mh.bindTo(arrayClass);
1.69 - }
1.70 - mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter));
1.71 - return mh;
1.72 - }
1.73 -
1.74 - static final class ArrayAccessor {
1.75 - /// Support for array element access
1.76 - static final HashMap<Class<?>, MethodHandle> GETTER_CACHE = new HashMap<>(); // TODO use it
1.77 - static final HashMap<Class<?>, MethodHandle> SETTER_CACHE = new HashMap<>(); // TODO use it
1.78 -
1.79 - static int getElementI(int[] a, int i) { return a[i]; }
1.80 - static long getElementJ(long[] a, int i) { return a[i]; }
1.81 - static float getElementF(float[] a, int i) { return a[i]; }
1.82 - static double getElementD(double[] a, int i) { return a[i]; }
1.83 - static boolean getElementZ(boolean[] a, int i) { return a[i]; }
1.84 - static byte getElementB(byte[] a, int i) { return a[i]; }
1.85 - static short getElementS(short[] a, int i) { return a[i]; }
1.86 - static char getElementC(char[] a, int i) { return a[i]; }
1.87 - static Object getElementL(Object[] a, int i) { return a[i]; }
1.88 -
1.89 - static void setElementI(int[] a, int i, int x) { a[i] = x; }
1.90 - static void setElementJ(long[] a, int i, long x) { a[i] = x; }
1.91 - static void setElementF(float[] a, int i, float x) { a[i] = x; }
1.92 - static void setElementD(double[] a, int i, double x) { a[i] = x; }
1.93 - static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
1.94 - static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
1.95 - static void setElementS(short[] a, int i, short x) { a[i] = x; }
1.96 - static void setElementC(char[] a, int i, char x) { a[i] = x; }
1.97 - static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
1.98 -
1.99 - static Object getElementL(Class<?> arrayClass, Object[] a, int i) { arrayClass.cast(a); return a[i]; }
1.100 - static void setElementL(Class<?> arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; }
1.101 -
1.102 - // Weakly typed wrappers of Object[] accessors:
1.103 - static Object getElementL(Object a, int i) { return getElementL((Object[])a, i); }
1.104 - static void setElementL(Object a, int i, Object x) { setElementL((Object[]) a, i, x); }
1.105 - static Object getElementL(Object arrayClass, Object a, int i) { return getElementL((Class<?>) arrayClass, (Object[])a, i); }
1.106 - static void setElementL(Object arrayClass, Object a, int i, Object x) { setElementL((Class<?>) arrayClass, (Object[])a, i, x); }
1.107 -
1.108 - static boolean needCast(Class<?> arrayClass) {
1.109 - Class<?> elemClass = arrayClass.getComponentType();
1.110 - return !elemClass.isPrimitive() && elemClass != Object.class;
1.111 - }
1.112 - static String name(Class<?> arrayClass, boolean isSetter) {
1.113 - Class<?> elemClass = arrayClass.getComponentType();
1.114 - if (elemClass == null) throw new IllegalArgumentException();
1.115 - return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass);
1.116 - }
1.117 - static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false; // FIXME: decide
1.118 - static MethodType type(Class<?> arrayClass, boolean isSetter) {
1.119 - Class<?> elemClass = arrayClass.getComponentType();
1.120 - Class<?> arrayArgClass = arrayClass;
1.121 - if (!elemClass.isPrimitive()) {
1.122 - arrayArgClass = Object[].class;
1.123 - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
1.124 - arrayArgClass = Object.class;
1.125 - }
1.126 - if (!needCast(arrayClass)) {
1.127 - return !isSetter ?
1.128 - MethodType.methodType(elemClass, arrayArgClass, int.class) :
1.129 - MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
1.130 - } else {
1.131 - Class<?> classArgClass = Class.class;
1.132 - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS)
1.133 - classArgClass = Object.class;
1.134 - return !isSetter ?
1.135 - MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) :
1.136 - MethodType.methodType(void.class, classArgClass, arrayArgClass, int.class, Object.class);
1.137 - }
1.138 - }
1.139 - static MethodType correctType(Class<?> arrayClass, boolean isSetter) {
1.140 - Class<?> elemClass = arrayClass.getComponentType();
1.141 - return !isSetter ?
1.142 - MethodType.methodType(elemClass, arrayClass, int.class) :
1.143 - MethodType.methodType(void.class, arrayClass, int.class, elemClass);
1.144 - }
1.145 - static MethodHandle getAccessor(Class<?> arrayClass, boolean isSetter) {
1.146 - String name = name(arrayClass, isSetter);
1.147 - MethodType type = type(arrayClass, isSetter);
1.148 - try {
1.149 - return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
1.150 - } catch (ReflectiveOperationException ex) {
1.151 - throw uncaughtException(ex);
1.152 - }
1.153 - }
1.154 - }
1.155 -
1.156 - /**
1.157 - * Create a JVM-level adapter method handle to conform the given method
1.158 - * handle to the similar newType, using only pairwise argument conversions.
1.159 - * For each argument, convert incoming argument to the exact type needed.
1.160 - * The argument conversions allowed are casting, boxing and unboxing,
1.161 - * integral widening or narrowing, and floating point widening or narrowing.
1.162 - * @param srcType required call type
1.163 - * @param target original method handle
1.164 - * @param level which strength of conversion is allowed
1.165 - * @return an adapter to the original handle with the desired new type,
1.166 - * or the original target if the types are already identical
1.167 - * or null if the adaptation cannot be made
1.168 - */
1.169 - static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) {
1.170 - assert(level >= 0 && level <= 2);
1.171 - MethodType dstType = target.type();
1.172 - assert(dstType.parameterCount() == target.type().parameterCount());
1.173 - if (srcType == dstType)
1.174 - return target;
1.175 -
1.176 - // Calculate extra arguments (temporaries) required in the names array.
1.177 - // FIXME: Use an ArrayList<Name>. Some arguments require more than one conversion step.
1.178 - final int INARG_COUNT = srcType.parameterCount();
1.179 - int conversions = 0;
1.180 - boolean[] needConv = new boolean[1+INARG_COUNT];
1.181 - for (int i = 0; i <= INARG_COUNT; i++) {
1.182 - Class<?> src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i);
1.183 - Class<?> dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i);
1.184 - if (!VerifyType.isNullConversion(src, dst) ||
1.185 - level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) {
1.186 - needConv[i] = true;
1.187 - conversions++;
1.188 - }
1.189 - }
1.190 - boolean retConv = needConv[INARG_COUNT];
1.191 -
1.192 - final int IN_MH = 0;
1.193 - final int INARG_BASE = 1;
1.194 - final int INARG_LIMIT = INARG_BASE + INARG_COUNT;
1.195 - final int NAME_LIMIT = INARG_LIMIT + conversions + 1;
1.196 - final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1);
1.197 - final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
1.198 -
1.199 - // Now build a LambdaForm.
1.200 - MethodType lambdaType = srcType.basicType().invokerType();
1.201 - Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
1.202 -
1.203 - // Collect the arguments to the outgoing call, maybe with conversions:
1.204 - final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0]
1.205 - Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
1.206 -
1.207 - int nameCursor = INARG_LIMIT;
1.208 - for (int i = 0; i < INARG_COUNT; i++) {
1.209 - Class<?> src = srcType.parameterType(i);
1.210 - Class<?> dst = dstType.parameterType(i);
1.211 -
1.212 - if (!needConv[i]) {
1.213 - // do nothing: difference is trivial
1.214 - outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
1.215 - continue;
1.216 - }
1.217 -
1.218 - // Tricky case analysis follows.
1.219 - MethodHandle fn = null;
1.220 - if (src.isPrimitive()) {
1.221 - if (dst.isPrimitive()) {
1.222 - fn = ValueConversions.convertPrimitive(src, dst);
1.223 - } else {
1.224 - Wrapper w = Wrapper.forPrimitiveType(src);
1.225 - MethodHandle boxMethod = ValueConversions.box(w);
1.226 - if (dst == w.wrapperType())
1.227 - fn = boxMethod;
1.228 - else
1.229 - fn = boxMethod.asType(MethodType.methodType(dst, src));
1.230 - }
1.231 - } else {
1.232 - if (dst.isPrimitive()) {
1.233 - // Caller has boxed a primitive. Unbox it for the target.
1.234 - Wrapper w = Wrapper.forPrimitiveType(dst);
1.235 - if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) {
1.236 - fn = ValueConversions.unbox(dst);
1.237 - } else if (src == Object.class || !Wrapper.isWrapperType(src)) {
1.238 - // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int
1.239 - // must include additional conversions
1.240 - // src must be examined at runtime, to detect Byte, Character, etc.
1.241 - MethodHandle unboxMethod = (level == 1
1.242 - ? ValueConversions.unbox(dst)
1.243 - : ValueConversions.unboxCast(dst));
1.244 - fn = unboxMethod;
1.245 - } else {
1.246 - // Example: Byte->int
1.247 - // Do this by reformulating the problem to Byte->byte.
1.248 - Class<?> srcPrim = Wrapper.forWrapperType(src).primitiveType();
1.249 - MethodHandle unbox = ValueConversions.unbox(srcPrim);
1.250 - // Compose the two conversions. FIXME: should make two Names for this job
1.251 - fn = unbox.asType(MethodType.methodType(dst, src));
1.252 - }
1.253 - } else {
1.254 - // Simple reference conversion.
1.255 - // Note: Do not check for a class hierarchy relation
1.256 - // between src and dst. In all cases a 'null' argument
1.257 - // will pass the cast conversion.
1.258 - fn = ValueConversions.cast(dst);
1.259 - }
1.260 - }
1.261 - Name conv = new Name(fn, names[INARG_BASE + i]);
1.262 - assert(names[nameCursor] == null);
1.263 - names[nameCursor++] = conv;
1.264 - assert(outArgs[OUTARG_BASE + i] == null);
1.265 - outArgs[OUTARG_BASE + i] = conv;
1.266 - }
1.267 -
1.268 - // Build argument array for the call.
1.269 - assert(nameCursor == OUT_CALL);
1.270 - names[OUT_CALL] = new Name(target, outArgs);
1.271 -
1.272 - if (RETURN_CONV < 0) {
1.273 - assert(OUT_CALL == names.length-1);
1.274 - } else {
1.275 - Class<?> needReturn = srcType.returnType();
1.276 - Class<?> haveReturn = dstType.returnType();
1.277 - MethodHandle fn;
1.278 - Object[] arg = { names[OUT_CALL] };
1.279 - if (haveReturn == void.class) {
1.280 - // synthesize a zero value for the given void
1.281 - Object zero = Wrapper.forBasicType(needReturn).zero();
1.282 - fn = MethodHandles.constant(needReturn, zero);
1.283 - arg = new Object[0]; // don't pass names[OUT_CALL] to conversion
1.284 - } else {
1.285 - MethodHandle identity = MethodHandles.identity(needReturn);
1.286 - MethodType needConversion = identity.type().changeParameterType(0, haveReturn);
1.287 - fn = makePairwiseConvert(identity, needConversion, level);
1.288 - }
1.289 - assert(names[RETURN_CONV] == null);
1.290 - names[RETURN_CONV] = new Name(fn, arg);
1.291 - assert(RETURN_CONV == names.length-1);
1.292 - }
1.293 -
1.294 - LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names);
1.295 - return SimpleMethodHandle.make(srcType, form);
1.296 - }
1.297 -
1.298 - static MethodHandle makeReferenceIdentity(Class<?> refType) {
1.299 - MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
1.300 - Name[] names = arguments(1, lambdaType);
1.301 - names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
1.302 - LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
1.303 - return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
1.304 - }
1.305 -
1.306 - static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
1.307 - MethodType type = target.type();
1.308 - int last = type.parameterCount() - 1;
1.309 - if (type.parameterType(last) != arrayType)
1.310 - target = target.asType(type.changeParameterType(last, arrayType));
1.311 - target = target.asFixedArity(); // make sure this attribute is turned off
1.312 - return new AsVarargsCollector(target, target.type(), arrayType);
1.313 - }
1.314 -
1.315 - static class AsVarargsCollector extends MethodHandle {
1.316 - private final MethodHandle target;
1.317 - private final Class<?> arrayType;
1.318 - private /*@Stable*/ MethodHandle asCollectorCache;
1.319 -
1.320 - AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
1.321 - super(type, reinvokerForm(target));
1.322 - this.target = target;
1.323 - this.arrayType = arrayType;
1.324 - this.asCollectorCache = target.asCollector(arrayType, 0);
1.325 - }
1.326 -
1.327 - @Override MethodHandle reinvokerTarget() { return target; }
1.328 -
1.329 - @Override
1.330 - public boolean isVarargsCollector() {
1.331 - return true;
1.332 - }
1.333 -
1.334 - @Override
1.335 - public MethodHandle asFixedArity() {
1.336 - return target;
1.337 - }
1.338 -
1.339 - @Override
1.340 - public MethodHandle asTypeUncached(MethodType newType) {
1.341 - MethodType type = this.type();
1.342 - int collectArg = type.parameterCount() - 1;
1.343 - int newArity = newType.parameterCount();
1.344 - if (newArity == collectArg+1 &&
1.345 - type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
1.346 - // if arity and trailing parameter are compatible, do normal thing
1.347 - return asTypeCache = asFixedArity().asType(newType);
1.348 - }
1.349 - // check cache
1.350 - MethodHandle acc = asCollectorCache;
1.351 - if (acc != null && acc.type().parameterCount() == newArity)
1.352 - return asTypeCache = acc.asType(newType);
1.353 - // build and cache a collector
1.354 - int arrayLength = newArity - collectArg;
1.355 - MethodHandle collector;
1.356 - try {
1.357 - collector = asFixedArity().asCollector(arrayType, arrayLength);
1.358 - assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
1.359 - } catch (IllegalArgumentException ex) {
1.360 - throw new WrongMethodTypeException("cannot build collector", ex);
1.361 - }
1.362 - asCollectorCache = collector;
1.363 - return asTypeCache = collector.asType(newType);
1.364 - }
1.365 -
1.366 - @Override
1.367 - MethodHandle setVarargs(MemberName member) {
1.368 - if (member.isVarargs()) return this;
1.369 - return asFixedArity();
1.370 - }
1.371 -
1.372 - @Override
1.373 - MethodHandle viewAsType(MethodType newType) {
1.374 - if (newType.lastParameterType() != type().lastParameterType())
1.375 - throw new InternalError();
1.376 - MethodHandle newTarget = asFixedArity().viewAsType(newType);
1.377 - // put back the varargs bit:
1.378 - return new AsVarargsCollector(newTarget, newType, arrayType);
1.379 - }
1.380 -
1.381 - @Override
1.382 - MemberName internalMemberName() {
1.383 - return asFixedArity().internalMemberName();
1.384 - }
1.385 - @Override
1.386 - Class<?> internalCallerClass() {
1.387 - return asFixedArity().internalCallerClass();
1.388 - }
1.389 -
1.390 - /*non-public*/
1.391 - @Override
1.392 - boolean isInvokeSpecial() {
1.393 - return asFixedArity().isInvokeSpecial();
1.394 - }
1.395 -
1.396 -
1.397 - @Override
1.398 - MethodHandle bindArgument(int pos, char basicType, Object value) {
1.399 - return asFixedArity().bindArgument(pos, basicType, value);
1.400 - }
1.401 -
1.402 - @Override
1.403 - MethodHandle bindReceiver(Object receiver) {
1.404 - return asFixedArity().bindReceiver(receiver);
1.405 - }
1.406 -
1.407 - @Override
1.408 - MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
1.409 - return asFixedArity().dropArguments(srcType, pos, drops);
1.410 - }
1.411 -
1.412 - @Override
1.413 - MethodHandle permuteArguments(MethodType newType, int[] reorder) {
1.414 - return asFixedArity().permuteArguments(newType, reorder);
1.415 - }
1.416 - }
1.417 -
1.418 - /** Factory method: Spread selected argument. */
1.419 - static MethodHandle makeSpreadArguments(MethodHandle target,
1.420 - Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
1.421 - MethodType targetType = target.type();
1.422 -
1.423 - for (int i = 0; i < spreadArgCount; i++) {
1.424 - Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
1.425 - if (arg == null) arg = Object.class;
1.426 - targetType = targetType.changeParameterType(spreadArgPos + i, arg);
1.427 - }
1.428 - target = target.asType(targetType);
1.429 -
1.430 - MethodType srcType = targetType
1.431 - .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
1.432 - // Now build a LambdaForm.
1.433 - MethodType lambdaType = srcType.invokerType();
1.434 - Name[] names = arguments(spreadArgCount + 2, lambdaType);
1.435 - int nameCursor = lambdaType.parameterCount();
1.436 - int[] indexes = new int[targetType.parameterCount()];
1.437 -
1.438 - for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
1.439 - Class<?> src = lambdaType.parameterType(i);
1.440 - if (i == spreadArgPos) {
1.441 - // Spread the array.
1.442 - MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
1.443 - Name array = names[argIndex];
1.444 - names[nameCursor++] = new Name(Lazy.NF_checkSpreadArgument, array, spreadArgCount);
1.445 - for (int j = 0; j < spreadArgCount; i++, j++) {
1.446 - indexes[i] = nameCursor;
1.447 - names[nameCursor++] = new Name(aload, array, j);
1.448 - }
1.449 - } else if (i < indexes.length) {
1.450 - indexes[i] = argIndex;
1.451 - }
1.452 - }
1.453 - assert(nameCursor == names.length-1); // leave room for the final call
1.454 -
1.455 - // Build argument array for the call.
1.456 - Name[] targetArgs = new Name[targetType.parameterCount()];
1.457 - for (int i = 0; i < targetType.parameterCount(); i++) {
1.458 - int idx = indexes[i];
1.459 - targetArgs[i] = names[idx];
1.460 - }
1.461 - names[names.length - 1] = new Name(target, (Object[]) targetArgs);
1.462 -
1.463 - LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names);
1.464 - return SimpleMethodHandle.make(srcType, form);
1.465 - }
1.466 -
1.467 - static void checkSpreadArgument(Object av, int n) {
1.468 - if (av == null) {
1.469 - if (n == 0) return;
1.470 - } else if (av instanceof Object[]) {
1.471 - int len = ((Object[])av).length;
1.472 - if (len == n) return;
1.473 - } else {
1.474 - int len = java.lang.reflect.Array.getLength(av);
1.475 - if (len == n) return;
1.476 - }
1.477 - // fall through to error:
1.478 - throw newIllegalArgumentException("array is not of length "+n);
1.479 - }
1.480 -
1.481 - /**
1.482 - * Pre-initialized NamedFunctions for bootstrapping purposes.
1.483 - * Factored in an inner class to delay initialization until first usage.
1.484 - */
1.485 - private static class Lazy {
1.486 - static final NamedFunction NF_checkSpreadArgument;
1.487 - static {
1.488 - try {
1.489 - NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class
1.490 - .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
1.491 - NF_checkSpreadArgument.resolve();
1.492 - } catch (ReflectiveOperationException ex) {
1.493 - throw newInternalError(ex);
1.494 - }
1.495 - }
1.496 - }
1.497 -
1.498 - /** Factory method: Collect or filter selected argument(s). */
1.499 - static MethodHandle makeCollectArguments(MethodHandle target,
1.500 - MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
1.501 - MethodType targetType = target.type(); // (a..., c, [b...])=>r
1.502 - MethodType collectorType = collector.type(); // (b...)=>c
1.503 - int collectArgCount = collectorType.parameterCount();
1.504 - Class<?> collectValType = collectorType.returnType();
1.505 - int collectValCount = (collectValType == void.class ? 0 : 1);
1.506 - MethodType srcType = targetType // (a..., [b...])=>r
1.507 - .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
1.508 - if (!retainOriginalArgs) { // (a..., b...)=>r
1.509 - srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList());
1.510 - }
1.511 - // in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ]
1.512 - // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ]
1.513 - // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ]
1.514 -
1.515 - // Now build a LambdaForm.
1.516 - MethodType lambdaType = srcType.invokerType();
1.517 - Name[] names = arguments(2, lambdaType);
1.518 - final int collectNamePos = names.length - 2;
1.519 - final int targetNamePos = names.length - 1;
1.520 -
1.521 - Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
1.522 - names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
1.523 -
1.524 - // Build argument array for the target.
1.525 - // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ].
1.526 - // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ].
1.527 - Name[] targetArgs = new Name[targetType.parameterCount()];
1.528 - int inputArgPos = 1; // incoming LF args to copy to target
1.529 - int targetArgPos = 0; // fill pointer for targetArgs
1.530 - int chunk = collectArgPos; // |headArgs|
1.531 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
1.532 - inputArgPos += chunk;
1.533 - targetArgPos += chunk;
1.534 - if (collectValType != void.class) {
1.535 - targetArgs[targetArgPos++] = names[collectNamePos];
1.536 - }
1.537 - chunk = collectArgCount;
1.538 - if (retainOriginalArgs) {
1.539 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
1.540 - targetArgPos += chunk; // optionally pass on the collected chunk
1.541 - }
1.542 - inputArgPos += chunk;
1.543 - chunk = targetArgs.length - targetArgPos; // all the rest
1.544 - System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
1.545 - assert(inputArgPos + chunk == collectNamePos); // use of rest of input args also
1.546 - names[targetNamePos] = new Name(target, (Object[]) targetArgs);
1.547 -
1.548 - LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
1.549 - return SimpleMethodHandle.make(srcType, form);
1.550 - }
1.551 -
1.552 - static
1.553 - MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
1.554 - return testResult ? target : fallback;
1.555 - }
1.556 -
1.557 - static MethodHandle SELECT_ALTERNATIVE;
1.558 - static MethodHandle selectAlternative() {
1.559 - if (SELECT_ALTERNATIVE != null) return SELECT_ALTERNATIVE;
1.560 - try {
1.561 - SELECT_ALTERNATIVE
1.562 - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
1.563 - MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
1.564 - } catch (ReflectiveOperationException ex) {
1.565 - throw new RuntimeException(ex);
1.566 - }
1.567 - return SELECT_ALTERNATIVE;
1.568 - }
1.569 -
1.570 - static
1.571 - MethodHandle makeGuardWithTest(MethodHandle test,
1.572 - MethodHandle target,
1.573 - MethodHandle fallback) {
1.574 - MethodType basicType = target.type().basicType();
1.575 - MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType);
1.576 - int arity = basicType.parameterCount();
1.577 - int extraNames = 3;
1.578 - MethodType lambdaType = basicType.invokerType();
1.579 - Name[] names = arguments(extraNames, lambdaType);
1.580 -
1.581 - Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class);
1.582 - Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class);
1.583 -
1.584 - // call test
1.585 - names[arity + 1] = new Name(test, testArgs);
1.586 -
1.587 - // call selectAlternative
1.588 - Object[] selectArgs = { names[arity + 1], target, fallback };
1.589 - names[arity + 2] = new Name(MethodHandleImpl.selectAlternative(), selectArgs);
1.590 - targetArgs[0] = names[arity + 2];
1.591 -
1.592 - // call target or fallback
1.593 - names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs);
1.594 -
1.595 - LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
1.596 - return SimpleMethodHandle.make(target.type(), form);
1.597 - }
1.598 -
1.599 - private static class GuardWithCatch {
1.600 - private final MethodHandle target;
1.601 - private final Class<? extends Throwable> exType;
1.602 - private final MethodHandle catcher;
1.603 - // FIXME: Build the control flow out of foldArguments.
1.604 - GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
1.605 - this.target = target;
1.606 - this.exType = exType;
1.607 - this.catcher = catcher;
1.608 - }
1.609 - @LambdaForm.Hidden
1.610 - private Object invoke_V(Object... av) throws Throwable {
1.611 - try {
1.612 - return target.invokeExact(av);
1.613 - } catch (Throwable t) {
1.614 - if (!exType.isInstance(t)) throw t;
1.615 - return catcher.invokeExact(t, av);
1.616 - }
1.617 - }
1.618 - @LambdaForm.Hidden
1.619 - private Object invoke_L0() throws Throwable {
1.620 - try {
1.621 - return target.invokeExact();
1.622 - } catch (Throwable t) {
1.623 - if (!exType.isInstance(t)) throw t;
1.624 - return catcher.invokeExact(t);
1.625 - }
1.626 - }
1.627 - @LambdaForm.Hidden
1.628 - private Object invoke_L1(Object a0) throws Throwable {
1.629 - try {
1.630 - return target.invokeExact(a0);
1.631 - } catch (Throwable t) {
1.632 - if (!exType.isInstance(t)) throw t;
1.633 - return catcher.invokeExact(t, a0);
1.634 - }
1.635 - }
1.636 - @LambdaForm.Hidden
1.637 - private Object invoke_L2(Object a0, Object a1) throws Throwable {
1.638 - try {
1.639 - return target.invokeExact(a0, a1);
1.640 - } catch (Throwable t) {
1.641 - if (!exType.isInstance(t)) throw t;
1.642 - return catcher.invokeExact(t, a0, a1);
1.643 - }
1.644 - }
1.645 - @LambdaForm.Hidden
1.646 - private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
1.647 - try {
1.648 - return target.invokeExact(a0, a1, a2);
1.649 - } catch (Throwable t) {
1.650 - if (!exType.isInstance(t)) throw t;
1.651 - return catcher.invokeExact(t, a0, a1, a2);
1.652 - }
1.653 - }
1.654 - @LambdaForm.Hidden
1.655 - private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
1.656 - try {
1.657 - return target.invokeExact(a0, a1, a2, a3);
1.658 - } catch (Throwable t) {
1.659 - if (!exType.isInstance(t)) throw t;
1.660 - return catcher.invokeExact(t, a0, a1, a2, a3);
1.661 - }
1.662 - }
1.663 - @LambdaForm.Hidden
1.664 - private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
1.665 - try {
1.666 - return target.invokeExact(a0, a1, a2, a3, a4);
1.667 - } catch (Throwable t) {
1.668 - if (!exType.isInstance(t)) throw t;
1.669 - return catcher.invokeExact(t, a0, a1, a2, a3, a4);
1.670 - }
1.671 - }
1.672 - @LambdaForm.Hidden
1.673 - private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
1.674 - try {
1.675 - return target.invokeExact(a0, a1, a2, a3, a4, a5);
1.676 - } catch (Throwable t) {
1.677 - if (!exType.isInstance(t)) throw t;
1.678 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
1.679 - }
1.680 - }
1.681 - @LambdaForm.Hidden
1.682 - private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
1.683 - try {
1.684 - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
1.685 - } catch (Throwable t) {
1.686 - if (!exType.isInstance(t)) throw t;
1.687 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
1.688 - }
1.689 - }
1.690 - @LambdaForm.Hidden
1.691 - private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
1.692 - try {
1.693 - return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
1.694 - } catch (Throwable t) {
1.695 - if (!exType.isInstance(t)) throw t;
1.696 - return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
1.697 - }
1.698 - }
1.699 - static MethodHandle[] makeInvokes() {
1.700 - ArrayList<MethodHandle> invokes = new ArrayList<>();
1.701 - MethodHandles.Lookup lookup = IMPL_LOOKUP;
1.702 - for (;;) {
1.703 - int nargs = invokes.size();
1.704 - String name = "invoke_L"+nargs;
1.705 - MethodHandle invoke = null;
1.706 - try {
1.707 - invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
1.708 - } catch (ReflectiveOperationException ex) {
1.709 - }
1.710 - if (invoke == null) break;
1.711 - invokes.add(invoke);
1.712 - }
1.713 - assert(invokes.size() == 9); // current number of methods
1.714 - return invokes.toArray(new MethodHandle[0]);
1.715 - };
1.716 - static final MethodHandle[] INVOKES = makeInvokes();
1.717 - // For testing use this:
1.718 - //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
1.719 - static final MethodHandle VARARGS_INVOKE;
1.720 - static {
1.721 - try {
1.722 - VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
1.723 - } catch (ReflectiveOperationException ex) {
1.724 - throw uncaughtException(ex);
1.725 - }
1.726 - }
1.727 - }
1.728 -
1.729 -
1.730 - static
1.731 - MethodHandle makeGuardWithCatch(MethodHandle target,
1.732 - Class<? extends Throwable> exType,
1.733 - MethodHandle catcher) {
1.734 - MethodType type = target.type();
1.735 - MethodType ctype = catcher.type();
1.736 - int nargs = type.parameterCount();
1.737 - if (nargs < GuardWithCatch.INVOKES.length) {
1.738 - MethodType gtype = type.generic();
1.739 - MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
1.740 - // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
1.741 - MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
1.742 - MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
1.743 - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
1.744 - if (gtarget == null || gcatcher == null) throw new InternalError();
1.745 - MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
1.746 - return makePairwiseConvert(ginvoker, type, 2);
1.747 - } else {
1.748 - target = target.asType(type.changeReturnType(Object.class));
1.749 - MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
1.750 - MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
1.751 - .changeReturnType(Object.class);
1.752 - catcher = catcher.asType(catcherType);
1.753 - MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
1.754 - GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
1.755 - if (gtarget == null || gcatcher == null) throw new InternalError();
1.756 - MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
1.757 - MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
1.758 - return makePairwiseConvert(gcollect, type, 2);
1.759 - }
1.760 - }
1.761 -
1.762 - static
1.763 - MethodHandle throwException(MethodType type) {
1.764 - assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
1.765 - int arity = type.parameterCount();
1.766 - if (arity > 1) {
1.767 - return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
1.768 - }
1.769 - return makePairwiseConvert(throwException(), type, 2);
1.770 - }
1.771 -
1.772 - static MethodHandle THROW_EXCEPTION;
1.773 - static MethodHandle throwException() {
1.774 - MethodHandle mh = THROW_EXCEPTION;
1.775 - if (mh != null) return mh;
1.776 - try {
1.777 - mh
1.778 - = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
1.779 - MethodType.methodType(Empty.class, Throwable.class));
1.780 - } catch (ReflectiveOperationException ex) {
1.781 - throw new RuntimeException(ex);
1.782 - }
1.783 - THROW_EXCEPTION = mh;
1.784 - return mh;
1.785 - }
1.786 - static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
1.787 -
1.788 - static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
1.789 - static MethodHandle fakeMethodHandleInvoke(MemberName method) {
1.790 - int idx;
1.791 - assert(method.isMethodHandleInvoke());
1.792 - switch (method.getName()) {
1.793 - case "invoke": idx = 0; break;
1.794 - case "invokeExact": idx = 1; break;
1.795 - default: throw new InternalError(method.getName());
1.796 - }
1.797 - MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
1.798 - if (mh != null) return mh;
1.799 - MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
1.800 - MethodHandle.class, Object[].class);
1.801 - mh = throwException(type);
1.802 - mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
1.803 - if (!method.getInvocationType().equals(mh.type()))
1.804 - throw new InternalError(method.toString());
1.805 - mh = mh.withInternalMemberName(method);
1.806 - mh = mh.asVarargsCollector(Object[].class);
1.807 - assert(method.isVarargs());
1.808 - FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
1.809 - return mh;
1.810 - }
1.811 -
1.812 - /**
1.813 - * Create an alias for the method handle which, when called,
1.814 - * appears to be called from the same class loader and protection domain
1.815 - * as hostClass.
1.816 - * This is an expensive no-op unless the method which is called
1.817 - * is sensitive to its caller. A small number of system methods
1.818 - * are in this category, including Class.forName and Method.invoke.
1.819 - */
1.820 - static
1.821 - MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1.822 - return BindCaller.bindCaller(mh, hostClass);
1.823 - }
1.824 -
1.825 - // Put the whole mess into its own nested class.
1.826 - // That way we can lazily load the code and set up the constants.
1.827 - private static class BindCaller {
1.828 - static
1.829 - MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1.830 - // Do not use this function to inject calls into system classes.
1.831 - if (hostClass == null
1.832 - || (hostClass.isArray() ||
1.833 - hostClass.isPrimitive() ||
1.834 - hostClass.getName().startsWith("java.") ||
1.835 - hostClass.getName().startsWith("sun."))) {
1.836 - throw new InternalError(); // does not happen, and should not anyway
1.837 - }
1.838 - // For simplicity, convert mh to a varargs-like method.
1.839 - MethodHandle vamh = prepareForInvoker(mh);
1.840 - // Cache the result of makeInjectedInvoker once per argument class.
1.841 - MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1.842 - return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
1.843 - }
1.844 -
1.845 - private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
1.846 - throw new IllegalStateException("Implement me too!");
1.847 - /*
1.848 - Class<?> bcc = UNSAFE.defineAnonymousClass(hostClass, T_BYTES, null);
1.849 - if (hostClass.getClassLoader() != bcc.getClassLoader())
1.850 - throw new InternalError(hostClass.getName()+" (CL)");
1.851 - try {
1.852 - if (hostClass.getProtectionDomain() != bcc.getProtectionDomain())
1.853 - throw new InternalError(hostClass.getName()+" (PD)");
1.854 - } catch (SecurityException ex) {
1.855 - // Self-check was blocked by security manager. This is OK.
1.856 - // In fact the whole try body could be turned into an assertion.
1.857 - }
1.858 - try {
1.859 - MethodHandle init = IMPL_LOOKUP.findStatic(bcc, "init", MethodType.methodType(void.class));
1.860 - init.invokeExact(); // force initialization of the class
1.861 - } catch (Throwable ex) {
1.862 - throw uncaughtException(ex);
1.863 - }
1.864 - MethodHandle bccInvoker;
1.865 - try {
1.866 - MethodType invokerMT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1.867 - bccInvoker = IMPL_LOOKUP.findStatic(bcc, "invoke_V", invokerMT);
1.868 - } catch (ReflectiveOperationException ex) {
1.869 - throw uncaughtException(ex);
1.870 - }
1.871 - // Test the invoker, to ensure that it really injects into the right place.
1.872 - try {
1.873 - MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
1.874 - Object ok = bccInvoker.invokeExact(vamh, new Object[]{hostClass, bcc});
1.875 - } catch (Throwable ex) {
1.876 - throw new InternalError(ex);
1.877 - }
1.878 - return bccInvoker;
1.879 - */
1.880 - }
1.881 - private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1.882 - @Override protected MethodHandle computeValue(Class<?> hostClass) {
1.883 - return makeInjectedInvoker(hostClass);
1.884 - }
1.885 - };
1.886 -
1.887 - // Adapt mh so that it can be called directly from an injected invoker:
1.888 - private static MethodHandle prepareForInvoker(MethodHandle mh) {
1.889 - mh = mh.asFixedArity();
1.890 - MethodType mt = mh.type();
1.891 - int arity = mt.parameterCount();
1.892 - MethodHandle vamh = mh.asType(mt.generic());
1.893 - vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
1.894 - vamh = vamh.asSpreader(Object[].class, arity);
1.895 - vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames
1.896 - return vamh;
1.897 - }
1.898 -
1.899 - // Undo the adapter effect of prepareForInvoker:
1.900 - private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
1.901 - MemberName member,
1.902 - Class<?> hostClass) {
1.903 - MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
1.904 - mh = mh.asType(type);
1.905 - mh = new WrappedMember(mh, type, member, hostClass);
1.906 - return mh;
1.907 - }
1.908 -
1.909 - private static final MethodHandle MH_checkCallerClass;
1.910 - static {
1.911 - final Class<?> THIS_CLASS = BindCaller.class;
1.912 -// assert(checkCallerClass(THIS_CLASS, THIS_CLASS));
1.913 - try {
1.914 - MH_checkCallerClass = IMPL_LOOKUP
1.915 - .findStatic(THIS_CLASS, "checkCallerClass",
1.916 - MethodType.methodType(boolean.class, Class.class, Class.class));
1.917 - assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS, THIS_CLASS));
1.918 - } catch (Throwable ex) {
1.919 - throw new InternalError(ex);
1.920 - }
1.921 - }
1.922 -
1.923 -// @CallerSensitive
1.924 -// private static boolean checkCallerClass(Class<?> expected, Class<?> expected2) {
1.925 -// // This method is called via MH_checkCallerClass and so it's
1.926 -// // correct to ask for the immediate caller here.
1.927 -// Class<?> actual = Reflection.getCallerClass();
1.928 -// if (actual != expected && actual != expected2)
1.929 -// throw new InternalError("found "+actual.getName()+", expected "+expected.getName()
1.930 -// +(expected == expected2 ? "" : ", or else "+expected2.getName()));
1.931 -// return true;
1.932 -// }
1.933 -
1.934 - private static final byte[] T_BYTES;
1.935 - static {
1.936 - final Object[] values = {null};
1.937 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
1.938 - public Void run() {
1.939 - try {
1.940 - Class<T> tClass = T.class;
1.941 - String tName = tClass.getName();
1.942 - String tResource = tName.substring(tName.lastIndexOf('.')+1)+".class";
1.943 - java.net.URLConnection uconn = tClass.getResource(tResource).openConnection();
1.944 - int len = uconn.getContentLength();
1.945 - byte[] bytes = new byte[len];
1.946 - try (java.io.InputStream str = uconn.getInputStream()) {
1.947 - int nr = str.read(bytes);
1.948 - if (nr != len) throw new java.io.IOException(tResource);
1.949 - }
1.950 - values[0] = bytes;
1.951 - } catch (java.io.IOException ex) {
1.952 - throw new InternalError(ex);
1.953 - }
1.954 - return null;
1.955 - }
1.956 - });
1.957 - T_BYTES = (byte[]) values[0];
1.958 - }
1.959 -
1.960 - // The following class is used as a template for Unsafe.defineAnonymousClass:
1.961 - private static class T {
1.962 - static void init() { } // side effect: initializes this class
1.963 - static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
1.964 - return vamh.invokeExact(args);
1.965 - }
1.966 - }
1.967 - }
1.968 -
1.969 -
1.970 - /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
1.971 - static class WrappedMember extends MethodHandle {
1.972 - private final MethodHandle target;
1.973 - private final MemberName member;
1.974 - private final Class<?> callerClass;
1.975 -
1.976 - private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class<?> callerClass) {
1.977 - super(type, reinvokerForm(target));
1.978 - this.target = target;
1.979 - this.member = member;
1.980 - this.callerClass = callerClass;
1.981 - }
1.982 -
1.983 - @Override
1.984 - MethodHandle reinvokerTarget() {
1.985 - return target;
1.986 - }
1.987 - @Override
1.988 - public MethodHandle asTypeUncached(MethodType newType) {
1.989 - // This MH is an alias for target, except for the MemberName
1.990 - // Drop the MemberName if there is any conversion.
1.991 - return asTypeCache = target.asType(newType);
1.992 - }
1.993 - @Override
1.994 - MemberName internalMemberName() {
1.995 - return member;
1.996 - }
1.997 - @Override
1.998 - Class<?> internalCallerClass() {
1.999 - return callerClass;
1.1000 - }
1.1001 - @Override
1.1002 - boolean isInvokeSpecial() {
1.1003 - return target.isInvokeSpecial();
1.1004 - }
1.1005 - @Override
1.1006 - MethodHandle viewAsType(MethodType newType) {
1.1007 - return new WrappedMember(target, newType, member, callerClass);
1.1008 - }
1.1009 - }
1.1010 -
1.1011 - static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
1.1012 - if (member.equals(target.internalMemberName()))
1.1013 - return target;
1.1014 - return new WrappedMember(target, target.type(), member, null);
1.1015 - }
1.1016 -
1.1017 -}