Home | History | Annotate | Download | only in mirror
      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_INL_H_
     18 #define ART_RUNTIME_MIRROR_ARRAY_INL_H_
     19 
     20 #include "array.h"
     21 
     22 #include "class.h"
     23 #include "gc/heap-inl.h"
     24 #include "thread.h"
     25 #include "utils.h"
     26 
     27 namespace art {
     28 namespace mirror {
     29 
     30 inline uint32_t Array::ClassSize() {
     31   uint32_t vtable_entries = Object::kVTableLength;
     32   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0);
     33 }
     34 
     35 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
     36 inline size_t Array::SizeOf() {
     37   // This is safe from overflow because the array was already allocated, so we know it's sane.
     38   size_t component_size =
     39       GetClass<kVerifyFlags, kReadBarrierOption>()->template GetComponentSize<kReadBarrierOption>();
     40   // Don't need to check this since we already check this in GetClass.
     41   int32_t component_count =
     42       GetLength<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>();
     43   size_t header_size = DataOffset(component_size).SizeValue();
     44   size_t data_size = component_count * component_size;
     45   return header_size + data_size;
     46 }
     47 
     48 template<VerifyObjectFlags kVerifyFlags>
     49 inline bool Array::CheckIsValidIndex(int32_t index) {
     50   if (UNLIKELY(static_cast<uint32_t>(index) >=
     51                static_cast<uint32_t>(GetLength<kVerifyFlags>()))) {
     52     ThrowArrayIndexOutOfBoundsException(index);
     53     return false;
     54   }
     55   return true;
     56 }
     57 
     58 static inline size_t ComputeArraySize(Thread* self, Class* array_class, int32_t component_count,
     59                                       size_t component_size)
     60     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     61   DCHECK(array_class != NULL);
     62   DCHECK_GE(component_count, 0);
     63   DCHECK(array_class->IsArrayClass());
     64 
     65   size_t header_size = Array::DataOffset(component_size).SizeValue();
     66   size_t data_size = component_count * component_size;
     67   size_t size = header_size + data_size;
     68 
     69   // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
     70   size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size);
     71   if (UNLIKELY(data_size >> component_shift != size_t(component_count) || size < data_size)) {
     72     self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
     73                                              PrettyDescriptor(array_class).c_str(),
     74                                              component_count).c_str());
     75     return 0;  // failure
     76   }
     77   return size;
     78 }
     79 
     80 // Used for setting the array length in the allocation code path to ensure it is guarded by a
     81 // StoreStore fence.
     82 class SetLengthVisitor {
     83  public:
     84   explicit SetLengthVisitor(int32_t length) : length_(length) {
     85   }
     86 
     87   void operator()(Object* obj, size_t usable_size) const
     88       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     89     UNUSED(usable_size);
     90     // Avoid AsArray as object is not yet in live bitmap or allocation stack.
     91     Array* array = down_cast<Array*>(obj);
     92     // DCHECK(array->IsArrayInstance());
     93     array->SetLength(length_);
     94   }
     95 
     96  private:
     97   const int32_t length_;
     98 
     99   DISALLOW_COPY_AND_ASSIGN(SetLengthVisitor);
    100 };
    101 
    102 // Similar to SetLengthVisitor, used for setting the array length to fill the usable size of an
    103 // array.
    104 class SetLengthToUsableSizeVisitor {
    105  public:
    106   SetLengthToUsableSizeVisitor(int32_t min_length, size_t header_size, size_t component_size) :
    107       minimum_length_(min_length), header_size_(header_size), component_size_(component_size) {
    108   }
    109 
    110   void operator()(Object* obj, size_t usable_size) const
    111       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
    112     // Avoid AsArray as object is not yet in live bitmap or allocation stack.
    113     Array* array = down_cast<Array*>(obj);
    114     // DCHECK(array->IsArrayInstance());
    115     int32_t length = (usable_size - header_size_) / component_size_;
    116     DCHECK_GE(length, minimum_length_);
    117     byte* old_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, minimum_length_));
    118     byte* new_end = reinterpret_cast<byte*>(array->GetRawData(component_size_, length));
    119     // Ensure space beyond original allocation is zeroed.
    120     memset(old_end, 0, new_end - old_end);
    121     array->SetLength(length);
    122   }
    123 
    124  private:
    125   const int32_t minimum_length_;
    126   const size_t header_size_;
    127   const size_t component_size_;
    128 
    129   DISALLOW_COPY_AND_ASSIGN(SetLengthToUsableSizeVisitor);
    130 };
    131 
    132 template <bool kIsInstrumented>
    133 inline Array* Array::Alloc(Thread* self, Class* array_class, int32_t component_count,
    134                            size_t component_size, gc::AllocatorType allocator_type,
    135                            bool fill_usable) {
    136   DCHECK(allocator_type != gc::kAllocatorTypeLOS);
    137   size_t size = ComputeArraySize(self, array_class, component_count, component_size);
    138   if (UNLIKELY(size == 0)) {
    139     return nullptr;
    140   }
    141   gc::Heap* heap = Runtime::Current()->GetHeap();
    142   Array* result;
    143   if (!fill_usable) {
    144     SetLengthVisitor visitor(component_count);
    145     result = down_cast<Array*>(
    146         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
    147                                                               allocator_type, visitor));
    148   } else {
    149     SetLengthToUsableSizeVisitor visitor(component_count, DataOffset(component_size).SizeValue(),
    150                                          component_size);
    151     result = down_cast<Array*>(
    152         heap->AllocObjectWithAllocator<kIsInstrumented, true>(self, array_class, size,
    153                                                               allocator_type, visitor));
    154   }
    155   if (kIsDebugBuild && result != nullptr && Runtime::Current()->IsStarted()) {
    156     array_class = result->GetClass();  // In case the array class moved.
    157     CHECK_EQ(array_class->GetComponentSize(), component_size);
    158     if (!fill_usable) {
    159       CHECK_EQ(result->SizeOf(), size);
    160     } else {
    161       CHECK_GE(result->SizeOf(), size);
    162     }
    163   }
    164   return result;
    165 }
    166 
    167 template<class T>
    168 inline void PrimitiveArray<T>::VisitRoots(RootCallback* callback, void* arg) {
    169   if (!array_class_.IsNull()) {
    170     array_class_.VisitRoot(callback, arg, 0, kRootStickyClass);
    171   }
    172 }
    173 
    174 template<typename T>
    175 inline PrimitiveArray<T>* PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
    176   Array* raw_array = Array::Alloc<true>(self, GetArrayClass(), length, sizeof(T),
    177                                         Runtime::Current()->GetHeap()->GetCurrentAllocator());
    178   return down_cast<PrimitiveArray<T>*>(raw_array);
    179 }
    180 
    181 template<typename T>
    182 inline T PrimitiveArray<T>::Get(int32_t i) {
    183   if (!CheckIsValidIndex(i)) {
    184     DCHECK(Thread::Current()->IsExceptionPending());
    185     return T(0);
    186   }
    187   return GetWithoutChecks(i);
    188 }
    189 
    190 template<typename T>
    191 inline void PrimitiveArray<T>::Set(int32_t i, T value) {
    192   if (Runtime::Current()->IsActiveTransaction()) {
    193     Set<true>(i, value);
    194   } else {
    195     Set<false>(i, value);
    196   }
    197 }
    198 
    199 template<typename T>
    200 template<bool kTransactionActive, bool kCheckTransaction>
    201 inline void PrimitiveArray<T>::Set(int32_t i, T value) {
    202   if (CheckIsValidIndex(i)) {
    203     SetWithoutChecks<kTransactionActive, kCheckTransaction>(i, value);
    204   } else {
    205     DCHECK(Thread::Current()->IsExceptionPending());
    206   }
    207 }
    208 
    209 template<typename T>
    210 template<bool kTransactionActive, bool kCheckTransaction>
    211 inline void PrimitiveArray<T>::SetWithoutChecks(int32_t i, T value) {
    212   if (kCheckTransaction) {
    213     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    214   }
    215   if (kTransactionActive) {
    216     Runtime::Current()->RecordWriteArray(this, i, GetWithoutChecks(i));
    217   }
    218   DCHECK(CheckIsValidIndex(i));
    219   GetData()[i] = value;
    220 }
    221 // Backward copy where elements are of aligned appropriately for T. Count is in T sized units.
    222 // Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
    223 template<typename T>
    224 static inline void ArrayBackwardCopy(T* d, const T* s, int32_t count) {
    225   d += count;
    226   s += count;
    227   for (int32_t i = 0; i < count; ++i) {
    228     d--;
    229     s--;
    230     *d = *s;
    231   }
    232 }
    233 
    234 // Forward copy where elements are of aligned appropriately for T. Count is in T sized units.
    235 // Copies are guaranteed not to tear when the sizeof T is less-than 64bit.
    236 template<typename T>
    237 static inline void ArrayForwardCopy(T* d, const T* s, int32_t count) {
    238   for (int32_t i = 0; i < count; ++i) {
    239     *d = *s;
    240     d++;
    241     s++;
    242   }
    243 }
    244 
    245 template<class T>
    246 inline void PrimitiveArray<T>::Memmove(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
    247                                        int32_t count) {
    248   if (UNLIKELY(count == 0)) {
    249     return;
    250   }
    251   DCHECK_GE(dst_pos, 0);
    252   DCHECK_GE(src_pos, 0);
    253   DCHECK_GT(count, 0);
    254   DCHECK(src != nullptr);
    255   DCHECK_LT(dst_pos, GetLength());
    256   DCHECK_LE(dst_pos, GetLength() - count);
    257   DCHECK_LT(src_pos, src->GetLength());
    258   DCHECK_LE(src_pos, src->GetLength() - count);
    259 
    260   // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
    261   // in our implementation, because they may copy byte-by-byte.
    262   if (LIKELY(src != this)) {
    263     // Memcpy ok for guaranteed non-overlapping distinct arrays.
    264     Memcpy(dst_pos, src, src_pos, count);
    265   } else {
    266     // Handle copies within the same array using the appropriate direction copy.
    267     void* dst_raw = GetRawData(sizeof(T), dst_pos);
    268     const void* src_raw = src->GetRawData(sizeof(T), src_pos);
    269     if (sizeof(T) == sizeof(uint8_t)) {
    270       uint8_t* d = reinterpret_cast<uint8_t*>(dst_raw);
    271       const uint8_t* s = reinterpret_cast<const uint8_t*>(src_raw);
    272       memmove(d, s, count);
    273     } else {
    274       const bool copy_forward = (dst_pos < src_pos) || (dst_pos - src_pos >= count);
    275       if (sizeof(T) == sizeof(uint16_t)) {
    276         uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
    277         const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
    278         if (copy_forward) {
    279           ArrayForwardCopy<uint16_t>(d, s, count);
    280         } else {
    281           ArrayBackwardCopy<uint16_t>(d, s, count);
    282         }
    283       } else if (sizeof(T) == sizeof(uint32_t)) {
    284         uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
    285         const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
    286         if (copy_forward) {
    287           ArrayForwardCopy<uint32_t>(d, s, count);
    288         } else {
    289           ArrayBackwardCopy<uint32_t>(d, s, count);
    290         }
    291       } else {
    292         DCHECK_EQ(sizeof(T), sizeof(uint64_t));
    293         uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
    294         const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
    295         if (copy_forward) {
    296           ArrayForwardCopy<uint64_t>(d, s, count);
    297         } else {
    298           ArrayBackwardCopy<uint64_t>(d, s, count);
    299         }
    300       }
    301     }
    302   }
    303 }
    304 
    305 template<class T>
    306 inline void PrimitiveArray<T>::Memcpy(int32_t dst_pos, PrimitiveArray<T>* src, int32_t src_pos,
    307                                       int32_t count) {
    308   if (UNLIKELY(count == 0)) {
    309     return;
    310   }
    311   DCHECK_GE(dst_pos, 0);
    312   DCHECK_GE(src_pos, 0);
    313   DCHECK_GT(count, 0);
    314   DCHECK(src != nullptr);
    315   DCHECK_LT(dst_pos, GetLength());
    316   DCHECK_LE(dst_pos, GetLength() - count);
    317   DCHECK_LT(src_pos, src->GetLength());
    318   DCHECK_LE(src_pos, src->GetLength() - count);
    319 
    320   // Note for non-byte copies we can't rely on standard libc functions like memcpy(3) and memmove(3)
    321   // in our implementation, because they may copy byte-by-byte.
    322   void* dst_raw = GetRawData(sizeof(T), dst_pos);
    323   const void* src_raw = src->GetRawData(sizeof(T), src_pos);
    324   if (sizeof(T) == sizeof(uint8_t)) {
    325     memcpy(dst_raw, src_raw, count);
    326   } else if (sizeof(T) == sizeof(uint16_t)) {
    327     uint16_t* d = reinterpret_cast<uint16_t*>(dst_raw);
    328     const uint16_t* s = reinterpret_cast<const uint16_t*>(src_raw);
    329     ArrayForwardCopy<uint16_t>(d, s, count);
    330   } else if (sizeof(T) == sizeof(uint32_t)) {
    331     uint32_t* d = reinterpret_cast<uint32_t*>(dst_raw);
    332     const uint32_t* s = reinterpret_cast<const uint32_t*>(src_raw);
    333     ArrayForwardCopy<uint32_t>(d, s, count);
    334   } else {
    335     DCHECK_EQ(sizeof(T), sizeof(uint64_t));
    336     uint64_t* d = reinterpret_cast<uint64_t*>(dst_raw);
    337     const uint64_t* s = reinterpret_cast<const uint64_t*>(src_raw);
    338     ArrayForwardCopy<uint64_t>(d, s, count);
    339   }
    340 }
    341 
    342 }  // namespace mirror
    343 }  // namespace art
    344 
    345 #endif  // ART_RUNTIME_MIRROR_ARRAY_INL_H_
    346