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