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