1
25
26 package java.lang.invoke;
27
28 import jdk.internal.perf.PerfCounter;
29 import jdk.internal.vm.annotation.DontInline;
30 import jdk.internal.vm.annotation.Stable;
31 import sun.invoke.util.Wrapper;
32
33 import java.lang.annotation.ElementType;
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.lang.annotation.Target;
37 import java.lang.reflect.Method;
38 import java.util.Arrays;
39 import java.util.HashMap;
40
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
43 import static java.lang.invoke.MethodHandleStatics.*;
44
45
123 class LambdaForm {
124 final int arity;
125 final int result;
126 final boolean forceInline;
127 final MethodHandle customized;
128 @Stable final Name[] names;
129 final Kind kind;
130 MemberName vmentry;
131 private boolean isCompiled;
132
133
134 volatile Object transformCache;
135
136 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
137
138 enum BasicType {
139 L_TYPE('L', Object.class, Wrapper.OBJECT),
140 I_TYPE('I', int.class, Wrapper.INT),
141 J_TYPE('J', long.class, Wrapper.LONG),
142 F_TYPE('F', float.class, Wrapper.FLOAT),
143 D_TYPE('D', double.class, Wrapper.DOUBLE),
144 V_TYPE('V', void.class, Wrapper.VOID);
145
146 static final @Stable BasicType[] ALL_TYPES = BasicType.values();
147 static final @Stable BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
148
149 static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
150 static final int TYPE_LIMIT = ALL_TYPES.length;
151
152
153
154 static final byte
155 L_TYPE_NUM = (byte) L_TYPE.ordinal(),
156 I_TYPE_NUM = (byte) I_TYPE.ordinal(),
157 J_TYPE_NUM = (byte) J_TYPE.ordinal(),
158 F_TYPE_NUM = (byte) F_TYPE.ordinal(),
159 D_TYPE_NUM = (byte) D_TYPE.ordinal(),
160 V_TYPE_NUM = (byte) V_TYPE.ordinal();
161
162 final char btChar;
163 final Class<?> btClass;
164 final Wrapper btWrapper;
165
166 private BasicType(char btChar, Class<?> btClass, Wrapper wrapper) {
167 this.btChar = btChar;
168 this.btClass = btClass;
169 this.btWrapper = wrapper;
170 }
171
172 char basicTypeChar() {
173 return btChar;
174 }
175 Class<?> basicTypeClass() {
176 return btClass;
177 }
178 Wrapper basicTypeWrapper() {
179 return btWrapper;
180 }
181 int basicTypeSlots() {
182 return btWrapper.stackSlots();
183 }
184
185 static BasicType basicType(byte type) {
186 return ALL_TYPES[type];
187 }
188 static BasicType basicType(char type) {
189 switch (type) {
190 case 'L': return L_TYPE;
191 case 'I': return I_TYPE;
192 case 'J': return J_TYPE;
193 case 'F': return F_TYPE;
194 case 'D': return D_TYPE;
195 case 'V': return V_TYPE;
196
197 case 'Z':
198 case 'B':
199 case 'S':
200 case 'C':
201 return I_TYPE;
202 default:
203 throw newInternalError("Unknown type char: '"+type+"'");
204 }
205 }
206 static BasicType basicType(Wrapper type) {
207 char c = type.basicTypeChar();
208 return basicType(c);
209 }
210 static BasicType basicType(Class<?> type) {
211 if (!type.isPrimitive()) return L_TYPE;
212 return basicType(Wrapper.forPrimitiveType(type));
213 }
214 static BasicType[] basicTypes(String types) {
215 BasicType[] btypes = new BasicType[types.length()];
216 for (int i = 0; i < btypes.length; i++) {
217 btypes[i] = basicType(types.charAt(i));
218 }
219 return btypes;
220 }
221 static String basicTypeDesc(BasicType[] types) {
222 if (types == null) {
223 return null;
224 }
225 if (types.length == 0) {
226 return "";
227 }
228 StringBuilder sb = new StringBuilder();
229 for (BasicType bt : types) {
230 sb.append(bt.basicTypeChar());
231 }
232 return sb.toString();
233 }
234 static int[] basicTypeOrds(BasicType[] types) {
235 if (types == null) {
236 return null;
237 }
238 int[] a = new int[types.length];
239 for(int i = 0; i < types.length; ++i) {
240 a[i] = types[i].ordinal();
241 }
242 return a;
243 }
244
245 static char basicTypeChar(Class<?> type) {
246 return basicType(type).btChar;
247 }
248
249 static byte[] basicTypesOrd(Class<?>[] types) {
250 byte[] ords = new byte[types.length];
251 for (int i = 0; i < ords.length; i++) {
252 ords[i] = (byte)basicType(types[i]).ordinal();
253 }
254 return ords;
255 }
256
257 static boolean isBasicTypeChar(char c) {
258 return "LIJFDV".indexOf(c) >= 0;
259 }
260 static boolean isArgBasicTypeChar(char c) {
261 return "LIJFD".indexOf(c) >= 0;
262 }
263
264 static { assert(checkBasicType()); }
265 private static boolean checkBasicType() {
266 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
267 assert ARG_TYPES[i].ordinal() == i;
268 assert ARG_TYPES[i] == ALL_TYPES[i];
269 }
270 for (int i = 0; i < TYPE_LIMIT; i++) {
271 assert ALL_TYPES[i].ordinal() == i;
272 }
273 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
274 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
275 return true;
276 }
277 }
278
279 enum Kind {
280 GENERIC("invoke"),
281 ZERO("zero"),
282 IDENTITY("identity"),
283 BOUND_REINVOKER("BMH.reinvoke", "reinvoke"),
284 REINVOKER("MH.reinvoke", "reinvoke"),
285 DELEGATE("MH.delegate", "delegate"),
286 EXACT_LINKER("MH.invokeExact_MT", "invokeExact_MT"),
287 EXACT_INVOKER("MH.exactInvoker", "exactInvoker"),
288 GENERIC_LINKER("MH.invoke_MT", "invoke_MT"),
289 GENERIC_INVOKER("MH.invoker", "invoker"),
290 LINK_TO_TARGET_METHOD("linkToTargetMethod"),
291 LINK_TO_CALL_SITE("linkToCallSite"),
292 DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual", "invokeVirtual"),
293 DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial", "invokeSpecial"),
294 DIRECT_INVOKE_SPECIAL_IFC("DMH.invokeSpecialIFC", "invokeSpecialIFC"),
295 DIRECT_INVOKE_STATIC("DMH.invokeStatic", "invokeStatic"),
296 DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial", "newInvokeSpecial"),
297 DIRECT_INVOKE_INTERFACE("DMH.invokeInterface", "invokeInterface"),
298 DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit", "invokeStaticInit"),
299 GET_OBJECT("getObject"),
300 PUT_OBJECT("putObject"),
301 GET_OBJECT_VOLATILE("getObjectVolatile"),
302 PUT_OBJECT_VOLATILE("putObjectVolatile"),
303 GET_INT("getInt"),
304 PUT_INT("putInt"),
305 GET_INT_VOLATILE("getIntVolatile"),
306 PUT_INT_VOLATILE("putIntVolatile"),
307 GET_BOOLEAN("getBoolean"),
308 PUT_BOOLEAN("putBoolean"),
309 GET_BOOLEAN_VOLATILE("getBooleanVolatile"),
310 PUT_BOOLEAN_VOLATILE("putBooleanVolatile"),
311 GET_BYTE("getByte"),
312 PUT_BYTE("putByte"),
313 GET_BYTE_VOLATILE("getByteVolatile"),
314 PUT_BYTE_VOLATILE("putByteVolatile"),
315 GET_CHAR("getChar"),
316 PUT_CHAR("putChar"),
317 GET_CHAR_VOLATILE("getCharVolatile"),
318 PUT_CHAR_VOLATILE("putCharVolatile"),
319 GET_SHORT("getShort"),
320 PUT_SHORT("putShort"),
321 GET_SHORT_VOLATILE("getShortVolatile"),
322 PUT_SHORT_VOLATILE("putShortVolatile"),
323 GET_LONG("getLong"),
324 PUT_LONG("putLong"),
325 GET_LONG_VOLATILE("getLongVolatile"),
326 PUT_LONG_VOLATILE("putLongVolatile"),
327 GET_FLOAT("getFloat"),
328 PUT_FLOAT("putFloat"),
329 GET_FLOAT_VOLATILE("getFloatVolatile"),
330 PUT_FLOAT_VOLATILE("putFloatVolatile"),
331 GET_DOUBLE("getDouble"),
332 PUT_DOUBLE("putDouble"),
333 GET_DOUBLE_VOLATILE("getDoubleVolatile"),
334 PUT_DOUBLE_VOLATILE("putDoubleVolatile"),
335 TRY_FINALLY("tryFinally"),
336 COLLECT("collect"),
337 CONVERT("convert"),
338 SPREAD("spread"),
339 LOOP("loop"),
340 FIELD("field"),
341 GUARD("guard"),
342 GUARD_WITH_CATCH("guardWithCatch"),
343 VARHANDLE_EXACT_INVOKER("VH.exactInvoker"),
344 VARHANDLE_INVOKER("VH.invoker", "invoker"),
345 VARHANDLE_LINKER("VH.invoke_MT", "invoke_MT");
346
347 final String defaultLambdaName;
348 final String methodName;
349
350 private Kind(String defaultLambdaName) {
351 this(defaultLambdaName, defaultLambdaName);
352 }
353
354 private Kind(String defaultLambdaName, String methodName) {
355 this.defaultLambdaName = defaultLambdaName;
356 this.methodName = methodName;
357 }
358 }
359
360 LambdaForm(int arity, Name[] names, int result) {
361 this(arity, names, result, true, null, Kind.GENERIC);
362 }
363 LambdaForm(int arity, Name[] names, int result, Kind kind) {
364 this(arity, names, result, true, null, kind);
365 }
366 LambdaForm(int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
367 this(arity, names, result, forceInline, customized, Kind.GENERIC);
368 }
369 LambdaForm(int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) {
370 assert(namesOK(arity, names));
371 this.arity = arity;
372 this.result = fixResult(result, names);
373 this.names = names.clone();
374 this.forceInline = forceInline;
375 this.customized = customized;
376 this.kind = kind;
377 int maxOutArity = normalize();
378 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
379
380 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
381 compileToBytecode();
382 }
383 }
384 LambdaForm(int arity, Name[] names) {
385 this(arity, names, LAST_RESULT, true, null, Kind.GENERIC);
386 }
387 LambdaForm(int arity, Name[] names, Kind kind) {
388 this(arity, names, LAST_RESULT, true, null, kind);
389 }
390 LambdaForm(int arity, Name[] names, boolean forceInline) {
391 this(arity, names, LAST_RESULT, forceInline, null, Kind.GENERIC);
392 }
393 LambdaForm(int arity, Name[] names, boolean forceInline, Kind kind) {
394 this(arity, names, LAST_RESULT, forceInline, null, kind);
395 }
396 LambdaForm(Name[] formals, Name[] temps, Name result) {
397 this(formals.length, buildNames(formals, temps, result), LAST_RESULT, true, null);
398 }
399 LambdaForm(Name[] formals, Name[] temps, Name result, boolean forceInline) {
400 this(formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, null);
401 }
402
403 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
404 int arity = formals.length;
405 int length = arity + temps.length + (result == null ? 0 : 1);
406 Name[] names = Arrays.copyOf(formals, length);
407 System.arraycopy(temps, 0, names, arity, temps.length);
408 if (result != null)
409 names[length - 1] = result;
410 return names;
411 }
412
413 private LambdaForm(MethodType mt) {
414
415
416
417 this.arity = mt.parameterCount();
418 this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
419 this.names = buildEmptyNames(arity, mt, result == -1);
420 this.forceInline = true;
421 this.customized = null;
422 this.kind = Kind.ZERO;
423 assert(nameRefsAreLegal());
424 assert(isEmpty());
425 String sig = null;
426 assert(isValidSignature(sig = basicTypeSignature()));
427 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
428 }
429
430 private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
431 Name[] names = arguments(isVoid ? 0 : 1, mt);
432 if (!isVoid) {
433 Name zero = new Name(constantZero(basicType(mt.returnType())));
434 names[arity] = zero.newIndex(arity);
435 }
436 return names;
437 }
438
439 private static int fixResult(int result, Name[] names) {
440 if (result == LAST_RESULT)
441 result = names.length - 1;
442 if (result >= 0 && names[result].type == V_TYPE)
443 result = VOID_RESULT;
444 return result;
445 }
446
447 static boolean debugNames() {
448 return DEBUG_NAME_COUNTERS != null;
449 }
450
451 static void associateWithDebugName(LambdaForm form, String name) {
452 assert (debugNames());
453 synchronized (DEBUG_NAMES) {
454 DEBUG_NAMES.put(form, name);
455 }
456 }
457
458 String lambdaName() {
459 if (DEBUG_NAMES != null) {
460 synchronized (DEBUG_NAMES) {
461 String name = DEBUG_NAMES.get(this);
462 if (name == null) {
463 name = generateDebugName();
464 }
465 return name;
466 }
467 }
468 return kind.defaultLambdaName;
469 }
470
471 private String generateDebugName() {
472 assert (debugNames());
473 String debugNameStem = kind.defaultLambdaName;
474 Integer ctr = DEBUG_NAME_COUNTERS.getOrDefault(debugNameStem, 0);
475 DEBUG_NAME_COUNTERS.put(debugNameStem, ctr + 1);
476 StringBuilder buf = new StringBuilder(debugNameStem);
477 int leadingZero = buf.length();
478 buf.append((int) ctr);
479 for (int i = buf.length() - leadingZero; i < 3; i++) {
480 buf.insert(leadingZero, '0');
481 }
482 buf.append('_');
483 buf.append(basicTypeSignature());
484 String name = buf.toString();
485 associateWithDebugName(this, name);
486 return name;
487 }
488
489 private static boolean namesOK(int arity, Name[] names) {
490 for (int i = 0; i < names.length; i++) {
491 Name n = names[i];
492 assert(n != null) : "n is null";
493 if (i < arity)
494 assert( n.isParam()) : n + " is not param at " + i;
495 else
496 assert(!n.isParam()) : n + " is param at " + i;
497 }
498 return true;
499 }
500
501
502 LambdaForm customize(MethodHandle mh) {
503 LambdaForm customForm = new LambdaForm(arity, names, result, forceInline, mh, kind);
504 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
505
506 customForm.compileToBytecode();
507 }
508 customForm.transformCache = this;
509 return customForm;
510 }
511
512
513 LambdaForm uncustomize() {
514 if (customized == null) {
515 return this;
516 }
517 assert(transformCache != null);
518 LambdaForm uncustomizedForm = (LambdaForm)transformCache;
519 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
520
521 uncustomizedForm.compileToBytecode();
522 }
523 return uncustomizedForm;
524 }
525
526
529 private int normalize() {
530 Name[] oldNames = null;
531 int maxOutArity = 0;
532 int changesStart = 0;
533 for (int i = 0; i < names.length; i++) {
534 Name n = names[i];
535 if (!n.initIndex(i)) {
536 if (oldNames == null) {
537 oldNames = names.clone();
538 changesStart = i;
539 }
540 names[i] = n.cloneWithIndex(i);
541 }
542 if (n.arguments != null && maxOutArity < n.arguments.length)
543 maxOutArity = n.arguments.length;
544 }
545 if (oldNames != null) {
546 int startFixing = arity;
547 if (startFixing <= changesStart)
548 startFixing = changesStart+1;
549 for (int i = startFixing; i < names.length; i++) {
550 Name fixed = names[i].replaceNames(oldNames, names, changesStart, i);
551 names[i] = fixed.newIndex(i);
552 }
553 }
554 assert(nameRefsAreLegal());
555 int maxInterned = Math.min(arity, INTERNED_ARGUMENT_LIMIT);
556 boolean needIntern = false;
557 for (int i = 0; i < maxInterned; i++) {
558 Name n = names[i], n2 = internArgument(n);
559 if (n != n2) {
560 names[i] = n2;
561 needIntern = true;
562 }
563 }
564 if (needIntern) {
565 for (int i = arity; i < names.length; i++) {
566 names[i].internArguments();
567 }
568 }
569 assert(nameRefsAreLegal());
570 return maxOutArity;
571 }
572
573
582 boolean nameRefsAreLegal() {
583 assert(arity >= 0 && arity <= names.length);
584 assert(result >= -1 && result < names.length);
585
586 for (int i = 0; i < arity; i++) {
587 Name n = names[i];
588 assert(n.index() == i) : Arrays.asList(n.index(), i);
589 assert(n.isParam());
590 }
591
592 for (int i = arity; i < names.length; i++) {
593 Name n = names[i];
594 assert(n.index() == i);
595 for (Object arg : n.arguments) {
596 if (arg instanceof Name) {
597 Name n2 = (Name) arg;
598 int i2 = n2.index;
599 assert(0 <= i2 && i2 < names.length) : n.debugString() + ": 0 <= i2 && i2 < names.length: 0 <= " + i2 + " < " + names.length;
600 assert(names[i2] == n2) : Arrays.asList("-1-", i, "-2-", n.debugString(), "-3-", i2, "-4-", n2.debugString(), "-5-", names[i2].debugString(), "-6-", this);
601 assert(i2 < i);
602 }
603 }
604 }
605 return true;
606 }
607
608
609
610
611
612
613
614
615 BasicType returnType() {
616 if (result < 0) return V_TYPE;
617 Name n = names[result];
618 return n.type;
619 }
620
621
622 BasicType parameterType(int n) {
623 return parameter(n).type;
624 }
625
626
627 Name parameter(int n) {
628 assert(n < arity);
629 Name param = names[n];
630 assert(param.isParam());
631 return param;
632 }
633
634
635 Object parameterConstraint(int n) {
636 return parameter(n).constraint;
637 }
638
639
640 int arity() {
641 return arity;
642 }
643
644
645 int expressionCount() {
646 return names.length - arity;
647 }
648
649
650 MethodType methodType() {
651 Class<?>[] ptypes = new Class<?>[arity];
652 for (int i = 0; i < arity; ++i) {
653 ptypes[i] = parameterType(i).btClass;
654 }
655 return MethodType.makeImpl(returnType().btClass, ptypes, true);
656 }
657
658
659 final String basicTypeSignature() {
660 StringBuilder buf = new StringBuilder(arity() + 3);
661 for (int i = 0, a = arity(); i < a; i++)
662 buf.append(parameterType(i).basicTypeChar());
663 return buf.append('_').append(returnType().basicTypeChar()).toString();
664 }
665 static int signatureArity(String sig) {
666 assert(isValidSignature(sig));
667 return sig.indexOf('_');
668 }
669 static BasicType signatureReturn(String sig) {
670 return basicType(sig.charAt(signatureArity(sig) + 1));
671 }
672 static boolean isValidSignature(String sig) {
673 int arity = sig.indexOf('_');
674 if (arity < 0) return false;
675 int siglen = sig.length();
676 if (siglen != arity + 2) return false;
677 for (int i = 0; i < siglen; i++) {
678 if (i == arity) continue;
679 char c = sig.charAt(i);
680 if (c == 'V')
681 return (i == siglen - 1 && arity == siglen - 2);
682 if (!isArgBasicTypeChar(c)) return false;
683 }
684 return true;
685 }
686 static MethodType signatureType(String sig) {
687 Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
688 for (int i = 0; i < ptypes.length; i++)
689 ptypes[i] = basicType(sig.charAt(i)).btClass;
690 Class<?> rtype = signatureReturn(sig).btClass;
691 return MethodType.makeImpl(rtype, ptypes, true);
692 }
693 static MethodType basicMethodType(MethodType mt) {
694 return signatureType(basicTypeSignature(mt));
695 }
696
697
700 boolean isSelectAlternative(int pos) {
701
702
703
704 if (pos+1 >= names.length) return false;
705 Name name0 = names[pos];
706 Name name1 = names[pos+1];
707 return name0.refersTo(MethodHandleImpl.class, "selectAlternative") &&
708 name1.isInvokeBasic() &&
709 name1.lastUseIndex(name0) == 0 &&
710 lastUseIndex(name0) == pos+1;
711 }
712
713 private boolean isMatchingIdiom(int pos, String idiomName, int nArgs) {
714 if (pos+2 >= names.length) return false;
715 Name name0 = names[pos];
716 Name name1 = names[pos+1];
717 Name name2 = names[pos+2];
718 return name1.refersTo(MethodHandleImpl.class, idiomName) &&
719 name0.isInvokeBasic() &&
720 name2.isInvokeBasic() &&
721 name1.lastUseIndex(name0) == nArgs &&
722 lastUseIndex(name0) == pos+1 &&
723 name2.lastUseIndex(name1) == 1 &&
724 lastUseIndex(name1) == pos+2;
725 }
726
727
730 boolean isGuardWithCatch(int pos) {
731
732
733
734
735 return isMatchingIdiom(pos, "guardWithCatch", 3);
736 }
737
738
741 boolean isTryFinally(int pos) {
742
743
744
745
746 return isMatchingIdiom(pos, "tryFinally", 2);
747 }
748
749
752 boolean isLoop(int pos) {
753
754
755
756
757 return isMatchingIdiom(pos, "loop", 2);
758 }
759
760
819
820
827 public void prepare() {
828 if (COMPILE_THRESHOLD == 0 && !forceInterpretation() && !isCompiled) {
829 compileToBytecode();
830 }
831 if (this.vmentry != null) {
832
833 return;
834 }
835 MethodType mtype = methodType();
836 LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET);
837 if (prep == null) {
838 assert (isValidSignature(basicTypeSignature()));
839 prep = new LambdaForm(mtype);
840 prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(mtype);
841 prep = mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep);
842 }
843 this.vmentry = prep.vmentry;
844
845 }
846
847 private static @Stable PerfCounter LF_FAILED;
848
849 private static PerfCounter failedCompilationCounter() {
850 if (LF_FAILED == null) {
851 LF_FAILED = PerfCounter.newPerfCounter("java.lang.invoke.failedLambdaFormCompilations");
852 }
853 return LF_FAILED;
854 }
855
856
857 void compileToBytecode() {
858 if (forceInterpretation()) {
859 return;
860 }
861 if (vmentry != null && isCompiled) {
862 return;
863 }
864
865
866
867
868 MethodType invokerType = methodType();
869 assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
870 try {
871 vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
872 if (TRACE_INTERPRETER)
873 traceInterpreter("compileToBytecode", this);
874 isCompiled = true;
875 } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
876
877 invocationCounter = -1;
878 failedCompilationCounter().increment();
879 if (LOG_LF_COMPILATION_FAILURE) {
880 System.out.println("LambdaForm compilation failed: " + this);
881 bge.printStackTrace(System.out);
882 }
883 } catch (Error e) {
884
885 throw e;
886 } catch (Exception e) {
887
888 throw newInternalError(this.toString(), e);
889 }
890 }
891
892
893
894 private static boolean argumentTypesMatch(String sig, Object[] av) {
895 int arity = signatureArity(sig);
896 assert(av.length == arity) : "av.length == arity: av.length=" + av.length + ", arity=" + arity;
897 assert(av[0] instanceof MethodHandle) : "av[0] not instace of MethodHandle: " + av[0];
898 MethodHandle mh = (MethodHandle) av[0];
899 MethodType mt = mh.type();
900 assert(mt.parameterCount() == arity-1);
901 for (int i = 0; i < av.length; i++) {
902 Class<?> pt = (i == 0 ? MethodHandle.class : mt.parameterType(i-1));
903 assert(valueMatches(basicType(sig.charAt(i)), pt, av[i]));
904 }
905 return true;
906 }
907 private static boolean valueMatches(BasicType tc, Class<?> type, Object x) {
908
909 if (type == void.class) tc = V_TYPE;
910 assert tc == basicType(type) : tc + " == basicType(" + type + ")=" + basicType(type);
911 switch (tc) {
912 case I_TYPE: assert checkInt(type, x) : "checkInt(" + type + "," + x +")"; break;
913 case J_TYPE: assert x instanceof Long : "instanceof Long: " + x; break;
914 case F_TYPE: assert x instanceof Float : "instanceof Float: " + x; break;
915 case D_TYPE: assert x instanceof Double : "instanceof Double: " + x; break;
916 case L_TYPE: assert checkRef(type, x) : "checkRef(" + type + "," + x + ")"; break;
917 case V_TYPE: break;
918 default: assert(false);
919 }
920 return true;
921 }
922 private static boolean checkInt(Class<?> type, Object x) {
923 assert(x instanceof Integer);
924 if (type == int.class) return true;
925 Wrapper w = Wrapper.forBasicType(type);
926 assert(w.isSubwordOrInt());
927 Object x1 = Wrapper.INT.wrap(w.wrap(x));
928 return x.equals(x1);
929 }
930 private static boolean checkRef(Class<?> type, Object x) {
931 assert(!type.isPrimitive());
932 if (x == null) return true;
933 if (type.isInterface()) return true;
934 return type.isInstance(x);
935 }
936
937
938 private static final int COMPILE_THRESHOLD;
939 static {
940 COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD);
941 }
942 private int invocationCounter = 0;
943
944 private boolean forceInterpretation() {
945 return invocationCounter == -1;
946 }
947
948 @Hidden
949 @DontInline
950
951 Object interpretWithArguments(Object... argumentValues) throws Throwable {
952 if (TRACE_INTERPRETER)
953 return interpretWithArgumentsTracing(argumentValues);
954 checkInvocationCounter();
955 assert(arityCheck(argumentValues));
956 Object[] values = Arrays.copyOf(argumentValues, names.length);
957 for (int i = argumentValues.length; i < values.length; i++) {
958 values[i] = interpretName(names[i], values);
959 }
960 Object rv = (result < 0) ? null : values[result];
961 assert(resultCheck(argumentValues, rv));
962 return rv;
963 }
964
965 @Hidden
966 @DontInline
967
968 Object interpretName(Name name, Object[] values) throws Throwable {
969 if (TRACE_INTERPRETER)
970 traceInterpreter("| interpretName", name.debugString(), (Object[]) null);
971 Object[] arguments = Arrays.copyOf(name.arguments, name.arguments.length, Object[].class);
972 for (int i = 0; i < arguments.length; i++) {
973 Object a = arguments[i];
974 if (a instanceof Name) {
975 int i2 = ((Name)a).index();
976 assert(names[i2] == a);
977 a = values[i2];
978 arguments[i] = a;
979 }
980 }
981 return name.function.invokeWithArguments(arguments);
982 }
983
984 private void checkInvocationCounter() {
985 if (COMPILE_THRESHOLD != 0 &&
986 !forceInterpretation() && invocationCounter < COMPILE_THRESHOLD) {
987 invocationCounter++;
988 if (invocationCounter >= COMPILE_THRESHOLD) {
989
990 compileToBytecode();
991 }
992 }
993 }
994 Object interpretWithArgumentsTracing(Object... argumentValues) throws Throwable {
995 traceInterpreter("[ interpretWithArguments", this, argumentValues);
996 if (!forceInterpretation() && invocationCounter < COMPILE_THRESHOLD) {
997 int ctr = invocationCounter++;
998 traceInterpreter("| invocationCounter", ctr);
999 if (invocationCounter >= COMPILE_THRESHOLD) {
1000 compileToBytecode();
1001 }
1002 }
1003 Object rval;
1004 try {
1005 assert(arityCheck(argumentValues));
1006 Object[] values = Arrays.copyOf(argumentValues, names.length);
1007 for (int i = argumentValues.length; i < values.length; i++) {
1008 values[i] = interpretName(names[i], values);
1009 }
1010 rval = (result < 0) ? null : values[result];
1011 } catch (Throwable ex) {
1012 traceInterpreter("] throw =>", ex);
1013 throw ex;
1014 }
1015 traceInterpreter("] return =>", rval);
1016 return rval;
1017 }
1018
1019 static void traceInterpreter(String event, Object obj, Object... args) {
1020 if (TRACE_INTERPRETER) {
1021 System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : ""));
1022 }
1023 }
1024 static void traceInterpreter(String event, Object obj) {
1025 traceInterpreter(event, obj, (Object[])null);
1026 }
1027 private boolean arityCheck(Object[] argumentValues) {
1028 assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length";
1029
1030 assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0];
1031 MethodHandle mh = (MethodHandle) argumentValues[0];
1032 assert(mh.internalForm() == this);
1033
1034 argumentTypesMatch(basicTypeSignature(), argumentValues);
1035 return true;
1036 }
1037 private boolean resultCheck(Object[] argumentValues, Object result) {
1038 MethodHandle mh = (MethodHandle) argumentValues[0];
1039 MethodType mt = mh.type();
1040 assert(valueMatches(returnType(), mt.returnType(), result));
1041 return true;
1042 }
1043
1044 private boolean isEmpty() {
1045 if (result < 0)
1046 return (names.length == arity);
1047 else if (result == arity && names.length == arity + 1)
1048 return names[arity].isConstantZero();
1049 else
1050 return false;
1051 }
1052
1053 public String toString() {
1054 String lambdaName = lambdaName();
1055 StringBuilder buf = new StringBuilder(lambdaName + "=Lambda(");
1056 for (int i = 0; i < names.length; i++) {
1057 if (i == arity) buf.append(")=>{");
1058 Name n = names[i];
1059 if (i >= arity) buf.append("\n ");
1060 buf.append(n.paramString());
1061 if (i < arity) {
1062 if (i+1 < arity) buf.append(",");
1063 continue;
1064 }
1065 buf.append("=").append(n.exprString());
1066 buf.append(";");
1067 }
1068 if (arity == names.length) buf.append(")=>{");
1069 buf.append(result < 0 ? "void" : names[result]).append("}");
1070 if (TRACE_INTERPRETER) {
1071
1072 buf.append(":").append(basicTypeSignature());
1073 buf.append("/").append(vmentry);
1074 }
1075 return buf.toString();
1076 }
1077
1078 @Override
1079 public boolean equals(Object obj) {
1080 return obj instanceof LambdaForm && equals((LambdaForm)obj);
1081 }
1082 public boolean equals(LambdaForm that) {
1083 if (this.result != that.result) return false;
1084 return Arrays.equals(this.names, that.names);
1085 }
1086 public int hashCode() {
1087 return result + 31 * Arrays.hashCode(names);
1088 }
1089 LambdaFormEditor editor() {
1090 return LambdaFormEditor.lambdaFormEditor(this);
1091 }
1092
1093 boolean contains(Name name) {
1094 int pos = name.index();
1095 if (pos >= 0) {
1096 return pos < names.length && name.equals(names[pos]);
1097 }
1098 for (int i = arity; i < names.length; i++) {
1099 if (name.equals(names[i]))
1100 return true;
1101 }
1102 return false;
1103 }
1104
1105 static class NamedFunction {
1106 final MemberName member;
1107 private @Stable MethodHandle resolvedHandle;
1108 @Stable MethodHandle invoker;
1109 private final MethodHandleImpl.Intrinsic intrinsicName;
1110
1111 NamedFunction(MethodHandle resolvedHandle) {
1112 this(resolvedHandle.internalMemberName(), resolvedHandle, MethodHandleImpl.Intrinsic.NONE);
1113 }
1114 NamedFunction(MethodHandle resolvedHandle, MethodHandleImpl.Intrinsic intrinsic) {
1115 this(resolvedHandle.internalMemberName(), resolvedHandle, intrinsic);
1116 }
1117 NamedFunction(MemberName member, MethodHandle resolvedHandle) {
1118 this(member, resolvedHandle, MethodHandleImpl.Intrinsic.NONE);
1119 }
1120 NamedFunction(MemberName member, MethodHandle resolvedHandle, MethodHandleImpl.Intrinsic intrinsic) {
1121 this.member = member;
1122 this.resolvedHandle = resolvedHandle;
1123 this.intrinsicName = intrinsic;
1124 assert(resolvedHandle == null ||
1125 resolvedHandle.intrinsicName() == MethodHandleImpl.Intrinsic.NONE ||
1126 resolvedHandle.intrinsicName() == intrinsic) : resolvedHandle.intrinsicName() + " != " + intrinsic;
1127
1128
1129 }
1130 NamedFunction(MethodType basicInvokerType) {
1131 assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType;
1132 if (basicInvokerType.parameterSlotCount() < MethodType.MAX_MH_INVOKER_ARITY) {
1133 this.resolvedHandle = basicInvokerType.invokers().basicInvoker();
1134 this.member = resolvedHandle.internalMemberName();
1135 } else {
1136
1137 this.member = Invokers.invokeBasicMethod(basicInvokerType);
1138 }
1139 this.intrinsicName = MethodHandleImpl.Intrinsic.NONE;
1140 assert(isInvokeBasic(member));
1141 }
1142
1143 private static boolean isInvokeBasic(MemberName member) {
1144 return member != null &&
1145 member.getDeclaringClass() == MethodHandle.class &&
1146 "invokeBasic".equals(member.getName());
1147 }
1148
1149
1150
1151
1152
1153 NamedFunction(Method method) {
1154 this(new MemberName(method));
1155 }
1156 NamedFunction(MemberName member) {
1157 this(member, null);
1158 }
1159
1160 MethodHandle resolvedHandle() {
1161 if (resolvedHandle == null) resolve();
1162 return resolvedHandle;
1163 }
1164
1165 synchronized void resolve() {
1166 if (resolvedHandle == null) {
1167 resolvedHandle = DirectMethodHandle.make(member);
1168 }
1169 }
1170
1171 @Override
1172 public boolean equals(Object other) {
1173 if (this == other) return true;
1174 if (other == null) return false;
1175 if (!(other instanceof NamedFunction)) return false;
1176 NamedFunction that = (NamedFunction) other;
1177 return this.member != null && this.member.equals(that.member);
1178 }
1179
1180 @Override
1181 public int hashCode() {
1182 if (member != null)
1183 return member.hashCode();
1184 return super.hashCode();
1185 }
1186
1187 static final MethodType INVOKER_METHOD_TYPE =
1188 MethodType.methodType(Object.class, MethodHandle.class, Object[].class);
1189
1190 private static MethodHandle computeInvoker(MethodTypeForm typeForm) {
1191 typeForm = typeForm.basicType().form();
1192 MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV);
1193 if (mh != null) return mh;
1194 MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm);
1195 mh = DirectMethodHandle.make(invoker);
1196 MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV);
1197 if (mh2 != null) return mh2;
1198 if (!mh.type().equals(INVOKER_METHOD_TYPE))
1199 throw newInternalError(mh.debugString());
1200 return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh);
1201 }
1202
1203 @Hidden
1204 Object invokeWithArguments(Object... arguments) throws Throwable {
1205
1206
1207 if (TRACE_INTERPRETER) return invokeWithArgumentsTracing(arguments);
1208 return invoker().invokeBasic(resolvedHandle(), arguments);
1209 }
1210
1211 @Hidden
1212 Object invokeWithArgumentsTracing(Object[] arguments) throws Throwable {
1213 Object rval;
1214 try {
1215 traceInterpreter("[ call", this, arguments);
1216 if (invoker == null) {
1217 traceInterpreter("| getInvoker", this);
1218 invoker();
1219 }
1220
1221 if (resolvedHandle == null) {
1222 traceInterpreter("| resolve", this);
1223 resolvedHandle();
1224 }
1225 rval = invoker().invokeBasic(resolvedHandle(), arguments);
1226 } catch (Throwable ex) {
1227 traceInterpreter("] throw =>", ex);
1228 throw ex;
1229 }
1230 traceInterpreter("] return =>", rval);
1231 return rval;
1232 }
1233
1234 private MethodHandle invoker() {
1235 if (invoker != null) return invoker;
1236
1237 return invoker = computeInvoker(methodType().form());
1238 }
1239
1240 MethodType methodType() {
1241 if (resolvedHandle != null)
1242 return resolvedHandle.type();
1243 else
1244
1245 return member.getInvocationType();
1246 }
1247
1248 MemberName member() {
1249 assert(assertMemberIsConsistent());
1250 return member;
1251 }
1252
1253
1254 private boolean assertMemberIsConsistent() {
1255 if (resolvedHandle instanceof DirectMethodHandle) {
1256 MemberName m = resolvedHandle.internalMemberName();
1257 assert(m.equals(member));
1258 }
1259 return true;
1260 }
1261
1262 Class<?> memberDeclaringClassOrNull() {
1263 return (member == null) ? null : member.getDeclaringClass();
1264 }
1265
1266 BasicType returnType() {
1267 return basicType(methodType().returnType());
1268 }
1269
1270 BasicType parameterType(int n) {
1271 return basicType(methodType().parameterType(n));
1272 }
1273
1274 int arity() {
1275 return methodType().parameterCount();
1276 }
1277
1278 public String toString() {
1279 if (member == null) return String.valueOf(resolvedHandle);
1280 return member.getDeclaringClass().getSimpleName()+"."+member.getName();
1281 }
1282
1283 public boolean isIdentity() {
1284 return this.equals(identity(returnType()));
1285 }
1286
1287 public boolean isConstantZero() {
1288 return this.equals(constantZero(returnType()));
1289 }
1290
1291 public MethodHandleImpl.Intrinsic intrinsicName() {
1292 return intrinsicName;
1293 }
1294 }
1295
1296 public static String basicTypeSignature(MethodType type) {
1297 int params = type.parameterCount();
1298 char[] sig = new char[params + 2];
1299 int sigp = 0;
1300 while (sigp < params) {
1301 sig[sigp] = basicTypeChar(type.parameterType(sigp++));
1302 }
1303 sig[sigp++] = '_';
1304 sig[sigp++] = basicTypeChar(type.returnType());
1305 assert(sigp == sig.length);
1306 return String.valueOf(sig);
1307 }
1308
1309
1316 public static String shortenSignature(String signature) {
1317 final int NO_CHAR = -1, MIN_RUN = 3;
1318 int c0, c1 = NO_CHAR, c1reps = 0;
1319 StringBuilder buf = null;
1320 int len = signature.length();
1321 if (len < MIN_RUN) return signature;
1322 for (int i = 0; i <= len; i++) {
1323 if (c1 != NO_CHAR && !('A' <= c1 && c1 <= 'Z')) {
1324
1325 if (buf != null) {
1326 buf.append(signature.substring(i - c1reps, len));
1327 }
1328 break;
1329 }
1330
1331 c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i));
1332 if (c1 == c0) { ++c1reps; continue; }
1333
1334 int c0reps = c1reps; c1reps = 1;
1335
1336 if (c0reps < MIN_RUN) {
1337 if (buf != null) {
1338 while (--c0reps >= 0)
1339 buf.append((char)c0);
1340 }
1341 continue;
1342 }
1343
1344 if (buf == null)
1345 buf = new StringBuilder().append(signature, 0, i - c0reps);
1346 buf.append((char)c0).append(c0reps);
1347 }
1348 return (buf == null) ? signature : buf.toString();
1349 }
1350
1351 static final class Name {
1352 final BasicType type;
1353 @Stable short index;
1354 final NamedFunction function;
1355 final Object constraint;
1356 @Stable final Object[] arguments;
1357
1358 private Name(int index, BasicType type, NamedFunction function, Object[] arguments) {
1359 this.index = (short)index;
1360 this.type = type;
1361 this.function = function;
1362 this.arguments = arguments;
1363 this.constraint = null;
1364 assert(this.index == index);
1365 }
1366 private Name(Name that, Object constraint) {
1367 this.index = that.index;
1368 this.type = that.type;
1369 this.function = that.function;
1370 this.arguments = that.arguments;
1371 this.constraint = constraint;
1372 assert(constraint == null || isParam());
1373 assert(constraint == null || constraint instanceof ClassSpecializer.SpeciesData || constraint instanceof Class);
1374 }
1375 Name(MethodHandle function, Object... arguments) {
1376 this(new NamedFunction(function), arguments);
1377 }
1378 Name(MethodType functionType, Object... arguments) {
1379 this(new NamedFunction(functionType), arguments);
1380 assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == L_TYPE);
1381 }
1382 Name(MemberName function, Object... arguments) {
1383 this(new NamedFunction(function), arguments);
1384 }
1385 Name(NamedFunction function, Object... arguments) {
1386 this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class));
1387 assert(typesMatch(function, arguments));
1388 }
1389
1390 Name(int index, BasicType type) {
1391 this(index, type, null, null);
1392 }
1393
1394 Name(BasicType type) { this(-1, type); }
1395
1396 BasicType type() { return type; }
1397 int index() { return index; }
1398 boolean initIndex(int i) {
1399 if (index != i) {
1400 if (index != -1) return false;
1401 index = (short)i;
1402 }
1403 return true;
1404 }
1405 char typeChar() {
1406 return type.btChar;
1407 }
1408
1409 void resolve() {
1410 if (function != null)
1411 function.resolve();
1412 }
1413
1414 Name newIndex(int i) {
1415 if (initIndex(i)) return this;
1416 return cloneWithIndex(i);
1417 }
1418 Name cloneWithIndex(int i) {
1419 Object[] newArguments = (arguments == null) ? null : arguments.clone();
1420 return new Name(i, type, function, newArguments).withConstraint(constraint);
1421 }
1422 Name withConstraint(Object constraint) {
1423 if (constraint == this.constraint) return this;
1424 return new Name(this, constraint);
1425 }
1426 Name replaceName(Name oldName, Name newName) {
1427 if (oldName == newName) return this;
1428 @SuppressWarnings("LocalVariableHidesMemberVariable")
1429 Object[] arguments = this.arguments;
1430 if (arguments == null) return this;
1431 boolean replaced = false;
1432 for (int j = 0; j < arguments.length; j++) {
1433 if (arguments[j] == oldName) {
1434 if (!replaced) {
1435 replaced = true;
1436 arguments = arguments.clone();
1437 }
1438 arguments[j] = newName;
1439 }
1440 }
1441 if (!replaced) return this;
1442 return new Name(function, arguments);
1443 }
1444
1447 Name replaceNames(Name[] oldNames, Name[] newNames, int start, int end) {
1448 if (start >= end) return this;
1449 @SuppressWarnings("LocalVariableHidesMemberVariable")
1450 Object[] arguments = this.arguments;
1451 boolean replaced = false;
1452 eachArg:
1453 for (int j = 0; j < arguments.length; j++) {
1454 if (arguments[j] instanceof Name) {
1455 Name n = (Name) arguments[j];
1456 int check = n.index;
1457
1458 if (check >= 0 && check < newNames.length && n == newNames[check])
1459 continue eachArg;
1460
1461 for (int i = start; i < end; i++) {
1462 if (n == oldNames[i]) {
1463 if (n == newNames[i])
1464 continue eachArg;
1465 if (!replaced) {
1466 replaced = true;
1467 arguments = arguments.clone();
1468 }
1469 arguments[j] = newNames[i];
1470 continue eachArg;
1471 }
1472 }
1473 }
1474 }
1475 if (!replaced) return this;
1476 return new Name(function, arguments);
1477 }
1478 void internArguments() {
1479 @SuppressWarnings("LocalVariableHidesMemberVariable")
1480 Object[] arguments = this.arguments;
1481 for (int j = 0; j < arguments.length; j++) {
1482 if (arguments[j] instanceof Name) {
1483 Name n = (Name) arguments[j];
1484 if (n.isParam() && n.index < INTERNED_ARGUMENT_LIMIT)
1485 arguments[j] = internArgument(n);
1486 }
1487 }
1488 }
1489 boolean isParam() {
1490 return function == null;
1491 }
1492 boolean isConstantZero() {
1493 return !isParam() && arguments.length == 0 && function.isConstantZero();
1494 }
1495
1496 boolean refersTo(Class<?> declaringClass, String methodName) {
1497 return function != null &&
1498 function.member() != null && function.member().refersTo(declaringClass, methodName);
1499 }
1500
1501
1504 boolean isInvokeBasic() {
1505 if (function == null)
1506 return false;
1507 if (arguments.length < 1)
1508 return false;
1509 MemberName member = function.member();
1510 return member != null && member.refersTo(MethodHandle.class, "invokeBasic") &&
1511 !member.isPublic() && !member.isStatic();
1512 }
1513
1514
1517 boolean isLinkerMethodInvoke() {
1518 if (function == null)
1519 return false;
1520 if (arguments.length < 1)
1521 return false;
1522 MemberName member = function.member();
1523 return member != null &&
1524 member.getDeclaringClass() == MethodHandle.class &&
1525 !member.isPublic() && member.isStatic() &&
1526 member.getName().startsWith("linkTo");
1527 }
1528
1529 public String toString() {
1530 return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+typeChar();
1531 }
1532 public String debugString() {
1533 String s = paramString();
1534 return (function == null) ? s : s + "=" + exprString();
1535 }
1536 public String paramString() {
1537 String s = toString();
1538 Object c = constraint;
1539 if (c == null)
1540 return s;
1541 if (c instanceof Class) c = ((Class<?>)c).getSimpleName();
1542 return s + "/" + c;
1543 }
1544 public String exprString() {
1545 if (function == null) return toString();
1546 StringBuilder buf = new StringBuilder(function.toString());
1547 buf.append("(");
1548 String cma = "";
1549 for (Object a : arguments) {
1550 buf.append(cma); cma = ",";
1551 if (a instanceof Name || a instanceof Integer)
1552 buf.append(a);
1553 else
1554 buf.append("(").append(a).append(")");
1555 }
1556 buf.append(")");
1557 return buf.toString();
1558 }
1559
1560 private boolean typesMatch(NamedFunction function, Object ... arguments) {
1561 assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
1562 for (int i = 0; i < arguments.length; i++) {
1563 assert (typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
1564 }
1565 return true;
1566 }
1567
1568 private static boolean typesMatch(BasicType parameterType, Object object) {
1569 if (object instanceof Name) {
1570 return ((Name)object).type == parameterType;
1571 }
1572 switch (parameterType) {
1573 case I_TYPE: return object instanceof Integer;
1574 case J_TYPE: return object instanceof Long;
1575 case F_TYPE: return object instanceof Float;
1576 case D_TYPE: return object instanceof Double;
1577 }
1578 assert(parameterType == L_TYPE);
1579 return true;
1580 }
1581
1582
1585 int lastUseIndex(Name n) {
1586 if (arguments == null) return -1;
1587 for (int i = arguments.length; --i >= 0; ) {
1588 if (arguments[i] == n) return i;
1589 }
1590 return -1;
1591 }
1592
1593
1596 int useCount(Name n) {
1597 if (arguments == null) return 0;
1598 int count = 0;
1599 for (int i = arguments.length; --i >= 0; ) {
1600 if (arguments[i] == n) ++count;
1601 }
1602 return count;
1603 }
1604
1605 boolean contains(Name n) {
1606 return this == n || lastUseIndex(n) >= 0;
1607 }
1608
1609 public boolean equals(Name that) {
1610 if (this == that) return true;
1611 if (isParam())
1612
1613 return false;
1614 return
1615
1616 this.type == that.type &&
1617 this.function.equals(that.function) &&
1618 Arrays.equals(this.arguments, that.arguments);
1619 }
1620 @Override
1621 public boolean equals(Object x) {
1622 return x instanceof Name && equals((Name)x);
1623 }
1624 @Override
1625 public int hashCode() {
1626 if (isParam())
1627 return index | (type.ordinal() << 8);
1628 return function.hashCode() ^ Arrays.hashCode(arguments);
1629 }
1630 }
1631
1632
1635 int lastUseIndex(Name n) {
1636 int ni = n.index, nmax = names.length;
1637 assert(names[ni] == n);
1638 if (result == ni) return nmax;
1639 for (int i = nmax; --i > ni; ) {
1640 if (names[i].lastUseIndex(n) >= 0)
1641 return i;
1642 }
1643 return -1;
1644 }
1645
1646
1647 int useCount(Name n) {
1648 int nmax = names.length;
1649 int end = lastUseIndex(n);
1650 if (end < 0) return 0;
1651 int count = 0;
1652 if (end == nmax) { count++; end--; }
1653 int beg = n.index() + 1;
1654 if (beg < arity) beg = arity;
1655 for (int i = beg; i <= end; i++) {
1656 count += names[i].useCount(n);
1657 }
1658 return count;
1659 }
1660
1661 static Name argument(int which, BasicType type) {
1662 if (which >= INTERNED_ARGUMENT_LIMIT)
1663 return new Name(which, type);
1664 return INTERNED_ARGUMENTS[type.ordinal()][which];
1665 }
1666 static Name internArgument(Name n) {
1667 assert(n.isParam()) : "not param: " + n;
1668 assert(n.index < INTERNED_ARGUMENT_LIMIT);
1669 if (n.constraint != null) return n;
1670 return argument(n.index, n.type);
1671 }
1672 static Name[] arguments(int extra, MethodType types) {
1673 int length = types.parameterCount();
1674 Name[] names = new Name[length + extra];
1675 for (int i = 0; i < length; i++)
1676 names[i] = argument(i, basicType(types.parameterType(i)));
1677 return names;
1678 }
1679 static final int INTERNED_ARGUMENT_LIMIT = 10;
1680 private static final Name[][] INTERNED_ARGUMENTS
1681 = new Name[ARG_TYPE_LIMIT][INTERNED_ARGUMENT_LIMIT];
1682 static {
1683 for (BasicType type : BasicType.ARG_TYPES) {
1684 int ord = type.ordinal();
1685 for (int i = 0; i < INTERNED_ARGUMENTS[ord].length; i++) {
1686 INTERNED_ARGUMENTS[ord][i] = new Name(i, type);
1687 }
1688 }
1689 }
1690
1691 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
1692
1693 static LambdaForm identityForm(BasicType type) {
1694 int ord = type.ordinal();
1695 LambdaForm form = LF_identity[ord];
1696 if (form != null) {
1697 return form;
1698 }
1699 createFormsFor(type);
1700 return LF_identity[ord];
1701 }
1702
1703 static LambdaForm zeroForm(BasicType type) {
1704 int ord = type.ordinal();
1705 LambdaForm form = LF_zero[ord];
1706 if (form != null) {
1707 return form;
1708 }
1709 createFormsFor(type);
1710 return LF_zero[ord];
1711 }
1712
1713 static NamedFunction identity(BasicType type) {
1714 int ord = type.ordinal();
1715 NamedFunction function = NF_identity[ord];
1716 if (function != null) {
1717 return function;
1718 }
1719 createFormsFor(type);
1720 return NF_identity[ord];
1721 }
1722
1723 static NamedFunction constantZero(BasicType type) {
1724 int ord = type.ordinal();
1725 NamedFunction function = NF_zero[ord];
1726 if (function != null) {
1727 return function;
1728 }
1729 createFormsFor(type);
1730 return NF_zero[ord];
1731 }
1732
1733 private static final @Stable LambdaForm[] LF_identity = new LambdaForm[TYPE_LIMIT];
1734 private static final @Stable LambdaForm[] LF_zero = new LambdaForm[TYPE_LIMIT];
1735 private static final @Stable NamedFunction[] NF_identity = new NamedFunction[TYPE_LIMIT];
1736 private static final @Stable NamedFunction[] NF_zero = new NamedFunction[TYPE_LIMIT];
1737
1738 private static final Object createFormsLock = new Object();
1739 private static void createFormsFor(BasicType type) {
1740
1741 UNSAFE.ensureClassInitialized(BoundMethodHandle.class);
1742 synchronized (createFormsLock) {
1743 final int ord = type.ordinal();
1744 LambdaForm idForm = LF_identity[ord];
1745 if (idForm != null) {
1746 return;
1747 }
1748 char btChar = type.basicTypeChar();
1749 boolean isVoid = (type == V_TYPE);
1750 Class<?> btClass = type.btClass;
1751 MethodType zeType = MethodType.methodType(btClass);
1752 MethodType idType = (isVoid) ? zeType : MethodType.methodType(btClass, btClass);
1753
1754
1755
1756
1757 MemberName idMem = new MemberName(LambdaForm.class, "identity_"+btChar, idType, REF_invokeStatic);
1758 MemberName zeMem = null;
1759 try {
1760 idMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, idMem, null, NoSuchMethodException.class);
1761 if (!isVoid) {
1762 zeMem = new MemberName(LambdaForm.class, "zero_"+btChar, zeType, REF_invokeStatic);
1763 zeMem = IMPL_NAMES.resolveOrFail(REF_invokeStatic, zeMem, null, NoSuchMethodException.class);
1764 }
1765 } catch (IllegalAccessException|NoSuchMethodException ex) {
1766 throw newInternalError(ex);
1767 }
1768
1769 NamedFunction idFun;
1770 LambdaForm zeForm;
1771 NamedFunction zeFun;
1772
1773
1774
1775 if (isVoid) {
1776 Name[] idNames = new Name[] { argument(0, L_TYPE) };
1777 idForm = new LambdaForm(1, idNames, VOID_RESULT, Kind.IDENTITY);
1778 idForm.compileToBytecode();
1779 idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm));
1780
1781 zeForm = idForm;
1782 zeFun = idFun;
1783 } else {
1784 Name[] idNames = new Name[] { argument(0, L_TYPE), argument(1, type) };
1785 idForm = new LambdaForm(2, idNames, 1, Kind.IDENTITY);
1786 idForm.compileToBytecode();
1787 idFun = new NamedFunction(idMem, SimpleMethodHandle.make(idMem.getInvocationType(), idForm),
1788 MethodHandleImpl.Intrinsic.IDENTITY);
1789
1790 Object zeValue = Wrapper.forBasicType(btChar).zero();
1791 Name[] zeNames = new Name[] { argument(0, L_TYPE), new Name(idFun, zeValue) };
1792 zeForm = new LambdaForm(1, zeNames, 1, Kind.ZERO);
1793 zeForm.compileToBytecode();
1794 zeFun = new NamedFunction(zeMem, SimpleMethodHandle.make(zeMem.getInvocationType(), zeForm),
1795 MethodHandleImpl.Intrinsic.ZERO);
1796 }
1797
1798 LF_zero[ord] = zeForm;
1799 NF_zero[ord] = zeFun;
1800 LF_identity[ord] = idForm;
1801 NF_identity[ord] = idFun;
1802
1803 assert(idFun.isIdentity());
1804 assert(zeFun.isConstantZero());
1805 assert(new Name(zeFun).isConstantZero());
1806 }
1807 }
1808
1809
1810 private static int identity_I(int x) { return x; }
1811 private static long identity_J(long x) { return x; }
1812 private static float identity_F(float x) { return x; }
1813 private static double identity_D(double x) { return x; }
1814 private static Object identity_L(Object x) { return x; }
1815 private static void identity_V() { return; }
1816 private static int zero_I() { return 0; }
1817 private static long zero_J() { return 0; }
1818 private static float zero_F() { return 0; }
1819 private static double zero_D() { return 0; }
1820 private static Object zero_L() { return null; }
1821
1822
1825
1826 @Target(ElementType.METHOD)
1827 @Retention(RetentionPolicy.RUNTIME)
1828 @interface Compiled {
1829 }
1830
1831
1834
1835 @Target(ElementType.METHOD)
1836 @Retention(RetentionPolicy.RUNTIME)
1837 @interface Hidden {
1838 }
1839
1840 private static final HashMap<String,Integer> DEBUG_NAME_COUNTERS;
1841 private static final HashMap<LambdaForm,String> DEBUG_NAMES;
1842 static {
1843 if (debugEnabled()) {
1844 DEBUG_NAME_COUNTERS = new HashMap<>();
1845 DEBUG_NAMES = new HashMap<>();
1846 } else {
1847 DEBUG_NAME_COUNTERS = null;
1848 DEBUG_NAMES = null;
1849 }
1850 }
1851
1852 static {
1853
1854
1855
1856
1857 UNSAFE.ensureClassInitialized(Holder.class);
1858 }
1859
1860
1861 final class Holder {}
1862
1863
1864
1865
1866
1867
1868
1869 private static final boolean TRACE_INTERPRETER = MethodHandleStatics.TRACE_INTERPRETER;
1870 }
1871