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