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