jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
changeset 44599 942f3546b679
parent 44592 6b028630b652
equal deleted inserted replaced
44598:ddaea4f20a7b 44599:942f3546b679
    71     private static final String LF_SIG  = "L" + LF + ";";
    71     private static final String LF_SIG  = "L" + LF + ";";
    72     private static final String LFN_SIG = "L" + LFN + ";";
    72     private static final String LFN_SIG = "L" + LFN + ";";
    73     private static final String LL_SIG  = "(L" + OBJ + ";)L" + OBJ + ";";
    73     private static final String LL_SIG  = "(L" + OBJ + ";)L" + OBJ + ";";
    74     private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
    74     private static final String LLV_SIG = "(L" + OBJ + ";L" + OBJ + ";)V";
    75     private static final String CLASS_PREFIX = LF + "$";
    75     private static final String CLASS_PREFIX = LF + "$";
       
    76     private static final String SOURCE_PREFIX = "LambdaForm$";
    76 
    77 
    77     /** Name of its super class*/
    78     /** Name of its super class*/
    78     static final String INVOKER_SUPER_NAME = OBJ;
    79     static final String INVOKER_SUPER_NAME = OBJ;
    79 
    80 
    80     /** Name of new class */
    81     /** Name of new class */
    81     private final String className;
    82     private final String className;
    82 
       
    83     /** Name of the source file (for stack trace printing). */
       
    84     private final String sourceFile;
       
    85 
    83 
    86     private final LambdaForm lambdaForm;
    84     private final LambdaForm lambdaForm;
    87     private final String     invokerName;
    85     private final String     invokerName;
    88     private final MethodType invokerType;
    86     private final MethodType invokerType;
    89 
    87 
   107             invokerName = invokerName.substring(p + 1);
   105             invokerName = invokerName.substring(p + 1);
   108         }
   106         }
   109         if (DUMP_CLASS_FILES) {
   107         if (DUMP_CLASS_FILES) {
   110             className = makeDumpableClassName(className);
   108             className = makeDumpableClassName(className);
   111         }
   109         }
   112         this.className  = CLASS_PREFIX + className;
   110         this.className  = className;
   113         this.sourceFile = "LambdaForm$" + className;
       
   114         this.lambdaForm = lambdaForm;
   111         this.lambdaForm = lambdaForm;
   115         this.invokerName = invokerName;
   112         this.invokerName = invokerName;
   116         this.invokerType = invokerType;
   113         this.invokerType = invokerType;
   117         this.localsMap = new int[localsMapSize+1]; // last entry of localsMap is count of allocated local slots
   114         this.localsMap = new int[localsMapSize+1]; // last entry of localsMap is count of allocated local slots
   118         this.localClasses = new Class<?>[localsMapSize+1];
   115         this.localClasses = new Class<?>[localsMapSize+1];
   128         }
   125         }
   129     }
   126     }
   130 
   127 
   131     /** For generating customized code for a single LambdaForm. */
   128     /** For generating customized code for a single LambdaForm. */
   132     private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
   129     private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) {
   133         this(className, form.debugName, form, invokerType);
   130         this(className, form.lambdaName(), form, invokerType);
   134     }
   131     }
   135 
   132 
   136     /** For generating customized code for a single LambdaForm. */
   133     /** For generating customized code for a single LambdaForm. */
   137     InvokerBytecodeGenerator(String className, String invokerName,
   134     InvokerBytecodeGenerator(String className, String invokerName,
   138             LambdaForm form, MethodType invokerType) {
   135             LambdaForm form, MethodType invokerType) {
   171             DUMP_CLASS_FILES_COUNTERS = null;
   168             DUMP_CLASS_FILES_COUNTERS = null;
   172             DUMP_CLASS_FILES_DIR = null;
   169             DUMP_CLASS_FILES_DIR = null;
   173         }
   170         }
   174     }
   171     }
   175 
   172 
       
   173     private void maybeDump(final byte[] classFile) {
       
   174         if (DUMP_CLASS_FILES) {
       
   175             maybeDump(CLASS_PREFIX + className, classFile);
       
   176         }
       
   177     }
       
   178 
       
   179     // Also used from BoundMethodHandle
   176     static void maybeDump(final String className, final byte[] classFile) {
   180     static void maybeDump(final String className, final byte[] classFile) {
   177         if (DUMP_CLASS_FILES) {
   181         if (DUMP_CLASS_FILES) {
   178             java.security.AccessController.doPrivileged(
   182             java.security.AccessController.doPrivileged(
   179             new java.security.PrivilegedAction<>() {
   183             new java.security.PrivilegedAction<>() {
   180                 public Void run() {
   184                 public Void run() {
   304      * Set up class file generation.
   308      * Set up class file generation.
   305      */
   309      */
   306     private ClassWriter classFilePrologue() {
   310     private ClassWriter classFilePrologue() {
   307         final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
   311         final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
   308         cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
   312         cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
   309         cw.visit(Opcodes.V1_8, NOT_ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER, className, null, INVOKER_SUPER_NAME, null);
   313         cw.visit(Opcodes.V1_8, NOT_ACC_PUBLIC + Opcodes.ACC_FINAL + Opcodes.ACC_SUPER,
   310         cw.visitSource(sourceFile, null);
   314                 CLASS_PREFIX + className, null, INVOKER_SUPER_NAME, null);
       
   315         cw.visitSource(SOURCE_PREFIX + className, null);
   311         return cw;
   316         return cw;
   312     }
   317     }
   313 
   318 
   314     private void methodPrologue() {
   319     private void methodPrologue() {
   315         String invokerDesc = invokerType.toMethodDescriptorString();
   320         String invokerDesc = invokerType.toMethodDescriptorString();
   615                     shortenSignature(basicTypeSignature(type)) + (resolvedMember != null ? " (success)" : " (fail)") );
   620                     shortenSignature(basicTypeSignature(type)) + (resolvedMember != null ? " (success)" : " (fail)") );
   616         }
   621         }
   617         return resolvedMember;
   622         return resolvedMember;
   618     }
   623     }
   619 
   624 
   620     private static MemberName lookupPregenerated(LambdaForm form) {
   625     private static MemberName lookupPregenerated(LambdaForm form, MethodType invokerType) {
   621         if (form.customized != null) {
   626         if (form.customized != null) {
   622             // No pre-generated version for customized LF
   627             // No pre-generated version for customized LF
   623             return null;
   628             return null;
   624         }
   629         }
   625         MethodType invokerType = form.methodType();
       
   626         String name = form.kind.methodName;
   630         String name = form.kind.methodName;
   627         switch (form.kind) {
   631         switch (form.kind) {
   628             case BOUND_REINVOKER: {
   632             case BOUND_REINVOKER: {
   629                 name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature();
   633                 name = name + "_" + BoundMethodHandle.speciesData(form).fieldSignature();
   630                 return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
   634                 return resolveFrom(name, invokerType, DelegatingMethodHandle.Holder.class);
   668 
   672 
   669     /**
   673     /**
   670      * Generate customized bytecode for a given LambdaForm.
   674      * Generate customized bytecode for a given LambdaForm.
   671      */
   675      */
   672     static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
   676     static MemberName generateCustomizedCode(LambdaForm form, MethodType invokerType) {
   673         MemberName pregenerated = lookupPregenerated(form);
   677         MemberName pregenerated = lookupPregenerated(form, invokerType);
   674         if (pregenerated != null)  return pregenerated; // pre-generated bytecode
   678         if (pregenerated != null)  return pregenerated; // pre-generated bytecode
   675 
   679 
   676         InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
   680         InvokerBytecodeGenerator g = new InvokerBytecodeGenerator("MH", form, invokerType);
   677         return g.loadMethod(g.generateCustomizedCodeBytes());
   681         return g.loadMethod(g.generateCustomizedCodeBytes());
   678     }
   682     }
   718         classFilePrologue();
   722         classFilePrologue();
   719         addMethod();
   723         addMethod();
   720         bogusMethod(lambdaForm);
   724         bogusMethod(lambdaForm);
   721 
   725 
   722         final byte[] classFile = toByteArray();
   726         final byte[] classFile = toByteArray();
   723         maybeDump(className, classFile);
   727         maybeDump(classFile);
   724         return classFile;
   728         return classFile;
   725     }
   729     }
   726 
   730 
   727     void setClassWriter(ClassWriter cw) {
   731     void setClassWriter(ClassWriter cw) {
   728         this.cw = cw;
   732         this.cw = cw;
   906         java.util.Arrays.class,
   910         java.util.Arrays.class,
   907         jdk.internal.misc.Unsafe.class
   911         jdk.internal.misc.Unsafe.class
   908         //MethodHandle.class already covered
   912         //MethodHandle.class already covered
   909     };
   913     };
   910 
   914 
   911     static boolean isStaticallyInvocable(NamedFunction[] functions) {
   915     static boolean isStaticallyInvocable(NamedFunction ... functions) {
   912         for (NamedFunction nf : functions) {
   916         for (NamedFunction nf : functions) {
   913             if (!isStaticallyInvocable(nf.member())) {
   917             if (!isStaticallyInvocable(nf.member())) {
   914                 return false;
   918                 return false;
   915             }
   919             }
   916         }
   920         }
  1759 
  1763 
  1760         methodEpilogue();
  1764         methodEpilogue();
  1761         bogusMethod(invokerType);
  1765         bogusMethod(invokerType);
  1762 
  1766 
  1763         final byte[] classFile = cw.toByteArray();
  1767         final byte[] classFile = cw.toByteArray();
  1764         maybeDump(className, classFile);
  1768         maybeDump(classFile);
  1765         return classFile;
  1769         return classFile;
  1766     }
  1770     }
  1767 
  1771 
  1768     /**
  1772     /**
  1769      * Generate bytecode for a NamedFunction invoker.
  1773      * Generate bytecode for a NamedFunction invoker.
  1827 
  1831 
  1828         methodEpilogue();
  1832         methodEpilogue();
  1829         bogusMethod(dstType);
  1833         bogusMethod(dstType);
  1830 
  1834 
  1831         final byte[] classFile = cw.toByteArray();
  1835         final byte[] classFile = cw.toByteArray();
  1832         maybeDump(className, classFile);
  1836         maybeDump(classFile);
  1833         return classFile;
  1837         return classFile;
  1834     }
  1838     }
  1835 
  1839 
  1836     /**
  1840     /**
  1837      * Emit a bogus method that just loads some string constants. This is to get the constants into the constant pool
  1841      * Emit a bogus method that just loads some string constants. This is to get the constants into the constant pool