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 #include "array.h"
     18 
     19 #include "class.h"
     20 #include "class-inl.h"
     21 #include "class_linker-inl.h"
     22 #include "common_throws.h"
     23 #include "dex_file-inl.h"
     24 #include "gc/accounting/card_table-inl.h"
     25 #include "object-inl.h"
     26 #include "object_array.h"
     27 #include "object_array-inl.h"
     28 #include "handle_scope-inl.h"
     29 #include "thread.h"
     30 #include "utils.h"
     31 
     32 namespace art {
     33 namespace mirror {
     34 
     35 // Create a multi-dimensional array of Objects or primitive types.
     36 //
     37 // We have to generate the names for X[], X[][], X[][][], and so on.  The
     38 // easiest way to deal with that is to create the full name once and then
     39 // subtract pieces off.  Besides, we want to start with the outermost
     40 // piece and work our way in.
     41 // Recursively create an array with multiple dimensions.  Elements may be
     42 // Objects or primitive types.
     43 static Array* RecursiveCreateMultiArray(Thread* self,
     44                                         Handle<Class> array_class, int current_dimension,
     45                                         Handle<mirror::IntArray> dimensions)
     46     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     47   int32_t array_length = dimensions->Get(current_dimension);
     48   StackHandleScope<1> hs(self);
     49   Handle<Array> new_array(
     50       hs.NewHandle(
     51           Array::Alloc<true>(self, array_class.Get(), array_length, array_class->GetComponentSize(),
     52                              Runtime::Current()->GetHeap()->GetCurrentAllocator())));
     53   if (UNLIKELY(new_array.Get() == nullptr)) {
     54     CHECK(self->IsExceptionPending());
     55     return nullptr;
     56   }
     57   if (current_dimension + 1 < dimensions->GetLength()) {
     58     // Create a new sub-array in every element of the array.
     59     for (int32_t i = 0; i < array_length; i++) {
     60       StackHandleScope<1> hs(self);
     61       Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType()));
     62       Array* sub_array = RecursiveCreateMultiArray(self, h_component_type,
     63                                                    current_dimension + 1, dimensions);
     64       if (UNLIKELY(sub_array == nullptr)) {
     65         CHECK(self->IsExceptionPending());
     66         return nullptr;
     67       }
     68       // Use non-transactional mode without check.
     69       new_array->AsObjectArray<Array>()->Set<false, false>(i, sub_array);
     70     }
     71   }
     72   return new_array.Get();
     73 }
     74 
     75 Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class,
     76                                Handle<IntArray> dimensions) {
     77   // Verify dimensions.
     78   //
     79   // The caller is responsible for verifying that "dimArray" is non-null
     80   // and has a length > 0 and <= 255.
     81   int num_dimensions = dimensions->GetLength();
     82   DCHECK_GT(num_dimensions, 0);
     83   DCHECK_LE(num_dimensions, 255);
     84 
     85   for (int i = 0; i < num_dimensions; i++) {
     86     int dimension = dimensions->Get(i);
     87     if (UNLIKELY(dimension < 0)) {
     88       ThrowNegativeArraySizeException(StringPrintf("Dimension %d: %d", i, dimension).c_str());
     89       return nullptr;
     90     }
     91   }
     92 
     93   // Find/generate the array class.
     94   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     95   mirror::Class* element_class_ptr = element_class.Get();
     96   StackHandleScope<1> hs(self);
     97   Handle<mirror::Class> array_class(
     98       hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr)));
     99   if (UNLIKELY(array_class.Get() == nullptr)) {
    100     CHECK(self->IsExceptionPending());
    101     return nullptr;
    102   }
    103   for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
    104     mirror::Class* array_class_ptr = array_class.Get();
    105     array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr));
    106     if (UNLIKELY(array_class.Get() == nullptr)) {
    107       CHECK(self->IsExceptionPending());
    108       return nullptr;
    109     }
    110   }
    111   // Create the array.
    112   Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions);
    113   if (UNLIKELY(new_array == nullptr)) {
    114     CHECK(self->IsExceptionPending());
    115   }
    116   return new_array;
    117 }
    118 
    119 void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
    120   art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
    121 }
    122 
    123 void Array::ThrowArrayStoreException(Object* object) {
    124   art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
    125 }
    126 
    127 template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_;
    128 
    129 // Explicitly instantiate all the primitive array types.
    130 template class PrimitiveArray<uint8_t>;   // BooleanArray
    131 template class PrimitiveArray<int8_t>;    // ByteArray
    132 template class PrimitiveArray<uint16_t>;  // CharArray
    133 template class PrimitiveArray<double>;    // DoubleArray
    134 template class PrimitiveArray<float>;     // FloatArray
    135 template class PrimitiveArray<int32_t>;   // IntArray
    136 template class PrimitiveArray<int64_t>;   // LongArray
    137 template class PrimitiveArray<int16_t>;   // ShortArray
    138 
    139 }  // namespace mirror
    140 }  // namespace art
    141