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_OBJECT_ARRAY_INL_H_
     18 #define ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
     19 
     20 #include "object_array.h"
     21 
     22 #include <string>
     23 
     24 #include "android-base/stringprintf.h"
     25 
     26 #include "array-inl.h"
     27 #include "class.h"
     28 #include "gc/heap.h"
     29 #include "object-inl.h"
     30 #include "obj_ptr-inl.h"
     31 #include "runtime.h"
     32 #include "handle_scope-inl.h"
     33 #include "thread.h"
     34 #include "utils.h"
     35 
     36 namespace art {
     37 namespace mirror {
     38 
     39 template<class T>
     40 inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
     41                                              ObjPtr<Class> object_array_class,
     42                                              int32_t length, gc::AllocatorType allocator_type) {
     43   Array* array = Array::Alloc<true>(self,
     44                                     object_array_class.Ptr(),
     45                                     length,
     46                                     ComponentSizeShiftWidth(kHeapReferenceSize),
     47                                     allocator_type);
     48   if (UNLIKELY(array == nullptr)) {
     49     return nullptr;
     50   }
     51   DCHECK_EQ(array->GetClass()->GetComponentSizeShift(),
     52             ComponentSizeShiftWidth(kHeapReferenceSize));
     53   return array->AsObjectArray<T>();
     54 }
     55 
     56 template<class T>
     57 inline ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self,
     58                                              ObjPtr<Class> object_array_class,
     59                                              int32_t length) {
     60   return Alloc(self,
     61                object_array_class,
     62                length,
     63                Runtime::Current()->GetHeap()->GetCurrentAllocator());
     64 }
     65 
     66 template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
     67 inline T* ObjectArray<T>::Get(int32_t i) {
     68   if (!CheckIsValidIndex(i)) {
     69     DCHECK(Thread::Current()->IsExceptionPending());
     70     return nullptr;
     71   }
     72   return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
     73 }
     74 
     75 template<class T> template<VerifyObjectFlags kVerifyFlags>
     76 inline bool ObjectArray<T>::CheckAssignable(ObjPtr<T> object) {
     77   if (object != nullptr) {
     78     Class* element_class = GetClass<kVerifyFlags>()->GetComponentType();
     79     if (UNLIKELY(!object->InstanceOf(element_class))) {
     80       ThrowArrayStoreException(object);
     81       return false;
     82     }
     83   }
     84   return true;
     85 }
     86 
     87 template<class T>
     88 inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
     89   if (Runtime::Current()->IsActiveTransaction()) {
     90     Set<true>(i, object);
     91   } else {
     92     Set<false>(i, object);
     93   }
     94 }
     95 
     96 template<class T>
     97 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
     98 inline void ObjectArray<T>::Set(int32_t i, ObjPtr<T> object) {
     99   if (CheckIsValidIndex(i) && CheckAssignable<kVerifyFlags>(object)) {
    100     SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
    101   } else {
    102     DCHECK(Thread::Current()->IsExceptionPending());
    103   }
    104 }
    105 
    106 template<class T>
    107 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    108 inline void ObjectArray<T>::SetWithoutChecks(int32_t i, ObjPtr<T> object) {
    109   DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
    110   DCHECK(CheckAssignable<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(object));
    111   SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags>(OffsetOfElement(i), object);
    112 }
    113 
    114 template<class T>
    115 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    116 inline void ObjectArray<T>::SetWithoutChecksAndWriteBarrier(int32_t i, ObjPtr<T> object) {
    117   DCHECK(CheckIsValidIndex<kVerifyFlags>(i));
    118   // TODO:  enable this check. It fails when writing the image in ImageWriter::FixupObjectArray.
    119   // DCHECK(CheckAssignable(object));
    120   SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
    121       OffsetOfElement(i), object);
    122 }
    123 
    124 template<class T> template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    125 inline T* ObjectArray<T>::GetWithoutChecks(int32_t i) {
    126   DCHECK(CheckIsValidIndex(i));
    127   return GetFieldObject<T, kVerifyFlags, kReadBarrierOption>(OffsetOfElement(i));
    128 }
    129 
    130 template<class T>
    131 inline void ObjectArray<T>::AssignableMemmove(int32_t dst_pos,
    132                                               ObjPtr<ObjectArray<T>> src,
    133                                               int32_t src_pos,
    134                                               int32_t count) {
    135   if (kIsDebugBuild) {
    136     for (int i = 0; i < count; ++i) {
    137       // The get will perform the VerifyObject.
    138       src->GetWithoutChecks(src_pos + i);
    139     }
    140   }
    141   // Perform the memmove using int memmove then perform the write barrier.
    142   static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
    143                 "art::mirror::HeapReference<T> and uint32_t have different sizes.");
    144   // TODO: Optimize this later?
    145   // We can't use memmove since it does not handle read barriers and may do by per byte copying.
    146   // See b/32012820.
    147   const bool copy_forward = (src != this) || (dst_pos < src_pos) || (dst_pos - src_pos >= count);
    148   if (copy_forward) {
    149     // Forward copy.
    150     bool baker_non_gray_case = false;
    151     if (kUseReadBarrier && kUseBakerReadBarrier) {
    152       uintptr_t fake_address_dependency;
    153       if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
    154         baker_non_gray_case = true;
    155         DCHECK_EQ(fake_address_dependency, 0U);
    156         src.Assign(reinterpret_cast<ObjectArray<T>*>(
    157             reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
    158         for (int i = 0; i < count; ++i) {
    159           // We can skip the RB here because 'src' isn't gray.
    160           T* obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
    161               src_pos + i);
    162           SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    163         }
    164       }
    165     }
    166     if (!baker_non_gray_case) {
    167       for (int i = 0; i < count; ++i) {
    168         // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
    169         T* obj = src->GetWithoutChecks(src_pos + i);
    170         SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    171       }
    172     }
    173   } else {
    174     // Backward copy.
    175     bool baker_non_gray_case = false;
    176     if (kUseReadBarrier && kUseBakerReadBarrier) {
    177       uintptr_t fake_address_dependency;
    178       if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
    179         baker_non_gray_case = true;
    180         DCHECK_EQ(fake_address_dependency, 0U);
    181         src.Assign(reinterpret_cast<ObjectArray<T>*>(
    182             reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
    183         for (int i = count - 1; i >= 0; --i) {
    184           // We can skip the RB here because 'src' isn't gray.
    185           T* obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
    186               src_pos + i);
    187           SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    188         }
    189       }
    190     }
    191     if (!baker_non_gray_case) {
    192       for (int i = count - 1; i >= 0; --i) {
    193         // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
    194         T* obj = src->GetWithoutChecks(src_pos + i);
    195         SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    196       }
    197     }
    198   }
    199   Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
    200   if (kIsDebugBuild) {
    201     for (int i = 0; i < count; ++i) {
    202       // The get will perform the VerifyObject.
    203       GetWithoutChecks(dst_pos + i);
    204     }
    205   }
    206 }
    207 
    208 template<class T>
    209 inline void ObjectArray<T>::AssignableMemcpy(int32_t dst_pos,
    210                                              ObjPtr<ObjectArray<T>> src,
    211                                              int32_t src_pos,
    212                                              int32_t count) {
    213   if (kIsDebugBuild) {
    214     for (int i = 0; i < count; ++i) {
    215       // The get will perform the VerifyObject.
    216       src->GetWithoutChecks(src_pos + i);
    217     }
    218   }
    219   // Perform the memmove using int memcpy then perform the write barrier.
    220   static_assert(sizeof(HeapReference<T>) == sizeof(uint32_t),
    221                 "art::mirror::HeapReference<T> and uint32_t have different sizes.");
    222   // TODO: Optimize this later?
    223   // We can't use memmove since it does not handle read barriers and may do by per byte copying.
    224   // See b/32012820.
    225   bool baker_non_gray_case = false;
    226   if (kUseReadBarrier && kUseBakerReadBarrier) {
    227     uintptr_t fake_address_dependency;
    228     if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
    229       baker_non_gray_case = true;
    230       DCHECK_EQ(fake_address_dependency, 0U);
    231       src.Assign(reinterpret_cast<ObjectArray<T>*>(
    232           reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
    233       for (int i = 0; i < count; ++i) {
    234         // We can skip the RB here because 'src' isn't gray.
    235         Object* obj = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
    236             src_pos + i);
    237         SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    238       }
    239     }
    240   }
    241   if (!baker_non_gray_case) {
    242     for (int i = 0; i < count; ++i) {
    243       // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
    244       T* obj = src->GetWithoutChecks(src_pos + i);
    245       SetWithoutChecksAndWriteBarrier<false>(dst_pos + i, obj);
    246     }
    247   }
    248   Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
    249   if (kIsDebugBuild) {
    250     for (int i = 0; i < count; ++i) {
    251       // The get will perform the VerifyObject.
    252       GetWithoutChecks(dst_pos + i);
    253     }
    254   }
    255 }
    256 
    257 template<class T>
    258 template<bool kTransactionActive>
    259 inline void ObjectArray<T>::AssignableCheckingMemcpy(int32_t dst_pos,
    260                                                      ObjPtr<ObjectArray<T>> src,
    261                                                      int32_t src_pos,
    262                                                      int32_t count,
    263                                                      bool throw_exception) {
    264   DCHECK_NE(this, src)
    265       << "This case should be handled with memmove that handles overlaps correctly";
    266   // We want to avoid redundant IsAssignableFrom checks where possible, so we cache a class that
    267   // we know is assignable to the destination array's component type.
    268   Class* dst_class = GetClass()->GetComponentType();
    269   Class* lastAssignableElementClass = dst_class;
    270 
    271   T* o = nullptr;
    272   int i = 0;
    273   bool baker_non_gray_case = false;
    274   if (kUseReadBarrier && kUseBakerReadBarrier) {
    275     uintptr_t fake_address_dependency;
    276     if (!ReadBarrier::IsGray(src.Ptr(), &fake_address_dependency)) {
    277       baker_non_gray_case = true;
    278       DCHECK_EQ(fake_address_dependency, 0U);
    279       src.Assign(reinterpret_cast<ObjectArray<T>*>(
    280           reinterpret_cast<uintptr_t>(src.Ptr()) | fake_address_dependency));
    281       for (; i < count; ++i) {
    282         // The follow get operations force the objects to be verified.
    283         // We can skip the RB here because 'src' isn't gray.
    284         o = src->template GetWithoutChecks<kDefaultVerifyFlags, kWithoutReadBarrier>(
    285             src_pos + i);
    286         if (o == nullptr) {
    287           // Null is always assignable.
    288           SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
    289         } else {
    290           // TODO: use the underlying class reference to avoid uncompression when not necessary.
    291           Class* o_class = o->GetClass();
    292           if (LIKELY(lastAssignableElementClass == o_class)) {
    293             SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
    294           } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
    295             lastAssignableElementClass = o_class;
    296             SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
    297           } else {
    298             // Can't put this element into the array, break to perform write-barrier and throw
    299             // exception.
    300             break;
    301           }
    302         }
    303       }
    304     }
    305   }
    306   if (!baker_non_gray_case) {
    307     for (; i < count; ++i) {
    308       // The follow get operations force the objects to be verified.
    309       // We need a RB here. ObjectArray::GetWithoutChecks() contains a RB.
    310       o = src->GetWithoutChecks(src_pos + i);
    311       if (o == nullptr) {
    312         // Null is always assignable.
    313         SetWithoutChecks<kTransactionActive>(dst_pos + i, nullptr);
    314       } else {
    315         // TODO: use the underlying class reference to avoid uncompression when not necessary.
    316         Class* o_class = o->GetClass();
    317         if (LIKELY(lastAssignableElementClass == o_class)) {
    318           SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
    319         } else if (LIKELY(dst_class->IsAssignableFrom(o_class))) {
    320           lastAssignableElementClass = o_class;
    321           SetWithoutChecks<kTransactionActive>(dst_pos + i, o);
    322         } else {
    323           // Can't put this element into the array, break to perform write-barrier and throw
    324           // exception.
    325           break;
    326         }
    327       }
    328     }
    329   }
    330   Runtime::Current()->GetHeap()->WriteBarrierArray(this, dst_pos, count);
    331   if (UNLIKELY(i != count)) {
    332     std::string actualSrcType(mirror::Object::PrettyTypeOf(o));
    333     std::string dstType(PrettyTypeOf());
    334     Thread* self = Thread::Current();
    335     std::string msg = android::base::StringPrintf(
    336         "source[%d] of type %s cannot be stored in destination array of type %s",
    337         src_pos + i,
    338         actualSrcType.c_str(),
    339         dstType.c_str());
    340     if (throw_exception) {
    341       self->ThrowNewException("Ljava/lang/ArrayStoreException;", msg.c_str());
    342     } else {
    343       LOG(FATAL) << msg;
    344     }
    345   }
    346 }
    347 
    348 template<class T>
    349 inline ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
    350   DCHECK_GE(new_length, 0);
    351   // We may get copied by a compacting GC.
    352   StackHandleScope<1> hs(self);
    353   Handle<ObjectArray<T>> h_this(hs.NewHandle(this));
    354   gc::Heap* heap = Runtime::Current()->GetHeap();
    355   gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() :
    356       heap->GetCurrentNonMovingAllocator();
    357   ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length, allocator_type);
    358   if (LIKELY(new_array != nullptr)) {
    359     new_array->AssignableMemcpy(0, h_this.Get(), 0, std::min(h_this->GetLength(), new_length));
    360   }
    361   return new_array;
    362 }
    363 
    364 template<class T>
    365 inline MemberOffset ObjectArray<T>::OffsetOfElement(int32_t i) {
    366   return MemberOffset(DataOffset(kHeapReferenceSize).Int32Value() + (i * kHeapReferenceSize));
    367 }
    368 
    369 template<class T> template<typename Visitor>
    370 inline void ObjectArray<T>::VisitReferences(const Visitor& visitor) {
    371   const size_t length = static_cast<size_t>(GetLength());
    372   for (size_t i = 0; i < length; ++i) {
    373     visitor(this, OffsetOfElement(i), false);
    374   }
    375 }
    376 
    377 }  // namespace mirror
    378 }  // namespace art
    379 
    380 #endif  // ART_RUNTIME_MIRROR_OBJECT_ARRAY_INL_H_
    381