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

#ifndef ART_SRC_MIRROR_CLASS_INL_H_
#define ART_SRC_MIRROR_CLASS_INL_H_

#include "class.h"

#include "abstract_method.h"
#include "class_loader.h"
#include "dex_cache.h"
#include "field.h"
#include "iftable.h"
#include "object_array-inl.h"
#include "runtime.h"
#include "string.h"

namespace art {
namespace mirror {

inline size_t Class::GetObjectSize() const {
  DCHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
  DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
  size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this);
  return result;
}

inline Class* Class::GetSuperClass() const {
  // Can only get super class for loaded classes (hack for when runtime is
  // initializing)
  DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
  return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
}

inline ClassLoader* Class::GetClassLoader() const {
  return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
}

inline DexCache* Class::GetDexCache() const {
  return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
}

inline ObjectArray<AbstractMethod>* Class::GetDirectMethods() const {
  DCHECK(IsLoaded() || IsErroneous());
  return GetFieldObject<ObjectArray<AbstractMethod>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
}

inline void Class::SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
  DCHECK_NE(0, new_direct_methods->GetLength());
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
                 new_direct_methods, false);
}

inline AbstractMethod* Class::GetDirectMethod(int32_t i) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  return GetDirectMethods()->Get(i);
}

inline void Class::SetDirectMethod(uint32_t i, AbstractMethod* f)  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
  ObjectArray<AbstractMethod>* direct_methods =
      GetFieldObject<ObjectArray<AbstractMethod>*>(
          OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
  direct_methods->Set(i, f);
}

// Returns the number of static, private, and constructor methods.
inline size_t Class::NumDirectMethods() const {
  return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
}

inline ObjectArray<AbstractMethod>* Class::GetVirtualMethods() const {
  DCHECK(IsLoaded() || IsErroneous());
  return GetFieldObject<ObjectArray<AbstractMethod>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
}

inline void Class::SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) {
  // TODO: we reassign virtual methods to grow the table for miranda
  // methods.. they should really just be assigned once
  DCHECK_NE(0, new_virtual_methods->GetLength());
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
                 new_virtual_methods, false);
}

inline size_t Class::NumVirtualMethods() const {
  return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
}

inline AbstractMethod* Class::GetVirtualMethod(uint32_t i) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(IsResolved() || IsErroneous());
  return GetVirtualMethods()->Get(i);
}

inline AbstractMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(IsLoaded() || IsErroneous());
  return GetVirtualMethods()->Get(i);
}

inline void Class::SetVirtualMethod(uint32_t i, AbstractMethod* f)  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  ObjectArray<AbstractMethod>* virtual_methods =
      GetFieldObject<ObjectArray<AbstractMethod>*>(
          OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
  virtual_methods->Set(i, f);
}

inline ObjectArray<AbstractMethod>* Class::GetVTable() const {
  DCHECK(IsResolved() || IsErroneous());
  return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}

inline ObjectArray<AbstractMethod>* Class::GetVTableDuringLinking() const {
  DCHECK(IsLoaded() || IsErroneous());
  return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
}

inline void Class::SetVTable(ObjectArray<AbstractMethod>* new_vtable)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
}

inline bool Class::Implements(const Class* klass) const {
  DCHECK(klass != NULL);
  DCHECK(klass->IsInterface()) << PrettyClass(this);
  // All interfaces implemented directly and by our superclass, and
  // recursively all super-interfaces of those interfaces, are listed
  // in iftable_, so we can just do a linear scan through that.
  int32_t iftable_count = GetIfTableCount();
  IfTable* iftable = GetIfTable();
  for (int32_t i = 0; i < iftable_count; i++) {
    if (iftable->GetInterface(i) == klass) {
      return true;
    }
  }
  return false;
}

// Determine whether "this" is assignable from "src", where both of these
// are array classes.
//
// Consider an array class, e.g. Y[][], where Y is a subclass of X.
//   Y[][]            = Y[][] --> true (identity)
//   X[][]            = Y[][] --> true (element superclass)
//   Y                = Y[][] --> false
//   Y[]              = Y[][] --> false
//   Object           = Y[][] --> true (everything is an object)
//   Object[]         = Y[][] --> true
//   Object[][]       = Y[][] --> true
//   Object[][][]     = Y[][] --> false (too many []s)
//   Serializable     = Y[][] --> true (all arrays are Serializable)
//   Serializable[]   = Y[][] --> true
//   Serializable[][] = Y[][] --> false (unless Y is Serializable)
//
// Don't forget about primitive types.
//   Object[]         = int[] --> false
//
inline bool Class::IsArrayAssignableFromArray(const Class* src) const {
  DCHECK(IsArrayClass())  << PrettyClass(this);
  DCHECK(src->IsArrayClass()) << PrettyClass(src);
  return GetComponentType()->IsAssignableFrom(src->GetComponentType());
}

