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