src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
jdk Cdiff src/share/classes/java/lang/invoke/MethodHandleImpl.java
src/share/classes/java/lang/invoke/MethodHandleImpl.java
Print this page
rev 9088 : 8027827: Improve performance of catchException combinator
Reviewed-by: ?
rev 9089 : [mq]: 8027827.catchException.custom.webrev01
rev 9090 : [mq]: 8027827.catchException.disable_caching
rev 9091 : [mq]: 8027827.catchException.ver03
rev 9092 : [mq]: 8027827.caching
*** 25,35 ****
package java.lang.invoke;
import java.security.AccessController;
import java.security.PrivilegedAction;
- import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import sun.invoke.empty.Empty;
import sun.invoke.util.ValueConversions;
import sun.invoke.util.VerifyType;
--- 25,34 ----
*** 546,555 ****
--- 545,555 ----
LambdaForm form = new LambdaForm("collect", lambdaType.parameterCount(), names);
return SimpleMethodHandle.make(srcType, form);
}
+ @LambdaForm.Hidden
static
MethodHandle selectAlternative(boolean testResult, MethodHandle target, MethodHandle fallback) {
return testResult ? target : fallback;
}
*** 559,569 ****
try {
SELECT_ALTERNATIVE
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
} catch (ReflectiveOperationException ex) {
! throw new RuntimeException(ex);
}
return SELECT_ALTERNATIVE;
}
static
--- 559,569 ----
try {
SELECT_ALTERNATIVE
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "selectAlternative",
MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class));
} catch (ReflectiveOperationException ex) {
! throw uncaughtException(ex);
}
return SELECT_ALTERNATIVE;
}
static
*** 593,763 ****
LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
return SimpleMethodHandle.make(target.type(), form);
}
! private static class GuardWithCatch {
! private final MethodHandle target;
! private final Class<? extends Throwable> exType;
! private final MethodHandle catcher;
! // FIXME: Build the control flow out of foldArguments.
! GuardWithCatch(MethodHandle target, Class<? extends Throwable> exType, MethodHandle catcher) {
! this.target = target;
! this.exType = exType;
! this.catcher = catcher;
! }
! @LambdaForm.Hidden
! private Object invoke_V(Object... av) throws Throwable {
! try {
! return target.invokeExact(av);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, av);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L0() throws Throwable {
! try {
! return target.invokeExact();
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L1(Object a0) throws Throwable {
! try {
! return target.invokeExact(a0);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L2(Object a0, Object a1) throws Throwable {
! try {
! return target.invokeExact(a0, a1);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L3(Object a0, Object a1, Object a2) throws Throwable {
! try {
! return target.invokeExact(a0, a1, a2);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L4(Object a0, Object a1, Object a2, Object a3) throws Throwable {
! try {
! return target.invokeExact(a0, a1, a2, a3);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2, a3);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L5(Object a0, Object a1, Object a2, Object a3, Object a4) throws Throwable {
! try {
! return target.invokeExact(a0, a1, a2, a3, a4);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2, a3, a4);
! }
! }
! @LambdaForm.Hidden
! private Object invoke_L6(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5) throws Throwable {
! try {
! return target.invokeExact(a0, a1, a2, a3, a4, a5);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5);
}
}
! @LambdaForm.Hidden
! private Object invoke_L7(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) throws Throwable {
try {
! return target.invokeExact(a0, a1, a2, a3, a4, a5, a6);
! } catch (Throwable t) {
! if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6);
}
}
@LambdaForm.Hidden
! private Object invoke_L8(Object a0, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) throws Throwable {
try {
! return target.invokeExact(a0, a1, a2, a3, a4, a5, a6, a7);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
! return catcher.invokeExact(t, a0, a1, a2, a3, a4, a5, a6, a7);
}
}
! static MethodHandle[] makeInvokes() {
! ArrayList<MethodHandle> invokes = new ArrayList<>();
! MethodHandles.Lookup lookup = IMPL_LOOKUP;
! for (;;) {
! int nargs = invokes.size();
! String name = "invoke_L"+nargs;
! MethodHandle invoke = null;
! try {
! invoke = lookup.findVirtual(GuardWithCatch.class, name, MethodType.genericMethodType(nargs));
! } catch (ReflectiveOperationException ex) {
! }
! if (invoke == null) break;
! invokes.add(invoke);
}
- assert(invokes.size() == 9); // current number of methods
- return invokes.toArray(new MethodHandle[0]);
- };
- static final MethodHandle[] INVOKES = makeInvokes();
- // For testing use this:
- //static final MethodHandle[] INVOKES = Arrays.copyOf(makeInvokes(), 2);
- static final MethodHandle VARARGS_INVOKE;
- static {
try {
! VARARGS_INVOKE = IMPL_LOOKUP.findVirtual(GuardWithCatch.class, "invoke_V", MethodType.genericMethodType(0, true));
} catch (ReflectiveOperationException ex) {
throw uncaughtException(ex);
}
! }
! }
!
!
! static
! MethodHandle makeGuardWithCatch(MethodHandle target,
! Class<? extends Throwable> exType,
! MethodHandle catcher) {
! MethodType type = target.type();
! MethodType ctype = catcher.type();
! int nargs = type.parameterCount();
! if (nargs < GuardWithCatch.INVOKES.length) {
! MethodType gtype = type.generic();
! MethodType gcatchType = gtype.insertParameterTypes(0, Throwable.class);
! // Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
! MethodHandle gtarget = makePairwiseConvert(target, gtype, 2);
! MethodHandle gcatcher = makePairwiseConvert(catcher, gcatchType, 2);
! GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
! if (gtarget == null || gcatcher == null) throw new InternalError();
! MethodHandle ginvoker = GuardWithCatch.INVOKES[nargs].bindReceiver(gguard);
! return makePairwiseConvert(ginvoker, type, 2);
! } else {
! target = target.asType(type.changeReturnType(Object.class));
! MethodHandle gtarget = makeSpreadArguments(target, Object[].class, 0, nargs);
! MethodType catcherType = ctype.changeParameterType(0, Throwable.class)
! .changeReturnType(Object.class);
! catcher = catcher.asType(catcherType);
! MethodHandle gcatcher = makeSpreadArguments(catcher, Object[].class, 1, nargs);
! GuardWithCatch gguard = new GuardWithCatch(gtarget, exType, gcatcher);
! if (gtarget == null || gcatcher == null) throw new InternalError();
! MethodHandle ginvoker = GuardWithCatch.VARARGS_INVOKE.bindReceiver(gguard);
! MethodHandle gcollect = makeCollectArguments(ginvoker, ValueConversions.varargsArray(nargs), 0, false);
! return makePairwiseConvert(gcollect, type, 2);
! }
}
static
MethodHandle throwException(MethodType type) {
assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
--- 593,748 ----
LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names);
return SimpleMethodHandle.make(target.type(), form);
}
! /**
! * The LambaForm shape for catchException combinator is the following:
! * <blockquote><pre>{@code
! * guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
! * t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
! * t4:L=BoundMethodHandle$Species_LLLLL.argL1(a0:L);
! * t5:L=BoundMethodHandle$Species_LLLLL.argL2(a0:L);
! * t6:L=BoundMethodHandle$Species_LLLLL.argL3(a0:L);
! * t7:L=BoundMethodHandle$Species_LLLLL.argL4(a0:L);
! * t8:L=MethodHandle.invokeBasic(t6:L,a1:L,a2:L);
! * t9:L=MethodHandleImpl.guardWithCatch(t3:L,t4:L,t5:L,t8:L);
! * t10:I=MethodHandle.invokeBasic(t7:L,t9:L);t10:I}
! * }</pre></blockquote>
! *
! * argL0 and argL2 are target and catcher method handles. argL1 is exception class.
! * argL3 and argL4 are auxiliary method handles: argL3 boxes arguments and wraps them into Object[]
! * (ValueConversions.array()) and argL4 unboxes result if necessary (ValueConversions.unbox()).
! *
! * Having t8 and t10 passed outside and not hardcoded into a lambda form allows to share lambda forms
! * among catchException combinators with the same basic type.
! */
! private static LambdaForm makeGuardWithCatchForm(MethodType basicType) {
! MethodType lambdaType = basicType.invokerType();
!
! LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWC);
! if (lform != null) {
! return lform;
! }
!
! final int THIS_MH = 0; // the BMH_LLLLL
! final int ARG_BASE = 1; // start of incoming arguments
! final int ARG_LIMIT = ARG_BASE + basicType.parameterCount();
!
! int nameCursor = ARG_LIMIT;
! final int GET_TARGET = nameCursor++;
! final int GET_CLASS = nameCursor++;
! final int GET_CATCHER = nameCursor++;
! final int GET_COLLECT_ARGS = nameCursor++;
! final int GET_UNBOX_RESULT = nameCursor++;
! final int BOXED_ARGS = nameCursor++;
! final int TRY_CATCH = nameCursor++;
! final int UNBOX_RESULT = nameCursor++;
!
! Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
!
! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
! names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]);
! names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]);
! names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]);
! names[GET_COLLECT_ARGS] = new Name(data.getterFunction(3), names[THIS_MH]);
! names[GET_UNBOX_RESULT] = new Name(data.getterFunction(4), names[THIS_MH]);
!
! // t_{i}:L=MethodHandle.invokeBasic(collectArgs:L,a1:L,...);
! MethodType collectArgsType = basicType.changeReturnType(Object.class);
! MethodHandle invokeBasic = MethodHandles.basicInvoker(collectArgsType);
! Object[] args = new Object[invokeBasic.type().parameterCount()];
! args[0] = names[GET_COLLECT_ARGS];
! System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
! names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
!
! // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
! Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
! names[TRY_CATCH] = new Name(MethodHandleImpl.guardWithCatch(), gwcArgs);
!
! // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
! MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
! Object[] unboxArgs = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
! names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
!
! lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
!
! basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWC, lform);
! return lform;
}
+
+ static
+ MethodHandle makeGuardWithCatch(MethodHandle target,
+ Class<? extends Throwable> exType,
+ MethodHandle catcher) {
+ MethodType type = target.type();
+ LambdaForm form = makeGuardWithCatchForm(type.basicType());
+
+ // Prepare auxiliary method handles used during LambdaForm interpreation.
+ // Box arguments and wrap them into Object[]: ValueConversions.array().
+ MethodType varargsType = type.changeReturnType(Object[].class);
+ MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
+ .asType(varargsType);
+ // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
+ MethodHandle unboxResult;
+ if (type.returnType().isPrimitive()) {
+ unboxResult = ValueConversions.unbox(type.returnType());
+ } else {
+ unboxResult = ValueConversions.identity();
}
!
! BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
! BoundMethodHandle mh;
try {
! mh = (BoundMethodHandle)
! data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
! (Object) collectArgs, (Object) unboxResult);
! } catch (Throwable ex) {
! throw uncaughtException(ex);
}
+ assert(mh.type() == type);
+ return mh;
}
+
+ /**
+ * Intrinsified during LambdaForm compilation
+ * (see {@link InvokerBytecodeGenerator#emitGuardWithCatch emitGuardWithCatch}).
+ */
@LambdaForm.Hidden
! static Object guardWithCatch(MethodHandle target, Class exType, MethodHandle catcher,
! Object... av) throws Throwable {
! int nargs = target.type().parameterCount();
!
! MethodHandle ctarget = makePairwiseConvert(target, target.type().generic(), 1);
! MethodHandle gtarget = makeSpreadArguments(ctarget, Object[].class, 0, nargs);
!
! MethodType ccatcherType = catcher.type().generic()
! .changeParameterType(0, Throwable.class);
! MethodHandle ccatcher = makePairwiseConvert(catcher, ccatcherType, 1);
! MethodHandle gcatcher = makeSpreadArguments(ccatcher, Object[].class, 1, nargs);
!
try {
! return gtarget.invokeExact(av);
} catch (Throwable t) {
if (!exType.isInstance(t)) throw t;
! return gcatcher.invokeExact(t, av);
}
}
!
! private static MethodHandle GUARD_WITH_CATCH;
! static MethodHandle guardWithCatch() {
! if (GUARD_WITH_CATCH != null) {
! return GUARD_WITH_CATCH;
}
try {
! GUARD_WITH_CATCH
! = IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "guardWithCatch",
! MethodType.methodType(Object.class, MethodHandle.class, Class.class, MethodHandle.class, Object[].class));
} catch (ReflectiveOperationException ex) {
throw uncaughtException(ex);
}
! return GUARD_WITH_CATCH;
}
static
MethodHandle throwException(MethodType type) {
assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
*** 775,785 ****
try {
mh
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
MethodType.methodType(Empty.class, Throwable.class));
} catch (ReflectiveOperationException ex) {
! throw new RuntimeException(ex);
}
THROW_EXCEPTION = mh;
return mh;
}
static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
--- 760,770 ----
try {
mh
= IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "throwException",
MethodType.methodType(Empty.class, Throwable.class));
} catch (ReflectiveOperationException ex) {
! throw uncaughtException(ex);
}
THROW_EXCEPTION = mh;
return mh;
}
static <T extends Throwable> Empty throwException(T t) throws T { throw t; }
src/share/classes/java/lang/invoke/MethodHandleImpl.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File