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