1 /*
  2  * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 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 jdk.internal.value;
 27 
 28 import jdk.internal.access.JavaLangAccess;
 29 import jdk.internal.access.SharedSecrets;
 30 import jdk.internal.vm.annotation.IntrinsicCandidate;
 31 
 32 import java.lang.constant.ClassDesc;
 33 
 34 /**
 35  * Utilities to access Primitive Classes as described in JEP 401.
 36  */
 37 public class PrimitiveClass {
 38 
 39     /**
 40      * ACC_PRIMITIVE modifier defined by JEP 401. Subject to change.
 41      */
 42     public static final int PRIMITIVE_CLASS = 0x00000800;
 43 
 44     private static final JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess();
 45 
 46 
 47     /**
 48      * Returns a {@code Class} object representing the primary type
 49      * of this class or interface.
 50      * <p>
 51      * If this {@code Class} object represents a primitive type or an array type,
 52      * then this method returns this class.
 53      * <p>
 54      * If this {@code Class} object represents a {@linkplain #isPrimitiveClass(Class)
 55      * primitive class}, then this method returns the <em>primitive reference type</em>
 56      * type of this primitive class.
 57      * <p>
 58      * Otherwise, this {@code Class} object represents a non-primitive class or interface
 59      * and this method returns this class.
 60      *
 61      * @param aClass a class
 62      * @return the {@code Class} representing the primary type of
 63      *         this class or interface
 64      * @since Valhalla
 65      */
 66     @IntrinsicCandidate
 67     public static Class<?> asPrimaryType(Class<?> aClass) {
 68         return javaLangAccess.asPrimaryType(aClass);
 69     }
 70 
 71     /**
 72      * Returns a {@code Class} object representing the <em>primitive value type</em>
 73      * of this class if this class is a {@linkplain #isPrimitiveClass(Class)}  primitive class}.
 74      *
 75      * @apiNote Alternatively, this method returns null if this class is not
 76      *          a primitive class rather than throwing UOE.
 77      *
 78      * @param aClass a class
 79      * @return the {@code Class} representing the {@linkplain #isPrimitiveValueType(Class)
 80      * primitive value type} of this class if this class is a primitive class
 81      * @throws UnsupportedOperationException if this class or interface
 82      *         is not a primitive class
 83      * @since Valhalla
 84      */
 85     @SuppressWarnings("unchecked")
 86     @IntrinsicCandidate
 87     public static Class<?> asValueType(Class<?> aClass) {
 88         return javaLangAccess.asValueType(aClass);
 89     }
 90 
 91     /**
 92      * Returns {@code true} if this {@code Class} object represents the primary type
 93      * of this class or interface.
 94      * <p>
 95      * If this {@code Class} object represents a primitive type or an array type,
 96      * then this method returns {@code true}.
 97      * <p>
 98      * If this {@code Class} object represents a {@linkplain #isPrimitiveClass(Class)
 99      * primitive}, then this method returns {@code true} if this {@code Class}
100      * object represents a primitive reference type, or returns {@code false}
101      * if this {@code Class} object represents a primitive value type.
102      * <p>
103      * If this {@code Class} object represents a non-primitive class or interface,
104      * then this method returns {@code true}.
105      *
106      * @param aClass a class
107      * @return {@code true} if this {@code Class} object represents
108      * the primary type of this class or interface
109      * @since Valhalla
110      */
111     public static boolean isPrimaryType(Class<?> aClass) {
112         return javaLangAccess.isPrimaryType(aClass);
113     }
114 
115     /**
116      * Returns {@code true} if this {@code Class} object represents
117      * a {@linkplain #isPrimitiveClass(Class)  primitive} value type.
118      *
119      * @return {@code true} if this {@code Class} object represents
120      * the value type of a primitive class
121      * @since Valhalla
122      */
123     public static boolean isPrimitiveValueType(Class<?> aClass) {
124         return javaLangAccess.isPrimitiveValueType(aClass);
125     }
126 
127     /**
128      * Returns {@code true} if this class is a primitive class.
129      * <p>
130      * Each primitive class has a {@linkplain #isPrimaryType(Class)  primary type}
131      * representing the <em>primitive reference type</em> and a
132      * {@linkplain #isPrimitiveValueType(Class)  secondary type} representing
133      * the <em>primitive value type</em>.  The primitive reference type
134      * and primitive value type can be obtained by calling the
135      * {@link #asPrimaryType(Class)} and {@link PrimitiveClass#asValueType} method
136      * of a primitive class respectively.
137      * <p>
138      * A primitive class is a {@linkplain Class#isValue() value class}.
139      *
140      * @param aClass a class
141      * @return {@code true} if this class is a primitive class, otherwise {@code false}
142      * @see Class#isValue()
143      * @see #asPrimaryType(Class)
144      * @see #asValueType(Class)
145      * @since Valhalla
146      */
147     public static boolean isPrimitiveClass(Class<?> aClass) {
148         return javaLangAccess.isPrimitiveClass(aClass);
149     }
150 
151     /**
152      * Returns whether this {@linkplain ClassDesc} describes a
153      * {@linkplain #isPrimitiveValueType(Class)}  primitive value type}.
154      *
155      * @return whether this {@linkplain ClassDesc} describes a primitive value type.
156      * @since Valhalla
157      */
158     public static boolean isPrimitiveValueClassDesc(ClassDesc classDesc) {
159         return classDesc.descriptorString().startsWith("Q");
160     }
161 }