/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "array-inl.h"

#include "array-alloc-inl.h"
#include "base/utils.h"
#include "class-inl.h"
#include "class.h"
#include "class_linker-inl.h"
#include "class_root-inl.h"
#include "common_throws.h"
#include "dex/dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "handle_scope-inl.h"
#include "object-inl.h"
#include "object_array-alloc-inl.h"
#include "object_array-inl.h"
#include "thread.h"

namespace art HIDDEN {
namespace mirror {

using android::base::StringPrintf;

// Create a multi-dimensional array of Objects or primitive types.
//
// We have to generate the names for X[], X[][], X[][][], and so on.  The
// easiest way to deal with that is to create the full name once and then
// subtract pieces off.  Besides, we want to start with the outermost
// piece and work our way in.
// Recursively create an array with multiple dimensions.  Elements may be
// Objects or primitive types.
static ObjPtr<Array> RecursiveCreateMultiArray(Thread* self,
                                               Handle<Class> array_class,
                                               int current_dimension,
                                               Handle<mirror::IntArray> dimensions)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  int32_t array_length = dimensions->Get(current_dimension);
  StackHandleScope<2> hs(self);
  Handle<mirror::Class> h_component_type(hs.NewHandle(array_class->GetComponentType()));
  size_t component_size_shift = h_component_type->GetPrimitiveTypeSizeShift();
  gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
  Handle<Array> new_array(hs.NewHandle(
      Array::Alloc(self, array_class.Get(), array_length, component_size_shift, allocator_type)));
  if (UNLIKELY(new_array == nullptr)) {
    CHECK(self->IsExceptionPending());
    return nullptr;
  }
  if (current_dimension + 1 < dimensions->GetLength()) {
    // Create a new sub-array in every element of the array.
    for (int32_t i = 0; i < array_length; i++) {
      ObjPtr<Array> sub_array =
          RecursiveCreateMultiArray(self, h_component_type, current_dimension + 1, dimensions);
      if (UNLIKELY(sub_array == nullptr)) {
        CHECK(self->IsExceptionPending());
        return nullptr;
      }
      // Use non-transactional mode without check.
      new_array->AsObjectArray<Array>()->Set<false, false>(i, sub_array);
    }
  }
  return new_array.Get();
}

ObjPtr<Array> Array::CreateMultiArray(Thread* self,
                                      Handle<Class> element_class,
                                      Handle<IntArray> dimensions) {
  // Verify dimensions.
  //
  // The caller is responsible for verifying that "dimArray" is non-null
  // and has a length > 0 and <= 255.
  int num_dimensions = dimensions->GetLength();
  DCHECK_GT(num_dimensions, 0);
  DCHECK_LE(num_dimensions, 255);

  for (int i = 0; i < num_dimensions; i++) {
    int dimension = dimensions->Get(i);
    if (UNLIKELY(dimension < 0)) {
      ThrowNegativeArraySizeException(StringPrintf("Dimension %d: %d", i, dimension).c_str());
      return nullptr;
    }
  }

  // Find/generate the array class.
  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
  StackHandleScope<1> hs(self);
  MutableHandle<mirror::Class> array_class(
      hs.NewHandle(class_linker->FindArrayClass(self, element_class.Get())));
  if (UNLIKELY(array_class == nullptr)) {
    CHECK(self->IsExceptionPending());
    return nullptr;
  }
  for (int32_t i = 1; i < dimensions->GetLength(); ++i) {
    array_class.Assign(class_linker->FindArrayClass(self, array_class.Get()));
    if (UNLIKELY(array_class == nullptr)) {
      CHECK(self->IsExceptionPending());
      return nullptr;
    }
  }
  // Create the array.
  ObjPtr<Array> new_array = RecursiveCreateMultiArray(self, array_class, 0, dimensions);
  if (UNLIKELY(new_array == nullptr)) {
    CHECK(self->IsExceptionPending());
  }
  return new_array.Ptr();
}

template<typename T>
ObjPtr<PrimitiveArray<T>> PrimitiveArray<T>::Alloc(Thread* self, size_t length) {
  Runtime* runtime = Runtime::Current();
  gc::AllocatorType allocator_type = runtime->GetHeap()->GetCurrentAllocator();
  ObjPtr<Array> raw_array = Array::Alloc(self,
                                         GetClassRoot<PrimitiveArray<T>>(runtime->GetClassLinker()),
                                         length,
                                         ComponentSizeShiftWidth(sizeof(T)),
                                         allocator_type);
  return ObjPtr<PrimitiveArray<T>>::DownCast(raw_array);
}

void Array::ThrowArrayIndexOutOfBoundsException(int32_t index) {
  art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
}

void Array::ThrowArrayStoreException(ObjPtr<Object> object) {
  art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
}

ObjPtr<Array> Array::CopyOf(Handle<Array> h_this, Thread* self, int32_t new_length) {
  ObjPtr<Class> klass = h_this->GetClass();
  CHECK(klass->IsPrimitiveArray()) << "Will miss write barriers";
  DCHECK_GE(new_length, 0);
  auto* heap = Runtime::Current()->GetHeap();
  gc::AllocatorType allocator_type = heap->IsMovableObject(h_this.Get())
      ? heap->GetCurrentAllocator()
      : heap->GetCurrentNonMovingAllocator();
  const auto component_size = klass->GetComponentSize();
  const auto component_shift = klass->GetComponentSizeShift();
  ObjPtr<Array> new_array =
      Alloc(self, klass, new_length, component_shift, allocator_type);  // Invalidates klass.
  if (LIKELY(new_array != nullptr)) {
    memcpy(new_array->GetRawData(component_size, 0),
           h_this->GetRawData(component_size, 0),
           std::min(h_this->GetLength(), new_length) << component_shift);
  }
  return new_array;
}

// Explicitly instantiate all the primitive array types.
template class PrimitiveArray<uint8_t>;   // BooleanArray
template class PrimitiveArray<int8_t>;    // ByteArray
template class PrimitiveArray<uint16_t>;  // CharArray
template class PrimitiveArray<double>;    // DoubleArray
template class PrimitiveArray<float>;     // FloatArray
template class PrimitiveArray<int32_t>;   // IntArray
template class PrimitiveArray<int64_t>;   // LongArray
template class PrimitiveArray<int16_t>;   // ShortArray

}  // namespace mirror
}  // namespace art
