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> (&parameters)[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