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