< 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 /**
 51  * Helper class to assist the GenerateJLIClassesPlugin to get access to
 52  * generate classes ahead of time.
 53  */
 54 class GenerateJLIClassesHelper {
 55     // Map from DirectMethodHandle method type name to index to LambdaForms
 56     static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
 57             Map.of(

416             MethodType[] methodTypes, int[] types) {
417         ArrayList<LambdaForm> forms = new ArrayList<>();
418         ArrayList<String> names = new ArrayList<>();
419         for (int i = 0; i < methodTypes.length; i++) {
420             // invokeVirtual and invokeInterface must have a leading Object
421             // parameter, i.e., the receiver
422             if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
423                 if (methodTypes[i].parameterCount() < 1 ||
424                         methodTypes[i].parameterType(0) != Object.class) {
425                     throw new InternalError("Invalid method type for " +
426                             (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
427                             " DMH, needs at least two leading reference arguments: " +
428                             methodTypes[i]);
429                 }
430             }
431 
432             LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
433             forms.add(form);
434             names.add(form.kind.defaultLambdaName);
435         }
436         for (Wrapper wrapper : Wrapper.values()) {
437             int ftype = wrapper == Wrapper.VOID ? DirectMethodHandle.FT_CHECKED_REF : DirectMethodHandle.ftypeKind(wrapper.primitiveType());
438             for (byte b = DirectMethodHandle.AF_GETFIELD; b < DirectMethodHandle.AF_LIMIT; b++) {
439                 LambdaForm form = DirectMethodHandle
440                         .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
441                 if (form.kind == GENERIC)
442                     throw new InternalError(b + " non-volatile " + ftype);
443                 forms.add(form);
444                 names.add(form.kind.defaultLambdaName);
445                 // volatile
446                 form = DirectMethodHandle
447                         .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
448                 if (form.kind == GENERIC)
449                     throw new InternalError(b + " volatile " + ftype);
450                 forms.add(form);
451                 names.add(form.kind.defaultLambdaName);
452             }
453         }






























454         return generateCodeBytesForLFs(className,
455                 names.toArray(new String[0]),
456                 forms.toArray(new LambdaForm[0]));
457     }
458 
459     /**
460      * Returns a {@code byte[]} representation of a class implementing
461      * DelegatingMethodHandles of each {@code MethodType} kind in the
462      * {@code methodTypes} argument.
463      */
464     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
465             MethodType[] methodTypes) {
466 
467         HashSet<MethodType> dedupSet = new HashSet<>();
468         ArrayList<LambdaForm> forms = new ArrayList<>();
469         ArrayList<String> names = new ArrayList<>();
470         for (int i = 0; i < methodTypes.length; i++) {
471             // generate methods representing the DelegatingMethodHandle
472             if (dedupSet.add(methodTypes[i])) {
473                 // 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 /**
 52  * Helper class to assist the GenerateJLIClassesPlugin to get access to
 53  * generate classes ahead of time.
 54  */
 55 class GenerateJLIClassesHelper {
 56     // Map from DirectMethodHandle method type name to index to LambdaForms
 57     static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
 58             Map.of(

417             MethodType[] methodTypes, int[] types) {
418         ArrayList<LambdaForm> forms = new ArrayList<>();
419         ArrayList<String> names = new ArrayList<>();
420         for (int i = 0; i < methodTypes.length; i++) {
421             // invokeVirtual and invokeInterface must have a leading Object
422             // parameter, i.e., the receiver
423             if (types[i] == LF_INVVIRTUAL || types[i] == LF_INVINTERFACE) {
424                 if (methodTypes[i].parameterCount() < 1 ||
425                         methodTypes[i].parameterType(0) != Object.class) {
426                     throw new InternalError("Invalid method type for " +
427                             (types[i] == LF_INVVIRTUAL ? "invokeVirtual" : "invokeInterface") +
428                             " DMH, needs at least two leading reference arguments: " +
429                             methodTypes[i]);
430                 }
431             }
432 
433             LambdaForm form = DirectMethodHandle.makePreparedLambdaForm(methodTypes[i], types[i]);
434             forms.add(form);
435             names.add(form.kind.defaultLambdaName);
436         }
437         record FieldLfToken(byte formOp, int ftypeKind) {}
438         List<FieldLfToken> tokens = new ArrayList<>();
439         for (int i = 0; i <= DirectMethodHandle.FT_CHECKED_REF; i++) {
440             for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
441                 tokens.add(new FieldLfToken(formOp, i));











442             }
443         }
444         for (int i : new int[] {DirectMethodHandle.FT_UNCHECKED_NR_REF, DirectMethodHandle.FT_CHECKED_NR_REF}) {
445             for (byte formOp = DirectMethodHandle.AF_GETFIELD; formOp < DirectMethodHandle.AF_LIMIT; formOp++) {
446                 boolean isGetter = (formOp & 1) == (DirectMethodHandle.AF_GETFIELD & 1);
447                 if (!isGetter) {
448                     tokens.add(new FieldLfToken(formOp, i));
449                 }
450             }
451         }
452         // Only legal flat combinations; no static
453         tokens.add(new FieldLfToken(DirectMethodHandle.AF_GETFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
454         tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NULLABLE_FLAT));
455         tokens.add(new FieldLfToken(DirectMethodHandle.AF_PUTFIELD, DirectMethodHandle.FT_NR_FLAT));
456         // Compile
457         for (var token : tokens) {
458             byte b = token.formOp;
459             int ftype = token.ftypeKind;
460             LambdaForm form = DirectMethodHandle
461                     .makePreparedFieldLambdaForm(b, /*isVolatile*/false, ftype);
462             if (form.kind == GENERIC)
463                 throw new InternalError(b + " non-volatile " + ftype);
464             forms.add(form);
465             names.add(form.kind.defaultLambdaName);
466             // volatile
467             form = DirectMethodHandle
468                     .makePreparedFieldLambdaForm(b, /*isVolatile*/true, ftype);
469             if (form.kind == GENERIC)
470                 throw new InternalError(b + " volatile " + ftype);
471             forms.add(form);
472             names.add(form.kind.defaultLambdaName);
473         }
474         return generateCodeBytesForLFs(className,
475                 names.toArray(new String[0]),
476                 forms.toArray(new LambdaForm[0]));
477     }
478 
479     /**
480      * Returns a {@code byte[]} representation of a class implementing
481      * DelegatingMethodHandles of each {@code MethodType} kind in the
482      * {@code methodTypes} argument.
483      */
484     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
485             MethodType[] methodTypes) {
486 
487         HashSet<MethodType> dedupSet = new HashSet<>();
488         ArrayList<LambdaForm> forms = new ArrayList<>();
489         ArrayList<String> names = new ArrayList<>();
490         for (int i = 0; i < methodTypes.length; i++) {
491             // generate methods representing the DelegatingMethodHandle
492             if (dedupSet.add(methodTypes[i])) {
493                 // reinvokers are variant with the associated SpeciesData
< prev index next >