1 /*
  2  * Copyright (c) 2023, 2024, 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.JavaLangReflectAccess;
 29 import jdk.internal.access.SharedSecrets;
 30 import jdk.internal.misc.Unsafe;
 31 import jdk.internal.vm.annotation.IntrinsicCandidate;
 32 
 33 import java.lang.reflect.Array;
 34 import java.lang.reflect.Field;
 35 
 36 /**
 37  * Utilities to access
 38  */
 39 public class ValueClass {
 40     private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 41     private static final JavaLangReflectAccess JLRA = SharedSecrets.getJavaLangReflectAccess();
 42 
 43     /**
 44      * {@return true if the given {@code Class} object is implicitly constructible}
 45      */
 46     public static native boolean isImplicitlyConstructible(Class<?> cls);
 47 
 48     /**
 49      * {@return the default value of the given value class type}
 50      *
 51      * @throws IllegalArgumentException if {@code cls} is not a
 52      *         value class type or is not annotated with
 53      *         {@link jdk.internal.vm.annotation.ImplicitlyConstructible}
 54      */
 55     public static <T> T zeroInstance(Class<T> cls) {
 56         if (!cls.isValue()) {
 57             throw new IllegalArgumentException(cls.getName() + " not a value class");
 58         }
 59         if (!isImplicitlyConstructible(cls)) {
 60             throw new IllegalArgumentException(cls.getName() + " not implicitly constructible");
 61         }
 62         UNSAFE.ensureClassInitialized(cls);
 63         return UNSAFE.uninitializedDefaultValue(cls);
 64     }
 65 
 66     /**
 67      * {@return {@code CheckedType} representing the type of the given field}
 68      */
 69     public static CheckedType checkedType(Field f) {
 70         return JLRA.isNullRestrictedField(f) ? NullRestrictedCheckedType.of(f.getType())
 71                                              : NormalCheckedType.of(f.getType());
 72     }
 73 
 74     /**
 75      * {@return {@code CheckedType} representing the component type of the given array}
 76      */
 77     public static CheckedType componentCheckedType(Object array) {
 78         Class<?> componentType = array.getClass().getComponentType();
 79         return isNullRestrictedArray(array) ? NullRestrictedCheckedType.of(componentType)
 80                                             : NormalCheckedType.of(componentType);
 81     }
 82 
 83     /**
 84      * Allocate an array of a value class type with components that behave in
 85      * the same way as a {@link jdk.internal.vm.annotation.NullRestricted}
 86      * field.
 87      * <p>
 88      * Because these behaviors are not specified by Java SE, arrays created with
 89      * this method should only be used by internal JDK code for experimental
 90      * purposes and should not affect user-observable outcomes.
 91      *
 92      * @throws IllegalArgumentException if {@code componentType} is not a
 93      *         value class type or is not annotated with
 94      *         {@link jdk.internal.vm.annotation.ImplicitlyConstructible}
 95      */
 96     @SuppressWarnings("unchecked")
 97     public static Object[] newArrayInstance(CheckedType componentType, int length) {
 98         if (componentType instanceof NullRestrictedCheckedType) {
 99             return newNullRestrictedArray(componentType.boundingClass(), length);
100         } else {
101             return (Object[]) Array.newInstance(componentType.boundingClass(), length);
102         }
103     }
104 
105     /**
106      * Allocate an array of a value class type with components that behave in
107      * the same way as a {@link jdk.internal.vm.annotation.NullRestricted}
108      * field.
109      * <p>
110      * Because these behaviors are not specified by Java SE, arrays created with
111      * this method should only be used by internal JDK code for experimental
112      * purposes and should not affect user-observable outcomes.
113      *
114      * @throws IllegalArgumentException if {@code componentType} is not a
115      *         value class type or is not annotated with
116      *         {@link jdk.internal.vm.annotation.ImplicitlyConstructible}
117      */
118     @IntrinsicCandidate
119     public static native Object[] newNullRestrictedArray(Class<?> componentType,
120                                                          int length);
121 
122     /**
123      * {@return true if the given array is a null-restricted array}
124      */
125     public static native boolean isNullRestrictedArray(Object array);
126 }