1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "var_handle.h"
18
19 #include "array-inl.h"
20 #include "art_field-inl.h"
21 #include "base/casts.h"
22 #include "class-inl.h"
23 #include "class_linker.h"
24 #include "class_root-inl.h"
25 #include "intrinsics_enum.h"
26 #include "jni/jni_internal.h"
27 #include "jvalue-inl.h"
28 #include "method_handles-inl.h"
29 #include "method_type-inl.h"
30 #include "object_array-alloc-inl.h"
31 #include "obj_ptr-inl.h"
32 #include "well_known_classes.h"
33
34 namespace art {
35 namespace mirror {
36
37 static constexpr bool kTransactionActive = true;
38 static constexpr bool kTransactionInactive = !kTransactionActive;
39
40 namespace {
41
42 struct VarHandleAccessorToAccessModeEntry {
43 const char* method_name;
44 VarHandle::AccessMode access_mode;
45
46 // Binary predicate function for finding access_mode by
47 // method_name. The access_mode field is ignored.
CompareNameart::mirror::__anonf04ed2060111::VarHandleAccessorToAccessModeEntry48 static bool CompareName(const VarHandleAccessorToAccessModeEntry& lhs,
49 const VarHandleAccessorToAccessModeEntry& rhs) {
50 return strcmp(lhs.method_name, rhs.method_name) < 0;
51 }
52 };
53
54 // Map of VarHandle accessor method names to access mode values. The list is alpha-sorted to support
55 // binary search. For the usage scenario - lookups in the verifier - a linear scan would likely
56 // suffice since we expect VarHandles to be a lesser encountered class. We could use a std::hashmap
57 // here and this would be easier to maintain if new values are added here. However, this entails
58 // CPU cycles initializing the structure on every execution and uses O(N) more memory for
59 // intermediate nodes and makes that memory dirty. Compile-time magic using constexpr is possible
60 // here, but that's a tax when this code is recompiled.
61 const VarHandleAccessorToAccessModeEntry kAccessorToAccessMode[VarHandle::kNumberOfAccessModes] = {
62 { "compareAndExchange", VarHandle::AccessMode::kCompareAndExchange },
63 { "compareAndExchangeAcquire", VarHandle::AccessMode::kCompareAndExchangeAcquire },
64 { "compareAndExchangeRelease", VarHandle::AccessMode::kCompareAndExchangeRelease },
65 { "compareAndSet", VarHandle::AccessMode::kCompareAndSet },
66 { "get", VarHandle::AccessMode::kGet },
67 { "getAcquire", VarHandle::AccessMode::kGetAcquire },
68 { "getAndAdd", VarHandle::AccessMode::kGetAndAdd },
69 { "getAndAddAcquire", VarHandle::AccessMode::kGetAndAddAcquire },
70 { "getAndAddRelease", VarHandle::AccessMode::kGetAndAddRelease },
71 { "getAndBitwiseAnd", VarHandle::AccessMode::kGetAndBitwiseAnd },
72 { "getAndBitwiseAndAcquire", VarHandle::AccessMode::kGetAndBitwiseAndAcquire },
73 { "getAndBitwiseAndRelease", VarHandle::AccessMode::kGetAndBitwiseAndRelease },
74 { "getAndBitwiseOr", VarHandle::AccessMode::kGetAndBitwiseOr },
75 { "getAndBitwiseOrAcquire", VarHandle::AccessMode::kGetAndBitwiseOrAcquire },
76 { "getAndBitwiseOrRelease", VarHandle::AccessMode::kGetAndBitwiseOrRelease },
77 { "getAndBitwiseXor", VarHandle::AccessMode::kGetAndBitwiseXor },
78 { "getAndBitwiseXorAcquire", VarHandle::AccessMode::kGetAndBitwiseXorAcquire },
79 { "getAndBitwiseXorRelease", VarHandle::AccessMode::kGetAndBitwiseXorRelease },
80 { "getAndSet", VarHandle::AccessMode::kGetAndSet },
81 { "getAndSetAcquire", VarHandle::AccessMode::kGetAndSetAcquire },
82 { "getAndSetRelease", VarHandle::AccessMode::kGetAndSetRelease },
83 { "getOpaque", VarHandle::AccessMode::kGetOpaque },
84 { "getVolatile", VarHandle::AccessMode::kGetVolatile },
85 { "set", VarHandle::AccessMode::kSet },
86 { "setOpaque", VarHandle::AccessMode::kSetOpaque },
87 { "setRelease", VarHandle::AccessMode::kSetRelease },
88 { "setVolatile", VarHandle::AccessMode::kSetVolatile },
89 { "weakCompareAndSet", VarHandle::AccessMode::kWeakCompareAndSet },
90 { "weakCompareAndSetAcquire", VarHandle::AccessMode::kWeakCompareAndSetAcquire },
91 { "weakCompareAndSetPlain", VarHandle::AccessMode::kWeakCompareAndSetPlain },
92 { "weakCompareAndSetRelease", VarHandle::AccessMode::kWeakCompareAndSetRelease },
93 };
94
95 // Returns the number of parameters associated with an
96 // AccessModeTemplate and the supplied coordinate types.
GetNumberOfParameters(VarHandle::AccessModeTemplate access_mode_template,ObjPtr<Class> coordinateType0,ObjPtr<Class> coordinateType1)97 int32_t GetNumberOfParameters(VarHandle::AccessModeTemplate access_mode_template,
98 ObjPtr<Class> coordinateType0,
99 ObjPtr<Class> coordinateType1) {
100 int32_t count = 0;
101 if (!coordinateType0.IsNull()) {
102 count++;
103 if (!coordinateType1.IsNull()) {
104 count++;
105 }
106 }
107 return count + VarHandle::GetNumberOfVarTypeParameters(access_mode_template);
108 }
109
ThrowNullPointerExceptionForCoordinate()110 void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) {
111 ThrowNullPointerException("Attempt to access memory on a null object");
112 }
113
CheckElementIndex(Primitive::Type type,int32_t index,int32_t start,int32_t length)114 bool CheckElementIndex(Primitive::Type type,
115 int32_t index,
116 int32_t start,
117 int32_t length) REQUIRES_SHARED(Locks::mutator_lock_) {
118 // The underlying memory may be shared and offset from the start of allocated region,
119 // ie buffers can be created via ByteBuffer.split().
120 //
121 // `type` is the type of the value the caller is attempting to read / write.
122 // `index` represents the position the caller is trying to access in the underlying ByteBuffer
123 // or byte array. This is an offset from from `start` in bytes.
124 // `start` represents where the addressable memory begins relative to the base of the
125 // the underlying ByteBuffer or byte array.
126 // `length` represents the length of the addressable region.
127 //
128 // Thus the region being operated on is:
129 // `base` + `start` + `index` to `base` + `start` + `index` + `sizeof(type)`
130 int32_t max_index = length - start - Primitive::ComponentSize(type);
131 if (index < 0 || index > max_index) {
132 ThrowIndexOutOfBoundsException(index, length - start);
133 return false;
134 }
135 return true;
136 }
137
CheckElementIndex(Primitive::Type type,int32_t index,int32_t length)138 bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t length)
139 REQUIRES_SHARED(Locks::mutator_lock_) {
140 return CheckElementIndex(type, index, 0, length);
141 }
142
143 // Returns true if access_mode only entails a memory read. False if
144 // access_mode may write to memory.
IsReadOnlyAccessMode(VarHandle::AccessMode access_mode)145 bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) {
146 return VarHandle::GetAccessModeTemplate(access_mode) == VarHandle::AccessModeTemplate::kGet;
147 }
148
149 // Writes the parameter types associated with the AccessModeTemplate
150 // into an array. The parameter types are derived from the specified
151 // variable type and coordinate types. Returns the number of
152 // parameters written.
BuildParameterArray(ObjPtr<Class> (& parameters)[VarHandle::kMaxAccessorParameters],VarHandle::AccessModeTemplate access_mode_template,ObjPtr<Class> varType,ObjPtr<Class> coordinateType0,ObjPtr<Class> coordinateType1)153 int32_t BuildParameterArray(ObjPtr<Class> (¶meters)[VarHandle::kMaxAccessorParameters],
154 VarHandle::AccessModeTemplate access_mode_template,
155 ObjPtr<Class> varType,
156 ObjPtr<Class> coordinateType0,
157 ObjPtr<Class> coordinateType1)
158 REQUIRES_SHARED(Locks::mutator_lock_) {
159 DCHECK(varType != nullptr);
160 int32_t index = 0;
161 if (!coordinateType0.IsNull()) {
162 parameters[index++] = coordinateType0;
163 if (!coordinateType1.IsNull()) {
164 parameters[index++] = coordinateType1;
165 }
166 } else {
167 DCHECK(coordinateType1.IsNull());
168 }
169
170 switch (access_mode_template) {
171 case VarHandle::AccessModeTemplate::kCompareAndExchange:
172 case VarHandle::AccessModeTemplate::kCompareAndSet:
173 parameters[index++] = varType;
174 parameters[index++] = varType;
175 return index;
176 case VarHandle::AccessModeTemplate::kGet:
177 return index;
178 case VarHandle::AccessModeTemplate::kGetAndUpdate:
179 case VarHandle::AccessModeTemplate::kSet:
180 parameters[index++] = varType;
181 return index;
182 }
183 return -1;
184 }
185
186 // Returns the return type associated with an VarHandle::AccessModeTemplate based
187 // on the template and the variable type specified.
GetReturnType(VarHandle::AccessModeTemplate access_mode_template,ObjPtr<Class> varType)188 static ObjPtr<Class> GetReturnType(VarHandle::AccessModeTemplate access_mode_template,
189 ObjPtr<Class> varType)
190 REQUIRES_SHARED(Locks::mutator_lock_) {
191 DCHECK(varType != nullptr);
192 switch (access_mode_template) {
193 case VarHandle::AccessModeTemplate::kCompareAndSet:
194 return GetClassRoot(ClassRoot::kPrimitiveBoolean);
195 case VarHandle::AccessModeTemplate::kCompareAndExchange:
196 case VarHandle::AccessModeTemplate::kGet:
197 case VarHandle::AccessModeTemplate::kGetAndUpdate:
198 return varType;
199 case VarHandle::AccessModeTemplate::kSet:
200 return GetClassRoot(ClassRoot::kPrimitiveVoid);
201 }
202 return nullptr;
203 }
204
205 // Method to insert a read barrier for accessors to reference fields.
ReadBarrierForVarHandleAccess(ObjPtr<Object> obj,MemberOffset field_offset)206 inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> obj, MemberOffset field_offset)
207 REQUIRES_SHARED(Locks::mutator_lock_) {
208 if (kUseReadBarrier) {
209 // We need to ensure that the reference stored in the field is a to-space one before attempting
210 // the CompareAndSet/CompareAndExchange/Exchange operation otherwise it will fail incorrectly
211 // if obj is in the process of being moved.
212 uint8_t* raw_field_addr = reinterpret_cast<uint8_t*>(obj.Ptr()) + field_offset.SizeValue();
213 auto field_addr = reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr);
214 // Note that the read barrier load does NOT need to be volatile.
215 static constexpr bool kIsVolatile = false;
216 static constexpr bool kAlwaysUpdateField = true;
217 ReadBarrier::Barrier<mirror::Object, kIsVolatile, kWithReadBarrier, kAlwaysUpdateField>(
218 obj.Ptr(),
219 MemberOffset(field_offset),
220 field_addr);
221 }
222 }
223
GetMemberOffset(jfieldID field_id)224 inline MemberOffset GetMemberOffset(jfieldID field_id) REQUIRES_SHARED(Locks::mutator_lock_) {
225 ArtField* const field = jni::DecodeArtField(field_id);
226 return field->GetOffset();
227 }
228
229 //
230 // Helper methods for storing results from atomic operations into
231 // JValue instances.
232 //
233
StoreResult(uint8_t value,JValue * result)234 inline void StoreResult(uint8_t value, JValue* result) {
235 result->SetZ(value);
236 }
237
StoreResult(int8_t value,JValue * result)238 inline void StoreResult(int8_t value, JValue* result) {
239 result->SetB(value);
240 }
241
StoreResult(uint16_t value,JValue * result)242 inline void StoreResult(uint16_t value, JValue* result) {
243 result->SetC(value);
244 }
245
StoreResult(int16_t value,JValue * result)246 inline void StoreResult(int16_t value, JValue* result) {
247 result->SetS(value);
248 }
249
StoreResult(int32_t value,JValue * result)250 inline void StoreResult(int32_t value, JValue* result) {
251 result->SetI(value);
252 }
253
StoreResult(int64_t value,JValue * result)254 inline void StoreResult(int64_t value, JValue* result) {
255 result->SetJ(value);
256 }
257
StoreResult(float value,JValue * result)258 inline void StoreResult(float value, JValue* result) {
259 result->SetF(value);
260 }
261
StoreResult(double value,JValue * result)262 inline void StoreResult(double value, JValue* result) {
263 result->SetD(value);
264 }
265
StoreResult(ObjPtr<Object> value,JValue * result)266 inline void StoreResult(ObjPtr<Object> value, JValue* result)
267 REQUIRES_SHARED(Locks::mutator_lock_) {
268 result->SetL(value);
269 }
270
271 //
272 // Helper class for byte-swapping value that has been stored in a JValue.
273 //
274
275 template <typename T>
276 class JValueByteSwapper final {
277 public:
278 static void ByteSwap(JValue* value);
MaybeByteSwap(bool byte_swap,JValue * value)279 static void MaybeByteSwap(bool byte_swap, JValue* value) {
280 if (byte_swap) {
281 ByteSwap(value);
282 }
283 }
284 };
285
286 template <>
ByteSwap(JValue * value)287 void JValueByteSwapper<uint16_t>::ByteSwap(JValue* value) {
288 value->SetC(BSWAP(value->GetC()));
289 }
290
291 template <>
ByteSwap(JValue * value)292 void JValueByteSwapper<int16_t>::ByteSwap(JValue* value) {
293 value->SetS(BSWAP(value->GetS()));
294 }
295
296 template <>
ByteSwap(JValue * value)297 void JValueByteSwapper<int32_t>::ByteSwap(JValue* value) {
298 value->SetI(BSWAP(value->GetI()));
299 }
300
301 template <>
ByteSwap(JValue * value)302 void JValueByteSwapper<int64_t>::ByteSwap(JValue* value) {
303 value->SetJ(BSWAP(value->GetJ()));
304 }
305
306 //
307 // Accessor implementations, shared across all VarHandle types.
308 //
309
310 template <typename T, std::memory_order MO>
311 class AtomicGetAccessor : public Object::Accessor<T> {
312 public:
AtomicGetAccessor(JValue * result)313 explicit AtomicGetAccessor(JValue* result) : result_(result) {}
314
Access(T * addr)315 void Access(T* addr) override {
316 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
317 StoreResult(atom->load(MO), result_);
318 }
319
320 private:
321 JValue* result_;
322 };
323
324 template <typename T, std::memory_order MO>
325 class AtomicSetAccessor : public Object::Accessor<T> {
326 public:
AtomicSetAccessor(T new_value)327 explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {}
328
Access(T * addr)329 void Access(T* addr) override {
330 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
331 atom->store(new_value_, MO);
332 }
333
334 private:
335 T new_value_;
336 };
337
338 template <typename T> using GetAccessor = AtomicGetAccessor<T, std::memory_order_relaxed>;
339
340 template <typename T> using SetAccessor = AtomicSetAccessor<T, std::memory_order_relaxed>;
341
342 template <typename T>
343 using GetVolatileAccessor = AtomicGetAccessor<T, std::memory_order_seq_cst>;
344
345 template <typename T>
346 using SetVolatileAccessor = AtomicSetAccessor<T, std::memory_order_seq_cst>;
347
348 template <typename T, std::memory_order MOS, std::memory_order MOF>
349 class AtomicStrongCompareAndSetAccessor : public Object::Accessor<T> {
350 public:
AtomicStrongCompareAndSetAccessor(T expected_value,T desired_value,JValue * result)351 AtomicStrongCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
352 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
353
Access(T * addr)354 void Access(T* addr) override {
355 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
356 bool success = atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
357 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
358 }
359
360 private:
361 T expected_value_;
362 T desired_value_;
363 JValue* result_;
364 };
365
366 template<typename T>
367 using CompareAndSetAccessor =
368 AtomicStrongCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
369
370 template <typename T, std::memory_order MOS, std::memory_order MOF>
371 class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor<T> {
372 public:
AtomicStrongCompareAndExchangeAccessor(T expected_value,T desired_value,JValue * result)373 AtomicStrongCompareAndExchangeAccessor(T expected_value, T desired_value, JValue* result)
374 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
375
Access(T * addr)376 void Access(T* addr) override {
377 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
378 atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
379 StoreResult(expected_value_, result_);
380 }
381
382 private:
383 T expected_value_;
384 T desired_value_;
385 JValue* result_;
386 };
387
388 template <typename T>
389 using CompareAndExchangeAccessor =
390 AtomicStrongCompareAndExchangeAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
391
392 template <typename T, std::memory_order MOS, std::memory_order MOF>
393 class AtomicWeakCompareAndSetAccessor : public Object::Accessor<T> {
394 public:
AtomicWeakCompareAndSetAccessor(T expected_value,T desired_value,JValue * result)395 AtomicWeakCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
396 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
397
Access(T * addr)398 void Access(T* addr) override {
399 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
400 bool success = atom->compare_exchange_weak(expected_value_, desired_value_, MOS, MOF);
401 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
402 }
403
404 private:
405 T expected_value_;
406 T desired_value_;
407 JValue* result_;
408 };
409
410 template <typename T>
411 using WeakCompareAndSetAccessor =
412 AtomicWeakCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
413
414 template <typename T, std::memory_order MO>
415 class AtomicGetAndSetAccessor : public Object::Accessor<T> {
416 public:
AtomicGetAndSetAccessor(T new_value,JValue * result)417 AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {}
418
Access(T * addr)419 void Access(T* addr) override {
420 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
421 T old_value = atom->exchange(new_value_, MO);
422 StoreResult(old_value, result_);
423 }
424
425 private:
426 T new_value_;
427 JValue* result_;
428 };
429
430 template <typename T>
431 using GetAndSetAccessor = AtomicGetAndSetAccessor<T, std::memory_order_seq_cst>;
432
433 template <typename T, bool kIsFloat, std::memory_order MO>
434 class AtomicGetAndAddOperator {
435 public:
Apply(T * addr,T addend)436 static T Apply(T* addr, T addend) {
437 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
438 return atom->fetch_add(addend, MO);
439 }
440 };
441
442 template <typename T, std::memory_order MO>
443 class AtomicGetAndAddOperator<T, /* kIsFloat */ true, MO> {
444 public:
Apply(T * addr,T addend)445 static T Apply(T* addr, T addend) {
446 // c++11 does not have std::atomic<T>::fetch_and_add for floating
447 // point types, so we effect one with a compare and swap.
448 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
449 T old_value = atom->load(std::memory_order_relaxed);
450 T new_value;
451 do {
452 new_value = old_value + addend;
453 } while (!atom->compare_exchange_weak(old_value, new_value, MO, std::memory_order_relaxed));
454 return old_value;
455 }
456 };
457
458 template <typename T, std::memory_order MO>
459 class AtomicGetAndAddAccessor : public Object::Accessor<T> {
460 public:
AtomicGetAndAddAccessor(T addend,JValue * result)461 AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {}
462
Access(T * addr)463 void Access(T* addr) override {
464 constexpr bool kIsFloatingPoint = std::is_floating_point<T>::value;
465 T old_value = AtomicGetAndAddOperator<T, kIsFloatingPoint, MO>::Apply(addr, addend_);
466 StoreResult(old_value, result_);
467 }
468
469 private:
470 T addend_;
471 JValue* result_;
472 };
473
474 template <typename T>
475 using GetAndAddAccessor = AtomicGetAndAddAccessor<T, std::memory_order_seq_cst>;
476
477 // Accessor specifically for memory views where the caller can specify
478 // the byte-ordering. Addition only works outside of the byte-swapped
479 // memory view because of the direction of carries.
480 template <typename T, std::memory_order MO>
481 class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor<T> {
482 public:
AtomicGetAndAddWithByteSwapAccessor(T value,JValue * result)483 AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {}
484
Access(T * addr)485 void Access(T* addr) override {
486 std::atomic<T>* const atom = reinterpret_cast<std::atomic<T>*>(addr);
487 T current_value = atom->load(std::memory_order_relaxed);
488 T sum;
489 do {
490 sum = BSWAP(current_value) + value_;
491 // NB current_value is a pass-by-reference argument in the call to
492 // atomic<T>::compare_exchange_weak().
493 } while (!atom->compare_exchange_weak(current_value,
494 BSWAP(sum),
495 MO,
496 std::memory_order_relaxed));
497 StoreResult(BSWAP(current_value), result_);
498 }
499
500 private:
501 T value_;
502 JValue* result_;
503 };
504
505 template <typename T>
506 using GetAndAddWithByteSwapAccessor =
507 AtomicGetAndAddWithByteSwapAccessor<T, std::memory_order_seq_cst>;
508
509 template <typename T, std::memory_order MO>
510 class AtomicGetAndBitwiseOrAccessor : public Object::Accessor<T> {
511 public:
AtomicGetAndBitwiseOrAccessor(T value,JValue * result)512 AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {}
513
Access(T * addr)514 void Access(T* addr) override {
515 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
516 T old_value = atom->fetch_or(value_, MO);
517 StoreResult(old_value, result_);
518 }
519
520 private:
521 T value_;
522 JValue* result_;
523 };
524
525 template <typename T>
526 using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor<T, std::memory_order_seq_cst>;
527
528 template <typename T, std::memory_order MO>
529 class AtomicGetAndBitwiseAndAccessor : public Object::Accessor<T> {
530 public:
AtomicGetAndBitwiseAndAccessor(T value,JValue * result)531 AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {}
532
Access(T * addr)533 void Access(T* addr) override {
534 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
535 T old_value = atom->fetch_and(value_, MO);
536 StoreResult(old_value, result_);
537 }
538
539 private:
540 T value_;
541 JValue* result_;
542 };
543
544 template <typename T>
545 using GetAndBitwiseAndAccessor =
546 AtomicGetAndBitwiseAndAccessor<T, std::memory_order_seq_cst>;
547
548 template <typename T, std::memory_order MO>
549 class AtomicGetAndBitwiseXorAccessor : public Object::Accessor<T> {
550 public:
AtomicGetAndBitwiseXorAccessor(T value,JValue * result)551 AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {}
552
Access(T * addr)553 void Access(T* addr) override {
554 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
555 T old_value = atom->fetch_xor(value_, MO);
556 StoreResult(old_value, result_);
557 }
558
559 private:
560 T value_;
561 JValue* result_;
562 };
563
564 template <typename T>
565 using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor<T, std::memory_order_seq_cst>;
566
567 //
568 // Unreachable access modes.
569 //
570
UnreachableAccessMode(const char * access_mode,const char * type_name)571 NO_RETURN void UnreachableAccessMode(const char* access_mode, const char* type_name) {
572 LOG(FATAL) << "Unreachable access mode :" << access_mode << " for type " << type_name;
573 UNREACHABLE();
574 }
575
576 #define UNREACHABLE_ACCESS_MODE(ACCESS_MODE, TYPE) \
577 template<> void ACCESS_MODE ## Accessor<TYPE>::Access(TYPE*) { \
578 UnreachableAccessMode(#ACCESS_MODE, #TYPE); \
579 }
580
581 // The boolean primitive type is not numeric (boolean == std::uint8_t).
582 UNREACHABLE_ACCESS_MODE(GetAndAdd, uint8_t)
583
584 // The floating point types do not support bitwise operations.
585 UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, float)
586 UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, float)
587 UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, float)
588 UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, double)
589 UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, double)
590 UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, double)
591
592 // A helper class for object field accesses for floats and
593 // doubles. The object interface deals with Field32 and Field64. The
594 // former is used for both integers and floats, the latter for longs
595 // and doubles. This class provides the necessary coercion.
596 template <typename T, typename U>
597 class TypeAdaptorAccessor : public Object::Accessor<T> {
598 public:
TypeAdaptorAccessor(Object::Accessor<U> * inner_accessor)599 explicit TypeAdaptorAccessor(Object::Accessor<U>* inner_accessor)
600 : inner_accessor_(inner_accessor) {}
601
Access(T * addr)602 void Access(T* addr) override {
603 static_assert(sizeof(T) == sizeof(U), "bad conversion");
604 inner_accessor_->Access(reinterpret_cast<U*>(addr));
605 }
606
607 private:
608 Object::Accessor<U>* inner_accessor_;
609 };
610
611 template <typename T>
612 class FieldAccessViaAccessor {
613 public:
614 using Accessor = Object::Accessor<T>;
615
616 // Apply an Accessor to get a field in an object.
Get(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)617 static void Get(ObjPtr<Object> obj,
618 MemberOffset field_offset,
619 Accessor* accessor)
620 REQUIRES_SHARED(Locks::mutator_lock_) {
621 obj->GetPrimitiveFieldViaAccessor(field_offset, accessor);
622 }
623
624 // Apply an Accessor to update a field in an object.
625 static void Update(ObjPtr<Object> obj,
626 MemberOffset field_offset,
627 Accessor* accessor)
628 REQUIRES_SHARED(Locks::mutator_lock_);
629 };
630
631 template <>
Get(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)632 inline void FieldAccessViaAccessor<float>::Get(ObjPtr<Object> obj,
633 MemberOffset field_offset,
634 Accessor* accessor)
635 REQUIRES_SHARED(Locks::mutator_lock_) {
636 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
637 obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor);
638 }
639
640 template <>
Get(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)641 inline void FieldAccessViaAccessor<double>::Get(ObjPtr<Object> obj,
642 MemberOffset field_offset,
643 Accessor* accessor)
644 REQUIRES_SHARED(Locks::mutator_lock_) {
645 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
646 obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor);
647 }
648
649 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)650 void FieldAccessViaAccessor<uint8_t>::Update(ObjPtr<Object> obj,
651 MemberOffset field_offset,
652 Accessor* accessor)
653 REQUIRES_SHARED(Locks::mutator_lock_) {
654 if (Runtime::Current()->IsActiveTransaction()) {
655 obj->UpdateFieldBooleanViaAccessor<kTransactionActive>(field_offset, accessor);
656 } else {
657 obj->UpdateFieldBooleanViaAccessor<kTransactionInactive>(field_offset, accessor);
658 }
659 }
660
661 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)662 void FieldAccessViaAccessor<int8_t>::Update(ObjPtr<Object> obj,
663 MemberOffset field_offset,
664 Accessor* accessor)
665 REQUIRES_SHARED(Locks::mutator_lock_) {
666 if (Runtime::Current()->IsActiveTransaction()) {
667 obj->UpdateFieldByteViaAccessor<kTransactionActive>(field_offset, accessor);
668 } else {
669 obj->UpdateFieldByteViaAccessor<kTransactionInactive>(field_offset, accessor);
670 }
671 }
672
673 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)674 void FieldAccessViaAccessor<uint16_t>::Update(ObjPtr<Object> obj,
675 MemberOffset field_offset,
676 Accessor* accessor)
677 REQUIRES_SHARED(Locks::mutator_lock_) {
678 if (Runtime::Current()->IsActiveTransaction()) {
679 obj->UpdateFieldCharViaAccessor<kTransactionActive>(field_offset, accessor);
680 } else {
681 obj->UpdateFieldCharViaAccessor<kTransactionInactive>(field_offset, accessor);
682 }
683 }
684
685 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)686 void FieldAccessViaAccessor<int16_t>::Update(ObjPtr<Object> obj,
687 MemberOffset field_offset,
688 Accessor* accessor)
689 REQUIRES_SHARED(Locks::mutator_lock_) {
690 if (Runtime::Current()->IsActiveTransaction()) {
691 obj->UpdateFieldShortViaAccessor<kTransactionActive>(field_offset, accessor);
692 } else {
693 obj->UpdateFieldShortViaAccessor<kTransactionInactive>(field_offset, accessor);
694 }
695 }
696
697 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)698 void FieldAccessViaAccessor<int32_t>::Update(ObjPtr<Object> obj,
699 MemberOffset field_offset,
700 Accessor* accessor)
701 REQUIRES_SHARED(Locks::mutator_lock_) {
702 if (Runtime::Current()->IsActiveTransaction()) {
703 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, accessor);
704 } else {
705 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, accessor);
706 }
707 }
708
709 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)710 void FieldAccessViaAccessor<int64_t>::Update(ObjPtr<Object> obj,
711 MemberOffset field_offset,
712 Accessor* accessor)
713 REQUIRES_SHARED(Locks::mutator_lock_) {
714 if (Runtime::Current()->IsActiveTransaction()) {
715 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, accessor);
716 } else {
717 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, accessor);
718 }
719 }
720
721 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)722 void FieldAccessViaAccessor<float>::Update(ObjPtr<Object> obj,
723 MemberOffset field_offset,
724 Accessor* accessor)
725 REQUIRES_SHARED(Locks::mutator_lock_) {
726 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
727 if (Runtime::Current()->IsActiveTransaction()) {
728 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, &float_to_int_accessor);
729 } else {
730 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, &float_to_int_accessor);
731 }
732 }
733
734 template <>
Update(ObjPtr<Object> obj,MemberOffset field_offset,Accessor * accessor)735 void FieldAccessViaAccessor<double>::Update(ObjPtr<Object> obj,
736 MemberOffset field_offset,
737 Accessor* accessor)
738 REQUIRES_SHARED(Locks::mutator_lock_) {
739 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
740 if (Runtime::Current()->IsActiveTransaction()) {
741 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, &double_to_int_accessor);
742 } else {
743 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, &double_to_int_accessor);
744 }
745 }
746
747 // Helper class that gets values from a shadow frame with appropriate type coercion.
748 template <typename T>
749 class ValueGetter {
750 public:
Get(ShadowFrameGetter * getter)751 static T Get(ShadowFrameGetter* getter) REQUIRES_SHARED(Locks::mutator_lock_) {
752 static_assert(sizeof(T) <= sizeof(uint32_t), "Bad size");
753 uint32_t raw_value = getter->Get();
754 return static_cast<T>(raw_value);
755 }
756 };
757
758 template <>
Get(ShadowFrameGetter * getter)759 int64_t ValueGetter<int64_t>::Get(ShadowFrameGetter* getter) {
760 return getter->GetLong();
761 }
762
763 template <>
Get(ShadowFrameGetter * getter)764 float ValueGetter<float>::Get(ShadowFrameGetter* getter) {
765 uint32_t raw_value = getter->Get();
766 return *reinterpret_cast<float*>(&raw_value);
767 }
768
769 template <>
Get(ShadowFrameGetter * getter)770 double ValueGetter<double>::Get(ShadowFrameGetter* getter) {
771 int64_t raw_value = getter->GetLong();
772 return *reinterpret_cast<double*>(&raw_value);
773 }
774
775 template <>
Get(ShadowFrameGetter * getter)776 ObjPtr<Object> ValueGetter<ObjPtr<Object>>::Get(ShadowFrameGetter* getter) {
777 return getter->GetReference();
778 }
779
780 // Class for accessing fields of Object instances
781 template <typename T>
782 class FieldAccessor {
783 public:
784 static bool Dispatch(VarHandle::AccessMode access_mode,
785 ObjPtr<Object> obj,
786 MemberOffset field_offset,
787 ShadowFrameGetter* getter,
788 JValue* result)
789 REQUIRES_SHARED(Locks::mutator_lock_);
790 };
791
792 // Dispatch implementation for primitive fields.
793 template <typename T>
Dispatch(VarHandle::AccessMode access_mode,ObjPtr<Object> obj,MemberOffset field_offset,ShadowFrameGetter * getter,JValue * result)794 bool FieldAccessor<T>::Dispatch(VarHandle::AccessMode access_mode,
795 ObjPtr<Object> obj,
796 MemberOffset field_offset,
797 ShadowFrameGetter* getter,
798 JValue* result) {
799 switch (access_mode) {
800 case VarHandle::AccessMode::kGet: {
801 GetAccessor<T> accessor(result);
802 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
803 break;
804 }
805 case VarHandle::AccessMode::kSet: {
806 T new_value = ValueGetter<T>::Get(getter);
807 SetAccessor<T> accessor(new_value);
808 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
809 break;
810 }
811 case VarHandle::AccessMode::kGetAcquire:
812 case VarHandle::AccessMode::kGetOpaque:
813 case VarHandle::AccessMode::kGetVolatile: {
814 GetVolatileAccessor<T> accessor(result);
815 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
816 break;
817 }
818 case VarHandle::AccessMode::kSetOpaque:
819 case VarHandle::AccessMode::kSetRelease:
820 case VarHandle::AccessMode::kSetVolatile: {
821 T new_value = ValueGetter<T>::Get(getter);
822 SetVolatileAccessor<T> accessor(new_value);
823 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
824 break;
825 }
826 case VarHandle::AccessMode::kCompareAndSet: {
827 T expected_value = ValueGetter<T>::Get(getter);
828 T desired_value = ValueGetter<T>::Get(getter);
829 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
830 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
831 break;
832 }
833 case VarHandle::AccessMode::kCompareAndExchange:
834 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
835 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
836 T expected_value = ValueGetter<T>::Get(getter);
837 T desired_value = ValueGetter<T>::Get(getter);
838 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
839 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
840 break;
841 }
842 case VarHandle::AccessMode::kWeakCompareAndSet:
843 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
844 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
845 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
846 T expected_value = ValueGetter<T>::Get(getter);
847 T desired_value = ValueGetter<T>::Get(getter);
848 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
849 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
850 break;
851 }
852 case VarHandle::AccessMode::kGetAndSet:
853 case VarHandle::AccessMode::kGetAndSetAcquire:
854 case VarHandle::AccessMode::kGetAndSetRelease: {
855 T new_value = ValueGetter<T>::Get(getter);
856 GetAndSetAccessor<T> accessor(new_value, result);
857 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
858 break;
859 }
860 case VarHandle::AccessMode::kGetAndAdd:
861 case VarHandle::AccessMode::kGetAndAddAcquire:
862 case VarHandle::AccessMode::kGetAndAddRelease: {
863 T value = ValueGetter<T>::Get(getter);
864 GetAndAddAccessor<T> accessor(value, result);
865 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
866 break;
867 }
868 case VarHandle::AccessMode::kGetAndBitwiseOr:
869 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
870 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
871 T value = ValueGetter<T>::Get(getter);
872 GetAndBitwiseOrAccessor<T> accessor(value, result);
873 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
874 break;
875 }
876 case VarHandle::AccessMode::kGetAndBitwiseAnd:
877 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
878 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
879 T value = ValueGetter<T>::Get(getter);
880 GetAndBitwiseAndAccessor<T> accessor(value, result);
881 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
882 break;
883 }
884 case VarHandle::AccessMode::kGetAndBitwiseXor:
885 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
886 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
887 T value = ValueGetter<T>::Get(getter);
888 GetAndBitwiseXorAccessor<T> accessor(value, result);
889 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
890 break;
891 }
892 }
893 return true;
894 }
895
896 // Dispatch implementation for reference fields.
897 template <>
Dispatch(VarHandle::AccessMode access_mode,ObjPtr<Object> obj,MemberOffset field_offset,ShadowFrameGetter * getter,JValue * result)898 bool FieldAccessor<ObjPtr<Object>>::Dispatch(VarHandle::AccessMode access_mode,
899 ObjPtr<Object> obj,
900 MemberOffset field_offset,
901 ShadowFrameGetter* getter,
902 JValue* result)
903 REQUIRES_SHARED(Locks::mutator_lock_) {
904 // To keep things simple, use the minimum strongest existing
905 // field accessor for Object fields. This may be the most
906 // straightforward strategy in general for the interpreter.
907 switch (access_mode) {
908 case VarHandle::AccessMode::kGet: {
909 StoreResult(obj->GetFieldObject<Object>(field_offset), result);
910 break;
911 }
912 case VarHandle::AccessMode::kSet: {
913 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
914 if (Runtime::Current()->IsActiveTransaction()) {
915 obj->SetFieldObject<kTransactionActive>(field_offset, new_value);
916 } else {
917 obj->SetFieldObject<kTransactionInactive>(field_offset, new_value);
918 }
919 break;
920 }
921 case VarHandle::AccessMode::kGetAcquire:
922 case VarHandle::AccessMode::kGetOpaque:
923 case VarHandle::AccessMode::kGetVolatile: {
924 StoreResult(obj->GetFieldObjectVolatile<Object>(field_offset), result);
925 break;
926 }
927 case VarHandle::AccessMode::kSetOpaque:
928 case VarHandle::AccessMode::kSetRelease:
929 case VarHandle::AccessMode::kSetVolatile: {
930 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
931 if (Runtime::Current()->IsActiveTransaction()) {
932 obj->SetFieldObjectVolatile<kTransactionActive>(field_offset, new_value);
933 } else {
934 obj->SetFieldObjectVolatile<kTransactionInactive>(field_offset, new_value);
935 }
936 break;
937 }
938 case VarHandle::AccessMode::kCompareAndSet: {
939 ReadBarrierForVarHandleAccess(obj, field_offset);
940 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
941 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
942 bool cas_result;
943 if (Runtime::Current()->IsActiveTransaction()) {
944 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
945 expected_value,
946 desired_value,
947 CASMode::kStrong,
948 std::memory_order_seq_cst);
949 } else {
950 cas_result = obj->CasFieldObject<kTransactionInactive>(field_offset,
951 expected_value,
952 desired_value,
953 CASMode::kStrong,
954 std::memory_order_seq_cst);
955 }
956 StoreResult(static_cast<uint8_t>(cas_result), result);
957 break;
958 }
959 case VarHandle::AccessMode::kWeakCompareAndSet:
960 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
961 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
962 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
963 ReadBarrierForVarHandleAccess(obj, field_offset);
964 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
965 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
966 bool cas_result;
967 if (Runtime::Current()->IsActiveTransaction()) {
968 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
969 expected_value,
970 desired_value,
971 CASMode::kWeak,
972 std::memory_order_seq_cst);
973 } else {
974 cas_result = obj->CasFieldObject<kTransactionInactive>(
975 field_offset,
976 expected_value,
977 desired_value,
978 CASMode::kWeak,
979 std::memory_order_seq_cst);
980 }
981 StoreResult(static_cast<uint8_t>(cas_result), result);
982 break;
983 }
984 case VarHandle::AccessMode::kCompareAndExchange:
985 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
986 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
987 ReadBarrierForVarHandleAccess(obj, field_offset);
988 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
989 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
990 ObjPtr<Object> witness_value;
991 if (Runtime::Current()->IsActiveTransaction()) {
992 witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>(field_offset,
993 expected_value,
994 desired_value);
995 } else {
996 witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>(field_offset,
997 expected_value,
998 desired_value);
999 }
1000 StoreResult(witness_value, result);
1001 break;
1002 }
1003 case VarHandle::AccessMode::kGetAndSet:
1004 case VarHandle::AccessMode::kGetAndSetAcquire:
1005 case VarHandle::AccessMode::kGetAndSetRelease: {
1006 ReadBarrierForVarHandleAccess(obj, field_offset);
1007 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1008 ObjPtr<Object> old_value;
1009 if (Runtime::Current()->IsActiveTransaction()) {
1010 old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value);
1011 } else {
1012 old_value = obj->ExchangeFieldObject<kTransactionInactive>(field_offset, new_value);
1013 }
1014 StoreResult(old_value, result);
1015 break;
1016 }
1017 case VarHandle::AccessMode::kGetAndAdd:
1018 case VarHandle::AccessMode::kGetAndAddAcquire:
1019 case VarHandle::AccessMode::kGetAndAddRelease:
1020 case VarHandle::AccessMode::kGetAndBitwiseOr:
1021 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1022 case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
1023 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1024 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1025 case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
1026 case VarHandle::AccessMode::kGetAndBitwiseXor:
1027 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1028 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1029 size_t index = static_cast<size_t>(access_mode);
1030 const char* access_mode_name = kAccessorToAccessMode[index].method_name;
1031 UnreachableAccessMode(access_mode_name, "Object");
1032 }
1033 }
1034 return true;
1035 }
1036
1037 // Class for accessing primitive array elements.
1038 template <typename T>
1039 class PrimitiveArrayElementAccessor {
1040 public:
GetElementAddress(ObjPtr<Array> target_array,int target_element)1041 static T* GetElementAddress(ObjPtr<Array> target_array, int target_element)
1042 REQUIRES_SHARED(Locks::mutator_lock_) {
1043 auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array);
1044 DCHECK(primitive_array->CheckIsValidIndex(target_element));
1045 return &primitive_array->GetData()[target_element];
1046 }
1047
Dispatch(VarHandle::AccessMode access_mode,ObjPtr<Array> target_array,int target_element,ShadowFrameGetter * getter,JValue * result)1048 static bool Dispatch(VarHandle::AccessMode access_mode,
1049 ObjPtr<Array> target_array,
1050 int target_element,
1051 ShadowFrameGetter* getter,
1052 JValue* result)
1053 REQUIRES_SHARED(Locks::mutator_lock_) {
1054 T* element_address = GetElementAddress(target_array, target_element);
1055 switch (access_mode) {
1056 case VarHandle::AccessMode::kGet: {
1057 GetAccessor<T> accessor(result);
1058 accessor.Access(element_address);
1059 break;
1060 }
1061 case VarHandle::AccessMode::kSet: {
1062 T new_value = ValueGetter<T>::Get(getter);
1063 SetAccessor<T> accessor(new_value);
1064 accessor.Access(element_address);
1065 break;
1066 }
1067 case VarHandle::AccessMode::kGetAcquire:
1068 case VarHandle::AccessMode::kGetOpaque:
1069 case VarHandle::AccessMode::kGetVolatile: {
1070 GetVolatileAccessor<T> accessor(result);
1071 accessor.Access(element_address);
1072 break;
1073 }
1074 case VarHandle::AccessMode::kSetOpaque:
1075 case VarHandle::AccessMode::kSetRelease:
1076 case VarHandle::AccessMode::kSetVolatile: {
1077 T new_value = ValueGetter<T>::Get(getter);
1078 SetVolatileAccessor<T> accessor(new_value);
1079 accessor.Access(element_address);
1080 break;
1081 }
1082 case VarHandle::AccessMode::kCompareAndSet: {
1083 T expected_value = ValueGetter<T>::Get(getter);
1084 T desired_value = ValueGetter<T>::Get(getter);
1085 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1086 accessor.Access(element_address);
1087 break;
1088 }
1089 case VarHandle::AccessMode::kCompareAndExchange:
1090 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1091 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1092 T expected_value = ValueGetter<T>::Get(getter);
1093 T desired_value = ValueGetter<T>::Get(getter);
1094 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1095 accessor.Access(element_address);
1096 break;
1097 }
1098 case VarHandle::AccessMode::kWeakCompareAndSet:
1099 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1100 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1101 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1102 T expected_value = ValueGetter<T>::Get(getter);
1103 T desired_value = ValueGetter<T>::Get(getter);
1104 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1105 accessor.Access(element_address);
1106 break;
1107 }
1108 case VarHandle::AccessMode::kGetAndSet:
1109 case VarHandle::AccessMode::kGetAndSetAcquire:
1110 case VarHandle::AccessMode::kGetAndSetRelease: {
1111 T new_value = ValueGetter<T>::Get(getter);
1112 GetAndSetAccessor<T> accessor(new_value, result);
1113 accessor.Access(element_address);
1114 break;
1115 }
1116 case VarHandle::AccessMode::kGetAndAdd:
1117 case VarHandle::AccessMode::kGetAndAddAcquire:
1118 case VarHandle::AccessMode::kGetAndAddRelease: {
1119 T value = ValueGetter<T>::Get(getter);
1120 GetAndAddAccessor<T> accessor(value, result);
1121 accessor.Access(element_address);
1122 break;
1123 }
1124 case VarHandle::AccessMode::kGetAndBitwiseOr:
1125 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1126 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1127 T value = ValueGetter<T>::Get(getter);
1128 GetAndBitwiseOrAccessor<T> accessor(value, result);
1129 accessor.Access(element_address);
1130 break;
1131 }
1132 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1133 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1134 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1135 T value = ValueGetter<T>::Get(getter);
1136 GetAndBitwiseAndAccessor<T> accessor(value, result);
1137 accessor.Access(element_address);
1138 break;
1139 }
1140 case VarHandle::AccessMode::kGetAndBitwiseXor:
1141 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1142 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1143 T value = ValueGetter<T>::Get(getter);
1144 GetAndBitwiseXorAccessor<T> accessor(value, result);
1145 accessor.Access(element_address);
1146 break;
1147 }
1148 }
1149 return true;
1150 }
1151 };
1152
1153 // Class for accessing primitive array elements.
1154 template <typename T>
1155 class ByteArrayViewAccessor {
1156 public:
IsAccessAligned(int8_t * data,int data_index)1157 static inline bool IsAccessAligned(int8_t* data, int data_index) {
1158 static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size");
1159 static_assert(std::is_arithmetic<T>::value, "unexpected type");
1160 uintptr_t alignment_mask = sizeof(T) - 1;
1161 uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index);
1162 return (address & alignment_mask) == 0;
1163 }
1164
MaybeByteSwap(bool byte_swap,T * const value)1165 static inline void MaybeByteSwap(bool byte_swap, T* const value) {
1166 if (byte_swap) {
1167 *value = BSWAP(*value);
1168 }
1169 }
1170
Dispatch(const VarHandle::AccessMode access_mode,int8_t * const data,const int data_index,const bool byte_swap,ShadowFrameGetter * const getter,JValue * const result)1171 static bool Dispatch(const VarHandle::AccessMode access_mode,
1172 int8_t* const data,
1173 const int data_index,
1174 const bool byte_swap,
1175 ShadowFrameGetter* const getter,
1176 JValue* const result)
1177 REQUIRES_SHARED(Locks::mutator_lock_) {
1178 const bool is_aligned = IsAccessAligned(data, data_index);
1179 if (!is_aligned) {
1180 switch (access_mode) {
1181 case VarHandle::AccessMode::kGet: {
1182 T value;
1183 memcpy(&value, data + data_index, sizeof(T));
1184 MaybeByteSwap(byte_swap, &value);
1185 StoreResult(value, result);
1186 return true;
1187 }
1188 case VarHandle::AccessMode::kSet: {
1189 T new_value = ValueGetter<T>::Get(getter);
1190 MaybeByteSwap(byte_swap, &new_value);
1191 memcpy(data + data_index, &new_value, sizeof(T));
1192 return true;
1193 }
1194 default:
1195 // No other access modes support unaligned access.
1196 ThrowIllegalStateException("Unaligned access not supported");
1197 return false;
1198 }
1199 }
1200
1201 T* const element_address = reinterpret_cast<T*>(data + data_index);
1202 CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0));
1203 switch (access_mode) {
1204 case VarHandle::AccessMode::kGet: {
1205 GetAccessor<T> accessor(result);
1206 accessor.Access(element_address);
1207 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1208 break;
1209 }
1210 case VarHandle::AccessMode::kSet: {
1211 T new_value = ValueGetter<T>::Get(getter);
1212 MaybeByteSwap(byte_swap, &new_value);
1213 SetAccessor<T> accessor(new_value);
1214 accessor.Access(element_address);
1215 break;
1216 }
1217 case VarHandle::AccessMode::kGetAcquire:
1218 case VarHandle::AccessMode::kGetOpaque:
1219 case VarHandle::AccessMode::kGetVolatile: {
1220 GetVolatileAccessor<T> accessor(result);
1221 accessor.Access(element_address);
1222 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1223 break;
1224 }
1225 case VarHandle::AccessMode::kSetOpaque:
1226 case VarHandle::AccessMode::kSetRelease:
1227 case VarHandle::AccessMode::kSetVolatile: {
1228 T new_value = ValueGetter<T>::Get(getter);
1229 MaybeByteSwap(byte_swap, &new_value);
1230 SetVolatileAccessor<T> accessor(new_value);
1231 accessor.Access(element_address);
1232 break;
1233 }
1234 case VarHandle::AccessMode::kCompareAndSet: {
1235 T expected_value = ValueGetter<T>::Get(getter);
1236 T desired_value = ValueGetter<T>::Get(getter);
1237 MaybeByteSwap(byte_swap, &expected_value);
1238 MaybeByteSwap(byte_swap, &desired_value);
1239 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1240 accessor.Access(element_address);
1241 break;
1242 }
1243 case VarHandle::AccessMode::kCompareAndExchange:
1244 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1245 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1246 T expected_value = ValueGetter<T>::Get(getter);
1247 T desired_value = ValueGetter<T>::Get(getter);
1248 MaybeByteSwap(byte_swap, &expected_value);
1249 MaybeByteSwap(byte_swap, &desired_value);
1250 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1251 accessor.Access(element_address);
1252 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1253 break;
1254 }
1255 case VarHandle::AccessMode::kWeakCompareAndSet:
1256 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1257 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1258 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1259 T expected_value = ValueGetter<T>::Get(getter);
1260 T desired_value = ValueGetter<T>::Get(getter);
1261 MaybeByteSwap(byte_swap, &expected_value);
1262 MaybeByteSwap(byte_swap, &desired_value);
1263 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1264 accessor.Access(element_address);
1265 break;
1266 }
1267 case VarHandle::AccessMode::kGetAndSet:
1268 case VarHandle::AccessMode::kGetAndSetAcquire:
1269 case VarHandle::AccessMode::kGetAndSetRelease: {
1270 T new_value = ValueGetter<T>::Get(getter);
1271 MaybeByteSwap(byte_swap, &new_value);
1272 GetAndSetAccessor<T> accessor(new_value, result);
1273 accessor.Access(element_address);
1274 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1275 break;
1276 }
1277 case VarHandle::AccessMode::kGetAndAdd:
1278 case VarHandle::AccessMode::kGetAndAddAcquire:
1279 case VarHandle::AccessMode::kGetAndAddRelease: {
1280 T value = ValueGetter<T>::Get(getter);
1281 if (byte_swap) {
1282 GetAndAddWithByteSwapAccessor<T> accessor(value, result);
1283 accessor.Access(element_address);
1284 } else {
1285 GetAndAddAccessor<T> accessor(value, result);
1286 accessor.Access(element_address);
1287 }
1288 break;
1289 }
1290 case VarHandle::AccessMode::kGetAndBitwiseOr:
1291 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1292 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1293 T value = ValueGetter<T>::Get(getter);
1294 MaybeByteSwap(byte_swap, &value);
1295 GetAndBitwiseOrAccessor<T> accessor(value, result);
1296 accessor.Access(element_address);
1297 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1298 break;
1299 }
1300 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1301 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1302 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1303 T value = ValueGetter<T>::Get(getter);
1304 MaybeByteSwap(byte_swap, &value);
1305 GetAndBitwiseAndAccessor<T> accessor(value, result);
1306 accessor.Access(element_address);
1307 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1308 break;
1309 }
1310 case VarHandle::AccessMode::kGetAndBitwiseXor:
1311 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1312 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1313 T value = ValueGetter<T>::Get(getter);
1314 MaybeByteSwap(byte_swap, &value);
1315 GetAndBitwiseXorAccessor<T> accessor(value, result);
1316 accessor.Access(element_address);
1317 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1318 break;
1319 }
1320 }
1321 return true;
1322 }
1323 };
1324
1325 } // namespace
1326
GetVarType()1327 ObjPtr<Class> VarHandle::GetVarType() {
1328 return GetFieldObject<Class>(VarTypeOffset());
1329 }
1330
GetCoordinateType0()1331 ObjPtr<Class> VarHandle::GetCoordinateType0() {
1332 return GetFieldObject<Class>(CoordinateType0Offset());
1333 }
1334
GetCoordinateType1()1335 ObjPtr<Class> VarHandle::GetCoordinateType1() {
1336 return GetFieldObject<Class>(CoordinateType1Offset());
1337 }
1338
GetAccessModesBitMask()1339 int32_t VarHandle::GetAccessModesBitMask() {
1340 return GetField32(AccessModesBitMaskOffset());
1341 }
1342
GetMethodTypeMatchForAccessMode(AccessMode access_mode,ObjPtr<MethodType> method_type)1343 VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode,
1344 ObjPtr<MethodType> method_type) {
1345 MatchKind match = MatchKind::kExact;
1346
1347 ObjPtr<VarHandle> vh = this;
1348 ObjPtr<Class> var_type = vh->GetVarType();
1349 ObjPtr<Class> mt_rtype = method_type->GetRType();
1350 ObjPtr<Class> void_type = WellKnownClasses::ToClass(WellKnownClasses::java_lang_Void);
1351 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1352
1353 // Check return type first.
1354 ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
1355 if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid &&
1356 !mt_rtype->IsAssignableFrom(vh_rtype)) {
1357 // Call-site is an expression (expects a return value) and the value returned by the accessor
1358 // is not assignable to the expected return type.
1359 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
1360 return MatchKind::kNone;
1361 }
1362 match = MatchKind::kWithConversions;
1363 }
1364
1365 // Check the number of parameters matches.
1366 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
1367 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1368 access_mode_template,
1369 var_type,
1370 GetCoordinateType0(),
1371 GetCoordinateType1());
1372 if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
1373 return MatchKind::kNone;
1374 }
1375
1376 // Check the parameter types are compatible.
1377 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
1378 for (int32_t i = 0; i < vh_ptypes_count; ++i) {
1379 if (vh_ptypes[i]->IsAssignableFrom(mt_ptypes->Get(i))) {
1380 continue;
1381 }
1382 if (mt_ptypes->Get(i) == void_type && !vh_ptypes[i]->IsPrimitive()) {
1383 // The expected parameter is a reference and the parameter type from the call site is j.l.Void
1384 // which means the value is null. It is always valid for a reference parameter to be null.
1385 continue;
1386 }
1387 if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
1388 return MatchKind::kNone;
1389 }
1390 match = MatchKind::kWithConversions;
1391 }
1392 return match;
1393 }
1394
GetMethodTypeForAccessMode(Thread * self,ObjPtr<VarHandle> var_handle,AccessMode access_mode)1395 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
1396 ObjPtr<VarHandle> var_handle,
1397 AccessMode access_mode) {
1398 // This is a static method as the var_handle might be moved by the GC during it's execution.
1399 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1400
1401 StackHandleScope<3> hs(self);
1402 Handle<VarHandle> vh = hs.NewHandle(var_handle);
1403 Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType()));
1404 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
1405 vh->GetCoordinateType0(),
1406 vh->GetCoordinateType1());
1407 ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>();
1408 Handle<ObjectArray<Class>> ptypes =
1409 hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
1410 if (ptypes == nullptr) {
1411 return nullptr;
1412 }
1413
1414 ObjPtr<Class> ptypes_array[VarHandle::kMaxAccessorParameters];
1415 BuildParameterArray(ptypes_array,
1416 access_mode_template,
1417 vh->GetVarType(),
1418 vh->GetCoordinateType0(),
1419 vh->GetCoordinateType1());
1420 for (int32_t i = 0; i < ptypes_count; ++i) {
1421 ptypes->Set(i, ptypes_array[i]);
1422 }
1423 return MethodType::Create(self, rtype, ptypes);
1424 }
1425
GetMethodTypeForAccessMode(Thread * self,AccessMode access_mode)1426 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
1427 return GetMethodTypeForAccessMode(self, this, access_mode);
1428 }
1429
PrettyDescriptorForAccessMode(AccessMode access_mode)1430 std::string VarHandle::PrettyDescriptorForAccessMode(AccessMode access_mode) {
1431 // Effect MethodType::PrettyDescriptor() without first creating a method type first.
1432 std::ostringstream oss;
1433 oss << '(';
1434
1435 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1436 ObjPtr<Class> var_type = GetVarType();
1437 ObjPtr<Class> ctypes[2] = { GetCoordinateType0(), GetCoordinateType1() };
1438 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, ctypes[0], ctypes[1]);
1439 int32_t ptypes_done = 0;
1440 for (ObjPtr<Class> ctype : ctypes) {
1441 if (!ctype.IsNull()) {
1442 if (ptypes_done != 0) {
1443 oss << ", ";
1444 }
1445 oss << ctype->PrettyDescriptor();;
1446 ptypes_done++;
1447 }
1448 }
1449 while (ptypes_done != ptypes_count) {
1450 if (ptypes_done != 0) {
1451 oss << ", ";
1452 }
1453 oss << var_type->PrettyDescriptor();
1454 ptypes_done++;
1455 }
1456 ObjPtr<Class> rtype = GetReturnType(access_mode_template, var_type);
1457 oss << ')' << rtype->PrettyDescriptor();
1458 return oss.str();
1459 }
1460
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1461 bool VarHandle::Access(AccessMode access_mode,
1462 ShadowFrame* shadow_frame,
1463 const InstructionOperands* const operands,
1464 JValue* result) {
1465 ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
1466 ObjPtr<Class> klass = GetClass();
1467 if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
1468 auto vh = ObjPtr<FieldVarHandle>::DownCast(this);
1469 return vh->Access(access_mode, shadow_frame, operands, result);
1470 } else if (klass == GetClassRoot<StaticFieldVarHandle>(class_roots)) {
1471 auto vh = ObjPtr<StaticFieldVarHandle>::DownCast(this);
1472 return vh->Access(access_mode, shadow_frame, operands, result);
1473 } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
1474 auto vh = ObjPtr<ArrayElementVarHandle>::DownCast(this);
1475 return vh->Access(access_mode, shadow_frame, operands, result);
1476 } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
1477 auto vh = ObjPtr<ByteArrayViewVarHandle>::DownCast(this);
1478 return vh->Access(access_mode, shadow_frame, operands, result);
1479 } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
1480 auto vh = ObjPtr<ByteBufferViewVarHandle>::DownCast(this);
1481 return vh->Access(access_mode, shadow_frame, operands, result);
1482 } else {
1483 LOG(FATAL) << "Unknown varhandle kind";
1484 UNREACHABLE();
1485 }
1486 }
1487
GetReturnTypeDescriptor(const char * accessor_name)1488 const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) {
1489 AccessMode access_mode;
1490 if (!GetAccessModeByMethodName(accessor_name, &access_mode)) {
1491 return nullptr;
1492 }
1493 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1494 switch (access_mode_template) {
1495 case AccessModeTemplate::kGet:
1496 case AccessModeTemplate::kCompareAndExchange:
1497 case AccessModeTemplate::kGetAndUpdate:
1498 return "Ljava/lang/Object;";
1499 case AccessModeTemplate::kCompareAndSet:
1500 return "Z";
1501 case AccessModeTemplate::kSet:
1502 return "V";
1503 }
1504 }
1505
GetAccessModeByIntrinsic(Intrinsics intrinsic)1506 VarHandle::AccessMode VarHandle::GetAccessModeByIntrinsic(Intrinsics intrinsic) {
1507 #define VAR_HANDLE_ACCESS_MODE(V) \
1508 V(CompareAndExchange) \
1509 V(CompareAndExchangeAcquire) \
1510 V(CompareAndExchangeRelease) \
1511 V(CompareAndSet) \
1512 V(Get) \
1513 V(GetAcquire) \
1514 V(GetAndAdd) \
1515 V(GetAndAddAcquire) \
1516 V(GetAndAddRelease) \
1517 V(GetAndBitwiseAnd) \
1518 V(GetAndBitwiseAndAcquire) \
1519 V(GetAndBitwiseAndRelease) \
1520 V(GetAndBitwiseOr) \
1521 V(GetAndBitwiseOrAcquire) \
1522 V(GetAndBitwiseOrRelease) \
1523 V(GetAndBitwiseXor) \
1524 V(GetAndBitwiseXorAcquire) \
1525 V(GetAndBitwiseXorRelease) \
1526 V(GetAndSet) \
1527 V(GetAndSetAcquire) \
1528 V(GetAndSetRelease) \
1529 V(GetOpaque) \
1530 V(GetVolatile) \
1531 V(Set) \
1532 V(SetOpaque) \
1533 V(SetRelease) \
1534 V(SetVolatile) \
1535 V(WeakCompareAndSet) \
1536 V(WeakCompareAndSetAcquire) \
1537 V(WeakCompareAndSetPlain) \
1538 V(WeakCompareAndSetRelease)
1539 switch (intrinsic) {
1540 #define INTRINSIC_CASE(Name) \
1541 case Intrinsics::kVarHandle ## Name: \
1542 return VarHandle::AccessMode::k ## Name;
1543 VAR_HANDLE_ACCESS_MODE(INTRINSIC_CASE)
1544 #undef INTRINSIC_CASE
1545 #undef VAR_HANDLE_ACCESS_MODE
1546 default:
1547 break;
1548 }
1549 LOG(FATAL) << "Unknown VarHandle instrinsic: " << static_cast<int>(intrinsic);
1550 UNREACHABLE();
1551 }
1552
GetAccessModeByMethodName(const char * method_name,AccessMode * access_mode)1553 bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode) {
1554 if (method_name == nullptr) {
1555 return false;
1556 }
1557 const auto kUnusedAccessMode = VarHandle::AccessMode::kGet; // arbitrary value.
1558 VarHandleAccessorToAccessModeEntry target = { method_name, kUnusedAccessMode };
1559 auto last = std::cend(kAccessorToAccessMode);
1560 auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode),
1561 last,
1562 target,
1563 VarHandleAccessorToAccessModeEntry::CompareName);
1564 if (it == last || strcmp(it->method_name, method_name) != 0) {
1565 return false;
1566 }
1567 *access_mode = it->access_mode;
1568 return true;
1569 }
1570
1571 // Look up the AccessModeTemplate for a given VarHandle
1572 // AccessMode. This simplifies finding the correct signature for a
1573 // VarHandle accessor method.
GetAccessModeTemplate(VarHandle::AccessMode access_mode)1574 VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
1575 switch (access_mode) {
1576 case VarHandle::AccessMode::kGet:
1577 return AccessModeTemplate::kGet;
1578 case VarHandle::AccessMode::kSet:
1579 return AccessModeTemplate::kSet;
1580 case VarHandle::AccessMode::kGetVolatile:
1581 return AccessModeTemplate::kGet;
1582 case VarHandle::AccessMode::kSetVolatile:
1583 return AccessModeTemplate::kSet;
1584 case VarHandle::AccessMode::kGetAcquire:
1585 return AccessModeTemplate::kGet;
1586 case VarHandle::AccessMode::kSetRelease:
1587 return AccessModeTemplate::kSet;
1588 case VarHandle::AccessMode::kGetOpaque:
1589 return AccessModeTemplate::kGet;
1590 case VarHandle::AccessMode::kSetOpaque:
1591 return AccessModeTemplate::kSet;
1592 case VarHandle::AccessMode::kCompareAndSet:
1593 return AccessModeTemplate::kCompareAndSet;
1594 case VarHandle::AccessMode::kCompareAndExchange:
1595 return AccessModeTemplate::kCompareAndExchange;
1596 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1597 return AccessModeTemplate::kCompareAndExchange;
1598 case VarHandle::AccessMode::kCompareAndExchangeRelease:
1599 return AccessModeTemplate::kCompareAndExchange;
1600 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1601 return AccessModeTemplate::kCompareAndSet;
1602 case VarHandle::AccessMode::kWeakCompareAndSet:
1603 return AccessModeTemplate::kCompareAndSet;
1604 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1605 return AccessModeTemplate::kCompareAndSet;
1606 case VarHandle::AccessMode::kWeakCompareAndSetRelease:
1607 return AccessModeTemplate::kCompareAndSet;
1608 case VarHandle::AccessMode::kGetAndSet:
1609 return AccessModeTemplate::kGetAndUpdate;
1610 case VarHandle::AccessMode::kGetAndSetAcquire:
1611 return AccessModeTemplate::kGetAndUpdate;
1612 case VarHandle::AccessMode::kGetAndSetRelease:
1613 return AccessModeTemplate::kGetAndUpdate;
1614 case VarHandle::AccessMode::kGetAndAdd:
1615 return AccessModeTemplate::kGetAndUpdate;
1616 case VarHandle::AccessMode::kGetAndAddAcquire:
1617 return AccessModeTemplate::kGetAndUpdate;
1618 case VarHandle::AccessMode::kGetAndAddRelease:
1619 return AccessModeTemplate::kGetAndUpdate;
1620 case VarHandle::AccessMode::kGetAndBitwiseOr:
1621 return AccessModeTemplate::kGetAndUpdate;
1622 case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
1623 return AccessModeTemplate::kGetAndUpdate;
1624 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1625 return AccessModeTemplate::kGetAndUpdate;
1626 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1627 return AccessModeTemplate::kGetAndUpdate;
1628 case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
1629 return AccessModeTemplate::kGetAndUpdate;
1630 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1631 return AccessModeTemplate::kGetAndUpdate;
1632 case VarHandle::AccessMode::kGetAndBitwiseXor:
1633 return AccessModeTemplate::kGetAndUpdate;
1634 case VarHandle::AccessMode::kGetAndBitwiseXorRelease:
1635 return AccessModeTemplate::kGetAndUpdate;
1636 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1637 return AccessModeTemplate::kGetAndUpdate;
1638 }
1639 }
1640
GetAccessModeTemplateByIntrinsic(Intrinsics ordinal)1641 VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplateByIntrinsic(Intrinsics ordinal) {
1642 AccessMode access_mode = GetAccessModeByIntrinsic(ordinal);
1643 return GetAccessModeTemplate(access_mode);
1644 }
1645
GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template)1646 int32_t VarHandle::GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
1647 switch (access_mode_template) {
1648 case AccessModeTemplate::kGet:
1649 return 0;
1650 case AccessModeTemplate::kSet:
1651 case AccessModeTemplate::kGetAndUpdate:
1652 return 1;
1653 case AccessModeTemplate::kCompareAndSet:
1654 case AccessModeTemplate::kCompareAndExchange:
1655 return 2;
1656 }
1657 UNREACHABLE();
1658 }
1659
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1660 bool FieldVarHandle::Access(AccessMode access_mode,
1661 ShadowFrame* shadow_frame,
1662 const InstructionOperands* const operands,
1663 JValue* result) {
1664 ShadowFrameGetter getter(*shadow_frame, operands);
1665 ArtField* field = GetArtField();
1666 ObjPtr<Object> obj;
1667 if (field->IsStatic()) {
1668 DCHECK_LE(operands->GetNumberOfOperands(),
1669 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1670 obj = field->GetDeclaringClass();
1671 } else {
1672 DCHECK_GE(operands->GetNumberOfOperands(), 1u);
1673 DCHECK_LE(operands->GetNumberOfOperands(),
1674 1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1675 obj = getter.GetReference();
1676 if (obj.IsNull()) {
1677 ThrowNullPointerExceptionForCoordinate();
1678 return false;
1679 }
1680 }
1681 DCHECK(!obj.IsNull());
1682
1683 const MemberOffset offset = field->GetOffset();
1684 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1685 switch (primitive_type) {
1686 case Primitive::Type::kPrimNot:
1687 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result);
1688 case Primitive::kPrimBoolean:
1689 return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1690 case Primitive::kPrimByte:
1691 return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1692 case Primitive::kPrimChar:
1693 return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1694 case Primitive::kPrimShort:
1695 return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1696 case Primitive::kPrimInt:
1697 return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result);
1698 case Primitive::kPrimFloat:
1699 return FieldAccessor<float>::Dispatch(access_mode, obj, offset, &getter, result);
1700 case Primitive::kPrimLong:
1701 return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result);
1702 case Primitive::kPrimDouble:
1703 return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result);
1704 case Primitive::kPrimVoid:
1705 break;
1706 }
1707 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1708 UNREACHABLE();
1709 }
1710
CheckArrayStore(AccessMode access_mode,ShadowFrameGetter getter,ObjPtr<ObjectArray<Object>> array)1711 bool ArrayElementVarHandle::CheckArrayStore(AccessMode access_mode,
1712 ShadowFrameGetter getter,
1713 ObjPtr<ObjectArray<Object>> array) {
1714 // This method checks the element being inserted into the array is correctly assignable.
1715 // NB This method assumes it is called from `ArrayElementVarHandle::Access()` and `getter`
1716 // has already consumed the array and index arguments.
1717 ObjPtr<Object> new_element;
1718 switch (GetAccessModeTemplate(access_mode)) {
1719 case AccessModeTemplate::kGet:
1720 return true; // Not a store.
1721 case AccessModeTemplate::kCompareAndExchange:
1722 case AccessModeTemplate::kCompareAndSet:
1723 getter.GetReference(); // Skip the comperand.
1724 new_element = getter.GetReference();
1725 break;
1726 case AccessModeTemplate::kGetAndUpdate:
1727 case AccessModeTemplate::kSet:
1728 new_element = getter.GetReference();
1729 break;
1730 }
1731 return array->CheckAssignable(new_element);
1732 }
1733
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1734 bool ArrayElementVarHandle::Access(AccessMode access_mode,
1735 ShadowFrame* shadow_frame,
1736 const InstructionOperands* const operands,
1737 JValue* result) {
1738 ShadowFrameGetter getter(*shadow_frame, operands);
1739
1740 // The target array is the first co-ordinate type preceeding var type arguments.
1741 ObjPtr<Object> raw_array(getter.GetReference());
1742 if (raw_array == nullptr) {
1743 ThrowNullPointerExceptionForCoordinate();
1744 return false;
1745 }
1746
1747 ObjPtr<Array> target_array = raw_array->AsArray();
1748
1749 // The target array element is the second co-ordinate type preceeding var type arguments.
1750 const int target_element = getter.Get();
1751 if (!target_array->CheckIsValidIndex(target_element)) {
1752 DCHECK(Thread::Current()->IsExceptionPending());
1753 return false;
1754 }
1755
1756 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1757 switch (primitive_type) {
1758 case Primitive::Type::kPrimNot: {
1759 ObjPtr<ObjectArray<Object>> object_array = target_array->AsObjectArray<Object>();
1760 if (!CheckArrayStore(access_mode, getter, object_array)) {
1761 DCHECK(Thread::Current()->IsExceptionPending());
1762 return false;
1763 }
1764 MemberOffset target_element_offset = object_array->OffsetOfElement(target_element);
1765 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode,
1766 target_array,
1767 target_element_offset,
1768 &getter,
1769 result);
1770 }
1771 case Primitive::Type::kPrimBoolean:
1772 return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode,
1773 target_array,
1774 target_element,
1775 &getter,
1776 result);
1777 case Primitive::Type::kPrimByte:
1778 return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode,
1779 target_array,
1780 target_element,
1781 &getter,
1782 result);
1783 case Primitive::Type::kPrimChar:
1784 return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode,
1785 target_array,
1786 target_element,
1787 &getter,
1788 result);
1789 case Primitive::Type::kPrimShort:
1790 return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode,
1791 target_array,
1792 target_element,
1793 &getter,
1794 result);
1795 case Primitive::Type::kPrimInt:
1796 return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode,
1797 target_array,
1798 target_element,
1799 &getter,
1800 result);
1801 case Primitive::Type::kPrimLong:
1802 return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode,
1803 target_array,
1804 target_element,
1805 &getter,
1806 result);
1807 case Primitive::Type::kPrimFloat:
1808 return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode,
1809 target_array,
1810 target_element,
1811 &getter,
1812 result);
1813 case Primitive::Type::kPrimDouble:
1814 return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode,
1815 target_array,
1816 target_element,
1817 &getter,
1818 result);
1819 case Primitive::Type::kPrimVoid:
1820 break;
1821 }
1822 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1823 UNREACHABLE();
1824 }
1825
GetNativeByteOrder()1826 bool ByteArrayViewVarHandle::GetNativeByteOrder() {
1827 return GetFieldBoolean(NativeByteOrderOffset());
1828 }
1829
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1830 bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
1831 ShadowFrame* shadow_frame,
1832 const InstructionOperands* const operands,
1833 JValue* result) {
1834 ShadowFrameGetter getter(*shadow_frame, operands);
1835
1836 // The byte array is the first co-ordinate type preceeding var type arguments.
1837 ObjPtr<Object> raw_byte_array(getter.GetReference());
1838 if (raw_byte_array == nullptr) {
1839 ThrowNullPointerExceptionForCoordinate();
1840 return false;
1841 }
1842
1843 ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray());
1844
1845 // The offset in the byte array element is the second co-ordinate type.
1846 const int32_t data_offset = getter.Get();
1847
1848 // Bounds check requested access.
1849 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1850 if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) {
1851 return false;
1852 }
1853
1854 int8_t* const data = byte_array->GetData();
1855 bool byte_swap = !GetNativeByteOrder();
1856 switch (primitive_type) {
1857 case Primitive::Type::kPrimNot:
1858 case Primitive::kPrimBoolean:
1859 case Primitive::kPrimByte:
1860 case Primitive::kPrimVoid:
1861 // These are not supported for byte array views and not instantiable.
1862 break;
1863 case Primitive::kPrimChar:
1864 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1865 data,
1866 data_offset,
1867 byte_swap,
1868 &getter,
1869 result);
1870 case Primitive::kPrimShort:
1871 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1872 data,
1873 data_offset,
1874 byte_swap,
1875 &getter,
1876 result);
1877 case Primitive::kPrimInt:
1878 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1879 data,
1880 data_offset,
1881 byte_swap,
1882 &getter,
1883 result);
1884 case Primitive::kPrimFloat:
1885 // Treated as a bitwise representation. See javadoc comments for
1886 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1887 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1888 data,
1889 data_offset,
1890 byte_swap,
1891 &getter,
1892 result);
1893 case Primitive::kPrimLong:
1894 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1895 data,
1896 data_offset,
1897 byte_swap,
1898 &getter,
1899 result);
1900 case Primitive::kPrimDouble:
1901 // Treated as a bitwise representation. See javadoc comments for
1902 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1903 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1904 data,
1905 data_offset,
1906 byte_swap,
1907 &getter,
1908 result);
1909 }
1910 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1911 UNREACHABLE();
1912 }
1913
GetNativeByteOrder()1914 bool ByteBufferViewVarHandle::GetNativeByteOrder() {
1915 return GetFieldBoolean(NativeByteOrderOffset());
1916 }
1917
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1918 bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
1919 ShadowFrame* shadow_frame,
1920 const InstructionOperands* const operands,
1921 JValue* result) {
1922 ShadowFrameGetter getter(*shadow_frame, operands);
1923
1924 // The byte buffer is the first co-ordinate argument preceeding var type arguments.
1925 ObjPtr<Object> byte_buffer(getter.GetReference());
1926 if (byte_buffer == nullptr) {
1927 ThrowNullPointerExceptionForCoordinate();
1928 return false;
1929 }
1930
1931 // The byte index for access is the second co-ordinate
1932 // argument. This is relative to the offset field of the ByteBuffer.
1933 const int32_t byte_index = getter.Get();
1934
1935 // Check access_mode is compatible with ByteBuffer's read-only property.
1936 bool is_read_only = byte_buffer->GetFieldBoolean(
1937 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_isReadOnly));
1938 if (is_read_only && !IsReadOnlyAccessMode(access_mode)) {
1939 ThrowReadOnlyBufferException();
1940 return false;
1941 }
1942
1943 // The native_address is only set for ByteBuffer instances backed by native memory.
1944 const int64_t native_address =
1945 byte_buffer->GetField64(GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_address));
1946
1947 // Determine offset and limit for accesses.
1948 int32_t byte_buffer_offset;
1949 if (native_address == 0L) {
1950 // Accessing a heap allocated byte buffer.
1951 byte_buffer_offset = byte_buffer->GetField32(
1952 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_offset));
1953 } else {
1954 // Accessing direct memory.
1955 byte_buffer_offset = 0;
1956 }
1957 const int32_t byte_buffer_limit = byte_buffer->GetField32(
1958 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_limit));
1959 const int32_t byte_buffer_length = byte_buffer_offset + byte_buffer_limit;
1960
1961 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1962 if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_length)) {
1963 return false;
1964 }
1965 const int32_t checked_offset32 = byte_buffer_offset + byte_index;
1966
1967 int8_t* data;
1968 if (native_address == 0) {
1969 ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>(
1970 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_hb));
1971 data = heap_byte_array->GetData();
1972 } else {
1973 data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address));
1974 }
1975
1976 bool byte_swap = !GetNativeByteOrder();
1977 switch (primitive_type) {
1978 case Primitive::kPrimChar:
1979 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1980 data,
1981 checked_offset32,
1982 byte_swap,
1983 &getter,
1984 result);
1985 case Primitive::kPrimShort:
1986 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1987 data,
1988 checked_offset32,
1989 byte_swap,
1990 &getter,
1991 result);
1992 case Primitive::kPrimInt:
1993 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1994 data,
1995 checked_offset32,
1996 byte_swap,
1997 &getter,
1998 result);
1999 case Primitive::kPrimFloat:
2000 // Treated as a bitwise representation. See javadoc comments for
2001 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
2002 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
2003 data,
2004 checked_offset32,
2005 byte_swap,
2006 &getter,
2007 result);
2008 case Primitive::kPrimLong:
2009 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2010 data,
2011 checked_offset32,
2012 byte_swap,
2013 &getter,
2014 result);
2015 case Primitive::kPrimDouble:
2016 // Treated as a bitwise representation. See javadoc comments for
2017 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
2018 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2019 data,
2020 checked_offset32,
2021 byte_swap,
2022 &getter,
2023 result);
2024 case Primitive::Type::kPrimNot:
2025 case Primitive::kPrimBoolean:
2026 case Primitive::kPrimByte:
2027 case Primitive::kPrimVoid:
2028 // These are not supported for byte array views and not instantiable.
2029 break;
2030 }
2031 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
2032 UNREACHABLE();
2033 }
2034
VisitTarget(ReflectiveValueVisitor * v)2035 void FieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) {
2036 ArtField* orig = GetArtField();
2037 ArtField* new_value =
2038 v->VisitField(orig, HeapReflectiveSourceInfo(kSourceJavaLangInvokeFieldVarHandle, this));
2039 if (orig != new_value) {
2040 SetArtField(new_value);
2041 }
2042 }
2043
VisitTarget(ReflectiveValueVisitor * v)2044 void StaticFieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) {
2045 ArtField* orig = GetArtField();
2046 ArtField* new_value =
2047 v->VisitField(orig, HeapReflectiveSourceInfo(kSourceJavaLangInvokeFieldVarHandle, this));
2048 if (orig != new_value) {
2049 SetArtField(new_value);
2050 SetFieldObject<false>(DeclaringClassOffset(), new_value->GetDeclaringClass());
2051 }
2052 }
2053
2054 } // namespace mirror
2055 } // namespace art
2056