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