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_ARRAY_H_ 18 #define ART_RUNTIME_MIRROR_ARRAY_H_ 19 20 #include "base/enums.h" 21 #include "gc/allocator_type.h" 22 #include "gc_root.h" 23 #include "obj_ptr.h" 24 #include "object.h" 25 26 namespace art { 27 28 template<class T> class Handle; 29 30 namespace mirror { 31 32 class MANAGED Array : public Object { 33 public: 34 // The size of a java.lang.Class representing an array. 35 static uint32_t ClassSize(PointerSize pointer_size); 36 37 // Allocates an array with the given properties, if kFillUsable is true the array will be of at 38 // least component_count size, however, if there's usable space at the end of the allocation the 39 // array will fill it. 40 template <bool kIsInstrumented, bool kFillUsable = false> 41 ALWAYS_INLINE static Array* Alloc(Thread* self, 42 ObjPtr<Class> array_class, 43 int32_t component_count, 44 size_t component_size_shift, 45 gc::AllocatorType allocator_type) 46 REQUIRES_SHARED(Locks::mutator_lock_) 47 REQUIRES(!Roles::uninterruptible_); 48 49 static Array* CreateMultiArray(Thread* self, 50 Handle<Class> element_class, 51 Handle<IntArray> dimensions) 52 REQUIRES_SHARED(Locks::mutator_lock_) 53 REQUIRES(!Roles::uninterruptible_); 54 55 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, 56 ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 57 size_t SizeOf() REQUIRES_SHARED(Locks::mutator_lock_); 58 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> GetLength()59 ALWAYS_INLINE int32_t GetLength() REQUIRES_SHARED(Locks::mutator_lock_) { 60 return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Array, length_)); 61 } 62 SetLength(int32_t length)63 void SetLength(int32_t length) REQUIRES_SHARED(Locks::mutator_lock_) { 64 DCHECK_GE(length, 0); 65 // We use non transactional version since we can't undo this write. We also disable checking 66 // since it would fail during a transaction. 67 SetField32<false, false, kVerifyNone>(OFFSET_OF_OBJECT_MEMBER(Array, length_), length); 68 } 69 LengthOffset()70 static MemberOffset LengthOffset() { 71 return OFFSET_OF_OBJECT_MEMBER(Array, length_); 72 } 73 74 static MemberOffset DataOffset(size_t component_size); 75 GetRawData(size_t component_size,int32_t index)76 void* GetRawData(size_t component_size, int32_t index) 77 REQUIRES_SHARED(Locks::mutator_lock_) { 78 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() + 79 + (index * component_size); 80 return reinterpret_cast<void*>(data); 81 } 82 GetRawData(size_t component_size,int32_t index)83 const void* GetRawData(size_t component_size, int32_t index) const { 84 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value() + 85 + (index * component_size); 86 return reinterpret_cast<void*>(data); 87 } 88 89 // Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and 90 // returns false. 91 template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> 92 ALWAYS_INLINE bool CheckIsValidIndex(int32_t index) REQUIRES_SHARED(Locks::mutator_lock_); 93 94 Array* CopyOf(Thread* self, int32_t new_length) REQUIRES_SHARED(Locks::mutator_lock_) 95 REQUIRES(!Roles::uninterruptible_); 96 97 protected: 98 void ThrowArrayStoreException(ObjPtr<Object> object) REQUIRES_SHARED(Locks::mutator_lock_) 99 REQUIRES(!Roles::uninterruptible_); 100 101 private: 102 void ThrowArrayIndexOutOfBoundsException(int32_t index) 103 REQUIRES_SHARED(Locks::mutator_lock_); 104 105 // The number of array elements. 106 int32_t length_; 107 // Marker for the data (used by generated code) 108 uint32_t first_element_[0]; 109 110 DISALLOW_IMPLICIT_CONSTRUCTORS(Array); 111 }; 112 113 template<typename T> 114 class MANAGED PrimitiveArray : public Array { 115 public: 116 typedef T ElementType; 117 118 static PrimitiveArray<T>* Alloc(Thread* self, size_t length) 119 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); 120 121 static PrimitiveArray<T>* AllocateAndFill(Thread* self, const T* data, size_t length) 122 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); 123 124 GetData()125 const T* GetData() const ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { 126 return reinterpret_cast<const T*>(GetRawData(sizeof(T), 0)); 127 } 128 GetData()129 T* GetData() ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { 130 return reinterpret_cast<T*>(GetRawData(sizeof(T), 0)); 131 } 132 133 T Get(int32_t i) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_); 134 GetWithoutChecks(int32_t i)135 T GetWithoutChecks(int32_t i) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_) { 136 DCHECK(CheckIsValidIndex(i)) << "i=" << i << " length=" << GetLength(); 137 return GetData()[i]; 138 } 139 140 void Set(int32_t i, T value) ALWAYS_INLINE REQUIRES_SHARED(Locks::mutator_lock_); 141 142 // TODO fix thread safety analysis broken by the use of template. This should be 143 // REQUIRES_SHARED(Locks::mutator_lock_). 144 template<bool kTransactionActive, bool kCheckTransaction = true> 145 void Set(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS; 146 147 // TODO fix thread safety analysis broken by the use of template. This should be 148 // REQUIRES_SHARED(Locks::mutator_lock_). 149 template<bool kTransactionActive, 150 bool kCheckTransaction = true, 151 VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> 152 void SetWithoutChecks(int32_t i, T value) ALWAYS_INLINE NO_THREAD_SAFETY_ANALYSIS; 153 154 /* 155 * Works like memmove(), except we guarantee not to allow tearing of array values (ie using 156 * smaller than element size copies). Arguments are assumed to be within the bounds of the array 157 * and the arrays non-null. 158 */ 159 void Memmove(int32_t dst_pos, ObjPtr<PrimitiveArray<T>> src, int32_t src_pos, int32_t count) 160 REQUIRES_SHARED(Locks::mutator_lock_); 161 162 /* 163 * Works like memcpy(), except we guarantee not to allow tearing of array values (ie using 164 * smaller than element size copies). Arguments are assumed to be within the bounds of the array 165 * and the arrays non-null. 166 */ 167 void Memcpy(int32_t dst_pos, ObjPtr<PrimitiveArray<T>> src, int32_t src_pos, int32_t count) 168 REQUIRES_SHARED(Locks::mutator_lock_); 169 170 static void SetArrayClass(ObjPtr<Class> array_class); 171 172 template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier> GetArrayClass()173 static Class* GetArrayClass() REQUIRES_SHARED(Locks::mutator_lock_) { 174 DCHECK(!array_class_.IsNull()); 175 return array_class_.Read<kReadBarrierOption>(); 176 } 177 ResetArrayClass()178 static void ResetArrayClass() { 179 CHECK(!array_class_.IsNull()); 180 array_class_ = GcRoot<Class>(nullptr); 181 } 182 183 static void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 184 185 private: 186 static GcRoot<Class> array_class_; 187 188 DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray); 189 }; 190 191 // Declare the different primitive arrays. Instantiations will be in array.cc. 192 extern template class PrimitiveArray<uint8_t>; // BooleanArray 193 extern template class PrimitiveArray<int8_t>; // ByteArray 194 extern template class PrimitiveArray<uint16_t>; // CharArray 195 extern template class PrimitiveArray<double>; // DoubleArray 196 extern template class PrimitiveArray<float>; // FloatArray 197 extern template class PrimitiveArray<int32_t>; // IntArray 198 extern template class PrimitiveArray<int64_t>; // LongArray 199 extern template class PrimitiveArray<int16_t>; // ShortArray 200 201 // Either an IntArray or a LongArray. 202 class PointerArray : public Array { 203 public: 204 template<typename T, 205 VerifyObjectFlags kVerifyFlags = kVerifyNone, 206 ReadBarrierOption kReadBarrierOption = kWithReadBarrier> 207 T GetElementPtrSize(uint32_t idx, PointerSize ptr_size) 208 REQUIRES_SHARED(Locks::mutator_lock_); 209 ElementAddress(size_t index,PointerSize ptr_size)210 void** ElementAddress(size_t index, PointerSize ptr_size) REQUIRES_SHARED(Locks::mutator_lock_) { 211 DCHECK_LT(index, static_cast<size_t>(GetLength())); 212 return reinterpret_cast<void**>(reinterpret_cast<uint8_t*>(this) + 213 Array::DataOffset(static_cast<size_t>(ptr_size)).Uint32Value() + 214 static_cast<size_t>(ptr_size) * index); 215 } 216 217 template<bool kTransactionActive = false, bool kUnchecked = false> 218 void SetElementPtrSize(uint32_t idx, uint64_t element, PointerSize ptr_size) 219 REQUIRES_SHARED(Locks::mutator_lock_); 220 template<bool kTransactionActive = false, bool kUnchecked = false, typename T> 221 void SetElementPtrSize(uint32_t idx, T* element, PointerSize ptr_size) 222 REQUIRES_SHARED(Locks::mutator_lock_); 223 224 // Fixup the pointers in the dest arrays by passing our pointers through the visitor. Only copies 225 // to dest if visitor(source_ptr) != source_ptr. 226 template <VerifyObjectFlags kVerifyFlags = kVerifyNone, 227 ReadBarrierOption kReadBarrierOption = kWithReadBarrier, 228 typename Visitor> 229 void Fixup(mirror::PointerArray* dest, PointerSize pointer_size, const Visitor& visitor) 230 REQUIRES_SHARED(Locks::mutator_lock_); 231 232 // Works like memcpy(), except we guarantee not to allow tearing of array values (ie using smaller 233 // than element size copies). Arguments are assumed to be within the bounds of the array and the 234 // arrays non-null. Cannot be called in an active transaction. 235 template<bool kUnchecked = false> 236 void Memcpy(int32_t dst_pos, 237 ObjPtr<PointerArray> src, 238 int32_t src_pos, 239 int32_t count, 240 PointerSize pointer_size) 241 REQUIRES_SHARED(Locks::mutator_lock_); 242 }; 243 244 } // namespace mirror 245 } // namespace art 246 247 #endif // ART_RUNTIME_MIRROR_ARRAY_H_ 248