< prev index next >

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

Print this page
rev 15353 : 8164044: Generate the corresponding BoundMethodHandle to all generated DirectMethodHandles
Reviewed-by: vlivanov, mhaupt


  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.perf.PerfCounter;
  29 import jdk.internal.vm.annotation.DontInline;
  30 import jdk.internal.vm.annotation.Stable;
  31 import sun.invoke.util.Wrapper;
  32 
  33 import java.lang.annotation.ElementType;
  34 import java.lang.annotation.Retention;
  35 import java.lang.annotation.RetentionPolicy;
  36 import java.lang.annotation.Target;
  37 import java.lang.reflect.Method;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 
  41 import static java.lang.invoke.LambdaForm.BasicType.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
  43 import static java.lang.invoke.MethodHandleStatics.*;

  44 
  45 /**
  46  * The symbolic, non-executable form of a method handle's invocation semantics.
  47  * It consists of a series of names.
  48  * The first N (N=arity) names are parameters,
  49  * while any remaining names are temporary values.
  50  * Each temporary specifies the application of a function to some arguments.
  51  * The functions are method handles, while the arguments are mixes of
  52  * constant values and local names.
  53  * The result of the lambda is defined as one of the names, often the last one.
  54  * <p>
  55  * Here is an approximate grammar:
  56  * <blockquote><pre>{@code
  57  * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
  58  * ArgName = "a" N ":" T
  59  * TempName = "t" N ":" T "=" Function "(" Argument* ");"
  60  * Function = ConstantValue
  61  * Argument = NameRef | ConstantValue
  62  * Result = NameRef | "void"
  63  * NameRef = "a" N | "t" N


 110  *     == general invoker for unary filterArgument combination
 111  * (a0:L, a1:L)=>{ ...(same as previous example)...
 112  *                 t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
 113  *     == general invoker for unary/unary foldArgument combination
 114  * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
 115  *     == invoker for identity method handle which performs i2l
 116  * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
 117  *                 t3:L = Class#cast(t2,a1); t3 }
 118  *     == invoker for identity method handle which performs cast
 119  * }</pre></blockquote>
 120  * <p>
 121  * @author John Rose, JSR 292 EG
 122  */
 123 class LambdaForm {
 124     final int arity;
 125     final int result;
 126     final boolean forceInline;
 127     final MethodHandle customized;
 128     @Stable final Name[] names;
 129     final String debugName;

 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;


 249         }
 250         static boolean isArgBasicTypeChar(char c) {
 251             return "LIJFD".indexOf(c) >= 0;
 252         }
 253 
 254         static { assert(checkBasicType()); }
 255         private static boolean checkBasicType() {
 256             for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
 257                 assert ARG_TYPES[i].ordinal() == i;
 258                 assert ARG_TYPES[i] == ALL_TYPES[i];
 259             }
 260             for (int i = 0; i < TYPE_LIMIT; i++) {
 261                 assert ALL_TYPES[i].ordinal() == i;
 262             }
 263             assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
 264             assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
 265             return true;
 266         }
 267     }
 268 


























 269     LambdaForm(String debugName,
 270                int arity, Name[] names, int result) {
 271         this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null);




 272     }
 273     LambdaForm(String debugName,
 274                int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {




 275         assert(namesOK(arity, names));
 276         this.arity = arity;
 277         this.result = fixResult(result, names);
 278         this.names = names.clone();
 279         this.debugName = fixDebugName(debugName);
 280         this.forceInline = forceInline;
 281         this.customized = customized;

 282         int maxOutArity = normalize();
 283         if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
 284             // Cannot use LF interpreter on very high arity expressions.
 285             assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
 286             compileToBytecode();
 287         }
 288     }
 289     LambdaForm(String debugName,
 290                int arity, Name[] names) {
 291         this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
 292     }
 293     LambdaForm(String debugName,
 294                int arity, Name[] names, boolean forceInline) {
 295         this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null);




 296     }
 297     LambdaForm(String debugName,
 298                Name[] formals, Name[] temps, Name result) {
 299         this(debugName,
 300              formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
 301     }
 302     LambdaForm(String debugName,
 303                Name[] formals, Name[] temps, Name result, boolean forceInline) {
 304         this(debugName,
 305              formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*customized=*/null);
 306     }
 307 
 308     private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
 309         int arity = formals.length;
 310         int length = arity + temps.length + (result == null ? 0 : 1);
 311         Name[] names = Arrays.copyOf(formals, length);
 312         System.arraycopy(temps, 0, names, arity, temps.length);
 313         if (result != null)
 314             names[length - 1] = result;
 315         return names;
 316     }
 317 
 318     private LambdaForm(MethodType mt) {
 319         // Make a blank lambda form, which returns a constant zero or null.
 320         // It is used as a template for managing the invocation of similar forms that are non-empty.
 321         // Called only from getPreparedForm.
 322         this.arity = mt.parameterCount();
 323         this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
 324         this.names = buildEmptyNames(arity, mt, result == -1);
 325         this.debugName = "LF.zero";
 326         this.forceInline = true;
 327         this.customized = null;

 328         assert(nameRefsAreLegal());
 329         assert(isEmpty());
 330         String sig = null;
 331         assert(isValidSignature(sig = basicTypeSignature()));
 332         assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
 333     }
 334 
 335     private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
 336         Name[] names = arguments(isVoid ? 0 : 1, mt);
 337         if (!isVoid) {
 338             Name zero = new Name(constantZero(basicType(mt.returnType())));
 339             names[arity] = zero.newIndex(arity);
 340         }
 341         return names;
 342     }
 343 
 344     private static int fixResult(int result, Name[] names) {
 345         if (result == LAST_RESULT)
 346             result = names.length - 1;  // might still be void
 347         if (result >= 0 && names[result].type == V_TYPE)


 378             }
 379             return buf.toString();
 380         }
 381         return debugName;
 382     }
 383 
 384     private static boolean namesOK(int arity, Name[] names) {
 385         for (int i = 0; i < names.length; i++) {
 386             Name n = names[i];
 387             assert(n != null) : "n is null";
 388             if (i < arity)
 389                 assert( n.isParam()) : n + " is not param at " + i;
 390             else
 391                 assert(!n.isParam()) : n + " is param at " + i;
 392         }
 393         return true;
 394     }
 395 
 396     /** Customize LambdaForm for a particular MethodHandle */
 397     LambdaForm customize(MethodHandle mh) {
 398         LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
 399         if (COMPILE_THRESHOLD >= 0 && isCompiled) {
 400             // If shared LambdaForm has been compiled, compile customized version as well.
 401             customForm.compileToBytecode();
 402         }
 403         customForm.transformCache = this; // LambdaFormEditor should always use uncustomized form.
 404         return customForm;
 405     }
 406 
 407     /** Get uncustomized flavor of the LambdaForm */
 408     LambdaForm uncustomize() {
 409         if (customized == null) {
 410             return this;
 411         }
 412         assert(transformCache != null); // Customized LambdaForm should always has a link to uncustomized version.
 413         LambdaForm uncustomizedForm = (LambdaForm)transformCache;
 414         if (COMPILE_THRESHOLD >= 0 && isCompiled) {
 415             // If customized LambdaForm has been compiled, compile uncustomized version as well.
 416             uncustomizedForm.compileToBytecode();
 417         }
 418         return uncustomizedForm;


 753         if (vmentry != null && isCompiled) {
 754             return;  // already compiled somehow
 755         }
 756         MethodType invokerType = methodType();
 757         assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
 758         try {
 759             vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
 760             if (TRACE_INTERPRETER)
 761                 traceInterpreter("compileToBytecode", this);
 762             isCompiled = true;
 763         } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
 764             // bytecode generation failed - mark this LambdaForm as to be run in interpretation mode only
 765             invocationCounter = -1;
 766             failedCompilationCounter().increment();
 767             if (LOG_LF_COMPILATION_FAILURE) {
 768                 System.out.println("LambdaForm compilation failed: " + this);
 769                 bge.printStackTrace(System.out);
 770             }
 771         } catch (Error | Exception e) {
 772             throw newInternalError(this.toString(), e);
 773         }
 774     }
 775 
 776     /**
 777      * Generate optimizable bytecode for this form after first looking for a
 778      * pregenerated version in a specified class.
 779      */
 780     void compileToBytecode(Class<?> lookupClass) {
 781         if (vmentry != null && isCompiled) {
 782             return;  // already compiled somehow
 783         }
 784         MethodType invokerType = methodType();
 785         assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
 786         int dot = debugName.indexOf('.');
 787         String methodName = (dot > 0) ? debugName.substring(dot + 1) : debugName;
 788         MemberName member = new MemberName(lookupClass, methodName, invokerType, REF_invokeStatic);
 789         MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, lookupClass);
 790         if (resolvedMember != null) {
 791             vmentry = resolvedMember;
 792             isCompiled = true;
 793         } else {
 794             compileToBytecode();
 795         }
 796     }
 797 
 798     private static void computeInitialPreparedForms() {
 799         // Find all predefined invokers and associate them with canonical empty lambda forms.
 800         for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
 801             if (!m.isStatic() || !m.isPackage())  continue;
 802             MethodType mt = m.getMethodType();
 803             if (mt.parameterCount() > 0 &&
 804                 mt.parameterType(0) == MethodHandle.class &&
 805                 m.getName().startsWith("interpret_")) {
 806                 String sig = null;
 807                 assert((sig = basicTypeSignature(mt)) != null &&
 808                         m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
 809                 LambdaForm form = new LambdaForm(mt);
 810                 form.vmentry = m;
 811                 form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
 812             }
 813         }
 814     }




  24  */
  25 
  26 package java.lang.invoke;
  27 
  28 import jdk.internal.perf.PerfCounter;
  29 import jdk.internal.vm.annotation.DontInline;
  30 import jdk.internal.vm.annotation.Stable;
  31 import sun.invoke.util.Wrapper;
  32 
  33 import java.lang.annotation.ElementType;
  34 import java.lang.annotation.Retention;
  35 import java.lang.annotation.RetentionPolicy;
  36 import java.lang.annotation.Target;
  37 import java.lang.reflect.Method;
  38 import java.util.Arrays;
  39 import java.util.HashMap;
  40 
  41 import static java.lang.invoke.LambdaForm.BasicType.*;
  42 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
  43 import static java.lang.invoke.MethodHandleStatics.*;
  44 import java.util.Objects;
  45 
  46 /**
  47  * The symbolic, non-executable form of a method handle's invocation semantics.
  48  * It consists of a series of names.
  49  * The first N (N=arity) names are parameters,
  50  * while any remaining names are temporary values.
  51  * Each temporary specifies the application of a function to some arguments.
  52  * The functions are method handles, while the arguments are mixes of
  53  * constant values and local names.
  54  * The result of the lambda is defined as one of the names, often the last one.
  55  * <p>
  56  * Here is an approximate grammar:
  57  * <blockquote><pre>{@code
  58  * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
  59  * ArgName = "a" N ":" T
  60  * TempName = "t" N ":" T "=" Function "(" Argument* ");"
  61  * Function = ConstantValue
  62  * Argument = NameRef | ConstantValue
  63  * Result = NameRef | "void"
  64  * NameRef = "a" N | "t" N


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


 251         }
 252         static boolean isArgBasicTypeChar(char c) {
 253             return "LIJFD".indexOf(c) >= 0;
 254         }
 255 
 256         static { assert(checkBasicType()); }
 257         private static boolean checkBasicType() {
 258             for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
 259                 assert ARG_TYPES[i].ordinal() == i;
 260                 assert ARG_TYPES[i] == ALL_TYPES[i];
 261             }
 262             for (int i = 0; i < TYPE_LIMIT; i++) {
 263                 assert ALL_TYPES[i].ordinal() == i;
 264             }
 265             assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
 266             assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
 267             return true;
 268         }
 269     }
 270 
 271     enum Kind {
 272         GENERIC(""),
 273         BOUND_REINVOKER("BMH.reinvoke"),
 274         REINVOKER("MH.reinvoke"),
 275         DELEGATE("MH.delegate"),
 276         DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
 277         DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
 278         DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
 279         DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
 280         DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
 281         DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
 282 
 283         final String defaultLambdaName;
 284         final String methodName;
 285 
 286         private Kind(String defaultLambdaName) {
 287             this.defaultLambdaName = defaultLambdaName;
 288             int p = defaultLambdaName.indexOf('.');
 289             if (p > -1) {
 290                 this.methodName = defaultLambdaName.substring(p + 1);
 291             } else {
 292                 this.methodName = defaultLambdaName;
 293             }
 294         }
 295     }
 296 
 297     LambdaForm(String debugName,
 298                int arity, Name[] names, int result) {
 299         this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
 300     }
 301     LambdaForm(String debugName,
 302                int arity, Name[] names, int result, Kind kind) {
 303         this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, kind);
 304     }
 305     LambdaForm(String debugName,
 306                int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
 307         this(debugName, arity, names, result, forceInline, customized, Kind.GENERIC);
 308     }
 309     LambdaForm(String debugName,
 310                int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) {
 311         assert(namesOK(arity, names));
 312         this.arity = arity;
 313         this.result = fixResult(result, names);
 314         this.names = names.clone();
 315         this.debugName = fixDebugName(debugName);
 316         this.forceInline = forceInline;
 317         this.customized = customized;
 318         this.kind = kind;
 319         int maxOutArity = normalize();
 320         if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
 321             // Cannot use LF interpreter on very high arity expressions.
 322             assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
 323             compileToBytecode();
 324         }
 325     }
 326     LambdaForm(String debugName,
 327                int arity, Name[] names) {
 328         this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
 329     }
 330     LambdaForm(String debugName,
 331                int arity, Name[] names, boolean forceInline) {
 332         this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
 333     }
 334     LambdaForm(String debugName,
 335                int arity, Name[] names, boolean forceInline, Kind kind) {
 336         this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind);
 337     }
 338     LambdaForm(String debugName,
 339                Name[] formals, Name[] temps, Name result) {
 340         this(debugName,
 341              formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
 342     }
 343     LambdaForm(String debugName,
 344                Name[] formals, Name[] temps, Name result, boolean forceInline) {
 345         this(debugName,
 346              formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*customized=*/null);
 347     }
 348 
 349     private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
 350         int arity = formals.length;
 351         int length = arity + temps.length + (result == null ? 0 : 1);
 352         Name[] names = Arrays.copyOf(formals, length);
 353         System.arraycopy(temps, 0, names, arity, temps.length);
 354         if (result != null)
 355             names[length - 1] = result;
 356         return names;
 357     }
 358 
 359     private LambdaForm(MethodType mt) {
 360         // Make a blank lambda form, which returns a constant zero or null.
 361         // It is used as a template for managing the invocation of similar forms that are non-empty.
 362         // Called only from getPreparedForm.
 363         this.arity = mt.parameterCount();
 364         this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
 365         this.names = buildEmptyNames(arity, mt, result == -1);
 366         this.debugName = "LF.zero";
 367         this.forceInline = true;
 368         this.customized = null;
 369         this.kind = Kind.GENERIC;
 370         assert(nameRefsAreLegal());
 371         assert(isEmpty());
 372         String sig = null;
 373         assert(isValidSignature(sig = basicTypeSignature()));
 374         assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
 375     }
 376 
 377     private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
 378         Name[] names = arguments(isVoid ? 0 : 1, mt);
 379         if (!isVoid) {
 380             Name zero = new Name(constantZero(basicType(mt.returnType())));
 381             names[arity] = zero.newIndex(arity);
 382         }
 383         return names;
 384     }
 385 
 386     private static int fixResult(int result, Name[] names) {
 387         if (result == LAST_RESULT)
 388             result = names.length - 1;  // might still be void
 389         if (result >= 0 && names[result].type == V_TYPE)


 420             }
 421             return buf.toString();
 422         }
 423         return debugName;
 424     }
 425 
 426     private static boolean namesOK(int arity, Name[] names) {
 427         for (int i = 0; i < names.length; i++) {
 428             Name n = names[i];
 429             assert(n != null) : "n is null";
 430             if (i < arity)
 431                 assert( n.isParam()) : n + " is not param at " + i;
 432             else
 433                 assert(!n.isParam()) : n + " is param at " + i;
 434         }
 435         return true;
 436     }
 437 
 438     /** Customize LambdaForm for a particular MethodHandle */
 439     LambdaForm customize(MethodHandle mh) {
 440         LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh, kind);
 441         if (COMPILE_THRESHOLD >= 0 && isCompiled) {
 442             // If shared LambdaForm has been compiled, compile customized version as well.
 443             customForm.compileToBytecode();
 444         }
 445         customForm.transformCache = this; // LambdaFormEditor should always use uncustomized form.
 446         return customForm;
 447     }
 448 
 449     /** Get uncustomized flavor of the LambdaForm */
 450     LambdaForm uncustomize() {
 451         if (customized == null) {
 452             return this;
 453         }
 454         assert(transformCache != null); // Customized LambdaForm should always has a link to uncustomized version.
 455         LambdaForm uncustomizedForm = (LambdaForm)transformCache;
 456         if (COMPILE_THRESHOLD >= 0 && isCompiled) {
 457             // If customized LambdaForm has been compiled, compile uncustomized version as well.
 458             uncustomizedForm.compileToBytecode();
 459         }
 460         return uncustomizedForm;


 795         if (vmentry != null && isCompiled) {
 796             return;  // already compiled somehow
 797         }
 798         MethodType invokerType = methodType();
 799         assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
 800         try {
 801             vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
 802             if (TRACE_INTERPRETER)
 803                 traceInterpreter("compileToBytecode", this);
 804             isCompiled = true;
 805         } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
 806             // bytecode generation failed - mark this LambdaForm as to be run in interpretation mode only
 807             invocationCounter = -1;
 808             failedCompilationCounter().increment();
 809             if (LOG_LF_COMPILATION_FAILURE) {
 810                 System.out.println("LambdaForm compilation failed: " + this);
 811                 bge.printStackTrace(System.out);
 812             }
 813         } catch (Error | Exception e) {
 814             throw newInternalError(this.toString(), e);






















 815         }
 816     }
 817 
 818     private static void computeInitialPreparedForms() {
 819         // Find all predefined invokers and associate them with canonical empty lambda forms.
 820         for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
 821             if (!m.isStatic() || !m.isPackage())  continue;
 822             MethodType mt = m.getMethodType();
 823             if (mt.parameterCount() > 0 &&
 824                 mt.parameterType(0) == MethodHandle.class &&
 825                 m.getName().startsWith("interpret_")) {
 826                 String sig = null;
 827                 assert((sig = basicTypeSignature(mt)) != null &&
 828                         m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
 829                 LambdaForm form = new LambdaForm(mt);
 830                 form.vmentry = m;
 831                 form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
 832             }
 833         }
 834     }


< prev index next >