1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 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 #ifndef ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
21*795d594fSAndroid Build Coastguard Worker #include "object_array.h"
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include <string>
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
26*795d594fSAndroid Build Coastguard Worker
27*795d594fSAndroid Build Coastguard Worker #include "array-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "class.h"
29*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
30*795d594fSAndroid Build Coastguard Worker #include "object-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "read_barrier-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
33*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
34*795d594fSAndroid Build Coastguard Worker #include "write_barrier-inl.h"
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
37*795d594fSAndroid Build Coastguard Worker namespace mirror {
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
Get(int32_t i)40*795d594fSAndroid Build Coastguard Worker inline ObjPtr<T> ObjectArray<T>::Get(int32_t i) {
41*795d594fSAndroid Build Coastguard Worker if (!CheckIsValidIndex<kVerifyFlags>(i)) {
42*795d594fSAndroid Build Coastguard Worker DCHECK(Thread::Current()->IsExceptionPending());
43*795d594fSAndroid Build Coastguard Worker return nullptr;
44*795d594fSAndroid Build Coastguard Worker }
45*795d594fSAndroid Build Coastguard Worker return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
46*795d594fSAndroid Build Coastguard Worker }
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker template<class T> template<VerifyObjectFlags kVerifyFlags>
CheckAssignable(ObjPtr<T> object)49*795d594fSAndroid Build Coastguard Worker inline bool ObjectArray<T>::CheckAssignable(ObjPtr<T> object) {
50*795d594fSAndroid Build Coastguard Worker if (object != nullptr) {
51*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> element_class = GetClass<kVerifyFlags>()->GetComponentType();
52*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(!object->InstanceOf(element_class))) {
53*795d594fSAndroid Build Coastguard Worker ThrowArrayStoreException(object);
54*795d594fSAndroid Build Coastguard Worker return false;
55*795d594fSAndroid Build Coastguard Worker }
56*795d594fSAndroid Build Coastguard Worker }
57*795d594fSAndroid Build Coastguard Worker return true;
58*795d594fSAndroid Build Coastguard Worker }
59*795d594fSAndroid Build Coastguard Worker
60*795d594fSAndroid Build Coastguard Worker template<class T>
Set(int32_t i,ObjPtr<T> object)61*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
62*795d594fSAndroid Build Coastguard Worker if (Runtime::Current()->IsActiveTransaction()) {
63*795d594fSAndroid Build Coastguard Worker Set<true>(i, object);
64*795d594fSAndroid Build Coastguard Worker } else {
65*795d594fSAndroid Build Coastguard Worker Set<false>(i, object);
66*795d594fSAndroid Build Coastguard Worker }
67*795d594fSAndroid Build Coastguard Worker }
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker template<class T>
70*795d594fSAndroid Build Coastguard Worker template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Set(int32_t i,ObjPtr<T> object)71*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
72*795d594fSAndroid Build Coastguard Worker if (CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object)) {
73*795d594fSAndroid Build Coastguard Worker SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
74*795d594fSAndroid Build Coastguard Worker } else {
75*795d594fSAndroid Build Coastguard Worker DCHECK(Thread::Current()->IsExceptionPending());
76*795d594fSAndroid Build Coastguard Worker }
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker
79*795d594fSAndroid Build Coastguard Worker template<class T>
80*795d594fSAndroid Build Coastguard Worker template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetWithoutChecks(int32_t i,ObjPtr<T> object)81*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::SetWithoutChecks(int32_t i, ObjPtr<T> object) {
82*795d594fSAndroid Build Coastguard Worker DCHECK(CheckIsValidIndex<kVerifyFlags>(i)) << i << " vs " << GetLength();
83*795d594fSAndroid Build Coastguard Worker DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
84*795d594fSAndroid Build Coastguard Worker SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker
87*795d594fSAndroid Build Coastguard Worker template<class T>
88*795d594fSAndroid Build Coastguard Worker template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetWithoutChecksAndWriteBarrier(int32_t i,ObjPtr<T> object)89*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, ObjPtr<T> object) {
90*795d594fSAndroid Build Coastguard Worker DCHECK(CheckIsValidIndex<kVerifyFlags>(i)) << i << " vs " << GetLength();
91*795d594fSAndroid Build Coastguard Worker // TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
92*795d594fSAndroid Build Coastguard Worker // DCHECK(CheckAssignable(object));
93*795d594fSAndroid Build Coastguard Worker SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
94*795d594fSAndroid Build Coastguard Worker OffsetOfElement(i), object);
95*795d594fSAndroid Build Coastguard Worker }
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetWithoutChecks(int32_t i)98*795d594fSAndroid Build Coastguard Worker inline ObjPtr<T> ObjectArray<T>::GetWithoutChecks(int32_t i) {
99*795d594fSAndroid Build Coastguard Worker DCHECK(CheckIsValidIndex(i)) << i << " vs " << GetLength();
100*795d594fSAndroid Build Coastguard Worker return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
101*795d594fSAndroid Build Coastguard Worker }
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Worker template<class T>
AssignableMemmove(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count)104*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos,
105*795d594fSAndroid Build Coastguard Worker ObjPtr<ObjectArray<T>> src,
106*795d594fSAndroid Build Coastguard Worker int32_t src_pos,
107*795d594fSAndroid Build Coastguard Worker int32_t count) {
108*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
109*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
110*795d594fSAndroid Build Coastguard Worker // The get will perform the VerifyObject.
111*795d594fSAndroid Build Coastguard Worker src->GetWithoutChecks(src_pos + i);
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker }
114*795d594fSAndroid Build Coastguard Worker // Perform the memmove using int memmove then perform the write barrier.
115*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
116*795d594fSAndroid Build Coastguard Worker "art::mirror::HeapReference<T> and uint32_t have different sizes.");
117*795d594fSAndroid Build Coastguard Worker // TODO: Optimize this later?
118*795d594fSAndroid Build Coastguard Worker // We can't use memmove since it does not handle read barriers and may do by per byte copying.
119*795d594fSAndroid Build Coastguard Worker // See b/32012820.
120*795d594fSAndroid Build Coastguard Worker const bool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count);
121*795d594fSAndroid Build Coastguard Worker if (copy_forward) {
122*795d594fSAndroid Build Coastguard Worker // Forward copy.
123*795d594fSAndroid Build Coastguard Worker bool baker_non_gray_case = false;
124*795d594fSAndroid Build Coastguard Worker if (gUseReadBarrier && kUseBakerReadBarrier) {
125*795d594fSAndroid Build Coastguard Worker uintptr_t fake_address_dependency;
126*795d594fSAndroid Build Coastguard Worker if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
127*795d594fSAndroid Build Coastguard Worker baker_non_gray_case = true;
128*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(fake_address_dependency, 0U);
129*795d594fSAndroid Build Coastguard Worker src.Assign(reinterpret_cast<ObjectArray<T>*>(
130*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
131*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
132*795d594fSAndroid Build Coastguard Worker // We can skip the RB here because 'src' isn't gray.
133*795d594fSAndroid Build Coastguard Worker ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
134*795d594fSAndroid Build Coastguard Worker src_pos + i);
135*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker }
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker if (!baker_non_gray_case) {
140*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
141*795d594fSAndroid Build Coastguard Worker // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
142*795d594fSAndroid Build Coastguard Worker ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
143*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker }
146*795d594fSAndroid Build Coastguard Worker } else {
147*795d594fSAndroid Build Coastguard Worker // Backward copy.
148*795d594fSAndroid Build Coastguard Worker bool baker_non_gray_case = false;
149*795d594fSAndroid Build Coastguard Worker if (gUseReadBarrier && kUseBakerReadBarrier) {
150*795d594fSAndroid Build Coastguard Worker uintptr_t fake_address_dependency;
151*795d594fSAndroid Build Coastguard Worker if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
152*795d594fSAndroid Build Coastguard Worker baker_non_gray_case = true;
153*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(fake_address_dependency, 0U);
154*795d594fSAndroid Build Coastguard Worker src.Assign(reinterpret_cast<ObjectArray<T>*>(
155*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
156*795d594fSAndroid Build Coastguard Worker for (int i = count - 1; i >= 0; --i) {
157*795d594fSAndroid Build Coastguard Worker // We can skip the RB here because 'src' isn't gray.
158*795d594fSAndroid Build Coastguard Worker ObjPtr<T> obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
159*795d594fSAndroid Build Coastguard Worker src_pos + i);
160*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker }
163*795d594fSAndroid Build Coastguard Worker }
164*795d594fSAndroid Build Coastguard Worker if (!baker_non_gray_case) {
165*795d594fSAndroid Build Coastguard Worker for (int i = count - 1; i >= 0; --i) {
166*795d594fSAndroid Build Coastguard Worker // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
167*795d594fSAndroid Build Coastguard Worker ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
168*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
169*795d594fSAndroid Build Coastguard Worker }
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker WriteBarrier::ForArrayWrite(this, dst_pos, count);
173*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
174*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
175*795d594fSAndroid Build Coastguard Worker // The get will perform the VerifyObject.
176*795d594fSAndroid Build Coastguard Worker GetWithoutChecks(dst_pos + i);
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker }
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker
181*795d594fSAndroid Build Coastguard Worker template<class T>
AssignableMemcpy(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count)182*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos,
183*795d594fSAndroid Build Coastguard Worker ObjPtr<ObjectArray<T>> src,
184*795d594fSAndroid Build Coastguard Worker int32_t src_pos,
185*795d594fSAndroid Build Coastguard Worker int32_t count) {
186*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
187*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
188*795d594fSAndroid Build Coastguard Worker // The get will perform the VerifyObject.
189*795d594fSAndroid Build Coastguard Worker src->GetWithoutChecks(src_pos + i);
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker }
192*795d594fSAndroid Build Coastguard Worker // Perform the memmove using int memcpy then perform the write barrier.
193*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
194*795d594fSAndroid Build Coastguard Worker "art::mirror::HeapReference<T> and uint32_t have different sizes.");
195*795d594fSAndroid Build Coastguard Worker // TODO: Optimize this later?
196*795d594fSAndroid Build Coastguard Worker // We can't use memmove since it does not handle read barriers and may do by per byte copying.
197*795d594fSAndroid Build Coastguard Worker // See b/32012820.
198*795d594fSAndroid Build Coastguard Worker bool baker_non_gray_case = false;
199*795d594fSAndroid Build Coastguard Worker if (gUseReadBarrier && kUseBakerReadBarrier) {
200*795d594fSAndroid Build Coastguard Worker uintptr_t fake_address_dependency;
201*795d594fSAndroid Build Coastguard Worker if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
202*795d594fSAndroid Build Coastguard Worker baker_non_gray_case = true;
203*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(fake_address_dependency, 0U);
204*795d594fSAndroid Build Coastguard Worker src.Assign(reinterpret_cast<ObjectArray<T>*>(
205*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
206*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
207*795d594fSAndroid Build Coastguard Worker // We can skip the RB here because 'src' isn't gray.
208*795d594fSAndroid Build Coastguard Worker ObjPtr<Object> obj =
209*795d594fSAndroid Build Coastguard Worker src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(src_pos + i);
210*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker if (!baker_non_gray_case) {
215*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
216*795d594fSAndroid Build Coastguard Worker // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
217*795d594fSAndroid Build Coastguard Worker ObjPtr<T> obj = src->GetWithoutChecks(src_pos + i);
218*795d594fSAndroid Build Coastguard Worker SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
219*795d594fSAndroid Build Coastguard Worker }
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker WriteBarrier::ForArrayWrite(this, dst_pos, count);
222*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
223*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < count; ++i) {
224*795d594fSAndroid Build Coastguard Worker // The get will perform the VerifyObject.
225*795d594fSAndroid Build Coastguard Worker GetWithoutChecks(dst_pos + i);
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker }
229*795d594fSAndroid Build Coastguard Worker
230*795d594fSAndroid Build Coastguard Worker template<class T>
231*795d594fSAndroid Build Coastguard Worker template<bool kTransactionActive>
AssignableCheckingMemcpy(int32_t dst_pos,ObjPtr<ObjectArray<T>> src,int32_t src_pos,int32_t count,bool throw_exception)232*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
233*795d594fSAndroid Build Coastguard Worker ObjPtr<ObjectArray<T>> src,
234*795d594fSAndroid Build Coastguard Worker int32_t src_pos,
235*795d594fSAndroid Build Coastguard Worker int32_t count,
236*795d594fSAndroid Build Coastguard Worker bool throw_exception) {
237*795d594fSAndroid Build Coastguard Worker DCHECK_NE(this, src)
238*795d594fSAndroid Build Coastguard Worker << "This case should be handled with memmove that handles overlaps correctly";
239*795d594fSAndroid Build Coastguard Worker // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
240*795d594fSAndroid Build Coastguard Worker // we know is assignable to the destination array's component type.
241*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> dst_class = GetClass()->GetComponentType();
242*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> lastAssignableElementClass = dst_class;
243*795d594fSAndroid Build Coastguard Worker
244*795d594fSAndroid Build Coastguard Worker ObjPtr<T> o = nullptr;
245*795d594fSAndroid Build Coastguard Worker int i = 0;
246*795d594fSAndroid Build Coastguard Worker bool baker_non_gray_case = false;
247*795d594fSAndroid Build Coastguard Worker if (gUseReadBarrier && kUseBakerReadBarrier) {
248*795d594fSAndroid Build Coastguard Worker uintptr_t fake_address_dependency;
249*795d594fSAndroid Build Coastguard Worker if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
250*795d594fSAndroid Build Coastguard Worker baker_non_gray_case = true;
251*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(fake_address_dependency, 0U);
252*795d594fSAndroid Build Coastguard Worker src.Assign(reinterpret_cast<ObjectArray<T>*>(
253*795d594fSAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
254*795d594fSAndroid Build Coastguard Worker for (; i < count; ++i) {
255*795d594fSAndroid Build Coastguard Worker // The follow get operations force the objects to be verified.
256*795d594fSAndroid Build Coastguard Worker // We can skip the RB here because 'src' isn't gray.
257*795d594fSAndroid Build Coastguard Worker o = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
258*795d594fSAndroid Build Coastguard Worker src_pos + i);
259*795d594fSAndroid Build Coastguard Worker if (o == nullptr) {
260*795d594fSAndroid Build Coastguard Worker // Null is always assignable.
261*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
262*795d594fSAndroid Build Coastguard Worker } else {
263*795d594fSAndroid Build Coastguard Worker // TODO: use the underlying class reference to avoid uncompression when not necessary.
264*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> o_class = o->GetClass();
265*795d594fSAndroid Build Coastguard Worker if (LIKELY(lastAssignableElementClass == o_class)) {
266*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
267*795d594fSAndroid Build Coastguard Worker } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
268*795d594fSAndroid Build Coastguard Worker lastAssignableElementClass = o_class;
269*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
270*795d594fSAndroid Build Coastguard Worker } else {
271*795d594fSAndroid Build Coastguard Worker // Can't put this element into the array, break to perform write-barrier and throw
272*795d594fSAndroid Build Coastguard Worker // exception.
273*795d594fSAndroid Build Coastguard Worker break;
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker }
276*795d594fSAndroid Build Coastguard Worker }
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker if (!baker_non_gray_case) {
280*795d594fSAndroid Build Coastguard Worker for (; i < count; ++i) {
281*795d594fSAndroid Build Coastguard Worker // The follow get operations force the objects to be verified.
282*795d594fSAndroid Build Coastguard Worker // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
283*795d594fSAndroid Build Coastguard Worker o = src->GetWithoutChecks(src_pos + i);
284*795d594fSAndroid Build Coastguard Worker if (o == nullptr) {
285*795d594fSAndroid Build Coastguard Worker // Null is always assignable.
286*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
287*795d594fSAndroid Build Coastguard Worker } else {
288*795d594fSAndroid Build Coastguard Worker // TODO: use the underlying class reference to avoid uncompression when not necessary.
289*795d594fSAndroid Build Coastguard Worker ObjPtr<Class> o_class = o->GetClass();
290*795d594fSAndroid Build Coastguard Worker if (LIKELY(lastAssignableElementClass == o_class)) {
291*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
292*795d594fSAndroid Build Coastguard Worker } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
293*795d594fSAndroid Build Coastguard Worker lastAssignableElementClass = o_class;
294*795d594fSAndroid Build Coastguard Worker SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
295*795d594fSAndroid Build Coastguard Worker } else {
296*795d594fSAndroid Build Coastguard Worker // Can't put this element into the array, break to perform write-barrier and throw
297*795d594fSAndroid Build Coastguard Worker // exception.
298*795d594fSAndroid Build Coastguard Worker break;
299*795d594fSAndroid Build Coastguard Worker }
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker }
302*795d594fSAndroid Build Coastguard Worker }
303*795d594fSAndroid Build Coastguard Worker WriteBarrier::ForArrayWrite(this, dst_pos, count);
304*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(i != count)) {
305*795d594fSAndroid Build Coastguard Worker std::string actualSrcType(mirror::Object::PrettyTypeOf(o));
306*795d594fSAndroid Build Coastguard Worker std::string dstType(PrettyTypeOf());
307*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
308*795d594fSAndroid Build Coastguard Worker std::string msg = android::base::StringPrintf(
309*795d594fSAndroid Build Coastguard Worker "source[%d] of type %s cannot be stored in destination array of type %s",
310*795d594fSAndroid Build Coastguard Worker src_pos + i,
311*795d594fSAndroid Build Coastguard Worker actualSrcType.c_str(),
312*795d594fSAndroid Build Coastguard Worker dstType.c_str());
313*795d594fSAndroid Build Coastguard Worker if (throw_exception) {
314*795d594fSAndroid Build Coastguard Worker self->ThrowNewException("Ljava/lang/ArrayStoreException;", msg.c_str());
315*795d594fSAndroid Build Coastguard Worker } else {
316*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << msg;
317*795d594fSAndroid Build Coastguard Worker }
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker }
320*795d594fSAndroid Build Coastguard Worker
321*795d594fSAndroid Build Coastguard Worker template<class T>
OffsetOfElement(int32_t i)322*795d594fSAndroid Build Coastguard Worker inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
323*795d594fSAndroid Build Coastguard Worker return MemberOffset(DataOffset(kHeapReferenceSize).Int32Value() + (i * kHeapReferenceSize));
324*795d594fSAndroid Build Coastguard Worker }
325*795d594fSAndroid Build Coastguard Worker
326*795d594fSAndroid Build Coastguard Worker template<class T> template<typename Visitor>
VisitReferences(const Visitor & visitor)327*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
328*795d594fSAndroid Build Coastguard Worker const size_t length = static_cast<size_t>(GetLength());
329*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < length; ++i) {
330*795d594fSAndroid Build Coastguard Worker visitor(this, OffsetOfElement(i), /* is_static= */ false);
331*795d594fSAndroid Build Coastguard Worker }
332*795d594fSAndroid Build Coastguard Worker }
333*795d594fSAndroid Build Coastguard Worker
334*795d594fSAndroid Build Coastguard Worker template<class T> template<typename Visitor>
VisitReferences(const Visitor & visitor,MemberOffset begin,MemberOffset end)335*795d594fSAndroid Build Coastguard Worker inline void ObjectArray<T>::VisitReferences(const Visitor& visitor,
336*795d594fSAndroid Build Coastguard Worker MemberOffset begin,
337*795d594fSAndroid Build Coastguard Worker MemberOffset end) {
338*795d594fSAndroid Build Coastguard Worker const size_t length = static_cast<size_t>(GetLength());
339*795d594fSAndroid Build Coastguard Worker begin = std::max(begin, OffsetOfElement(0));
340*795d594fSAndroid Build Coastguard Worker end = std::min(end, OffsetOfElement(length));
341*795d594fSAndroid Build Coastguard Worker while (begin < end) {
342*795d594fSAndroid Build Coastguard Worker visitor(this, begin, /* is_static= */ false, /*is_obj_array*/ true);
343*795d594fSAndroid Build Coastguard Worker begin += kHeapReferenceSize;
344*795d594fSAndroid Build Coastguard Worker }
345*795d594fSAndroid Build Coastguard Worker }
346*795d594fSAndroid Build Coastguard Worker
347*795d594fSAndroid Build Coastguard Worker template <class T>
cbegin()348*795d594fSAndroid Build Coastguard Worker inline ConstObjPtrArrayIter<T> ObjectArray<T>::cbegin() const {
349*795d594fSAndroid Build Coastguard Worker return ConstObjPtrArrayIter<T>(this, 0);
350*795d594fSAndroid Build Coastguard Worker }
351*795d594fSAndroid Build Coastguard Worker template <class T>
cend()352*795d594fSAndroid Build Coastguard Worker inline ConstObjPtrArrayIter<T> ObjectArray<T>::cend() const {
353*795d594fSAndroid Build Coastguard Worker return ConstObjPtrArrayIter<T>(this, GetLength());
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker template <class T>
cbegin(const Handle<ObjectArray<T>> & h_this)356*795d594fSAndroid Build Coastguard Worker inline ConstHandleArrayIter<T> ObjectArray<T>::cbegin(const Handle<ObjectArray<T>>& h_this) {
357*795d594fSAndroid Build Coastguard Worker return ConstHandleArrayIter<T>(h_this, 0);
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker template <class T>
cend(const Handle<ObjectArray<T>> & h_this)360*795d594fSAndroid Build Coastguard Worker inline ConstHandleArrayIter<T> ObjectArray<T>::cend(const Handle<ObjectArray<T>>& h_this) {
361*795d594fSAndroid Build Coastguard Worker return ConstHandleArrayIter<T>(h_this, h_this->GetLength());
362*795d594fSAndroid Build Coastguard Worker }
363*795d594fSAndroid Build Coastguard Worker
364*795d594fSAndroid Build Coastguard Worker template <class T>
begin()365*795d594fSAndroid Build Coastguard Worker inline ObjPtrArrayIter<T> ObjectArray<T>::begin() {
366*795d594fSAndroid Build Coastguard Worker return ObjPtrArrayIter<T>(this, 0);
367*795d594fSAndroid Build Coastguard Worker }
368*795d594fSAndroid Build Coastguard Worker template <class T>
end()369*795d594fSAndroid Build Coastguard Worker inline ObjPtrArrayIter<T> ObjectArray<T>::end() {
370*795d594fSAndroid Build Coastguard Worker return ObjPtrArrayIter<T>(this, GetLength());
371*795d594fSAndroid Build Coastguard Worker }
372*795d594fSAndroid Build Coastguard Worker template <class T>
begin(Handle<ObjectArray<T>> & h_this)373*795d594fSAndroid Build Coastguard Worker inline HandleArrayIter<T> ObjectArray<T>::begin(Handle<ObjectArray<T>>& h_this) {
374*795d594fSAndroid Build Coastguard Worker return HandleArrayIter<T>(h_this, 0);
375*795d594fSAndroid Build Coastguard Worker }
376*795d594fSAndroid Build Coastguard Worker template <class T>
end(Handle<ObjectArray<T>> & h_this)377*795d594fSAndroid Build Coastguard Worker inline HandleArrayIter<T> ObjectArray<T>::end(Handle<ObjectArray<T>>& h_this) {
378*795d594fSAndroid Build Coastguard Worker return HandleArrayIter<T>(h_this, h_this->GetLength());
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker
381*795d594fSAndroid Build Coastguard Worker template<typename T, typename C>
CheckIdx()382*795d594fSAndroid Build Coastguard Worker inline void ArrayIter<T, C>::CheckIdx() const {
383*795d594fSAndroid Build Coastguard Worker if (kIsDebugBuild) {
384*795d594fSAndroid Build Coastguard Worker Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
385*795d594fSAndroid Build Coastguard Worker }
386*795d594fSAndroid Build Coastguard Worker DCHECK_LE(0, idx_);
387*795d594fSAndroid Build Coastguard Worker DCHECK_LE(idx_, array_->GetLength());
388*795d594fSAndroid Build Coastguard Worker }
389*795d594fSAndroid Build Coastguard Worker
390*795d594fSAndroid Build Coastguard Worker } // namespace mirror
391*795d594fSAndroid Build Coastguard Worker } // namespace art
392*795d594fSAndroid Build Coastguard Worker
393*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
394