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