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> (¶meters)[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