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