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