• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "var_handle.h"
18 
19 #include "array-inl.h"
20 #include "art_field-inl.h"
21 #include "base/casts.h"
22 #include "class-inl.h"
23 #include "class_linker.h"
24 #include "class_root-inl.h"
25 #include "intrinsics_enum.h"
26 #include "jni/jni_internal.h"
27 #include "jvalue-inl.h"
28 #include "method_handles-inl.h"
29 #include "method_type-inl.h"
30 #include "object_array-alloc-inl.h"
31 #include "obj_ptr-inl.h"
32 #include "well_known_classes.h"
33 
34 namespace art {
35 namespace mirror {
36 
37 static constexpr bool kTransactionActive = true;
38 static constexpr bool kTransactionInactive = !kTransactionActive;
39 
40 namespace {
41 
42 struct VarHandleAccessorToAccessModeEntry {
43   const char* method_name;
44   VarHandle::AccessMode access_mode;
45 
46   // Binary predicate function for finding access_mode by
47   // method_name. The access_mode field is ignored.
CompareNameart::mirror::__anon84d86d5f0111::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 
GetMethodTypeMatchForAccessMode(AccessMode access_mode,ObjPtr<MethodType> method_type)1338 VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode,
1339                                                                 ObjPtr<MethodType> method_type) {
1340   MatchKind match = MatchKind::kExact;
1341 
1342   ObjPtr<VarHandle> vh = this;
1343   ObjPtr<Class> var_type = vh->GetVarType();
1344   ObjPtr<Class> mt_rtype = method_type->GetRType();
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[VarHandle::kMaxAccessorParameters];
1362   const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1363                                                       access_mode_template,
1364                                                       var_type,
1365                                                       GetCoordinateType0(),
1366                                                       GetCoordinateType1());
1367   if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
1368     return MatchKind::kNone;
1369   }
1370 
1371   // Check the parameter types are compatible.
1372   ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
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 
GetMethodTypeForAccessMode(Thread * self,ObjPtr<VarHandle> var_handle,AccessMode access_mode)1390 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
1391                                                          ObjPtr<VarHandle> var_handle,
1392                                                          AccessMode access_mode) {
1393   // This is a static method as the var_handle might be moved by the GC during it's execution.
1394   AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1395 
1396   StackHandleScope<3> hs(self);
1397   Handle<VarHandle> vh = hs.NewHandle(var_handle);
1398   Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType()));
1399   const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
1400                                                      vh->GetCoordinateType0(),
1401                                                      vh->GetCoordinateType1());
1402   ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>();
1403   Handle<ObjectArray<Class>> ptypes =
1404       hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
1405   if (ptypes == nullptr) {
1406     return nullptr;
1407   }
1408 
1409   ObjPtr<Class> ptypes_array[VarHandle::kMaxAccessorParameters];
1410   BuildParameterArray(ptypes_array,
1411                       access_mode_template,
1412                       vh->GetVarType(),
1413                       vh->GetCoordinateType0(),
1414                       vh->GetCoordinateType1());
1415   for (int32_t i = 0; i < ptypes_count; ++i) {
1416     ptypes->Set(i, ptypes_array[i]);
1417   }
1418   return MethodType::Create(self, rtype, ptypes);
1419 }
1420 
GetMethodTypeForAccessMode(Thread * self,AccessMode access_mode)1421 ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
1422   return GetMethodTypeForAccessMode(self, this, access_mode);
1423 }
1424 
PrettyDescriptorForAccessMode(AccessMode access_mode)1425 std::string VarHandle::PrettyDescriptorForAccessMode(AccessMode access_mode) {
1426   // Effect MethodType::PrettyDescriptor() without first creating a method type first.
1427   std::ostringstream oss;
1428   oss << '(';
1429 
1430   AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1431   ObjPtr<Class> var_type = GetVarType();
1432   ObjPtr<Class> ctypes[2] = { GetCoordinateType0(), GetCoordinateType1() };
1433   const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, ctypes[0], ctypes[1]);
1434   int32_t ptypes_done = 0;
1435   for (ObjPtr<Class> ctype : ctypes) {
1436     if (!ctype.IsNull()) {
1437       if (ptypes_done != 0) {
1438         oss << ", ";
1439       }
1440       oss << ctype->PrettyDescriptor();;
1441       ptypes_done++;
1442     }
1443   }
1444   while (ptypes_done != ptypes_count) {
1445     if (ptypes_done != 0) {
1446       oss << ", ";
1447     }
1448     oss << var_type->PrettyDescriptor();
1449     ptypes_done++;
1450   }
1451   ObjPtr<Class> rtype = GetReturnType(access_mode_template, var_type);
1452   oss << ')' << rtype->PrettyDescriptor();
1453   return oss.str();
1454 }
1455 
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1456 bool VarHandle::Access(AccessMode access_mode,
1457                        ShadowFrame* shadow_frame,
1458                        const InstructionOperands* const operands,
1459                        JValue* result) {
1460   ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
1461   ObjPtr<Class> klass = GetClass();
1462   if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
1463     auto vh = ObjPtr<FieldVarHandle>::DownCast(this);
1464     return vh->Access(access_mode, shadow_frame, operands, result);
1465   } else if (klass == GetClassRoot<StaticFieldVarHandle>(class_roots)) {
1466     auto vh = ObjPtr<StaticFieldVarHandle>::DownCast(this);
1467     return vh->Access(access_mode, shadow_frame, operands, result);
1468   } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
1469     auto vh = ObjPtr<ArrayElementVarHandle>::DownCast(this);
1470     return vh->Access(access_mode, shadow_frame, operands, result);
1471   } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
1472     auto vh = ObjPtr<ByteArrayViewVarHandle>::DownCast(this);
1473     return vh->Access(access_mode, shadow_frame, operands, result);
1474   } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
1475     auto vh = ObjPtr<ByteBufferViewVarHandle>::DownCast(this);
1476     return vh->Access(access_mode, shadow_frame, operands, result);
1477   } else {
1478     LOG(FATAL) << "Unknown varhandle kind";
1479     UNREACHABLE();
1480   }
1481 }
1482 
GetReturnTypeDescriptor(const char * accessor_name)1483 const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) {
1484   AccessMode access_mode;
1485   if (!GetAccessModeByMethodName(accessor_name, &access_mode)) {
1486     return nullptr;
1487   }
1488   AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1489   switch (access_mode_template) {
1490     case AccessModeTemplate::kGet:
1491     case AccessModeTemplate::kCompareAndExchange:
1492     case AccessModeTemplate::kGetAndUpdate:
1493       return "Ljava/lang/Object;";
1494     case AccessModeTemplate::kCompareAndSet:
1495       return "Z";
1496     case AccessModeTemplate::kSet:
1497       return "V";
1498   }
1499 }
1500 
GetAccessModeByIntrinsic(Intrinsics intrinsic)1501 VarHandle::AccessMode VarHandle::GetAccessModeByIntrinsic(Intrinsics intrinsic) {
1502 #define VAR_HANDLE_ACCESS_MODE(V)               \
1503     V(CompareAndExchange)                       \
1504     V(CompareAndExchangeAcquire)                \
1505     V(CompareAndExchangeRelease)                \
1506     V(CompareAndSet)                            \
1507     V(Get)                                      \
1508     V(GetAcquire)                               \
1509     V(GetAndAdd)                                \
1510     V(GetAndAddAcquire)                         \
1511     V(GetAndAddRelease)                         \
1512     V(GetAndBitwiseAnd)                         \
1513     V(GetAndBitwiseAndAcquire)                  \
1514     V(GetAndBitwiseAndRelease)                  \
1515     V(GetAndBitwiseOr)                          \
1516     V(GetAndBitwiseOrAcquire)                   \
1517     V(GetAndBitwiseOrRelease)                   \
1518     V(GetAndBitwiseXor)                         \
1519     V(GetAndBitwiseXorAcquire)                  \
1520     V(GetAndBitwiseXorRelease)                  \
1521     V(GetAndSet)                                \
1522     V(GetAndSetAcquire)                         \
1523     V(GetAndSetRelease)                         \
1524     V(GetOpaque)                                \
1525     V(GetVolatile)                              \
1526     V(Set)                                      \
1527     V(SetOpaque)                                \
1528     V(SetRelease)                               \
1529     V(SetVolatile)                              \
1530     V(WeakCompareAndSet)                        \
1531     V(WeakCompareAndSetAcquire)                 \
1532     V(WeakCompareAndSetPlain)                   \
1533     V(WeakCompareAndSetRelease)
1534   switch (intrinsic) {
1535 #define INTRINSIC_CASE(Name)                    \
1536     case Intrinsics::kVarHandle ## Name:        \
1537       return VarHandle::AccessMode::k ## Name;
1538     VAR_HANDLE_ACCESS_MODE(INTRINSIC_CASE)
1539 #undef INTRINSIC_CASE
1540 #undef VAR_HANDLE_ACCESS_MODE
1541     default:
1542       break;
1543   }
1544   LOG(FATAL) << "Unknown VarHandle instrinsic: " << static_cast<int>(intrinsic);
1545   UNREACHABLE();
1546 }
1547 
GetAccessModeByMethodName(const char * method_name,AccessMode * access_mode)1548 bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode) {
1549   if (method_name == nullptr) {
1550     return false;
1551   }
1552   const auto kUnusedAccessMode = VarHandle::AccessMode::kGet;  // arbitrary value.
1553   VarHandleAccessorToAccessModeEntry target = { method_name, kUnusedAccessMode };
1554   auto last = std::cend(kAccessorToAccessMode);
1555   auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode),
1556                              last,
1557                              target,
1558                              VarHandleAccessorToAccessModeEntry::CompareName);
1559   if (it == last || strcmp(it->method_name, method_name) != 0) {
1560     return false;
1561   }
1562   *access_mode = it->access_mode;
1563   return true;
1564 }
1565 
1566 // Look up the AccessModeTemplate for a given VarHandle
1567 // AccessMode. This simplifies finding the correct signature for a
1568 // VarHandle accessor method.
GetAccessModeTemplate(VarHandle::AccessMode access_mode)1569 VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
1570   switch (access_mode) {
1571     case VarHandle::AccessMode::kGet:
1572       return AccessModeTemplate::kGet;
1573     case VarHandle::AccessMode::kSet:
1574       return AccessModeTemplate::kSet;
1575     case VarHandle::AccessMode::kGetVolatile:
1576       return AccessModeTemplate::kGet;
1577     case VarHandle::AccessMode::kSetVolatile:
1578       return AccessModeTemplate::kSet;
1579     case VarHandle::AccessMode::kGetAcquire:
1580       return AccessModeTemplate::kGet;
1581     case VarHandle::AccessMode::kSetRelease:
1582       return AccessModeTemplate::kSet;
1583     case VarHandle::AccessMode::kGetOpaque:
1584       return AccessModeTemplate::kGet;
1585     case VarHandle::AccessMode::kSetOpaque:
1586       return AccessModeTemplate::kSet;
1587     case VarHandle::AccessMode::kCompareAndSet:
1588       return AccessModeTemplate::kCompareAndSet;
1589     case VarHandle::AccessMode::kCompareAndExchange:
1590       return AccessModeTemplate::kCompareAndExchange;
1591     case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1592       return AccessModeTemplate::kCompareAndExchange;
1593     case VarHandle::AccessMode::kCompareAndExchangeRelease:
1594       return AccessModeTemplate::kCompareAndExchange;
1595     case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1596       return AccessModeTemplate::kCompareAndSet;
1597     case VarHandle::AccessMode::kWeakCompareAndSet:
1598       return AccessModeTemplate::kCompareAndSet;
1599     case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1600       return AccessModeTemplate::kCompareAndSet;
1601     case VarHandle::AccessMode::kWeakCompareAndSetRelease:
1602       return AccessModeTemplate::kCompareAndSet;
1603     case VarHandle::AccessMode::kGetAndSet:
1604       return AccessModeTemplate::kGetAndUpdate;
1605     case VarHandle::AccessMode::kGetAndSetAcquire:
1606       return AccessModeTemplate::kGetAndUpdate;
1607     case VarHandle::AccessMode::kGetAndSetRelease:
1608       return AccessModeTemplate::kGetAndUpdate;
1609     case VarHandle::AccessMode::kGetAndAdd:
1610       return AccessModeTemplate::kGetAndUpdate;
1611     case VarHandle::AccessMode::kGetAndAddAcquire:
1612       return AccessModeTemplate::kGetAndUpdate;
1613     case VarHandle::AccessMode::kGetAndAddRelease:
1614       return AccessModeTemplate::kGetAndUpdate;
1615     case VarHandle::AccessMode::kGetAndBitwiseOr:
1616       return AccessModeTemplate::kGetAndUpdate;
1617     case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
1618       return AccessModeTemplate::kGetAndUpdate;
1619     case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1620       return AccessModeTemplate::kGetAndUpdate;
1621     case VarHandle::AccessMode::kGetAndBitwiseAnd:
1622       return AccessModeTemplate::kGetAndUpdate;
1623     case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
1624       return AccessModeTemplate::kGetAndUpdate;
1625     case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1626       return AccessModeTemplate::kGetAndUpdate;
1627     case VarHandle::AccessMode::kGetAndBitwiseXor:
1628       return AccessModeTemplate::kGetAndUpdate;
1629     case VarHandle::AccessMode::kGetAndBitwiseXorRelease:
1630       return AccessModeTemplate::kGetAndUpdate;
1631     case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1632       return AccessModeTemplate::kGetAndUpdate;
1633   }
1634 }
1635 
GetAccessModeTemplateByIntrinsic(Intrinsics ordinal)1636 VarHandle::AccessModeTemplate VarHandle::GetAccessModeTemplateByIntrinsic(Intrinsics ordinal) {
1637   AccessMode access_mode = GetAccessModeByIntrinsic(ordinal);
1638   return GetAccessModeTemplate(access_mode);
1639 }
1640 
GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template)1641 int32_t VarHandle::GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
1642   switch (access_mode_template) {
1643     case AccessModeTemplate::kGet:
1644       return 0;
1645     case AccessModeTemplate::kSet:
1646     case AccessModeTemplate::kGetAndUpdate:
1647       return 1;
1648     case AccessModeTemplate::kCompareAndSet:
1649     case AccessModeTemplate::kCompareAndExchange:
1650       return 2;
1651   }
1652   UNREACHABLE();
1653 }
1654 
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1655 bool FieldVarHandle::Access(AccessMode access_mode,
1656                             ShadowFrame* shadow_frame,
1657                             const InstructionOperands* const operands,
1658                             JValue* result) {
1659   ShadowFrameGetter getter(*shadow_frame, operands);
1660   ArtField* field = GetArtField();
1661   ObjPtr<Object> obj;
1662   if (field->IsStatic()) {
1663     DCHECK_LE(operands->GetNumberOfOperands(),
1664               2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1665     obj = field->GetDeclaringClass();
1666   } else {
1667     DCHECK_GE(operands->GetNumberOfOperands(), 1u);
1668     DCHECK_LE(operands->GetNumberOfOperands(),
1669               1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1670     obj = getter.GetReference();
1671     if (obj.IsNull()) {
1672       ThrowNullPointerExceptionForCoordinate();
1673       return false;
1674     }
1675   }
1676   DCHECK(!obj.IsNull());
1677 
1678   const MemberOffset offset = field->GetOffset();
1679   const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1680   switch (primitive_type) {
1681     case Primitive::Type::kPrimNot:
1682       return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result);
1683     case Primitive::kPrimBoolean:
1684       return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1685     case Primitive::kPrimByte:
1686       return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1687     case Primitive::kPrimChar:
1688       return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1689     case Primitive::kPrimShort:
1690       return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1691     case Primitive::kPrimInt:
1692       return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result);
1693     case Primitive::kPrimFloat:
1694       return FieldAccessor<float>::Dispatch(access_mode,  obj, offset, &getter, result);
1695     case Primitive::kPrimLong:
1696       return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result);
1697     case Primitive::kPrimDouble:
1698       return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result);
1699     case Primitive::kPrimVoid:
1700       break;
1701   }
1702   LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1703   UNREACHABLE();
1704 }
1705 
CheckArrayStore(AccessMode access_mode,ShadowFrameGetter getter,ObjPtr<ObjectArray<Object>> array)1706 bool ArrayElementVarHandle::CheckArrayStore(AccessMode access_mode,
1707                                             ShadowFrameGetter getter,
1708                                             ObjPtr<ObjectArray<Object>> array) {
1709   // This method checks the element being inserted into the array is correctly assignable.
1710   // NB This method assumes it is called from `ArrayElementVarHandle::Access()` and `getter`
1711   // has already consumed the array and index arguments.
1712   ObjPtr<Object> new_element;
1713   switch (GetAccessModeTemplate(access_mode)) {
1714     case AccessModeTemplate::kGet:
1715       return true;  // Not a store.
1716     case AccessModeTemplate::kCompareAndExchange:
1717     case AccessModeTemplate::kCompareAndSet:
1718       getter.GetReference();  // Skip the comperand.
1719       new_element = getter.GetReference();
1720       break;
1721     case AccessModeTemplate::kGetAndUpdate:
1722     case AccessModeTemplate::kSet:
1723       new_element = getter.GetReference();
1724       break;
1725   }
1726   return array->CheckAssignable(new_element);
1727 }
1728 
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1729 bool ArrayElementVarHandle::Access(AccessMode access_mode,
1730                                    ShadowFrame* shadow_frame,
1731                                    const InstructionOperands* const operands,
1732                                    JValue* result) {
1733   ShadowFrameGetter getter(*shadow_frame, operands);
1734 
1735   // The target array is the first co-ordinate type preceeding var type arguments.
1736   ObjPtr<Object> raw_array(getter.GetReference());
1737   if (raw_array == nullptr) {
1738     ThrowNullPointerExceptionForCoordinate();
1739     return false;
1740   }
1741 
1742   ObjPtr<Array> target_array = raw_array->AsArray();
1743 
1744   // The target array element is the second co-ordinate type preceeding var type arguments.
1745   const int target_element = getter.Get();
1746   if (!target_array->CheckIsValidIndex(target_element)) {
1747     DCHECK(Thread::Current()->IsExceptionPending());
1748     return false;
1749   }
1750 
1751   const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1752   switch (primitive_type) {
1753     case Primitive::Type::kPrimNot: {
1754       ObjPtr<ObjectArray<Object>> object_array = target_array->AsObjectArray<Object>();
1755       if (!CheckArrayStore(access_mode, getter, object_array)) {
1756         DCHECK(Thread::Current()->IsExceptionPending());
1757         return false;
1758       }
1759       MemberOffset target_element_offset = object_array->OffsetOfElement(target_element);
1760       return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode,
1761                                                      target_array,
1762                                                      target_element_offset,
1763                                                      &getter,
1764                                                      result);
1765     }
1766     case Primitive::Type::kPrimBoolean:
1767       return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode,
1768                                                               target_array,
1769                                                               target_element,
1770                                                               &getter,
1771                                                               result);
1772     case Primitive::Type::kPrimByte:
1773       return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode,
1774                                                              target_array,
1775                                                              target_element,
1776                                                              &getter,
1777                                                              result);
1778     case Primitive::Type::kPrimChar:
1779       return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode,
1780                                                                target_array,
1781                                                                target_element,
1782                                                                &getter,
1783                                                                result);
1784     case Primitive::Type::kPrimShort:
1785       return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode,
1786                                                               target_array,
1787                                                               target_element,
1788                                                               &getter,
1789                                                               result);
1790     case Primitive::Type::kPrimInt:
1791       return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode,
1792                                                               target_array,
1793                                                               target_element,
1794                                                               &getter,
1795                                                               result);
1796     case Primitive::Type::kPrimLong:
1797       return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode,
1798                                                               target_array,
1799                                                               target_element,
1800                                                               &getter,
1801                                                               result);
1802     case Primitive::Type::kPrimFloat:
1803       return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode,
1804                                                             target_array,
1805                                                             target_element,
1806                                                             &getter,
1807                                                             result);
1808     case Primitive::Type::kPrimDouble:
1809       return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode,
1810                                                              target_array,
1811                                                              target_element,
1812                                                              &getter,
1813                                                              result);
1814     case Primitive::Type::kPrimVoid:
1815       break;
1816   }
1817   LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1818   UNREACHABLE();
1819 }
1820 
GetNativeByteOrder()1821 bool ByteArrayViewVarHandle::GetNativeByteOrder() {
1822   return GetFieldBoolean(NativeByteOrderOffset());
1823 }
1824 
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1825 bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
1826                                     ShadowFrame* shadow_frame,
1827                                     const InstructionOperands* const operands,
1828                                     JValue* result) {
1829   ShadowFrameGetter getter(*shadow_frame, operands);
1830 
1831   // The byte array is the first co-ordinate type preceeding var type arguments.
1832   ObjPtr<Object> raw_byte_array(getter.GetReference());
1833   if (raw_byte_array == nullptr) {
1834     ThrowNullPointerExceptionForCoordinate();
1835     return false;
1836   }
1837 
1838   ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray());
1839 
1840   // The offset in the byte array element is the second co-ordinate type.
1841   const int32_t data_offset = getter.Get();
1842 
1843   // Bounds check requested access.
1844   const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1845   if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) {
1846     return false;
1847   }
1848 
1849   int8_t* const data = byte_array->GetData();
1850   bool byte_swap = !GetNativeByteOrder();
1851   switch (primitive_type) {
1852     case Primitive::Type::kPrimNot:
1853     case Primitive::kPrimBoolean:
1854     case Primitive::kPrimByte:
1855     case Primitive::kPrimVoid:
1856       // These are not supported for byte array views and not instantiable.
1857       break;
1858     case Primitive::kPrimChar:
1859       return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1860                                                        data,
1861                                                        data_offset,
1862                                                        byte_swap,
1863                                                        &getter,
1864                                                        result);
1865     case Primitive::kPrimShort:
1866       return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1867                                                       data,
1868                                                       data_offset,
1869                                                       byte_swap,
1870                                                       &getter,
1871                                                       result);
1872     case Primitive::kPrimInt:
1873       return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1874                                                       data,
1875                                                       data_offset,
1876                                                       byte_swap,
1877                                                       &getter,
1878                                                       result);
1879     case Primitive::kPrimFloat:
1880       // Treated as a bitwise representation. See javadoc comments for
1881       // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1882       return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1883                                                       data,
1884                                                       data_offset,
1885                                                       byte_swap,
1886                                                       &getter,
1887                                                       result);
1888     case Primitive::kPrimLong:
1889       return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1890                                                       data,
1891                                                       data_offset,
1892                                                       byte_swap,
1893                                                       &getter,
1894                                                       result);
1895     case Primitive::kPrimDouble:
1896       // Treated as a bitwise representation. See javadoc comments for
1897       // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1898       return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1899                                                       data,
1900                                                       data_offset,
1901                                                       byte_swap,
1902                                                       &getter,
1903                                                       result);
1904   }
1905   LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1906   UNREACHABLE();
1907 }
1908 
GetNativeByteOrder()1909 bool ByteBufferViewVarHandle::GetNativeByteOrder() {
1910   return GetFieldBoolean(NativeByteOrderOffset());
1911 }
1912 
Access(AccessMode access_mode,ShadowFrame * shadow_frame,const InstructionOperands * const operands,JValue * result)1913 bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
1914                                      ShadowFrame* shadow_frame,
1915                                      const InstructionOperands* const operands,
1916                                      JValue* result) {
1917   ShadowFrameGetter getter(*shadow_frame, operands);
1918 
1919   // The byte buffer is the first co-ordinate argument preceeding var type arguments.
1920   ObjPtr<Object> byte_buffer(getter.GetReference());
1921   if (byte_buffer == nullptr) {
1922     ThrowNullPointerExceptionForCoordinate();
1923     return false;
1924   }
1925 
1926   // The byte index for access is the second co-ordinate
1927   // argument. This is relative to the offset field of the ByteBuffer.
1928   const int32_t byte_index = getter.Get();
1929 
1930   // Check access_mode is compatible with ByteBuffer's read-only property.
1931   bool is_read_only = byte_buffer->GetFieldBoolean(
1932       WellKnownClasses::java_nio_ByteBuffer_isReadOnly->GetOffset());
1933   if (is_read_only && !IsReadOnlyAccessMode(access_mode)) {
1934     ThrowReadOnlyBufferException();
1935     return false;
1936   }
1937 
1938   // The native_address is only set for ByteBuffer instances backed by native memory.
1939   const int64_t native_address =
1940       byte_buffer->GetField64(WellKnownClasses::java_nio_Buffer_address->GetOffset());
1941 
1942   // Determine offset and limit for accesses.
1943   int32_t byte_buffer_offset;
1944   if (native_address == 0L) {
1945     // Accessing a heap allocated byte buffer.
1946     byte_buffer_offset = byte_buffer->GetField32(
1947         WellKnownClasses::java_nio_ByteBuffer_offset->GetOffset());
1948   } else {
1949     // Accessing direct memory.
1950     byte_buffer_offset = 0;
1951   }
1952   const int32_t byte_buffer_limit =
1953       byte_buffer->GetField32(WellKnownClasses::java_nio_Buffer_limit->GetOffset());
1954   const int32_t byte_buffer_length = byte_buffer_offset + byte_buffer_limit;
1955 
1956   const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1957   if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_length)) {
1958     return false;
1959   }
1960   const int32_t checked_offset32 = byte_buffer_offset + byte_index;
1961 
1962   int8_t* data;
1963   if (native_address == 0) {
1964     ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>(
1965         WellKnownClasses::java_nio_ByteBuffer_hb->GetOffset());
1966     data = heap_byte_array->GetData();
1967   } else {
1968     data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address));
1969   }
1970 
1971   bool byte_swap = !GetNativeByteOrder();
1972   switch (primitive_type) {
1973     case Primitive::kPrimChar:
1974       return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1975                                                        data,
1976                                                        checked_offset32,
1977                                                        byte_swap,
1978                                                        &getter,
1979                                                        result);
1980     case Primitive::kPrimShort:
1981       return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1982                                                       data,
1983                                                       checked_offset32,
1984                                                       byte_swap,
1985                                                       &getter,
1986                                                       result);
1987     case Primitive::kPrimInt:
1988       return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1989                                                       data,
1990                                                       checked_offset32,
1991                                                       byte_swap,
1992                                                       &getter,
1993                                                       result);
1994     case Primitive::kPrimFloat:
1995       // Treated as a bitwise representation. See javadoc comments for
1996       // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1997       return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1998                                                       data,
1999                                                       checked_offset32,
2000                                                       byte_swap,
2001                                                       &getter,
2002                                                       result);
2003     case Primitive::kPrimLong:
2004       return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2005                                                       data,
2006                                                       checked_offset32,
2007                                                       byte_swap,
2008                                                       &getter,
2009                                                       result);
2010     case Primitive::kPrimDouble:
2011       // Treated as a bitwise representation. See javadoc comments for
2012       // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
2013       return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2014                                                       data,
2015                                                       checked_offset32,
2016                                                       byte_swap,
2017                                                       &getter,
2018                                                       result);
2019     case Primitive::Type::kPrimNot:
2020     case Primitive::kPrimBoolean:
2021     case Primitive::kPrimByte:
2022     case Primitive::kPrimVoid:
2023       // These are not supported for byte array views and not instantiable.
2024       break;
2025   }
2026   LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
2027   UNREACHABLE();
2028 }
2029 
VisitTarget(ReflectiveValueVisitor * v)2030 void FieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) {
2031   ArtField* orig = GetArtField();
2032   ArtField* new_value =
2033       v->VisitField(orig, HeapReflectiveSourceInfo(kSourceJavaLangInvokeFieldVarHandle, this));
2034   if (orig != new_value) {
2035     SetArtField(new_value);
2036   }
2037 }
2038 
VisitTarget(ReflectiveValueVisitor * v)2039 void StaticFieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) {
2040   ArtField* orig = GetArtField();
2041   ArtField* new_value =
2042       v->VisitField(orig, HeapReflectiveSourceInfo(kSourceJavaLangInvokeFieldVarHandle, this));
2043   if (orig != new_value) {
2044     SetArtField(new_value);
2045     SetFieldObject<false>(DeclaringClassOffset(), new_value->GetDeclaringClass());
2046   }
2047 }
2048 
2049 }  // namespace mirror
2050 }  // namespace art
2051