inline bool Class::IsAssignableFromArray(const Class* src) const {
  DCHECK(!IsInterface()) << PrettyClass(this);  // handled first in IsAssignableFrom
  DCHECK(src->IsArrayClass()) << PrettyClass(src);
  if (!IsArrayClass()) {
    // If "this" is not also an array, it must be Object.
    // src's super should be java_lang_Object, since it is an array.
    Class* java_lang_Object = src->GetSuperClass();
    DCHECK(java_lang_Object != NULL) << PrettyClass(src);
     DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src);
    return this == java_lang_Object;
  }
  return IsArrayAssignableFromArray(src);
}

inline bool Class::IsSubClass(const Class* klass) const {
  DCHECK(!IsInterface()) << PrettyClass(this);
  DCHECK(!IsArrayClass()) << PrettyClass(this);
  const Class* current = this;
  do {
    if (current == klass) {
      return true;
    }
    current = current->GetSuperClass();
  } while (current != NULL);
  return false;
}

inline AbstractMethod* Class::FindVirtualMethodForInterface(AbstractMethod* method) const {
  Class* declaring_class = method->GetDeclaringClass();
  DCHECK(declaring_class != NULL) << PrettyClass(this);
  DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
  // TODO cache to improve lookup speed
  int32_t iftable_count = GetIfTableCount();
  IfTable* iftable = GetIfTable();
  for (int32_t i = 0; i < iftable_count; i++) {
    if (iftable->GetInterface(i) == declaring_class) {
      return iftable->GetMethodArray(i)->Get(method->GetMethodIndex());
    }
  }
  return NULL;
}

inline AbstractMethod* Class::FindVirtualMethodForVirtual(AbstractMethod* method) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(!method->GetDeclaringClass()->IsInterface());
  // The argument method may from a super class.
  // Use the index to a potentially overridden one for this instance's class.
  return GetVTable()->Get(method->GetMethodIndex());
}

inline AbstractMethod* Class::FindVirtualMethodForSuper(AbstractMethod* method) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(!method->GetDeclaringClass()->IsInterface());
  return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
}

inline AbstractMethod* Class::FindVirtualMethodForVirtualOrInterface(AbstractMethod* method) const {
  if (method->IsDirect()) {
    return method;
  }
  if (method->GetDeclaringClass()->IsInterface()) {
    return FindVirtualMethodForInterface(method);
  }
  return FindVirtualMethodForVirtual(method);
}

inline IfTable* Class::GetIfTable() const {
  return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
}

inline int32_t Class::GetIfTableCount() const {
  IfTable* iftable = GetIfTable();
  if (iftable == NULL) {
    return 0;
  }
  return iftable->Count();
}

inline void Class::SetIfTable(IfTable* new_iftable) {
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
}

inline ObjectArray<Field>* Class::GetIFields() const {
  DCHECK(IsLoaded() || IsErroneous());
  return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
}

inline void Class::SetIFields(ObjectArray<Field>* new_ifields)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
}

inline ObjectArray<Field>* Class::GetSFields() const {
  DCHECK(IsLoaded() || IsErroneous());
  return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
}

inline void Class::SetSFields(ObjectArray<Field>* new_sfields)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
}

inline size_t Class::NumStaticFields() const {
  return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
}

inline Field* Class::GetStaticField(uint32_t i) const  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  return GetSFields()->Get(i);
}

inline void Class::SetStaticField(uint32_t i, Field* f)  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  ObjectArray<Field>* sfields= GetFieldObject<ObjectArray<Field>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
  sfields->Set(i, f);
}

inline size_t Class::NumInstanceFields() const {
  return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
}

inline Field* Class::GetInstanceField(uint32_t i) const  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
  DCHECK_NE(NumInstanceFields(), 0U);
  return GetIFields()->Get(i);
}

inline void Class::SetInstanceField(uint32_t i, Field* f)  // TODO: uint16_t
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
  ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>(
      OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
  ifields->Set(i, f);
}

inline void Class::SetVerifyErrorClass(Class* klass) {
  CHECK(klass != NULL) << PrettyClass(this);
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
}

inline uint32_t Class::GetAccessFlags() const {
  // Check class is loaded or this is java.lang.String that has a
  // circularity issue during loading the names of its members
  DCHECK(IsLoaded() || IsErroneous() ||
         this == String::GetJavaLangString() ||
         this == Field::GetJavaLangReflectField() ||
         this == AbstractMethod::GetConstructorClass() ||
         this == AbstractMethod::GetMethodClass());
  return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
}

inline String* Class::GetName() const {
  return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
}
inline void Class::SetName(String* name) {
  SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
}

}  // namespace mirror
}  // namespace art

#endif  // ART_SRC_MIRROR_CLASS_INL_H_
