/*
 * Copyright (C) 2016 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 "emulated_stack_frame-inl.h"

#include "array-alloc-inl.h"
#include "array-inl.h"
#include "class-alloc-inl.h"
#include "class_root.h"
#include "handle.h"
#include "jvalue-inl.h"
#include "method_handles-inl.h"
#include "method_handles.h"
#include "method_type-inl.h"
#include "object_array-alloc-inl.h"
#include "object_array-inl.h"
#include "reflection-inl.h"

namespace art {
namespace mirror {

// Calculates the size of a stack frame based on the size of its argument
// types and return types.
static void CalculateFrameAndReferencesSize(ObjPtr<mirror::ObjectArray<mirror::Class>> p_types,
                                            ObjPtr<mirror::Class> r_type,
                                            size_t* frame_size_out,
                                            size_t* references_size_out)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  const size_t length = p_types->GetLength();
  size_t frame_size = 0;
  size_t references_size = 0;
  for (size_t i = 0; i < length; ++i) {
    ObjPtr<mirror::Class> type = p_types->GetWithoutChecks(i);
    const Primitive::Type primitive_type = type->GetPrimitiveType();
    if (primitive_type == Primitive::kPrimNot) {
      references_size++;
    } else if (Primitive::Is64BitType(primitive_type)) {
      frame_size += 8;
    } else {
      frame_size += 4;
    }
  }

  const Primitive::Type return_type = r_type->GetPrimitiveType();
  if (return_type == Primitive::kPrimNot) {
    references_size++;
  } else if (Primitive::Is64BitType(return_type)) {
    frame_size += 8;
  } else {
    frame_size += 4;
  }

  (*frame_size_out) = frame_size;
  (*references_size_out) = references_size;
}

// Allows for read or write access to an emulated stack frame. Each
// accessor index has an associated index into the references / stack frame
// arrays which is incremented on every read or write to the frame.
//
// This class is used in conjunction with PerformConversions, either as a setter
// or as a getter.
class EmulatedStackFrameAccessor {
 public:
  EmulatedStackFrameAccessor(Handle<mirror::ObjectArray<mirror::Object>> references,
                             Handle<mirror::ByteArray> stack_frame,
                             size_t stack_frame_size) :
    references_(references),
    stack_frame_(stack_frame),
    stack_frame_size_(stack_frame_size),
    reference_idx_(0u),
    stack_frame_idx_(0u) {
  }

  ALWAYS_INLINE void SetReference(ObjPtr<mirror::Object> reference)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    references_->Set(reference_idx_++, reference);
  }

  ALWAYS_INLINE void Set(const uint32_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
    int8_t* array = stack_frame_->GetData();

    CHECK_LE((stack_frame_idx_ + 4u), stack_frame_size_);
    memcpy(array + stack_frame_idx_, &value, sizeof(uint32_t));
    stack_frame_idx_ += 4u;
  }

  ALWAYS_INLINE void SetLong(const int64_t value) REQUIRES_SHARED(Locks::mutator_lock_) {
    int8_t* array = stack_frame_->GetData();

    CHECK_LE((stack_frame_idx_ + 8u), stack_frame_size_);
    memcpy(array + stack_frame_idx_, &value, sizeof(int64_t));
    stack_frame_idx_ += 8u;
  }

  ALWAYS_INLINE ObjPtr<mirror::Object> GetReference() REQUIRES_SHARED(Locks::mutator_lock_) {
    return references_->Get(reference_idx_++);
  }

  ALWAYS_INLINE uint32_t Get() REQUIRES_SHARED(Locks::mutator_lock_) {
    const int8_t* array = stack_frame_->GetData();

    CHECK_LE((stack_frame_idx_ + 4u), stack_frame_size_);
    uint32_t val = 0;

    memcpy(&val, array + stack_frame_idx_, sizeof(uint32_t));
    stack_frame_idx_ += 4u;
    return val;
  }

  ALWAYS_INLINE int64_t GetLong() REQUIRES_SHARED(Locks::mutator_lock_) {
    const int8_t* array = stack_frame_->GetData();

    CHECK_LE((stack_frame_idx_ + 8u), stack_frame_size_);
    int64_t val = 0;

    memcpy(&val, array + stack_frame_idx_, sizeof(int64_t));
    stack_frame_idx_ += 8u;
    return val;
  }

 private:
  Handle<mirror::ObjectArray<mirror::Object>> references_;
  Handle<mirror::ByteArray> stack_frame_;
  const size_t stack_frame_size_;

  size_t reference_idx_;
  size_t stack_frame_idx_;

  DISALLOW_COPY_AND_ASSIGN(EmulatedStackFrameAccessor);
};

ObjPtr<mirror::EmulatedStackFrame> EmulatedStackFrame::CreateFromShadowFrameAndArgs(
    Thread* self,
    Handle<mirror::MethodType> caller_type,
    Handle<mirror::MethodType> callee_type,
    const ShadowFrame& caller_frame,
    const InstructionOperands* const operands) {
  StackHandleScope<6> hs(self);

  // Step 1: We must throw a WrongMethodTypeException if there's a mismatch in the
  // number of arguments between the caller and the callsite.
  Handle<mirror::ObjectArray<mirror::Class>> from_types(hs.NewHandle(caller_type->GetPTypes()));
  Handle<mirror::ObjectArray<mirror::Class>> to_types(hs.NewHandle(callee_type->GetPTypes()));

  const int32_t num_method_params = from_types->GetLength();
  if (to_types->GetLength() != num_method_params) {
    ThrowWrongMethodTypeException(callee_type.Get(), caller_type.Get());
    return nullptr;
  }

  // Step 2: Calculate the size of the reference / byte arrays in the emulated
  // stack frame.
  size_t frame_size = 0;
  size_t refs_size = 0;
  Handle<mirror::Class> r_type(hs.NewHandle(callee_type->GetRType()));
  CalculateFrameAndReferencesSize(to_types.Get(), r_type.Get(), &frame_size, &refs_size);

  // Step 3 : Allocate the arrays.
  ObjPtr<mirror::Class> array_class(GetClassRoot<mirror::ObjectArray<mirror::Object>>());

  Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(
      mirror::ObjectArray<mirror::Object>::Alloc(self, array_class, refs_size)));
  if (references == nullptr) {
    DCHECK(self->IsExceptionPending());
    return nullptr;
  }

  Handle<ByteArray> stack_frame(hs.NewHandle(ByteArray::Alloc(self, frame_size)));
  if (stack_frame == nullptr) {
    DCHECK(self->IsExceptionPending());
    return nullptr;
  }

  // Step 4 : Perform argument conversions (if required).
  ShadowFrameGetter getter(caller_frame, operands);
  EmulatedStackFrameAccessor setter(references, stack_frame, stack_frame->GetLength());
  if (!PerformConversions<ShadowFrameGetter, EmulatedStackFrameAccessor>(
          self, caller_type, callee_type, &getter, &setter, num_method_params)) {
    return nullptr;
  }

  // Step 5: Construct the EmulatedStackFrame object.
  Handle<EmulatedStackFrame> sf(hs.NewHandle(
      ObjPtr<EmulatedStackFrame>::DownCast(GetClassRoot<EmulatedStackFrame>()->AllocObject(self))));
  sf->SetFieldObject<false>(CallsiteTypeOffset(), caller_type.Get());
  sf->SetFieldObject<false>(TypeOffset(), callee_type.Get());
  sf->SetFieldObject<false>(ReferencesOffset(), references.Get());
  sf->SetFieldObject<false>(StackFrameOffset(), stack_frame.Get());

  return sf.Get();
}

bool EmulatedStackFrame::WriteToShadowFrame(Thread* self,
                                            Handle<mirror::MethodType> callee_type,
                                            const uint32_t first_dest_reg,
                                            ShadowFrame* callee_frame) {
  ObjPtr<mirror::ObjectArray<mirror::Class>> from_types(GetType()->GetPTypes());
  ObjPtr<mirror::ObjectArray<mirror::Class>> to_types(callee_type->GetPTypes());

  const int32_t num_method_params = from_types->GetLength();
  if (to_types->GetLength() != num_method_params) {
    ThrowWrongMethodTypeException(callee_type.Get(), GetType());
    return false;
  }

  StackHandleScope<3> hs(self);
  Handle<mirror::MethodType> frame_callsite_type(hs.NewHandle(GetType()));
  Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
  Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));

  EmulatedStackFrameAccessor getter(references, stack_frame, stack_frame->GetLength());
  ShadowFrameSetter setter(callee_frame, first_dest_reg);

  return PerformConversions<EmulatedStackFrameAccessor, ShadowFrameSetter>(
      self, frame_callsite_type, callee_type, &getter, &setter, num_method_params);
}

void EmulatedStackFrame::GetReturnValue(Thread* self, JValue* value) {
  StackHandleScope<2> hs(self);
  Handle<mirror::Class> r_type(hs.NewHandle(GetType()->GetRType()));

  const Primitive::Type type = r_type->GetPrimitiveType();
  if (type == Primitive::kPrimNot) {
    Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
    value->SetL(references->GetWithoutChecks(references->GetLength() - 1));
  } else {
    Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));
    const int8_t* array = stack_frame->GetData();
    const size_t length = stack_frame->GetLength();
    if (Primitive::Is64BitType(type)) {
      int64_t primitive = 0;
      memcpy(&primitive, array + length - sizeof(int64_t), sizeof(int64_t));
      value->SetJ(primitive);
    } else {
      uint32_t primitive = 0;
      memcpy(&primitive, array + length - sizeof(uint32_t), sizeof(uint32_t));
      value->SetI(primitive);
    }
  }
}

void EmulatedStackFrame::SetReturnValue(Thread* self, const JValue& value) {
  StackHandleScope<2> hs(self);
  Handle<mirror::Class> r_type(hs.NewHandle(GetType()->GetRType()));

  const Primitive::Type type = r_type->GetPrimitiveType();
  if (type == Primitive::kPrimNot) {
    Handle<mirror::ObjectArray<mirror::Object>> references(hs.NewHandle(GetReferences()));
    references->SetWithoutChecks<false>(references->GetLength() - 1, value.GetL());
  } else {
    Handle<ByteArray> stack_frame(hs.NewHandle(GetStackFrame()));
    int8_t* array = stack_frame->GetData();
    const size_t length = stack_frame->GetLength();
    if (Primitive::Is64BitType(type)) {
      const int64_t primitive = value.GetJ();
      memcpy(array + length - sizeof(int64_t), &primitive, sizeof(int64_t));
    } else {
      const uint32_t primitive = value.GetI();
      memcpy(array + length - sizeof(uint32_t), &primitive, sizeof(uint32_t));
    }
  }
}

}  // namespace mirror
}  // namespace art
