1
25
26 package java.lang.invoke;
27
28 import jdk.internal.misc.JavaLangInvokeAccess;
29 import jdk.internal.misc.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.Stable;
37 import sun.invoke.empty.Empty;
38 import sun.invoke.util.ValueConversions;
39 import sun.invoke.util.VerifyType;
40 import sun.invoke.util.Wrapper;
41
42 import java.lang.reflect.Array;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.function.Function;
49 import java.util.stream.Stream;
50
51 import static java.lang.invoke.LambdaForm.*;
52 import static java.lang.invoke.MethodHandleStatics.*;
53 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
54 import static jdk.internal.org.objectweb.asm.Opcodes.*;
55
56
60 abstract class MethodHandleImpl {
61
62
63
64 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, ArrayAccess access) {
65 if (arrayClass == Object[].class) {
66 return ArrayAccess.objectAccessor(access);
67 }
68 if (!arrayClass.isArray())
69 throw newIllegalArgumentException("not an array: "+arrayClass);
70 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
71 int cacheIndex = ArrayAccess.cacheIndex(access);
72 MethodHandle mh = cache[cacheIndex];
73 if (mh != null) return mh;
74 mh = ArrayAccessor.getAccessor(arrayClass, access);
75 MethodType correctType = ArrayAccessor.correctType(arrayClass, access);
76 if (mh.type() != correctType) {
77 assert(mh.type().parameterType(0) == Object[].class);
78 assert(access != ArrayAccess.SET || mh.type().parameterType(2) == Object.class);
79 assert(access != ArrayAccess.GET ||
80 (mh.type().returnType() == Object.class &&
81 correctType.parameterType(0).getComponentType() == correctType.returnType()));
82
83 mh = mh.viewAsType(correctType, false);
84 }
85 mh = makeIntrinsic(mh, ArrayAccess.intrinsic(access));
86
87 synchronized(cache) {
88 if (cache[cacheIndex] == null) {
89 cache[cacheIndex] = mh;
90 } else {
91
92 mh = cache[cacheIndex];
93 }
94 }
95 return mh;
96 }
97
98 enum ArrayAccess {
99 GET, SET, LENGTH;
100
101
102
103
104 static String opName(ArrayAccess a) {
105 switch (a) {
106 case GET: return "getElement";
107 case SET: return "setElement";
108 case LENGTH: return "length";
109 }
110 throw unmatchedArrayAccess(a);
111 }
112
113 static MethodHandle objectAccessor(ArrayAccess a) {
114 switch (a) {
115 case GET: return ArrayAccessor.OBJECT_ARRAY_GETTER;
116 case SET: return ArrayAccessor.OBJECT_ARRAY_SETTER;
117 case LENGTH: return ArrayAccessor.OBJECT_ARRAY_LENGTH;
118 }
119 throw unmatchedArrayAccess(a);
120 }
121
122 static int cacheIndex(ArrayAccess a) {
123 switch (a) {
124 case GET: return ArrayAccessor.GETTER_INDEX;
125 case SET: return ArrayAccessor.SETTER_INDEX;
126 case LENGTH: return ArrayAccessor.LENGTH_INDEX;
127 }
128 throw unmatchedArrayAccess(a);
129 }
130
131 static Intrinsic intrinsic(ArrayAccess a) {
132 switch (a) {
133 case GET: return Intrinsic.ARRAY_LOAD;
134 case SET: return Intrinsic.ARRAY_STORE;
135 case LENGTH: return Intrinsic.ARRAY_LENGTH;
136 }
137 throw unmatchedArrayAccess(a);
138 }
139 }
140
141 static InternalError unmatchedArrayAccess(ArrayAccess a) {
142 return newInternalError("should not reach here (unmatched ArrayAccess: " + a + ")");
143 }
144
145 static final class ArrayAccessor {
146
147 static final int GETTER_INDEX = 0, SETTER_INDEX = 1, LENGTH_INDEX = 2, INDEX_LIMIT = 3;
148 static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
149 = new ClassValue<MethodHandle[]>() {
150 @Override
151 protected MethodHandle[] computeValue(Class<?> type) {
152 return new MethodHandle[INDEX_LIMIT];
153 }
154 };
155 static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER, OBJECT_ARRAY_LENGTH;
156 static {
157 MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class);
158 cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.GET), Intrinsic.ARRAY_LOAD);
159 cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.SET), Intrinsic.ARRAY_STORE);
160 cache[LENGTH_INDEX] = OBJECT_ARRAY_LENGTH = makeIntrinsic(getAccessor(Object[].class, ArrayAccess.LENGTH), Intrinsic.ARRAY_LENGTH);
161
162 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName()));
163 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName()));
164 assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_LENGTH.internalMemberName()));
165 }
166
167 static int getElementI(int[] a, int i) { return a[i]; }
168 static long getElementJ(long[] a, int i) { return a[i]; }
169 static float getElementF(float[] a, int i) { return a[i]; }
170 static double getElementD(double[] a, int i) { return a[i]; }
171 static boolean getElementZ(boolean[] a, int i) { return a[i]; }
172 static byte getElementB(byte[] a, int i) { return a[i]; }
173 static short getElementS(short[] a, int i) { return a[i]; }
174 static char getElementC(char[] a, int i) { return a[i]; }
175 static Object getElementL(Object[] a, int i) { return a[i]; }
176
177 static void setElementI(int[] a, int i, int x) { a[i] = x; }
178 static void setElementJ(long[] a, int i, long x) { a[i] = x; }
179 static void setElementF(float[] a, int i, float x) { a[i] = x; }
180 static void setElementD(double[] a, int i, double x) { a[i] = x; }
181 static void setElementZ(boolean[] a, int i, boolean x) { a[i] = x; }
182 static void setElementB(byte[] a, int i, byte x) { a[i] = x; }
183 static void setElementS(short[] a, int i, short x) { a[i] = x; }
184 static void setElementC(char[] a, int i, char x) { a[i] = x; }
185 static void setElementL(Object[] a, int i, Object x) { a[i] = x; }
186
187 static int lengthI(int[] a) { return a.length; }
188 static int lengthJ(long[] a) { return a.length; }
189 static int lengthF(float[] a) { return a.length; }
190 static int lengthD(double[] a) { return a.length; }
191 static int lengthZ(boolean[] a) { return a.length; }
192 static int lengthB(byte[] a) { return a.length; }
193 static int lengthS(short[] a) { return a.length; }
194 static int lengthC(char[] a) { return a.length; }
195 static int lengthL(Object[] a) { return a.length; }
196
197 static String name(Class<?> arrayClass, ArrayAccess access) {
198 Class<?> elemClass = arrayClass.getComponentType();
199 if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass);
200 return ArrayAccess.opName(access) + Wrapper.basicTypeChar(elemClass);
201 }
202 static MethodType type(Class<?> arrayClass, ArrayAccess access) {
203 Class<?> elemClass = arrayClass.getComponentType();
204 Class<?> arrayArgClass = arrayClass;
205 if (!elemClass.isPrimitive()) {
206 arrayArgClass = Object[].class;
207 elemClass = Object.class;
208 }
209 switch (access) {
210 case GET: return MethodType.methodType(elemClass, arrayArgClass, int.class);
211 case SET: return MethodType.methodType(void.class, arrayArgClass, int.class, elemClass);
212 case LENGTH: return MethodType.methodType(int.class, arrayArgClass);
213 }
214 throw unmatchedArrayAccess(access);
215 }
216 static MethodType correctType(Class<?> arrayClass, ArrayAccess access) {
217 Class<?> elemClass = arrayClass.getComponentType();
218 switch (access) {
219 case GET: return MethodType.methodType(elemClass, arrayClass, int.class);
220 case SET: return MethodType.methodType(void.class, arrayClass, int.class, elemClass);
221 case LENGTH: return MethodType.methodType(int.class, arrayClass);
222 }
223 throw unmatchedArrayAccess(access);
224 }
225 static MethodHandle getAccessor(Class<?> arrayClass, ArrayAccess access) {
226 String name = name(arrayClass, access);
227 MethodType type = type(arrayClass, access);
228 try {
229 return IMPL_LOOKUP.findStatic(ArrayAccessor.class, name, type);
230 } catch (ReflectiveOperationException ex) {
231 throw uncaughtException(ex);
232 }
233 }
234 }
235
236
250 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
251 boolean strict, boolean monobox) {
252 MethodType dstType = target.type();
253 if (srcType == dstType)
254 return target;
255 return makePairwiseConvertByEditor(target, srcType, strict, monobox);
256 }
257
258 private static int countNonNull(Object[] array) {
259 int count = 0;
260 for (Object x : array) {
261 if (x != null) ++count;
262 }
263 return count;
264 }
265
266 static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType,
267 boolean strict, boolean monobox) {
268 Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
269 int convCount = countNonNull(convSpecs);
270 if (convCount == 0)
271 return target.viewAsType(srcType, strict);
272 MethodType basicSrcType = srcType.basicType();
273 MethodType midType = target.type().basicType();
274 BoundMethodHandle mh = target.rebind();
275
276
277 for (int i = 0; i < convSpecs.length-1; i++) {
278 Object convSpec = convSpecs[i];
279 if (convSpec == null) continue;
280 MethodHandle fn;
281 if (convSpec instanceof Class) {
282 fn = getConstantHandle(MH_cast).bindTo(convSpec);
283 } else {
284 fn = (MethodHandle) convSpec;
285 }
286 Class<?> newType = basicSrcType.parameterType(i);
287 if (--convCount == 0)
288 midType = srcType;
289 else
290 midType = midType.changeParameterType(i, newType);
291 LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType));
292 mh = mh.copyWithExtendL(midType, form2, fn);
293 mh = mh.rebind();
294 }
295 Object convSpec = convSpecs[convSpecs.length-1];
296 if (convSpec != null) {
297 MethodHandle fn;
298 if (convSpec instanceof Class) {
299 if (convSpec == void.class)
300 fn = null;
301 else
302 fn = getConstantHandle(MH_cast).bindTo(convSpec);
303 } else {
304 fn = (MethodHandle) convSpec;
305 }
306 Class<?> newType = basicSrcType.returnType();
307 assert(--convCount == 0);
308 midType = srcType;
309 if (fn != null) {
310 mh = mh.rebind();
311 LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false);
312 mh = mh.copyWithExtendL(midType, form2, fn);
313 } else {
314 LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true);
315 mh = mh.copyWith(midType, form2);
316 }
317 }
318 assert(convCount == 0);
319 assert(mh.type().equals(srcType));
320 return mh;
321 }
322
323 static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType,
324 boolean strict, boolean monobox) {
325 assert(target.type().parameterCount() == srcType.parameterCount());
326
327 Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox);
328 final int INARG_COUNT = srcType.parameterCount();
329 int convCount = countNonNull(convSpecs);
330 boolean retConv = (convSpecs[INARG_COUNT] != null);
331 boolean retVoid = srcType.returnType() == void.class;
332 if (retConv && retVoid) {
333 convCount -= 1;
334 retConv = false;
335 }
336
337 final int IN_MH = 0;
338 final int INARG_BASE = 1;
339 final int INARG_LIMIT = INARG_BASE + INARG_COUNT;
340 final int NAME_LIMIT = INARG_LIMIT + convCount + 1;
341 final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1);
342 final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1;
343 final int RESULT = (retVoid ? -1 : NAME_LIMIT - 1);
344
345
346 MethodType lambdaType = srcType.basicType().invokerType();
347 Name[] names = arguments(NAME_LIMIT - INARG_LIMIT, lambdaType);
348
349
350 final int OUTARG_BASE = 0;
351 Object[] outArgs = new Object[OUTARG_BASE + INARG_COUNT];
352
353 int nameCursor = INARG_LIMIT;
354 for (int i = 0; i < INARG_COUNT; i++) {
355 Object convSpec = convSpecs[i];
356 if (convSpec == null) {
357
358 outArgs[OUTARG_BASE + i] = names[INARG_BASE + i];
359 continue;
360 }
361
362 Name conv;
363 if (convSpec instanceof Class) {
364 Class<?> convClass = (Class<?>) convSpec;
365 conv = new Name(getConstantHandle(MH_cast), convClass, names[INARG_BASE + i]);
366 } else {
367 MethodHandle fn = (MethodHandle) convSpec;
368 conv = new Name(fn, names[INARG_BASE + i]);
369 }
370 assert(names[nameCursor] == null);
371 names[nameCursor++] = conv;
372 assert(outArgs[OUTARG_BASE + i] == null);
373 outArgs[OUTARG_BASE + i] = conv;
374 }
375
376
377 assert(nameCursor == OUT_CALL);
378 names[OUT_CALL] = new Name(target, outArgs);
379
380 Object convSpec = convSpecs[INARG_COUNT];
381 if (!retConv) {
382 assert(OUT_CALL == names.length-1);
383 } else {
384 Name conv;
385 if (convSpec == void.class) {
386 conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType())));
387 } else if (convSpec instanceof Class) {
388 Class<?> convClass = (Class<?>) convSpec;
389 conv = new Name(getConstantHandle(MH_cast), convClass, names[OUT_CALL]);
390 } else {
391 MethodHandle fn = (MethodHandle) convSpec;
392 if (fn.type().parameterCount() == 0)
393 conv = new Name(fn);
394 else
395 conv = new Name(fn, names[OUT_CALL]);
396 }
397 assert(names[RETURN_CONV] == null);
398 names[RETURN_CONV] = conv;
399 assert(RETURN_CONV == names.length-1);
400 }
401
402 LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, RESULT, Kind.CONVERT);
403 return SimpleMethodHandle.make(srcType, form);
404 }
405
406 static Object[] computeValueConversions(MethodType srcType, MethodType dstType,
407 boolean strict, boolean monobox) {
408 final int INARG_COUNT = srcType.parameterCount();
409 Object[] convSpecs = new Object[INARG_COUNT+1];
410 for (int i = 0; i <= INARG_COUNT; i++) {
411 boolean isRet = (i == INARG_COUNT);
412 Class<?> src = isRet ? dstType.returnType() : srcType.parameterType(i);
413 Class<?> dst = isRet ? srcType.returnType() : dstType.parameterType(i);
414 if (!VerifyType.isNullConversion(src, dst, strict)) {
415 convSpecs[i] = valueConversion(src, dst, strict, monobox);
416 }
417 }
418 return convSpecs;
419 }
420 static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType,
421 boolean strict) {
422 return makePairwiseConvert(target, srcType, strict, false);
423 }
424
425
431 static Object valueConversion(Class<?> src, Class<?> dst, boolean strict, boolean monobox) {
432 assert(!VerifyType.isNullConversion(src, dst, strict));
433 if (dst == void.class)
434 return dst;
435 MethodHandle fn;
436 if (src.isPrimitive()) {
437 if (src == void.class) {
438 return void.class;
439 } else if (dst.isPrimitive()) {
440
441 fn = ValueConversions.convertPrimitive(src, dst);
442 } else {
443
444 Wrapper wsrc = Wrapper.forPrimitiveType(src);
445 fn = ValueConversions.boxExact(wsrc);
446 assert(fn.type().parameterType(0) == wsrc.primitiveType());
447 assert(fn.type().returnType() == wsrc.wrapperType());
448 if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) {
449
450 MethodType mt = MethodType.methodType(dst, src);
451 if (strict)
452 fn = fn.asType(mt);
453 else
454 fn = MethodHandleImpl.makePairwiseConvert(fn, mt, false);
455 }
456 }
457 } else if (dst.isPrimitive()) {
458 Wrapper wdst = Wrapper.forPrimitiveType(dst);
459 if (monobox || src == wdst.wrapperType()) {
460
461 fn = ValueConversions.unboxExact(wdst, strict);
462 } else {
463
464
465
466 fn = (strict
467 ? ValueConversions.unboxWiden(wdst)
468 : ValueConversions.unboxCast(wdst));
469 }
470 } else {
471
472
473
474
475 return dst;
476 }
477 assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn);
478 return fn;
479 }
480
481 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
482 MethodType type = target.type();
483 int last = type.parameterCount() - 1;
484 if (type.parameterType(last) != arrayType)
485 target = target.asType(type.changeParameterType(last, arrayType));
486 target = target.asFixedArity();
487 return new AsVarargsCollector(target, arrayType);
488 }
489
490 private static final class AsVarargsCollector extends DelegatingMethodHandle {
491 private final MethodHandle target;
492 private final Class<?> arrayType;
493 private @Stable MethodHandle asCollectorCache;
494
495 AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
496 this(target.type(), target, arrayType);
497 }
498 AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
499 super(type, target);
500 this.target = target;
501 this.arrayType = arrayType;
502 }
503
504 @Override
505 public boolean isVarargsCollector() {
506 return true;
507 }
508
509 @Override
510 protected MethodHandle getTarget() {
511 return target;
512 }
513
514 @Override
515 public MethodHandle asFixedArity() {
516 return target;
517 }
518
519 @Override
520 MethodHandle setVarargs(MemberName member) {
521 if (member.isVarargs()) return this;
522 return asFixedArity();
523 }
524
525 @Override
526 public MethodHandle withVarargs(boolean makeVarargs) {
527 if (makeVarargs) return this;
528 return asFixedArity();
529 }
530
531 @Override
532 public MethodHandle asTypeUncached(MethodType newType) {
533 MethodType type = this.type();
534 int collectArg = type.parameterCount() - 1;
535 int newArity = newType.parameterCount();
536 if (newArity == collectArg+1 &&
537 type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
538
539 return asTypeCache = asFixedArity().asType(newType);
540 }
541
542 MethodHandle acc = asCollectorCache;
543 if (acc != null && acc.type().parameterCount() == newArity)
544 return asTypeCache = acc.asType(newType);
545
546 int arrayLength = newArity - collectArg;
547 MethodHandle collector;
548 try {
549 collector = asFixedArity().asCollector(arrayType, arrayLength);
550 assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
551 } catch (IllegalArgumentException ex) {
552 throw new WrongMethodTypeException("cannot build collector", ex);
553 }
554 asCollectorCache = collector;
555 return asTypeCache = collector.asType(newType);
556 }
557
558 @Override
559 boolean viewAsTypeChecks(MethodType newType, boolean strict) {
560 super.viewAsTypeChecks(newType, true);
561 if (strict) return true;
562
563 assert (type().lastParameterType().getComponentType()
564 .isAssignableFrom(
565 newType.lastParameterType().getComponentType()))
566 : Arrays.asList(this, newType);
567 return true;
568 }
569
570 @Override
571 public Object invokeWithArguments(Object... arguments) throws Throwable {
572 MethodType type = this.type();
573 int argc;
574 final int MAX_SAFE = 127;
575 if (arguments == null
576 || (argc = arguments.length) <= MAX_SAFE
577 || argc < type.parameterCount()) {
578 return super.invokeWithArguments(arguments);
579 }
580
581
582 int uncollected = type.parameterCount() - 1;
583 Class<?> elemType = arrayType.getComponentType();
584 int collected = argc - uncollected;
585 Object collArgs = (elemType == Object.class)
586 ? new Object[collected] : Array.newInstance(elemType, collected);
587 if (!elemType.isPrimitive()) {
588
589 try {
590 System.arraycopy(arguments, uncollected, collArgs, 0, collected);
591 } catch (ArrayStoreException ex) {
592 return super.invokeWithArguments(arguments);
593 }
594 } else {
595
596 MethodHandle arraySetter = MethodHandles.arrayElementSetter(arrayType);
597 try {
598 for (int i = 0; i < collected; i++) {
599 arraySetter.invoke(collArgs, i, arguments[uncollected + i]);
600 }
601 } catch (WrongMethodTypeException|ClassCastException ex) {
602 return super.invokeWithArguments(arguments);
603 }
604 }
605
606
607 Object[] newArgs = new Object[uncollected + 1];
608 System.arraycopy(arguments, 0, newArgs, 0, uncollected);
609 newArgs[uncollected] = collArgs;
610 return asFixedArity().invokeWithArguments(newArgs);
611 }
612 }
613
614
615 static MethodHandle makeSpreadArguments(MethodHandle target,
616 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
617 MethodType targetType = target.type();
618
619 for (int i = 0; i < spreadArgCount; i++) {
620 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
621 if (arg == null) arg = Object.class;
622 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
623 }
624 target = target.asType(targetType);
625
626 MethodType srcType = targetType
627 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
628
629 MethodType lambdaType = srcType.invokerType();
630 Name[] names = arguments(spreadArgCount + 2, lambdaType);
631 int nameCursor = lambdaType.parameterCount();
632 int[] indexes = new int[targetType.parameterCount()];
633
634 for (int i = 0, argIndex = 1; i < targetType.parameterCount() + 1; i++, argIndex++) {
635 Class<?> src = lambdaType.parameterType(i);
636 if (i == spreadArgPos) {
637
638 MethodHandle aload = MethodHandles.arrayElementGetter(spreadArgType);
639 Name array = names[argIndex];
640 names[nameCursor++] = new Name(getFunction(NF_checkSpreadArgument), array, spreadArgCount);
641 for (int j = 0; j < spreadArgCount; i++, j++) {
642 indexes[i] = nameCursor;
643 names[nameCursor++] = new Name(new NamedFunction(aload, Intrinsic.ARRAY_LOAD), array, j);
644 }
645 } else if (i < indexes.length) {
646 indexes[i] = argIndex;
647 }
648 }
649 assert(nameCursor == names.length-1);
650
651
652 Name[] targetArgs = new Name[targetType.parameterCount()];
653 for (int i = 0; i < targetType.parameterCount(); i++) {
654 int idx = indexes[i];
655 targetArgs[i] = names[idx];
656 }
657 names[names.length - 1] = new Name(target, (Object[]) targetArgs);
658
659 LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, Kind.SPREAD);
660 return SimpleMethodHandle.make(srcType, form);
661 }
662
663 static void checkSpreadArgument(Object av, int n) {
664 if (av == null && n == 0) {
665 return;
666 } else if (av == null) {
667 throw new NullPointerException("null array reference");
668 } else if (av instanceof Object[]) {
669 int len = ((Object[])av).length;
670 if (len == n) return;
671 } else {
672 int len = java.lang.reflect.Array.getLength(av);
673 if (len == n) return;
674 }
675
676 throw newIllegalArgumentException("array is not of length "+n);
677 }
678
679
680 static MethodHandle makeCollectArguments(MethodHandle target,
681 MethodHandle collector, int collectArgPos, boolean retainOriginalArgs) {
682 MethodType targetType = target.type();
683 MethodType collectorType = collector.type();
684 int collectArgCount = collectorType.parameterCount();
685 Class<?> collectValType = collectorType.returnType();
686 int collectValCount = (collectValType == void.class ? 0 : 1);
687 MethodType srcType = targetType
688 .dropParameterTypes(collectArgPos, collectArgPos+collectValCount);
689 if (!retainOriginalArgs) {
690 srcType = srcType.insertParameterTypes(collectArgPos, collectorType.parameterArray());
691 }
692
693
694
695
696
697 MethodType lambdaType = srcType.invokerType();
698 Name[] names = arguments(2, lambdaType);
699 final int collectNamePos = names.length - 2;
700 final int targetNamePos = names.length - 1;
701
702 Name[] collectorArgs = Arrays.copyOfRange(names, 1 + collectArgPos, 1 + collectArgPos + collectArgCount);
703 names[collectNamePos] = new Name(collector, (Object[]) collectorArgs);
704
705
706
707
708 Name[] targetArgs = new Name[targetType.parameterCount()];
709 int inputArgPos = 1;
710 int targetArgPos = 0;
711 int chunk = collectArgPos;
712 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
713 inputArgPos += chunk;
714 targetArgPos += chunk;
715 if (collectValType != void.class) {
716 targetArgs[targetArgPos++] = names[collectNamePos];
717 }
718 chunk = collectArgCount;
719 if (retainOriginalArgs) {
720 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
721 targetArgPos += chunk;
722 }
723 inputArgPos += chunk;
724 chunk = targetArgs.length - targetArgPos;
725 System.arraycopy(names, inputArgPos, targetArgs, targetArgPos, chunk);
726 assert(inputArgPos + chunk == collectNamePos);
727 names[targetNamePos] = new Name(target, (Object[]) targetArgs);
728
729 LambdaForm form = new LambdaForm(lambdaType.parameterCount(), names, Kind.COLLECT);
730 return SimpleMethodHandle.make(srcType, form);
731 }
732
733 @LambdaForm.Hidden
734 static
735 MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
736 if (testResult) {
737 return target;
738 } else {
739 return fallback;
740 }
741 }
742
743
744 @LambdaForm.Hidden
745 @jdk.internal.HotSpotIntrinsicCandidate
746 static
747 boolean profileBoolean(boolean result, int[] counters) {
748
749 int idx = result ? 1 : 0;
750 try {
751 counters[idx] = Math.addExact(counters[idx], 1);
752 } catch (ArithmeticException e) {
753
754 counters[idx] = counters[idx] / 2;
755 }
756 return result;
757 }
758
759
760 @LambdaForm.Hidden
761 @jdk.internal.HotSpotIntrinsicCandidate
762 static
763 boolean isCompileConstant(Object obj) {
764 return false;
765 }
766
767 static
768 MethodHandle makeGuardWithTest(MethodHandle test,
769 MethodHandle target,
770 MethodHandle fallback) {
771 MethodType type = target.type();
772 assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
773 MethodType basicType = type.basicType();
774 LambdaForm form = makeGuardWithTestForm(basicType);
775 BoundMethodHandle mh;
776 try {
777 if (PROFILE_GWT) {
778 int[] counts = new int[2];
779 mh = (BoundMethodHandle)
780 BoundMethodHandle.speciesData_LLLL().factory().invokeBasic(type, form,
781 (Object) test, (Object) profile(target), (Object) profile(fallback), counts);
782 } else {
783 mh = (BoundMethodHandle)
784 BoundMethodHandle.speciesData_LLL().factory().invokeBasic(type, form,
785 (Object) test, (Object) profile(target), (Object) profile(fallback));
786 }
787 } catch (Throwable ex) {
788 throw uncaughtException(ex);
789 }
790 assert(mh.type() == type);
791 return mh;
792 }
793
794
795 static
796 MethodHandle profile(MethodHandle target) {
797 if (DONT_INLINE_THRESHOLD >= 0) {
798 return makeBlockInliningWrapper(target);
799 } else {
800 return target;
801 }
802 }
803
804
808 static
809 MethodHandle makeBlockInliningWrapper(MethodHandle target) {
810 LambdaForm lform;
811 if (DONT_INLINE_THRESHOLD > 0) {
812 lform = Makers.PRODUCE_BLOCK_INLINING_FORM.apply(target);
813 } else {
814 lform = Makers.PRODUCE_REINVOKER_FORM.apply(target);
815 }
816 return new CountingWrapper(target, lform,
817 Makers.PRODUCE_BLOCK_INLINING_FORM, Makers.PRODUCE_REINVOKER_FORM,
818 DONT_INLINE_THRESHOLD);
819 }
820
821 private final static class Makers {
822
823 static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
824 @Override
825 public LambdaForm apply(MethodHandle target) {
826 return DelegatingMethodHandle.makeReinvokerForm(target,
827 MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, false,
828 DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
829 }
830 };
831
832
833 static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
834 @Override
835 public LambdaForm apply(MethodHandle target) {
836 return DelegatingMethodHandle.makeReinvokerForm(target,
837 MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
838 }
839 };
840
841
842 static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() {
843 @Override
844 protected MethodHandle[] computeValue(Class<?> type) {
845 return new MethodHandle[MAX_JVM_ARITY + 1];
846 }
847 };
848 }
849
850
856 static class CountingWrapper extends DelegatingMethodHandle {
857 private final MethodHandle target;
858 private int count;
859 private Function<MethodHandle, LambdaForm> countingFormProducer;
860 private Function<MethodHandle, LambdaForm> nonCountingFormProducer;
861 private volatile boolean isCounting;
862
863 private CountingWrapper(MethodHandle target, LambdaForm lform,
864 Function<MethodHandle, LambdaForm> countingFromProducer,
865 Function<MethodHandle, LambdaForm> nonCountingFormProducer,
866 int count) {
867 super(target.type(), lform);
868 this.target = target;
869 this.count = count;
870 this.countingFormProducer = countingFromProducer;
871 this.nonCountingFormProducer = nonCountingFormProducer;
872 this.isCounting = (count > 0);
873 }
874
875 @Hidden
876 @Override
877 protected MethodHandle getTarget() {
878 return target;
879 }
880
881 @Override
882 public MethodHandle asTypeUncached(MethodType newType) {
883 MethodHandle newTarget = target.asType(newType);
884 MethodHandle wrapper;
885 if (isCounting) {
886 LambdaForm lform;
887 lform = countingFormProducer.apply(newTarget);
888 wrapper = new CountingWrapper(newTarget, lform, countingFormProducer, nonCountingFormProducer, DONT_INLINE_THRESHOLD);
889 } else {
890 wrapper = newTarget;
891 }
892 return (asTypeCache = wrapper);
893 }
894
895
896 private int invocations = CUSTOMIZE_THRESHOLD;
897 private void maybeCustomizeTarget() {
898 int c = invocations;
899 if (c >= 0) {
900 if (c == 1) {
901 target.customize();
902 }
903 invocations = c - 1;
904 }
905 }
906
907 boolean countDown() {
908 int c = count;
909 maybeCustomizeTarget();
910 if (c <= 1) {
911
912 if (isCounting) {
913 isCounting = false;
914 return true;
915 } else {
916 return false;
917 }
918 } else {
919 count = c - 1;
920 return false;
921 }
922 }
923
924 @Hidden
925 static void maybeStopCounting(Object o1) {
926 CountingWrapper wrapper = (CountingWrapper) o1;
927 if (wrapper.countDown()) {
928
929 LambdaForm lform = wrapper.nonCountingFormProducer.apply(wrapper.target);
930 lform.compileToBytecode();
931 wrapper.updateForm(lform);
932 }
933 }
934
935 static final NamedFunction NF_maybeStopCounting;
936 static {
937 Class<?> THIS_CLASS = CountingWrapper.class;
938 try {
939 NF_maybeStopCounting = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeStopCounting", Object.class));
940 } catch (ReflectiveOperationException ex) {
941 throw newInternalError(ex);
942 }
943 }
944 }
945
946 static
947 LambdaForm makeGuardWithTestForm(MethodType basicType) {
948 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
949 if (lform != null) return lform;
950 final int THIS_MH = 0;
951 final int ARG_BASE = 1;
952 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
953 int nameCursor = ARG_LIMIT;
954 final int GET_TEST = nameCursor++;
955 final int GET_TARGET = nameCursor++;
956 final int GET_FALLBACK = nameCursor++;
957 final int GET_COUNTERS = PROFILE_GWT ? nameCursor++ : -1;
958 final int CALL_TEST = nameCursor++;
959 final int PROFILE = (GET_COUNTERS != -1) ? nameCursor++ : -1;
960 final int TEST = nameCursor-1;
961 final int SELECT_ALT = nameCursor++;
962 final int CALL_TARGET = nameCursor++;
963 assert(CALL_TARGET == SELECT_ALT+1);
964
965 MethodType lambdaType = basicType.invokerType();
966 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
967
968 BoundMethodHandle.SpeciesData data =
969 (GET_COUNTERS != -1) ? BoundMethodHandle.speciesData_LLLL()
970 : BoundMethodHandle.speciesData_LLL();
971 names[THIS_MH] = names[THIS_MH].withConstraint(data);
972 names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]);
973 names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]);
974 names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]);
975 if (GET_COUNTERS != -1) {
976 names[GET_COUNTERS] = new Name(data.getterFunction(3), names[THIS_MH]);
977 }
978 Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class);
979
980
981 MethodType testType = basicType.changeReturnType(boolean.class).basicType();
982 invokeArgs[0] = names[GET_TEST];
983 names[CALL_TEST] = new Name(testType, invokeArgs);
984
985
986 if (PROFILE != -1) {
987 names[PROFILE] = new Name(getFunction(NF_profileBoolean), names[CALL_TEST], names[GET_COUNTERS]);
988 }
989
990 names[SELECT_ALT] = new Name(new NamedFunction(getConstantHandle(MH_selectAlternative), Intrinsic.SELECT_ALTERNATIVE), names[TEST], names[GET_TARGET], names[GET_FALLBACK]);
991
992
993 invokeArgs[0] = names[SELECT_ALT];
994 names[CALL_TARGET] = new Name(basicType, invokeArgs);
995
996 lform = new LambdaForm(lambdaType.parameterCount(), names, true, Kind.GUARD);
997
998 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform);
999 }
1000
1001
1022 private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
1023 MethodType lambdaType = basicType.invokerType();
1024
1025 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
1026 if (lform != null) {
1027 return lform;
1028 }
1029 final int THIS_MH = 0;
1030 final int ARG_BASE = 1;
1031 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
1032
1033 int nameCursor = ARG_LIMIT;
1034 final int GET_TARGET = nameCursor++;
1035 final int GET_CLASS = nameCursor++;
1036 final int GET_CATCHER = nameCursor++;
1037 final int GET_COLLECT_ARGS = nameCursor++;
1038 final int GET_UNBOX_RESULT = nameCursor++;
1039 final int BOXED_ARGS = nameCursor++;
1040 final int TRY_CATCH = nameCursor++;
1041 final int UNBOX_RESULT = nameCursor++;
1042
1043 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
1044
1045 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
1046 names[THIS_MH] = names[THIS_MH].withConstraint(data);
1047 names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]);
1048 names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]);
1049 names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]);
1050 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
1051 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
1052
1053
1054
1055
1056 MethodType collectArgsType = basicType.changeReturnType(Object.class);
1057 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
1058 Object[] args = new Object[invokeBasic.type().parameterCount()];
1059 args[0] = names[GET_COLLECT_ARGS];
1060 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
1061 names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args);
1062
1063
1064 Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
1065 names[TRY_CATCH] = new Name(getFunction(NF_guardWithCatch), gwcArgs);
1066
1067
1068 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
1069 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
1070 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
1071
1072 lform = new LambdaForm(lambdaType.parameterCount(), names, Kind.GUARD_WITH_CATCH);
1073
1074 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
1075 }
1076
1077 static
1078 MethodHandle makeGuardWithCatch(MethodHandle target,
1079 Class<? extends Throwable> exType,
1080 MethodHandle catcher) {
1081 MethodType type = target.type();
1082 LambdaForm form = makeGuardWithCatchForm(type.basicType());
1083
1084
1085
1086 MethodType varargsType = type.changeReturnType(Object[].class);
1087 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
1088 MethodHandle unboxResult = unboxResultHandle(type.returnType());
1089
1090 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
1091 BoundMethodHandle mh;
1092 try {
1093 mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) target, (Object) exType,
1094 (Object) catcher, (Object) collectArgs, (Object) unboxResult);
1095 } catch (Throwable ex) {
1096 throw uncaughtException(ex);
1097 }
1098 assert(mh.type() == type);
1099 return mh;
1100 }
1101
1102
1106 @LambdaForm.Hidden
1107 static Object guardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher,
1108 Object... av) throws Throwable {
1109
1110 try {
1111 return target.asFixedArity().invokeWithArguments(av);
1112 } catch (Throwable t) {
1113 if (!exType.isInstance(t)) throw t;
1114 return catcher.asFixedArity().invokeWithArguments(prepend(av, t));
1115 }
1116 }
1117
1118
1119 @LambdaForm.Hidden
1120 private static Object[] prepend(Object[] array, Object... elems) {
1121 int nArray = array.length;
1122 int nElems = elems.length;
1123 Object[] newArray = new Object[nArray + nElems];
1124 System.arraycopy(elems, 0, newArray, 0, nElems);
1125 System.arraycopy(array, 0, newArray, nElems, nArray);
1126 return newArray;
1127 }
1128
1129 static
1130 MethodHandle throwException(MethodType type) {
1131 assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
1132 int arity = type.parameterCount();
1133 if (arity > 1) {
1134 MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
1135 mh = MethodHandles.dropArguments(mh, 1, Arrays.copyOfRange(type.parameterArray(), 1, arity));
1136 return mh;
1137 }
1138 return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true);
1139 }
1140
1141 static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
1142
1143 static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2];
1144 static MethodHandle fakeMethodHandleInvoke(MemberName method) {
1145 int idx;
1146 assert(method.isMethodHandleInvoke());
1147 switch (method.getName()) {
1148 case "invoke": idx = 0; break;
1149 case "invokeExact": idx = 1; break;
1150 default: throw new InternalError(method.getName());
1151 }
1152 MethodHandle mh = FAKE_METHOD_HANDLE_INVOKE[idx];
1153 if (mh != null) return mh;
1154 MethodType type = MethodType.methodType(Object.class, UnsupportedOperationException.class,
1155 MethodHandle.class, Object[].class);
1156 mh = throwException(type);
1157 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
1158 if (!method.getInvocationType().equals(mh.type()))
1159 throw new InternalError(method.toString());
1160 mh = mh.withInternalMemberName(method, false);
1161 mh = mh.withVarargs(true);
1162 assert(method.isVarargs());
1163 FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
1164 return mh;
1165 }
1166 static MethodHandle fakeVarHandleInvoke(MemberName method) {
1167
1168 MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class,
1169 VarHandle.class, Object[].class);
1170 MethodHandle mh = throwException(type);
1171 mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle"));
1172 if (!method.getInvocationType().equals(mh.type()))
1173 throw new InternalError(method.toString());
1174 mh = mh.withInternalMemberName(method, false);
1175 mh = mh.asVarargsCollector(Object[].class);
1176 assert(method.isVarargs());
1177 return mh;
1178 }
1179
1180
1188 static
1189 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1190 return BindCaller.bindCaller(mh, hostClass);
1191 }
1192
1193
1194
1195 private static class BindCaller {
1196 private static MethodType INVOKER_MT = MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1197
1198 static
1199 MethodHandle bindCaller(MethodHandle mh, Class<?> hostClass) {
1200
1201
1202
1203
1204 if (hostClass == null
1205 || (hostClass.isArray() ||
1206 hostClass.isPrimitive() ||
1207 hostClass.getName().startsWith("java.lang.invoke."))) {
1208 throw new InternalError();
1209 }
1210
1211 MethodHandle vamh = prepareForInvoker(mh);
1212
1213 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
1214 return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
1215 }
1216
1217 private static MethodHandle makeInjectedInvoker(Class<?> hostClass) {
1218 try {
1219 Class<?> invokerClass = UNSAFE.defineAnonymousClass(hostClass, INJECTED_INVOKER_TEMPLATE, null);
1220 assert checkInjectedInvoker(hostClass, invokerClass);
1221 return IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1222 } catch (ReflectiveOperationException ex) {
1223 throw uncaughtException(ex);
1224 }
1225 }
1226
1227 private static ClassValue<MethodHandle> CV_makeInjectedInvoker = new ClassValue<MethodHandle>() {
1228 @Override protected MethodHandle computeValue(Class<?> hostClass) {
1229 return makeInjectedInvoker(hostClass);
1230 }
1231 };
1232
1233
1234 private static MethodHandle prepareForInvoker(MethodHandle mh) {
1235 mh = mh.asFixedArity();
1236 MethodType mt = mh.type();
1237 int arity = mt.parameterCount();
1238 MethodHandle vamh = mh.asType(mt.generic());
1239 vamh.internalForm().compileToBytecode();
1240 vamh = vamh.asSpreader(Object[].class, arity);
1241 vamh.internalForm().compileToBytecode();
1242 return vamh;
1243 }
1244
1245
1246 private static MethodHandle restoreToType(MethodHandle vamh,
1247 MethodHandle original,
1248 Class<?> hostClass) {
1249 MethodType type = original.type();
1250 MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
1251 MemberName member = original.internalMemberName();
1252 mh = mh.asType(type);
1253 mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass);
1254 return mh;
1255 }
1256
1257 private static boolean checkInjectedInvoker(Class<?> hostClass, Class<?> invokerClass) {
1258 assert (hostClass.getClassLoader() == invokerClass.getClassLoader()) : hostClass.getName()+" (CL)";
1259 try {
1260 assert (hostClass.getProtectionDomain() == invokerClass.getProtectionDomain()) : hostClass.getName()+" (PD)";
1261 } catch (SecurityException ex) {
1262
1263 }
1264 try {
1265
1266 MethodHandle invoker = IMPL_LOOKUP.findStatic(invokerClass, "invoke_V", INVOKER_MT);
1267 MethodHandle vamh = prepareForInvoker(MH_checkCallerClass);
1268 return (boolean)invoker.invoke(vamh, new Object[]{ invokerClass });
1269 } catch (Throwable ex) {
1270 throw new InternalError(ex);
1271 }
1272 }
1273
1274 private static final MethodHandle MH_checkCallerClass;
1275 static {
1276 final Class<?> THIS_CLASS = BindCaller.class;
1277 assert(checkCallerClass(THIS_CLASS));
1278 try {
1279 MH_checkCallerClass = IMPL_LOOKUP
1280 .findStatic(THIS_CLASS, "checkCallerClass",
1281 MethodType.methodType(boolean.class, Class.class));
1282 assert((boolean) MH_checkCallerClass.invokeExact(THIS_CLASS));
1283 } catch (Throwable ex) {
1284 throw new InternalError(ex);
1285 }
1286 }
1287
1288 @CallerSensitive
1289 @ForceInline
1290 private static boolean checkCallerClass(Class<?> expected) {
1291
1292 Class<?> actual = Reflection.getCallerClass();
1293 if (actual != expected)
1294 throw new InternalError("found " + actual.getName() + ", expected " + expected.getName());
1295 return true;
1296 }
1297
1298 private static final byte[] INJECTED_INVOKER_TEMPLATE = generateInvokerTemplate();
1299
1300
1301 private static byte[] generateInvokerTemplate() {
1302 ClassWriter cw = new ClassWriter(0);
1303
1304
1305
1306
1307
1308
1309
1310 cw.visit(52, ACC_PRIVATE | ACC_SUPER, "InjectedInvoker", null, "java/lang/Object", null);
1311
1312 MethodVisitor mv = cw.visitMethod(ACC_STATIC, "invoke_V",
1313 "(Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;",
1314 null, null);
1315
1316
1317 AnnotationVisitor av0 = mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true);
1318 av0.visitEnd();
1319
1320 mv.visitCode();
1321 mv.visitVarInsn(ALOAD, 0);
1322 mv.visitVarInsn(ALOAD, 1);
1323 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/invoke/MethodHandle", "invokeExact",
1324 "([Ljava/lang/Object;)Ljava/lang/Object;", false);
1325 mv.visitInsn(ARETURN);
1326 mv.visitMaxs(2, 2);
1327 mv.visitEnd();
1328
1329 cw.visitEnd();
1330 return cw.toByteArray();
1331 }
1332 }
1333
1334
1335 private static final class WrappedMember extends DelegatingMethodHandle {
1336 private final MethodHandle target;
1337 private final MemberName member;
1338 private final Class<?> callerClass;
1339 private final boolean isInvokeSpecial;
1340
1341 private WrappedMember(MethodHandle target, MethodType type,
1342 MemberName member, boolean isInvokeSpecial,
1343 Class<?> callerClass) {
1344 super(type, target);
1345 this.target = target;
1346 this.member = member;
1347 this.callerClass = callerClass;
1348 this.isInvokeSpecial = isInvokeSpecial;
1349 }
1350
1351 @Override
1352 MemberName internalMemberName() {
1353 return member;
1354 }
1355 @Override
1356 Class<?> internalCallerClass() {
1357 return callerClass;
1358 }
1359 @Override
1360 boolean isInvokeSpecial() {
1361 return isInvokeSpecial;
1362 }
1363 @Override
1364 protected MethodHandle getTarget() {
1365 return target;
1366 }
1367 @Override
1368 public MethodHandle asTypeUncached(MethodType newType) {
1369
1370
1371 return asTypeCache = target.asType(newType);
1372 }
1373 }
1374
1375 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
1376 if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
1377 return target;
1378 return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
1379 }
1380
1381
1382
1383 enum Intrinsic {
1384 SELECT_ALTERNATIVE,
1385 GUARD_WITH_CATCH,
1386 TRY_FINALLY,
1387 LOOP,
1388 NEW_ARRAY,
1389 ARRAY_LOAD,
1390 ARRAY_STORE,
1391 ARRAY_LENGTH,
1392 IDENTITY,
1393 ZERO,
1394 NONE
1395 }
1396
1397
1399 static final class IntrinsicMethodHandle extends DelegatingMethodHandle {
1400 private final MethodHandle target;
1401 private final Intrinsic intrinsicName;
1402
1403 IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) {
1404 super(target.type(), target);
1405 this.target = target;
1406 this.intrinsicName = intrinsicName;
1407 }
1408
1409 @Override
1410 protected MethodHandle getTarget() {
1411 return target;
1412 }
1413
1414 @Override
1415 Intrinsic intrinsicName() {
1416 return intrinsicName;
1417 }
1418
1419 @Override
1420 public MethodHandle asTypeUncached(MethodType newType) {
1421
1422
1423 return asTypeCache = target.asType(newType);
1424 }
1425
1426 @Override
1427 String internalProperties() {
1428 return super.internalProperties() +
1429 "\n& Intrinsic="+intrinsicName;
1430 }
1431
1432 @Override
1433 public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
1434 if (intrinsicName == Intrinsic.IDENTITY) {
1435 MethodType resultType = type().asCollectorType(arrayType, type().parameterCount() - 1, arrayLength);
1436 MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
1437 return newArray.asType(resultType);
1438 }
1439 return super.asCollector(arrayType, arrayLength);
1440 }
1441 }
1442
1443 static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) {
1444 if (intrinsicName == target.intrinsicName())
1445 return target;
1446 return new IntrinsicMethodHandle(target, intrinsicName);
1447 }
1448
1449 static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) {
1450 return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName);
1451 }
1452
1453
1454
1455 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1456 MethodType type = MethodType.genericMethodType(nargs)
1457 .changeReturnType(rtype)
1458 .insertParameterTypes(0, ptypes);
1459 try {
1460 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1461 } catch (ReflectiveOperationException ex) {
1462 return null;
1463 }
1464 }
1465
1466 private static final Object[] NO_ARGS_ARRAY = {};
1467 private static Object[] makeArray(Object... args) { return args; }
1468 private static Object[] array() { return NO_ARGS_ARRAY; }
1469 private static Object[] array(Object a0)
1470 { return makeArray(a0); }
1471 private static Object[] array(Object a0, Object a1)
1472 { return makeArray(a0, a1); }
1473 private static Object[] array(Object a0, Object a1, Object a2)
1474 { return makeArray(a0, a1, a2); }
1475 private static Object[] array(Object a0, Object a1, Object a2, Object a3)
1476 { return makeArray(a0, a1, a2, a3); }
1477 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1478 Object a4)
1479 { return makeArray(a0, a1, a2, a3, a4); }
1480 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1481 Object a4, Object a5)
1482 { return makeArray(a0, a1, a2, a3, a4, a5); }
1483 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1484 Object a4, Object a5, Object a6)
1485 { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
1486 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1487 Object a4, Object a5, Object a6, Object a7)
1488 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
1489 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1490 Object a4, Object a5, Object a6, Object a7,
1491 Object a8)
1492 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
1493 private static Object[] array(Object a0, Object a1, Object a2, Object a3,
1494 Object a4, Object a5, Object a6, Object a7,
1495 Object a8, Object a9)
1496 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
1497
1498 private static final int ARRAYS_COUNT = 11;
1499 private static final @Stable MethodHandle[] ARRAYS = new MethodHandle[MAX_ARITY + 1];
1500
1501
1502
1503 private static Object[] fillNewArray(Integer len, Object[] args) {
1504 Object[] a = new Object[len];
1505 fillWithArguments(a, 0, args);
1506 return a;
1507 }
1508 private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] args) {
1509 Object[] a = Arrays.copyOf(example, len);
1510 assert(a.getClass() != Object[].class);
1511 fillWithArguments(a, 0, args);
1512 return a;
1513 }
1514 private static void fillWithArguments(Object[] a, int pos, Object... args) {
1515 System.arraycopy(args, 0, a, pos, args.length);
1516 }
1517
1518 private static Object[] fillArray(Integer pos, Object[] a, Object a0)
1519 { fillWithArguments(a, pos, a0); return a; }
1520 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
1521 { fillWithArguments(a, pos, a0, a1); return a; }
1522 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
1523 { fillWithArguments(a, pos, a0, a1, a2); return a; }
1524 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
1525 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
1526 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1527 Object a4)
1528 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
1529 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1530 Object a4, Object a5)
1531 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
1532 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1533 Object a4, Object a5, Object a6)
1534 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
1535 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1536 Object a4, Object a5, Object a6, Object a7)
1537 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
1538 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1539 Object a4, Object a5, Object a6, Object a7,
1540 Object a8)
1541 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
1542 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
1543 Object a4, Object a5, Object a6, Object a7,
1544 Object a8, Object a9)
1545 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
1546
1547 private static final int FILL_ARRAYS_COUNT = 11;
1548 private static final @Stable MethodHandle[] FILL_ARRAYS = new MethodHandle[FILL_ARRAYS_COUNT];
1549
1550 private static MethodHandle getFillArray(int count) {
1551 assert (count > 0 && count < FILL_ARRAYS_COUNT);
1552 MethodHandle mh = FILL_ARRAYS[count];
1553 if (mh != null) {
1554 return mh;
1555 }
1556 mh = findCollector("fillArray", count, Object[].class, Integer.class, Object[].class);
1557 FILL_ARRAYS[count] = mh;
1558 return mh;
1559 }
1560
1561 private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
1562 Object a = w.makeArray(boxes.length);
1563 w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
1564 return a;
1565 }
1566
1567
1570 static MethodHandle varargsArray(int nargs) {
1571 MethodHandle mh = ARRAYS[nargs];
1572 if (mh != null) {
1573 return mh;
1574 }
1575 if (nargs < ARRAYS_COUNT) {
1576 mh = findCollector("array", nargs, Object[].class);
1577 } else {
1578 mh = buildVarargsArray(getConstantHandle(MH_fillNewArray),
1579 getConstantHandle(MH_arrayIdentity), nargs);
1580 }
1581 assert(assertCorrectArity(mh, nargs));
1582 mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1583 return ARRAYS[nargs] = mh;
1584 }
1585
1586 private static boolean assertCorrectArity(MethodHandle mh, int arity) {
1587 assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
1588 return true;
1589 }
1590
1591
1592 static <T> T[] identity(T[] x) {
1593 return x;
1594 }
1595
1596 private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
1597
1598
1599
1600 int leftLen = Math.min(nargs, LEFT_ARGS);
1601 int rightLen = nargs - leftLen;
1602 MethodHandle leftCollector = newArray.bindTo(nargs);
1603 leftCollector = leftCollector.asCollector(Object[].class, leftLen);
1604 MethodHandle mh = finisher;
1605 if (rightLen > 0) {
1606 MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
1607 if (mh.equals(getConstantHandle(MH_arrayIdentity)))
1608 mh = rightFiller;
1609 else
1610 mh = MethodHandles.collectArguments(mh, 0, rightFiller);
1611 }
1612 if (mh.equals(getConstantHandle(MH_arrayIdentity)))
1613 mh = leftCollector;
1614 else
1615 mh = MethodHandles.collectArguments(mh, 0, leftCollector);
1616 return mh;
1617 }
1618
1619 private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1;
1620 private static final @Stable MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY + 1];
1621
1625 private static MethodHandle fillToRight(int nargs) {
1626 MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
1627 if (filler != null) return filler;
1628 filler = buildFiller(nargs);
1629 assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
1630 return FILL_ARRAY_TO_RIGHT[nargs] = filler;
1631 }
1632 private static MethodHandle buildFiller(int nargs) {
1633 if (nargs <= LEFT_ARGS)
1634 return getConstantHandle(MH_arrayIdentity);
1635
1636 final int CHUNK = LEFT_ARGS;
1637 int rightLen = nargs % CHUNK;
1638 int midLen = nargs - rightLen;
1639 if (rightLen == 0) {
1640 midLen = nargs - (rightLen = CHUNK);
1641 if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
1642
1643 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
1644 if (j > LEFT_ARGS) fillToRight(j);
1645 }
1646 }
1647 if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
1648 assert(rightLen > 0);
1649 MethodHandle midFill = fillToRight(midLen);
1650 MethodHandle rightFill = getFillArray(rightLen).bindTo(midLen);
1651 assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS);
1652 assert(rightFill.type().parameterCount() == 1 + rightLen);
1653
1654
1655
1656
1657
1658 if (midLen == LEFT_ARGS)
1659 return rightFill;
1660 else
1661 return MethodHandles.collectArguments(rightFill, 0, midFill);
1662 }
1663
1664 static final int MAX_JVM_ARITY = 255;
1665
1666
1670 static MethodHandle varargsArray(Class<?> arrayType, int nargs) {
1671 Class<?> elemType = arrayType.getComponentType();
1672 if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType);
1673
1674 if (nargs >= MAX_JVM_ARITY/2 - 1) {
1675 int slots = nargs;
1676 final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;
1677 if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive())
1678 slots *= Wrapper.forPrimitiveType(elemType).stackSlots();
1679 if (slots > MAX_ARRAY_SLOTS)
1680 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
1681 }
1682 if (elemType == Object.class)
1683 return varargsArray(nargs);
1684
1685 MethodHandle cache[] = Makers.TYPED_COLLECTORS.get(elemType);
1686 MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
1687 if (mh != null) return mh;
1688 if (nargs == 0) {
1689 Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0);
1690 mh = MethodHandles.constant(arrayType, example);
1691 } else if (elemType.isPrimitive()) {
1692 MethodHandle builder = getConstantHandle(MH_fillNewArray);
1693 MethodHandle producer = buildArrayProducer(arrayType);
1694 mh = buildVarargsArray(builder, producer, nargs);
1695 } else {
1696 Class<? extends Object[]> objArrayType = arrayType.asSubclass(Object[].class);
1697 Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
1698 MethodHandle builder = getConstantHandle(MH_fillNewTypedArray).bindTo(example);
1699 MethodHandle producer = getConstantHandle(MH_arrayIdentity);
1700 mh = buildVarargsArray(builder, producer, nargs);
1701 }
1702 mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)));
1703 mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
1704 assert(assertCorrectArity(mh, nargs));
1705 if (nargs < cache.length)
1706 cache[nargs] = mh;
1707 return mh;
1708 }
1709
1710 private static MethodHandle buildArrayProducer(Class<?> arrayType) {
1711 Class<?> elemType = arrayType.getComponentType();
1712 assert(elemType.isPrimitive());
1713 return getConstantHandle(MH_copyAsPrimitiveArray).bindTo(Wrapper.forPrimitiveType(elemType));
1714 }
1715
1716 static void assertSame(Object mh1, Object mh2) {
1717 if (mh1 != mh2) {
1718 String msg = String.format("mh1 != mh2: mh1 = %s (form: %s); mh2 = %s (form: %s)",
1719 mh1, ((MethodHandle)mh1).form,
1720 mh2, ((MethodHandle)mh2).form);
1721 throw newInternalError(msg);
1722 }
1723 }
1724
1725
1726
1727
1728 static final byte NF_checkSpreadArgument = 0,
1729 NF_guardWithCatch = 1,
1730 NF_throwException = 2,
1731 NF_tryFinally = 3,
1732 NF_loop = 4,
1733 NF_profileBoolean = 5,
1734 NF_LIMIT = 6;
1735
1736 private static final @Stable NamedFunction[] NFS = new NamedFunction[NF_LIMIT];
1737
1738 static NamedFunction getFunction(byte func) {
1739 NamedFunction nf = NFS[func];
1740 if (nf != null) {
1741 return nf;
1742 }
1743 return NFS[func] = createFunction(func);
1744 }
1745
1746 private static NamedFunction createFunction(byte func) {
1747 try {
1748 switch (func) {
1749 case NF_checkSpreadArgument:
1750 return new NamedFunction(MethodHandleImpl.class
1751 .getDeclaredMethod("checkSpreadArgument", Object.class, int.class));
1752 case NF_guardWithCatch:
1753 return new NamedFunction(MethodHandleImpl.class
1754 .getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class,
1755 MethodHandle.class, Object[].class));
1756 case NF_tryFinally:
1757 return new NamedFunction(MethodHandleImpl.class
1758 .getDeclaredMethod("tryFinally", MethodHandle.class, MethodHandle.class, Object[].class));
1759 case NF_loop:
1760 return new NamedFunction(MethodHandleImpl.class
1761 .getDeclaredMethod("loop", BasicType[].class, LoopClauses.class, Object[].class));
1762 case NF_throwException:
1763 return new NamedFunction(MethodHandleImpl.class
1764 .getDeclaredMethod("throwException", Throwable.class));
1765 case NF_profileBoolean:
1766 return new NamedFunction(MethodHandleImpl.class
1767 .getDeclaredMethod("profileBoolean", boolean.class, int[].class));
1768 default:
1769 throw new InternalError("Undefined function: " + func);
1770 }
1771 } catch (ReflectiveOperationException ex) {
1772 throw newInternalError(ex);
1773 }
1774 }
1775
1776 static {
1777 SharedSecrets.setJavaLangInvokeAccess(new JavaLangInvokeAccess() {
1778 @Override
1779 public Object newMemberName() {
1780 return new MemberName();
1781 }
1782
1783 @Override
1784 public String getName(Object mname) {
1785 MemberName memberName = (MemberName)mname;
1786 return memberName.getName();
1787 }
1788 @Override
1789 public Class<?> getDeclaringClass(Object mname) {
1790 MemberName memberName = (MemberName)mname;
1791 return memberName.getDeclaringClass();
1792 }
1793
1794 @Override
1795 public MethodType getMethodType(Object mname) {
1796 MemberName memberName = (MemberName)mname;
1797 return memberName.getMethodType();
1798 }
1799
1800 @Override
1801 public String getMethodDescriptor(Object mname) {
1802 MemberName memberName = (MemberName)mname;
1803 return memberName.getMethodDescriptor();
1804 }
1805
1806 @Override
1807 public boolean isNative(Object mname) {
1808 MemberName memberName = (MemberName)mname;
1809 return memberName.isNative();
1810 }
1811
1812 @Override
1813 public byte[] generateDirectMethodHandleHolderClassBytes(
1814 String className, MethodType[] methodTypes, int[] types) {
1815 return GenerateJLIClassesHelper
1816 .generateDirectMethodHandleHolderClassBytes(
1817 className, methodTypes, types);
1818 }
1819
1820 @Override
1821 public byte[] generateDelegatingMethodHandleHolderClassBytes(
1822 String className, MethodType[] methodTypes) {
1823 return GenerateJLIClassesHelper
1824 .generateDelegatingMethodHandleHolderClassBytes(
1825 className, methodTypes);
1826 }
1827
1828 @Override
1829 public Map.Entry<String, byte[]> generateConcreteBMHClassBytes(
1830 final String types) {
1831 return GenerateJLIClassesHelper
1832 .generateConcreteBMHClassBytes(types);
1833 }
1834
1835 @Override
1836 public byte[] generateBasicFormsClassBytes(final String className) {
1837 return GenerateJLIClassesHelper
1838 .generateBasicFormsClassBytes(className);
1839 }
1840
1841 @Override
1842 public byte[] generateInvokersHolderClassBytes(final String className,
1843 MethodType[] invokerMethodTypes,
1844 MethodType[] callSiteMethodTypes) {
1845 return GenerateJLIClassesHelper
1846 .generateInvokersHolderClassBytes(className,
1847 invokerMethodTypes, callSiteMethodTypes);
1848 }
1849
1850 });
1851 }
1852
1853
1854 private static MethodHandle unboxResultHandle(Class<?> returnType) {
1855 if (returnType.isPrimitive()) {
1856 if (returnType == void.class) {
1857 return ValueConversions.ignore();
1858 } else {
1859 Wrapper w = Wrapper.forPrimitiveType(returnType);
1860 return ValueConversions.unboxExact(w);
1861 }
1862 } else {
1863 return MethodHandles.identity(Object.class);
1864 }
1865 }
1866
1867
1879 static MethodHandle makeLoop(Class<?> tloop, List<Class<?>> targs, List<MethodHandle> init, List<MethodHandle> step,
1880 List<MethodHandle> pred, List<MethodHandle> fini) {
1881 MethodType type = MethodType.methodType(tloop, targs);
1882 BasicType[] initClauseTypes =
1883 init.stream().map(h -> h.type().returnType()).map(BasicType::basicType).toArray(BasicType[]::new);
1884 LambdaForm form = makeLoopForm(type.basicType(), initClauseTypes);
1885
1886
1887
1888 MethodType varargsType = type.changeReturnType(Object[].class);
1889 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
1890 MethodHandle unboxResult = unboxResultHandle(tloop);
1891
1892 LoopClauses clauseData =
1893 new LoopClauses(new MethodHandle[][]{toArray(init), toArray(step), toArray(pred), toArray(fini)});
1894 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
1895 BoundMethodHandle mh;
1896 try {
1897 mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) clauseData,
1898 (Object) collectArgs, (Object) unboxResult);
1899 } catch (Throwable ex) {
1900 throw uncaughtException(ex);
1901 }
1902 assert(mh.type() == type);
1903 return mh;
1904 }
1905
1906 private static MethodHandle[] toArray(List<MethodHandle> l) {
1907 return l.toArray(new MethodHandle[0]);
1908 }
1909
1910
1938 private static LambdaForm makeLoopForm(MethodType basicType, BasicType[] localVarTypes) {
1939 MethodType lambdaType = basicType.invokerType();
1940
1941 final int THIS_MH = 0;
1942 final int ARG_BASE = 1;
1943 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
1944
1945 int nameCursor = ARG_LIMIT;
1946 final int GET_CLAUSE_DATA = nameCursor++;
1947 final int GET_COLLECT_ARGS = nameCursor++;
1948 final int GET_UNBOX_RESULT = nameCursor++;
1949 final int BOXED_ARGS = nameCursor++;
1950 final int LOOP = nameCursor++;
1951 final int UNBOX_RESULT = nameCursor++;
1952
1953 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_LOOP);
1954 if (lform == null) {
1955 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
1956
1957 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
1958 names[THIS_MH] = names[THIS_MH].withConstraint(data);
1959 names[GET_CLAUSE_DATA] = new Name(data.getterFunction(0), names[THIS_MH]);
1960 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(1), names[THIS_MH]);
1961 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(2), names[THIS_MH]);
1962
1963
1964 MethodType collectArgsType = basicType.changeReturnType(Object.class);
1965 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
1966 Object[] args = new Object[invokeBasic.type().parameterCount()];
1967 args[0] = names[GET_COLLECT_ARGS];
1968 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT - ARG_BASE);
1969 names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.LOOP), args);
1970
1971
1972 Object[] lArgs =
1973 new Object[]{null,
1974 names[GET_CLAUSE_DATA], names[BOXED_ARGS]};
1975 names[LOOP] = new Name(getFunction(NF_loop), lArgs);
1976
1977
1978 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
1979 Object[] unboxArgs = new Object[]{names[GET_UNBOX_RESULT], names[LOOP]};
1980 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
1981
1982 lform = basicType.form().setCachedLambdaForm(MethodTypeForm.LF_LOOP,
1983 new LambdaForm(lambdaType.parameterCount(), names, Kind.LOOP));
1984 }
1985
1986
1987 return lform.editor().noteLoopLocalTypesForm(BOXED_ARGS, localVarTypes);
1988 }
1989
1990 static class LoopClauses {
1991 @Stable final MethodHandle[][] clauses;
1992 LoopClauses(MethodHandle[][] clauses) {
1993 assert clauses.length == 4;
1994 this.clauses = clauses;
1995 }
1996 @Override
1997 public String toString() {
1998 StringBuffer sb = new StringBuffer("LoopClauses -- ");
1999 for (int i = 0; i < 4; ++i) {
2000 if (i > 0) {
2001 sb.append(" ");
2002 }
2003 sb.append('<').append(i).append(">: ");
2004 MethodHandle[] hs = clauses[i];
2005 for (int j = 0; j < hs.length; ++j) {
2006 if (j > 0) {
2007 sb.append(" ");
2008 }
2009 sb.append('*').append(j).append(": ").append(hs[j]).append('\n');
2010 }
2011 }
2012 sb.append(" --\n");
2013 return sb.toString();
2014 }
2015 }
2016
2017
2021 @LambdaForm.Hidden
2022 static Object loop(BasicType[] localTypes, LoopClauses clauseData, Object... av) throws Throwable {
2023 final MethodHandle[] init = clauseData.clauses[0];
2024 final MethodHandle[] step = clauseData.clauses[1];
2025 final MethodHandle[] pred = clauseData.clauses[2];
2026 final MethodHandle[] fini = clauseData.clauses[3];
2027 int varSize = (int) Stream.of(init).filter(h -> h.type().returnType() != void.class).count();
2028 int nArgs = init[0].type().parameterCount();
2029 Object[] varsAndArgs = new Object[varSize + nArgs];
2030 for (int i = 0, v = 0; i < init.length; ++i) {
2031 MethodHandle ih = init[i];
2032 if (ih.type().returnType() == void.class) {
2033 ih.invokeWithArguments(av);
2034 } else {
2035 varsAndArgs[v++] = ih.invokeWithArguments(av);
2036 }
2037 }
2038 System.arraycopy(av, 0, varsAndArgs, varSize, nArgs);
2039 final int nSteps = step.length;
2040 for (; ; ) {
2041 for (int i = 0, v = 0; i < nSteps; ++i) {
2042 MethodHandle p = pred[i];
2043 MethodHandle s = step[i];
2044 MethodHandle f = fini[i];
2045 if (s.type().returnType() == void.class) {
2046 s.invokeWithArguments(varsAndArgs);
2047 } else {
2048 varsAndArgs[v++] = s.invokeWithArguments(varsAndArgs);
2049 }
2050 if (!(boolean) p.invokeWithArguments(varsAndArgs)) {
2051 return f.invokeWithArguments(varsAndArgs);
2052 }
2053 }
2054 }
2055 }
2056
2057
2066 static boolean countedLoopPredicate(int limit, int counter) {
2067 return counter < limit;
2068 }
2069
2070
2079 static int countedLoopStep(int limit, int counter) {
2080 return counter + 1;
2081 }
2082
2083
2090 static Iterator<?> initIterator(Iterable<?> it) {
2091 return it.iterator();
2092 }
2093
2094
2101 static boolean iteratePredicate(Iterator<?> it) {
2102 return it.hasNext();
2103 }
2104
2105
2113 static Object iterateNext(Iterator<?> it) {
2114 return it.next();
2115 }
2116
2117
2127 static MethodHandle makeTryFinally(MethodHandle target, MethodHandle cleanup, Class<?> rtype, List<Class<?>> argTypes) {
2128 MethodType type = MethodType.methodType(rtype, argTypes);
2129 LambdaForm form = makeTryFinallyForm(type.basicType());
2130
2131
2132
2133 MethodType varargsType = type.changeReturnType(Object[].class);
2134 MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
2135 MethodHandle unboxResult = unboxResultHandle(rtype);
2136
2137 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
2138 BoundMethodHandle mh;
2139 try {
2140 mh = (BoundMethodHandle) data.factory().invokeBasic(type, form, (Object) target, (Object) cleanup,
2141 (Object) collectArgs, (Object) unboxResult);
2142 } catch (Throwable ex) {
2143 throw uncaughtException(ex);
2144 }
2145 assert(mh.type() == type);
2146 return mh;
2147 }
2148
2149
2171 private static LambdaForm makeTryFinallyForm(MethodType basicType) {
2172 MethodType lambdaType = basicType.invokerType();
2173
2174 LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_TF);
2175 if (lform != null) {
2176 return lform;
2177 }
2178 final int THIS_MH = 0;
2179 final int ARG_BASE = 1;
2180 final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
2181
2182 int nameCursor = ARG_LIMIT;
2183 final int GET_TARGET = nameCursor++;
2184 final int GET_CLEANUP = nameCursor++;
2185 final int GET_COLLECT_ARGS = nameCursor++;
2186 final int GET_UNBOX_RESULT = nameCursor++;
2187 final int BOXED_ARGS = nameCursor++;
2188 final int TRY_FINALLY = nameCursor++;
2189 final int UNBOX_RESULT = nameCursor++;
2190
2191 Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
2192
2193 BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL();
2194 names[THIS_MH] = names[THIS_MH].withConstraint(data);
2195 names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]);
2196 names[GET_CLEANUP] = new Name(data.getterFunction(1), names[THIS_MH]);
2197 names[GET_COLLECT_ARGS] = new Name(data.getterFunction(2), names[THIS_MH]);
2198 names[GET_UNBOX_RESULT] = new Name(data.getterFunction(3), names[THIS_MH]);
2199
2200
2201 MethodType collectArgsType = basicType.changeReturnType(Object.class);
2202 MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
2203 Object[] args = new Object[invokeBasic.type().parameterCount()];
2204 args[0] = names[GET_COLLECT_ARGS];
2205 System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
2206 names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic, Intrinsic.TRY_FINALLY), args);
2207
2208
2209 Object[] tfArgs = new Object[] {names[GET_TARGET], names[GET_CLEANUP], names[BOXED_ARGS]};
2210 names[TRY_FINALLY] = new Name(getFunction(NF_tryFinally), tfArgs);
2211
2212
2213 MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
2214 Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_FINALLY]};
2215 names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
2216
2217 lform = new LambdaForm(lambdaType.parameterCount(), names, Kind.TRY_FINALLY);
2218
2219 return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_TF, lform);
2220 }
2221
2222
2226 @LambdaForm.Hidden
2227 static Object tryFinally(MethodHandle target, MethodHandle cleanup, Object... av) throws Throwable {
2228 Throwable t = null;
2229 Object r = null;
2230 try {
2231 r = target.invokeWithArguments(av);
2232 } catch (Throwable thrown) {
2233 t = thrown;
2234 throw t;
2235 } finally {
2236 Object[] args = target.type().returnType() == void.class ? prepend(av, t) : prepend(av, t, r);
2237 r = cleanup.invokeWithArguments(args);
2238 }
2239 return r;
2240 }
2241
2242
2243 static final int
2244 MH_cast = 0,
2245 MH_selectAlternative = 1,
2246 MH_copyAsPrimitiveArray = 2,
2247 MH_fillNewTypedArray = 3,
2248 MH_fillNewArray = 4,
2249 MH_arrayIdentity = 5,
2250 MH_countedLoopPred = 6,
2251 MH_countedLoopStep = 7,
2252 MH_initIterator = 8,
2253 MH_iteratePred = 9,
2254 MH_iterateNext = 10,
2255 MH_Array_newInstance = 11,
2256 MH_LIMIT = 12;
2257
2258 static MethodHandle getConstantHandle(int idx) {
2259 MethodHandle handle = HANDLES[idx];
2260 if (handle != null) {
2261 return handle;
2262 }
2263 return setCachedHandle(idx, makeConstantHandle(idx));
2264 }
2265
2266 private static synchronized MethodHandle setCachedHandle(int idx, final MethodHandle method) {
2267
2268 MethodHandle prev = HANDLES[idx];
2269 if (prev != null) {
2270 return prev;
2271 }
2272 HANDLES[idx] = method;
2273 return method;
2274 }
2275
2276
2277 private static final @Stable MethodHandle[] HANDLES = new MethodHandle[MH_LIMIT];
2278
2279 private static MethodHandle makeConstantHandle(int idx) {
2280 try {
2281 switch (idx) {
2282 case MH_cast:
2283 return IMPL_LOOKUP.findVirtual(Class.class, "cast",
2284 MethodType.methodType(Object.class, Object.class));
2285 case MH_copyAsPrimitiveArray:
2286 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "copyAsPrimitiveArray",
2287 MethodType.methodType(Object.class, Wrapper.class, Object[].class));
2288 case MH_arrayIdentity:
2289 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "identity",
2290 MethodType.methodType(Object[].class, Object[].class));
2291 case MH_fillNewArray:
2292 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewArray",
2293 MethodType.methodType(Object[].class, Integer.class, Object[].class));
2294 case MH_fillNewTypedArray:
2295 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "fillNewTypedArray",
2296 MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class));
2297 case MH_selectAlternative:
2298 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
2299 MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
2300 case MH_countedLoopPred:
2301 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopPredicate",
2302 MethodType.methodType(boolean.class, int.class, int.class));
2303 case MH_countedLoopStep:
2304 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "countedLoopStep",
2305 MethodType.methodType(int.class, int.class, int.class));
2306 case MH_initIterator:
2307 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "initIterator",
2308 MethodType.methodType(Iterator.class, Iterable.class));
2309 case MH_iteratePred:
2310 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iteratePredicate",
2311 MethodType.methodType(boolean.class, Iterator.class));
2312 case MH_iterateNext:
2313 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "iterateNext",
2314 MethodType.methodType(Object.class, Iterator.class));
2315 case MH_Array_newInstance:
2316 return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
2317 MethodType.methodType(Object.class, Class.class, int.class));
2318 }
2319 } catch (ReflectiveOperationException ex) {
2320 throw newInternalError(ex);
2321 }
2322 throw newInternalError("Unknown function index: " + idx);
2323 }
2324 }
2325