src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 10755 : 8059877: GWT branch frequencies pollution due to LF sharing
Reviewed-by: ?


 690         LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
 691         return SimpleMethodHandle.make(srcType, form);
 692     }
 693 
 694     @LambdaForm.Hidden
 695     static
 696     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
 697         return testResult ? target : fallback;
 698     }
 699 
 700     static
 701     MethodHandle makeGuardWithTest(MethodHandle test,
 702                                    MethodHandle target,
 703                                    MethodHandle fallback) {
 704         MethodType type = target.type();
 705         assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
 706         MethodType basicType = type.basicType();
 707         LambdaForm form = makeGuardWithTestForm(basicType);
 708         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
 709         BoundMethodHandle mh;

 710         try {
 711             mh = (BoundMethodHandle)
 712                     data.constructor().invokeBasic(type, form,
 713                         (Object) test, (Object) target, (Object) fallback);
 714         } catch (Throwable ex) {
 715             throw uncaughtException(ex);
 716         }
 717         assert(mh.type() == type);
 718         return mh;
 719     }
 720 





















































































 721     static
 722     LambdaForm makeGuardWithTestForm(MethodType basicType) {
 723         LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
 724         if (lform != null)  return lform;
 725         final int THIS_MH      = 0;  // the BMH_LLL
 726         final int ARG_BASE     = 1;  // start of incoming arguments
 727         final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
 728         int nameCursor = ARG_LIMIT;
 729         final int GET_TEST     = nameCursor++;
 730         final int GET_TARGET   = nameCursor++;
 731         final int GET_FALLBACK = nameCursor++;
 732         final int CALL_TEST    = nameCursor++;
 733         final int SELECT_ALT   = nameCursor++;
 734         final int CALL_TARGET  = nameCursor++;
 735         assert(CALL_TARGET == SELECT_ALT+1);  // must be true to trigger IBG.emitSelectAlternative
 736 
 737         MethodType lambdaType = basicType.invokerType();
 738         Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 739 
 740         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();




 690         LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
 691         return SimpleMethodHandle.make(srcType, form);
 692     }
 693 
 694     @LambdaForm.Hidden
 695     static
 696     MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
 697         return testResult ? target : fallback;
 698     }
 699 
 700     static
 701     MethodHandle makeGuardWithTest(MethodHandle test,
 702                                    MethodHandle target,
 703                                    MethodHandle fallback) {
 704         MethodType type = target.type();
 705         assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type));
 706         MethodType basicType = type.basicType();
 707         LambdaForm form = makeGuardWithTestForm(basicType);
 708         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();
 709         BoundMethodHandle mh;
 710 
 711         try {
 712             mh = (BoundMethodHandle)
 713                     data.constructor().invokeBasic(type, form,
 714                         (Object) test, (Object) profile(target), (Object) profile(fallback));
 715         } catch (Throwable ex) {
 716             throw uncaughtException(ex);
 717         }
 718         assert(mh.type() == type);
 719         return mh;
 720     }
 721 
 722 
 723     static
 724     MethodHandle profile(MethodHandle target) {
 725         if (DONT_INLINE_THRESHOLD > 0) {
 726             return BlockInliningWrapper.make(target);
 727         } else {
 728             return target;
 729         }
 730     }
 731 
 732     /**
 733      * Block inlining during JIT-compilation of a target method handle if it hasn't been invoked enough times.
 734      * Corresponding LambdaForm has @DontInline when compiled into bytecode.
 735      */
 736     static class BlockInliningWrapper extends DelegatingMethodHandle {
 737         private final MethodHandle target;
 738         private int count;
 739         private volatile boolean isActivated = true;
 740 
 741         private BlockInliningWrapper(MethodHandle target, LambdaForm lform, int count) {
 742             super(target.type(), lform);
 743             this.target = target;
 744             this.count = count;
 745         }
 746 
 747         @Hidden
 748         @Override
 749         protected MethodHandle getTarget() {
 750             return target;
 751         }
 752 
 753         @Override
 754         public MethodHandle asTypeUncached(MethodType newType) {
 755             MethodHandle newTarget = target.asType(newType);
 756             return asTypeCache = isActivated ? make(newTarget)
 757                                              : newTarget; // no need for a wrapper anymore
 758         }
 759 
 760         boolean unblock() {
 761             if (count <= 0) {
 762                 // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
 763                 if (isActivated) {
 764                     isActivated = false;
 765                     return true;
 766                 } else {
 767                     return false;
 768                 }
 769             } else {
 770                 --count;
 771                 return false;
 772             }
 773         }
 774 
 775         static MethodHandle make(MethodHandle target) {
 776             LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(target,
 777                     MethodTypeForm.LF_DELEGATE_COUNTING, BlockInliningWrapper.class, "reinvoker.dontInline", false,
 778                     DelegatingMethodHandle.NF_getTarget, NF_maybeUnblock);
 779             MethodHandle wrapper = new BlockInliningWrapper(target, lform, DONT_INLINE_THRESHOLD);
 780             return wrapper;
 781         }
 782 
 783         @Hidden
 784         static void maybeUnblock(Object o1) {
 785              BlockInliningWrapper wrapper = (BlockInliningWrapper) o1;
 786              if (wrapper.unblock()) {
 787                  // Reached invocation threshold. Replace counting/blocking wrapper with a reinvoker.
 788                  wrapper.isActivated = false;
 789                  MethodHandle target = wrapper.getTarget();
 790                  LambdaForm lform = DelegatingMethodHandle.makeReinvokerForm(
 791                          target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
 792                  wrapper.updateForm(lform);
 793              }
 794         }
 795 
 796         static final NamedFunction NF_maybeUnblock;
 797         static {
 798             Class<?> THIS_CLASS = BlockInliningWrapper.class;
 799             try {
 800                 NF_maybeUnblock = new NamedFunction(THIS_CLASS.getDeclaredMethod("maybeUnblock", Object.class));
 801             } catch (ReflectiveOperationException ex) {
 802                 throw newInternalError(ex);
 803             }
 804         }
 805     }
 806 
 807     static
 808     LambdaForm makeGuardWithTestForm(MethodType basicType) {
 809         LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT);
 810         if (lform != null)  return lform;
 811         final int THIS_MH      = 0;  // the BMH_LLL
 812         final int ARG_BASE     = 1;  // start of incoming arguments
 813         final int ARG_LIMIT    = ARG_BASE + basicType.parameterCount();
 814         int nameCursor = ARG_LIMIT;
 815         final int GET_TEST     = nameCursor++;
 816         final int GET_TARGET   = nameCursor++;
 817         final int GET_FALLBACK = nameCursor++;
 818         final int CALL_TEST    = nameCursor++;
 819         final int SELECT_ALT   = nameCursor++;
 820         final int CALL_TARGET  = nameCursor++;
 821         assert(CALL_TARGET == SELECT_ALT+1);  // must be true to trigger IBG.emitSelectAlternative
 822 
 823         MethodType lambdaType = basicType.invokerType();
 824         Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
 825 
 826         BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL();


src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File