12dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers/* 22dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Copyright (C) 2011 The Android Open Source Project 32dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * 42dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 52dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * you may not use this file except in compliance with the License. 62dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * You may obtain a copy of the License at 72dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * 82dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * http://www.apache.org/licenses/LICENSE-2.0 92dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * 102dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * Unless required by applicable law or agreed to in writing, software 112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * distributed under the License is distributed on an "AS IS" BASIS, 122dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * See the License for the specific language governing permissions and 142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers * limitations under the License. 152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers */ 162dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 172dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "array.h" 182dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 192dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class.h" 202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class-inl.h" 219837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers#include "class_linker-inl.h" 2262d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers#include "common_throws.h" 234f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 241d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "object-inl.h" 262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "object_array.h" 272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "object_array-inl.h" 28eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h" 292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "thread.h" 302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "utils.h" 312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace art { 332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersnamespace mirror { 342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// Create a multi-dimensional array of Objects or primitive types. 362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// 372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// We have to generate the names for X[], X[][], X[][][], and so on. The 382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// easiest way to deal with that is to create the full name once and then 392dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// subtract pieces off. Besides, we want to start with the outermost 402dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// piece and work our way in. 412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// Recursively create an array with multiple dimensions. Elements may be 422dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// Objects or primitive types. 435bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartierstatic Array* RecursiveCreateMultiArray(Thread* self, 440cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier Handle<Class> array_class, int current_dimension, 450cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier Handle<mirror::IntArray> dimensions) 462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers int32_t array_length = dimensions->Get(current_dimension); 48eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(self); 49eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<Array> new_array( 50eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle( 51eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Array::Alloc<true>(self, array_class.Get(), array_length, array_class->GetComponentSize(), 52eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Runtime::Current()->GetHeap()->GetCurrentAllocator()))); 53eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (UNLIKELY(new_array.Get() == nullptr)) { 542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers CHECK(self->IsExceptionPending()); 555bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier return nullptr; 562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 57590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (current_dimension + 1 < dimensions->GetLength()) { 582dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // Create a new sub-array in every element of the array. 592dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers for (int32_t i = 0; i < array_length; i++) { 60eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(self); 61eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType())); 62eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Array* sub_array = RecursiveCreateMultiArray(self, h_component_type, 632dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers current_dimension + 1, dimensions); 645bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier if (UNLIKELY(sub_array == nullptr)) { 652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers CHECK(self->IsExceptionPending()); 665bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier return nullptr; 672dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 68d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz // Use non-transactional mode without check. 69d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz new_array->AsObjectArray<Array>()->Set<false, false>(i, sub_array); 702dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 712dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 72eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier return new_array.Get(); 732dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} 742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 750cd81352a7c06e381951cea1b104fd73516f4341Mathieu ChartierArray* Array::CreateMultiArray(Thread* self, Handle<Class> element_class, 760cd81352a7c06e381951cea1b104fd73516f4341Mathieu Chartier Handle<IntArray> dimensions) { 772dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // Verify dimensions. 782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // 792dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // The caller is responsible for verifying that "dimArray" is non-null 802dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // and has a length > 0 and <= 255. 812dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers int num_dimensions = dimensions->GetLength(); 822dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers DCHECK_GT(num_dimensions, 0); 832dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers DCHECK_LE(num_dimensions, 255); 842dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 852dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers for (int i = 0; i < num_dimensions; i++) { 862dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers int dimension = dimensions->Get(i); 872dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers if (UNLIKELY(dimension < 0)) { 8862d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers ThrowNegativeArraySizeException(StringPrintf("Dimension %d: %d", i, dimension).c_str()); 895bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier return nullptr; 902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 912dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 922dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers // Find/generate the array class. 942dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 95b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier mirror::Class* element_class_ptr = element_class.Get(); 96eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(self); 97eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::Class> array_class( 98b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier hs.NewHandle(class_linker->FindArrayClass(self, &element_class_ptr))); 99eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (UNLIKELY(array_class.Get() == nullptr)) { 1002dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers CHECK(self->IsExceptionPending()); 1015bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier return nullptr; 1022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 1039837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers for (int32_t i = 1; i < dimensions->GetLength(); ++i) { 104b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier mirror::Class* array_class_ptr = array_class.Get(); 105b74cd29802f364b4cec88f4913fa38ade26b8fabMathieu Chartier array_class.Assign(class_linker->FindArrayClass(self, &array_class_ptr)); 106eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier if (UNLIKELY(array_class.Get() == nullptr)) { 1079837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers CHECK(self->IsExceptionPending()); 1089837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers return nullptr; 1099837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 1109837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers } 1119837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers // Create the array. 1125bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier Array* new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions); 1135bb99037bef70784ae4630c2e4b81688d2a18621Mathieu Chartier if (UNLIKELY(new_array == nullptr)) { 1142dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers CHECK(self->IsExceptionPending()); 1152dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers } 1162dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers return new_array; 1172dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} 1182dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 119ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid Array::ThrowArrayIndexOutOfBoundsException(int32_t index) { 12062d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers art::ThrowArrayIndexOutOfBoundsException(index, GetLength()); 1212dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} 1222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 123ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid Array::ThrowArrayStoreException(Object* object) { 12462d6c772205b8859f0ebf7ad105402ec4c3e2e01Ian Rogers art::ThrowArrayStoreException(object->GetClass(), this->GetClass()); 1252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} 1262dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 12794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchitemplate <typename T> GcRoot<Class> PrimitiveArray<T>::array_class_; 1282dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 1292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers// Explicitly instantiate all the primitive array types. 1302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<uint8_t>; // BooleanArray 1312dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<int8_t>; // ByteArray 1322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<uint16_t>; // CharArray 1332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<double>; // DoubleArray 1342dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<float>; // FloatArray 1352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<int32_t>; // IntArray 1362dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<int64_t>; // LongArray 1372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogerstemplate class PrimitiveArray<int16_t>; // ShortArray 1382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 1392dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} // namespace mirror 1402dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers} // namespace art 141