# HG changeset patch # User jrose # Date 1383448090 25200 # Node ID 2ad6b165b7d8f825ea6cecbf4922eeac0733ee67 # Parent e88919c55dac1b7a8c9163a79456e025308e25e5 8024635: Caching MethodType's descriptor string improves lambda linkage performance Summary: Better interpreted and compiled performance of operations in MethodType important to LambdaMetafactory. Reviewed-by: jrose, twisti, mchung Contributed-by: sergey.kuksenko@oracle.com diff -r e88919c55dac -r 2ad6b165b7d8 jdk/src/share/classes/java/lang/invoke/MethodType.java --- a/jdk/src/share/classes/java/lang/invoke/MethodType.java Fri Nov 01 14:40:03 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodType.java Sat Nov 02 20:08:10 2013 -0700 @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentHashMap; import sun.invoke.util.BytecodeDescriptor; @@ -98,14 +99,26 @@ private @Stable MethodTypeForm form; // erased form, plus cached data about primitives private @Stable MethodType wrapAlt; // alternative wrapped/unwrapped version private @Stable Invokers invokers; // cache of handy higher-order adapters + private @Stable String methodDescriptor; // cache for toMethodDescriptorString /** * Check the given parameters for validity and store them into the final fields. */ - private MethodType(Class rtype, Class[] ptypes) { + private MethodType(Class rtype, Class[] ptypes, boolean trusted) { checkRtype(rtype); checkPtypes(ptypes); this.rtype = rtype; + // defensively copy the array passed in by the user + this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length); + } + + /** + * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table. + * Does not check the given parameters for validity, and must be discarded after it is used as a searching key. + * The parameters are reversed for this constructor, so that is is not accidentally used. + */ + private MethodType(Class[] ptypes, Class rtype) { + this.rtype = rtype; this.ptypes = ptypes; } @@ -146,20 +159,21 @@ /*non-public*/ static final int MAX_MH_INVOKER_ARITY = MAX_MH_ARITY-1; // deduct one more for invoker private static void checkRtype(Class rtype) { - rtype.equals(rtype); // null check + Objects.requireNonNull(rtype); } - private static int checkPtype(Class ptype) { - ptype.getClass(); //NPE + private static void checkPtype(Class ptype) { + Objects.requireNonNull(ptype); if (ptype == void.class) throw newIllegalArgumentException("parameter type cannot be void"); - if (ptype == double.class || ptype == long.class) return 1; - return 0; } /** Return number of extra slots (count of long/double args). */ private static int checkPtypes(Class[] ptypes) { int slots = 0; for (Class ptype : ptypes) { - slots += checkPtype(ptype); + checkPtype(ptype); + if (ptype == double.class || ptype == long.class) { + slots++; + } } checkSlotCount(ptypes.length + slots); return slots; @@ -284,20 +298,16 @@ */ /*trusted*/ static MethodType makeImpl(Class rtype, Class[] ptypes, boolean trusted) { + MethodType mt = internTable.get(new MethodType(ptypes, rtype)); + if (mt != null) + return mt; if (ptypes.length == 0) { ptypes = NO_PTYPES; trusted = true; } - MethodType mt1 = new MethodType(rtype, ptypes); - MethodType mt0 = internTable.get(mt1); - if (mt0 != null) - return mt0; - if (!trusted) - // defensively copy the array passed in by the user - mt1 = new MethodType(rtype, ptypes.clone()); + mt = new MethodType(rtype, ptypes, trusted); // promote the object to the Real Thing, and reprobe - MethodTypeForm form = MethodTypeForm.findForm(mt1); - mt1.form = form; - return internTable.add(mt1); + mt.form = MethodTypeForm.findForm(mt); + return internTable.add(mt); } private static final MethodType[] objectOnlyTypes = new MethodType[20]; @@ -919,7 +929,12 @@ * @return the bytecode type descriptor representation */ public String toMethodDescriptorString() { - return BytecodeDescriptor.unparse(this); + String desc = methodDescriptor; + if (desc == null) { + desc = BytecodeDescriptor.unparse(this); + methodDescriptor = desc; + } + return desc; } /*non-public*/ static String toFieldDescriptorString(Class cls) {