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

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

Print this page
rev 11254 : 8063137: Never-taken branches should be pruned when GWT LambdaForms are shared
Reviewed-by: ?
rev 11255 : [mq]: gwt.profile.1

*** 630,640 **** MH_fillNewTypedArray = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray", MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); MH_selectAlternative = makeIntrinsic( IMPL_LOOKUP.findStatic(MHI, "selectAlternative", ! MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)), Intrinsic.SELECT_ALTERNATIVE); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } } --- 630,640 ---- MH_fillNewTypedArray = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray", MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); MH_selectAlternative = makeIntrinsic( IMPL_LOOKUP.findStatic(MHI, "selectAlternative", ! MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class, int[].class)), Intrinsic.SELECT_ALTERNATIVE); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } }
*** 694,722 **** return SimpleMethodHandle.make(srcType, form); } @LambdaForm.Hidden static ! MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) { ! return testResult ? target : fallback; } static MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { MethodType type = target.type(); assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type)); MethodType basicType = type.basicType(); LambdaForm form = makeGuardWithTestForm(basicType); ! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); BoundMethodHandle mh; try { mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, ! (Object) test, (Object) profile(target), (Object) profile(fallback)); } catch (Throwable ex) { throw uncaughtException(ex); } assert(mh.type() == type); return mh; --- 694,751 ---- return SimpleMethodHandle.make(srcType, form); } @LambdaForm.Hidden static ! MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback, int[] counters) { ! if (counters != null) { ! updateCounters(counters, testResult); ! } ! if (testResult) { ! return target; ! } else { ! return fallback; ! } ! } ! ! // Intrinsified by C2. Counters are used during parsing to calculate branch frequencies. ! @LambdaForm.Hidden ! static ! boolean profileBranch(boolean result, int[] counters) { ! updateCounters(counters, result); ! return result; ! } ! ! @LambdaForm.Hidden ! @ForceInline ! static ! void updateCounters(int[] counters, boolean result) { ! int idx = result ? 0 : 1; ! try { ! counters[idx] = Math.addExact(counters[idx], 1); ! } catch (ArithmeticException e) { ! // Avoid continuous overflow by halving the problematic count. ! counters[idx] = counters[idx] / 2; ! } } static MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { MethodType type = target.type(); assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type)); MethodType basicType = type.basicType(); + int[] counters = PROFILE_GWT ? new int[2] : null; LambdaForm form = makeGuardWithTestForm(basicType); ! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL(); BoundMethodHandle mh; try { mh = (BoundMethodHandle) data.constructor().invokeBasic(type, form, ! (Object) test, (Object) profile(target), (Object) profile(fallback), counters); } catch (Throwable ex) { throw uncaughtException(ex); } assert(mh.type() == type); return mh;
*** 854,893 **** final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); int nameCursor = ARG_LIMIT; final int GET_TEST = nameCursor++; final int GET_TARGET = nameCursor++; final int GET_FALLBACK = nameCursor++; final int CALL_TEST = nameCursor++; final int SELECT_ALT = nameCursor++; final int CALL_TARGET = nameCursor++; assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative MethodType lambdaType = basicType.invokerType(); Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); ! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); names[THIS_MH] = names[THIS_MH].withConstraint(data); names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]); names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]); names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]); ! Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class); // call test MethodType testType = basicType.changeReturnType(boolean.class).basicType(); invokeArgs[0] = names[GET_TEST]; names[CALL_TEST] = new Name(testType, invokeArgs); // call selectAlternative names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST], ! names[GET_TARGET], names[GET_FALLBACK]); // call target or fallback invokeArgs[0] = names[SELECT_ALT]; names[CALL_TARGET] = new Name(basicType, invokeArgs); ! lform = new LambdaForm("guard", lambdaType.parameterCount(), names); return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform); } /** --- 883,923 ---- final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); int nameCursor = ARG_LIMIT; final int GET_TEST = nameCursor++; final int GET_TARGET = nameCursor++; final int GET_FALLBACK = nameCursor++; + final int GET_COUNTERS = nameCursor++; final int CALL_TEST = nameCursor++; final int SELECT_ALT = nameCursor++; final int CALL_TARGET = nameCursor++; assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative MethodType lambdaType = basicType.invokerType(); Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); ! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLL(); names[THIS_MH] = names[THIS_MH].withConstraint(data); names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]); names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]); names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]); ! names[GET_COUNTERS] = new Name(data.getterFunction(3), names[THIS_MH]); Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class); // call test MethodType testType = basicType.changeReturnType(boolean.class).basicType(); invokeArgs[0] = names[GET_TEST]; names[CALL_TEST] = new Name(testType, invokeArgs); // call selectAlternative names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST], ! names[GET_TARGET], names[GET_FALLBACK], names[GET_COUNTERS]); // call target or fallback invokeArgs[0] = names[SELECT_ALT]; names[CALL_TARGET] = new Name(basicType, invokeArgs); ! lform = new LambdaForm("guard", lambdaType.parameterCount(), names, /*forceInline=*/true); return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform); } /**
src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File