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