src/java.base/share/classes/java/lang/invoke/LambdaForm.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/LambdaForm.java

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


 102  * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
 103  *                 t3:L = MethodHandle#invoke(t2, a1);
 104  *                 t4:L = FilterMethodHandle#target(a0);
 105  *                 t5:L = MethodHandle#invoke(t4, t3); t5 }
 106  *     == general invoker for unary filterArgument combination
 107  * (a0:L, a1:L)=>{ ...(same as previous example)...
 108  *                 t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
 109  *     == general invoker for unary/unary foldArgument combination
 110  * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
 111  *     == invoker for identity method handle which performs i2l
 112  * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
 113  *                 t3:L = Class#cast(t2,a1); t3 }
 114  *     == invoker for identity method handle which performs cast
 115  * }</pre></blockquote>
 116  * <p>
 117  * @author John Rose, JSR 292 EG
 118  */
 119 class LambdaForm {
 120     final int arity;
 121     final int result;

 122     @Stable final Name[] names;
 123     final String debugName;
 124     MemberName vmentry;   // low-level behavior, or null if not yet prepared
 125     private boolean isCompiled;
 126 
 127     Object transformCache;  // managed by LambdaFormEditor
 128 
 129     public static final int VOID_RESULT = -1, LAST_RESULT = -2;
 130 
 131     enum BasicType {
 132         L_TYPE('L', Object.class, Wrapper.OBJECT),  // all reference types
 133         I_TYPE('I', int.class,    Wrapper.INT),
 134         J_TYPE('J', long.class,   Wrapper.LONG),
 135         F_TYPE('F', float.class,  Wrapper.FLOAT),
 136         D_TYPE('D', double.class, Wrapper.DOUBLE),  // all primitive types
 137         V_TYPE('V', void.class,   Wrapper.VOID);    // not valid in all contexts
 138 
 139         static final BasicType[] ALL_TYPES = BasicType.values();
 140         static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
 141 


 226             return "LIJFD".indexOf(c) >= 0;
 227         }
 228 
 229         static { assert(checkBasicType()); }
 230         private static boolean checkBasicType() {
 231             for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
 232                 assert ARG_TYPES[i].ordinal() == i;
 233                 assert ARG_TYPES[i] == ALL_TYPES[i];
 234             }
 235             for (int i = 0; i < TYPE_LIMIT; i++) {
 236                 assert ALL_TYPES[i].ordinal() == i;
 237             }
 238             assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
 239             assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
 240             return true;
 241         }
 242     }
 243 
 244     LambdaForm(String debugName,
 245                int arity, Name[] names, int result) {




 246         assert(namesOK(arity, names));
 247         this.arity = arity;
 248         this.result = fixResult(result, names);
 249         this.names = names.clone();
 250         this.debugName = fixDebugName(debugName);

 251         int maxOutArity = normalize();
 252         if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
 253             // Cannot use LF interpreter on very high arity expressions.
 254             assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
 255             compileToBytecode();
 256         }
 257     }
 258 
 259     LambdaForm(String debugName,
 260                int arity, Name[] names) {
 261         this(debugName,
 262              arity, names, LAST_RESULT);



 263     }
 264 
 265     LambdaForm(String debugName,
 266                Name[] formals, Name[] temps, Name result) {
 267         this(debugName,
 268              formals.length, buildNames(formals, temps, result), LAST_RESULT);





 269     }
 270 
 271     private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
 272         int arity = formals.length;
 273         int length = arity + temps.length + (result == null ? 0 : 1);
 274         Name[] names = Arrays.copyOf(formals, length);
 275         System.arraycopy(temps, 0, names, arity, temps.length);
 276         if (result != null)
 277             names[length - 1] = result;
 278         return names;
 279     }
 280 
 281     private LambdaForm(String sig) {




 282         // Make a blank lambda form, which returns a constant zero or null.
 283         // It is used as a template for managing the invocation of similar forms that are non-empty.
 284         // Called only from getPreparedForm.
 285         assert(isValidSignature(sig));
 286         this.arity = signatureArity(sig);
 287         this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
 288         this.names = buildEmptyNames(arity, sig);
 289         this.debugName = "LF.zero";

 290         assert(nameRefsAreLegal());
 291         assert(isEmpty());
 292         assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
 293     }
 294 
 295     private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
 296         assert(isValidSignature(basicTypeSignature));
 297         int resultPos = arity + 1;  // skip '_'
 298         if (arity < 0 || basicTypeSignature.length() != resultPos+1)
 299             throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
 300         int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
 301         Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
 302         for (int i = 0; i < numRes; i++) {
 303             Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
 304             names[arity + i] = zero.newIndex(arity + i);
 305         }
 306         return names;
 307     }
 308 
 309     private static int fixResult(int result, Name[] names) {




 102  * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
 103  *                 t3:L = MethodHandle#invoke(t2, a1);
 104  *                 t4:L = FilterMethodHandle#target(a0);
 105  *                 t5:L = MethodHandle#invoke(t4, t3); t5 }
 106  *     == general invoker for unary filterArgument combination
 107  * (a0:L, a1:L)=>{ ...(same as previous example)...
 108  *                 t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
 109  *     == general invoker for unary/unary foldArgument combination
 110  * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
 111  *     == invoker for identity method handle which performs i2l
 112  * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
 113  *                 t3:L = Class#cast(t2,a1); t3 }
 114  *     == invoker for identity method handle which performs cast
 115  * }</pre></blockquote>
 116  * <p>
 117  * @author John Rose, JSR 292 EG
 118  */
 119 class LambdaForm {
 120     final int arity;
 121     final int result;
 122     final boolean forceInline;
 123     @Stable final Name[] names;
 124     final String debugName;
 125     MemberName vmentry;   // low-level behavior, or null if not yet prepared
 126     private boolean isCompiled;
 127 
 128     Object transformCache;  // managed by LambdaFormEditor
 129 
 130     public static final int VOID_RESULT = -1, LAST_RESULT = -2;
 131 
 132     enum BasicType {
 133         L_TYPE('L', Object.class, Wrapper.OBJECT),  // all reference types
 134         I_TYPE('I', int.class,    Wrapper.INT),
 135         J_TYPE('J', long.class,   Wrapper.LONG),
 136         F_TYPE('F', float.class,  Wrapper.FLOAT),
 137         D_TYPE('D', double.class, Wrapper.DOUBLE),  // all primitive types
 138         V_TYPE('V', void.class,   Wrapper.VOID);    // not valid in all contexts
 139 
 140         static final BasicType[] ALL_TYPES = BasicType.values();
 141         static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
 142 


 227             return "LIJFD".indexOf(c) >= 0;
 228         }
 229 
 230         static { assert(checkBasicType()); }
 231         private static boolean checkBasicType() {
 232             for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
 233                 assert ARG_TYPES[i].ordinal() == i;
 234                 assert ARG_TYPES[i] == ALL_TYPES[i];
 235             }
 236             for (int i = 0; i < TYPE_LIMIT; i++) {
 237                 assert ALL_TYPES[i].ordinal() == i;
 238             }
 239             assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
 240             assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
 241             return true;
 242         }
 243     }
 244 
 245     LambdaForm(String debugName,
 246                int arity, Name[] names, int result) {
 247         this(debugName, arity, names, result, true);
 248     }
 249     LambdaForm(String debugName,
 250                int arity, Name[] names, int result, boolean forceInline) {
 251         assert(namesOK(arity, names));
 252         this.arity = arity;
 253         this.result = fixResult(result, names);
 254         this.names = names.clone();
 255         this.debugName = fixDebugName(debugName);
 256         this.forceInline = forceInline;
 257         int maxOutArity = normalize();
 258         if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
 259             // Cannot use LF interpreter on very high arity expressions.
 260             assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
 261             compileToBytecode();
 262         }
 263     }

 264     LambdaForm(String debugName,
 265                int arity, Name[] names) {
 266         this(debugName, arity, names, LAST_RESULT, true);
 267     }
 268     LambdaForm(String debugName,
 269                int arity, Name[] names, boolean forceInline) {
 270         this(debugName, arity, names, LAST_RESULT, forceInline);
 271     }

 272     LambdaForm(String debugName,
 273                Name[] formals, Name[] temps, Name result) {
 274         this(debugName,
 275              formals.length, buildNames(formals, temps, result), LAST_RESULT, true);
 276     }
 277     LambdaForm(String debugName,
 278                Name[] formals, Name[] temps, Name result, boolean forceInline) {
 279         this(debugName,
 280              formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline);
 281     }
 282 
 283     private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
 284         int arity = formals.length;
 285         int length = arity + temps.length + (result == null ? 0 : 1);
 286         Name[] names = Arrays.copyOf(formals, length);
 287         System.arraycopy(temps, 0, names, arity, temps.length);
 288         if (result != null)
 289             names[length - 1] = result;
 290         return names;
 291     }
 292 
 293     private LambdaForm(String sig) {
 294         this(sig, true);
 295     }
 296 
 297     private LambdaForm(String sig, boolean forceInline) {
 298         // Make a blank lambda form, which returns a constant zero or null.
 299         // It is used as a template for managing the invocation of similar forms that are non-empty.
 300         // Called only from getPreparedForm.
 301         assert(isValidSignature(sig));
 302         this.arity = signatureArity(sig);
 303         this.result = (signatureReturn(sig) == V_TYPE ? -1 : arity);
 304         this.names = buildEmptyNames(arity, sig);
 305         this.debugName = "LF.zero";
 306         this.forceInline = forceInline;
 307         assert(nameRefsAreLegal());
 308         assert(isEmpty());
 309         assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
 310     }
 311 
 312     private static Name[] buildEmptyNames(int arity, String basicTypeSignature) {
 313         assert(isValidSignature(basicTypeSignature));
 314         int resultPos = arity + 1;  // skip '_'
 315         if (arity < 0 || basicTypeSignature.length() != resultPos+1)
 316             throw new IllegalArgumentException("bad arity for "+basicTypeSignature);
 317         int numRes = (basicType(basicTypeSignature.charAt(resultPos)) == V_TYPE ? 0 : 1);
 318         Name[] names = arguments(numRes, basicTypeSignature.substring(0, arity));
 319         for (int i = 0; i < numRes; i++) {
 320             Name zero = new Name(constantZero(basicType(basicTypeSignature.charAt(resultPos + i))));
 321             names[arity + i] = zero.newIndex(arity + i);
 322         }
 323         return names;
 324     }
 325 
 326     private static int fixResult(int result, Name[] names) {


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