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