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