/*
 * Copyright (C) 2015 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_TABLE_H_
#define ART_RUNTIME_CLASS_TABLE_H_

#include <string>
#include <utility>
#include <vector>

#include "base/gc_visited_arena_pool.h"
#include "base/hash_set.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "gc_root.h"
#include "obj_ptr.h"

namespace art HIDDEN {

class OatFile;

namespace linker {
class ImageWriter;
}  // namespace linker

namespace linker {
class OatWriter;
}  // namespace linker

namespace mirror {
class Class;
class ClassLoader;
class Object;
}  // namespace mirror

// Each loader has a ClassTable
class ClassTable {
 public:
  class TableSlot {
   public:
    TableSlot() : data_(0u) {}

    TableSlot(const TableSlot& copy) : data_(copy.data_.load(std::memory_order_relaxed)) {}

    explicit TableSlot(ObjPtr<mirror::Class> klass);

    TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
    TableSlot(uint32_t ptr, uint32_t descriptor_hash);

    TableSlot& operator=(const TableSlot& copy) {
      data_.store(copy.data_.load(std::memory_order_relaxed), std::memory_order_relaxed);
      return *this;
    }

    uint32_t Data() const {
      return data_.load(std::memory_order_relaxed);
    }

    bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_);

    uint32_t Hash() const {
      return MaskHash(data_.load(std::memory_order_relaxed));
    }

    uint32_t NonHashData() const {
      return RemoveHash(Data());
    }

    static uint32_t RemoveHash(uint32_t hash) {
      return hash & ~kHashMask;
    }

    static uint32_t MaskHash(uint32_t hash) {
      return hash & kHashMask;
    }

    bool MaskedHashEquals(uint32_t other) const {
      return MaskHash(other) == Hash();
    }

    template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
    ObjPtr<mirror::Class> Read() const REQUIRES_SHARED(Locks::mutator_lock_);

    // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
    template<typename Visitor>
    void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;

    template<typename Visitor>
    class ClassAndRootVisitor;

   private:
    // Extract a raw pointer from an address.
    static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
        REQUIRES_SHARED(Locks::mutator_lock_);

    static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
        REQUIRES_SHARED(Locks::mutator_lock_);

    // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
    mutable Atomic<uint32_t> data_;
    static constexpr uint32_t kHashMask = kObjectAlignment - 1;
  };

  using DescriptorHashPair = std::pair<std::string_view, uint32_t>;

  class ClassDescriptorHash {
   public:
    // uint32_t for cross compilation. Requires mutator lock, but caller is not properly annotated.
    uint32_t operator()(const TableSlot& slot) const;
    // uint32_t for cross compilation.
    uint32_t operator()(const DescriptorHashPair& pair) const;
  };

  class ClassDescriptorEquals {
   public:
    // Same class loader and descriptor.
    bool operator()(const TableSlot& a, const TableSlot& b) const
        NO_THREAD_SAFETY_ANALYSIS;
    // Same descriptor.
    bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
        NO_THREAD_SAFETY_ANALYSIS;
  };

  class TableSlotEmptyFn {
   public:
    void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
      item = TableSlot();
      DCHECK(IsEmpty(item));
    }
    bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
      return item.IsNull();
    }
  };

  // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
  // should be compared for a matching class descriptor and class loader.
  using ClassSet = HashSet<TableSlot,
                           TableSlotEmptyFn,
                           ClassDescriptorHash,
                           ClassDescriptorEquals,
                           GcRootArenaAllocator<TableSlot, kAllocatorTagClassTable>>;

  EXPORT ClassTable();

  // Freeze the current class tables by allocating a new table and never updating or modifying the
  // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
  void FreezeSnapshot()
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns the number of classes in previous snapshots defined by `defining_loader`.
  size_t NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns all off the classes in the lastest snapshot defined by `defining_loader`.
  size_t NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns the number of classes in previous snapshots no matter the defining loader.
  EXPORT size_t NumReferencedZygoteClasses() const
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns all off the classes in the lastest snapshot no matter the defining loader.
  size_t NumReferencedNonZygoteClasses() const
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Returns the number of class-sets in the class table.
  size_t Size() const
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Update a class in the table with the new class. Returns the existing class which was replaced.
  ObjPtr<mirror::Class> UpdateClass(ObjPtr<mirror::Class> new_klass, size_t hash)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
  template <class Visitor>
  void VisitRoots(Visitor& visitor, bool skip_classes = false) NO_THREAD_SAFETY_ANALYSIS
      REQUIRES(!lock_) REQUIRES_SHARED(Locks::mutator_lock_);

  template <class Visitor>
  void VisitRoots(const Visitor& visitor, bool skip_classes = false) NO_THREAD_SAFETY_ANALYSIS
      REQUIRES(!lock_) REQUIRES_SHARED(Locks::mutator_lock_);

  template<class Visitor>
  void VisitClassesAndRoots(Visitor& visitor)
      NO_THREAD_SAFETY_ANALYSIS
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Visit classes in those class-sets which satisfy 'cond'.
  template <class Condition, class Visitor>
  void VisitClassesIfConditionMet(Condition& cond, Visitor& visitor) REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  // Stops visit if the visitor returns false.
  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
  bool Visit(Visitor& visitor)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);
  template <ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename Visitor>
  bool Visit(const Visitor& visitor)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return the first class that matches the descriptor. Returns null if there are none.
  ObjPtr<mirror::Class> Lookup(std::string_view descriptor, size_t hash)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return the first class that matches the descriptor of klass. Returns null if there are none.
  // Used for tests and debug-build checks.
  ObjPtr<mirror::Class> LookupByDescriptor(ObjPtr<mirror::Class> klass)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void Insert(ObjPtr<mirror::Class> klass)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return true if we inserted the strong root, false if it already exists.
  bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return true if we inserted the oat file, false if it already exists.
  bool InsertOatFile(const OatFile* oat_file)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Read a table from ptr and put it at the front of the class set.
  EXPORT size_t ReadFromMemory(uint8_t* ptr)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Add a class set to the front of classes.
  void AddClassSet(ClassSet&& set)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Clear strong roots (other than classes themselves).
  void ClearStrongRoots()
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Filter strong roots (other than classes themselves).
  template <typename Filter>
  void RemoveStrongRoots(const Filter& filter)
      REQUIRES(!lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  ReaderWriterMutex& GetLock() {
    return lock_;
  }

 private:
  size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
                                    const ClassSet& set) const
      REQUIRES(lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Return true if we inserted the oat file, false if it already exists.
  bool InsertOatFileLocked(const OatFile* oat_file)
      REQUIRES(lock_)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Lock to guard inserting and removing.
  mutable ReaderWriterMutex lock_;
  // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
  std::vector<ClassSet> classes_ GUARDED_BY(lock_);
  // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
  // loader which may not be owned by the class loader must be held strongly live. Also dex caches
  // are held live to prevent them being unloading once they have classes in them.
  std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
  // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
  std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);

  friend class linker::ImageWriter;  // for InsertWithoutLocks.
};

}  // namespace art

#endif  // ART_RUNTIME_CLASS_TABLE_H_
