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

Print this page
rev 17771 : 8184777: species logic for BoundMethodHandle doesn't scale, needs refactor


 126     final boolean forceInline;
 127     final MethodHandle customized;
 128     @Stable final Name[] names;
 129     final Kind kind;
 130     MemberName vmentry;   // low-level behavior, or null if not yet prepared
 131     private boolean isCompiled;
 132 
 133     // Either a LambdaForm cache (managed by LambdaFormEditor) or a link to uncustomized version (for customized LF)
 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),  // all reference types
 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),  // all primitive types
 144         V_TYPE('V', void.class,   Wrapper.VOID);    // not valid in all contexts
 145 
 146         static final BasicType[] ALL_TYPES = BasicType.values();
 147         static final 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         final char btChar;
 153         final Class<?> btClass;
 154         final Wrapper btWrapper;
 155 
 156         private BasicType(char btChar, Class<?> btClass, Wrapper wrapper) {
 157             this.btChar = btChar;
 158             this.btClass = btClass;
 159             this.btWrapper = wrapper;
 160         }
 161 
 162         char basicTypeChar() {
 163             return btChar;
 164         }
 165         Class<?> basicTypeClass() {
 166             return btClass;
 167         }
 168         Wrapper basicTypeWrapper() {
 169             return btWrapper;
 170         }
 171         int basicTypeSlots() {


 662         int arity = sig.indexOf('_');
 663         if (arity < 0)  return false;  // must be of the form *_*
 664         int siglen = sig.length();
 665         if (siglen != arity + 2)  return false;  // *_X
 666         for (int i = 0; i < siglen; i++) {
 667             if (i == arity)  continue;  // skip '_'
 668             char c = sig.charAt(i);
 669             if (c == 'V')
 670                 return (i == siglen - 1 && arity == siglen - 2);
 671             if (!isArgBasicTypeChar(c))  return false; // must be [LIJFD]
 672         }
 673         return true;  // [LIJFD]*_[LIJFDV]
 674     }
 675     static MethodType signatureType(String sig) {
 676         Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
 677         for (int i = 0; i < ptypes.length; i++)
 678             ptypes[i] = basicType(sig.charAt(i)).btClass;
 679         Class<?> rtype = signatureReturn(sig).btClass;
 680         return MethodType.makeImpl(rtype, ptypes, true);
 681     }



 682 
 683     /**
 684      * Check if i-th name is a call to MethodHandleImpl.selectAlternative.
 685      */
 686     boolean isSelectAlternative(int pos) {
 687         // selectAlternative idiom:
 688         //   t_{n}:L=MethodHandleImpl.selectAlternative(...)
 689         //   t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
 690         if (pos+1 >= names.length)  return false;
 691         Name name0 = names[pos];
 692         Name name1 = names[pos+1];
 693         return name0.refersTo(MethodHandleImpl.class, "selectAlternative") &&
 694                 name1.isInvokeBasic() &&
 695                 name1.lastUseIndex(name0) == 0 && // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
 696                 lastUseIndex(name0) == pos+1;     // t_{n} is local: used only in t_{n+1}
 697     }
 698 
 699     private boolean isMatchingIdiom(int pos, String idiomName, int nArgs) {
 700         if (pos+2 >= names.length)  return false;
 701         Name name0 = names[pos];


1274             return this.equals(constantZero(returnType()));
1275         }
1276 
1277         public MethodHandleImpl.Intrinsic intrinsicName() {
1278             return intrinsicName;
1279         }
1280     }
1281 
1282     public static String basicTypeSignature(MethodType type) {
1283         int params = type.parameterCount();
1284         char[] sig = new char[params + 2];
1285         int sigp = 0;
1286         while (sigp < params) {
1287             sig[sigp] = basicTypeChar(type.parameterType(sigp++));
1288         }
1289         sig[sigp++] = '_';
1290         sig[sigp++] = basicTypeChar(type.returnType());
1291         assert(sigp == sig.length);
1292         return String.valueOf(sig);
1293     }








1294     public static String shortenSignature(String signature) {
1295         // Hack to make signatures more readable when they show up in method names.
1296         final int NO_CHAR = -1, MIN_RUN = 3;
1297         int c0, c1 = NO_CHAR, c1reps = 0;
1298         StringBuilder buf = null;
1299         int len = signature.length();
1300         if (len < MIN_RUN)  return signature;
1301         for (int i = 0; i <= len; i++) {







1302             // shift in the next char:
1303             c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i));
1304             if (c1 == c0) { ++c1reps; continue; }
1305             // shift in the next count:
1306             int c0reps = c1reps; c1reps = 1;
1307             // end of a  character run
1308             if (c0reps < MIN_RUN) {
1309                 if (buf != null) {
1310                     while (--c0reps >= 0)
1311                         buf.append((char)c0);
1312                 }
1313                 continue;
1314             }
1315             // found three or more in a row
1316             if (buf == null)
1317                 buf = new StringBuilder().append(signature, 0, i - c0reps);
1318             buf.append((char)c0).append(c0reps);
1319         }
1320         return (buf == null) ? signature : buf.toString();
1321     }


