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