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 32namespace art { 33namespace 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. 43static Array* RecursiveCreateMultiArray(Thread* self, 44 Handle<Class> array_class, int current_dimension, 45 Handle<mirror::IntArray> dimensions) 46 SHARED_REQUIRES(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, 52 array_class->GetComponentSizeShift(), 53 Runtime::Current()->GetHeap()->GetCurrentAllocator()))); 54 if (UNLIKELY(new_array.Get() == nullptr)) { 55 CHECK(self->IsExceptionPending()); 56 return nullptr; 57 } 58 if (current_dimension + 1 < dimensions->GetLength()) { 59 // Create a new sub-array in every element of the array. 60 for (int32_t i = 0; i < array_length; i++) { 61 StackHandleScope<1> hs2(self); 62 Handle<mirror::Class> h_component_type(hs2.NewHandle(array_class->GetComponentType())); 63 Array* sub_array = RecursiveCreateMultiArray(self, h_component_type, 64 current_dimension + 1, dimensions); 65 if (UNLIKELY(sub_array == nullptr)) { 66 CHECK(self->IsExceptionPending()); 67 return nullptr; 68 } 69 // Use non-transactional mode without check. 70 new_array->AsObjectArray<Array>()->Set<false, false>(i, sub_array); 71 } 72 } 73 return new_array.Get(); 74} 75 76Array* Array::CreateMultiArray(Thread* self, Handle<Class> element_class, 77 Handle<IntArray> dimensions) { 78 // Verify dimensions. 79 // 80 // The caller is responsible for verifying that "dimArray" is non-null 81 // and has a length > 0 and <= 255. 82 int num_dimensions = dimensions->GetLength(); 83 DCHECK_GT(num_dimensions, 0); 84 DCHECK_LE(num_dimensions, 255); 85 86 for (int i = 0; i < num_dimensions; i++) { 87 int dimension = dimensions->Get(i); 88 if (UNLIKELY(dimension < 0)) { 89 ThrowNegativeArraySizeException(StringPrintf("Dimension %d: %d", i, dimension).c_str()); 90 return nullptr; 91 } 92 } 93 94 // Find/generate the array class. 95 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 96 mirror::Class* element_class_ptr = element_class.Get(); 97 StackHandleScope<1> hs(self); 98 MutableHandle<mirror::Class> array_class( 99 hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr))); 100 if (UNLIKELY(array_class.Get() == nullptr)) { 101 CHECK(self->IsExceptionPending()); 102 return nullptr; 103 } 104 for (int32_t i = 1; i < dimensions->GetLength(); ++i) { 105 mirror::Class* array_class_ptr = array_class.Get(); 106 array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr)); 107 if (UNLIKELY(array_class.Get() == nullptr)) { 108 CHECK(self->IsExceptionPending()); 109 return nullptr; 110 } 111 } 112 // Create the array. 113 Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions); 114 if (UNLIKELY(new_array == nullptr)) { 115 CHECK(self->IsExceptionPending()); 116 } 117 return new_array; 118} 119 120void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) { 121 art::ThrowArrayIndexOutOfBoundsException(index, GetLength()); 122} 123 124void Array::ThrowArrayStoreException(Object* object) { 125 art::ThrowArrayStoreException(object->GetClass(), this->GetClass()); 126} 127 128Array* Array::CopyOf(Thread* self, int32_t new_length) { 129 CHECK(GetClass()->GetComponentType()->IsPrimitive()) << "Will miss write barriers"; 130 DCHECK_GE(new_length, 0); 131 // We may get copied by a compacting GC. 132 StackHandleScope<1> hs(self); 133 auto h_this(hs.NewHandle(this)); 134 auto* heap = Runtime::Current()->GetHeap(); 135 gc::AllocatorType allocator_type = heap->IsMovableObject(this) ? heap->GetCurrentAllocator() : 136 heap->GetCurrentNonMovingAllocator(); 137 const auto component_size = GetClass()->GetComponentSize(); 138 const auto component_shift = GetClass()->GetComponentSizeShift(); 139 Array* new_array = Alloc<true>(self, GetClass(), new_length, component_shift, allocator_type); 140 if (LIKELY(new_array != nullptr)) { 141 memcpy(new_array->GetRawData(component_size, 0), h_this->GetRawData(component_size, 0), 142 std::min(h_this->GetLength(), new_length) << component_shift); 143 } 144 return new_array; 145} 146 147 148template <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_; 149 150// Explicitly instantiate all the primitive array types. 151template class PrimitiveArray<uint8_t>; // BooleanArray 152template class PrimitiveArray<int8_t>; // ByteArray 153template class PrimitiveArray<uint16_t>; // CharArray 154template class PrimitiveArray<double>; // DoubleArray 155template class PrimitiveArray<float>; // FloatArray 156template class PrimitiveArray<int32_t>; // IntArray 157template class PrimitiveArray<int64_t>; // LongArray 158template class PrimitiveArray<int16_t>; // ShortArray 159 160} // namespace mirror 161} // namespace art 162