array.h revision abff6439db28fbbed95490bfff7e24d1fdf5b771
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 "object.h" 21#include "gc/heap.h" 22#include "thread.h" 23 24namespace art { 25namespace mirror { 26 27class MANAGED Array : public Object { 28 public: 29 // A convenience for code that doesn't know the component size, and doesn't want to have to work 30 // it out itself. 31 template <bool kIsInstrumented> 32 static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, 33 gc::AllocatorType allocator_type) 34 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 35 36 template <bool kIsInstrumented> 37 static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, 38 size_t component_size, gc::AllocatorType allocator_type) 39 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 40 41 template <bool kIsInstrumented> 42 static Array* Alloc(Thread* self, Class* array_class, int32_t component_count) 43 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 44 45 template <bool kIsInstrumented> 46 static Array* Alloc(Thread* self, Class* array_class, int32_t component_count, 47 size_t component_size) 48 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 49 50 static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions) 51 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 52 53 size_t SizeOf() const; 54 55 int32_t GetLength() const { 56 return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false); 57 } 58 59 void SetLength(int32_t length) { 60 CHECK_GE(length, 0); 61 SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false); 62 } 63 64 static MemberOffset LengthOffset() { 65 return OFFSET_OF_OBJECT_MEMBER(Array, length_); 66 } 67 68 static MemberOffset DataOffset(size_t component_size) { 69 if (component_size != sizeof(int64_t)) { 70 return OFFSET_OF_OBJECT_MEMBER(Array, first_element_); 71 } else { 72 // Align longs and doubles. 73 return MemberOffset(OFFSETOF_MEMBER(Array, first_element_) + 4); 74 } 75 } 76 77 void* GetRawData(size_t component_size) { 78 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); 79 return reinterpret_cast<void*>(data); 80 } 81 82 const void* GetRawData(size_t component_size) const { 83 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value(); 84 return reinterpret_cast<const void*>(data); 85 } 86 87 // Returns true if the index is valid. If not, throws an ArrayIndexOutOfBoundsException and 88 // returns false. 89 bool CheckIsValidIndex(int32_t index) const 90 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 91 if (UNLIKELY(static_cast<uint32_t>(index) >= static_cast<uint32_t>(GetLength()))) { 92 ThrowArrayIndexOutOfBoundsException(index); 93 return false; 94 } 95 return true; 96 } 97 98 protected: 99 void ThrowArrayStoreException(Object* object) const 100 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 101 102 private: 103 void ThrowArrayIndexOutOfBoundsException(int32_t index) const 104 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 105 106 // The number of array elements. 107 int32_t length_; 108 // Marker for the data (used by generated code) 109 uint32_t first_element_[0]; 110 111 DISALLOW_IMPLICIT_CONSTRUCTORS(Array); 112}; 113 114template<class T> 115class MANAGED PrimitiveArray : public Array { 116 public: 117 typedef T ElementType; 118 119 static PrimitiveArray<T>* Alloc(Thread* self, size_t length) 120 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 121 122 const T* GetData() const { 123 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); 124 return reinterpret_cast<T*>(data); 125 } 126 127 T* GetData() { 128 intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value(); 129 return reinterpret_cast<T*>(data); 130 } 131 132 T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 133 if (UNLIKELY(!CheckIsValidIndex(i))) { 134 DCHECK(Thread::Current()->IsExceptionPending()); 135 return T(0); 136 } 137 return GetWithoutChecks(i); 138 } 139 140 T GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 141 DCHECK(CheckIsValidIndex(i)); 142 return GetData()[i]; 143 } 144 145 void Set(int32_t i, T value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 146 if (LIKELY(CheckIsValidIndex(i))) { 147 SetWithoutChecks(i, value); 148 } else { 149 DCHECK(Thread::Current()->IsExceptionPending()); 150 } 151 } 152 153 void SetWithoutChecks(int32_t i, T value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 154 DCHECK(CheckIsValidIndex(i)); 155 GetData()[i] = value; 156 } 157 158 static void SetArrayClass(Class* array_class) { 159 CHECK(array_class_ == NULL); 160 CHECK(array_class != NULL); 161 array_class_ = array_class; 162 } 163 164 static void ResetArrayClass() { 165 CHECK(array_class_ != NULL); 166 array_class_ = NULL; 167 } 168 169 static void VisitRoots(RootVisitor* visitor, void* arg) 170 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); 171 172 private: 173 static Class* array_class_; 174 175 DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray); 176}; 177 178} // namespace mirror 179} // namespace art 180 181#endif // ART_RUNTIME_MIRROR_ARRAY_H_ 182