/*
 * 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_RUNTIME_CLASS_LINKER_INL_H_
#define ART_RUNTIME_CLASS_LINKER_INL_H_

#include <atomic>

#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/mutex.h"
#include "class_linker.h"
#include "dex/dex_file.h"
#include "dex/dex_file_structs.h"
#include "gc_root-inl.h"
#include "handle_scope-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/iftable.h"
#include "mirror/object_array-inl.h"
#include "obj_ptr-inl.h"
#include "scoped_thread_state_change-inl.h"

namespace art {

inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
                                                         ObjPtr<mirror::Class> element_class) {
  for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
    // Read the cached array class once to avoid races with other threads setting it.
    ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
    if (array_class != nullptr && array_class->GetComponentType() == element_class) {
      return array_class;
    }
  }
  std::string descriptor = "[";
  std::string temp;
  descriptor += element_class->GetDescriptor(&temp);
  StackHandleScope<1> hs(Thread::Current());
  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
  ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
  if (array_class != nullptr) {
    // Benign races in storing array class and incrementing index.
    size_t victim_index = find_array_class_cache_next_victim_;
    find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
    find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
  } else {
    // We should have a NoClassDefFoundError.
    self->AssertPendingException();
  }
  return array_class;
}

inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
                                                         ArtField* referrer) {
  Thread::PoisonObjectPointersIfDebug();
  DCHECK(!Thread::Current()->IsExceptionPending());
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::String> resolved =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
  if (resolved == nullptr) {
    resolved = DoResolveString(string_idx, referrer->GetDexCache());
  }
  return resolved;
}

inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
                                                         ArtMethod* referrer) {
  Thread::PoisonObjectPointersIfDebug();
  DCHECK(!Thread::Current()->IsExceptionPending());
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::String> resolved =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
  if (resolved == nullptr) {
    resolved = DoResolveString(string_idx, referrer->GetDexCache());
  }
  return resolved;
}

inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
                                                         Handle<mirror::DexCache> dex_cache) {
  Thread::PoisonObjectPointersIfDebug();
  DCHECK(!Thread::Current()->IsExceptionPending());
  ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
  if (resolved == nullptr) {
    resolved = DoResolveString(string_idx, dex_cache);
  }
  return resolved;
}

inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
                                                        ObjPtr<mirror::DexCache> dex_cache) {
  ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
  if (resolved == nullptr) {
    resolved = DoLookupString(string_idx, dex_cache);
  }
  return resolved;
}

inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
                                                      ObjPtr<mirror::Class> referrer) {
  if (kObjPtrPoisoning) {
    StackHandleScope<1> hs(Thread::Current());
    HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
    Thread::Current()->PoisonObjectPointers();
  }
  DCHECK(!Thread::Current()->IsExceptionPending());
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> resolved_type =
      referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (resolved_type == nullptr) {
    resolved_type = DoResolveType(type_idx, referrer);
  }
  return resolved_type;
}

inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
                                                      ArtField* referrer) {
  Thread::PoisonObjectPointersIfDebug();
  DCHECK(!Thread::Current()->IsExceptionPending());
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> resolved_type =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (UNLIKELY(resolved_type == nullptr)) {
    resolved_type = DoResolveType(type_idx, referrer);
  }
  return resolved_type;
}

inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
                                                      ArtMethod* referrer) {
  Thread::PoisonObjectPointersIfDebug();
  DCHECK(!Thread::Current()->IsExceptionPending());
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> resolved_type =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (UNLIKELY(resolved_type == nullptr)) {
    resolved_type = DoResolveType(type_idx, referrer);
  }
  return resolved_type;
}

inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
                                                      Handle<mirror::DexCache> dex_cache,
                                                      Handle<mirror::ClassLoader> class_loader) {
  DCHECK(dex_cache != nullptr);
  Thread::PoisonObjectPointersIfDebug();
  ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
  if (resolved == nullptr) {
    resolved = DoResolveType(type_idx, dex_cache, class_loader);
  }
  return resolved;
}

inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
                                                             ObjPtr<mirror::Class> referrer) {
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> type =
      referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (type == nullptr) {
    type = DoLookupResolvedType(type_idx, referrer);
  }
  return type;
}

inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
                                                             ArtField* referrer) {
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> type =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (type == nullptr) {
    type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
  }
  return type;
}

inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
                                                             ArtMethod* referrer) {
  // We do not need the read barrier for getting the DexCache for the initial resolved type
  // lookup as both from-space and to-space copies point to the same native resolved types array.
  ObjPtr<mirror::Class> type =
      referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
  if (type == nullptr) {
    type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
  }
  return type;
}

inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
    dex::TypeIndex type_idx,
    ObjPtr<mirror::DexCache> dex_cache,
    ObjPtr<mirror::ClassLoader> class_loader) {
  ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
  if (type == nullptr) {
    type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
  }
  return type;
}

template <bool kThrowOnError, typename ClassGetter>
inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
                                                  InvokeType type,
                                                  ClassGetter class_getter) {
  switch (type) {
    case kStatic:
    case kSuper:
      break;
    case kInterface: {
      // We have to check whether the method id really belongs to an interface (dex static bytecode
      // constraints A15, A16). Otherwise you must not invoke-interface on it.
      ObjPtr<mirror::Class> klass = class_getter();
      if (UNLIKELY(!klass->IsInterface())) {
        if (kThrowOnError) {
          ThrowIncompatibleClassChangeError(klass,
                                            "Found class %s, but interface was expected",
                                            klass->PrettyDescriptor().c_str());
        }
        return true;
      }
      break;
    }
    case kDirect:
      if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
        break;
      }
      FALLTHROUGH_INTENDED;
    case kVirtual: {
      // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
      // a non-interface class (dex static bytecode constraint A24, A25).
      ObjPtr<mirror::Class> klass = class_getter();
      if (UNLIKELY(klass->IsInterface())) {
        if (kThrowOnError) {
          ThrowIncompatibleClassChangeError(klass,
                                            "Found interface %s, but class was expected",
                                            klass->PrettyDescriptor().c_str());
        }
        return true;
      }
      break;
    }
    default:
      LOG(FATAL) << "Unreachable - invocation type: " << type;
      UNREACHABLE();
  }
  return false;
}

template <bool kThrow>
inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
                                                  InvokeType type,
                                                  uint32_t method_idx,
                                                  ObjPtr<mirror::ClassLoader> class_loader) {
  return CheckInvokeClassMismatch<kThrow>(
      dex_cache,
      type,
      [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
        const dex::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
        ObjPtr<mirror::Class> klass =
            LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
        DCHECK(klass != nullptr);
        return klass;
      });
}

inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
                                                    ObjPtr<mirror::DexCache> dex_cache,
                                                    ObjPtr<mirror::ClassLoader> class_loader) {
  PointerSize pointer_size = image_pointer_size_;
  ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
  if (resolved == nullptr) {
    const DexFile& dex_file = *dex_cache->GetDexFile();
    const dex::MethodId& method_id = dex_file.GetMethodId(method_idx);
    ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
    if (klass != nullptr) {
      resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
    }
  }
  return resolved;
}

template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
  DCHECK(referrer != nullptr);
  // Note: The referrer can be a Proxy constructor. In that case, we need to do the
  // lookup in the context of the original method from where it steals the code.
  // However, we delay the GetInterfaceMethodIfProxy() until needed.
  DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
  // We do not need the read barrier for getting the DexCache for the initial resolved method
  // lookup as both from-space and to-space copies point to the same native resolved methods array.
  ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
      method_idx, image_pointer_size_);
  if (resolved_method == nullptr) {
    return nullptr;
  }
  DCHECK(!resolved_method->IsRuntimeMethod());
  if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
    referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    // Check if the invoke type matches the class type.
    ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
    ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
    if (CheckInvokeClassMismatch</* kThrow= */ false>(dex_cache, type, method_idx, class_loader)) {
      return nullptr;
    }
    // Check access.
    ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
                                                  resolved_method,
                                                  dex_cache,
                                                  method_idx)) {
      return nullptr;
    }
    // Check if the invoke type matches the method type.
    if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
      return nullptr;
    }
  }
  return resolved_method;
}