1325         @Stable short index;
1326         final NamedFunction function;
1327         final Object constraint;  // additional type information, if not null
1328         @Stable final Object[] arguments;
1329 
1330         private Name(int index, BasicType type, NamedFunction function, Object[] arguments) {
1331             this.index = (short)index;
1332             this.type = type;
1333             this.function = function;
1334             this.arguments = arguments;
1335             this.constraint = null;
1336             assert(this.index == index);
1337         }
1338         private Name(Name that, Object constraint) {
1339             this.index = that.index;
1340             this.type = that.type;
1341             this.function = that.function;
1342             this.arguments = that.arguments;
1343             this.constraint = constraint;
1344             assert(constraint == null || isParam());  // only params have constraints
1345             assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class);
1346         }
1347         Name(MethodHandle function, Object... arguments) {
1348             this(new NamedFunction(function), arguments);
1349         }
1350         Name(MethodType functionType, Object... arguments) {
1351             this(new NamedFunction(functionType), arguments);
1352             assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == L_TYPE);
1353         }
1354         Name(MemberName function, Object... arguments) {
1355             this(new NamedFunction(function), arguments);
1356         }
1357         Name(NamedFunction function, Object... arguments) {
1358             this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class));
1359             assert(typesMatch(function, arguments));
1360         }
1361         /** Create a raw parameter of the given type, with an expected index. */
1362         Name(int index, BasicType type) {
1363             this(index, type, null, null);
1364         }
1365         /** Create a raw parameter of the given type. */




 126     final boolean forceInline;
 127     final MethodHandle customized;
 128     @Stable final Name[] names;
 129     final Kind kind;
 130     MemberName vmentry;   // low-level behavior, or null if not yet prepared
 131     private boolean isCompiled;
 132 
 133     // Either a LambdaForm cache (managed by LambdaFormEditor) or a link to uncustomized version (for customized LF)
 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),  // all reference types
 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),  // all primitive types
 144         V_TYPE('V', void.class,   Wrapper.VOID);    // not valid in all contexts
 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         // Derived int constants, which (unlike the enums) can be constant folded.
 153         // We can remove them when JDK-8161245 is fixed.
 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() {


 672         int arity = sig.indexOf('_');
 673         if (arity < 0)  return false;  // must be of the form *_*
 674         int siglen = sig.length();
 675         if (siglen != arity + 2)  return false;  // *_X
 676         for (int i = 0; i < siglen; i++) {
 677             if (i == arity)  continue;  // skip '_'
 678             char c = sig.charAt(i);
 679             if (c == 'V')
 680                 return (i == siglen - 1 && arity == siglen - 2);
 681             if (!isArgBasicTypeChar(c))  return false; // must be [LIJFD]
 682         }
 683         return true;  // [LIJFD]*_[LIJFDV]
 684     }
 685     static MethodType signatureType(String sig) {
 686         Class<?>[] ptypes = new Class<?>[signatureArity(sig)];
 687         for (int i = 0; i < ptypes.length; i++)
 688             ptypes[i] = basicType(sig.charAt(i)).btClass;
 689         Class<?> rtype = signatureReturn(sig).btClass;
 690         return MethodType.makeImpl(rtype, ptypes, true);
 691     }
 692     static MethodType basicMethodType(MethodType mt) {
 693         return signatureType(basicTypeSignature(mt));
 694     }
 695 
 696     /**
 697      * Check if i-th name is a call to MethodHandleImpl.selectAlternative.
 698      */
 699     boolean isSelectAlternative(int pos) {
 700         // selectAlternative idiom:
 701         //   t_{n}:L=MethodHandleImpl.selectAlternative(...)
 702         //   t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
 703         if (pos+1 >= names.length)  return false;
 704         Name name0 = names[pos];
 705         Name name1 = names[pos+1];
 706         return name0.refersTo(MethodHandleImpl.class, "selectAlternative") &&
 707                 name1.isInvokeBasic() &&
 708                 name1.lastUseIndex(name0) == 0 && // t_{n+1}:?=MethodHandle.invokeBasic(t_{n}, ...)
 709                 lastUseIndex(name0) == pos+1;     // t_{n} is local: used only in t_{n+1}
 710     }
 711 
 712     private boolean isMatchingIdiom(int pos, String idiomName, int nArgs) {
 713         if (pos+2 >= names.length)  return false;
 714         Name name0 = names[pos];


1287             return this.equals(constantZero(returnType()));
1288         }
1289 
1290         public MethodHandleImpl.Intrinsic intrinsicName() {
1291             return intrinsicName;
1292         }
1293     }
1294 
1295     public static String basicTypeSignature(MethodType type) {
1296         int params = type.parameterCount();
1297         char[] sig = new char[params + 2];
1298         int sigp = 0;
1299         while (sigp < params) {
1300             sig[sigp] = basicTypeChar(type.parameterType(sigp++));
1301         }
1302         sig[sigp++] = '_';
1303         sig[sigp++] = basicTypeChar(type.returnType());
1304         assert(sigp == sig.length);
1305         return String.valueOf(sig);
1306     }
1307 
1308     /** Hack to make signatures more readable when they show up in method names.
1309      * Signature should start with a sequence of uppercase ASCII letters.
1310      * Runs of three or more are replaced by a single letter plus a decimal repeat count.
1311      * A tail of anything other than uppercase ASCII is passed through unchanged.
1312      * @param signature sequence of uppercase ASCII letters with possible repetitions
1313      * @return same sequence, with repetitions counted by decimal numerals
1314      */
1315     public static String shortenSignature(String signature) {

1316         final int NO_CHAR = -1, MIN_RUN = 3;
1317         int c0, c1 = NO_CHAR, c1reps = 0;
1318         StringBuilder buf = null;
1319         int len = signature.length();
1320         if (len < MIN_RUN)  return signature;
1321         for (int i = 0; i <= len; i++) {
1322             if (c1 != NO_CHAR && !('A' <= c1 && c1 <= 'Z')) {
1323                 // wrong kind of char; bail out here
1324                 if (buf != null) {
1325                     buf.append(signature.substring(i - c1reps, len));
1326                 }
1327                 break;
1328             }
1329             // shift in the next char:
1330             c0 = c1; c1 = (i == len ? NO_CHAR : signature.charAt(i));
1331             if (c1 == c0) { ++c1reps; continue; }
1332             // shift in the next count:
1333             int c0reps = c1reps; c1reps = 1;
1334             // end of a  character run
1335             if (c0reps < MIN_RUN) {
1336                 if (buf != null) {
1337                     while (--c0reps >= 0)
1338                         buf.append((char)c0);
1339                 }
1340                 continue;
1341             }
1342             // found three or more in a row
1343             if (buf == null)
1344                 buf = new StringBuilder().append(signature, 0, i - c0reps);
1345             buf.append((char)c0).append(c0reps);
1346         }
1347         return (buf == null) ? signature : buf.toString();
1348     }


