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