template <ClassLinker::ResolveMode kResolveMode>
inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
                                             uint32_t method_idx,
                                             ArtMethod* referrer,
                                             InvokeType type) {
  DCHECK(referrer != nullptr);
  // Note: The referrer can be a Proxy constructor. In that case, we need to do the
  // lookup in the context of the original method from where it steals the code.
  // However, we delay the GetInterfaceMethodIfProxy() until needed.
  DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
  Thread::PoisonObjectPointersIfDebug();
  // We do not need the read barrier for getting the DexCache for the initial resolved method
  // lookup as both from-space and to-space copies point to the same native resolved methods array.
  ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
      method_idx, image_pointer_size_);
  DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
  if (UNLIKELY(resolved_method == nullptr)) {
    referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
    StackHandleScope<2> hs(self);
    Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
    Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
    resolved_method = ResolveMethod<kResolveMode>(method_idx,
                                                  h_dex_cache,
                                                  h_class_loader,
                                                  referrer,
                                                  type);
  } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
    referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    // Check if the invoke type matches the class type.
    ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
    ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
    if (CheckInvokeClassMismatch</* kThrow= */ true>(dex_cache, type, method_idx, class_loader)) {
      DCHECK(Thread::Current()->IsExceptionPending());
      return nullptr;
    }
    // Check access.
    ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
                                                    resolved_method,
                                                    dex_cache,
                                                    method_idx,
                                                    type)) {
      DCHECK(Thread::Current()->IsExceptionPending());
      return nullptr;
    }
    // Check if the invoke type matches the method type.
    if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
      ThrowIncompatibleClassChangeError(type,
                                        resolved_method->GetInvokeType(),
                                        resolved_method,
                                        referrer);
      return nullptr;
    }
  }
  // Note: We cannot check here to see whether we added the method to the cache. It
  //       might be an erroneous class, which results in it being hidden from us.
  return resolved_method;
}

inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
                                                  ArtMethod* referrer,
                                                  bool is_static) {
  // We do not need the read barrier for getting the DexCache for the initial resolved field
  // lookup as both from-space and to-space copies point to the same native resolved fields array.
  ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
      field_idx, image_pointer_size_);
  if (field == nullptr) {
    ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
    field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
  }
  return field;
}

inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
                                           ArtMethod* referrer,
                                           bool is_static) {
  Thread::PoisonObjectPointersIfDebug();
  // We do not need the read barrier for getting the DexCache for the initial resolved field
  // lookup as both from-space and to-space copies point to the same native resolved fields array.
  ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
      field_idx, image_pointer_size_);
  if (UNLIKELY(resolved_field == nullptr)) {
    StackHandleScope<2> hs(Thread::Current());
    ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
    Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
    resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
    // Note: We cannot check here to see whether we added the field to the cache. The type
    //       might be an erroneous class, which results in it being hidden from us.
  }
  return resolved_field;
}

template <class Visitor>
inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
  Thread* const self = Thread::Current();
  WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
  for (const ClassLoaderData& data : class_loaders_) {
    if (data.class_table != nullptr) {
      visitor(data.class_table);
    }
  }
}

template <ReadBarrierOption kReadBarrierOption>
inline ObjPtr<mirror::ObjectArray<mirror::Class>> ClassLinker::GetClassRoots() {
  ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
      class_roots_.Read<kReadBarrierOption>();
  DCHECK(class_roots != nullptr);
  return class_roots;
}

}  // namespace art

#endif  // ART_RUNTIME_CLASS_LINKER_INL_H_
