/*
 * 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_OBJECT_UTILS_H_
#define ART_SRC_OBJECT_UTILS_H_

#include "class_linker.h"
#include "dex_cache.h"
#include "dex_file.h"
#include "intern_table.h"
#include "monitor.h"
#include "object.h"
#include "runtime.h"
#include "UniquePtr.h"

#include <string>

namespace art {

class ObjectLock {
 public:
  explicit ObjectLock(Object* object) : self_(Thread::Current()), obj_(object) {
    CHECK(object != NULL);
    obj_->MonitorEnter(self_);
  }

  ~ObjectLock() {
    obj_->MonitorExit(self_);
  }

  void Wait() {
    return Monitor::Wait(self_, obj_, 0, 0, false);
  }

  void Notify() {
    obj_->Notify();
  }

  void NotifyAll() {
    obj_->NotifyAll();
  }

 private:
  Thread* self_;
  Object* obj_;
  DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};

class ClassHelper {
 public:
  ClassHelper(const Class* c = NULL, ClassLinker* l = NULL)
      : class_def_(NULL),
        class_linker_(l),
        dex_cache_(NULL),
        dex_file_(NULL),
        interface_type_list_(NULL),
        klass_(c) {
  }

  void ChangeClass(const Class* new_c) {
    DCHECK(new_c != NULL);
    if (dex_cache_ != NULL) {
      DexCache* new_c_dex_cache = new_c->GetDexCache();
      if (new_c_dex_cache != dex_cache_) {
        dex_cache_ = new_c_dex_cache;
        dex_file_ = NULL;
      }
    }
    klass_ = new_c;
    interface_type_list_ = NULL;
    class_def_ = NULL;
  }

  // The returned const char* is only guaranteed to be valid for the lifetime of the ClassHelper.
  // If you need it longer, copy it into a std::string.
  const char* GetDescriptor() {
    if (UNLIKELY(klass_->IsArrayClass())) {
      return GetArrayDescriptor();
    } else if (UNLIKELY(klass_->IsPrimitive())) {
      return Primitive::Descriptor(klass_->GetPrimitiveType());
    } else if (UNLIKELY(klass_->IsProxyClass())) {
      descriptor_ = GetClassLinker()->GetDescriptorForProxy(klass_);
      return descriptor_.c_str();
    } else {
      const DexFile& dex_file = GetDexFile();
      const DexFile::TypeId& type_id = dex_file.GetTypeId(klass_->GetDexTypeIndex());
      return dex_file.GetTypeDescriptor(type_id);
    }
  }

  const char* GetArrayDescriptor() {
    std::string result("[");
    const Class* saved_klass = klass_;
    ChangeClass(klass_->GetComponentType());
    result += GetDescriptor();
    ChangeClass(saved_klass);
    descriptor_ = result;
    return descriptor_.c_str();
  }

  const DexFile::ClassDef* GetClassDef() {
    const DexFile::ClassDef* result = class_def_;
    if (result == NULL) {
      result = GetDexFile().FindClassDef(GetDescriptor());
      class_def_ = result;
    }
    return result;
  }

  uint32_t NumInterfaces() {
    if (klass_->IsPrimitive()) {
      return 0;
    } else if (klass_->IsArrayClass()) {
      return 2;
    } else if (klass_->IsProxyClass()) {
      return klass_->GetIfTable()->GetLength();
    } else {
      const DexFile::TypeList* interfaces = GetInterfaceTypeList();
      if (interfaces == NULL) {
        return 0;
      } else {
        return interfaces->Size();
      }
    }
  }

  uint16_t GetInterfaceTypeIdx(uint32_t idx) {
    DCHECK(!klass_->IsPrimitive());
    DCHECK(!klass_->IsArrayClass());
    return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
  }

  Class* GetInterface(uint32_t idx) {
    DCHECK(!klass_->IsPrimitive());
    if (klass_->IsArrayClass()) {
      if (idx == 0) {
        return GetClassLinker()->FindSystemClass("Ljava/lang/Cloneable;");
      } else {
        DCHECK_EQ(1U, idx);
        return GetClassLinker()->FindSystemClass("Ljava/io/Serializable;");
      }
    } else if (klass_->IsProxyClass()) {
      return klass_->GetIfTable()->Get(idx)->GetInterface();
    } else {
      uint16_t type_idx = GetInterfaceTypeIdx(idx);
      Class* interface = GetDexCache()->GetResolvedType(type_idx);
      if (interface == NULL) {
        interface = GetClassLinker()->ResolveType(GetDexFile(), type_idx, klass_);
        CHECK(interface != NULL || Thread::Current()->IsExceptionPending());
      }
      return interface;
    }
  }

  const char* GetSourceFile() {
    std::string descriptor(GetDescriptor());
    const DexFile& dex_file = GetDexFile();
    const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
    CHECK(dex_class_def != NULL);
    return dex_file.GetSourceFile(*dex_class_def);
  }

  std::string GetLocation() {
    return GetDexCache()->GetLocation()->ToModifiedUtf8();
  }

  const DexFile& GetDexFile() {
    const DexFile* result = dex_file_;
    if (result == NULL) {
      const DexCache* dex_cache = GetDexCache();
      result = &GetClassLinker()->FindDexFile(dex_cache);
      dex_file_ = result;
    }
    return *result;
  }

 private:
  const DexFile::TypeList* GetInterfaceTypeList() {
    const DexFile::TypeList* result = interface_type_list_;
    if (result == NULL) {
      const DexFile::ClassDef* class_def = GetClassDef();
      if (class_def != NULL) {
        result =  GetDexFile().GetInterfacesList(*class_def);
        interface_type_list_ = result;
      }
    }
    return result;
  }

  DexCache* GetDexCache() {
    DexCache* result = dex_cache_;
    if (result == NULL) {
      result = klass_->GetDexCache();
      dex_cache_ = result;
    }
    return result;
  }

  ClassLinker* GetClassLinker() {
    ClassLinker* result = class_linker_;
    if (result == NULL) {
      result = Runtime::Current()->GetClassLinker();
      class_linker_ = result;
    }
    return result;
  }

  const DexFile::ClassDef* class_def_;
  ClassLinker* class_linker_;
  DexCache* dex_cache_;
  const DexFile* dex_file_;
  const DexFile::TypeList* interface_type_list_;
  const Class* klass_;
  std::string descriptor_;

  DISALLOW_COPY_AND_ASSIGN(ClassHelper);
};

class FieldHelper {
 public:
  FieldHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(NULL) {}
  explicit FieldHelper(const Field* f) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), field_(f) {}
  FieldHelper(const Field* f, ClassLinker* l) : class_linker_(l), dex_cache_(NULL), dex_file_(NULL),
      field_(f) {}

  void ChangeField(const Field* new_f) {
    DCHECK(new_f != NULL);
    if (dex_cache_ != NULL) {
      DexCache* new_f_dex_cache = new_f->GetDeclaringClass()->GetDexCache();
      if (new_f_dex_cache != dex_cache_) {
        dex_cache_ = new_f_dex_cache;
        dex_file_ = NULL;
      }
    }
    field_ = new_f;
  }
  const char* GetName() {
    uint32_t field_index = field_->GetDexFieldIndex();
    if (field_index != DexFile::kDexNoIndex) {
      const DexFile& dex_file = GetDexFile();
      return dex_file.GetFieldName(dex_file.GetFieldId(field_index));
    } else {
      // Proxy classes have a single static field called "throws"
      CHECK(field_->GetDeclaringClass()->IsProxyClass());
      DCHECK(field_->IsStatic());
      return "throws";
    }
  }
  String* GetNameAsString() {
    uint32_t field_index = field_->GetDexFieldIndex();
    if (field_index != DexFile::kDexNoIndex) {
      const DexFile& dex_file = GetDexFile();
      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
      return GetClassLinker()->ResolveString(dex_file, field_id.name_idx_, GetDexCache());
    } else {
      // Proxy classes have a single static field called "throws"
      CHECK(field_->GetDeclaringClass()->IsProxyClass());
      DCHECK(field_->IsStatic());
      return Runtime::Current()->GetInternTable()->InternStrong("throws");
    }
  }
  Class* GetType() {
    uint32_t field_index = field_->GetDexFieldIndex();
    if (field_index != DexFile::kDexNoIndex) {
      const DexFile& dex_file = GetDexFile();
      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
      Class* type = GetDexCache()->GetResolvedType(field_id.type_idx_);
      if (type == NULL) {
        type = GetClassLinker()->ResolveType(field_id.type_idx_, field_);
        CHECK(type != NULL || Thread::Current()->IsExceptionPending());
      }
      return type;
    } else {
      // Proxy classes have a single static field called "throws" whose type is Class[][]
      CHECK(field_->GetDeclaringClass()->IsProxyClass());
      DCHECK(field_->IsStatic());
      return GetClassLinker()->FindSystemClass("[[Ljava/lang/Class;");
    }
  }
  const char* GetTypeDescriptor() {
    uint32_t field_index = field_->GetDexFieldIndex();
    if (field_index != DexFile::kDexNoIndex) {
      const DexFile& dex_file = GetDexFile();
      const DexFile::FieldId& field_id = dex_file.GetFieldId(field_index);
      return dex_file.GetFieldTypeDescriptor(field_id);
    } else {
      // Proxy classes have a single static field called "throws" whose type is Class[][]
      CHECK(field_->GetDeclaringClass()->IsProxyClass());
      DCHECK(field_->IsStatic());
      return "[[Ljava/lang/Class;";
    }
  }
  Primitive::Type GetTypeAsPrimitiveType() {
    return Primitive::GetType(GetTypeDescriptor()[0]);
  }
  bool IsPrimitiveType() {
    Primitive::Type type = GetTypeAsPrimitiveType();
    return type != Primitive::kPrimNot;
  }
  size_t FieldSize() {
    Primitive::Type type = GetTypeAsPrimitiveType();
    return Primitive::FieldSize(type);
  }

  // The returned const char* is only guaranteed to be valid for the lifetime of the FieldHelper.
  // If you need it longer, copy it into a std::string.
  const char* GetDeclaringClassDescriptor() {
    uint16_t type_idx = field_->GetDeclaringClass()->GetDexTypeIndex();
    if (type_idx != DexFile::kDexNoIndex16) {
      const DexFile& dex_file = GetDexFile();
      return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
    } else {
      // Most likely a proxy class
      ClassHelper kh(field_->GetDeclaringClass());
      declaring_class_descriptor_ = kh.GetDescriptor();
      return declaring_class_descriptor_.c_str();
    }
  }

 private:
  DexCache* GetDexCache() {
    DexCache* result = dex_cache_;
    if (result == NULL) {
      result = field_->GetDeclaringClass()->GetDexCache();
      dex_cache_ = result;
    }
    return result;
  }
  ClassLinker* GetClassLinker() {
    ClassLinker* result = class_linker_;
    if (result == NULL) {
      result = Runtime::Current()->GetClassLinker();
      class_linker_ = result;
    }
    return result;
  }
  const DexFile& GetDexFile() {
    const DexFile* result = dex_file_;
    if (result == NULL) {
      const DexCache* dex_cache = GetDexCache();
      result = &GetClassLinker()->FindDexFile(dex_cache);
      dex_file_ = result;
    }
    return *result;
  }

  ClassLinker* class_linker_;
  DexCache* dex_cache_;
  const DexFile* dex_file_;
  const Field* field_;
  std::string declaring_class_descriptor_;

  DISALLOW_COPY_AND_ASSIGN(FieldHelper);
};

class MethodHelper {
 public:
  MethodHelper() : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL), method_(NULL),
      shorty_(NULL), shorty_len_(0) {}
  explicit MethodHelper(const Method* m) : class_linker_(NULL), dex_cache_(NULL), dex_file_(NULL),
      method_(NULL), shorty_(NULL), shorty_len_(0) {
    SetMethod(m);
  }
  MethodHelper(const Method* m, ClassLinker* l) : class_linker_(l), dex_cache_(NULL),
      dex_file_(NULL), method_(NULL), shorty_(NULL), shorty_len_(0) {
    SetMethod(m);
  }

  void ChangeMethod(Method* new_m) {
    DCHECK(new_m != NULL);
    if (dex_cache_ != NULL) {
      Class* klass = new_m->GetDeclaringClass();
      if (klass->IsProxyClass()) {
        dex_cache_ = NULL;
        dex_file_ = NULL;
      } else {
        DexCache* new_m_dex_cache = klass->GetDexCache();
        if (new_m_dex_cache != dex_cache_) {
          dex_cache_ = new_m_dex_cache;
          dex_file_ = NULL;
        }
      }
    }
    SetMethod(new_m);
    shorty_ = NULL;
  }
  const char* GetName() {
    const DexFile& dex_file = GetDexFile();
    uint32_t dex_method_idx = method_->GetDexMethodIndex();
    if (dex_method_idx != DexFile::kDexNoIndex16) {
      return dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
    } else {
      Runtime* runtime = Runtime::Current();
      if (method_ == runtime->GetResolutionMethod()) {
        return "<VM internal resolution method>";
      } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kSaveAll)) {
        return "<VM internal callee-save all registers method>";
      } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)) {
        return "<VM internal callee-save reference registers method>";
      } else if (method_ == runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)) {
        return "<VM internal callee-save reference and argument registers method>";
      } else {
        return "<unknown VM internal method>";
      }
    }
  }
  String* GetNameAsString() {
    const DexFile& dex_file = GetDexFile();
    uint32_t dex_method_idx = method_->GetDexMethodIndex();
    const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
    return GetClassLinker()->ResolveString(dex_file, method_id.name_idx_, GetDexCache());
  }
  const char* GetShorty() {
    const char* result = shorty_;
    if (result == NULL) {
      const DexFile& dex_file = GetDexFile();
      result = dex_file.GetMethodShorty(dex_file.GetMethodId(method_->GetDexMethodIndex()),
                                        &shorty_len_);
      shorty_ = result;
    }
    return result;
  }
  uint32_t GetShortyLength() {
    if (shorty_ == NULL) {
      GetShorty();
    }
    return shorty_len_;
  }
  const std::string GetSignature() {
    const DexFile& dex_file = GetDexFile();
    uint32_t dex_method_idx = method_->GetDexMethodIndex();
    if (dex_method_idx != DexFile::kDexNoIndex16) {
      return dex_file.GetMethodSignature(dex_file.GetMethodId(dex_method_idx));
    } else {
      return "<no signature>";
    }
  }
  const DexFile::ProtoId& GetPrototype() {
    const DexFile& dex_file = GetDexFile();
    return dex_file.GetMethodPrototype(dex_file.GetMethodId(method_->GetDexMethodIndex()));
  }
  const DexFile::TypeList* GetParameterTypeList() {
    const DexFile::ProtoId& proto = GetPrototype();
    return GetDexFile().GetProtoParameters(proto);
  }
  ObjectArray<Class>* GetParameterTypes() {
    const DexFile::TypeList* params = GetParameterTypeList();
    Class* array_class = GetClassLinker()->FindSystemClass("[Ljava/lang/Class;");
    uint32_t num_params = params == NULL ? 0 : params->Size();
    ObjectArray<Class>* result = ObjectArray<Class>::Alloc(array_class, num_params);
    for (uint32_t i = 0; i < num_params; i++) {
      Class* param_type = GetClassFromTypeIdx(params->GetTypeItem(i).type_idx_);
      result->Set(i, param_type);
    }
    return result;
  }
  Class* GetReturnType() {
    const DexFile& dex_file = GetDexFile();
    const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
    const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
    uint16_t return_type_idx = proto_id.return_type_idx_;
    return GetClassFromTypeIdx(return_type_idx);
  }
  const char* GetReturnTypeDescriptor() {
    const DexFile& dex_file = GetDexFile();
    const DexFile::MethodId& method_id = dex_file.GetMethodId(method_->GetDexMethodIndex());
    const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(method_id);
    uint16_t return_type_idx = proto_id.return_type_idx_;
    return dex_file.GetTypeDescriptor(dex_file.GetTypeId(return_type_idx));
  }
  int32_t GetLineNumFromNativePC(uintptr_t raw_pc) {
    const DexFile& dex_file = GetDexFile();
    return dex_file.GetLineNumFromPC(method_, method_->ToDexPC(raw_pc));
  }
  const char* GetDeclaringClassDescriptor() {
    Class* klass = method_->GetDeclaringClass();
    DCHECK(!klass->IsProxyClass());
    uint16_t type_idx = klass->GetDexTypeIndex();
    const DexFile& dex_file = GetDexFile();
    return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
  }
  const char* GetDeclaringClassSourceFile() {
    const char* descriptor = GetDeclaringClassDescriptor();
    const DexFile& dex_file = GetDexFile();
    const DexFile::ClassDef* dex_class_def = dex_file.FindClassDef(descriptor);
    CHECK(dex_class_def != NULL);
    return dex_file.GetSourceFile(*dex_class_def);
  }
  bool IsStatic() {
    return method_->IsStatic();
  }
  bool IsClassInitializer() {
    return IsStatic() && StringPiece(GetName()) == "<clinit>";
  }
  size_t NumArgs() {
    // "1 +" because the first in Args is the receiver.
    // "- 1" because we don't count the return type.
    return (IsStatic() ? 0 : 1) + GetShortyLength() - 1;
  }
  // Is the specified parameter a long or double, where parameter 0 is 'this' for instance methods
  bool IsParamALongOrDouble(size_t param) {
    CHECK_LT(param, NumArgs());
    if (IsStatic()) {
      param++;  // 0th argument must skip return value at start of the shorty
    } else if (param == 0) {
      return false;  // this argument
    }
    char ch = GetShorty()[param];
    return (ch == 'J' || ch == 'D');
  }
  // Is the specified parameter a reference, where parameter 0 is 'this' for instance methods
  bool IsParamAReference(size_t param) {
    CHECK_LT(param, NumArgs());
    if (IsStatic()) {
      param++;  // 0th argument must skip return value at start of the shorty
    } else if (param == 0) {
      return true;  // this argument
    }
    return GetShorty()[param] == 'L';  // An array also has a shorty character of 'L' (not '[')
  }
  bool HasSameNameAndSignature(MethodHelper* other) {
    if (GetDexCache() == other->GetDexCache()) {
      const DexFile& dex_file = GetDexFile();
      const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
      const DexFile::MethodId& other_mid =
          dex_file.GetMethodId(other->method_->GetDexMethodIndex());
      return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
    }
    StringPiece name(GetName());
    StringPiece other_name(other->GetName());
    return name == other_name && GetSignature() == other->GetSignature();
  }
  const DexFile::CodeItem* GetCodeItem() {
    return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());
  }
  bool IsResolvedTypeIdx(uint16_t type_idx) const {
    return method_->GetDexCacheResolvedTypes()->Get(type_idx) != NULL;
  }
  Class* GetClassFromTypeIdx(uint16_t type_idx) {
    Class* type = method_->GetDexCacheResolvedTypes()->Get(type_idx);
    if (type == NULL) {
      type = GetClassLinker()->ResolveType(type_idx, method_);
      CHECK(type != NULL || Thread::Current()->IsExceptionPending());
    }
    return type;
  }
  const char* GetTypeDescriptorFromTypeIdx(uint16_t type_idx) {
    const DexFile& dex_file = GetDexFile();
    return dex_file.GetTypeDescriptor(dex_file.GetTypeId(type_idx));
  }
  Class* GetDexCacheResolvedType(uint16_t type_idx) {
    return GetDexCache()->GetResolvedType(type_idx);
  }
  const DexFile& GetDexFile() {
    const DexFile* result = dex_file_;
    if (result == NULL) {
      const DexCache* dex_cache = GetDexCache();
      result = &GetClassLinker()->FindDexFile(dex_cache);
      dex_file_ = result;
    }
    return *result;
  }
 private:
  // Set the method_ field, for proxy methods looking up the interface method via the resolved
  // methods table.
  void SetMethod(const Method* method) {
    if (method != NULL) {
      Class* klass = method->GetDeclaringClass();
      if (klass->IsProxyClass()) {
        Method* interface_method =
            method->GetDexCacheResolvedMethods()->Get(method->GetDexMethodIndex());
        CHECK(interface_method != NULL);
        CHECK(interface_method == GetClassLinker()->FindMethodForProxy(klass, method));
        method = interface_method;
      }
    }
    method_ = method;
  }
  DexCache* GetDexCache() {
    DexCache* result = dex_cache_;
    if (result == NULL) {
      Class* klass = method_->GetDeclaringClass();
      result = klass->GetDexCache();
      dex_cache_ = result;
    }
    return result;
  }
  ClassLinker* GetClassLinker() {
    ClassLinker* result = class_linker_;
    if (result == NULL) {
      result = Runtime::Current()->GetClassLinker();
      class_linker_ = result;
    }
    return result;
  }

  ClassLinker* class_linker_;
  DexCache* dex_cache_;
  const DexFile* dex_file_;
  const Method* method_;
  const char* shorty_;
  uint32_t shorty_len_;

  DISALLOW_COPY_AND_ASSIGN(MethodHelper);
};

}  // namespace art

#endif  // ART_SRC_OBJECT_UTILS_H_
