/*
 * 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 {
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
