32 import java.lang.reflect.Method;
33 import java.lang.reflect.Modifier;
34 import java.nio.ByteOrder;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Objects;
38 import java.util.stream.Stream;
39
40 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
41 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
42 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
43 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
44
45 final class VarHandles {
46
47 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
48 if (!f.isStatic()) {
49 long foffset = MethodHandleNatives.objectFieldOffset(f);
50 Class<?> type = f.getFieldType();
51 if (!type.isPrimitive()) {
52 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
53 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
54 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));
55 }
56 else if (type == boolean.class) {
57 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
58 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
59 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
60 }
61 else if (type == byte.class) {
62 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
63 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
64 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
65 }
66 else if (type == short.class) {
67 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
68 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
69 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
70 }
71 else if (type == char.class) {
72 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
73 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
74 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
94 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
95 }
96 else {
97 throw new UnsupportedOperationException();
98 }
99 }
100 else {
101 Class<?> decl = f.getDeclaringClass();
102 var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
103 return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
104 ? new LazyInitializingVarHandle(vh, decl)
105 : vh);
106 }
107 }
108
109 static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
110 Object base = MethodHandleNatives.staticFieldBase(f);
111 long foffset = MethodHandleNatives.staticFieldOffset(f);
112 Class<?> type = f.getFieldType();
113 if (!type.isPrimitive()) {
114 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
115 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
116 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));
117 }
118 else if (type == boolean.class) {
119 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
120 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
121 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
122 }
123 else if (type == byte.class) {
124 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
125 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
126 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
127 }
128 else if (type == short.class) {
129 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
130 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
131 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
132 }
133 else if (type == char.class) {
134 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
135 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
136 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));
184
185 if (offset == UNSAFE.staticFieldOffset(f)) {
186 assert f.getType() == fieldType;
187 return f;
188 }
189 }
190 throw new InternalError("Static field not found at offset");
191 }
192
193 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
194 if (!arrayClass.isArray())
195 throw new IllegalArgumentException("not an array: " + arrayClass);
196
197 Class<?> componentType = arrayClass.getComponentType();
198
199 int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
200 int ascale = UNSAFE.arrayIndexScale(arrayClass);
201 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
202
203 if (!componentType.isPrimitive()) {
204 return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));
205 }
206 else if (componentType == boolean.class) {
207 return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
208 }
209 else if (componentType == byte.class) {
210 return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
211 }
212 else if (componentType == short.class) {
213 return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
214 }
215 else if (componentType == char.class) {
216 return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
217 }
218 else if (componentType == int.class) {
219 return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
220 }
221 else if (componentType == long.class) {
222 return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
223 }
224 else if (componentType == float.class) {
|
32 import java.lang.reflect.Method;
33 import java.lang.reflect.Modifier;
34 import java.nio.ByteOrder;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Objects;
38 import java.util.stream.Stream;
39
40 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
41 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
42 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
43 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
44
45 final class VarHandles {
46
47 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
48 if (!f.isStatic()) {
49 long foffset = MethodHandleNatives.objectFieldOffset(f);
50 Class<?> type = f.getFieldType();
51 if (!type.isPrimitive()) {
52 if (f.isFlat()) {
53 int layout = f.getLayout();
54 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
55 ? new VarHandleFlatValues.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType(), layout)
56 : new VarHandleFlatValues.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType(), layout));
57 } else {
58 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
59 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType())
60 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType()));
61 }
62 }
63 else if (type == boolean.class) {
64 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
65 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
66 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
67 }
68 else if (type == byte.class) {
69 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
70 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
71 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
72 }
73 else if (type == short.class) {
74 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
75 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
76 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
77 }
78 else if (type == char.class) {
79 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
80 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
81 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
101 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
102 }
103 else {
104 throw new UnsupportedOperationException();
105 }
106 }
107 else {
108 Class<?> decl = f.getDeclaringClass();
109 var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
110 return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
111 ? new LazyInitializingVarHandle(vh, decl)
112 : vh);
113 }
114 }
115
116 static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
117 Object base = MethodHandleNatives.staticFieldBase(f);
118 long foffset = MethodHandleNatives.staticFieldOffset(f);
119 Class<?> type = f.getFieldType();
120 if (!type.isPrimitive()) {
121 if (f.isFlat()) {
122 assert false : ("static field is flat in " + decl + "." + f.getName());
123 int layout = f.getLayout();
124 return f.isFinal() && !isWriteAllowedOnFinalFields
125 ? new VarHandleFlatValues.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType(), layout)
126 : new VarHandleFlatValues.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType(), layout);
127 } else {
128 return f.isFinal() && !isWriteAllowedOnFinalFields
129 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType())
130 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType());
131 }
132 }
133 else if (type == boolean.class) {
134 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
135 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
136 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
137 }
138 else if (type == byte.class) {
139 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
140 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
141 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
142 }
143 else if (type == short.class) {
144 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
145 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
146 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
147 }
148 else if (type == char.class) {
149 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
150 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
151 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));
199
200 if (offset == UNSAFE.staticFieldOffset(f)) {
201 assert f.getType() == fieldType;
202 return f;
203 }
204 }
205 throw new InternalError("Static field not found at offset");
206 }
207
208 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
209 if (!arrayClass.isArray())
210 throw new IllegalArgumentException("not an array: " + arrayClass);
211
212 Class<?> componentType = arrayClass.getComponentType();
213
214 int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
215 int ascale = UNSAFE.arrayIndexScale(arrayClass);
216 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
217
218 if (!componentType.isPrimitive()) {
219 VarHandle vh;
220 if (UNSAFE.isFlatArray(arrayClass)) {
221 int layout = UNSAFE.arrayLayout(arrayClass);
222 vh = new VarHandleFlatValues.Array(aoffset, ashift, arrayClass, layout);
223 } else {
224 vh = new VarHandleReferences.Array(aoffset, ashift, arrayClass);
225 }
226 return maybeAdapt(vh);
227 }
228 else if (componentType == boolean.class) {
229 return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
230 }
231 else if (componentType == byte.class) {
232 return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
233 }
234 else if (componentType == short.class) {
235 return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
236 }
237 else if (componentType == char.class) {
238 return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
239 }
240 else if (componentType == int.class) {
241 return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
242 }
243 else if (componentType == long.class) {
244 return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
245 }
246 else if (componentType == float.class) {
|