< prev index next >

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

Print this page

 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.invoke;
 27 
 28 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
 29 import sun.invoke.util.Wrapper;
 30 
 31 import java.lang.classfile.Annotation;
 32 import java.lang.classfile.ClassFile;
 33 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
 34 import java.lang.classfile.attribute.SourceFileAttribute;
 35 import java.lang.constant.ClassDesc;
 36 import java.util.ArrayList;
 37 import java.util.HashSet;

 38 import java.util.Map;
 39 import java.util.Objects;
 40 import java.util.Set;
 41 import java.util.TreeMap;
 42 import java.util.TreeSet;
 43 import java.util.stream.Stream;
 44 
 45 import static java.lang.classfile.ClassFile.*;
 46 import static java.lang.invoke.LambdaForm.BasicType.*;
 47 import static java.lang.invoke.LambdaForm.Kind.*;
 48 import static java.lang.invoke.MethodTypeForm.*;
 49 
 50 /// Generates bound method handle species classes, and classes with methods that
 51 /// hold compiled lambda form bytecode ahead of time, so certain lambda forms
 52 /// no longer need to spin classes because they can find existing bytecode.
 53 /// Bytecode pre-generation reduces static initialization costs, footprint costs,
 54 /// and circular dependencies that may arise if a class is generated per
 55 /// LambdaForm by [InvokerBytecodeGenerator].
 56 ///
 57 /// Since lambda forms and bound method handle species are closely tied to

487             MethodType[] methodTypes, int[] types) {
488         ArrayList<LambdaForm> forms = new ArrayList<>();
489         ArrayList<String> names = new ArrayList<>();
490         for (int i = 0; i < methodTypes.length; i++) {
491             // invokeVirtual and invokeInterface must have a leading Object
492             // parameter, i.e., the receiver
493             if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
494                 if (methodTypes[i].parameterCount() < 1 ||
495                         methodTypes[i].parameterType(0) != Object.class) {
496                     throw new InternalError("Invalid method type for " +
497                             (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
498                             " DMH, needs at least two leading reference arguments: " +
499                             methodTypes[i]);
500                 }
501             }
502 
503             LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
504             forms.add(form);
505             names.add(form.kind.defaultLambdaName);
506         }
507         for (Wrapper wrapper : Wrapper.values()) {
508             int ftype = wrapper == Wrapper.VOID ? DirectMethodHandle.FT_CHECKED_REF : DirectMethodHandle.ftypeKind(wrapper.primitiveType());
509             for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
510                 LambdaForm form = DirectMethodHandle
511                         .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
512                 if (form.kind == GENERIC)
513                     throw new InternalError(b + " non-volatile " + ftype);
514                 forms.add(form);
515                 names.add(form.kind.defaultLambdaName);
516                 // volatile
517                 form = DirectMethodHandle
518                         .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
519                 if (form.kind == GENERIC)
520                     throw new InternalError(b + " volatile " + ftype);
521                 forms.add(form);
522                 names.add(form.kind.defaultLambdaName);
523             }
524         }






























