blob: 9b6e90159bc2a193b8252e34476117ac601d8aa0 [file] [log] [blame]
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
18#define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
20#include "object_array.h"
21
Ian Rogers1d54e732013-05-02 21:10:01 -070022#include "gc/heap.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070023#include "mirror/art_field.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "mirror/class.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080025#include "runtime.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070026#include "handle_scope-inl.h"
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +020027#include "thread.h"
Ian Rogersef7d42f2014-01-06 12:55:46 -080028#include <string>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029
30namespace art {
31namespace mirror {
32
33template<class T>
Mathieu Chartiercbb2d202013-11-14 17:45:16 -080034inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
35 int32_t length, gc::AllocatorType allocator_type) {
Ian Rogersef7d42f2014-01-06 12:55:46 -080036 Array* array = Array::Alloc<true>(self, object_array_class, length,
37 sizeof(HeapReference<Object>), allocator_type);
Mathieu Chartiercbb2d202013-11-14 17:45:16 -080038 if (UNLIKELY(array == nullptr)) {
39 return nullptr;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080040 } else {
41 return array->AsObjectArray<T>();
42 }
43}
44
45template<class T>
Mathieu Chartiercbb2d202013-11-14 17:45:16 -080046inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class,
47 int32_t length) {
48 return Alloc(self, object_array_class, length,
49 Runtime::Current()->GetHeap()->GetCurrentAllocator());
50}
51
52template<class T>
Ian Rogersef7d42f2014-01-06 12:55:46 -080053inline T* ObjectArray<T>::Get(int32_t i) {
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070054 if (!CheckIsValidIndex(i)) {
Sebastien Hertzabff6432014-01-27 18:01:39 +010055 DCHECK(Thread::Current()->IsExceptionPending());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080056 return NULL;
57 }
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070058 return GetFieldObject<T>(OffsetOfElement(i));
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080059}
60
Mathieu Chartier4e305412014-02-19 10:54:44 -080061template<class T> template<VerifyObjectFlags kVerifyFlags>
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +020062inline bool ObjectArray<T>::CheckAssignable(T* object) {
63 if (object != NULL) {
Mathieu Chartier4e305412014-02-19 10:54:44 -080064 Class* element_class = GetClass<kVerifyFlags>()->GetComponentType();
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +020065 if (UNLIKELY(!object->InstanceOf(element_class))) {
66 ThrowArrayStoreException(object);
67 return false;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080068 }
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +020069 }
70 return true;
71}
72
73template<class T>
74inline void ObjectArray<T>::Set(int32_t i, T* object) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010075 if (Runtime::Current()->IsActiveTransaction()) {
76 Set<true>(i, object);
77 } else {
78 Set<false>(i, object);
79 }
80}
81
82template<class T>
Mathieu Chartier4e305412014-02-19 10:54:44 -080083template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010084inline void ObjectArray<T>::Set(int32_t i, T* object) {
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070085 if (CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object)) {
86 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
Sebastien Hertz6bdd8f42013-05-17 14:44:01 +020087 } else {
88 DCHECK(Thread::Current()->IsExceptionPending());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080089 }
90}
91
92template<class T>
Mathieu Chartier4e305412014-02-19 10:54:44 -080093template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080094inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
Mathieu Chartier4e305412014-02-19 10:54:44 -080095 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
96 DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -070097 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080098}
99
100template<class T>
Mathieu Chartier4e305412014-02-19 10:54:44 -0800101template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
Ian Rogersef7d42f2014-01-06 12:55:46 -0800102inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, T* object) {
Mathieu Chartier4e305412014-02-19 10:54:44 -0800103 DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
Ian Rogersef7d42f2014-01-06 12:55:46 -0800104 // TODO: enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
Sebastien Hertzabff6432014-01-27 18:01:39 +0100105 // DCHECK(CheckAssignable(object));
Mathieu Chartier4e305412014-02-19 10:54:44 -0800106 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700107 OffsetOfElement(i), object);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800108}
109
110template<class T>
Ian Rogersef7d42f2014-01-06 12:55:46 -0800111inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) {
Sebastien Hertzabff6432014-01-27 18:01:39 +0100112 DCHECK(CheckIsValidIndex(i));
Ian Rogersb0fa5dc2014-04-28 16:47:08 -0700113 return GetFieldObject<T>(OffsetOfElement(i));
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800114}
115
116template<class T>
Ian Rogersef7d42f2014-01-06 12:55:46 -0800117inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos, ObjectArray<T>* src,
118 int32_t src_pos, int32_t count) {
119 if (kIsDebugBuild) {
120 for (int i = 0; i < count; ++i) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700121 // The get will perform the VerifyObject.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800122 src->GetWithoutChecks(src_pos + i);
123 }
124 }
125 // Perform the memmove using int memmove then perform the write barrier.
126 CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
127 IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
128 IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
Hiroshi Yamauchi79719282014-04-10 12:46:22 -0700129 if (kUseBakerOrBrooksReadBarrier) {
130 // TODO: Optimize this later?
131 const bool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count);
132 if (copy_forward) {
133 // Forward copy.
134 for (int i = 0; i < count; ++i) {
135 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
136 Object* obj = src->GetWithoutChecks(src_pos + i);
137 SetWithoutChecks<false>(dst_pos + i, obj);
138 }
139 } else {
140 // Backward copy.
141 for (int i = count - 1; i >= 0; --i) {
142 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
143 Object* obj = src->GetWithoutChecks(src_pos + i);
144 SetWithoutChecks<false>(dst_pos + i, obj);
145 }
146 }
147 } else {
148 dstAsIntArray->Memmove(dst_pos, srcAsIntArray, src_pos, count);
149 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800150 Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
151 if (kIsDebugBuild) {
152 for (int i = 0; i < count; ++i) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700153 // The get will perform the VerifyObject.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800154 GetWithoutChecks(dst_pos + i);
155 }
156 }
157}
158
159template<class T>
160inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos, ObjectArray<T>* src,
161 int32_t src_pos, int32_t count) {
162 if (kIsDebugBuild) {
163 for (int i = 0; i < count; ++i) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700164 // The get will perform the VerifyObject.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800165 src->GetWithoutChecks(src_pos + i);
166 }
167 }
168 // Perform the memmove using int memcpy then perform the write barrier.
169 CHECK_EQ(sizeof(HeapReference<T>), sizeof(uint32_t));
170 IntArray* dstAsIntArray = reinterpret_cast<IntArray*>(this);
171 IntArray* srcAsIntArray = reinterpret_cast<IntArray*>(src);
Hiroshi Yamauchi79719282014-04-10 12:46:22 -0700172 if (kUseBakerOrBrooksReadBarrier) {
173 // TODO: Optimize this later?
174 for (int i = 0; i < count; ++i) {
175 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
176 T* obj = src->GetWithoutChecks(src_pos + i);
177 SetWithoutChecks<false>(dst_pos + i, obj);
178 }
179 } else {
180 dstAsIntArray->Memcpy(dst_pos, srcAsIntArray, src_pos, count);
181 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800182 Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
183 if (kIsDebugBuild) {
184 for (int i = 0; i < count; ++i) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700185 // The get will perform the VerifyObject.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800186 GetWithoutChecks(dst_pos + i);
187 }
188 }
189}
190
191template<class T>
192inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos, ObjectArray<T>* src,
193 int32_t src_pos, int32_t count,
194 bool throw_exception) {
195 DCHECK_NE(this, src)
196 << "This case should be handled with memmove that handles overlaps correctly";
197 // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
198 // we know is assignable to the destination array's component type.
199 Class* dst_class = GetClass()->GetComponentType();
200 Class* lastAssignableElementClass = dst_class;
201
202 Object* o = nullptr;
203 int i = 0;
204 for (; i < count; ++i) {
205 // The follow get operations force the objects to be verified.
Hiroshi Yamauchi79719282014-04-10 12:46:22 -0700206 // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800207 o = src->GetWithoutChecks(src_pos + i);
208 if (o == nullptr) {
209 // Null is always assignable.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100210 SetWithoutChecks<false>(dst_pos + i, nullptr);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800211 } else {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800212 // TODO: use the underlying class reference to avoid uncompression when not necessary.
213 Class* o_class = o->GetClass();
214 if (LIKELY(lastAssignableElementClass == o_class)) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100215 SetWithoutChecks<false>(dst_pos + i, o);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800216 } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
217 lastAssignableElementClass = o_class;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100218 SetWithoutChecks<false>(dst_pos + i, o);
Ian Rogersef7d42f2014-01-06 12:55:46 -0800219 } else {
220 // Can't put this element into the array, break to perform write-barrier and throw
221 // exception.
222 break;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800223 }
224 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800225 }
226 Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
227 if (UNLIKELY(i != count)) {
228 std::string actualSrcType(PrettyTypeOf(o));
229 std::string dstType(PrettyTypeOf(this));
230 Thread* self = Thread::Current();
231 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
232 if (throw_exception) {
233 self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
234 "source[%d] of type %s cannot be stored in destination array of type %s",
235 src_pos + i, actualSrcType.c_str(), dstType.c_str());
236 } else {
237 LOG(FATAL) << StringPrintf("source[%d] of type %s cannot be stored in destination array of type %s",
238 src_pos + i, actualSrcType.c_str(), dstType.c_str());
239 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800240 }
241}
242
243template<class T>
244inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800245 DCHECK_GE(new_length, 0);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700246 // We may get copied by a compacting GC.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700247 StackHandleScope<1> hs(self);
Ian Rogers700a4022014-05-19 16:49:03 -0700248 Handle<ObjectArray<T>> h_this(hs.NewHandle(this));
Mathieu Chartiercbb2d202013-11-14 17:45:16 -0800249 gc::Heap* heap = Runtime::Current()->GetHeap();
250 gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
251 heap->GetCurrentNonMovingAllocator();
252 ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
Mathieu Chartier590fee92013-09-13 13:46:47 -0700253 if (LIKELY(new_array != nullptr)) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700254 new_array->AssignableMemcpy(0, h_this.Get(), 0, std::min(h_this->GetLength(), new_length));
Ian Rogersa436fde2013-08-27 23:34:06 -0700255 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800256 return new_array;
257}
258
Ian Rogersef7d42f2014-01-06 12:55:46 -0800259template<class T>
260inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
261 return MemberOffset(DataOffset(sizeof(HeapReference<Object>)).Int32Value() +
262 (i * sizeof(HeapReference<Object>)));
263}
264
Mathieu Chartier407f7022014-02-18 14:37:05 -0800265template<class T> template<const bool kVisitClass, typename Visitor>
266void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
267 if (kVisitClass) {
268 visitor(this, ClassOffset(), false);
269 }
270 const size_t length = static_cast<size_t>(GetLength());
271 for (size_t i = 0; i < length; ++i) {
272 visitor(this, OffsetOfElement(i), false);
273 }
274}
275
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800276} // namespace mirror
277} // namespace art
278
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700279#endif // ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_