1 /* 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 17 #ifndef ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_ 18 #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_ 19 20 #include "object_array.h" 21 22 #include "gc/heap.h" 23 #include "mirror/art_field.h" 24 #include "mirror/class.h" 25 #include "runtime.h" 26 #include "thread.h" 27 28 namespace art { 29 namespace mirror { 30 31 template<class T> 32 inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) { 33 Array* array = Array::Alloc(self, object_array_class, length, sizeof(Object*)); 34 if (UNLIKELY(array == NULL)) { 35 return NULL; 36 } else { 37 return array->AsObjectArray<T>(); 38 } 39 } 40 41 template<class T> 42 inline T* ObjectArray<T>::Get(int32_t i) const { 43 if (UNLIKELY(!IsValidIndex(i))) { 44 return NULL; 45 } 46 MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); 47 return GetFieldObject<T*>(data_offset, false); 48 } 49 50 template<class T> 51 inline bool ObjectArray<T>::CheckAssignable(T* object) { 52 if (object != NULL) { 53 Class* element_class = GetClass()->GetComponentType(); 54 if (UNLIKELY(!object->InstanceOf(element_class))) { 55 ThrowArrayStoreException(object); 56 return false; 57 } 58 } 59 return true; 60 } 61 62 template<class T> 63 inline void ObjectArray<T>::Set(int32_t i, T* object) { 64 if (LIKELY(IsValidIndex(i) && CheckAssignable(object))) { 65 MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); 66 SetFieldObject(data_offset, object, false); 67 } else { 68 DCHECK(Thread::Current()->IsExceptionPending()); 69 } 70 } 71 72 template<class T> 73 inline void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) { 74 DCHECK(IsValidIndex(i)); 75 MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); 76 SetFieldObject(data_offset, object, false); 77 } 78 79 template<class T> 80 inline void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) { 81 DCHECK(IsValidIndex(i)); 82 MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); 83 SetFieldPtr(data_offset, object, false); 84 } 85 86 template<class T> 87 inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) const { 88 DCHECK(IsValidIndex(i)); 89 MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*)); 90 return GetFieldObject<T*>(data_offset, false); 91 } 92 93 template<class T> 94 inline void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos, 95 ObjectArray<T>* dst, int dst_pos, 96 size_t length) { 97 if (src->IsValidIndex(src_pos) && 98 src->IsValidIndex(src_pos+length-1) && 99 dst->IsValidIndex(dst_pos) && 100 dst->IsValidIndex(dst_pos+length-1)) { 101 MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*)); 102 MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*)); 103 Class* array_class = dst->GetClass(); 104 gc::Heap* heap = Runtime::Current()->GetHeap(); 105 if (array_class == src->GetClass()) { 106 // No need for array store checks if arrays are of the same type 107 for (size_t i = 0; i < length; i++) { 108 Object* object = src->GetFieldObject<Object*>(src_offset, false); 109 heap->VerifyObject(object); 110 // directly set field, we do a bulk write barrier at the end 111 dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); 112 src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); 113 dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); 114 } 115 } else { 116 Class* element_class = array_class->GetComponentType(); 117 CHECK(!element_class->IsPrimitive()); 118 for (size_t i = 0; i < length; i++) { 119 Object* object = src->GetFieldObject<Object*>(src_offset, false); 120 if (object != NULL && !object->InstanceOf(element_class)) { 121 dst->ThrowArrayStoreException(object); 122 return; 123 } 124 heap->VerifyObject(object); 125 // directly set field, we do a bulk write barrier at the end 126 dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true); 127 src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*)); 128 dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*)); 129 } 130 } 131 heap->WriteBarrierArray(dst, dst_pos, length); 132 } 133 } 134 135 template<class T> 136 inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) { 137 ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length); 138 if (LIKELY(new_array != NULL)) { 139 Copy(this, 0, new_array, 0, std::min(GetLength(), new_length)); 140 } 141 return new_array; 142 } 143 144 } // namespace mirror 145 } // namespace art 146 147 #endif // ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_ 148