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