1 /*
  2  * Copyright (c) 2023, 2026, 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.PreviewFeatures;
 31 import jdk.internal.misc.Unsafe;
 32 import jdk.internal.vm.annotation.IntrinsicCandidate;
 33 
 34 import java.lang.reflect.Field;
 35 import java.lang.reflect.Modifier;
 36 
 37 /**
 38  * Utilities to access package private methods of java.lang.Class and related reflection classes.
 39  */
 40 public final class ValueClass {
 41     private static final JavaLangReflectAccess JLRA = SharedSecrets.getJavaLangReflectAccess();
 42 
 43     /// {@return whether this field type may store value objects}
 44     /// This excludes primitives and includes Object.
 45     public static boolean isValueObjectCompatible(Class<?> fieldType) {
 46         return PreviewFeatures.isEnabled()
 47                 && !fieldType.isPrimitive() // non-primitive
 48                 && (!fieldType.isIdentity() || fieldType == Object.class); // AVC or Object
 49     }
 50 
 51     /// {@return whether an object of this exact class is a value object}
 52     /// This excludes abstract value classes and primitives.
 53     public static boolean isConcreteValueClass(Class<?> clazz) {
 54         return clazz.isValue() && !Modifier.isAbstract(clazz.getModifiers());
 55     }
 56 
 57     /// {@return whether a field of type `c` can be represented with a payload
 58     /// without oops}  For example, primitive type fields and value classes with
 59     /// all primitive fields recursively may be represented by a payload of a
 60     /// layout without oops.  Returns false if there is no flat layout for a
 61     /// field of type `c`.
 62     public static boolean hasBinaryPayload(Class<?> c) {
 63         // non-concrete value class type field always a reference
 64         if (!ValueClass.isConcreteValueClass(c))
 65             return c.isPrimitive();
 66         // Check the flat layout
 67         return Unsafe.getUnsafe().isFlatPayloadBinary(c);
 68     }
 69 
 70     /**
 71      * {@return {@code true} if the field is NullRestricted}
 72      */
 73     public static boolean isNullRestrictedField(Field f) {
 74         return JLRA.isNullRestrictedField(f);
 75     }
 76 
 77     /**
 78      * Allocate an array of a value class type with components that behave in
 79      * the same way as a {@link jdk.internal.vm.annotation.NullRestricted}
 80      * field.
 81      * <p>
 82      * Because these behaviors are not specified by Java SE, arrays created with
 83      * this method should only be used by internal JDK code for experimental
 84      * purposes and should not affect user-observable outcomes.
 85      *
 86      * @throws IllegalArgumentException if {@code componentType} is not a
 87      *                                  value class type.
 88      */
 89     @IntrinsicCandidate
 90     public static native Object[] newNullRestrictedAtomicArray(Class<?> componentType,
 91                                                                int length, Object initVal);
 92 
 93     @IntrinsicCandidate
 94     public static native Object[] newNullRestrictedNonAtomicArray(Class<?> componentType,
 95                                                                   int length, Object initVal);
 96 
 97     @IntrinsicCandidate
 98     public static native Object[] newNullableAtomicArray(Class<?> componentType,
 99                                                          int length);
100 
101     public static native Object[] newReferenceArray(Class<?> componentType,
102                                                     int length);
103 
104     /**
105      * {@return true if the given array is a flat array}
106      */
107     @IntrinsicCandidate
108     public static native boolean isFlatArray(Object array);
109 
110     public static Object[] copyOfSpecialArray(Object[] array, int newLength) {
111         if (newLength < 0) {
112             throw new NegativeArraySizeException("" + newLength);
113         }
114         return copyOfSpecialArray0(array, 0, newLength);
115     }
116 
117     public static Object[] copyOfRangeSpecialArray(Object[] array, int from, int to) {
118         int length = array.length;
119         if (from < 0 || from > length) {
120             throw new ArrayIndexOutOfBoundsException("source index " + from + " out of bounds for object array[" + length + "]");
121         }
122         if (from > to) {
123             throw new IllegalArgumentException(from + " > " + to);
124         }
125         return copyOfSpecialArray0(array, from, to);
126     }
127 
128     private static native Object[] copyOfSpecialArray0(Object[] array, int from, int to);
129 
130     /**
131      * {@return true if the given array is a null-restricted array}
132      */
133     @IntrinsicCandidate
134     public static native boolean isNullRestrictedArray(Object array);
135 
136     /**
137      * {@return true if the given array uses a layout designed for atomic accesses }
138      */
139     @IntrinsicCandidate
140     public static native boolean isAtomicArray(Object array);
141 }