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