42
43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
44 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
45 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
46 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
47
48 final class VarHandles {
49
50 static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() {
51 @Override
52 protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) {
53 return new ConcurrentHashMap<>();
54 }
55 };
56
57 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
58 if (!f.isStatic()) {
59 long foffset = MethodHandleNatives.objectFieldOffset(f);
60 Class<?> type = f.getFieldType();
61 if (!type.isPrimitive()) {
62 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
63 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type)
64 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type));
65 }
66 else if (type == boolean.class) {
67 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
68 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
69 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
70 }
71 else if (type == byte.class) {
72 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
73 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
74 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
75 }
76 else if (type == short.class) {
77 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
78 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
79 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
80 }
81 else if (type == char.class) {
82 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
83 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
84 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
104 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
105 }
106 else {
107 throw new UnsupportedOperationException();
108 }
109 }
110 else {
111 Class<?> decl = f.getDeclaringClass();
112 var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
113 return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
114 ? new LazyInitializingVarHandle(vh, decl)
115 : vh);
116 }
117 }
118
119 static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
120 Object base = MethodHandleNatives.staticFieldBase(f);
121 long foffset = MethodHandleNatives.staticFieldOffset(f);
122 Class<?> type = f.getFieldType();
123 if (!type.isPrimitive()) {
124 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
125 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type)
126 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type));
127 }
128 else if (type == boolean.class) {
129 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
130 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
131 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
132 }
133 else if (type == byte.class) {
134 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
135 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
136 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
137 }
138 else if (type == short.class) {
139 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
140 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
141 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
142 }
143 else if (type == char.class) {
144 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
145 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
146 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));
194
195 if (offset == UNSAFE.staticFieldOffset(f)) {
196 assert f.getType() == fieldType;
197 return f;
198 }
199 }
200 throw new InternalError("Static field not found at offset");
201 }
202
203 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
204 if (!arrayClass.isArray())
205 throw new IllegalArgumentException("not an array: " + arrayClass);
206
207 Class<?> componentType = arrayClass.getComponentType();
208
209 int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
210 int ascale = UNSAFE.arrayIndexScale(arrayClass);
211 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
212
213 if (!componentType.isPrimitive()) {
214 return maybeAdapt(new VarHandleReferences.Array(aoffset, ashift, arrayClass));
215 }
216 else if (componentType == boolean.class) {
217 return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
218 }
219 else if (componentType == byte.class) {
220 return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
221 }
222 else if (componentType == short.class) {
223 return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
224 }
225 else if (componentType == char.class) {
226 return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
227 }
228 else if (componentType == int.class) {
229 return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
230 }
231 else if (componentType == long.class) {
232 return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
233 }
234 else if (componentType == float.class) {
|
42
43 import static java.lang.invoke.MethodHandleStatics.UNSAFE;
44 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_SEGMENT_FORCE_EXACT;
45 import static java.lang.invoke.MethodHandleStatics.VAR_HANDLE_IDENTITY_ADAPT;
46 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
47
48 final class VarHandles {
49
50 static ClassValue<ConcurrentMap<Integer, MethodHandle>> ADDRESS_FACTORIES = new ClassValue<>() {
51 @Override
52 protected ConcurrentMap<Integer, MethodHandle> computeValue(Class<?> type) {
53 return new ConcurrentHashMap<>();
54 }
55 };
56
57 static VarHandle makeFieldHandle(MemberName f, Class<?> refc, boolean isWriteAllowedOnFinalFields) {
58 if (!f.isStatic()) {
59 long foffset = MethodHandleNatives.objectFieldOffset(f);
60 Class<?> type = f.getFieldType();
61 if (!type.isPrimitive()) {
62 if (f.isFlat()) {
63 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
64 ? new VarHandleValues.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType())
65 : new VarHandleValues.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType()));
66 } else {
67 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
68 ? new VarHandleReferences.FieldInstanceReadOnly(refc, foffset, type, f.getCheckedFieldType())
69 : new VarHandleReferences.FieldInstanceReadWrite(refc, foffset, type, f.getCheckedFieldType()));
70 }
71 }
72 else if (type == boolean.class) {
73 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
74 ? new VarHandleBooleans.FieldInstanceReadOnly(refc, foffset)
75 : new VarHandleBooleans.FieldInstanceReadWrite(refc, foffset));
76 }
77 else if (type == byte.class) {
78 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
79 ? new VarHandleBytes.FieldInstanceReadOnly(refc, foffset)
80 : new VarHandleBytes.FieldInstanceReadWrite(refc, foffset));
81 }
82 else if (type == short.class) {
83 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
84 ? new VarHandleShorts.FieldInstanceReadOnly(refc, foffset)
85 : new VarHandleShorts.FieldInstanceReadWrite(refc, foffset));
86 }
87 else if (type == char.class) {
88 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
89 ? new VarHandleChars.FieldInstanceReadOnly(refc, foffset)
90 : new VarHandleChars.FieldInstanceReadWrite(refc, foffset));
110 : new VarHandleDoubles.FieldInstanceReadWrite(refc, foffset));
111 }
112 else {
113 throw new UnsupportedOperationException();
114 }
115 }
116 else {
117 Class<?> decl = f.getDeclaringClass();
118 var vh = makeStaticFieldVarHandle(decl, f, isWriteAllowedOnFinalFields);
119 return maybeAdapt(UNSAFE.shouldBeInitialized(decl)
120 ? new LazyInitializingVarHandle(vh, decl)
121 : vh);
122 }
123 }
124
125 static VarHandle makeStaticFieldVarHandle(Class<?> decl, MemberName f, boolean isWriteAllowedOnFinalFields) {
126 Object base = MethodHandleNatives.staticFieldBase(f);
127 long foffset = MethodHandleNatives.staticFieldOffset(f);
128 Class<?> type = f.getFieldType();
129 if (!type.isPrimitive()) {
130 if (f.isFlat()) {
131 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
132 ? new VarHandleValues.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType())
133 : new VarHandleValues.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType()));
134 } else {
135 return f.isFinal() && !isWriteAllowedOnFinalFields
136 ? new VarHandleReferences.FieldStaticReadOnly(decl, base, foffset, type, f.getCheckedFieldType())
137 : new VarHandleReferences.FieldStaticReadWrite(decl, base, foffset, type, f.getCheckedFieldType());
138 }
139 }
140 else if (type == boolean.class) {
141 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
142 ? new VarHandleBooleans.FieldStaticReadOnly(decl, base, foffset)
143 : new VarHandleBooleans.FieldStaticReadWrite(decl, base, foffset));
144 }
145 else if (type == byte.class) {
146 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
147 ? new VarHandleBytes.FieldStaticReadOnly(decl, base, foffset)
148 : new VarHandleBytes.FieldStaticReadWrite(decl, base, foffset));
149 }
150 else if (type == short.class) {
151 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
152 ? new VarHandleShorts.FieldStaticReadOnly(decl, base, foffset)
153 : new VarHandleShorts.FieldStaticReadWrite(decl, base, foffset));
154 }
155 else if (type == char.class) {
156 return maybeAdapt(f.isFinal() && !isWriteAllowedOnFinalFields
157 ? new VarHandleChars.FieldStaticReadOnly(decl, base, foffset)
158 : new VarHandleChars.FieldStaticReadWrite(decl, base, foffset));
206
207 if (offset == UNSAFE.staticFieldOffset(f)) {
208 assert f.getType() == fieldType;
209 return f;
210 }
211 }
212 throw new InternalError("Static field not found at offset");
213 }
214
215 static VarHandle makeArrayElementHandle(Class<?> arrayClass) {
216 if (!arrayClass.isArray())
217 throw new IllegalArgumentException("not an array: " + arrayClass);
218
219 Class<?> componentType = arrayClass.getComponentType();
220
221 int aoffset = UNSAFE.arrayBaseOffset(arrayClass);
222 int ascale = UNSAFE.arrayIndexScale(arrayClass);
223 int ashift = 31 - Integer.numberOfLeadingZeros(ascale);
224
225 if (!componentType.isPrimitive()) {
226 return maybeAdapt(UNSAFE.isFlatArray(arrayClass)
227 ? new VarHandleValues.Array(aoffset, ashift, arrayClass)
228 : new VarHandleReferences.Array(aoffset, ashift, arrayClass));
229 }
230 else if (componentType == boolean.class) {
231 return maybeAdapt(new VarHandleBooleans.Array(aoffset, ashift));
232 }
233 else if (componentType == byte.class) {
234 return maybeAdapt(new VarHandleBytes.Array(aoffset, ashift));
235 }
236 else if (componentType == short.class) {
237 return maybeAdapt(new VarHandleShorts.Array(aoffset, ashift));
238 }
239 else if (componentType == char.class) {
240 return maybeAdapt(new VarHandleChars.Array(aoffset, ashift));
241 }
242 else if (componentType == int.class) {
243 return maybeAdapt(new VarHandleInts.Array(aoffset, ashift));
244 }
245 else if (componentType == long.class) {
246 return maybeAdapt(new VarHandleLongs.Array(aoffset, ashift));
247 }
248 else if (componentType == float.class) {
|