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