525         return generateCodeBytesForLFs(className,
526                 names.toArray(new String[0]),
527                 forms.toArray(new LambdaForm[0]));
528     }
529 
530     /**
531      * Returns a {@code byte[]} representation of a class implementing
532      * DelegatingMethodHandles of each {@code MethodType} kind in the
533      * {@code methodTypes} argument.
534      */
535     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
536             MethodType[] methodTypes) {
537 
538         HashSet<MethodType> dedupSet = new HashSet<>();
539         ArrayList<LambdaForm> forms = new ArrayList<>();
540         ArrayList<String> names = new ArrayList<>();
541         for (int i = 0; i < methodTypes.length; i++) {
542             // generate methods representing the DelegatingMethodHandle
543             if (dedupSet.add(methodTypes[i])) {
544                 // reinvokers are variant with the associated SpeciesData

 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang.invoke;
 27 
 28 import jdk.internal.vm.annotation.AOTSafeClassInitializer;
 29 import sun.invoke.util.Wrapper;
 30 
 31 import java.lang.classfile.Annotation;
 32 import java.lang.classfile.ClassFile;
 33 import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
 34 import java.lang.classfile.attribute.SourceFileAttribute;
 35 import java.lang.constant.ClassDesc;
 36 import java.util.ArrayList;
 37 import java.util.HashSet;
 38 import java.util.List;
 39 import java.util.Map;
 40 import java.util.Objects;
 41 import java.util.Set;
 42 import java.util.TreeMap;
 43 import java.util.TreeSet;
 44 import java.util.stream.Stream;
 45 
 46 import static java.lang.classfile.ClassFile.*;
 47 import static java.lang.invoke.LambdaForm.BasicType.*;
 48 import static java.lang.invoke.LambdaForm.Kind.*;
 49 import static java.lang.invoke.MethodTypeForm.*;
 50 
 51 /// Generates bound method handle species classes, and classes with methods that
 52 /// hold compiled lambda form bytecode ahead of time, so certain lambda forms
 53 /// no longer need to spin classes because they can find existing bytecode.
 54 /// Bytecode pre-generation reduces static initialization costs, footprint costs,
 55 /// and circular dependencies that may arise if a class is generated per
 56 /// LambdaForm by [InvokerBytecodeGenerator].
 57 ///
 58 /// Since lambda forms and bound method handle species are closely tied to

488             MethodType[] methodTypes, int[] types) {
489         ArrayList<LambdaForm> forms = new ArrayList<>();
490         ArrayList<String> names = new ArrayList<>();
491         for (int i = 0; i < methodTypes.length; i++) {
492             // invokeVirtual and invokeInterface must have a leading Object
493             // parameter, i.e., the receiver
494             if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
495                 if (methodTypes[i].parameterCount() < 1 ||
496                         methodTypes[i].parameterType(0) != Object.class) {
497                     throw new InternalError("Invalid method type for " +
498                             (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
499                             " DMH, needs at least two leading reference arguments: " +
500                             methodTypes[i]);
501                 }
502             }
503 
504             LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
505             forms.add(form);
506             names.add(form.kind.defaultLambdaName);
507         }
508         record FieldLfToken(byte formOp, int ftypeKind) {}
509         List<FieldLfToken> tokens = new ArrayList<>();
510         for (int i = 0; i <= DirectMethodHandle.FT_CHECKED_REF; i++) {
511             for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
512                 tokens.add(new FieldLfToken(formOp, i));











513             }
514         }
515         for (int i : new int[] {DirectMethodHandle.FT_UNCHECKED_NR_REF, DirectMethodHandle.FT_CHECKED_NR_REF}) {
516             for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
517                 boolean isGetter = (formOp & 1) == (DirectMethodHandle.AF_GETFIELD & 1);
518                 if (!isGetter) {
519                     tokens.add(new FieldLfToken(formOp, i));
520                 }
521             }
522         }
523         // Only legal flat combinations; no static
524         tokens.add(new FieldLfToken(DirectMethodHandle.AF_GETFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
525         tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
526         tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NR_FLAT));
527         // Compile
528         for (var token : tokens) {
529             byte b = token.formOp;
530             int ftype = token.ftypeKind;
531             LambdaForm form = DirectMethodHandle
532                     .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
533             if (form.kind == GENERIC)
534                 throw new InternalError(b + " non-volatile " + ftype);
535             forms.add(form);
536             names.add(form.kind.defaultLambdaName);
537             // volatile
538             form = DirectMethodHandle
539                     .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
540             if (form.kind == GENERIC)
541                 throw new InternalError(b + " volatile " + ftype);
542             forms.add(form);
543             names.add(form.kind.defaultLambdaName);
544         }
545         return generateCodeBytesForLFs(className,
546                 names.toArray(new String[0]),
547                 forms.toArray(new LambdaForm[0]));
548     }
549 
550     /**
551      * Returns a {@code byte[]} representation of a class implementing
552      * DelegatingMethodHandles of each {@code MethodType} kind in the
553      * {@code methodTypes} argument.
554      */
555     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
556             MethodType[] methodTypes) {
557 
558         HashSet<MethodType> dedupSet = new HashSet<>();
559         ArrayList<LambdaForm> forms = new ArrayList<>();
560         ArrayList<String> names = new ArrayList<>();
561         for (int i = 0; i < methodTypes.length; i++) {
562             // generate methods representing the DelegatingMethodHandle
563             if (dedupSet.add(methodTypes[i])) {
564                 // reinvokers are variant with the associated SpeciesData
< prev index next >