< prev index next >

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

Print this page

 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 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 sun.invoke.util.Wrapper;
 29 
 30 import java.lang.classfile.ClassFile;
 31 import java.lang.classfile.attribute.SourceFileAttribute;
 32 import java.lang.constant.ClassDesc;
 33 import java.util.ArrayList;
 34 import java.util.HashSet;

 35 import java.util.Map;
 36 import java.util.Objects;
 37 import java.util.Set;
 38 import java.util.TreeMap;
 39 import java.util.TreeSet;
 40 import java.util.stream.Stream;
 41 
 42 import static java.lang.classfile.ClassFile.*;
 43 import static java.lang.invoke.LambdaForm.BasicType.*;
 44 import static java.lang.invoke.LambdaForm.Kind.*;
 45 import static java.lang.invoke.MethodTypeForm.*;
 46 
 47 /**
 48  * Helper class to assist the GenerateJLIClassesPlugin to get access to
 49  * generate classes ahead of time.
 50  */
 51 class GenerateJLIClassesHelper {
 52     // Map from DirectMethodHandle method type name to index to LambdaForms
 53     static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
 54             Map.of(

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






























450         return generateCodeBytesForLFs(className,
451                 names.toArray(new String[0]),
452                 forms.toArray(new LambdaForm[0]));
453     }
454 
455     /**
456      * Returns a {@code byte[]} representation of a class implementing
457      * DelegatingMethodHandles of each {@code MethodType} kind in the
458      * {@code methodTypes} argument.
459      */
460     static byte[] generateDelegatingMethodHandleHolderClassBytes(String className,
461             MethodType[] methodTypes) {
462 
463         HashSet<MethodType> dedupSet = new HashSet<>();
464         ArrayList<LambdaForm> forms = new ArrayList<>();
465         ArrayList<String> names = new ArrayList<>();
466         for (int i = 0; i < methodTypes.length; i++) {
467             // generate methods representing the DelegatingMethodHandle
468             if (dedupSet.add(methodTypes[i])) {
469                 // reinvokers are variant with the associated SpeciesData

 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 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 sun.invoke.util.Wrapper;
 29 
 30 import java.lang.classfile.ClassFile;
 31 import java.lang.classfile.attribute.SourceFileAttribute;
 32 import java.lang.constant.ClassDesc;
 33 import java.util.ArrayList;
 34 import java.util.HashSet;
 35 import java.util.List;
 36 import java.util.Map;
 37 import java.util.Objects;
 38 import java.util.Set;
 39 import java.util.TreeMap;
 40 import java.util.TreeSet;
 41 import java.util.stream.Stream;
 42 
 43 import static java.lang.classfile.ClassFile.*;
 44 import static java.lang.invoke.LambdaForm.BasicType.*;
 45 import static java.lang.invoke.LambdaForm.Kind.*;
 46 import static java.lang.invoke.MethodTypeForm.*;
 47 
 48 /**
 49  * Helper class to assist the GenerateJLIClassesPlugin to get access to
 50  * generate classes ahead of time.
 51  */
 52 class GenerateJLIClassesHelper {
 53     // Map from DirectMethodHandle method type name to index to LambdaForms
 54     static final Map<String, Integer> DMH_METHOD_TYPE_MAP =
 55             Map.of(

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











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