blob: 43919107b4b0e828eb820eedda694cf589cfc9d4 [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"
Vladimir Marko78baed52018-10-11 10:44:58 +010021#include "base/casts.h"
Orion Hodson005ac512017-10-24 15:43:43 +010022#include "class-inl.h"
23#include "class_linker.h"
Vladimir Markoc7aa87e2018-05-24 15:19:52 +010024#include "class_root.h"
Orion Hodsonb8b93872018-01-30 07:51:10 +000025#include "intrinsics_enum.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010026#include "jni/jni_internal.h"
Orion Hodson928033d2018-02-07 05:30:54 +000027#include "jvalue-inl.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010028#include "method_handles-inl.h"
Orion Hodson005ac512017-10-24 15:43:43 +010029#include "method_type.h"
Vladimir Markoa8bba7d2018-05-30 15:18:48 +010030#include "obj_ptr-inl.h"
Orion Hodson928033d2018-02-07 05:30:54 +000031#include "well_known_classes.h"
Orion Hodson005ac512017-10-24 15:43:43 +010032
33namespace art {
34namespace mirror {
35
Orion Hodson928033d2018-02-07 05:30:54 +000036static constexpr bool kTransactionActive = true;
37static constexpr bool kTransactionInactive = !kTransactionActive;
38
Orion Hodson005ac512017-10-24 15:43:43 +010039namespace {
40
Orion Hodsonfe92d122018-01-02 10:45:17 +000041struct VarHandleAccessorToAccessModeEntry {
42 const char* method_name;
43 VarHandle::AccessMode access_mode;
44
45 // Binary predicate function for finding access_mode by
46 // method_name. The access_mode field is ignored.
47 static bool CompareName(const VarHandleAccessorToAccessModeEntry& lhs,
48 const VarHandleAccessorToAccessModeEntry& rhs) {
49 return strcmp(lhs.method_name, rhs.method_name) < 0;
50 }
51};
52
53// Map of VarHandle accessor method names to access mode values. The list is alpha-sorted to support
54// binary search. For the usage scenario - lookups in the verifier - a linear scan would likely
55// suffice since we expect VarHandles to be a lesser encountered class. We could use a std::hashmap
56// here and this would be easier to maintain if new values are added here. However, this entails
57// CPU cycles initializing the structure on every execution and uses O(N) more memory for
58// intermediate nodes and makes that memory dirty. Compile-time magic using constexpr is possible
59// here, but that's a tax when this code is recompiled.
60const VarHandleAccessorToAccessModeEntry kAccessorToAccessMode[VarHandle::kNumberOfAccessModes] = {
61 { "compareAndExchange", VarHandle::AccessMode::kCompareAndExchange },
62 { "compareAndExchangeAcquire", VarHandle::AccessMode::kCompareAndExchangeAcquire },
63 { "compareAndExchangeRelease", VarHandle::AccessMode::kCompareAndExchangeRelease },
64 { "compareAndSet", VarHandle::AccessMode::kCompareAndSet },
65 { "get", VarHandle::AccessMode::kGet },
66 { "getAcquire", VarHandle::AccessMode::kGetAcquire },
67 { "getAndAdd", VarHandle::AccessMode::kGetAndAdd },
68 { "getAndAddAcquire", VarHandle::AccessMode::kGetAndAddAcquire },
69 { "getAndAddRelease", VarHandle::AccessMode::kGetAndAddRelease },
70 { "getAndBitwiseAnd", VarHandle::AccessMode::kGetAndBitwiseAnd },
71 { "getAndBitwiseAndAcquire", VarHandle::AccessMode::kGetAndBitwiseAndAcquire },
72 { "getAndBitwiseAndRelease", VarHandle::AccessMode::kGetAndBitwiseAndRelease },
73 { "getAndBitwiseOr", VarHandle::AccessMode::kGetAndBitwiseOr },
74 { "getAndBitwiseOrAcquire", VarHandle::AccessMode::kGetAndBitwiseOrAcquire },
75 { "getAndBitwiseOrRelease", VarHandle::AccessMode::kGetAndBitwiseOrRelease },
76 { "getAndBitwiseXor", VarHandle::AccessMode::kGetAndBitwiseXor },
77 { "getAndBitwiseXorAcquire", VarHandle::AccessMode::kGetAndBitwiseXorAcquire },
78 { "getAndBitwiseXorRelease", VarHandle::AccessMode::kGetAndBitwiseXorRelease },
79 { "getAndSet", VarHandle::AccessMode::kGetAndSet },
80 { "getAndSetAcquire", VarHandle::AccessMode::kGetAndSetAcquire },
81 { "getAndSetRelease", VarHandle::AccessMode::kGetAndSetRelease },
82 { "getOpaque", VarHandle::AccessMode::kGetOpaque },
83 { "getVolatile", VarHandle::AccessMode::kGetVolatile },
84 { "set", VarHandle::AccessMode::kSet },
85 { "setOpaque", VarHandle::AccessMode::kSetOpaque },
86 { "setRelease", VarHandle::AccessMode::kSetRelease },
87 { "setVolatile", VarHandle::AccessMode::kSetVolatile },
88 { "weakCompareAndSet", VarHandle::AccessMode::kWeakCompareAndSet },
89 { "weakCompareAndSetAcquire", VarHandle::AccessMode::kWeakCompareAndSetAcquire },
90 { "weakCompareAndSetPlain", VarHandle::AccessMode::kWeakCompareAndSetPlain },
91 { "weakCompareAndSetRelease", VarHandle::AccessMode::kWeakCompareAndSetRelease },
92};
93
Orion Hodson005ac512017-10-24 15:43:43 +010094// Enumeration for describing the parameter and return types of an AccessMode.
95enum class AccessModeTemplate : uint32_t {
96 kGet, // T Op(C0..CN)
97 kSet, // void Op(C0..CN, T)
98 kCompareAndSet, // boolean Op(C0..CN, T, T)
99 kCompareAndExchange, // T Op(C0..CN, T, T)
100 kGetAndUpdate, // T Op(C0..CN, T)
101};
102
103// Look up the AccessModeTemplate for a given VarHandle
104// AccessMode. This simplifies finding the correct signature for a
105// VarHandle accessor method.
106AccessModeTemplate GetAccessModeTemplate(VarHandle::AccessMode access_mode) {
107 switch (access_mode) {
108 case VarHandle::AccessMode::kGet:
109 return AccessModeTemplate::kGet;
110 case VarHandle::AccessMode::kSet:
111 return AccessModeTemplate::kSet;
112 case VarHandle::AccessMode::kGetVolatile:
113 return AccessModeTemplate::kGet;
114 case VarHandle::AccessMode::kSetVolatile:
115 return AccessModeTemplate::kSet;
116 case VarHandle::AccessMode::kGetAcquire:
117 return AccessModeTemplate::kGet;
118 case VarHandle::AccessMode::kSetRelease:
119 return AccessModeTemplate::kSet;
120 case VarHandle::AccessMode::kGetOpaque:
121 return AccessModeTemplate::kGet;
122 case VarHandle::AccessMode::kSetOpaque:
123 return AccessModeTemplate::kSet;
124 case VarHandle::AccessMode::kCompareAndSet:
125 return AccessModeTemplate::kCompareAndSet;
126 case VarHandle::AccessMode::kCompareAndExchange:
127 return AccessModeTemplate::kCompareAndExchange;
128 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
129 return AccessModeTemplate::kCompareAndExchange;
130 case VarHandle::AccessMode::kCompareAndExchangeRelease:
131 return AccessModeTemplate::kCompareAndExchange;
132 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
133 return AccessModeTemplate::kCompareAndSet;
134 case VarHandle::AccessMode::kWeakCompareAndSet:
135 return AccessModeTemplate::kCompareAndSet;
136 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
137 return AccessModeTemplate::kCompareAndSet;
138 case VarHandle::AccessMode::kWeakCompareAndSetRelease:
139 return AccessModeTemplate::kCompareAndSet;
140 case VarHandle::AccessMode::kGetAndSet:
141 return AccessModeTemplate::kGetAndUpdate;
142 case VarHandle::AccessMode::kGetAndSetAcquire:
143 return AccessModeTemplate::kGetAndUpdate;
144 case VarHandle::AccessMode::kGetAndSetRelease:
145 return AccessModeTemplate::kGetAndUpdate;
146 case VarHandle::AccessMode::kGetAndAdd:
147 return AccessModeTemplate::kGetAndUpdate;
148 case VarHandle::AccessMode::kGetAndAddAcquire:
149 return AccessModeTemplate::kGetAndUpdate;
150 case VarHandle::AccessMode::kGetAndAddRelease:
151 return AccessModeTemplate::kGetAndUpdate;
152 case VarHandle::AccessMode::kGetAndBitwiseOr:
153 return AccessModeTemplate::kGetAndUpdate;
154 case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
155 return AccessModeTemplate::kGetAndUpdate;
156 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
157 return AccessModeTemplate::kGetAndUpdate;
158 case VarHandle::AccessMode::kGetAndBitwiseAnd:
159 return AccessModeTemplate::kGetAndUpdate;
160 case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
161 return AccessModeTemplate::kGetAndUpdate;
162 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
163 return AccessModeTemplate::kGetAndUpdate;
164 case VarHandle::AccessMode::kGetAndBitwiseXor:
165 return AccessModeTemplate::kGetAndUpdate;
166 case VarHandle::AccessMode::kGetAndBitwiseXorRelease:
167 return AccessModeTemplate::kGetAndUpdate;
168 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
169 return AccessModeTemplate::kGetAndUpdate;
170 }
171}
172
Orion Hodson928033d2018-02-07 05:30:54 +0000173int32_t GetNumberOfVarTypeParameters(AccessModeTemplate access_mode_template) {
Orion Hodsonc4d3bf42018-02-06 16:02:49 +0000174 switch (access_mode_template) {
175 case AccessModeTemplate::kGet:
Orion Hodson928033d2018-02-07 05:30:54 +0000176 return 0;
Orion Hodsonc4d3bf42018-02-06 16:02:49 +0000177 case AccessModeTemplate::kSet:
178 case AccessModeTemplate::kGetAndUpdate:
Orion Hodson928033d2018-02-07 05:30:54 +0000179 return 1;
Orion Hodsonc4d3bf42018-02-06 16:02:49 +0000180 case AccessModeTemplate::kCompareAndSet:
181 case AccessModeTemplate::kCompareAndExchange:
Orion Hodson928033d2018-02-07 05:30:54 +0000182 return 2;
Orion Hodsonbecc83b2017-12-08 11:36:19 +0000183 }
Orion Hodsonc4d3bf42018-02-06 16:02:49 +0000184 UNREACHABLE();
Orion Hodsonbecc83b2017-12-08 11:36:19 +0000185}
186
Orion Hodson928033d2018-02-07 05:30:54 +0000187// Returns the number of parameters associated with an
188// AccessModeTemplate and the supplied coordinate types.
189int32_t GetNumberOfParameters(AccessModeTemplate access_mode_template,
190 ObjPtr<Class> coordinateType0,
191 ObjPtr<Class> coordinateType1) {
192 int32_t count = 0;
193 if (!coordinateType0.IsNull()) {
194 count++;
195 if (!coordinateType1.IsNull()) {
196 count++;
197 }
198 }
199 return count + GetNumberOfVarTypeParameters(access_mode_template);
200}
201
202void ThrowNullPointerExceptionForCoordinate() REQUIRES_SHARED(Locks::mutator_lock_) {
203 ThrowNullPointerException("Attempt to access memory on a null object");
204}
205
206bool CheckElementIndex(Primitive::Type type,
207 int32_t relative_index,
208 int32_t start,
209 int32_t limit) REQUIRES_SHARED(Locks::mutator_lock_) {
210 int64_t index = start + relative_index;
211 int64_t max_index = limit - Primitive::ComponentSize(type);
212 if (index < start || index > max_index) {
213 ThrowIndexOutOfBoundsException(index, limit - start);
214 return false;
215 }
216 return true;
217}
218
219bool CheckElementIndex(Primitive::Type type, int32_t index, int32_t range_limit)
220 REQUIRES_SHARED(Locks::mutator_lock_) {
221 return CheckElementIndex(type, index, 0, range_limit);
222}
223
224// Returns true if access_mode only entails a memory read. False if
225// access_mode may write to memory.
226bool IsReadOnlyAccessMode(VarHandle::AccessMode access_mode) {
227 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
228 return access_mode_template == AccessModeTemplate::kGet;
229}
230
Orion Hodson005ac512017-10-24 15:43:43 +0100231// Writes the parameter types associated with the AccessModeTemplate
232// into an array. The parameter types are derived from the specified
233// variable type and coordinate types. Returns the number of
234// parameters written.
235int32_t BuildParameterArray(ObjPtr<Class> (&parameters)[VarHandle::kMaxAccessorParameters],
236 AccessModeTemplate access_mode_template,
237 ObjPtr<Class> varType,
238 ObjPtr<Class> coordinateType0,
239 ObjPtr<Class> coordinateType1)
240 REQUIRES_SHARED(Locks::mutator_lock_) {
241 DCHECK(varType != nullptr);
242 int32_t index = 0;
243 if (!coordinateType0.IsNull()) {
244 parameters[index++] = coordinateType0;
245 if (!coordinateType1.IsNull()) {
246 parameters[index++] = coordinateType1;
247 }
248 } else {
249 DCHECK(coordinateType1.IsNull());
250 }
251
252 switch (access_mode_template) {
253 case AccessModeTemplate::kCompareAndExchange:
254 case AccessModeTemplate::kCompareAndSet:
255 parameters[index++] = varType;
256 parameters[index++] = varType;
257 return index;
258 case AccessModeTemplate::kGet:
259 return index;
260 case AccessModeTemplate::kGetAndUpdate:
261 case AccessModeTemplate::kSet:
262 parameters[index++] = varType;
263 return index;
264 }
265 return -1;
266}
267
268// Returns the return type associated with an AccessModeTemplate based
269// on the template and the variable type specified.
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100270static ObjPtr<Class> GetReturnType(AccessModeTemplate access_mode_template, ObjPtr<Class> varType)
Orion Hodson005ac512017-10-24 15:43:43 +0100271 REQUIRES_SHARED(Locks::mutator_lock_) {
272 DCHECK(varType != nullptr);
273 switch (access_mode_template) {
274 case AccessModeTemplate::kCompareAndSet:
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100275 return GetClassRoot(ClassRoot::kPrimitiveBoolean);
Orion Hodson005ac512017-10-24 15:43:43 +0100276 case AccessModeTemplate::kCompareAndExchange:
277 case AccessModeTemplate::kGet:
278 case AccessModeTemplate::kGetAndUpdate:
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100279 return varType;
Orion Hodson005ac512017-10-24 15:43:43 +0100280 case AccessModeTemplate::kSet:
Vladimir Markoa8bba7d2018-05-30 15:18:48 +0100281 return GetClassRoot(ClassRoot::kPrimitiveVoid);
Orion Hodson005ac512017-10-24 15:43:43 +0100282 }
283 return nullptr;
284}
285
Orion Hodson928033d2018-02-07 05:30:54 +0000286// Method to insert a read barrier for accessors to reference fields.
287inline void ReadBarrierForVarHandleAccess(ObjPtr<Object> obj, MemberOffset field_offset)
288 REQUIRES_SHARED(Locks::mutator_lock_) {
289 if (kUseReadBarrier) {
290 // We need to ensure that the reference stored in the field is a to-space one before attempting
291 // the CompareAndSet/CompareAndExchange/Exchange operation otherwise it will fail incorrectly
292 // if obj is in the process of being moved.
293 uint8_t* raw_field_addr = reinterpret_cast<uint8_t*>(obj.Ptr()) + field_offset.SizeValue();
294 auto field_addr = reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr);
295 // Note that the read barrier load does NOT need to be volatile.
296 static constexpr bool kIsVolatile = false;
297 static constexpr bool kAlwaysUpdateField = true;
298 ReadBarrier::Barrier<mirror::Object, kIsVolatile, kWithReadBarrier, kAlwaysUpdateField>(
299 obj.Ptr(),
300 MemberOffset(field_offset),
301 field_addr);
302 }
303}
304
305inline MemberOffset GetMemberOffset(jfieldID field_id) REQUIRES_SHARED(Locks::mutator_lock_) {
306 ArtField* const field = jni::DecodeArtField(field_id);
307 return field->GetOffset();
308}
309
310//
311// Helper methods for storing results from atomic operations into
312// JValue instances.
313//
314
315inline void StoreResult(uint8_t value, JValue* result) {
316 result->SetZ(value);
317}
318
319inline void StoreResult(int8_t value, JValue* result) {
320 result->SetB(value);
321}
322
323inline void StoreResult(uint16_t value, JValue* result) {
324 result->SetC(value);
325}
326
327inline void StoreResult(int16_t value, JValue* result) {
328 result->SetS(value);
329}
330
331inline void StoreResult(int32_t value, JValue* result) {
332 result->SetI(value);
333}
334
335inline void StoreResult(int64_t value, JValue* result) {
336 result->SetJ(value);
337}
338
339inline void StoreResult(float value, JValue* result) {
340 result->SetF(value);
341}
342
343inline void StoreResult(double value, JValue* result) {
344 result->SetD(value);
345}
346
347inline void StoreResult(ObjPtr<Object> value, JValue* result)
348 REQUIRES_SHARED(Locks::mutator_lock_) {
349 result->SetL(value);
350}
351
352//
353// Helper class for byte-swapping value that has been stored in a JValue.
354//
355
356template <typename T>
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100357class JValueByteSwapper final {
Orion Hodson928033d2018-02-07 05:30:54 +0000358 public:
359 static void ByteSwap(JValue* value);
360 static void MaybeByteSwap(bool byte_swap, JValue* value) {
361 if (byte_swap) {
362 ByteSwap(value);
363 }
364 }
365};
366
367template <>
368void JValueByteSwapper<uint16_t>::ByteSwap(JValue* value) {
369 value->SetC(BSWAP(value->GetC()));
370}
371
372template <>
373void JValueByteSwapper<int16_t>::ByteSwap(JValue* value) {
374 value->SetS(BSWAP(value->GetS()));
375}
376
377template <>
378void JValueByteSwapper<int32_t>::ByteSwap(JValue* value) {
379 value->SetI(BSWAP(value->GetI()));
380}
381
382template <>
383void JValueByteSwapper<int64_t>::ByteSwap(JValue* value) {
384 value->SetJ(BSWAP(value->GetJ()));
385}
386
387//
388// Accessor implementations, shared across all VarHandle types.
389//
390
391template <typename T, std::memory_order MO>
392class AtomicGetAccessor : public Object::Accessor<T> {
393 public:
394 explicit AtomicGetAccessor(JValue* result) : result_(result) {}
395
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100396 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000397 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
398 StoreResult(atom->load(MO), result_);
399 }
400
401 private:
402 JValue* result_;
403};
404
405template <typename T, std::memory_order MO>
406class AtomicSetAccessor : public Object::Accessor<T> {
407 public:
408 explicit AtomicSetAccessor(T new_value) : new_value_(new_value) {}
409
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100410 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000411 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
412 atom->store(new_value_, MO);
413 }
414
415 private:
416 T new_value_;
417};
418
419template <typename T> using GetAccessor = AtomicGetAccessor<T, std::memory_order_relaxed>;
420
421template <typename T> using SetAccessor = AtomicSetAccessor<T, std::memory_order_relaxed>;
422
423template <typename T>
424using GetVolatileAccessor = AtomicGetAccessor<T, std::memory_order_seq_cst>;
425
426template <typename T>
427using SetVolatileAccessor = AtomicSetAccessor<T, std::memory_order_seq_cst>;
428
429template <typename T, std::memory_order MOS, std::memory_order MOF>
430class AtomicStrongCompareAndSetAccessor : public Object::Accessor<T> {
431 public:
432 AtomicStrongCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
433 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
434
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100435 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000436 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
437 bool success = atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
438 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
439 }
440
441 private:
442 T expected_value_;
443 T desired_value_;
444 JValue* result_;
445};
446
447template<typename T>
448using CompareAndSetAccessor =
449 AtomicStrongCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
450
451template <typename T, std::memory_order MOS, std::memory_order MOF>
452class AtomicStrongCompareAndExchangeAccessor : public Object::Accessor<T> {
453 public:
454 AtomicStrongCompareAndExchangeAccessor(T expected_value, T desired_value, JValue* result)
455 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
456
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100457 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000458 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
459 atom->compare_exchange_strong(expected_value_, desired_value_, MOS, MOF);
460 StoreResult(expected_value_, result_);
461 }
462
463 private:
464 T expected_value_;
465 T desired_value_;
466 JValue* result_;
467};
468
469template <typename T>
470using CompareAndExchangeAccessor =
471 AtomicStrongCompareAndExchangeAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
472
473template <typename T, std::memory_order MOS, std::memory_order MOF>
474class AtomicWeakCompareAndSetAccessor : public Object::Accessor<T> {
475 public:
476 AtomicWeakCompareAndSetAccessor(T expected_value, T desired_value, JValue* result)
477 : expected_value_(expected_value), desired_value_(desired_value), result_(result) {}
478
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100479 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000480 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
481 bool success = atom->compare_exchange_weak(expected_value_, desired_value_, MOS, MOF);
482 StoreResult(success ? JNI_TRUE : JNI_FALSE, result_);
483 }
484
485 private:
486 T expected_value_;
487 T desired_value_;
488 JValue* result_;
489};
490
491template <typename T>
492using WeakCompareAndSetAccessor =
493 AtomicWeakCompareAndSetAccessor<T, std::memory_order_seq_cst, std::memory_order_seq_cst>;
494
495template <typename T, std::memory_order MO>
496class AtomicGetAndSetAccessor : public Object::Accessor<T> {
497 public:
498 AtomicGetAndSetAccessor(T new_value, JValue* result) : new_value_(new_value), result_(result) {}
499
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100500 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000501 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
502 T old_value = atom->exchange(new_value_, MO);
503 StoreResult(old_value, result_);
504 }
505
506 private:
507 T new_value_;
508 JValue* result_;
509};
510
511template <typename T>
512using GetAndSetAccessor = AtomicGetAndSetAccessor<T, std::memory_order_seq_cst>;
513
514template <typename T, bool kIsFloat, std::memory_order MO>
515class AtomicGetAndAddOperator {
516 public:
517 static T Apply(T* addr, T addend) {
518 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
519 return atom->fetch_add(addend, MO);
520 }
521};
522
523template <typename T, std::memory_order MO>
524class AtomicGetAndAddOperator<T, /* kIsFloat */ true, MO> {
525 public:
526 static T Apply(T* addr, T addend) {
527 // c++11 does not have std::atomic<T>::fetch_and_add for floating
528 // point types, so we effect one with a compare and swap.
529 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
530 T old_value = atom->load(std::memory_order_relaxed);
531 T new_value;
532 do {
533 new_value = old_value + addend;
534 } while (!atom->compare_exchange_weak(old_value, new_value, MO, std::memory_order_relaxed));
535 return old_value;
536 }
537};
538
539template <typename T, std::memory_order MO>
540class AtomicGetAndAddAccessor : public Object::Accessor<T> {
541 public:
542 AtomicGetAndAddAccessor(T addend, JValue* result) : addend_(addend), result_(result) {}
543
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100544 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000545 constexpr bool kIsFloatingPoint = std::is_floating_point<T>::value;
546 T old_value = AtomicGetAndAddOperator<T, kIsFloatingPoint, MO>::Apply(addr, addend_);
547 StoreResult(old_value, result_);
548 }
549
550 private:
551 T addend_;
552 JValue* result_;
553};
554
555template <typename T>
556using GetAndAddAccessor = AtomicGetAndAddAccessor<T, std::memory_order_seq_cst>;
557
558// Accessor specifically for memory views where the caller can specify
559// the byte-ordering. Addition only works outside of the byte-swapped
560// memory view because of the direction of carries.
561template <typename T, std::memory_order MO>
562class AtomicGetAndAddWithByteSwapAccessor : public Object::Accessor<T> {
563 public:
564 AtomicGetAndAddWithByteSwapAccessor(T value, JValue* result) : value_(value), result_(result) {}
565
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100566 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000567 std::atomic<T>* const atom = reinterpret_cast<std::atomic<T>*>(addr);
568 T current_value = atom->load(std::memory_order_relaxed);
569 T sum;
570 do {
571 sum = BSWAP(current_value) + value_;
572 // NB current_value is a pass-by-reference argument in the call to
573 // atomic<T>::compare_exchange_weak().
574 } while (!atom->compare_exchange_weak(current_value,
575 BSWAP(sum),
576 MO,
577 std::memory_order_relaxed));
578 StoreResult(BSWAP(current_value), result_);
579 }
580
581 private:
582 T value_;
583 JValue* result_;
584};
585
586template <typename T>
587using GetAndAddWithByteSwapAccessor =
588 AtomicGetAndAddWithByteSwapAccessor<T, std::memory_order_seq_cst>;
589
590template <typename T, std::memory_order MO>
591class AtomicGetAndBitwiseOrAccessor : public Object::Accessor<T> {
592 public:
593 AtomicGetAndBitwiseOrAccessor(T value, JValue* result) : value_(value), result_(result) {}
594
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100595 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000596 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
597 T old_value = atom->fetch_or(value_, MO);
598 StoreResult(old_value, result_);
599 }
600
601 private:
602 T value_;
603 JValue* result_;
604};
605
606template <typename T>
607using GetAndBitwiseOrAccessor = AtomicGetAndBitwiseOrAccessor<T, std::memory_order_seq_cst>;
608
609template <typename T, std::memory_order MO>
610class AtomicGetAndBitwiseAndAccessor : public Object::Accessor<T> {
611 public:
612 AtomicGetAndBitwiseAndAccessor(T value, JValue* result) : value_(value), result_(result) {}
613
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100614 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000615 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
616 T old_value = atom->fetch_and(value_, MO);
617 StoreResult(old_value, result_);
618 }
619
620 private:
621 T value_;
622 JValue* result_;
623};
624
625template <typename T>
626using GetAndBitwiseAndAccessor =
627 AtomicGetAndBitwiseAndAccessor<T, std::memory_order_seq_cst>;
628
629template <typename T, std::memory_order MO>
630class AtomicGetAndBitwiseXorAccessor : public Object::Accessor<T> {
631 public:
632 AtomicGetAndBitwiseXorAccessor(T value, JValue* result) : value_(value), result_(result) {}
633
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100634 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000635 std::atomic<T>* atom = reinterpret_cast<std::atomic<T>*>(addr);
636 T old_value = atom->fetch_xor(value_, MO);
637 StoreResult(old_value, result_);
638 }
639
640 private:
641 T value_;
642 JValue* result_;
643};
644
645template <typename T>
646using GetAndBitwiseXorAccessor = AtomicGetAndBitwiseXorAccessor<T, std::memory_order_seq_cst>;
647
648//
649// Unreachable access modes.
650//
651
652NO_RETURN void UnreachableAccessMode(const char* access_mode, const char* type_name) {
653 LOG(FATAL) << "Unreachable access mode :" << access_mode << " for type " << type_name;
654 UNREACHABLE();
655}
656
657#define UNREACHABLE_ACCESS_MODE(ACCESS_MODE, TYPE) \
658template<> void ACCESS_MODE ## Accessor<TYPE>::Access(TYPE*) { \
659 UnreachableAccessMode(#ACCESS_MODE, #TYPE); \
660}
661
662// The boolean primitive type is not numeric (boolean == std::uint8_t).
663UNREACHABLE_ACCESS_MODE(GetAndAdd, uint8_t)
664
665// The floating point types do not support bitwise operations.
666UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, float)
667UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, float)
668UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, float)
669UNREACHABLE_ACCESS_MODE(GetAndBitwiseOr, double)
670UNREACHABLE_ACCESS_MODE(GetAndBitwiseAnd, double)
671UNREACHABLE_ACCESS_MODE(GetAndBitwiseXor, double)
672
673// A helper class for object field accesses for floats and
674// doubles. The object interface deals with Field32 and Field64. The
675// former is used for both integers and floats, the latter for longs
676// and doubles. This class provides the necessary coercion.
677template <typename T, typename U>
678class TypeAdaptorAccessor : public Object::Accessor<T> {
679 public:
680 explicit TypeAdaptorAccessor(Object::Accessor<U>* inner_accessor)
681 : inner_accessor_(inner_accessor) {}
682
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100683 void Access(T* addr) override {
Orion Hodson928033d2018-02-07 05:30:54 +0000684 static_assert(sizeof(T) == sizeof(U), "bad conversion");
685 inner_accessor_->Access(reinterpret_cast<U*>(addr));
686 }
687
688 private:
689 Object::Accessor<U>* inner_accessor_;
690};
691
692template <typename T>
693class FieldAccessViaAccessor {
694 public:
Andreas Gampec55bb392018-09-21 00:02:02 +0000695 using Accessor = Object::Accessor<T>;
Orion Hodson928033d2018-02-07 05:30:54 +0000696
697 // Apply an Accessor to get a field in an object.
698 static void Get(ObjPtr<Object> obj,
699 MemberOffset field_offset,
700 Accessor* accessor)
701 REQUIRES_SHARED(Locks::mutator_lock_) {
702 obj->GetPrimitiveFieldViaAccessor(field_offset, accessor);
703 }
704
705 // Apply an Accessor to update a field in an object.
706 static void Update(ObjPtr<Object> obj,
707 MemberOffset field_offset,
708 Accessor* accessor)
709 REQUIRES_SHARED(Locks::mutator_lock_);
710};
711
712template <>
713inline void FieldAccessViaAccessor<float>::Get(ObjPtr<Object> obj,
714 MemberOffset field_offset,
715 Accessor* accessor)
716 REQUIRES_SHARED(Locks::mutator_lock_) {
717 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
718 obj->GetPrimitiveFieldViaAccessor(field_offset, &float_to_int_accessor);
719}
720
721template <>
722inline void FieldAccessViaAccessor<double>::Get(ObjPtr<Object> obj,
723 MemberOffset field_offset,
724 Accessor* accessor)
725 REQUIRES_SHARED(Locks::mutator_lock_) {
726 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
727 obj->GetPrimitiveFieldViaAccessor(field_offset, &double_to_int_accessor);
728}
729
730template <>
731void FieldAccessViaAccessor<uint8_t>::Update(ObjPtr<Object> obj,
732 MemberOffset field_offset,
733 Accessor* accessor)
734 REQUIRES_SHARED(Locks::mutator_lock_) {
735 if (Runtime::Current()->IsActiveTransaction()) {
736 obj->UpdateFieldBooleanViaAccessor<kTransactionActive>(field_offset, accessor);
737 } else {
738 obj->UpdateFieldBooleanViaAccessor<kTransactionInactive>(field_offset, accessor);
739 }
740}
741
742template <>
743void FieldAccessViaAccessor<int8_t>::Update(ObjPtr<Object> obj,
744 MemberOffset field_offset,
745 Accessor* accessor)
746 REQUIRES_SHARED(Locks::mutator_lock_) {
747 if (Runtime::Current()->IsActiveTransaction()) {
748 obj->UpdateFieldByteViaAccessor<kTransactionActive>(field_offset, accessor);
749 } else {
750 obj->UpdateFieldByteViaAccessor<kTransactionInactive>(field_offset, accessor);
751 }
752}
753
754template <>
755void FieldAccessViaAccessor<uint16_t>::Update(ObjPtr<Object> obj,
756 MemberOffset field_offset,
757 Accessor* accessor)
758 REQUIRES_SHARED(Locks::mutator_lock_) {
759 if (Runtime::Current()->IsActiveTransaction()) {
760 obj->UpdateFieldCharViaAccessor<kTransactionActive>(field_offset, accessor);
761 } else {
762 obj->UpdateFieldCharViaAccessor<kTransactionInactive>(field_offset, accessor);
763 }
764}
765
766template <>
767void FieldAccessViaAccessor<int16_t>::Update(ObjPtr<Object> obj,
768 MemberOffset field_offset,
769 Accessor* accessor)
770 REQUIRES_SHARED(Locks::mutator_lock_) {
771 if (Runtime::Current()->IsActiveTransaction()) {
772 obj->UpdateFieldShortViaAccessor<kTransactionActive>(field_offset, accessor);
773 } else {
774 obj->UpdateFieldShortViaAccessor<kTransactionInactive>(field_offset, accessor);
775 }
776}
777
778template <>
779void FieldAccessViaAccessor<int32_t>::Update(ObjPtr<Object> obj,
780 MemberOffset field_offset,
781 Accessor* accessor)
782 REQUIRES_SHARED(Locks::mutator_lock_) {
783 if (Runtime::Current()->IsActiveTransaction()) {
784 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, accessor);
785 } else {
786 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, accessor);
787 }
788}
789
790template <>
791void FieldAccessViaAccessor<int64_t>::Update(ObjPtr<Object> obj,
792 MemberOffset field_offset,
793 Accessor* accessor)
794 REQUIRES_SHARED(Locks::mutator_lock_) {
795 if (Runtime::Current()->IsActiveTransaction()) {
796 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, accessor);
797 } else {
798 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, accessor);
799 }
800}
801
802template <>
803void FieldAccessViaAccessor<float>::Update(ObjPtr<Object> obj,
804 MemberOffset field_offset,
805 Accessor* accessor)
806 REQUIRES_SHARED(Locks::mutator_lock_) {
807 TypeAdaptorAccessor<int32_t, float> float_to_int_accessor(accessor);
808 if (Runtime::Current()->IsActiveTransaction()) {
809 obj->UpdateField32ViaAccessor<kTransactionActive>(field_offset, &float_to_int_accessor);
810 } else {
811 obj->UpdateField32ViaAccessor<kTransactionInactive>(field_offset, &float_to_int_accessor);
812 }
813}
814
815template <>
816void FieldAccessViaAccessor<double>::Update(ObjPtr<Object> obj,
817 MemberOffset field_offset,
818 Accessor* accessor)
819 REQUIRES_SHARED(Locks::mutator_lock_) {
820 TypeAdaptorAccessor<int64_t, double> double_to_int_accessor(accessor);
821 if (Runtime::Current()->IsActiveTransaction()) {
822 obj->UpdateField64ViaAccessor<kTransactionActive>(field_offset, &double_to_int_accessor);
823 } else {
824 obj->UpdateField64ViaAccessor<kTransactionInactive>(field_offset, &double_to_int_accessor);
825 }
826}
827
828// Helper class that gets values from a shadow frame with appropriate type coercion.
829template <typename T>
830class ValueGetter {
831 public:
832 static T Get(ShadowFrameGetter* getter) REQUIRES_SHARED(Locks::mutator_lock_) {
833 static_assert(sizeof(T) <= sizeof(uint32_t), "Bad size");
834 uint32_t raw_value = getter->Get();
835 return static_cast<T>(raw_value);
836 }
837};
838
839template <>
840int64_t ValueGetter<int64_t>::Get(ShadowFrameGetter* getter) {
841 return getter->GetLong();
842}
843
844template <>
845float ValueGetter<float>::Get(ShadowFrameGetter* getter) {
846 uint32_t raw_value = getter->Get();
847 return *reinterpret_cast<float*>(&raw_value);
848}
849
850template <>
851double ValueGetter<double>::Get(ShadowFrameGetter* getter) {
852 int64_t raw_value = getter->GetLong();
853 return *reinterpret_cast<double*>(&raw_value);
854}
855
856template <>
857ObjPtr<Object> ValueGetter<ObjPtr<Object>>::Get(ShadowFrameGetter* getter) {
858 return getter->GetReference();
859}
860
861// Class for accessing fields of Object instances
862template <typename T>
863class FieldAccessor {
864 public:
865 static bool Dispatch(VarHandle::AccessMode access_mode,
866 ObjPtr<Object> obj,
867 MemberOffset field_offset,
868 ShadowFrameGetter* getter,
869 JValue* result)
870 REQUIRES_SHARED(Locks::mutator_lock_);
871};
872
873// Dispatch implementation for primitive fields.
874template <typename T>
875bool FieldAccessor<T>::Dispatch(VarHandle::AccessMode access_mode,
876 ObjPtr<Object> obj,
877 MemberOffset field_offset,
878 ShadowFrameGetter* getter,
879 JValue* result) {
880 switch (access_mode) {
881 case VarHandle::AccessMode::kGet: {
882 GetAccessor<T> accessor(result);
883 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
884 break;
885 }
886 case VarHandle::AccessMode::kSet: {
887 T new_value = ValueGetter<T>::Get(getter);
888 SetAccessor<T> accessor(new_value);
889 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
890 break;
891 }
892 case VarHandle::AccessMode::kGetAcquire:
893 case VarHandle::AccessMode::kGetOpaque:
894 case VarHandle::AccessMode::kGetVolatile: {
895 GetVolatileAccessor<T> accessor(result);
896 FieldAccessViaAccessor<T>::Get(obj, field_offset, &accessor);
897 break;
898 }
899 case VarHandle::AccessMode::kSetOpaque:
900 case VarHandle::AccessMode::kSetRelease:
901 case VarHandle::AccessMode::kSetVolatile: {
902 T new_value = ValueGetter<T>::Get(getter);
903 SetVolatileAccessor<T> accessor(new_value);
904 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
905 break;
906 }
907 case VarHandle::AccessMode::kCompareAndSet: {
908 T expected_value = ValueGetter<T>::Get(getter);
909 T desired_value = ValueGetter<T>::Get(getter);
910 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
911 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
912 break;
913 }
914 case VarHandle::AccessMode::kCompareAndExchange:
915 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
916 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
917 T expected_value = ValueGetter<T>::Get(getter);
918 T desired_value = ValueGetter<T>::Get(getter);
919 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
920 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
921 break;
922 }
923 case VarHandle::AccessMode::kWeakCompareAndSet:
924 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
925 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
926 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
927 T expected_value = ValueGetter<T>::Get(getter);
928 T desired_value = ValueGetter<T>::Get(getter);
929 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
930 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
931 break;
932 }
933 case VarHandle::AccessMode::kGetAndSet:
934 case VarHandle::AccessMode::kGetAndSetAcquire:
935 case VarHandle::AccessMode::kGetAndSetRelease: {
936 T new_value = ValueGetter<T>::Get(getter);
937 GetAndSetAccessor<T> accessor(new_value, result);
938 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
939 break;
940 }
941 case VarHandle::AccessMode::kGetAndAdd:
942 case VarHandle::AccessMode::kGetAndAddAcquire:
943 case VarHandle::AccessMode::kGetAndAddRelease: {
944 T value = ValueGetter<T>::Get(getter);
945 GetAndAddAccessor<T> accessor(value, result);
946 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
947 break;
948 }
949 case VarHandle::AccessMode::kGetAndBitwiseOr:
950 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
951 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
952 T value = ValueGetter<T>::Get(getter);
953 GetAndBitwiseOrAccessor<T> accessor(value, result);
954 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
955 break;
956 }
957 case VarHandle::AccessMode::kGetAndBitwiseAnd:
958 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
959 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
960 T value = ValueGetter<T>::Get(getter);
961 GetAndBitwiseAndAccessor<T> accessor(value, result);
962 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
963 break;
964 }
965 case VarHandle::AccessMode::kGetAndBitwiseXor:
966 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
967 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
968 T value = ValueGetter<T>::Get(getter);
969 GetAndBitwiseXorAccessor<T> accessor(value, result);
970 FieldAccessViaAccessor<T>::Update(obj, field_offset, &accessor);
971 break;
972 }
973 }
974 return true;
975}
976
977// Dispatch implementation for reference fields.
978template <>
979bool FieldAccessor<ObjPtr<Object>>::Dispatch(VarHandle::AccessMode access_mode,
980 ObjPtr<Object> obj,
981 MemberOffset field_offset,
982 ShadowFrameGetter* getter,
983 JValue* result)
984 REQUIRES_SHARED(Locks::mutator_lock_) {
985 // To keep things simple, use the minimum strongest existing
986 // field accessor for Object fields. This may be the most
987 // straightforward strategy in general for the interpreter.
988 switch (access_mode) {
989 case VarHandle::AccessMode::kGet: {
990 StoreResult(obj->GetFieldObject<Object>(field_offset), result);
991 break;
992 }
993 case VarHandle::AccessMode::kSet: {
994 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
995 if (Runtime::Current()->IsActiveTransaction()) {
996 obj->SetFieldObject<kTransactionActive>(field_offset, new_value);
997 } else {
998 obj->SetFieldObject<kTransactionInactive>(field_offset, new_value);
999 }
1000 break;
1001 }
1002 case VarHandle::AccessMode::kGetAcquire:
1003 case VarHandle::AccessMode::kGetOpaque:
1004 case VarHandle::AccessMode::kGetVolatile: {
1005 StoreResult(obj->GetFieldObjectVolatile<Object>(field_offset), result);
1006 break;
1007 }
1008 case VarHandle::AccessMode::kSetOpaque:
1009 case VarHandle::AccessMode::kSetRelease:
1010 case VarHandle::AccessMode::kSetVolatile: {
1011 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1012 if (Runtime::Current()->IsActiveTransaction()) {
1013 obj->SetFieldObjectVolatile<kTransactionActive>(field_offset, new_value);
1014 } else {
1015 obj->SetFieldObjectVolatile<kTransactionInactive>(field_offset, new_value);
1016 }
1017 break;
1018 }
1019 case VarHandle::AccessMode::kCompareAndSet: {
1020 ReadBarrierForVarHandleAccess(obj, field_offset);
1021 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1022 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1023 bool cas_result;
1024 if (Runtime::Current()->IsActiveTransaction()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001025 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
1026 expected_value,
1027 desired_value,
1028 CASMode::kStrong,
1029 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001030 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001031 cas_result = obj->CasFieldObject<kTransactionInactive>(field_offset,
1032 expected_value,
1033 desired_value,
1034 CASMode::kStrong,
1035 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001036 }
Andreas Gampe5ec6f362018-09-20 17:25:05 -07001037 StoreResult(static_cast<uint8_t>(cas_result), result);
Orion Hodson928033d2018-02-07 05:30:54 +00001038 break;
1039 }
1040 case VarHandle::AccessMode::kWeakCompareAndSet:
1041 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1042 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1043 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1044 ReadBarrierForVarHandleAccess(obj, field_offset);
1045 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1046 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1047 bool cas_result;
1048 if (Runtime::Current()->IsActiveTransaction()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001049 cas_result = obj->CasFieldObject<kTransactionActive>(field_offset,
1050 expected_value,
1051 desired_value,
1052 CASMode::kWeak,
1053 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001054 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001055 cas_result = obj->CasFieldObject<kTransactionInactive>(
Orion Hodson928033d2018-02-07 05:30:54 +00001056 field_offset,
1057 expected_value,
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001058 desired_value,
1059 CASMode::kWeak,
1060 std::memory_order_seq_cst);
Orion Hodson928033d2018-02-07 05:30:54 +00001061 }
Andreas Gampe5ec6f362018-09-20 17:25:05 -07001062 StoreResult(static_cast<uint8_t>(cas_result), result);
Orion Hodson928033d2018-02-07 05:30:54 +00001063 break;
1064 }
1065 case VarHandle::AccessMode::kCompareAndExchange:
1066 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1067 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1068 ReadBarrierForVarHandleAccess(obj, field_offset);
1069 ObjPtr<Object> expected_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1070 ObjPtr<Object> desired_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1071 ObjPtr<Object> witness_value;
1072 if (Runtime::Current()->IsActiveTransaction()) {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001073 witness_value = obj->CompareAndExchangeFieldObject<kTransactionActive>(field_offset,
1074 expected_value,
1075 desired_value);
Orion Hodson928033d2018-02-07 05:30:54 +00001076 } else {
Mathieu Chartiera9746b92018-06-22 10:25:40 -07001077 witness_value = obj->CompareAndExchangeFieldObject<kTransactionInactive>(field_offset,
1078 expected_value,
1079 desired_value);
Orion Hodson928033d2018-02-07 05:30:54 +00001080 }
1081 StoreResult(witness_value, result);
1082 break;
1083 }
1084 case VarHandle::AccessMode::kGetAndSet:
1085 case VarHandle::AccessMode::kGetAndSetAcquire:
1086 case VarHandle::AccessMode::kGetAndSetRelease: {
1087 ReadBarrierForVarHandleAccess(obj, field_offset);
1088 ObjPtr<Object> new_value = ValueGetter<ObjPtr<Object>>::Get(getter);
1089 ObjPtr<Object> old_value;
1090 if (Runtime::Current()->IsActiveTransaction()) {
1091 old_value = obj->ExchangeFieldObject<kTransactionActive>(field_offset, new_value);
1092 } else {
1093 old_value = obj->ExchangeFieldObject<kTransactionInactive>(field_offset, new_value);
1094 }
1095 StoreResult(old_value, result);
1096 break;
1097 }
1098 case VarHandle::AccessMode::kGetAndAdd:
1099 case VarHandle::AccessMode::kGetAndAddAcquire:
1100 case VarHandle::AccessMode::kGetAndAddRelease:
1101 case VarHandle::AccessMode::kGetAndBitwiseOr:
1102 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1103 case VarHandle::AccessMode::kGetAndBitwiseOrRelease:
1104 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1105 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1106 case VarHandle::AccessMode::kGetAndBitwiseAndRelease:
1107 case VarHandle::AccessMode::kGetAndBitwiseXor:
1108 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1109 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1110 size_t index = static_cast<size_t>(access_mode);
1111 const char* access_mode_name = kAccessorToAccessMode[index].method_name;
1112 UnreachableAccessMode(access_mode_name, "Object");
1113 }
1114 }
1115 return true;
1116}
1117
1118// Class for accessing primitive array elements.
1119template <typename T>
1120class PrimitiveArrayElementAccessor {
1121 public:
1122 static T* GetElementAddress(ObjPtr<Array> target_array, int target_element)
1123 REQUIRES_SHARED(Locks::mutator_lock_) {
1124 auto primitive_array = ObjPtr<PrimitiveArray<T>>::DownCast(target_array);
1125 DCHECK(primitive_array->CheckIsValidIndex(target_element));
1126 return &primitive_array->GetData()[target_element];
1127 }
1128
1129 static bool Dispatch(VarHandle::AccessMode access_mode,
1130 ObjPtr<Array> target_array,
1131 int target_element,
1132 ShadowFrameGetter* getter,
1133 JValue* result)
1134 REQUIRES_SHARED(Locks::mutator_lock_) {
1135 T* element_address = GetElementAddress(target_array, target_element);
1136 switch (access_mode) {
1137 case VarHandle::AccessMode::kGet: {
1138 GetAccessor<T> accessor(result);
1139 accessor.Access(element_address);
1140 break;
1141 }
1142 case VarHandle::AccessMode::kSet: {
1143 T new_value = ValueGetter<T>::Get(getter);
1144 SetAccessor<T> accessor(new_value);
1145 accessor.Access(element_address);
1146 break;
1147 }
1148 case VarHandle::AccessMode::kGetAcquire:
1149 case VarHandle::AccessMode::kGetOpaque:
1150 case VarHandle::AccessMode::kGetVolatile: {
1151 GetVolatileAccessor<T> accessor(result);
1152 accessor.Access(element_address);
1153 break;
1154 }
1155 case VarHandle::AccessMode::kSetOpaque:
1156 case VarHandle::AccessMode::kSetRelease:
1157 case VarHandle::AccessMode::kSetVolatile: {
1158 T new_value = ValueGetter<T>::Get(getter);
1159 SetVolatileAccessor<T> accessor(new_value);
1160 accessor.Access(element_address);
1161 break;
1162 }
1163 case VarHandle::AccessMode::kCompareAndSet: {
1164 T expected_value = ValueGetter<T>::Get(getter);
1165 T desired_value = ValueGetter<T>::Get(getter);
1166 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1167 accessor.Access(element_address);
1168 break;
1169 }
1170 case VarHandle::AccessMode::kCompareAndExchange:
1171 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1172 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1173 T expected_value = ValueGetter<T>::Get(getter);
1174 T desired_value = ValueGetter<T>::Get(getter);
1175 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1176 accessor.Access(element_address);
1177 break;
1178 }
1179 case VarHandle::AccessMode::kWeakCompareAndSet:
1180 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1181 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1182 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1183 T expected_value = ValueGetter<T>::Get(getter);
1184 T desired_value = ValueGetter<T>::Get(getter);
1185 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1186 accessor.Access(element_address);
1187 break;
1188 }
1189 case VarHandle::AccessMode::kGetAndSet:
1190 case VarHandle::AccessMode::kGetAndSetAcquire:
1191 case VarHandle::AccessMode::kGetAndSetRelease: {
1192 T new_value = ValueGetter<T>::Get(getter);
1193 GetAndSetAccessor<T> accessor(new_value, result);
1194 accessor.Access(element_address);
1195 break;
1196 }
1197 case VarHandle::AccessMode::kGetAndAdd:
1198 case VarHandle::AccessMode::kGetAndAddAcquire:
1199 case VarHandle::AccessMode::kGetAndAddRelease: {
1200 T value = ValueGetter<T>::Get(getter);
1201 GetAndAddAccessor<T> accessor(value, result);
1202 accessor.Access(element_address);
1203 break;
1204 }
1205 case VarHandle::AccessMode::kGetAndBitwiseOr:
1206 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1207 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1208 T value = ValueGetter<T>::Get(getter);
1209 GetAndBitwiseOrAccessor<T> accessor(value, result);
1210 accessor.Access(element_address);
1211 break;
1212 }
1213 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1214 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1215 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1216 T value = ValueGetter<T>::Get(getter);
1217 GetAndBitwiseAndAccessor<T> accessor(value, result);
1218 accessor.Access(element_address);
1219 break;
1220 }
1221 case VarHandle::AccessMode::kGetAndBitwiseXor:
1222 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1223 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1224 T value = ValueGetter<T>::Get(getter);
1225 GetAndBitwiseXorAccessor<T> accessor(value, result);
1226 accessor.Access(element_address);
1227 break;
1228 }
1229 }
1230 return true;
1231 }
1232};
1233
1234// Class for accessing primitive array elements.
1235template <typename T>
1236class ByteArrayViewAccessor {
1237 public:
1238 static inline bool IsAccessAligned(int8_t* data, int data_index) {
1239 static_assert(IsPowerOfTwo(sizeof(T)), "unexpected size");
1240 static_assert(std::is_arithmetic<T>::value, "unexpected type");
1241 uintptr_t alignment_mask = sizeof(T) - 1;
1242 uintptr_t address = reinterpret_cast<uintptr_t>(data + data_index);
1243 return (address & alignment_mask) == 0;
1244 }
1245
1246 static inline void MaybeByteSwap(bool byte_swap, T* const value) {
1247 if (byte_swap) {
1248 *value = BSWAP(*value);
1249 }
1250 }
1251
1252 static bool Dispatch(const VarHandle::AccessMode access_mode,
1253 int8_t* const data,
1254 const int data_index,
1255 const bool byte_swap,
1256 ShadowFrameGetter* const getter,
1257 JValue* const result)
1258 REQUIRES_SHARED(Locks::mutator_lock_) {
1259 const bool is_aligned = IsAccessAligned(data, data_index);
1260 if (!is_aligned) {
1261 switch (access_mode) {
1262 case VarHandle::AccessMode::kGet: {
1263 T value;
1264 memcpy(&value, data + data_index, sizeof(T));
1265 MaybeByteSwap(byte_swap, &value);
1266 StoreResult(value, result);
1267 return true;
1268 }
1269 case VarHandle::AccessMode::kSet: {
1270 T new_value = ValueGetter<T>::Get(getter);
1271 MaybeByteSwap(byte_swap, &new_value);
1272 memcpy(data + data_index, &new_value, sizeof(T));
1273 return true;
1274 }
1275 default:
1276 // No other access modes support unaligned access.
1277 ThrowIllegalStateException("Unaligned access not supported");
1278 return false;
1279 }
1280 }
1281
1282 T* const element_address = reinterpret_cast<T*>(data + data_index);
1283 CHECK(IsAccessAligned(reinterpret_cast<int8_t*>(element_address), 0));
1284 switch (access_mode) {
1285 case VarHandle::AccessMode::kGet: {
1286 GetAccessor<T> accessor(result);
1287 accessor.Access(element_address);
1288 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1289 break;
1290 }
1291 case VarHandle::AccessMode::kSet: {
1292 T new_value = ValueGetter<T>::Get(getter);
1293 MaybeByteSwap(byte_swap, &new_value);
1294 SetAccessor<T> accessor(new_value);
1295 accessor.Access(element_address);
1296 break;
1297 }
1298 case VarHandle::AccessMode::kGetAcquire:
1299 case VarHandle::AccessMode::kGetOpaque:
1300 case VarHandle::AccessMode::kGetVolatile: {
1301 GetVolatileAccessor<T> accessor(result);
1302 accessor.Access(element_address);
1303 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1304 break;
1305 }
1306 case VarHandle::AccessMode::kSetOpaque:
1307 case VarHandle::AccessMode::kSetRelease:
1308 case VarHandle::AccessMode::kSetVolatile: {
1309 T new_value = ValueGetter<T>::Get(getter);
1310 MaybeByteSwap(byte_swap, &new_value);
1311 SetVolatileAccessor<T> accessor(new_value);
1312 accessor.Access(element_address);
1313 break;
1314 }
1315 case VarHandle::AccessMode::kCompareAndSet: {
1316 T expected_value = ValueGetter<T>::Get(getter);
1317 T desired_value = ValueGetter<T>::Get(getter);
1318 MaybeByteSwap(byte_swap, &expected_value);
1319 MaybeByteSwap(byte_swap, &desired_value);
1320 CompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1321 accessor.Access(element_address);
1322 break;
1323 }
1324 case VarHandle::AccessMode::kCompareAndExchange:
1325 case VarHandle::AccessMode::kCompareAndExchangeAcquire:
1326 case VarHandle::AccessMode::kCompareAndExchangeRelease: {
1327 T expected_value = ValueGetter<T>::Get(getter);
1328 T desired_value = ValueGetter<T>::Get(getter);
1329 MaybeByteSwap(byte_swap, &expected_value);
1330 MaybeByteSwap(byte_swap, &desired_value);
1331 CompareAndExchangeAccessor<T> accessor(expected_value, desired_value, result);
1332 accessor.Access(element_address);
1333 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1334 break;
1335 }
1336 case VarHandle::AccessMode::kWeakCompareAndSet:
1337 case VarHandle::AccessMode::kWeakCompareAndSetAcquire:
1338 case VarHandle::AccessMode::kWeakCompareAndSetPlain:
1339 case VarHandle::AccessMode::kWeakCompareAndSetRelease: {
1340 T expected_value = ValueGetter<T>::Get(getter);
1341 T desired_value = ValueGetter<T>::Get(getter);
1342 MaybeByteSwap(byte_swap, &expected_value);
1343 MaybeByteSwap(byte_swap, &desired_value);
1344 WeakCompareAndSetAccessor<T> accessor(expected_value, desired_value, result);
1345 accessor.Access(element_address);
1346 break;
1347 }
1348 case VarHandle::AccessMode::kGetAndSet:
1349 case VarHandle::AccessMode::kGetAndSetAcquire:
1350 case VarHandle::AccessMode::kGetAndSetRelease: {
1351 T new_value = ValueGetter<T>::Get(getter);
1352 MaybeByteSwap(byte_swap, &new_value);
1353 GetAndSetAccessor<T> accessor(new_value, result);
1354 accessor.Access(element_address);
1355 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1356 break;
1357 }
1358 case VarHandle::AccessMode::kGetAndAdd:
1359 case VarHandle::AccessMode::kGetAndAddAcquire:
1360 case VarHandle::AccessMode::kGetAndAddRelease: {
1361 T value = ValueGetter<T>::Get(getter);
1362 if (byte_swap) {
1363 GetAndAddWithByteSwapAccessor<T> accessor(value, result);
1364 accessor.Access(element_address);
1365 } else {
1366 GetAndAddAccessor<T> accessor(value, result);
1367 accessor.Access(element_address);
1368 }
1369 break;
1370 }
1371 case VarHandle::AccessMode::kGetAndBitwiseOr:
1372 case VarHandle::AccessMode::kGetAndBitwiseOrAcquire:
1373 case VarHandle::AccessMode::kGetAndBitwiseOrRelease: {
1374 T value = ValueGetter<T>::Get(getter);
1375 MaybeByteSwap(byte_swap, &value);
1376 GetAndBitwiseOrAccessor<T> accessor(value, result);
1377 accessor.Access(element_address);
1378 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1379 break;
1380 }
1381 case VarHandle::AccessMode::kGetAndBitwiseAnd:
1382 case VarHandle::AccessMode::kGetAndBitwiseAndAcquire:
1383 case VarHandle::AccessMode::kGetAndBitwiseAndRelease: {
1384 T value = ValueGetter<T>::Get(getter);
1385 MaybeByteSwap(byte_swap, &value);
1386 GetAndBitwiseAndAccessor<T> accessor(value, result);
1387 accessor.Access(element_address);
1388 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1389 break;
1390 }
1391 case VarHandle::AccessMode::kGetAndBitwiseXor:
1392 case VarHandle::AccessMode::kGetAndBitwiseXorAcquire:
1393 case VarHandle::AccessMode::kGetAndBitwiseXorRelease: {
1394 T value = ValueGetter<T>::Get(getter);
1395 MaybeByteSwap(byte_swap, &value);
1396 GetAndBitwiseXorAccessor<T> accessor(value, result);
1397 accessor.Access(element_address);
1398 JValueByteSwapper<T>::MaybeByteSwap(byte_swap, result);
1399 break;
1400 }
1401 }
1402 return true;
1403 }
1404};
1405
Orion Hodson005ac512017-10-24 15:43:43 +01001406} // namespace
1407
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001408ObjPtr<Class> VarHandle::GetVarType() {
Orion Hodson005ac512017-10-24 15:43:43 +01001409 return GetFieldObject<Class>(VarTypeOffset());
1410}
1411
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001412ObjPtr<Class> VarHandle::GetCoordinateType0() {
Orion Hodson005ac512017-10-24 15:43:43 +01001413 return GetFieldObject<Class>(CoordinateType0Offset());
1414}
1415
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001416ObjPtr<Class> VarHandle::GetCoordinateType1() {
Orion Hodson005ac512017-10-24 15:43:43 +01001417 return GetFieldObject<Class>(CoordinateType1Offset());
1418}
1419
1420int32_t VarHandle::GetAccessModesBitMask() {
1421 return GetField32(AccessModesBitMaskOffset());
1422}
1423
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001424VarHandle::MatchKind VarHandle::GetMethodTypeMatchForAccessMode(AccessMode access_mode,
1425 MethodType* method_type) {
1426 MatchKind match = MatchKind::kExact;
1427
1428 ObjPtr<VarHandle> vh = this;
1429 ObjPtr<Class> var_type = vh->GetVarType();
1430 ObjPtr<Class> mt_rtype = method_type->GetRType();
Orion Hodsonc4d3bf42018-02-06 16:02:49 +00001431 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
Orion Hodsonc4d3bf42018-02-06 16:02:49 +00001432
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001433 // Check return type first. If the return type of the method
1434 // of the VarHandle is immaterial.
1435 if (mt_rtype->GetPrimitiveType() != Primitive::Type::kPrimVoid) {
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001436 ObjPtr<Class> vh_rtype = GetReturnType(access_mode_template, var_type);
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001437 if (vh_rtype != mt_rtype) {
1438 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype)) {
1439 return MatchKind::kNone;
1440 }
1441 match = MatchKind::kWithConversions;
Orion Hodson928033d2018-02-07 05:30:54 +00001442 }
Orion Hodson005ac512017-10-24 15:43:43 +01001443 }
1444
1445 // Check the number of parameters matches.
1446 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
1447 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1448 access_mode_template,
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001449 var_type,
Orion Hodson005ac512017-10-24 15:43:43 +01001450 GetCoordinateType0(),
1451 GetCoordinateType1());
1452 if (vh_ptypes_count != method_type->GetPTypes()->GetLength()) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001453 return MatchKind::kNone;
Orion Hodson005ac512017-10-24 15:43:43 +01001454 }
1455
Orion Hodson928033d2018-02-07 05:30:54 +00001456 // Check the parameter types are compatible.
Orion Hodson005ac512017-10-24 15:43:43 +01001457 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
1458 for (int32_t i = 0; i < vh_ptypes_count; ++i) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001459 if (mt_ptypes->Get(i) == vh_ptypes[i]) {
1460 continue;
Orion Hodson005ac512017-10-24 15:43:43 +01001461 }
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001462 if (!IsParameterTypeConvertible(mt_ptypes->Get(i), vh_ptypes[i])) {
1463 return MatchKind::kNone;
1464 }
1465 match = MatchKind::kWithConversions;
Orion Hodson005ac512017-10-24 15:43:43 +01001466 }
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001467 return match;
Orion Hodson005ac512017-10-24 15:43:43 +01001468}
1469
Orion Hodsonb8b93872018-01-30 07:51:10 +00001470bool VarHandle::IsInvokerMethodTypeCompatible(AccessMode access_mode,
1471 MethodType* method_type) {
1472 StackHandleScope<3> hs(Thread::Current());
1473 Handle<Class> mt_rtype(hs.NewHandle(method_type->GetRType()));
1474 Handle<VarHandle> vh(hs.NewHandle(this));
1475 Handle<Class> var_type(hs.NewHandle(vh->GetVarType()));
1476 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1477
1478 // Check return type first.
1479 if (mt_rtype->GetPrimitiveType() == Primitive::Type::kPrimVoid) {
1480 // The result of the operation will be discarded. The return type
1481 // of the VarHandle is immaterial.
1482 } else {
1483 ObjPtr<Class> vh_rtype(GetReturnType(access_mode_template, var_type.Get()));
1484 if (!IsReturnTypeConvertible(vh_rtype, mt_rtype.Get())) {
1485 return false;
1486 }
1487 }
1488
1489 // Check the number of parameters matches (ignoring the VarHandle parameter).
1490 static const int32_t kVarHandleParameters = 1;
1491 ObjPtr<Class> vh_ptypes[VarHandle::kMaxAccessorParameters];
1492 const int32_t vh_ptypes_count = BuildParameterArray(vh_ptypes,
1493 access_mode_template,
1494 var_type.Get(),
1495 GetCoordinateType0(),
1496 GetCoordinateType1());
1497 if (vh_ptypes_count != method_type->GetPTypes()->GetLength() - kVarHandleParameters) {
1498 return false;
1499 }
1500
1501 // Check the parameter types are compatible (ignoring the VarHandle parameter).
1502 ObjPtr<ObjectArray<Class>> mt_ptypes = method_type->GetPTypes();
1503 for (int32_t i = 0; i < vh_ptypes_count; ++i) {
1504 if (!IsParameterTypeConvertible(mt_ptypes->Get(i + kVarHandleParameters), vh_ptypes[i])) {
1505 return false;
1506 }
1507 }
1508 return true;
1509}
1510
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001511ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self,
1512 ObjPtr<VarHandle> var_handle,
1513 AccessMode access_mode) {
Orion Hodsonc4d5c132018-05-15 13:57:58 +01001514 // 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 +01001515 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1516
1517 StackHandleScope<3> hs(self);
1518 Handle<VarHandle> vh = hs.NewHandle(var_handle);
1519 Handle<Class> rtype = hs.NewHandle(GetReturnType(access_mode_template, vh->GetVarType()));
Orion Hodson928033d2018-02-07 05:30:54 +00001520 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template,
1521 vh->GetCoordinateType0(),
1522 vh->GetCoordinateType1());
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001523 ObjPtr<Class> array_of_class = GetClassRoot<ObjectArray<Class>>();
1524 Handle<ObjectArray<Class>> ptypes =
1525 hs.NewHandle(ObjectArray<Class>::Alloc(Thread::Current(), array_of_class, ptypes_count));
Orion Hodson005ac512017-10-24 15:43:43 +01001526 if (ptypes == nullptr) {
1527 return nullptr;
1528 }
1529
1530 ObjPtr<Class> ptypes_array[VarHandle::kMaxAccessorParameters];
1531 BuildParameterArray(ptypes_array,
1532 access_mode_template,
1533 vh->GetVarType(),
1534 vh->GetCoordinateType0(),
1535 vh->GetCoordinateType1());
1536 for (int32_t i = 0; i < ptypes_count; ++i) {
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001537 ptypes->Set(i, ptypes_array[i]);
Orion Hodson005ac512017-10-24 15:43:43 +01001538 }
1539 return MethodType::Create(self, rtype, ptypes);
1540}
1541
Vladimir Markoa8bba7d2018-05-30 15:18:48 +01001542ObjPtr<MethodType> VarHandle::GetMethodTypeForAccessMode(Thread* self, AccessMode access_mode) {
Orion Hodson005ac512017-10-24 15:43:43 +01001543 return GetMethodTypeForAccessMode(self, this, access_mode);
1544}
1545
Orion Hodson3f383462018-05-17 14:03:39 +01001546std::string VarHandle::PrettyDescriptorForAccessMode(AccessMode access_mode) {
1547 // Effect MethodType::PrettyDescriptor() without first creating a method type first.
1548 std::ostringstream oss;
1549 oss << '(';
1550
1551 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1552 ObjPtr<Class> var_type = GetVarType();
1553 ObjPtr<Class> ctypes[2] = { GetCoordinateType0(), GetCoordinateType1() };
1554 const int32_t ptypes_count = GetNumberOfParameters(access_mode_template, ctypes[0], ctypes[1]);
1555 int32_t ptypes_done = 0;
1556 for (ObjPtr<Class> ctype : ctypes) {
1557 if (!ctype.IsNull()) {
1558 if (ptypes_done != 0) {
1559 oss << ", ";
1560 }
1561 oss << ctype->PrettyDescriptor();;
1562 ptypes_done++;
1563 }
1564 }
1565 while (ptypes_done != ptypes_count) {
1566 if (ptypes_done != 0) {
1567 oss << ", ";
1568 }
1569 oss << var_type->PrettyDescriptor();
1570 ptypes_done++;
1571 }
1572 ObjPtr<Class> rtype = GetReturnType(access_mode_template, var_type);
1573 oss << ')' << rtype->PrettyDescriptor();
1574 return oss.str();
1575}
1576
Orion Hodson928033d2018-02-07 05:30:54 +00001577bool VarHandle::Access(AccessMode access_mode,
1578 ShadowFrame* shadow_frame,
Orion Hodson537a4fe2018-05-15 13:57:58 +01001579 const InstructionOperands* const operands,
Orion Hodson928033d2018-02-07 05:30:54 +00001580 JValue* result) {
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001581 ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
1582 ObjPtr<Class> klass = GetClass();
1583 if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001584 auto vh = reinterpret_cast<FieldVarHandle*>(this);
1585 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001586 } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001587 auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
1588 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001589 } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001590 auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
1591 return vh->Access(access_mode, shadow_frame, operands, result);
Vladimir Markoc7aa87e2018-05-24 15:19:52 +01001592 } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
Orion Hodson928033d2018-02-07 05:30:54 +00001593 auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
1594 return vh->Access(access_mode, shadow_frame, operands, result);
1595 } else {
1596 LOG(FATAL) << "Unknown varhandle kind";
1597 UNREACHABLE();
1598 }
1599}
1600
Orion Hodsonfe92d122018-01-02 10:45:17 +00001601const char* VarHandle::GetReturnTypeDescriptor(const char* accessor_name) {
1602 AccessMode access_mode;
1603 if (!GetAccessModeByMethodName(accessor_name, &access_mode)) {
1604 return nullptr;
1605 }
1606 AccessModeTemplate access_mode_template = GetAccessModeTemplate(access_mode);
1607 switch (access_mode_template) {
1608 case AccessModeTemplate::kGet:
1609 case AccessModeTemplate::kCompareAndExchange:
1610 case AccessModeTemplate::kGetAndUpdate:
1611 return "Ljava/lang/Object;";
1612 case AccessModeTemplate::kCompareAndSet:
1613 return "Z";
1614 case AccessModeTemplate::kSet:
1615 return "V";
1616 }
1617}
1618
Orion Hodsonb8b93872018-01-30 07:51:10 +00001619VarHandle::AccessMode VarHandle::GetAccessModeByIntrinsic(Intrinsics intrinsic) {
1620#define VAR_HANDLE_ACCESS_MODE(V) \
1621 V(CompareAndExchange) \
1622 V(CompareAndExchangeAcquire) \
1623 V(CompareAndExchangeRelease) \
1624 V(CompareAndSet) \
1625 V(Get) \
1626 V(GetAcquire) \
1627 V(GetAndAdd) \
1628 V(GetAndAddAcquire) \
1629 V(GetAndAddRelease) \
1630 V(GetAndBitwiseAnd) \
1631 V(GetAndBitwiseAndAcquire) \
1632 V(GetAndBitwiseAndRelease) \
1633 V(GetAndBitwiseOr) \
1634 V(GetAndBitwiseOrAcquire) \
1635 V(GetAndBitwiseOrRelease) \
1636 V(GetAndBitwiseXor) \
1637 V(GetAndBitwiseXorAcquire) \
1638 V(GetAndBitwiseXorRelease) \
1639 V(GetAndSet) \
1640 V(GetAndSetAcquire) \
1641 V(GetAndSetRelease) \
1642 V(GetOpaque) \
1643 V(GetVolatile) \
1644 V(Set) \
1645 V(SetOpaque) \
1646 V(SetRelease) \
1647 V(SetVolatile) \
1648 V(WeakCompareAndSet) \
1649 V(WeakCompareAndSetAcquire) \
1650 V(WeakCompareAndSetPlain) \
1651 V(WeakCompareAndSetRelease)
1652 switch (intrinsic) {
1653#define INTRINSIC_CASE(Name) \
1654 case Intrinsics::kVarHandle ## Name: \
1655 return VarHandle::AccessMode::k ## Name;
1656 VAR_HANDLE_ACCESS_MODE(INTRINSIC_CASE)
1657#undef INTRINSIC_CASE
1658#undef VAR_HANDLE_ACCESS_MODE
1659 default:
1660 break;
1661 }
1662 LOG(FATAL) << "Unknown VarHandle instrinsic: " << static_cast<int>(intrinsic);
1663 UNREACHABLE();
1664}
1665
Orion Hodsonfe92d122018-01-02 10:45:17 +00001666bool VarHandle::GetAccessModeByMethodName(const char* method_name, AccessMode* access_mode) {
1667 if (method_name == nullptr) {
1668 return false;
1669 }
1670 VarHandleAccessorToAccessModeEntry target = { method_name, /*dummy*/VarHandle::AccessMode::kGet };
1671 auto last = std::cend(kAccessorToAccessMode);
1672 auto it = std::lower_bound(std::cbegin(kAccessorToAccessMode),
1673 last,
1674 target,
1675 VarHandleAccessorToAccessModeEntry::CompareName);
1676 if (it == last || strcmp(it->method_name, method_name) != 0) {
1677 return false;
1678 }
1679 *access_mode = it->access_mode;
1680 return true;
1681}
1682
Orion Hodson005ac512017-10-24 15:43:43 +01001683ArtField* FieldVarHandle::GetField() {
Vladimir Marko78baed52018-10-11 10:44:58 +01001684 return reinterpret_cast64<ArtField*>(GetField64(ArtFieldOffset()));
Orion Hodson005ac512017-10-24 15:43:43 +01001685}
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