blob: ce794084d1907fa7f201f4c6dd180dddd62b2fc6 [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>
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100356class JValueByteSwapper final {
Orion Hodson928033d2018-02-07 05:30:54 +0000357 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100395 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000396 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100409 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000410 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100434 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000435 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100456 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000457 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100478 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000479 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100499 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000500 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100543 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000544 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100565 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000566 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100594 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000595 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100613 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000614 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100633 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000634 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
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100682 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000683 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:
Andreas Gampec55bb392018-09-21 00:02:02 +0000694 using Accessor = Object::Accessor<T>;
Orion Hodson928033d2018-02-07 05:30:54 +0000695
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()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001024 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
1025 expected_value,
1026 desired_value,
1027 CASMode::kStrong,
1028 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001029 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001030 cas_result = obj->CasFieldObject<kTransactionInactive>(field_offset,
1031 expected_value,
1032 desired_value,
1033 CASMode::kStrong,
1034 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001035 }
1036 StoreResult(cas_result, result);
1037 break;
1038 }
1039 case VarHandle::AccessMode::kWeakCompareAndSet:
1040 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1041 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1042 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1043 ReadBarrierForVarHandleAccess(obj, field_offset);
1044 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1045 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1046 bool cas_result;
1047 if (Runtime::Current()->IsActiveTransaction()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001048 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
1049 expected_value,
1050 desired_value,
1051 CASMode::kWeak,
1052 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001053 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001054 cas_result = obj->CasFieldObject<kTransactionInactive>(
Orion Hodson928033d2018-02-07 05:30:54 +00001055 field_offset,
1056 expected_value,
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001057 desired_value,
1058 CASMode::kWeak,
1059 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001060 }
1061 StoreResult(cas_result, result);
1062 break;
1063 }
1064 case VarHandle::AccessMode::kCompareAndExchange:
1065 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1066 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1067 ReadBarrierForVarHandleAccess(obj, field_offset);
1068 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1069 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1070 ObjPtr<Object> witness_value;
1071 if (Runtime::Current()->IsActiveTransaction()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001072 witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>(field_offset,
1073 expected_value,
1074 desired_value);
Orion Hodson928033d2018-02-07 05:30:54 +00001075 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001076 witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>(field_offset,
1077 expected_value,
1078 desired_value);
Orion Hodson928033d2018-02-07 05:30:54 +00001079 }
1080 StoreResult(witness_value, result);
1081 break;
1082 }
1083 case VarHandle::AccessMode::kGetAndSet:
1084 case VarHandle::AccessMode::kGetAndSetAcquire:
1085 case VarHandle::AccessMode::kGetAndSetRelease: {
1086 ReadBarrierForVarHandleAccess(obj, field_offset);
1087 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1088 ObjPtr<Object> old_value;
1089 if (Runtime::Current()->IsActiveTransaction()) {
1090 old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value);
1091 } else {
1092 old_value = obj->ExchangeFieldObject<kTransactionInactive>(field_offset, new_value);
1093 }
1094 StoreResult(old_value, result);
1095 break;
1096 }
1097 case VarHandle::AccessMode::kGetAndAdd:
1098 case VarHandle::AccessMode::kGetAndAddAcquire:
1099 case VarHandle::AccessMode::kGetAndAddRelease:
1100 case VarHandle::AccessMode::kGetAndBitwiseOr:
1101 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1102 case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
1103 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1104 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1105 case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
1106 case VarHandle::AccessMode::kGetAndBitwiseXor:
1107 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1108 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1109 size_t index = static_cast<size_t>(access_mode);
1110 const char* access_mode_name = kAccessorToAccessMode[index].method_name;
1111 UnreachableAccessMode(access_mode_name, "Object");
1112 }
1113 }
1114 return true;
1115}
1116
1117// Class for accessing primitive array elements.
1118template <typename T>
1119class PrimitiveArrayElementAccessor {
1120 public:
1121 static T* GetElementAddress(ObjPtr<Array> target_array, int target_element)
1122 REQUIRES_SHARED(Locks::mutator_lock_) {
1123 auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array);
1124 DCHECK(primitive_array->CheckIsValidIndex(target_element));
1125 return &primitive_array->GetData()[target_element];
1126 }
1127
1128 static bool Dispatch(VarHandle::AccessMode access_mode,
1129 ObjPtr<Array> target_array,
1130 int target_element,
1131 ShadowFrameGetter* getter,
1132 JValue* result)
1133 REQUIRES_SHARED(Locks::mutator_lock_) {
1134 T* element_address = GetElementAddress(target_array, target_element);
1135 switch (access_mode) {
1136 case VarHandle::AccessMode::kGet: {
1137 GetAccessor<T> accessor(result);
1138 accessor.Access(element_address);
1139 break;
1140 }
1141 case VarHandle::AccessMode::kSet: {
1142 T new_value = ValueGetter<T>::Get(getter);
1143 SetAccessor<T> accessor(new_value);
1144 accessor.Access(element_address);
1145 break;
1146 }
1147 case VarHandle::AccessMode::kGetAcquire:
1148 case VarHandle::AccessMode::kGetOpaque:
1149 case VarHandle::AccessMode::kGetVolatile: {
1150 GetVolatileAccessor<T> accessor(result);
1151 accessor.Access(element_address);
1152 break;
1153 }
1154 case VarHandle::AccessMode::kSetOpaque:
1155 case VarHandle::AccessMode::kSetRelease:
1156 case VarHandle::AccessMode::kSetVolatile: {
1157 T new_value = ValueGetter<T>::Get(getter);
1158 SetVolatileAccessor<T> accessor(new_value);
1159 accessor.Access(element_address);
1160 break;
1161 }
1162 case VarHandle::AccessMode::kCompareAndSet: {
1163 T expected_value = ValueGetter<T>::Get(getter);
1164 T desired_value = ValueGetter<T>::Get(getter);
1165 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1166 accessor.Access(element_address);
1167 break;
1168 }
1169 case VarHandle::AccessMode::kCompareAndExchange:
1170 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1171 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1172 T expected_value = ValueGetter<T>::Get(getter);
1173 T desired_value = ValueGetter<T>::Get(getter);
1174 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1175 accessor.Access(element_address);
1176 break;
1177 }
1178 case VarHandle::AccessMode::kWeakCompareAndSet:
1179 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1180 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1181 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1182 T expected_value = ValueGetter<T>::Get(getter);
1183 T desired_value = ValueGetter<T>::Get(getter);
1184 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1185 accessor.Access(element_address);
1186 break;
1187 }
1188 case VarHandle::AccessMode::kGetAndSet:
1189 case VarHandle::AccessMode::kGetAndSetAcquire:
1190 case VarHandle::AccessMode::kGetAndSetRelease: {
1191 T new_value = ValueGetter<T>::Get(getter);
1192 GetAndSetAccessor<T> accessor(new_value, result);
1193 accessor.Access(element_address);
1194 break;
1195 }
1196 case VarHandle::AccessMode::kGetAndAdd:
1197 case VarHandle::AccessMode::kGetAndAddAcquire:
1198 case VarHandle::AccessMode::kGetAndAddRelease: {
1199 T value = ValueGetter<T>::Get(getter);
1200 GetAndAddAccessor<T> accessor(value, result);
1201 accessor.Access(element_address);
1202 break;
1203 }
1204 case VarHandle::AccessMode::kGetAndBitwiseOr:
1205 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1206 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1207 T value = ValueGetter<T>::Get(getter);
1208 GetAndBitwiseOrAccessor<T> accessor(value, result);
1209 accessor.Access(element_address);
1210 break;
1211 }
1212 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1213 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1214 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1215 T value = ValueGetter<T>::Get(getter);
1216 GetAndBitwiseAndAccessor<T> accessor(value, result);
1217 accessor.Access(element_address);
1218 break;
1219 }
1220 case VarHandle::AccessMode::kGetAndBitwiseXor:
1221 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1222 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1223 T value = ValueGetter<T>::Get(getter);
1224 GetAndBitwiseXorAccessor<T> accessor(value, result);
1225 accessor.Access(element_address);
1226 break;
1227 }
1228 }
1229 return true;
1230 }
1231};
1232
1233// Class for accessing primitive array elements.
1234template <typename T>
1235class ByteArrayViewAccessor {
1236 public:
1237 static inline bool IsAccessAligned(int8_t* data, int data_index) {
1238 static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size");
1239 static_assert(std::is_arithmetic<T>::value, "unexpected type");
1240 uintptr_t alignment_mask = sizeof(T) - 1;
1241 uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index);
1242 return (address & alignment_mask) == 0;
1243 }
1244
1245 static inline void MaybeByteSwap(bool byte_swap, T* const value) {
1246 if (byte_swap) {
1247 *value = BSWAP(*value);
1248 }
1249 }
1250
1251 static bool Dispatch(const VarHandle::AccessMode access_mode,
1252 int8_t* const data,
1253 const int data_index,
1254 const bool byte_swap,
1255 ShadowFrameGetter* const getter,
1256 JValue* const result)
1257 REQUIRES_SHARED(Locks::mutator_lock_) {
1258 const bool is_aligned = IsAccessAligned(data, data_index);
1259 if (!is_aligned) {
1260 switch (access_mode) {
1261 case VarHandle::AccessMode::kGet: {
1262 T value;
1263 memcpy(&value, data + data_index, sizeof(T));
1264 MaybeByteSwap(byte_swap, &value);
1265 StoreResult(value, result);
1266 return true;
1267 }
1268 case VarHandle::AccessMode::kSet: {
1269 T new_value = ValueGetter<T>::Get(getter);
1270 MaybeByteSwap(byte_swap, &new_value);
1271 memcpy(data + data_index, &new_value, sizeof(T));
1272 return true;
1273 }
1274 default:
1275 // No other access modes support unaligned access.
1276 ThrowIllegalStateException("Unaligned access not supported");
1277 return false;
1278 }
1279 }
1280
1281 T* const element_address = reinterpret_cast<T*>(data + data_index);
1282 CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0));
1283 switch (access_mode) {
1284 case VarHandle::AccessMode::kGet: {
1285 GetAccessor<T> accessor(result);
1286 accessor.Access(element_address);
1287 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1288 break;
1289 }
1290 case VarHandle::AccessMode::kSet: {
1291 T new_value = ValueGetter<T>::Get(getter);
1292 MaybeByteSwap(byte_swap, &new_value);
1293 SetAccessor<T> accessor(new_value);
1294 accessor.Access(element_address);
1295 break;
1296 }
1297 case VarHandle::AccessMode::kGetAcquire:
1298 case VarHandle::AccessMode::kGetOpaque:
1299 case VarHandle::AccessMode::kGetVolatile: {
1300 GetVolatileAccessor<T> accessor(result);
1301 accessor.Access(element_address);
1302 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1303 break;
1304 }
1305 case VarHandle::AccessMode::kSetOpaque:
1306 case VarHandle::AccessMode::kSetRelease:
1307 case VarHandle::AccessMode::kSetVolatile: {
1308 T new_value = ValueGetter<T>::Get(getter);
1309 MaybeByteSwap(byte_swap, &new_value);
1310 SetVolatileAccessor<T> accessor(new_value);
1311 accessor.Access(element_address);
1312 break;
1313 }
1314 case VarHandle::AccessMode::kCompareAndSet: {
1315 T expected_value = ValueGetter<T>::Get(getter);
1316 T desired_value = ValueGetter<T>::Get(getter);
1317 MaybeByteSwap(byte_swap, &expected_value);
1318 MaybeByteSwap(byte_swap, &desired_value);
1319 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1320 accessor.Access(element_address);
1321 break;
1322 }
1323 case VarHandle::AccessMode::kCompareAndExchange:
1324 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1325 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1326 T expected_value = ValueGetter<T>::Get(getter);
1327 T desired_value = ValueGetter<T>::Get(getter);
1328 MaybeByteSwap(byte_swap, &expected_value);
1329 MaybeByteSwap(byte_swap, &desired_value);
1330 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1331 accessor.Access(element_address);
1332 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1333 break;
1334 }
1335 case VarHandle::AccessMode::kWeakCompareAndSet:
1336 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1337 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1338 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1339 T expected_value = ValueGetter<T>::Get(getter);
1340 T desired_value = ValueGetter<T>::Get(getter);
1341 MaybeByteSwap(byte_swap, &expected_value);
1342 MaybeByteSwap(byte_swap, &desired_value);
1343 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1344 accessor.Access(element_address);
1345 break;
1346 }
1347 case VarHandle::AccessMode::kGetAndSet:
1348 case VarHandle::AccessMode::kGetAndSetAcquire:
1349 case VarHandle::AccessMode::kGetAndSetRelease: {
1350 T new_value = ValueGetter<T>::Get(getter);
1351 MaybeByteSwap(byte_swap, &new_value);
1352 GetAndSetAccessor<T> accessor(new_value, result);
1353 accessor.Access(element_address);
1354 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1355 break;
1356 }
1357 case VarHandle::AccessMode::kGetAndAdd:
1358 case VarHandle::AccessMode::kGetAndAddAcquire:
1359 case VarHandle::AccessMode::kGetAndAddRelease: {
1360 T value = ValueGetter<T>::Get(getter);
1361 if (byte_swap) {
1362 GetAndAddWithByteSwapAccessor<T> accessor(value, result);
1363 accessor.Access(element_address);
1364 } else {
1365 GetAndAddAccessor<T> accessor(value, result);
1366 accessor.Access(element_address);
1367 }
1368 break;
1369 }
1370 case VarHandle::AccessMode::kGetAndBitwiseOr:
1371 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1372 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1373 T value = ValueGetter<T>::Get(getter);
1374 MaybeByteSwap(byte_swap, &value);
1375 GetAndBitwiseOrAccessor<T> accessor(value, result);
1376 accessor.Access(element_address);
1377 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1378 break;
1379 }
1380 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1381 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1382 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1383 T value = ValueGetter<T>::Get(getter);
1384 MaybeByteSwap(byte_swap, &value);
1385 GetAndBitwiseAndAccessor<T> accessor(value, result);
1386 accessor.Access(element_address);
1387 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1388 break;
1389 }
1390 case VarHandle::AccessMode::kGetAndBitwiseXor:
1391 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1392 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1393 T value = ValueGetter<T>::Get(getter);
1394 MaybeByteSwap(byte_swap, &value);
1395 GetAndBitwiseXorAccessor<T> accessor(value, result);
1396 accessor.Access(element_address);
1397 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1398 break;
1399 }
1400 }
1401 return true;
1402 }
1403};
1404
Orion Hodson005ac512017-10-24 15:43:43 +01001405} // namespace
1406
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001407ObjPtr<Class> VarHandle::GetVarType() {
Orion Hodson005ac512017-10-24 15:43:43 +01001408 return GetFieldObject<Class>(VarTypeOffset());
1409}
1410
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001411ObjPtr<Class> VarHandle::GetCoordinateType0() {
Orion Hodson005ac512017-10-24 15:43:43 +01001412 return GetFieldObject<Class>(CoordinateType0Offset());
1413}
1414
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001415ObjPtr<Class> VarHandle::GetCoordinateType1() {
Orion Hodson005ac512017-10-24 15:43:43 +01001416 return GetFieldObject<Class>(CoordinateType1Offset());
1417}
1418
1419int32_t VarHandle::GetAccessModesBitMask() {
1420 return GetField32(AccessModesBitMaskOffset());
1421}
1422
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001423VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode,
1424 MethodType* method_type) {
1425 MatchKind match = MatchKind::kExact;
1426
1427 ObjPtr<VarHandle> vh = this;
1428 ObjPtr<Class> var_type = vh->GetVarType();
1429 ObjPtr<Class> mt_rtype = method_type->GetRType();
Orion Hodsonc4d3bf42018-02-06 16:02:49 +00001430 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
Orion Hodsonc4d3bf42018-02-06 16:02:49 +00001431
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001432 // Check return type first. If the return type of the method
1433 // of the VarHandle is immaterial.
1434 if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001435 ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001436 if (vh_rtype != mt_rtype) {
1437 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
1438 return MatchKind::kNone;
1439 }
1440 match = MatchKind::kWithConversions;
Orion Hodson928033d2018-02-07 05:30:54 +00001441 }
Orion Hodson005ac512017-10-24 15:43:43 +01001442 }
1443
1444 // Check the number of parameters matches.
1445 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
1446 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1447 access_mode_template,
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001448 var_type,
Orion Hodson005ac512017-10-24 15:43:43 +01001449 GetCoordinateType0(),
1450 GetCoordinateType1());
1451 if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001452 return MatchKind::kNone;
Orion Hodson005ac512017-10-24 15:43:43 +01001453 }
1454
Orion Hodson928033d2018-02-07 05:30:54 +00001455 // Check the parameter types are compatible.
Orion Hodson005ac512017-10-24 15:43:43 +01001456 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
1457 for (int32_t i = 0; i < vh_ptypes_count; ++i) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001458 if (mt_ptypes->Get(i) == vh_ptypes[i]) {
1459 continue;
Orion Hodson005ac512017-10-24 15:43:43 +01001460 }
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001461 if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
1462 return MatchKind::kNone;
1463 }
1464 match = MatchKind::kWithConversions;
Orion Hodson005ac512017-10-24 15:43:43 +01001465 }
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001466 return match;
Orion Hodson005ac512017-10-24 15:43:43 +01001467}
1468
Orion Hodsonb8b93872018-01-30 07:51:10 +00001469bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
1470 MethodType* method_type) {
1471 StackHandleScope<3> hs(Thread::Current());
1472 Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
1473 Handle<VarHandle> vh(hs.NewHandle(this));
1474 Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
1475 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1476
1477 // Check return type first.
1478 if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
1479 // The result of the operation will be discarded. The return type
1480 // of the VarHandle is immaterial.
1481 } else {
1482 ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
1483 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
1484 return false;
1485 }
1486 }
1487
1488 // Check the number of parameters matches (ignoring the VarHandle parameter).
1489 static const int32_t kVarHandleParameters = 1;
1490 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
1491 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1492 access_mode_template,
1493 var_type.Get(),
1494 GetCoordinateType0(),
1495 GetCoordinateType1());
1496 if (vh_ptypes_count != method_type->GetPTypes()->GetLength() - kVarHandleParameters) {
1497 return false;
1498 }
1499
1500 // Check the parameter types are compatible (ignoring the VarHandle parameter).
1501 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
1502 for (int32_t i = 0; i < vh_ptypes_count; ++i) {
1503 if (!IsParameterTypeConvertible(mt_ptypes->Get(i + kVarHandleParameters), vh_ptypes[i])) {
1504 return false;
1505 }
1506 }
1507 return true;
1508}
1509
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001510ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
1511 ObjPtr<VarHandle> var_handle,
1512 AccessMode access_mode) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001513 // 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 +01001514 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1515
1516 StackHandleScope<3> hs(self);
1517 Handle<VarHandle> vh = hs.NewHandle(var_handle);
1518 Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType()));
Orion Hodson928033d2018-02-07 05:30:54 +00001519 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
1520 vh->GetCoordinateType0(),
1521 vh->GetCoordinateType1());
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001522 ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>();
1523 Handle<ObjectArray<Class>> ptypes =
1524 hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
Orion Hodson005ac512017-10-24 15:43:43 +01001525 if (ptypes == nullptr) {
1526 return nullptr;
1527 }
1528
1529 ObjPtr<Class> ptypes_array[VarHandle::kMaxAccessorParameters];
1530 BuildParameterArray(ptypes_array,
1531 access_mode_template,
1532 vh->GetVarType(),
1533 vh->GetCoordinateType0(),
1534 vh->GetCoordinateType1());
1535 for (int32_t i = 0; i < ptypes_count; ++i) {
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001536 ptypes->Set(i, ptypes_array[i]);
Orion Hodson005ac512017-10-24 15:43:43 +01001537 }
1538 return MethodType::Create(self, rtype, ptypes);
1539}
1540
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001541ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
Orion Hodson005ac512017-10-24 15:43:43 +01001542 return GetMethodTypeForAccessMode(self, this, access_mode);
1543}
1544
Orion Hodson3f383462018-05-17 14:03:39 +01001545std::string VarHandle::PrettyDescriptorForAccessMode(AccessMode access_mode) {
1546 // Effect MethodType::PrettyDescriptor() without first creating a method type first.
1547 std::ostringstream oss;
1548 oss << '(';
1549
1550 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1551 ObjPtr<Class> var_type = GetVarType();
1552 ObjPtr<Class> ctypes[2] = { GetCoordinateType0(), GetCoordinateType1() };
1553 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, ctypes[0], ctypes[1]);
1554 int32_t ptypes_done = 0;
1555 for (ObjPtr<Class> ctype : ctypes) {
1556 if (!ctype.IsNull()) {
1557 if (ptypes_done != 0) {
1558 oss << ", ";
1559 }
1560 oss << ctype->PrettyDescriptor();;
1561 ptypes_done++;
1562 }
1563 }
1564 while (ptypes_done != ptypes_count) {
1565 if (ptypes_done != 0) {
1566 oss << ", ";
1567 }
1568 oss << var_type->PrettyDescriptor();
1569 ptypes_done++;
1570 }
1571 ObjPtr<Class> rtype = GetReturnType(access_mode_template, var_type);
1572 oss << ')' << rtype->PrettyDescriptor();
1573 return oss.str();
1574}
1575
Orion Hodson928033d2018-02-07 05:30:54 +00001576bool VarHandle::Access(AccessMode access_mode,
1577 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001578 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001579 JValue* result) {
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001580 ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
1581 ObjPtr<Class> klass = GetClass();
1582 if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001583 auto vh = reinterpret_cast<FieldVarHandle*>(this);
1584 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001585 } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001586 auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
1587 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001588 } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001589 auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
1590 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001591 } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001592 auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
1593 return vh->Access(access_mode, shadow_frame, operands, result);
1594 } else {
1595 LOG(FATAL) << "Unknown varhandle kind";
1596 UNREACHABLE();
1597 }
1598}
1599
Orion Hodsonfe92d122018-01-02 10:45:17 +00001600const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) {
1601 AccessMode access_mode;
1602 if (!GetAccessModeByMethodName(accessor_name, &access_mode)) {
1603 return nullptr;
1604 }
1605 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1606 switch (access_mode_template) {
1607 case AccessModeTemplate::kGet:
1608 case AccessModeTemplate::kCompareAndExchange:
1609 case AccessModeTemplate::kGetAndUpdate:
1610 return "Ljava/lang/Object;";
1611 case AccessModeTemplate::kCompareAndSet:
1612 return "Z";
1613 case AccessModeTemplate::kSet:
1614 return "V";
1615 }
1616}
1617
Orion Hodsonb8b93872018-01-30 07:51:10 +00001618VarHandle::AccessMode VarHandle::GetAccessModeByIntrinsic(Intrinsics intrinsic) {
1619#define VAR_HANDLE_ACCESS_MODE(V) \
1620 V(CompareAndExchange) \
1621 V(CompareAndExchangeAcquire) \
1622 V(CompareAndExchangeRelease) \
1623 V(CompareAndSet) \
1624 V(Get) \
1625 V(GetAcquire) \
1626 V(GetAndAdd) \
1627 V(GetAndAddAcquire) \
1628 V(GetAndAddRelease) \
1629 V(GetAndBitwiseAnd) \
1630 V(GetAndBitwiseAndAcquire) \
1631 V(GetAndBitwiseAndRelease) \
1632 V(GetAndBitwiseOr) \
1633 V(GetAndBitwiseOrAcquire) \
1634 V(GetAndBitwiseOrRelease) \
1635 V(GetAndBitwiseXor) \
1636 V(GetAndBitwiseXorAcquire) \
1637 V(GetAndBitwiseXorRelease) \
1638 V(GetAndSet) \
1639 V(GetAndSetAcquire) \
1640 V(GetAndSetRelease) \
1641 V(GetOpaque) \
1642 V(GetVolatile) \
1643 V(Set) \
1644 V(SetOpaque) \
1645 V(SetRelease) \
1646 V(SetVolatile) \
1647 V(WeakCompareAndSet) \
1648 V(WeakCompareAndSetAcquire) \
1649 V(WeakCompareAndSetPlain) \
1650 V(WeakCompareAndSetRelease)
1651 switch (intrinsic) {
1652#define INTRINSIC_CASE(Name) \
1653 case Intrinsics::kVarHandle ## Name: \
1654 return VarHandle::AccessMode::k ## Name;
1655 VAR_HANDLE_ACCESS_MODE(INTRINSIC_CASE)
1656#undef INTRINSIC_CASE
1657#undef VAR_HANDLE_ACCESS_MODE
1658 default:
1659 break;
1660 }
1661 LOG(FATAL) << "Unknown VarHandle instrinsic: " << static_cast<int>(intrinsic);
1662 UNREACHABLE();
1663}
1664
Orion Hodsonfe92d122018-01-02 10:45:17 +00001665bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode) {
1666 if (method_name == nullptr) {
1667 return false;
1668 }
1669 VarHandleAccessorToAccessModeEntry target = { method_name, /*dummy*/VarHandle::AccessMode::kGet };
1670 auto last = std::cend(kAccessorToAccessMode);
1671 auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode),
1672 last,
1673 target,
1674 VarHandleAccessorToAccessModeEntry::CompareName);
1675 if (it == last || strcmp(it->method_name, method_name) != 0) {
1676 return false;
1677 }
1678 *access_mode = it->access_mode;
1679 return true;
1680}
1681
Orion Hodson005ac512017-10-24 15:43:43 +01001682ArtField* FieldVarHandle::GetField() {
1683 uintptr_t opaque_field = static_cast<uintptr_t>(GetField64(ArtFieldOffset()));
1684 return reinterpret_cast<ArtField*>(opaque_field);
1685}
1686
Orion Hodson928033d2018-02-07 05:30:54 +00001687bool FieldVarHandle::Access(AccessMode access_mode,
1688 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001689 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001690 JValue* result) {
1691 ShadowFrameGetter getter(*shadow_frame, operands);
1692 ArtField* field = GetField();
1693 ObjPtr<Object> obj;
1694 if (field->IsStatic()) {
1695 DCHECK_LE(operands->GetNumberOfOperands(),
1696 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1697 obj = field->GetDeclaringClass();
1698 } else {
1699 DCHECK_GE(operands->GetNumberOfOperands(), 1u);
1700 DCHECK_LE(operands->GetNumberOfOperands(),
1701 1u + 2u * (Primitive::Is64BitType(GetVarType()->GetPrimitiveType()) ? 2u : 1u));
1702 obj = getter.GetReference();
1703 if (obj.IsNull()) {
1704 ThrowNullPointerExceptionForCoordinate();
1705 return false;
1706 }
1707 }
1708 DCHECK(!obj.IsNull());
1709
1710 const MemberOffset offset = field->GetOffset();
1711 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1712 switch (primitive_type) {
1713 case Primitive::Type::kPrimNot:
1714 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode, obj, offset, &getter, result);
1715 case Primitive::kPrimBoolean:
1716 return FieldAccessor<uint8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1717 case Primitive::kPrimByte:
1718 return FieldAccessor<int8_t>::Dispatch(access_mode, obj, offset, &getter, result);
1719 case Primitive::kPrimChar:
1720 return FieldAccessor<uint16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1721 case Primitive::kPrimShort:
1722 return FieldAccessor<int16_t>::Dispatch(access_mode, obj, offset, &getter, result);
1723 case Primitive::kPrimInt:
1724 return FieldAccessor<int32_t>::Dispatch(access_mode, obj, offset, &getter, result);
1725 case Primitive::kPrimFloat:
1726 return FieldAccessor<float>::Dispatch(access_mode, obj, offset, &getter, result);
1727 case Primitive::kPrimLong:
1728 return FieldAccessor<int64_t>::Dispatch(access_mode, obj, offset, &getter, result);
1729 case Primitive::kPrimDouble:
1730 return FieldAccessor<double>::Dispatch(access_mode, obj, offset, &getter, result);
1731 case Primitive::kPrimVoid:
1732 break;
1733 }
1734 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1735 UNREACHABLE();
1736}
1737
Orion Hodson928033d2018-02-07 05:30:54 +00001738bool ArrayElementVarHandle::Access(AccessMode access_mode,
1739 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001740 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001741 JValue* result) {
1742 ShadowFrameGetter getter(*shadow_frame, operands);
1743
1744 // The target array is the first co-ordinate type preceeding var type arguments.
1745 ObjPtr<Object> raw_array(getter.GetReference());
1746 if (raw_array == nullptr) {
1747 ThrowNullPointerExceptionForCoordinate();
1748 return false;
1749 }
1750
1751 ObjPtr<Array> target_array(raw_array->AsArray());
1752
1753 // The target array element is the second co-ordinate type preceeding var type arguments.
1754 const int target_element = getter.Get();
1755 if (!target_array->CheckIsValidIndex(target_element)) {
1756 DCHECK(Thread::Current()->IsExceptionPending());
1757 return false;
1758 }
1759
1760 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1761 switch (primitive_type) {
1762 case Primitive::Type::kPrimNot: {
1763 MemberOffset target_element_offset =
1764 target_array->AsObjectArray<Object>()->OffsetOfElement(target_element);
1765 return FieldAccessor<ObjPtr<Object>>::Dispatch(access_mode,
1766 target_array,
1767 target_element_offset,
1768 &getter,
1769 result);
1770 }
1771 case Primitive::Type::kPrimBoolean:
1772 return PrimitiveArrayElementAccessor<uint8_t>::Dispatch(access_mode,
1773 target_array,
1774 target_element,
1775 &getter,
1776 result);
1777 case Primitive::Type::kPrimByte:
1778 return PrimitiveArrayElementAccessor<int8_t>::Dispatch(access_mode,
1779 target_array,
1780 target_element,
1781 &getter,
1782 result);
1783 case Primitive::Type::kPrimChar:
1784 return PrimitiveArrayElementAccessor<uint16_t>::Dispatch(access_mode,
1785 target_array,
1786 target_element,
1787 &getter,
1788 result);
1789 case Primitive::Type::kPrimShort:
1790 return PrimitiveArrayElementAccessor<int16_t>::Dispatch(access_mode,
1791 target_array,
1792 target_element,
1793 &getter,
1794 result);
1795 case Primitive::Type::kPrimInt:
1796 return PrimitiveArrayElementAccessor<int32_t>::Dispatch(access_mode,
1797 target_array,
1798 target_element,
1799 &getter,
1800 result);
1801 case Primitive::Type::kPrimLong:
1802 return PrimitiveArrayElementAccessor<int64_t>::Dispatch(access_mode,
1803 target_array,
1804 target_element,
1805 &getter,
1806 result);
1807 case Primitive::Type::kPrimFloat:
1808 return PrimitiveArrayElementAccessor<float>::Dispatch(access_mode,
1809 target_array,
1810 target_element,
1811 &getter,
1812 result);
1813 case Primitive::Type::kPrimDouble:
1814 return PrimitiveArrayElementAccessor<double>::Dispatch(access_mode,
1815 target_array,
1816 target_element,
1817 &getter,
1818 result);
1819 case Primitive::Type::kPrimVoid:
1820 break;
1821 }
1822 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1823 UNREACHABLE();
1824}
1825
Orion Hodson005ac512017-10-24 15:43:43 +01001826bool ByteArrayViewVarHandle::GetNativeByteOrder() {
1827 return GetFieldBoolean(NativeByteOrderOffset());
1828}
1829
Orion Hodson928033d2018-02-07 05:30:54 +00001830bool ByteArrayViewVarHandle::Access(AccessMode access_mode,
1831 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001832 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001833 JValue* result) {
1834 ShadowFrameGetter getter(*shadow_frame, operands);
1835
1836 // The byte array is the first co-ordinate type preceeding var type arguments.
1837 ObjPtr<Object> raw_byte_array(getter.GetReference());
1838 if (raw_byte_array == nullptr) {
1839 ThrowNullPointerExceptionForCoordinate();
1840 return false;
1841 }
1842
1843 ObjPtr<ByteArray> byte_array(raw_byte_array->AsByteArray());
1844
1845 // The offset in the byte array element is the second co-ordinate type.
1846 const int32_t data_offset = getter.Get();
1847
1848 // Bounds check requested access.
1849 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1850 if (!CheckElementIndex(primitive_type, data_offset, byte_array->GetLength())) {
1851 return false;
1852 }
1853
1854 int8_t* const data = byte_array->GetData();
1855 bool byte_swap = !GetNativeByteOrder();
1856 switch (primitive_type) {
1857 case Primitive::Type::kPrimNot:
1858 case Primitive::kPrimBoolean:
1859 case Primitive::kPrimByte:
1860 case Primitive::kPrimVoid:
1861 // These are not supported for byte array views and not instantiable.
1862 break;
1863 case Primitive::kPrimChar:
1864 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1865 data,
1866 data_offset,
1867 byte_swap,
1868 &getter,
1869 result);
1870 case Primitive::kPrimShort:
1871 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1872 data,
1873 data_offset,
1874 byte_swap,
1875 &getter,
1876 result);
1877 case Primitive::kPrimInt:
1878 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1879 data,
1880 data_offset,
1881 byte_swap,
1882 &getter,
1883 result);
1884 case Primitive::kPrimFloat:
1885 // Treated as a bitwise representation. See javadoc comments for
1886 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1887 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1888 data,
1889 data_offset,
1890 byte_swap,
1891 &getter,
1892 result);
1893 case Primitive::kPrimLong:
1894 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1895 data,
1896 data_offset,
1897 byte_swap,
1898 &getter,
1899 result);
1900 case Primitive::kPrimDouble:
1901 // Treated as a bitwise representation. See javadoc comments for
1902 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
1903 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
1904 data,
1905 data_offset,
1906 byte_swap,
1907 &getter,
1908 result);
1909 }
1910 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
1911 UNREACHABLE();
1912}
1913
Orion Hodson005ac512017-10-24 15:43:43 +01001914bool ByteBufferViewVarHandle::GetNativeByteOrder() {
1915 return GetFieldBoolean(NativeByteOrderOffset());
1916}
1917
Orion Hodson928033d2018-02-07 05:30:54 +00001918bool ByteBufferViewVarHandle::Access(AccessMode access_mode,
1919 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001920 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001921 JValue* result) {
1922 ShadowFrameGetter getter(*shadow_frame, operands);
1923
1924 // The byte buffer is the first co-ordinate argument preceeding var type arguments.
1925 ObjPtr<Object> byte_buffer(getter.GetReference());
1926 if (byte_buffer == nullptr) {
1927 ThrowNullPointerExceptionForCoordinate();
1928 return false;
1929 }
1930
1931 // The byte index for access is the second co-ordinate
1932 // argument. This is relative to the offset field of the ByteBuffer.
1933 const int32_t byte_index = getter.Get();
1934
1935 // Check access_mode is compatible with ByteBuffer's read-only property.
1936 bool is_read_only = byte_buffer->GetFieldBoolean(
1937 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_isReadOnly));
1938 if (is_read_only && !IsReadOnlyAccessMode(access_mode)) {
1939 ThrowReadOnlyBufferException();
1940 return false;
1941 }
1942
1943 // The native_address is only set for ByteBuffer instances backed by native memory.
1944 const int64_t native_address =
1945 byte_buffer->GetField64(GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_address));
1946
1947 // Determine offset and limit for accesses.
1948 int32_t byte_buffer_offset;
1949 if (native_address == 0l) {
1950 // Accessing a heap allocated byte buffer.
1951 byte_buffer_offset = byte_buffer->GetField32(
1952 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_offset));
1953 } else {
1954 // Accessing direct memory.
1955 byte_buffer_offset = 0;
1956 }
1957 const int32_t byte_buffer_limit = byte_buffer->GetField32(
1958 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_limit));
1959
1960 const Primitive::Type primitive_type = GetVarType()->GetPrimitiveType();
1961 if (!CheckElementIndex(primitive_type, byte_index, byte_buffer_offset, byte_buffer_limit)) {
1962 return false;
1963 }
1964 const int32_t checked_offset32 = byte_buffer_offset + byte_index;
1965
1966 int8_t* data;
1967 if (native_address == 0) {
1968 ObjPtr<ByteArray> heap_byte_array = byte_buffer->GetFieldObject<ByteArray>(
1969 GetMemberOffset(WellKnownClasses::java_nio_ByteBuffer_hb));
1970 data = heap_byte_array->GetData();
1971 } else {
1972 data = reinterpret_cast<int8_t*>(static_cast<uint32_t>(native_address));
1973 }
1974
1975 bool byte_swap = !GetNativeByteOrder();
1976 switch (primitive_type) {
1977 case Primitive::kPrimChar:
1978 return ByteArrayViewAccessor<uint16_t>::Dispatch(access_mode,
1979 data,
1980 checked_offset32,
1981 byte_swap,
1982 &getter,
1983 result);
1984 case Primitive::kPrimShort:
1985 return ByteArrayViewAccessor<int16_t>::Dispatch(access_mode,
1986 data,
1987 checked_offset32,
1988 byte_swap,
1989 &getter,
1990 result);
1991 case Primitive::kPrimInt:
1992 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
1993 data,
1994 checked_offset32,
1995 byte_swap,
1996 &getter,
1997 result);
1998 case Primitive::kPrimFloat:
1999 // Treated as a bitwise representation. See javadoc comments for
2000 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
2001 return ByteArrayViewAccessor<int32_t>::Dispatch(access_mode,
2002 data,
2003 checked_offset32,
2004 byte_swap,
2005 &getter,
2006 result);
2007 case Primitive::kPrimLong:
2008 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2009 data,
2010 checked_offset32,
2011 byte_swap,
2012 &getter,
2013 result);
2014 case Primitive::kPrimDouble:
2015 // Treated as a bitwise representation. See javadoc comments for
2016 // java.lang.invoke.MethodHandles.byteArrayViewVarHandle().
2017 return ByteArrayViewAccessor<int64_t>::Dispatch(access_mode,
2018 data,
2019 checked_offset32,
2020 byte_swap,
2021 &getter,
2022 result);
2023 case Primitive::Type::kPrimNot:
2024 case Primitive::kPrimBoolean:
2025 case Primitive::kPrimByte:
2026 case Primitive::kPrimVoid:
2027 // These are not supported for byte array views and not instantiable.
2028 break;
2029 }
2030 LOG(FATAL) << "Unreachable: Unexpected primitive " << primitive_type;
2031 UNREACHABLE();
2032}
2033
Orion Hodson005ac512017-10-24 15:43:43 +01002034} // namespace mirror
2035} // namespace art