1 /*
2 * Copyright (c) 2014, 2025, 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 java.lang.invoke;
27
28 import jdk.internal.misc.CDS;
29 import sun.invoke.util.Wrapper;
30
31 import java.lang.foreign.MemoryLayout;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.Method;
35 import java.lang.reflect.Modifier;
36 import java.nio.ByteOrder;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Objects;
40 import java.util.stream.Stream;
41
42 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
43 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
44 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
45 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
46
47 final class VarHandles {
48
49 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
50 if (!f.isStatic()) {
51 long foffset = MethodHandleNatives.objectFieldOffset(f);
52 Class<?> type = f.getFieldType();
53 if (!type.isPrimitive()) {
54 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
55 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
56 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));
57 }
58 else if (type == boolean.class) {
59 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
60 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
61 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
62 }
63 else if (type == byte.class) {
64 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
65 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
66 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
67 }
68 else if (type == short.class) {
69 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
70 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
71 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
72 }
73 else if (type == char.class) {
74 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
75 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
76 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
77 }
78 else if (type == int.class) {
79 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
80 ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
81 : new VarHandleInts.FieldInstanceReadWrite(refc, foffset));
82 }
83 else if (type == long.class) {
84 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
85 ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
86 : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset));
87 }
88 else if (type == float.class) {
89 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
90 ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
91 : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset));
92 }
93 else if (type == double.class) {
94 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
95 ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
96 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
97 }
98 else {
99 throw new UnsupportedOperationException();
100 }
101 }
102 else {
103 Class<?> decl = f.getDeclaringClass();
104 var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
105 return maybeAdapt((UNSAFE.shouldBeInitialized(decl) || CDS.needsClassInitBarrier(decl))
106 ? new LazyInitializingVarHandle(vh, decl)
107 : vh);
108 }
109 }
110
111 static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
112 Object base = MethodHandleNatives.staticFieldBase(f);
113 long foffset = MethodHandleNatives.staticFieldOffset(f);
114 Class<?> type = f.getFieldType();
115 if (!type.isPrimitive()) {
116 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
117 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
118 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));
119 }
120 else if (type == boolean.class) {
121 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
122 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
123 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
124 }
125 else if (type == byte.class) {
126 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
127 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
128 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
129 }
130 else if (type == short.class) {
131 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
132 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
133 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
134 }
135 else if (type == char.class) {
136 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
137 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
138 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));
139 }
140 else if (type == int.class) {
141 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
142 ? new VarHandleInts.FieldStaticReadOnly(decl, base, foffset)
143 : new VarHandleInts.FieldStaticReadWrite(decl, base, foffset));
144 }
145 else if (type == long.class) {
146 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
147 ? new VarHandleLongs.FieldStaticReadOnly(decl, base, foffset)
148 : new VarHandleLongs.FieldStaticReadWrite(decl, base, foffset));
149 }
150 else if (type == float.class) {
151 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
152 ? new VarHandleFloats.FieldStaticReadOnly(decl, base, foffset)
153 : new VarHandleFloats.FieldStaticReadWrite(decl, base, foffset));
154 }
155 else if (type == double.class) {
156 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
157 ? new VarHandleDoubles.FieldStaticReadOnly(decl, base, foffset)
158 : new VarHandleDoubles.FieldStaticReadWrite(decl, base, foffset));
159 }
160 else {
161 throw new UnsupportedOperationException();
162 }
163 }
164
165 // Required by instance field handles
166 static Field getFieldFromReceiverAndOffset(Class<?> receiverType,
167 long offset,
168 Class<?> fieldType) {
169 // The receiver may be a referenced class different from the declaring class
170 for (var declaringClass = receiverType; declaringClass != null; declaringClass = declaringClass.getSuperclass()) {
171 for (Field f : declaringClass.getDeclaredFields()) {
172 if (Modifier.isStatic(f.getModifiers())) continue;
173
174 if (offset == UNSAFE.objectFieldOffset(f)) {
175 assert f.getType() == fieldType;
176 return f;
177 }
178 }
179 }
180 throw new InternalError("Field not found at offset");
181 }
182
183 // Required by instance static field handles
184 static Field getStaticFieldFromBaseAndOffset(Class<?> declaringClass,
185 long offset,
186 Class<?> fieldType) {
187 for (Field f : declaringClass.getDeclaredFields()) {
188 if (!Modifier.isStatic(f.getModifiers())) continue;
189
190 if (offset == UNSAFE.staticFieldOffset(f)) {
191 assert f.getType() == fieldType;
192 return f;
193 }
194 }
195 throw new InternalError("Static field not found at offset");
196 }
197
198 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
199 if (!arrayClass.isArray())
200 throw new IllegalArgumentException("not an array: " + arrayClass);
201
202 Class<?> componentType = arrayClass.getComponentType();
203
204 int aoffset = (int) UNSAFE.arrayBaseOffset(arrayClass);
205 int ascale = UNSAFE.arrayIndexScale(arrayClass);
206 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
207
208 if (!componentType.isPrimitive()) {
209 return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));
210 }
211 else if (componentType == boolean.class) {
212 return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
213 }
214 else if (componentType == byte.class) {
215 return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
216 }
217 else if (componentType == short.class) {
218 return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
219 }
220 else if (componentType == char.class) {
221 return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
222 }
223 else if (componentType == int.class) {
224 return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
225 }
226 else if (componentType == long.class) {
227 return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
228 }
229 else if (componentType == float.class) {
230 return maybeAdapt(new VarHandleFloats.Array(aoffset, ashift));
231 }
232 else if (componentType == double.class) {
233 return maybeAdapt(new VarHandleDoubles.Array(aoffset, ashift));
234 }
235 else {
236 throw new UnsupportedOperationException();
237 }
238 }
239
240 static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
241 boolean be) {
242 if (!viewArrayClass.isArray())
243 throw new IllegalArgumentException("not an array: " + viewArrayClass);
244
245 Class<?> viewComponentType = viewArrayClass.getComponentType();
246
247 if (viewComponentType == long.class) {
248 return maybeAdapt(new VarHandleByteArrayAsLongs.ArrayHandle(be));
249 }
250 else if (viewComponentType == int.class) {
251 return maybeAdapt(new VarHandleByteArrayAsInts.ArrayHandle(be));
252 }
253 else if (viewComponentType == short.class) {
|
1 /*
2 * Copyright (c) 2014, 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 java.lang.invoke;
27
28 import jdk.internal.misc.CDS;
29 import jdk.internal.value.ValueClass;
30 import jdk.internal.vm.annotation.LooselyConsistentValue;
31 import sun.invoke.util.Wrapper;
32
33 import java.lang.foreign.MemoryLayout;
34 import java.lang.reflect.Constructor;
35 import java.lang.reflect.Field;
36 import java.lang.reflect.Method;
37 import java.lang.reflect.Modifier;
38 import java.nio.ByteOrder;
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.stream.Stream;
43
44 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
45 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
46 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
47 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
48
49 final class VarHandles {
50
51 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean trustedLookup) {
52 // No strict final or trusted final writes: we don't know the lifecycle of such a field.
53 boolean noWriting = f.isFinal() && (!trustedLookup || f.isStrictInit() || f.isTrustedFinalField());
54 if (!f.isStatic()) {
55 long foffset = MethodHandleNatives.objectFieldOffset(f);
56 Class<?> type = f.getFieldType();
57 if (!type.isPrimitive()) {
58 if (ValueClass.isConcreteValueClass(type)) {
59 int layout = f.getLayout();
60 boolean isAtomic = isAtomicFlat(f);
61 boolean isFlat = f.isFlat();
62 if (isFlat) {
63 if (isAtomic) {
64 return maybeAdapt(noWriting
65 ? new VarHandleFlatValues.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted(), layout)
66 : new VarHandleFlatValues.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted(), layout));
67 } else {
68 return maybeAdapt(noWriting
69 ? new VarHandleNonAtomicFlatValues.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted(), layout)
70 : new VarHandleNonAtomicFlatValues.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted(), layout));
71 }
72 } else {
73 if (isAtomic) {
74 return maybeAdapt(noWriting
75 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
76 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
77 } else {
78 return maybeAdapt(noWriting
79 ? new VarHandleNonAtomicReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
80 : new VarHandleNonAtomicReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
81 }
82 }
83 } else {
84 return maybeAdapt(noWriting
85 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.isNullRestricted())
86 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.isNullRestricted()));
87 }
88 }
89 else if (type == boolean.class) {
90 return maybeAdapt(noWriting
91 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
92 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
93 }
94 else if (type == byte.class) {
95 return maybeAdapt(noWriting
96 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
97 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
98 }
99 else if (type == short.class) {
100 return maybeAdapt(noWriting
101 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
102 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
103 }
104 else if (type == char.class) {
105 return maybeAdapt(noWriting
106 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
107 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
108 }
109 else if (type == int.class) {
110 return maybeAdapt(noWriting
111 ? new VarHandleInts.FieldInstanceReadOnly(refc, foffset)
112 : new VarHandleInts.FieldInstanceReadWrite(refc, foffset));
113 }
114 else if (type == long.class) {
115 return maybeAdapt(noWriting
116 ? new VarHandleLongs.FieldInstanceReadOnly(refc, foffset)
117 : new VarHandleLongs.FieldInstanceReadWrite(refc, foffset));
118 }
119 else if (type == float.class) {
120 return maybeAdapt(noWriting
121 ? new VarHandleFloats.FieldInstanceReadOnly(refc, foffset)
122 : new VarHandleFloats.FieldInstanceReadWrite(refc, foffset));
123 }
124 else if (type == double.class) {
125 return maybeAdapt(noWriting
126 ? new VarHandleDoubles.FieldInstanceReadOnly(refc, foffset)
127 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
128 }
129 else {
130 throw new UnsupportedOperationException();
131 }
132 }
133 else {
134 Class<?> decl = f.getDeclaringClass();
135 var vh = makeStaticFieldVarHandle(decl, f, noWriting);
136 return maybeAdapt((UNSAFE.shouldBeInitialized(decl) || CDS.needsClassInitBarrier(decl))
137 ? new LazyInitializingVarHandle(vh, f.isStrictInit())
138 : vh);
139 }
140 }
141
142 /// A root class for static field var handles. Allows [LazyInitializingVarHandle]
143 /// to access the declaring class and field offsets.
144 sealed static abstract class StaticFieldVarHandle extends VarHandle permits
145 VarHandleBooleans.FieldStaticReadOnly,
146 VarHandleBytes.FieldStaticReadOnly,
147 VarHandleChars.FieldStaticReadOnly,
148 VarHandleShorts.FieldStaticReadOnly,
149 VarHandleInts.FieldStaticReadOnly,
150 VarHandleLongs.FieldStaticReadOnly,
151 VarHandleFloats.FieldStaticReadOnly,
152 VarHandleDoubles.FieldStaticReadOnly,
153 VarHandleReferences.FieldStaticReadOnly,
154 VarHandleNonAtomicReferences.FieldStaticReadOnly {
155 final Class<?> declaringClass;
156 final Object base;
157 final long fieldOffset;
158
159 StaticFieldVarHandle(VarForm vform, boolean exact, Class<?> declaringClass, Object base, long fieldOffset) {
160 this.declaringClass = declaringClass;
161 this.base = base;
162 this.fieldOffset = fieldOffset;
163 super(vform, exact);
164 }
165
166 @Override
167 public abstract StaticFieldVarHandle withInvokeBehavior();
168
169 @Override
170 public abstract StaticFieldVarHandle withInvokeExactBehavior();
171 }
172
173 static StaticFieldVarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean noWriting) {
174 Object base = MethodHandleNatives.staticFieldBase(f);
175 long foffset = MethodHandleNatives.staticFieldOffset(f);
176 Class<?> type = f.getFieldType();
177 if (!type.isPrimitive()) {
178 assert !f.isFlat() : ("static field is flat in " + decl + "." + f.getName());
179 if (ValueClass.isConcreteValueClass(type)) {
180 if (isAtomicFlat(f)) {
181 return noWriting
182 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
183 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
184 } else {
185 return noWriting
186 ? new VarHandleNonAtomicReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
187 : new VarHandleNonAtomicReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
188 }
189 } else {
190 return noWriting
191 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.isNullRestricted())
192 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.isNullRestricted());
193 }
194 }
195 else if (type == boolean.class) {
196 return noWriting
197 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
198 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset);
199 }
200 else if (type == byte.class) {
201 return noWriting
202 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
203 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset);
204 }
205 else if (type == short.class) {
206 return noWriting
207 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
208 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset);
209 }
210 else if (type == char.class) {
211 return noWriting
212 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
213 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset);
214 }
215 else if (type == int.class) {
216 return noWriting
217 ? new VarHandleInts.FieldStaticReadOnly(decl, base, foffset)
218 : new VarHandleInts.FieldStaticReadWrite(decl, base, foffset);
219 }
220 else if (type == long.class) {
221 return noWriting
222 ? new VarHandleLongs.FieldStaticReadOnly(decl, base, foffset)
223 : new VarHandleLongs.FieldStaticReadWrite(decl, base, foffset);
224 }
225 else if (type == float.class) {
226 return noWriting
227 ? new VarHandleFloats.FieldStaticReadOnly(decl, base, foffset)
228 : new VarHandleFloats.FieldStaticReadWrite(decl, base, foffset);
229 }
230 else if (type == double.class) {
231 return noWriting
232 ? new VarHandleDoubles.FieldStaticReadOnly(decl, base, foffset)
233 : new VarHandleDoubles.FieldStaticReadWrite(decl, base, foffset);
234 }
235 else {
236 throw new UnsupportedOperationException();
237 }
238 }
239
240 static boolean isAtomicFlat(MemberName field) {
241 boolean hasAtomicAccess = (field.getModifiers() & Modifier.VOLATILE) != 0 ||
242 !(field.isNullRestricted()) ||
243 !field.getFieldType().isAnnotationPresent(LooselyConsistentValue.class);
244 return hasAtomicAccess && ValueClass.hasBinaryPayload(field.getFieldType());
245 }
246
247 static boolean isAtomicFlat(Object[] array) {
248 Class<?> componentType = array.getClass().componentType();
249 boolean hasAtomicAccess = ValueClass.isAtomicArray(array) ||
250 !ValueClass.isNullRestrictedArray(array) ||
251 !componentType.isAnnotationPresent(LooselyConsistentValue.class);
252 return hasAtomicAccess && ValueClass.hasBinaryPayload(componentType);
253 }
254
255 // Required by instance field handles
256 static Field getFieldFromReceiverAndOffset(Class<?> receiverType,
257 long offset,
258 Class<?> fieldType) {
259 // The receiver may be a referenced class different from the declaring class
260 for (var declaringClass = receiverType; declaringClass != null; declaringClass = declaringClass.getSuperclass()) {
261 for (Field f : declaringClass.getDeclaredFields()) {
262 if (Modifier.isStatic(f.getModifiers())) continue;
263
264 if (offset == UNSAFE.objectFieldOffset(f)) {
265 assert f.getType() == fieldType;
266 return f;
267 }
268 }
269 }
270 throw new InternalError("Field not found at offset");
271 }
272
273 // Required by instance static field handles
274 static Field getStaticFieldFromBaseAndOffset(Class<?> declaringClass,
275 long offset,
276 Class<?> fieldType) {
277 for (Field f : declaringClass.getDeclaredFields()) {
278 if (!Modifier.isStatic(f.getModifiers())) continue;
279
280 if (offset == UNSAFE.staticFieldOffset(f)) {
281 assert f.getType() == fieldType;
282 return f;
283 }
284 }
285 throw new InternalError("Static field not found at offset");
286 }
287
288 // This is invoked by non-flat array var handle code when attempting to access a flat array
289 public static void checkAtomicFlatArray(Object[] array) {
290 if (!isAtomicFlat(array)) {
291 throw new IllegalArgumentException("Attempt to perform a non-plain access on a non-atomic array");
292 }
293 }
294
295 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
296 if (!arrayClass.isArray())
297 throw new IllegalArgumentException("not an array: " + arrayClass);
298
299 Class<?> componentType = arrayClass.getComponentType();
300 if (!componentType.isPrimitive()) {
301 // Here we always return a reference array element var handle. This is because
302 // the access semantics is determined at runtime, when an actual array object is passed
303 // to the var handle. The var handle implementation will switch to use flat access
304 // primitives if it sees a flat array.
305 return maybeAdapt(new ArrayVarHandle(arrayClass));
306 }
307 else if (componentType == boolean.class) {
308 return maybeAdapt(VarHandleBooleans.Array.NON_EXACT_INSTANCE);
309 }
310 else if (componentType == byte.class) {
311 return maybeAdapt(VarHandleBytes.Array.NON_EXACT_INSTANCE);
312 }
313 else if (componentType == short.class) {
314 return maybeAdapt(VarHandleShorts.Array.NON_EXACT_INSTANCE);
315 }
316 else if (componentType == char.class) {
317 return maybeAdapt(VarHandleChars.Array.NON_EXACT_INSTANCE);
318 }
319 else if (componentType == int.class) {
320 return maybeAdapt(VarHandleInts.Array.NON_EXACT_INSTANCE);
321 }
322 else if (componentType == long.class) {
323 return maybeAdapt(VarHandleLongs.Array.NON_EXACT_INSTANCE);
324 }
325 else if (componentType == float.class) {
326 return maybeAdapt(VarHandleFloats.Array.NON_EXACT_INSTANCE);
327 }
328 else if (componentType == double.class) {
329 return maybeAdapt(VarHandleDoubles.Array.NON_EXACT_INSTANCE);
330 }
331 else {
332 throw new UnsupportedOperationException();
333 }
334 }
335
336 static VarHandle byteArrayViewHandle(Class<?> viewArrayClass,
337 boolean be) {
338 if (!viewArrayClass.isArray())
339 throw new IllegalArgumentException("not an array: " + viewArrayClass);
340
341 Class<?> viewComponentType = viewArrayClass.getComponentType();
342
343 if (viewComponentType == long.class) {
344 return maybeAdapt(new VarHandleByteArrayAsLongs.ArrayHandle(be));
345 }
346 else if (viewComponentType == int.class) {
347 return maybeAdapt(new VarHandleByteArrayAsInts.ArrayHandle(be));
348 }
349 else if (viewComponentType == short.class) {
|