1352         @Stable short index;
1353         final NamedFunction function;
1354         final Object constraint;  // additional type information, if not null
1355         @Stable final Object[] arguments;
1356 
1357         private Name(int index, BasicType type, NamedFunction function, Object[] arguments) {
1358             this.index = (short)index;
1359             this.type = type;
1360             this.function = function;
1361             this.arguments = arguments;
1362             this.constraint = null;
1363             assert(this.index == index);
1364         }
1365         private Name(Name that, Object constraint) {
1366             this.index = that.index;
1367             this.type = that.type;
1368             this.function = that.function;
1369             this.arguments = that.arguments;
1370             this.constraint = constraint;
1371             assert(constraint == null || isParam());  // only params have constraints
1372             assert(constraint == null || constraint instanceof ClassSpecializer.SpeciesData || constraint instanceof Class);
1373         }
1374         Name(MethodHandle function, Object... arguments) {
1375             this(new NamedFunction(function), arguments);
1376         }
1377         Name(MethodType functionType, Object... arguments) {
1378             this(new NamedFunction(functionType), arguments);
1379             assert(arguments[0] instanceof Name && ((Name)arguments[0]).type == L_TYPE);
1380         }
1381         Name(MemberName function, Object... arguments) {
1382             this(new NamedFunction(function), arguments);
1383         }
1384         Name(NamedFunction function, Object... arguments) {
1385             this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class));
1386             assert(typesMatch(function, arguments));
1387         }
1388         /** Create a raw parameter of the given type, with an expected index. */
1389         Name(int index, BasicType type) {
1390             this(index, type, null, null);
1391         }
1392         /** Create a raw parameter of the given type. */