// Copyright 2011 Google Inc. All Rights Reserved.

#include "calling_convention.h"
#include "logging.h"
#include "utils.h"

namespace art {

// Offset of Method within the frame
FrameOffset CallingConvention::MethodStackOffset() {
  return displacement_;
}

// Managed runtime calling convention

size_t ManagedRuntimeCallingConvention::FrameSize() {
  UNIMPLEMENTED(FATAL);
  return 0;
}

bool ManagedRuntimeCallingConvention::HasNext() {
  return itr_args_ < GetMethod()->NumArgs();
}

void ManagedRuntimeCallingConvention::Next() {
  CHECK(HasNext());
  if (IsCurrentUserArg() && 
      GetMethod()->IsParamALongOrDouble(itr_args_)) {
    itr_longs_and_doubles_++;
    itr_slots_++;
  }
  itr_args_++;
  itr_slots_++;
}

bool ManagedRuntimeCallingConvention::IsCurrentUserArg() {
  if (GetMethod()->IsStatic()) {
    return true;
  }
  // For a virtual method, "this" should never be NULL.
  return (itr_args_ != 0);
}

size_t ManagedRuntimeCallingConvention::CurrentParamSize() {
  return GetMethod()->ParamSize(itr_args_);
}

bool ManagedRuntimeCallingConvention::IsCurrentParamAReference() {
  return GetMethod()->IsParamAReference(itr_args_);
}

// JNI calling convention

size_t JniCallingConvention::OutArgSize() {
  return RoundUp(NumberOfOutgoingStackArgs() * kPointerSize, 16);
}

size_t JniCallingConvention::HandleCount() {
  const Method* method = GetMethod();
  return method->NumReferenceArgs() + (method->IsStatic() ? 1 : 0);
}

FrameOffset JniCallingConvention::ReturnValueSaveLocation() {
  size_t start_of_shb = ShbLinkOffset().Int32Value() +  kPointerSize;
  size_t handle_size = kPointerSize * HandleCount();  // size excluding header
  return FrameOffset(start_of_shb + handle_size);
}

bool JniCallingConvention::HasNext() {
  if (itr_args_ <= kObjectOrClass) {
    return true;
  } else {
    unsigned int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
    return arg_pos < GetMethod()->NumArgs();
  }
}

void JniCallingConvention::Next() {
  CHECK(HasNext());
  if (itr_args_ > kObjectOrClass) {
    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
    if (GetMethod()->IsParamALongOrDouble(arg_pos)) {
      itr_longs_and_doubles_++;
      itr_slots_++;
    }
  }
  itr_args_++;
  itr_slots_++;
}

bool JniCallingConvention::IsCurrentParamAReference() {
  switch (itr_args_) {
    case kJniEnv:
      return false;  // JNIEnv*
    case kObjectOrClass:
      return true;   // jobject or jclass
    default: {
      int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
      return GetMethod()->IsParamAReference(arg_pos);
    }
  }
}

// Return position of handle holding reference at the current iterator position
FrameOffset JniCallingConvention::CurrentParamHandleOffset() {
  CHECK(IsCurrentParamAReference());
  CHECK_GT(ShbLinkOffset(), ShbNumRefsOffset());
  // Address of 1st handle
  int result = ShbLinkOffset().Int32Value() + kPointerSize;
  if (itr_args_ != kObjectOrClass) {
    const Method *method = GetMethod();
    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(method);
    int previous_refs = GetMethod()->NumReferenceArgsBefore(arg_pos);
    if (method->IsStatic()) {
      previous_refs++;  // account for jclass
    }
    result += previous_refs * kPointerSize;
  }
  CHECK_GT(result, ShbLinkOffset().Int32Value());
  return FrameOffset(result);
}

size_t JniCallingConvention::CurrentParamSize() {
  if (itr_args_ <= kObjectOrClass) {
    return kPointerSize;  // JNIEnv or jobject/jclass
  } else {
    int arg_pos = itr_args_ - NumberOfExtraArgumentsForJni(GetMethod());
    return GetMethod()->ParamSize(arg_pos);
  }
}

size_t JniCallingConvention::NumberOfExtraArgumentsForJni(
    const Method* method) {
  // The first argument is the JNIEnv*.
  // Static methods have an extra argument which is the jclass.
  return (method->IsStatic() ? 2 : 1);
}

}  // namespace art
