1 /* 2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang.invoke; 27 28 import jdk.internal.org.objectweb.asm.AnnotationVisitor; 29 import jdk.internal.org.objectweb.asm.ClassWriter; 30 import jdk.internal.org.objectweb.asm.MethodVisitor; 31 import jdk.internal.reflect.CallerSensitive; 32 import jdk.internal.reflect.Reflection; 33 import jdk.internal.vm.annotation.ForceInline; 34 import jdk.internal.vm.annotation.Stable; 35 import sun.invoke.empty.Empty; 36 import sun.invoke.util.ValueConversions; 37 import sun.invoke.util.VerifyType; 38 import sun.invoke.util.Wrapper; 39 40 import java.lang.reflect.Array; 41 import java.security.AccessController; 42 import java.security.PrivilegedAction; 43 import java.util.Arrays; 44 import java.util.Collections; 45 import java.util.Iterator; 46 import java.util.List; 47 import java.util.function.Function; 48 import java.util.stream.Stream; 49 50 import static java.lang.invoke.LambdaForm.*; 51 import static java.lang.invoke.MethodHandleStatics.*; 52 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; 53 import static jdk.internal.org.objectweb.asm.Opcodes.*; 54 55 /** 56 * Trusted implementation code for MethodHandle. 57 * @author jrose 58 */ 59 /*non-public*/ abstract class MethodHandleImpl { 60 // Do not adjust this except for special platforms: 61 private static final int MAX_ARITY; 62 static { 63 final Object[] values = { 255 }; 64 AccessController.doPrivileged(new PrivilegedAction<>() { 65 @Override 66 public Void run() { 67 values[0] = Integer.getInteger(MethodHandleImpl.class.getName()+".MAX_ARITY", 255); 68 return null; 69 } 70 }); 71 MAX_ARITY = (Integer) values[0]; 72 } 73 74 /// Factory methods to create method handles: 75 76 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) { 77 if (arrayClass == Object[].class) { 78 return ArrayAccess.objectAccessor(access); 79 } 80 if (!arrayClass.isArray()) 81 throw newIllegalArgumentException("not an array: "+arrayClass); 82 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); 83 int cacheIndex = ArrayAccess.cacheIndex(access); 84 MethodHandle mh = cache[cacheIndex]; 85 if (mh != null) return mh; 86 mh = ArrayAccessor.getAccessor(arrayClass, access); 87 MethodType correctType = ArrayAccessor.correctType(arrayClass, access); 88 if (mh.type() != correctType) { 89 assert(mh.type().parameterType(0) == Object[].class); 90 /* if access == SET */ assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class); 91 /* if access == GET */ assert(access != ArrayAccess.GET || 92 (mh.type().returnType() == Object.class && 93 correctType.parameterType(0).getComponentType() == correctType.returnType())); 94 // safe to view non-strictly, because element type follows from array type 95 mh = mh.viewAsType(correctType, false); 96 } 97 mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access)); 98 // Atomically update accessor cache. 99 synchronized(cache) { 100 if (cache[cacheIndex] == null) { 101 cache[cacheIndex] = mh; 102 } else { 103 // Throw away newly constructed accessor and use cached version. 104 mh = cache[cacheIndex]; 105 } 106 } 107 return mh; 108 } 109 110 enum ArrayAccess { 111 GET, SET, LENGTH; 112 113 // As ArrayAccess and ArrayAccessor have a circular dependency, the ArrayAccess properties cannot be stored in 114 // final fields. 115 116 static String opName(ArrayAccess a) { 117 switch (a) { 118 case GET: return "getElement"; 119 case SET: return "setElement"; 120 case LENGTH: return "length"; 121 } 122 throw unmatchedArrayAccess(a); 123 } 124 125 static MethodHandle objectAccessor(ArrayAccess a) { 126 switch (a) { 127 case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER; 128 case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER; 129 case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH; 130 } 131 throw unmatchedArrayAccess(a); 132 } 133 134 static int cacheIndex(ArrayAccess a) { 135 switch (a) { 136 case GET: return ArrayAccessor.GETTER_INDEX; 137 case SET: return ArrayAccessor.SETTER_INDEX; 138 case LENGTH: return ArrayAccessor.LENGTH_INDEX; 139 } 140 throw unmatchedArrayAccess(a); 141 } 142 143 static Intrinsic intrinsic(ArrayAccess a) { 144 switch (a) { 145 case GET: return Intrinsic.ARRAY_LOAD; 146 case SET: return Intrinsic.ARRAY_STORE; 147 case LENGTH: return Intrinsic.ARRAY_LENGTH; 148 } 149 throw unmatchedArrayAccess(a); 150 } 151 } 152 153 static InternalError unmatchedArrayAccess(ArrayAccess a) { 154 return newInternalError("should not reach here (unmatched ArrayAccess: " + a + ")"); 155 } 156 157 static final class ArrayAccessor { 158 /// Support for array element and length access 159 static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3; 160 static final ClassValue<MethodHandle[]> TYPED_ACCESSORS 161 = new ClassValue<MethodHandle[]>() { 162 @Override 163 protected MethodHandle[] computeValue(Class<?> type) { 164 return new MethodHandle[INDEX_LIMIT]; 165 } 166 }; 167 static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH; 168 static { 169 MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); 170 cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET), Intrinsic.ARRAY_LOAD); 171 cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET), Intrinsic.ARRAY_STORE); 172 cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH); 173 174 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName())); 175 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName())); 176 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName())); 177 } 178 179 static int getElementI(int[] a, int i) { return a[i]; } 180 static long getElementJ(long[] a, int i) { return a[i]; } 181 static float getElementF(float[] a, int i) { return a[i]; } 182 static double getElementD(double[] a, int i) { return a[i]; } 183 static boolean getElementZ(boolean[] a, int i) { return a[i]; } 184 static byte getElementB(byte[] a, int i) { return a[i]; } 185 static short getElementS(short[] a, int i) { return a[i]; } 186 static char getElementC(char[] a, int i) { return a[i]; } 187 static Object getElementL(Object[] a, int i) { return a[i]; } 188 189 static void setElementI(int[] a, int i, int x) { a[i] = x; } 190 static void setElementJ(long[] a, int i, long x) { a[i] = x; } 191 static void setElementF(float[] a, int i, float x) { a[i] = x; } 192 static void setElementD(double[] a, int i, double x) { a[i] = x; } 193 static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; } 194 static void setElementB(byte[] a, int i, byte x) { a[i] = x; } 195 static void setElementS(short[] a, int i, short x) { a[i] = x; } 196 static void setElementC(char[] a, int i, char x) { a[i] = x; } 197 static void setElementL(Object[] a, int i, Object x) { a[i] = x; } 198 199 static int lengthI(int[] a) { return a.length; } 200 static int lengthJ(long[] a) { return a.length; } 201 static int lengthF(float[] a) { return a.length; } 202 static int lengthD(double[] a) { return a.length; } 203 static int lengthZ(boolean[] a) { return a.length; } 204 static int lengthB(byte[] a) { return a.length; } 205 static int lengthS(short[] a) { return a.length; } 206 static int lengthC(char[] a) { return a.length; } 207 static int lengthL(Object[] a) { return a.length; } 208 209 static String name(Class<?> arrayClass, ArrayAccess access) { 210 Class<?> elemClass = arrayClass.getComponentType(); 211 if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); 212 return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass); 213 } 214 static MethodType type(Class<?> arrayClass, ArrayAccess access) { 215 Class<?> elemClass = arrayClass.getComponentType(); 216 Class<?> arrayArgClass = arrayClass; 217 if (!elemClass.isPrimitive()) { 218 arrayArgClass = Object[].class; 219 elemClass = Object.class; 220 } 221 switch (access) { 222 case GET: return MethodType.methodType(elemClass, arrayArgClass, int.class); 223 case SET: return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); 224 case LENGTH: return MethodType.methodType(int.class, arrayArgClass); 225 } 226 throw unmatchedArrayAccess(access); 227 } 228 static MethodType correctType(Class<?> arrayClass, ArrayAccess access) { 229 Class<?> elemClass = arrayClass.getComponentType(); 230 switch (access) { 231 case GET: return MethodType.methodType(elemClass, arrayClass, int.class); 232 case SET: return MethodType.methodType(void.class, arrayClass, int.class, elemClass); 233 case LENGTH: return MethodType.methodType(int.class, arrayClass); 234 } 235 throw unmatchedArrayAccess(access); 236 } 237 static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) { 238 String name = name(arrayClass, access); 239 MethodType type = type(arrayClass, access); 240 try { 241 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type); 242 } catch (ReflectiveOperationException ex) { 243 throw uncaughtException(ex); 244 } 245 } 246 } 247 248 /** 249 * Create a JVM-level adapter method handle to conform the given method 250 * handle to the similar newType, using only pairwise argument conversions. 251 * For each argument, convert incoming argument to the exact type needed. 252 * The argument conversions allowed are casting, boxing and unboxing, 253 * integral widening or narrowing, and floating point widening or narrowing. 254 * @param srcType required call type 255 * @param target original method handle 256 * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed 257 * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double) 258 * @return an adapter to the original handle with the desired new type, 259 * or the original target if the types are already identical 260 * or null if the adaptation cannot be made 261 */ 262 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, 263 boolean strict, boolean monobox) { 264 MethodType dstType = target.type(); 265 if (srcType == dstType) 266 return target; 267 return makePairwiseConvertByEditor(target, srcType, strict, monobox); 268 } 269 270 private static int countNonNull(Object[] array) { 271 int count = 0; 272 for (Object x : array) { 273 if (x != null) ++count; 274 } 275 return count; 276 } 277 278 static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType, 279 boolean strict, boolean monobox) { 280 Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); 281 int convCount = countNonNull(convSpecs); 282 if (convCount == 0) 283 return target.viewAsType(srcType, strict); 284 MethodType basicSrcType = srcType.basicType(); 285 MethodType midType = target.type().basicType(); 286 BoundMethodHandle mh = target.rebind(); 287 // FIXME: Reduce number of bindings when there is more than one Class conversion. 288 // FIXME: Reduce number of bindings when there are repeated conversions. 289 for (int i = 0; i < convSpecs.length-1; i++) { 290 Object convSpec = convSpecs[i]; 291 if (convSpec == null) continue; 292 MethodHandle fn; 293 if (convSpec instanceof Class) { 294 fn = getConstantHandle(MH_cast).bindTo(convSpec); 295 } else { 296 fn = (MethodHandle) convSpec; 297 } 298 Class<?> newType = basicSrcType.parameterType(i); 299 if (--convCount == 0) 300 midType = srcType; 301 else 302 midType = midType.changeParameterType(i, newType); 303 LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType)); 304 mh = mh.copyWithExtendL(midType, form2, fn); 305 mh = mh.rebind(); 306 } 307 Object convSpec = convSpecs[convSpecs.length-1]; 308 if (convSpec != null) { 309 MethodHandle fn; 310 if (convSpec instanceof Class) { 311 if (convSpec == void.class) 312 fn = null; 313 else 314 fn = getConstantHandle(MH_cast).bindTo(convSpec); 315 } else { 316 fn = (MethodHandle) convSpec; 317 } 318 Class<?> newType = basicSrcType.returnType(); 319 assert(--convCount == 0); 320 midType = srcType; 321 if (fn != null) { 322 mh = mh.rebind(); // rebind if too complex 323 LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false); 324 mh = mh.copyWithExtendL(midType, form2, fn); 325 } else { 326 LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true); 327 mh = mh.copyWith(midType, form2); 328 } 329 } 330 assert(convCount == 0); 331 assert(mh.type().equals(srcType)); 332 return mh; 333 } 334 335 static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, 336 boolean strict, boolean monobox) { 337 assert(target.type().parameterCount() == srcType.parameterCount()); 338 // Calculate extra arguments (temporaries) required in the names array. 339 Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); 340 final int INARG_COUNT = srcType.parameterCount(); 341 int convCount = countNonNull(convSpecs); 342 boolean retConv = (convSpecs[INARG_COUNT] != null); 343 boolean retVoid = srcType.returnType() == void.class; 344 if (retConv && retVoid) { 345 convCount -= 1; 346 retConv = false; 347 } 348 349 final int IN_MH = 0; 350 final int INARG_BASE = 1; 351 final int INARG_LIMIT = INARG_BASE + INARG_COUNT; 352 final int NAME_LIMIT = INARG_LIMIT + convCount + 1; 353 final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); 354 final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; 355 final int RESULT = (retVoid ? -1 : NAME_LIMIT - 1); 356 357 // Now build a LambdaForm. 358 MethodType lambdaType = srcType.basicType().invokerType(); 359 Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType); 360 361 // Collect the arguments to the outgoing call, maybe with conversions: 362 final int OUTARG_BASE = 0; // target MH is Name.function, name Name.arguments[0] 363 Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT]; 364 365 int nameCursor = INARG_LIMIT; 366 for (int i = 0; i < INARG_COUNT; i++) { 367 Object convSpec = convSpecs[i]; 368 if (convSpec == null) { 369 // do nothing: difference is trivial 370 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i]; 371 continue; 372 } 373 374 Name conv; 375 if (convSpec instanceof Class) { 376 Class<?> convClass = (Class<?>) convSpec; 377 conv = new Name(getConstantHandle(MH_cast), convClass, names[INARG_BASE + i]); 378 } else { 379 MethodHandle fn = (MethodHandle) convSpec; 380 conv = new Name(fn, names[INARG_BASE + i]); 381 } 382 assert(names[nameCursor] == null); 383 names[nameCursor++] = conv; 384 assert(outArgs[OUTARG_BASE + i] == null); 385 outArgs[OUTARG_BASE + i] = conv; 386 } 387 388 // Build argument array for the call. 389 assert(nameCursor == OUT_CALL); 390 names[OUT_CALL] = new Name(target, outArgs); 391 392 Object convSpec = convSpecs[INARG_COUNT]; 393 if (!retConv) { 394 assert(OUT_CALL == names.length-1); 395 } else { 396 Name conv; 397 if (convSpec == void.class) { 398 conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); 399 } else if (convSpec instanceof Class) { 400 Class<?> convClass = (Class<?>) convSpec; 401 conv = new Name(getConstantHandle(MH_cast), convClass, names[OUT_CALL]); 402 } else { 403 MethodHandle fn = (MethodHandle) convSpec; 404 if (fn.type().parameterCount() == 0) 405 conv = new Name(fn); // don't pass retval to void conversion 406 else 407 conv = new Name(fn, names[OUT_CALL]); 408 } 409 assert(names[RETURN_CONV] == null); 410 names[RETURN_CONV] = conv; 411 assert(RETURN_CONV == names.length-1); 412 } 413 414 LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); 415 return SimpleMethodHandle.make(srcType, form); 416 } 417 418 static Object[] computeValueConversions(MethodType srcType, MethodType dstType, 419 boolean strict, boolean monobox) { 420 final int INARG_COUNT = srcType.parameterCount(); 421 Object[] convSpecs = new Object[INARG_COUNT+1]; 422 for (int i = 0; i <= INARG_COUNT; i++) { 423 boolean isRet = (i == INARG_COUNT); 424 Class<?> src = isRet ? dstType.returnType() : srcType.parameterType(i); 425 Class<?> dst = isRet ? srcType.returnType() : dstType.parameterType(i); 426 if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) { 427 convSpecs[i] = valueConversion(src, dst, strict, monobox); 428 } 429 } 430 return convSpecs; 431 } 432 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, 433 boolean strict) { 434 return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false); 435 } 436 437 /** 438 * Find a conversion function from the given source to the given destination. 439 * This conversion function will be used as a LF NamedFunction. 440 * Return a Class object if a simple cast is needed. 441 * Return void.class if void is involved. 442 */ 443 static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) { 444 assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)); // caller responsibility 445 if (dst == void.class) 446 return dst; 447 MethodHandle fn; 448 if (src.isPrimitive()) { 449 if (src == void.class) { 450 return void.class; // caller must recognize this specially 451 } else if (dst.isPrimitive()) { 452 // Examples: int->byte, byte->int, boolean->int (!strict) 453 fn = ValueConversions.convertPrimitive(src, dst); 454 } else { 455 // Examples: int->Integer, boolean->Object, float->Number 456 Wrapper wsrc = Wrapper.forPrimitiveType(src); 457 fn = ValueConversions.boxExact(wsrc); 458 assert(fn.type().parameterType(0) == wsrc.primitiveType()); 459 assert(fn.type().returnType() == wsrc.wrapperType()); 460 if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) { 461 // Corner case, such as int->Long, which will probably fail. 462 MethodType mt = MethodType.methodType(dst, src); 463 if (strict) 464 fn = fn.asType(mt); 465 else 466 fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false); 467 } 468 } 469 } else if (dst.isPrimitive()) { 470 Wrapper wdst = Wrapper.forPrimitiveType(dst); 471 if (monobox || src == wdst.wrapperType()) { 472 // Use a strongly-typed unboxer, if possible. 473 fn = ValueConversions.unboxExact(wdst, strict); 474 } else { 475 // Examples: Object->int, Number->int, Comparable->int, Byte->int 476 // must include additional conversions 477 // src must be examined at runtime, to detect Byte, Character, etc. 478 fn = (strict 479 ? ValueConversions.unboxWiden(wdst) 480 : ValueConversions.unboxCast(wdst)); 481 } 482 } else { 483 // Simple reference conversion. 484 // Note: Do not check for a class hierarchy relation 485 // between src and dst. In all cases a 'null' argument 486 // will pass the cast conversion. 487 return dst; 488 } 489 assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn); 490 return fn; 491 } 492 493 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) { 494 MethodType type = target.type(); 495 int last = type.parameterCount() - 1; 496 if (type.parameterType(last) != arrayType) 497 target = target.asType(type.changeParameterType(last, arrayType)); 498 target = target.asFixedArity(); // make sure this attribute is turned off 499 return new AsVarargsCollector(target, arrayType); 500 } 501 502 private static final class AsVarargsCollector extends DelegatingMethodHandle { 503 private final MethodHandle target; 504 private final Class<?> arrayType; 505 private @Stable MethodHandle asCollectorCache; 506 507 AsVarargsCollector(MethodHandle target, Class<?> arrayType) { 508 this(target.type(), target, arrayType); 509 } 510 AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) { 511 super(type, target); 512 this.target = target; 513 this.arrayType = arrayType; 514 this.asCollectorCache = target.asCollector(arrayType, 0); 515 } 516 517 @Override 518 public boolean isVarargsCollector() { 519 return true; 520 } 521 522 @Override 523 protected MethodHandle getTarget() { 524 return target; 525 } 526 527 @Override 528 public MethodHandle asFixedArity() { 529 return target; 530 } 531 532 @Override 533 MethodHandle setVarargs(MemberName member) { 534 if (member.isVarargs()) return this; 535 return asFixedArity(); 536 } 537 538 @Override 539 public MethodHandle asTypeUncached(MethodType newType) { 540 MethodType type = this.type(); 541 int collectArg = type.parameterCount() - 1; 542 int newArity = newType.parameterCount(); 543 if (newArity == collectArg+1 && 544 type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) { 545 // if arity and trailing parameter are compatible, do normal thing 546 return asTypeCache = asFixedArity().asType(newType); 547 } 548 // check cache 549 MethodHandle acc = asCollectorCache; 550 if (acc != null && acc.type().parameterCount() == newArity) 551 return asTypeCache = acc.asType(newType); 552 // build and cache a collector 553 int arrayLength = newArity - collectArg; 554 MethodHandle collector; 555 try { 556 collector = asFixedArity().asCollector(arrayType, arrayLength); 557 assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector; 558 } catch (IllegalArgumentException ex) { 559 throw new WrongMethodTypeException("cannot build collector", ex); 560 } 561 asCollectorCache = collector; 562 return asTypeCache = collector.asType(newType); 563 } 564 565 @Override 566 boolean viewAsTypeChecks(MethodType newType, boolean strict) { 567 super.viewAsTypeChecks(newType, true); 568 if (strict) return true; 569 // extra assertion for non-strict checks: 570 assert (type().lastParameterType().getComponentType() 571 .isAssignableFrom( 572 newType.lastParameterType().getComponentType())) 573 : Arrays.asList(this, newType); 574 return true; 575 } 576 } 577 578 /** Factory method: Spread selected argument. */ 579 static MethodHandle makeSpreadArguments(MethodHandle target, 580 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) { 581 MethodType targetType = target.type(); 582 583 for (int i = 0; i < spreadArgCount; i++) { 584 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i); 585 if (arg == null) arg = Object.class; 586 targetType = targetType.changeParameterType(spreadArgPos + i, arg); 587 } 588 target = target.asType(targetType); 589 590 MethodType srcType = targetType 591 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType); 592 // Now build a LambdaForm. 593 MethodType lambdaType = srcType.invokerType(); 594 Name[] names = arguments(spreadArgCount + 2, lambdaType); 595 int nameCursor = lambdaType.parameterCount(); 596 int[] indexes = new int[targetType.parameterCount()]; 597 598 for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) { 599 Class<?> src = lambdaType.parameterType(i); 600 if (i == spreadArgPos) { 601 // Spread the array. 602 MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType); 603 Name array = names[argIndex]; 604 names[nameCursor++] = new Name(NF_checkSpreadArgument, array, spreadArgCount); 605 for (int j = 0; j < spreadArgCount; i++, j++) { 606 indexes[i] = nameCursor; 607 names[nameCursor++] = new Name(aload, array, j); 608 } 609 } else if (i < indexes.length) { 610 indexes[i] = argIndex; 611 } 612 } 613 assert(nameCursor == names.length-1); // leave room for the final call 614 615 // Build argument array for the call. 616 Name[] targetArgs = new Name[targetType.parameterCount()]; 617 for (int i = 0; i < targetType.parameterCount(); i++) { 618 int idx = indexes[i]; 619 targetArgs[i] = names[idx]; 620 } 621 names[names.length - 1] = new Name(target, (Object[]) targetArgs); 622 623 LambdaForm form = new LambdaForm("spread", lambdaType.parameterCount(), names); 624 return SimpleMethodHandle.make(srcType, form); 625 } 626 627 static void checkSpreadArgument(Object av, int n) { 628 if (av == null) { 629 if (n == 0) return; 630 } else if (av instanceof Object[]) { 631 int len = ((Object[])av).length; 632 if (len == n) return; 633 } else { 634 int len = java.lang.reflect.Array.getLength(av); 635 if (len == n) return; 636 } 637 // fall through to error: 638 throw newIllegalArgumentException("array is not of length "+n); 639 } 640 641 /** Factory method: Collect or filter selected argument(s). */ 642 static MethodHandle makeCollectArguments(MethodHandle target, 643 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) { 644 MethodType targetType = target.type(); // (a..., c, [b...])=>r 645 MethodType collectorType = collector.type(); // (b...)=>c 646 int collectArgCount = collectorType.parameterCount(); 647 Class<?> collectValType = collectorType.returnType(); 648 int collectValCount = (collectValType == void.class ? 0 : 1); 649 MethodType srcType = targetType // (a..., [b...])=>r 650 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount); 651 if (!retainOriginalArgs) { // (a..., b...)=>r 652 srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterList()); 653 } 654 // in arglist: [0: ...keep1 | cpos: collect... | cpos+cacount: keep2... ] 655 // out arglist: [0: ...keep1 | cpos: collectVal? | cpos+cvcount: keep2... ] 656 // out(retain): [0: ...keep1 | cpos: cV? coll... | cpos+cvc+cac: keep2... ] 657 658 // Now build a LambdaForm. 659 MethodType lambdaType = srcType.invokerType(); 660 Name[] names = arguments(2, lambdaType); 661 final int collectNamePos = names.length - 2; 662 final int targetNamePos = names.length - 1; 663 664 Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount); 665 names[collectNamePos] = new Name(collector, (Object[]) collectorArgs); 666 667 // Build argument array for the target. 668 // Incoming LF args to copy are: [ (mh) headArgs collectArgs tailArgs ]. 669 // Output argument array is [ headArgs (collectVal)? (collectArgs)? tailArgs ]. 670 Name[] targetArgs = new Name[targetType.parameterCount()]; 671 int inputArgPos = 1; // incoming LF args to copy to target 672 int targetArgPos = 0; // fill pointer for targetArgs 673 int chunk = collectArgPos; // |headArgs| 674 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk); 675 inputArgPos += chunk; 676 targetArgPos += chunk; 677 if (collectValType != void.class) { 678 targetArgs[targetArgPos++] = names[collectNamePos]; 679 } 680 chunk = collectArgCount; 681 if (retainOriginalArgs) { 682 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk); 683 targetArgPos += chunk; // optionally pass on the collected chunk 684 } 685 inputArgPos += chunk; 686 chunk = targetArgs.length - targetArgPos; // all the rest 687 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk); 688 assert(inputArgPos + chunk == collectNamePos); // use of rest of input args also 689 names[targetNamePos] = new Name(target, (Object[]) targetArgs); 690 691 LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names); 692 return SimpleMethodHandle.make(srcType, form); 693 } 694 695 @LambdaForm.Hidden 696 static 697 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) { 698 if (testResult) { 699 return target; 700 } else { 701 return fallback; 702 } 703 } 704 705 // Intrinsified by C2. Counters are used during parsing to calculate branch frequencies. 706 @LambdaForm.Hidden 707 @jdk.internal.HotSpotIntrinsicCandidate 708 static 709 boolean profileBoolean(boolean result, int[] counters) { 710 // Profile is int[2] where [0] and [1] correspond to false and true occurrences respectively. 711 int idx = result ? 1 : 0; 712 try { 713 counters[idx] = Math.addExact(counters[idx], 1); 714 } catch (ArithmeticException e) { 715 // Avoid continuous overflow by halving the problematic count. 716 counters[idx] = counters[idx] / 2; 717 } 718 return result; 719 } 720 721 // Intrinsified by C2. Returns true if obj is a compile-time constant. 722 @LambdaForm.Hidden 723 @jdk.internal.HotSpotIntrinsicCandidate 724 static 725 boolean isCompileConstant(Object obj) { 726 return false; 727 } 728 729 static 730 MethodHandle makeGuardWithTest(MethodHandle test, 731 MethodHandle target, 732 MethodHandle fallback) { 733 MethodType type = target.type(); 734 assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type)); 735 MethodType basicType = type.basicType(); 736 LambdaForm form = makeGuardWithTestForm(basicType); 737 BoundMethodHandle mh; 738 try { 739 if (PROFILE_GWT) { 740 int[] counts = new int[2]; 741 mh = (BoundMethodHandle) 742 BoundMethodHandle.speciesData_LLLL().constructor().invokeBasic(type, form, 743 (Object) test, (Object) profile(target), (Object) profile(fallback), counts); 744 } else { 745 mh = (BoundMethodHandle) 746 BoundMethodHandle.speciesData_LLL().constructor().invokeBasic(type, form, 747 (Object) test, (Object) profile(target), (Object) profile(fallback)); 748 } 749 } catch (Throwable ex) { 750 throw uncaughtException(ex); 751 } 752 assert(mh.type() == type); 753 return mh; 754 } 755 756 757 static 758 MethodHandle profile(MethodHandle target) { 759 if (DONT_INLINE_THRESHOLD >= 0) { 760 return makeBlockInliningWrapper(target); 761 } else { 762 return target; 763 } 764 } 765 766 /** 767 * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times. 768 * Corresponding LambdaForm has @DontInline when compiled into bytecode. 769 */ 770 static 771 MethodHandle makeBlockInliningWrapper(MethodHandle target) { 772 LambdaForm lform; 773 if (DONT_INLINE_THRESHOLD > 0) { 774 lform = Makers.PRODUCE_BLOCK_INLINING_FORM.apply(target); 775 } else { 776 lform = Makers.PRODUCE_REINVOKER_FORM.apply(target); 777 } 778 return new CountingWrapper(target, lform, 779 Makers.PRODUCE_BLOCK_INLINING_FORM, Makers.PRODUCE_REINVOKER_FORM, 780 DONT_INLINE_THRESHOLD); 781 } 782 783 private final static class Makers { 784 /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */ 785 static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() { 786 @Override 787 public LambdaForm apply(MethodHandle target) { 788 return DelegatingMethodHandle.makeReinvokerForm(target, 789 MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false, 790 DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting); 791 } 792 }; 793 794 /** Constructs simple reinvoker lambda form for a particular method handle */ 795 static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() { 796 @Override 797 public LambdaForm apply(MethodHandle target) { 798 return DelegatingMethodHandle.makeReinvokerForm(target, 799 MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget); 800 } 801 }; 802 803 /** Maker of type-polymorphic varargs */ 804 static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() { 805 @Override 806 protected MethodHandle[] computeValue(Class<?> type) { 807 return new MethodHandle[MAX_JVM_ARITY + 1]; 808 } 809 }; 810 } 811 812 /** 813 * Counting method handle. It has 2 states: counting and non-counting. 814 * It is in counting state for the first n invocations and then transitions to non-counting state. 815 * Behavior in counting and non-counting states is determined by lambda forms produced by 816 * countingFormProducer & nonCountingFormProducer respectively. 817 */ 818 static class CountingWrapper extends DelegatingMethodHandle { 819 private final MethodHandle target; 820 private int count; 821 private Function<MethodHandle, LambdaForm> countingFormProducer; 822 private Function<MethodHandle, LambdaForm> nonCountingFormProducer; 823 private volatile boolean isCounting; 824 825 private CountingWrapper(MethodHandle target, LambdaForm lform, 826 Function<MethodHandle, LambdaForm> countingFromProducer, 827 Function<MethodHandle, LambdaForm> nonCountingFormProducer, 828 int count) { 829 super(target.type(), lform); 830 this.target = target; 831 this.count = count; 832 this.countingFormProducer = countingFromProducer; 833 this.nonCountingFormProducer = nonCountingFormProducer; 834 this.isCounting = (count > 0); 835 } 836 837 @Hidden 838 @Override 839 protected MethodHandle getTarget() { 840 return target; 841 } 842 843 @Override 844 public MethodHandle asTypeUncached(MethodType newType) { 845 MethodHandle newTarget = target.asType(newType); 846 MethodHandle wrapper; 847 if (isCounting) { 848 LambdaForm lform; 849 lform = countingFormProducer.apply(newTarget); 850 wrapper = new CountingWrapper(newTarget, lform, countingFormProducer, nonCountingFormProducer, DONT_INLINE_THRESHOLD); 851 } else { 852 wrapper = newTarget; // no need for a counting wrapper anymore 853 } 854 return (asTypeCache = wrapper); 855 } 856 857 // Customize target if counting happens for too long. 858 private int invocations = CUSTOMIZE_THRESHOLD; 859 private void maybeCustomizeTarget() { 860 int c = invocations; 861 if (c >= 0) { 862 if (c == 1) { 863 target.customize(); 864 } 865 invocations = c - 1; 866 } 867 } 868 869 boolean countDown() { 870 int c = count; 871 maybeCustomizeTarget(); 872 if (c <= 1) { 873 // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. 874 if (isCounting) { 875 isCounting = false; 876 return true; 877 } else { 878 return false; 879 } 880 } else { 881 count = c - 1; 882 return false; 883 } 884 } 885 886 @Hidden 887 static void maybeStopCounting(Object o1) { 888 CountingWrapper wrapper = (CountingWrapper) o1; 889 if (wrapper.countDown()) { 890 // Reached invocation threshold. Replace counting behavior with a non-counting one. 891 LambdaForm lform = wrapper.nonCountingFormProducer.apply(wrapper.target); 892 lform.compileToBytecode(); // speed up warmup by avoiding LF interpretation again after transition 893 wrapper.updateForm(lform); 894 } 895 } 896 897 static final NamedFunction NF_maybeStopCounting; 898 static { 899 Class<?> THIS_CLASS = CountingWrapper.class; 900 try { 901 NF_maybeStopCounting = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeStopCounting", Object.class)); 902 } catch (ReflectiveOperationException ex) { 903 throw newInternalError(ex); 904 } 905 } 906 } 907 908 static 909 LambdaForm makeGuardWithTestForm(MethodType basicType) { 910 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT); 911 if (lform != null) return lform; 912 final int THIS_MH = 0; // the BMH_LLL 913 final int ARG_BASE = 1; // start of incoming arguments 914 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); 915 int nameCursor = ARG_LIMIT; 916 final int GET_TEST = nameCursor++; 917 final int GET_TARGET = nameCursor++; 918 final int GET_FALLBACK = nameCursor++; 919 final int GET_COUNTERS = PROFILE_GWT ? nameCursor++ : -1; 920 final int CALL_TEST = nameCursor++; 921 final int PROFILE = (GET_COUNTERS != -1) ? nameCursor++ : -1; 922 final int TEST = nameCursor-1; // previous statement: either PROFILE or CALL_TEST 923 final int SELECT_ALT = nameCursor++; 924 final int CALL_TARGET = nameCursor++; 925 assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative 926 927 MethodType lambdaType = basicType.invokerType(); 928 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); 929 930 BoundMethodHandle.SpeciesData data = 931 (GET_COUNTERS != -1) ? BoundMethodHandle.speciesData_LLLL() 932 : BoundMethodHandle.speciesData_LLL(); 933 names[THIS_MH] = names[THIS_MH].withConstraint(data); 934 names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]); 935 names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]); 936 names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]); 937 if (GET_COUNTERS != -1) { 938 names[GET_COUNTERS] = new Name(data.getterFunction(3), names[THIS_MH]); 939 } 940 Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class); 941 942 // call test 943 MethodType testType = basicType.changeReturnType(boolean.class).basicType(); 944 invokeArgs[0] = names[GET_TEST]; 945 names[CALL_TEST] = new Name(testType, invokeArgs); 946 947 // profile branch 948 if (PROFILE != -1) { 949 names[PROFILE] = new Name(NF_profileBoolean, names[CALL_TEST], names[GET_COUNTERS]); 950 } 951 // call selectAlternative 952 names[SELECT_ALT] = new Name(getConstantHandle(MH_selectAlternative), names[TEST], names[GET_TARGET], names[GET_FALLBACK]); 953 954 // call target or fallback 955 invokeArgs[0] = names[SELECT_ALT]; 956 names[CALL_TARGET] = new Name(basicType, invokeArgs); 957 958 lform = new LambdaForm("guard", lambdaType.parameterCount(), names, /*forceInline=*/true); 959 960 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform); 961 } 962 963 /** 964 * The LambdaForm shape for catchException combinator is the following: 965 * <blockquote><pre>{@code 966 * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{ 967 * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L); 968 * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L); 969 * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L); 970 * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L); 971 * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L); 972 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L); 973 * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L); 974 * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I} 975 * }</pre></blockquote> 976 * 977 * argL0 and argL2 are target and catcher method handles. argL1 is exception class. 978 * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[] 979 * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()). 980 * 981 * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms 982 * among catchException combinators with the same basic type. 983 */ 984 private static LambdaForm makeGuardWithCatchForm(MethodType basicType) { 985 MethodType lambdaType = basicType.invokerType(); 986 987 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC); 988 if (lform != null) { 989 return lform; 990 } 991 final int THIS_MH = 0; // the BMH_LLLLL 992 final int ARG_BASE = 1; // start of incoming arguments 993 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); 994 995 int nameCursor = ARG_LIMIT; 996 final int GET_TARGET = nameCursor++; 997 final int GET_CLASS = nameCursor++; 998 final int GET_CATCHER = nameCursor++; 999 final int GET_COLLECT_ARGS = nameCursor++; 1000 final int GET_UNBOX_RESULT = nameCursor++; 1001 final int BOXED_ARGS = nameCursor++; 1002 final int TRY_CATCH = nameCursor++; 1003 final int UNBOX_RESULT = nameCursor++; 1004 1005 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); 1006 1007 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); 1008 names[THIS_MH] = names[THIS_MH].withConstraint(data); 1009 names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]); 1010 names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]); 1011 names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]); 1012 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]); 1013 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]); 1014 1015 // FIXME: rework argument boxing/result unboxing logic for LF interpretation 1016 1017 // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...); 1018 MethodType collectArgsType = basicType.changeReturnType(Object.class); 1019 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType); 1020 Object[] args = new Object[invokeBasic.type().parameterCount()]; 1021 args[0] = names[GET_COLLECT_ARGS]; 1022 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE); 1023 names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args); 1024 1025 // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L); 1026 Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]}; 1027 names[TRY_CATCH] = new Name(NF_guardWithCatch, gwcArgs); 1028 1029 // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); 1030 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); 1031 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]}; 1032 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs); 1033 1034 lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names); 1035 1036 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform); 1037 } 1038 1039 static 1040 MethodHandle makeGuardWithCatch(MethodHandle target, 1041 Class<? extends Throwable> exType, 1042 MethodHandle catcher) { 1043 MethodType type = target.type(); 1044 LambdaForm form = makeGuardWithCatchForm(type.basicType()); 1045 1046 // Prepare auxiliary method handles used during LambdaForm interpretation. 1047 // Box arguments and wrap them into Object[]: ValueConversions.array(). 1048 MethodType varargsType = type.changeReturnType(Object[].class); 1049 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType); 1050 MethodHandle unboxResult = unboxResultHandle(type.returnType()); 1051 1052 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL(); 1053 BoundMethodHandle mh; 1054 try { 1055 mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, 1056 (Object) catcher, (Object) collectArgs, (Object) unboxResult); 1057 } catch (Throwable ex) { 1058 throw uncaughtException(ex); 1059 } 1060 assert(mh.type() == type); 1061 return mh; 1062 } 1063 1064 /** 1065 * Intrinsified during LambdaForm compilation 1066 * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}). 1067 */ 1068 @LambdaForm.Hidden 1069 static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher, 1070 Object... av) throws Throwable { 1071 // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case. 1072 try { 1073 return target.asFixedArity().invokeWithArguments(av); 1074 } catch (Throwable t) { 1075 if (!exType.isInstance(t)) throw t; 1076 return catcher.asFixedArity().invokeWithArguments(prepend(av, t)); 1077 } 1078 } 1079 1080 /** Prepend elements to an array. */ 1081 @LambdaForm.Hidden 1082 private static Object[] prepend(Object[] array, Object... elems) { 1083 int nArray = array.length; 1084 int nElems = elems.length; 1085 Object[] newArray = new Object[nArray + nElems]; 1086 System.arraycopy(elems, 0, newArray, 0, nElems); 1087 System.arraycopy(array, 0, newArray, nElems, nArray); 1088 return newArray; 1089 } 1090 1091 static 1092 MethodHandle throwException(MethodType type) { 1093 assert(Throwable.class.isAssignableFrom(type.parameterType(0))); 1094 int arity = type.parameterCount(); 1095 if (arity > 1) { 1096 MethodHandle mh = throwException(type.dropParameterTypes(1, arity)); 1097 mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity)); 1098 return mh; 1099 } 1100 return makePairwiseConvert(NF_throwException.resolvedHandle(), type, false, true); 1101 } 1102 1103 static <T extends Throwable> Empty throwException(T t) throws T { throw t; } 1104 1105 static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2]; 1106 static MethodHandle fakeMethodHandleInvoke(MemberName method) { 1107 int idx; 1108 assert(method.isMethodHandleInvoke()); 1109 switch (method.getName()) { 1110 case "invoke": idx = 0; break; 1111 case "invokeExact": idx = 1; break; 1112 default: throw new InternalError(method.getName()); 1113 } 1114 MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx]; 1115 if (mh != null) return mh; 1116 MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class, 1117 MethodHandle.class, Object[].class); 1118 mh = throwException(type); 1119 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle")); 1120 if (!method.getInvocationType().equals(mh.type())) 1121 throw new InternalError(method.toString()); 1122 mh = mh.withInternalMemberName(method, false); 1123 mh = mh.withVarargs(true); 1124 assert(method.isVarargs()); 1125 FAKE_METHOD_HANDLE_INVOKE[idx] = mh; 1126 return mh; 1127 } 1128 static MethodHandle fakeVarHandleInvoke(MemberName method) { 1129 // TODO caching, is it necessary? 1130 MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class, 1131 VarHandle.class, Object[].class); 1132 MethodHandle mh = throwException(type); 1133 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle")); 1134 if (!method.getInvocationType().equals(mh.type())) 1135 throw new InternalError(method.toString()); 1136 mh = mh.withInternalMemberName(method, false); 1137 mh = mh.asVarargsCollector(Object[].class); 1138 assert(method.isVarargs()); 1139 return mh; 1140 } 1141 1142 /** 1143 * Create an alias for the method handle which, when called, 1144 * appears to be called from the same class loader and protection domain 1145 * as hostClass. 1146 * This is an expensive no-op unless the method which is called 1147 * is sensitive to its caller. A small number of system methods 1148 * are in this category, including Class.forName and Method.invoke. 1149 */ 1150 static 1151 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) { 1152 return BindCaller.bindCaller(mh, hostClass); 1153 } 1154 1155 // Put the whole mess into its own nested class. 1156 // That way we can lazily load the code and set up the constants. 1157 private static class BindCaller { 1158 private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); 1159 1160 static 1161 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) { 1162 // Do not use this function to inject calls into system classes. 1163 if (hostClass == null 1164 || (hostClass.isArray() || 1165 hostClass.isPrimitive() || 1166 hostClass.getName().startsWith("java.") || 1167 hostClass.getName().startsWith("sun."))) { 1168 throw new InternalError(); // does not happen, and should not anyway 1169 } 1170 // For simplicity, convert mh to a varargs-like method. 1171 MethodHandle vamh = prepareForInvoker(mh); 1172 // Cache the result of makeInjectedInvoker once per argument class. 1173 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass); 1174 return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass); 1175 } 1176 1177 private static MethodHandle makeInjectedInvoker(Class<?> hostClass) { 1178 try { 1179 Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null); 1180 assert checkInjectedInvoker(hostClass, invokerClass); 1181 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT); 1182 } catch (ReflectiveOperationException ex) { 1183 throw uncaughtException(ex); 1184 } 1185 } 1186 1187 private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() { 1188 @Override protected MethodHandle computeValue(Class<?> hostClass) { 1189 return makeInjectedInvoker(hostClass); 1190 } 1191 }; 1192 1193 // Adapt mh so that it can be called directly from an injected invoker: 1194 private static MethodHandle prepareForInvoker(MethodHandle mh) { 1195 mh = mh.asFixedArity(); 1196 MethodType mt = mh.type(); 1197 int arity = mt.parameterCount(); 1198 MethodHandle vamh = mh.asType(mt.generic()); 1199 vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames 1200 vamh = vamh.asSpreader(Object[].class, arity); 1201 vamh.internalForm().compileToBytecode(); // eliminate LFI stack frames 1202 return vamh; 1203 } 1204 1205 // Undo the adapter effect of prepareForInvoker: 1206 private static MethodHandle restoreToType(MethodHandle vamh, 1207 MethodHandle original, 1208 Class<?> hostClass) { 1209 MethodType type = original.type(); 1210 MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount()); 1211 MemberName member = original.internalMemberName(); 1212 mh = mh.asType(type); 1213 mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass); 1214 return mh; 1215 } 1216 1217 private static boolean checkInjectedInvoker(Class<?> hostClass, Class<?> invokerClass) { 1218 assert (hostClass.getClassLoader() == invokerClass.getClassLoader()) : hostClass.getName()+" (CL)"; 1219 try { 1220 assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)"; 1221 } catch (SecurityException ex) { 1222 // Self-check was blocked by security manager. This is OK. 1223 } 1224 try { 1225 // Test the invoker to ensure that it really injects into the right place. 1226 MethodHandle invoker = IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT); 1227 MethodHandle vamh = prepareForInvoker(MH_checkCallerClass); 1228 return (boolean)invoker.invoke(vamh, new Object[]{ invokerClass }); 1229 } catch (Throwable ex) { 1230 throw new InternalError(ex); 1231 } 1232 } 1233 1234 private static final MethodHandle MH_checkCallerClass; 1235 static { 1236 final Class<?> THIS_CLASS = BindCaller.class; 1237 assert(checkCallerClass(THIS_CLASS)); 1238 try { 1239 MH_checkCallerClass = IMPL_LOOKUP 1240 .findStatic(THIS_CLASS, "checkCallerClass", 1241 MethodType.methodType(boolean.class, Class.class)); 1242 assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS)); 1243 } catch (Throwable ex) { 1244 throw new InternalError(ex); 1245 } 1246 } 1247 1248 @CallerSensitive 1249 @ForceInline 1250 private static boolean checkCallerClass(Class<?> expected) { 1251 // This method is called via MH_checkCallerClass and so it's correct to ask for the immediate caller here. 1252 Class<?> actual = Reflection.getCallerClass(); 1253 if (actual != expected) 1254 throw new InternalError("found " + actual.getName() + ", expected " + expected.getName()); 1255 return true; 1256 } 1257 1258 private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate(); 1259 1260 /** Produces byte code for a class that is used as an injected invoker. */ 1261 private static byte[] generateInvokerTemplate() { 1262 ClassWriter cw = new ClassWriter(0); 1263 1264 // private static class InjectedInvoker { 1265 // @Hidden 1266 // static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable { 1267 // return vamh.invokeExact(args); 1268 // } 1269 // } 1270 cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null); 1271 1272 MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V", 1273 "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;", 1274 null, null); 1275 1276 // Suppress invoker method in stack traces. 1277 AnnotationVisitor av0 = mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); 1278 av0.visitEnd(); 1279 1280 mv.visitCode(); 1281 mv.visitVarInsn(ALOAD, 0); 1282 mv.visitVarInsn(ALOAD, 1); 1283 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact", 1284 "([Ljava/lang/Object;)Ljava/lang/Object;", false); 1285 mv.visitInsn(ARETURN); 1286 mv.visitMaxs(2, 2); 1287 mv.visitEnd(); 1288 1289 cw.visitEnd(); 1290 return cw.toByteArray(); 1291 } 1292 } 1293 1294 /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */ 1295 private static final class WrappedMember extends DelegatingMethodHandle { 1296 private final MethodHandle target; 1297 private final MemberName member; 1298 private final Class<?> callerClass; 1299 private final boolean isInvokeSpecial; 1300 1301 private WrappedMember(MethodHandle target, MethodType type, 1302 MemberName member, boolean isInvokeSpecial, 1303 Class<?> callerClass) { 1304 super(type, target); 1305 this.target = target; 1306 this.member = member; 1307 this.callerClass = callerClass; 1308 this.isInvokeSpecial = isInvokeSpecial; 1309 } 1310 1311 @Override 1312 MemberName internalMemberName() { 1313 return member; 1314 } 1315 @Override 1316 Class<?> internalCallerClass() { 1317 return callerClass; 1318 } 1319 @Override 1320 boolean isInvokeSpecial() { 1321 return isInvokeSpecial; 1322 } 1323 @Override 1324 protected MethodHandle getTarget() { 1325 return target; 1326 } 1327 @Override 1328 public MethodHandle asTypeUncached(MethodType newType) { 1329 // This MH is an alias for target, except for the MemberName 1330 // Drop the MemberName if there is any conversion. 1331 return asTypeCache = target.asType(newType); 1332 } 1333 } 1334 1335 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) { 1336 if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial()) 1337 return target; 1338 return new WrappedMember(target, target.type(), member, isInvokeSpecial, null); 1339 } 1340 1341 /** Intrinsic IDs */ 1342 /*non-public*/ 1343 enum Intrinsic { 1344 SELECT_ALTERNATIVE, 1345 GUARD_WITH_CATCH, 1346 TRY_FINALLY, 1347 LOOP, 1348 NEW_ARRAY, 1349 ARRAY_LOAD, 1350 ARRAY_STORE, 1351 ARRAY_LENGTH, 1352 IDENTITY, 1353 ZERO, 1354 NONE // no intrinsic associated 1355 } 1356 1357 /** Mark arbitrary method handle as intrinsic. 1358 * InvokerBytecodeGenerator uses this info to produce more efficient bytecode shape. */ 1359 static final class IntrinsicMethodHandle extends DelegatingMethodHandle { 1360 private final MethodHandle target; 1361 private final Intrinsic intrinsicName; 1362 1363 IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) { 1364 super(target.type(), target); 1365 this.target = target; 1366 this.intrinsicName = intrinsicName; 1367 } 1368 1369 @Override 1370 protected MethodHandle getTarget() { 1371 return target; 1372 } 1373 1374 @Override 1375 Intrinsic intrinsicName() { 1376 return intrinsicName; 1377 } 1378 1379 @Override 1380 public MethodHandle asTypeUncached(MethodType newType) { 1381 // This MH is an alias for target, except for the intrinsic name 1382 // Drop the name if there is any conversion. 1383 return asTypeCache = target.asType(newType); 1384 } 1385 1386 @Override 1387 String internalProperties() { 1388 return super.internalProperties() + 1389 "\n& Intrinsic="+intrinsicName; 1390 } 1391 1392 @Override 1393 public MethodHandle asCollector(Class<?> arrayType, int arrayLength) { 1394 if (intrinsicName == Intrinsic.IDENTITY) { 1395 MethodType resultType = type().asCollectorType(arrayType, type().parameterCount() - 1, arrayLength); 1396 MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); 1397 return newArray.asType(resultType); 1398 } 1399 return super.asCollector(arrayType, arrayLength); 1400 } 1401 } 1402 1403 static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) { 1404 if (intrinsicName == target.intrinsicName()) 1405 return target; 1406 return new IntrinsicMethodHandle(target, intrinsicName); 1407 } 1408 1409 static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) { 1410 return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName); 1411 } 1412 1413 /// Collection of multiple arguments. 1414 1415 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) { 1416 MethodType type = MethodType.genericMethodType(nargs) 1417 .changeReturnType(rtype) 1418 .insertParameterTypes(0, ptypes); 1419 try { 1420 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type); 1421 } catch (ReflectiveOperationException ex) { 1422 return null; 1423 } 1424 } 1425 1426 private static final Object[] NO_ARGS_ARRAY = {}; 1427 private static Object[] makeArray(Object... args) { return args; } 1428 private static Object[] array() { return NO_ARGS_ARRAY; } 1429 private static Object[] array(Object a0) 1430 { return makeArray(a0); } 1431 private static Object[] array(Object a0, Object a1) 1432 { return makeArray(a0, a1); } 1433 private static Object[] array(Object a0, Object a1, Object a2) 1434 { return makeArray(a0, a1, a2); } 1435 private static Object[] array(Object a0, Object a1, Object a2, Object a3) 1436 { return makeArray(a0, a1, a2, a3); } 1437 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1438 Object a4) 1439 { return makeArray(a0, a1, a2, a3, a4); } 1440 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1441 Object a4, Object a5) 1442 { return makeArray(a0, a1, a2, a3, a4, a5); } 1443 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1444 Object a4, Object a5, Object a6) 1445 { return makeArray(a0, a1, a2, a3, a4, a5, a6); } 1446 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1447 Object a4, Object a5, Object a6, Object a7) 1448 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } 1449 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1450 Object a4, Object a5, Object a6, Object a7, 1451 Object a8) 1452 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } 1453 private static Object[] array(Object a0, Object a1, Object a2, Object a3, 1454 Object a4, Object a5, Object a6, Object a7, 1455 Object a8, Object a9) 1456 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } 1457 1458 private static final int ARRAYS_COUNT = 11; 1459 private static final @Stable MethodHandle[] ARRAYS = new MethodHandle[MAX_ARITY + 1]; 1460 1461 // filling versions of the above: 1462 // using Integer len instead of int len and no varargs to avoid bootstrapping problems 1463 private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { 1464 Object[] a = new Object[len]; 1465 fillWithArguments(a, 0, args); 1466 return a; 1467 } 1468 private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { 1469 Object[] a = Arrays.copyOf(example, len); 1470 assert(a.getClass() != Object[].class); 1471 fillWithArguments(a, 0, args); 1472 return a; 1473 } 1474 private static void fillWithArguments(Object[] a, int pos, Object... args) { 1475 System.arraycopy(args, 0, a, pos, args.length); 1476 } 1477 // using Integer pos instead of int pos to avoid bootstrapping problems 1478 private static Object[] fillArray(Integer pos, Object[] a, Object a0) 1479 { fillWithArguments(a, pos, a0); return a; } 1480 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) 1481 { fillWithArguments(a, pos, a0, a1); return a; } 1482 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) 1483 { fillWithArguments(a, pos, a0, a1, a2); return a; } 1484 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) 1485 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } 1486 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1487 Object a4) 1488 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } 1489 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1490 Object a4, Object a5) 1491 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } 1492 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1493 Object a4, Object a5, Object a6) 1494 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } 1495 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1496 Object a4, Object a5, Object a6, Object a7) 1497 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } 1498 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1499 Object a4, Object a5, Object a6, Object a7, 1500 Object a8) 1501 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } 1502 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, 1503 Object a4, Object a5, Object a6, Object a7, 1504 Object a8, Object a9) 1505 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } 1506 1507 private static final int FILL_ARRAYS_COUNT = 11; // current number of fillArray methods 1508 private static final @Stable MethodHandle[] FILL_ARRAYS = new MethodHandle[FILL_ARRAYS_COUNT]; 1509 1510 private static MethodHandle getFillArray(int count) { 1511 assert (count > 0 && count < FILL_ARRAYS_COUNT); 1512 MethodHandle mh = FILL_ARRAYS[count]; 1513 if (mh != null) { 1514 return mh; 1515 } 1516 mh = findCollector("fillArray", count, Object[].class, Integer.class, Object[].class); 1517 FILL_ARRAYS[count] = mh; 1518 return mh; 1519 } 1520 1521 private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { 1522 Object a = w.makeArray(boxes.length); 1523 w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); 1524 return a; 1525 } 1526 1527 /** Return a method handle that takes the indicated number of Object 1528 * arguments and returns an Object array of them, as if for varargs. 1529 */ 1530 static MethodHandle varargsArray(int nargs) { 1531 MethodHandle mh = ARRAYS[nargs]; 1532 if (mh != null) { 1533 return mh; 1534 } 1535 if (nargs < ARRAYS_COUNT) { 1536 mh = findCollector("array", nargs, Object[].class); 1537 } else { 1538 mh = buildVarargsArray(getConstantHandle(MH_fillNewArray), 1539 getConstantHandle(MH_arrayIdentity), nargs); 1540 } 1541 assert(assertCorrectArity(mh, nargs)); 1542 mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); 1543 return ARRAYS[nargs] = mh; 1544 } 1545 1546 private static boolean assertCorrectArity(MethodHandle mh, int arity) { 1547 assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; 1548 return true; 1549 } 1550 1551 // Array identity function (used as getConstantHandle(MH_arrayIdentity)). 1552 static <T> T[] identity(T[] x) { 1553 return x; 1554 } 1555 1556 private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { 1557 // Build up the result mh as a sequence of fills like this: 1558 // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) 1559 // The various fill(_,10*I,___*[J]) are reusable. 1560 int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately 1561 int rightLen = nargs - leftLen; 1562 MethodHandle leftCollector = newArray.bindTo(nargs); 1563 leftCollector = leftCollector.asCollector(Object[].class, leftLen); 1564 MethodHandle mh = finisher; 1565 if (rightLen > 0) { 1566 MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); 1567 if (mh.equals(getConstantHandle(MH_arrayIdentity))) 1568 mh = rightFiller; 1569 else 1570 mh = MethodHandles.collectArguments(mh, 0, rightFiller); 1571 } 1572 if (mh.equals(getConstantHandle(MH_arrayIdentity))) 1573 mh = leftCollector; 1574 else 1575 mh = MethodHandles.collectArguments(mh, 0, leftCollector); 1576 return mh; 1577 } 1578 1579 private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1; 1580 private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1]; 1581 /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) 1582 * fills a[L]..a[N-1] with corresponding arguments, 1583 * and then returns a. The value L is a global constant (LEFT_ARGS). 1584 */ 1585 private static MethodHandle fillToRight(int nargs) { 1586 MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; 1587 if (filler != null) return filler; 1588 filler = buildFiller(nargs); 1589 assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); 1590 return FILL_ARRAY_TO_RIGHT[nargs] = filler; 1591 } 1592 private static MethodHandle buildFiller(int nargs) { 1593 if (nargs <= LEFT_ARGS) 1594 return getConstantHandle(MH_arrayIdentity); // no args to fill; return the array unchanged 1595 // we need room for both mh and a in mh.invoke(a, arg*[nargs]) 1596 final int CHUNK = LEFT_ARGS; 1597 int rightLen = nargs % CHUNK; 1598 int midLen = nargs - rightLen; 1599 if (rightLen == 0) { 1600 midLen = nargs - (rightLen = CHUNK); 1601 if (FILL_ARRAY_TO_RIGHT[midLen] == null) { 1602 // build some precursors from left to right 1603 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) 1604 if (j > LEFT_ARGS) fillToRight(j); 1605 } 1606 } 1607 if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); 1608 assert(rightLen > 0); 1609 MethodHandle midFill = fillToRight(midLen); // recursive fill 1610 MethodHandle rightFill = getFillArray(rightLen).bindTo(midLen); // [midLen..nargs-1] 1611 assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); 1612 assert(rightFill.type().parameterCount() == 1 + rightLen); 1613 1614 // Combine the two fills: 1615 // right(mid(a, x10..x19), x20..x23) 1616 // The final product will look like this: 1617 // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) 1618 if (midLen == LEFT_ARGS) 1619 return rightFill; 1620 else 1621 return MethodHandles.collectArguments(rightFill, 0, midFill); 1622 } 1623 1624 static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM 1625 1626 /** Return a method handle that takes the indicated number of 1627 * typed arguments and returns an array of them. 1628 * The type argument is the array type. 1629 */ 1630 static MethodHandle varargsArray(Class<?> arrayType, int nargs) { 1631 Class<?> elemType = arrayType.getComponentType(); 1632 if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); 1633 // FIXME: Need more special casing and caching here. 1634 if (nargs >= MAX_JVM_ARITY/2 - 1) { 1635 int slots = nargs; 1636 final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH 1637 if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive()) 1638 slots *= Wrapper.forPrimitiveType(elemType).stackSlots(); 1639 if (slots > MAX_ARRAY_SLOTS) 1640 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); 1641 } 1642 if (elemType == Object.class) 1643 return varargsArray(nargs); 1644 // other cases: primitive arrays, subtypes of Object[] 1645 MethodHandle cache[] = Makers.TYPED_COLLECTORS.get(elemType); 1646 MethodHandle mh = nargs < cache.length ? cache[nargs] : null; 1647 if (mh != null) return mh; 1648 if (nargs == 0) { 1649 Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0); 1650 mh = MethodHandles.constant(arrayType, example); 1651 } else if (elemType.isPrimitive()) { 1652 MethodHandle builder = getConstantHandle(MH_fillNewArray); 1653 MethodHandle producer = buildArrayProducer(arrayType); 1654 mh = buildVarargsArray(builder, producer, nargs); 1655 } else { 1656 Class<? extends Object[]> objArrayType = arrayType.asSubclass(Object[].class); 1657 Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); 1658 MethodHandle builder = getConstantHandle(MH_fillNewTypedArray).bindTo(example); 1659 MethodHandle producer = getConstantHandle(MH_arrayIdentity); // must be weakly typed 1660 mh = buildVarargsArray(builder, producer, nargs); 1661 } 1662 mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType))); 1663 mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); 1664 assert(assertCorrectArity(mh, nargs)); 1665 if (nargs < cache.length) 1666 cache[nargs] = mh; 1667 return mh; 1668 } 1669 1670 private static MethodHandle buildArrayProducer(Class<?> arrayType) { 1671 Class<?> elemType = arrayType.getComponentType(); 1672 assert(elemType.isPrimitive()); 1673 return getConstantHandle(MH_copyAsPrimitiveArray).bindTo(Wrapper.forPrimitiveType(elemType)); 1674 } 1675 1676 /*non-public*/ static void assertSame(Object mh1, Object mh2) { 1677 if (mh1 != mh2) { 1678 String msg = String.format("mh1 != mh2: mh1 = %s (form: %s); mh2 = %s (form: %s)", 1679 mh1, ((MethodHandle)mh1).form, 1680 mh2, ((MethodHandle)mh2).form); 1681 throw newInternalError(msg); 1682 } 1683 } 1684 1685 // Local constant functions: 1686 /*non-public*/ static final NamedFunction 1687 NF_checkSpreadArgument, 1688 NF_guardWithCatch, 1689 NF_throwException, 1690 NF_tryFinally, 1691 NF_loop, 1692 NF_profileBoolean; 1693 1694 static { 1695 try { 1696 NF_checkSpreadArgument = new NamedFunction(MethodHandleImpl.class 1697 .getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); 1698 NF_guardWithCatch = new NamedFunction(MethodHandleImpl.class 1699 .getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class, 1700 MethodHandle.class, Object[].class)); 1701 NF_tryFinally = new NamedFunction(MethodHandleImpl.class 1702 .getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class)); 1703 NF_loop = new NamedFunction(MethodHandleImpl.class 1704 .getDeclaredMethod("loop", BasicType[].class, MethodHandle[].class, MethodHandle[].class, 1705 MethodHandle[].class, MethodHandle[].class, Object[].class)); 1706 NF_throwException = new NamedFunction(MethodHandleImpl.class 1707 .getDeclaredMethod("throwException", Throwable.class)); 1708 NF_profileBoolean = new NamedFunction(MethodHandleImpl.class 1709 .getDeclaredMethod("profileBoolean", boolean.class, int[].class)); 1710 } catch (ReflectiveOperationException ex) { 1711 throw newInternalError(ex); 1712 } 1713 } 1714 1715 /** Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore(). */ 1716 private static MethodHandle unboxResultHandle(Class<?> returnType) { 1717 if (returnType.isPrimitive()) { 1718 if (returnType == void.class) { 1719 return ValueConversions.ignore(); 1720 } else { 1721 Wrapper w = Wrapper.forPrimitiveType(returnType); 1722 return ValueConversions.unboxExact(w); 1723 } 1724 } else { 1725 return MethodHandles.identity(Object.class); 1726 } 1727 } 1728 1729 /** 1730 * Assembles a loop method handle from the given handles and type information. 1731 * 1732 * @param tloop the return type of the loop. 1733 * @param targs types of the arguments to be passed to the loop. 1734 * @param init sanitized array of initializers for loop-local variables. 1735 * @param step sanitited array of loop bodies. 1736 * @param pred sanitized array of predicates. 1737 * @param fini sanitized array of loop finalizers. 1738 * 1739 * @return a handle that, when invoked, will execute the loop. 1740 */ 1741 static MethodHandle makeLoop(Class<?> tloop, List<Class<?>> targs, List<MethodHandle> init, List<MethodHandle> step, 1742 List<MethodHandle> pred, List<MethodHandle> fini) { 1743 MethodType type = MethodType.methodType(tloop, targs); 1744 BasicType[] initClauseTypes = 1745 init.stream().map(h -> h.type().returnType()).map(BasicType::basicType).toArray(BasicType[]::new); 1746 LambdaForm form = makeLoopForm(type.basicType(), initClauseTypes); 1747 1748 // Prepare auxiliary method handles used during LambdaForm interpretation. 1749 // Box arguments and wrap them into Object[]: ValueConversions.array(). 1750 MethodType varargsType = type.changeReturnType(Object[].class); 1751 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType); 1752 MethodHandle unboxResult = unboxResultHandle(tloop); 1753 1754 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLLL(); 1755 BoundMethodHandle mh; 1756 try { 1757 mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) toArray(init), 1758 (Object) toArray(step), (Object) toArray(pred), (Object) toArray(fini), (Object) collectArgs, 1759 (Object) unboxResult); 1760 } catch (Throwable ex) { 1761 throw uncaughtException(ex); 1762 } 1763 assert(mh.type() == type); 1764 return mh; 1765 } 1766 1767 private static MethodHandle[] toArray(List<MethodHandle> l) { 1768 return l.toArray(new MethodHandle[0]); 1769 } 1770 1771 /** 1772 * Loops introduce some complexity as they can have additional local state. Hence, LambdaForms for loops are 1773 * generated from a template. The LambdaForm template shape for the loop combinator is as follows (assuming one 1774 * reference parameter passed in {@code a1}, and a reference return type, with the return value represented by 1775 * {@code t12}): 1776 * <blockquote><pre>{@code 1777 * loop=Lambda(a0:L,a1:L)=>{ 1778 * t2:L=BoundMethodHandle$Species_L6.argL0(a0:L); // array of init method handles 1779 * t3:L=BoundMethodHandle$Species_L6.argL1(a0:L); // array of step method handles 1780 * t4:L=BoundMethodHandle$Species_L6.argL2(a0:L); // array of pred method handles 1781 * t5:L=BoundMethodHandle$Species_L6.argL3(a0:L); // array of fini method handles 1782 * t6:L=BoundMethodHandle$Species_L6.argL4(a0:L); // helper handle to box the arguments into an Object[] 1783 * t7:L=BoundMethodHandle$Species_L6.argL5(a0:L); // helper handle to unbox the result 1784 * t8:L=MethodHandle.invokeBasic(t6:L,a1:L); // box the arguments into an Object[] 1785 * t9:L=MethodHandleImpl.loop(null,t2:L,t3:L,t4:L,t5:L,t6:L); // call the loop executor 1786 * t10:L=MethodHandle.invokeBasic(t7:L,t9:L);t10:L} // unbox the result; return the result 1787 * }</pre></blockquote> 1788 * <p> 1789 * {@code argL0} through {@code argL3} are the arrays of init, step, pred, and fini method handles. 1790 * {@code argL4} and {@code argL5} are auxiliary method handles: {@code argL2} boxes arguments and wraps them into 1791 * {@code Object[]} ({@code ValueConversions.array()}), and {@code argL3} unboxes the result if necessary 1792 * ({@code ValueConversions.unbox()}). 1793 * <p> 1794 * Having {@code t6} and {@code t7} passed in via a BMH and not hardcoded in the lambda form allows to share lambda 1795 * forms among loop combinators with the same basic type. 1796 * <p> 1797 * The above template is instantiated by using the {@link LambdaFormEditor} to replace the {@code null} argument to 1798 * the {@code loop} invocation with the {@code BasicType} array describing the loop clause types. This argument is 1799 * ignored in the loop invoker, but will be extracted and used in {@linkplain InvokerBytecodeGenerator#emitLoop(int) 1800 * bytecode generation}. 1801 */ 1802 private static LambdaForm makeLoopForm(MethodType basicType, BasicType[] localVarTypes) { 1803 MethodType lambdaType = basicType.invokerType(); 1804 1805 final int THIS_MH = 0; // the BMH_LLLLLL 1806 final int ARG_BASE = 1; // start of incoming arguments 1807 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); 1808 1809 int nameCursor = ARG_LIMIT; 1810 final int GET_INITS = nameCursor++; 1811 final int GET_STEPS = nameCursor++; 1812 final int GET_PREDS = nameCursor++; 1813 final int GET_FINIS = nameCursor++; 1814 final int GET_COLLECT_ARGS = nameCursor++; 1815 final int GET_UNBOX_RESULT = nameCursor++; 1816 final int BOXED_ARGS = nameCursor++; 1817 final int LOOP = nameCursor++; 1818 final int UNBOX_RESULT = nameCursor++; 1819 1820 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_LOOP); 1821 if (lform == null) { 1822 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); 1823 1824 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLLL(); 1825 names[THIS_MH] = names[THIS_MH].withConstraint(data); 1826 names[GET_INITS] = new Name(data.getterFunction(0), names[THIS_MH]); 1827 names[GET_STEPS] = new Name(data.getterFunction(1), names[THIS_MH]); 1828 names[GET_PREDS] = new Name(data.getterFunction(2), names[THIS_MH]); 1829 names[GET_FINIS] = new Name(data.getterFunction(3), names[THIS_MH]); 1830 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(4), names[THIS_MH]); 1831 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(5), names[THIS_MH]); 1832 1833 // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...); 1834 MethodType collectArgsType = basicType.changeReturnType(Object.class); 1835 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType); 1836 Object[] args = new Object[invokeBasic.type().parameterCount()]; 1837 args[0] = names[GET_COLLECT_ARGS]; 1838 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT - ARG_BASE); 1839 names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.LOOP), args); 1840 1841 // t_{i+1}:L=MethodHandleImpl.loop(localTypes:L,inits:L,steps:L,preds:L,finis:L,t_{i}:L); 1842 Object[] lArgs = 1843 new Object[]{null, // placeholder for BasicType[] localTypes - will be added by LambdaFormEditor 1844 names[GET_INITS], names[GET_STEPS], names[GET_PREDS], names[GET_FINIS], names[BOXED_ARGS]}; 1845 names[LOOP] = new Name(NF_loop, lArgs); 1846 1847 // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); 1848 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); 1849 Object[] unboxArgs = new Object[]{names[GET_UNBOX_RESULT], names[LOOP]}; 1850 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs); 1851 1852 lform = basicType.form().setCachedLambdaForm(MethodTypeForm.LF_LOOP, 1853 new LambdaForm("loop", lambdaType.parameterCount(), names)); 1854 } 1855 1856 // BOXED_ARGS is the index into the names array where the loop idiom starts 1857 return lform.editor().noteLoopLocalTypesForm(BOXED_ARGS, localVarTypes); 1858 } 1859 1860 1861 /** 1862 * Intrinsified during LambdaForm compilation 1863 * (see {@link InvokerBytecodeGenerator#emitLoop(int)}). 1864 */ 1865 @LambdaForm.Hidden 1866 static Object loop(BasicType[] localTypes, MethodHandle[] init, MethodHandle[] step, MethodHandle[] pred, 1867 MethodHandle[] fini, Object... av) throws Throwable { 1868 int varSize = (int) Stream.of(init).filter(h -> h.type().returnType() != void.class).count(); 1869 int nArgs = init[0].type().parameterCount(); 1870 Object[] varsAndArgs = new Object[varSize + nArgs]; 1871 for (int i = 0, v = 0; i < init.length; ++i) { 1872 if (init[i].type().returnType() == void.class) { 1873 init[i].asFixedArity().invokeWithArguments(av); 1874 } else { 1875 varsAndArgs[v++] = init[i].asFixedArity().invokeWithArguments(av); 1876 } 1877 } 1878 System.arraycopy(av, 0, varsAndArgs, varSize, nArgs); 1879 final int nSteps = step.length; 1880 for (; ; ) { 1881 for (int i = 0, v = 0; i < nSteps; ++i) { 1882 MethodHandle p = pred[i]; 1883 MethodHandle s = step[i]; 1884 MethodHandle f = fini[i]; 1885 if (s.type().returnType() == void.class) { 1886 s.asFixedArity().invokeWithArguments(varsAndArgs); 1887 } else { 1888 varsAndArgs[v++] = s.asFixedArity().invokeWithArguments(varsAndArgs); 1889 } 1890 if (!(boolean) p.asFixedArity().invokeWithArguments(varsAndArgs)) { 1891 return f.asFixedArity().invokeWithArguments(varsAndArgs); 1892 } 1893 } 1894 } 1895 } 1896 1897 /** 1898 * This method is bound as the predicate in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle, 1899 * MethodHandle) counting loops}. 1900 * 1901 * @param counter the counter parameter, passed in during loop execution. 1902 * @param limit the upper bound of the parameter, statically bound at loop creation time. 1903 * 1904 * @return whether the counter has reached the limit. 1905 */ 1906 static boolean countedLoopPredicate(int counter, int limit) { 1907 return counter <= limit; 1908 } 1909 1910 /** 1911 * This method is bound as the step function in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle, 1912 * MethodHandle) counting loops} to increment the counter. 1913 * 1914 * @param counter the loop counter. 1915 * 1916 * @return the loop counter incremented by 1. 1917 */ 1918 static int countedLoopStep(int counter, int limit) { 1919 return counter + 1; 1920 } 1921 1922 /** 1923 * This method is bound as a filter in {@linkplain MethodHandles#countedLoop(MethodHandle, MethodHandle, MethodHandle, 1924 * MethodHandle) counting loops} to pass the correct counter value to the body. 1925 * 1926 * @param counter the loop counter. 1927 * 1928 * @return the loop counter decremented by 1. 1929 */ 1930 static int decrementCounter(int counter) { 1931 return counter - 1; 1932 } 1933 1934 /** 1935 * This is bound to initialize the loop-local iterator in {@linkplain MethodHandles#iteratedLoop iterating loops}. 1936 * 1937 * @param it the {@link Iterable} over which the loop iterates. 1938 * 1939 * @return an {@link Iterator} over the argument's elements. 1940 */ 1941 static Iterator<?> initIterator(Iterable<?> it) { 1942 return it.iterator(); 1943 } 1944 1945 /** 1946 * This method is bound as the predicate in {@linkplain MethodHandles#iteratedLoop iterating loops}. 1947 * 1948 * @param it the iterator to be checked. 1949 * 1950 * @return {@code true} iff there are more elements to iterate over. 1951 */ 1952 static boolean iteratePredicate(Iterator<?> it) { 1953 return it.hasNext(); 1954 } 1955 1956 /** 1957 * This method is bound as the step for retrieving the current value from the iterator in {@linkplain 1958 * MethodHandles#iteratedLoop iterating loops}. 1959 * 1960 * @param it the iterator. 1961 * 1962 * @return the next element from the iterator. 1963 */ 1964 static Object iterateNext(Iterator<?> it) { 1965 return it.next(); 1966 } 1967 1968 /** 1969 * Makes a {@code try-finally} handle that conforms to the type constraints. 1970 * 1971 * @param target the target to execute in a {@code try-finally} block. 1972 * @param cleanup the cleanup to execute in the {@code finally} block. 1973 * @param rtype the result type of the entire construct. 1974 * @param argTypes the types of the arguments. 1975 * 1976 * @return a handle on the constructed {@code try-finally} block. 1977 */ 1978 static MethodHandle makeTryFinally(MethodHandle target, MethodHandle cleanup, Class<?> rtype, List<Class<?>> argTypes) { 1979 MethodType type = MethodType.methodType(rtype, argTypes); 1980 LambdaForm form = makeTryFinallyForm(type.basicType()); 1981 1982 // Prepare auxiliary method handles used during LambdaForm interpretation. 1983 // Box arguments and wrap them into Object[]: ValueConversions.array(). 1984 MethodType varargsType = type.changeReturnType(Object[].class); 1985 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType); 1986 MethodHandle unboxResult = unboxResultHandle(rtype); 1987 1988 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL(); 1989 BoundMethodHandle mh; 1990 try { 1991 mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, (Object) target, (Object) cleanup, 1992 (Object) collectArgs, (Object) unboxResult); 1993 } catch (Throwable ex) { 1994 throw uncaughtException(ex); 1995 } 1996 assert(mh.type() == type); 1997 return mh; 1998 } 1999 2000 /** 2001 * The LambdaForm shape for the tryFinally combinator is as follows (assuming one reference parameter passed in 2002 * {@code a1}, and a reference return type, with the return value represented by {@code t8}): 2003 * <blockquote><pre>{@code 2004 * tryFinally=Lambda(a0:L,a1:L)=>{ 2005 * t2:L=BoundMethodHandle$Species_LLLL.argL0(a0:L); // target method handle 2006 * t3:L=BoundMethodHandle$Species_LLLL.argL1(a0:L); // cleanup method handle 2007 * t4:L=BoundMethodHandle$Species_LLLL.argL2(a0:L); // helper handle to box the arguments into an Object[] 2008 * t5:L=BoundMethodHandle$Species_LLLL.argL3(a0:L); // helper handle to unbox the result 2009 * t6:L=MethodHandle.invokeBasic(t4:L,a1:L); // box the arguments into an Object[] 2010 * t7:L=MethodHandleImpl.tryFinally(t2:L,t3:L,t6:L); // call the tryFinally executor 2011 * t8:L=MethodHandle.invokeBasic(t5:L,t7:L);t8:L} // unbox the result; return the result 2012 * }</pre></blockquote> 2013 * <p> 2014 * {@code argL0} and {@code argL1} are the target and cleanup method handles. 2015 * {@code argL2} and {@code argL3} are auxiliary method handles: {@code argL2} boxes arguments and wraps them into 2016 * {@code Object[]} ({@code ValueConversions.array()}), and {@code argL3} unboxes the result if necessary 2017 * ({@code ValueConversions.unbox()}). 2018 * <p> 2019 * Having {@code t4} and {@code t5} passed in via a BMH and not hardcoded in the lambda form allows to share lambda 2020 * forms among tryFinally combinators with the same basic type. 2021 */ 2022 private static LambdaForm makeTryFinallyForm(MethodType basicType) { 2023 MethodType lambdaType = basicType.invokerType(); 2024 2025 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_TF); 2026 if (lform != null) { 2027 return lform; 2028 } 2029 final int THIS_MH = 0; // the BMH_LLLL 2030 final int ARG_BASE = 1; // start of incoming arguments 2031 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); 2032 2033 int nameCursor = ARG_LIMIT; 2034 final int GET_TARGET = nameCursor++; 2035 final int GET_CLEANUP = nameCursor++; 2036 final int GET_COLLECT_ARGS = nameCursor++; 2037 final int GET_UNBOX_RESULT = nameCursor++; 2038 final int BOXED_ARGS = nameCursor++; 2039 final int TRY_FINALLY = nameCursor++; 2040 final int UNBOX_RESULT = nameCursor++; 2041 2042 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); 2043 2044 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL(); 2045 names[THIS_MH] = names[THIS_MH].withConstraint(data); 2046 names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]); 2047 names[GET_CLEANUP] = new Name(data.getterFunction(1), names[THIS_MH]); 2048 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(2), names[THIS_MH]); 2049 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(3), names[THIS_MH]); 2050 2051 // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...); 2052 MethodType collectArgsType = basicType.changeReturnType(Object.class); 2053 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType); 2054 Object[] args = new Object[invokeBasic.type().parameterCount()]; 2055 args[0] = names[GET_COLLECT_ARGS]; 2056 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE); 2057 names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.TRY_FINALLY), args); 2058 2059 // t_{i+1}:L=MethodHandleImpl.tryFinally(target:L,exType:L,catcher:L,t_{i}:L); 2060 Object[] tfArgs = new Object[] {names[GET_TARGET], names[GET_CLEANUP], names[BOXED_ARGS]}; 2061 names[TRY_FINALLY] = new Name(NF_tryFinally, tfArgs); 2062 2063 // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L); 2064 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class)); 2065 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_FINALLY]}; 2066 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs); 2067 2068 lform = new LambdaForm("tryFinally", lambdaType.parameterCount(), names); 2069 2070 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_TF, lform); 2071 } 2072 2073 /** 2074 * Intrinsified during LambdaForm compilation 2075 * (see {@link InvokerBytecodeGenerator#emitTryFinally emitTryFinally}). 2076 */ 2077 @LambdaForm.Hidden 2078 static Object tryFinally(MethodHandle target, MethodHandle cleanup, Object... av) throws Throwable { 2079 Throwable t = null; 2080 Object r = null; 2081 try { 2082 // Use asFixedArity() to avoid unnecessary boxing of last argument for VarargsCollector case. 2083 r = target.asFixedArity().invokeWithArguments(av); 2084 } catch (Throwable thrown) { 2085 t = thrown; 2086 throw t; 2087 } finally { 2088 Object[] args = target.type().returnType() == void.class ? prepend(av, t) : prepend(av, t, r); 2089 r = cleanup.asFixedArity().invokeWithArguments(args); 2090 } 2091 return r; 2092 } 2093 2094 // Indexes into constant method handles: 2095 static final int 2096 MH_cast = 0, 2097 MH_selectAlternative = 1, 2098 MH_copyAsPrimitiveArray = 2, 2099 MH_fillNewTypedArray = 3, 2100 MH_fillNewArray = 4, 2101 MH_arrayIdentity = 5, 2102 MH_countedLoopPred = 6, 2103 MH_countedLoopStep = 7, 2104 MH_iteratePred = 8, 2105 MH_initIterator = 9, 2106 MH_iterateNext = 10, 2107 MH_decrementCounter = 11, 2108 MH_Array_newInstance = 12, 2109 MH_LIMIT = 13; 2110 2111 static MethodHandle getConstantHandle(int idx) { 2112 MethodHandle handle = HANDLES[idx]; 2113 if (handle != null) { 2114 return handle; 2115 } 2116 return setCachedHandle(idx, makeConstantHandle(idx)); 2117 } 2118 2119 private static synchronized MethodHandle setCachedHandle(int idx, final MethodHandle method) { 2120 // Simulate a CAS, to avoid racy duplication of results. 2121 MethodHandle prev = HANDLES[idx]; 2122 if (prev != null) { 2123 return prev; 2124 } 2125 HANDLES[idx] = method; 2126 return method; 2127 } 2128 2129 // Local constant method handles: 2130 private static final @Stable MethodHandle[] HANDLES = new MethodHandle[MH_LIMIT]; 2131 2132 private static MethodHandle makeConstantHandle(int idx) { 2133 try { 2134 switch (idx) { 2135 case MH_cast: 2136 return IMPL_LOOKUP.findVirtual(Class.class, "cast", 2137 MethodType.methodType(Object.class, Object.class)); 2138 case MH_copyAsPrimitiveArray: 2139 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "copyAsPrimitiveArray", 2140 MethodType.methodType(Object.class, Wrapper.class, Object[].class)); 2141 case MH_arrayIdentity: 2142 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "identity", 2143 MethodType.methodType(Object[].class, Object[].class)); 2144 case MH_fillNewArray: 2145 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewArray", 2146 MethodType.methodType(Object[].class, Integer.class, Object[].class)); 2147 case MH_fillNewTypedArray: 2148 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewTypedArray", 2149 MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); 2150 case MH_selectAlternative: 2151 return makeIntrinsic(IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative", 2152 MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)), 2153 Intrinsic.SELECT_ALTERNATIVE); 2154 case MH_countedLoopPred: 2155 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopPredicate", 2156 MethodType.methodType(boolean.class, int.class, int.class)); 2157 case MH_countedLoopStep: 2158 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep", 2159 MethodType.methodType(int.class, int.class, int.class)); 2160 case MH_iteratePred: 2161 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate", 2162 MethodType.methodType(boolean.class, Iterator.class)); 2163 case MH_initIterator: 2164 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator", 2165 MethodType.methodType(Iterator.class, Iterable.class)); 2166 case MH_iterateNext: 2167 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext", 2168 MethodType.methodType(Object.class, Iterator.class)); 2169 case MH_decrementCounter: 2170 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter", 2171 MethodType.methodType(int.class, int.class)); 2172 case MH_Array_newInstance: 2173 return IMPL_LOOKUP.findStatic(Array.class, "newInstance", 2174 MethodType.methodType(Object.class, Class.class, int.class)); 2175 } 2176 } catch (ReflectiveOperationException ex) { 2177 throw newInternalError(ex); 2178 } 2179 throw newInternalError("Unknown function index: " + idx); 2180 } 2181 }