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