Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_CLASS_TABLE_H_
     18 #define ART_RUNTIME_CLASS_TABLE_H_
     19 
     20 #include <string>
     21 #include <utility>
     22 #include <vector>
     23 
     24 #include "base/allocator.h"
     25 #include "base/hash_set.h"
     26 #include "base/macros.h"
     27 #include "base/mutex.h"
     28 #include "gc_root.h"
     29 #include "obj_ptr.h"
     30 
     31 namespace art {
     32 
     33 class OatFile;
     34 
     35 namespace mirror {
     36   class Class;
     37   class ClassLoader;
     38   class Object;
     39 }  // namespace mirror
     40 
     41 // Each loader has a ClassTable
     42 class ClassTable {
     43  public:
     44   class TableSlot {
     45    public:
     46     TableSlot() : data_(0u) {}
     47 
     48     TableSlot(const TableSlot& copy) : data_(copy.data_.LoadRelaxed()) {}
     49 
     50     explicit TableSlot(ObjPtr<mirror::Class> klass);
     51 
     52     TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash);
     53 
     54     TableSlot& operator=(const TableSlot& copy) {
     55       data_.StoreRelaxed(copy.data_.LoadRelaxed());
     56       return *this;
     57     }
     58 
     59     bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
     60       return Read<kWithoutReadBarrier>() == nullptr;
     61     }
     62 
     63     uint32_t Hash() const {
     64       return MaskHash(data_.LoadRelaxed());
     65     }
     66 
     67     static uint32_t MaskHash(uint32_t hash) {
     68       return hash & kHashMask;
     69     }
     70 
     71     bool MaskedHashEquals(uint32_t other) const {
     72       return MaskHash(other) == Hash();
     73     }
     74 
     75     static uint32_t HashDescriptor(ObjPtr<mirror::Class> klass)
     76         REQUIRES_SHARED(Locks::mutator_lock_);
     77 
     78     template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
     79     mirror::Class* Read() const REQUIRES_SHARED(Locks::mutator_lock_);
     80 
     81     // NO_THREAD_SAFETY_ANALYSIS since the visitor may require heap bitmap lock.
     82     template<typename Visitor>
     83     void VisitRoot(const Visitor& visitor) const NO_THREAD_SAFETY_ANALYSIS;
     84 
     85    private:
     86     // Extract a raw pointer from an address.
     87     static ObjPtr<mirror::Class> ExtractPtr(uint32_t data)
     88         REQUIRES_SHARED(Locks::mutator_lock_);
     89 
     90     static uint32_t Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits)
     91         REQUIRES_SHARED(Locks::mutator_lock_);
     92 
     93     // Data contains the class pointer GcRoot as well as the low bits of the descriptor hash.
     94     mutable Atomic<uint32_t> data_;
     95     static const uint32_t kHashMask = kObjectAlignment - 1;
     96   };
     97 
     98   using DescriptorHashPair = std::pair<const char*, uint32_t>;
     99 
    100   class ClassDescriptorHashEquals {
    101    public:
    102     // uint32_t for cross compilation.
    103     uint32_t operator()(const TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS;
    104     // Same class loader and descriptor.
    105     bool operator()(const TableSlot& a, const TableSlot& b) const
    106         NO_THREAD_SAFETY_ANALYSIS;
    107     // Same descriptor.
    108     bool operator()(const TableSlot& a, const DescriptorHashPair& b) const
    109         NO_THREAD_SAFETY_ANALYSIS;
    110     // uint32_t for cross compilation.
    111     uint32_t operator()(const DescriptorHashPair& pair) const NO_THREAD_SAFETY_ANALYSIS;
    112   };
    113 
    114   class TableSlotEmptyFn {
    115    public:
    116     void MakeEmpty(TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
    117       item = TableSlot();
    118       DCHECK(IsEmpty(item));
    119     }
    120     bool IsEmpty(const TableSlot& item) const NO_THREAD_SAFETY_ANALYSIS {
    121       return item.IsNull();
    122     }
    123   };
    124 
    125   // Hash set that hashes class descriptor, and compares descriptors and class loaders. Results
    126   // should be compared for a matching class descriptor and class loader.
    127   typedef HashSet<TableSlot,
    128                   TableSlotEmptyFn,
    129                   ClassDescriptorHashEquals,
    130                   ClassDescriptorHashEquals,
    131                   TrackingAllocator<TableSlot, kAllocatorTagClassTable>> ClassSet;
    132 
    133   ClassTable();
    134 
    135   // Used by image writer for checking.
    136   bool Contains(ObjPtr<mirror::Class> klass)
    137       REQUIRES(!lock_)
    138       REQUIRES_SHARED(Locks::mutator_lock_);
    139 
    140   // Freeze the current class tables by allocating a new table and never updating or modifying the
    141   // existing table. This helps prevents dirty pages after caused by inserting after zygote fork.
    142   void FreezeSnapshot()
    143       REQUIRES(!lock_)
    144       REQUIRES_SHARED(Locks::mutator_lock_);
    145 
    146   // Returns the number of classes in previous snapshots defined by `defining_loader`.
    147   size_t NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
    148       REQUIRES(!lock_)
    149       REQUIRES_SHARED(Locks::mutator_lock_);
    150 
    151   // Returns all off the classes in the lastest snapshot defined by `defining_loader`.
    152   size_t NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const
    153       REQUIRES(!lock_)
    154       REQUIRES_SHARED(Locks::mutator_lock_);
    155 
    156   // Returns the number of classes in previous snapshots no matter the defining loader.
    157   size_t NumReferencedZygoteClasses() const
    158       REQUIRES(!lock_)
    159       REQUIRES_SHARED(Locks::mutator_lock_);
    160 
    161   // Returns all off the classes in the lastest snapshot no matter the defining loader.
    162   size_t NumReferencedNonZygoteClasses() const
    163       REQUIRES(!lock_)
    164       REQUIRES_SHARED(Locks::mutator_lock_);
    165 
    166   // Update a class in the table with the new class. Returns the existing class which was replaced.
    167   mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash)
    168       REQUIRES(!lock_)
    169       REQUIRES_SHARED(Locks::mutator_lock_);
    170 
    171   // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock.
    172   template<class Visitor>
    173   void VisitRoots(Visitor& visitor)
    174       NO_THREAD_SAFETY_ANALYSIS
    175       REQUIRES(!lock_)
    176       REQUIRES_SHARED(Locks::mutator_lock_);
    177 
    178   template<class Visitor>
    179   void VisitRoots(const Visitor& visitor)
    180       NO_THREAD_SAFETY_ANALYSIS
    181       REQUIRES(!lock_)
    182       REQUIRES_SHARED(Locks::mutator_lock_);
    183 
    184   // Stops visit if the visitor returns false.
    185   template <typename Visitor>
    186   bool Visit(Visitor& visitor)
    187       REQUIRES(!lock_)
    188       REQUIRES_SHARED(Locks::mutator_lock_);
    189   template <typename Visitor>
    190   bool Visit(const Visitor& visitor)
    191       REQUIRES(!lock_)
    192       REQUIRES_SHARED(Locks::mutator_lock_);
    193 
    194   // Return the first class that matches the descriptor. Returns null if there are none.
    195   mirror::Class* Lookup(const char* descriptor, size_t hash)
    196       REQUIRES(!lock_)
    197       REQUIRES_SHARED(Locks::mutator_lock_);
    198 
    199   // Return the first class that matches the descriptor of klass. Returns null if there are none.
    200   mirror::Class* LookupByDescriptor(ObjPtr<mirror::Class> klass)
    201       REQUIRES(!lock_)
    202       REQUIRES_SHARED(Locks::mutator_lock_);
    203 
    204   // Try to insert a class and return the inserted class if successful. If another class
    205   // with the same descriptor is already in the table, return the existing entry.
    206   ObjPtr<mirror::Class> TryInsert(ObjPtr<mirror::Class> klass)
    207       REQUIRES(!lock_)
    208       REQUIRES_SHARED(Locks::mutator_lock_);
    209 
    210   void Insert(ObjPtr<mirror::Class> klass)
    211       REQUIRES(!lock_)
    212       REQUIRES_SHARED(Locks::mutator_lock_);
    213 
    214   void InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash)
    215       REQUIRES(!lock_)
    216       REQUIRES_SHARED(Locks::mutator_lock_);
    217 
    218   // Returns true if the class was found and removed, false otherwise.
    219   bool Remove(const char* descriptor)
    220       REQUIRES(!lock_)
    221       REQUIRES_SHARED(Locks::mutator_lock_);
    222 
    223   // Return true if we inserted the strong root, false if it already exists.
    224   bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
    225       REQUIRES(!lock_)
    226       REQUIRES_SHARED(Locks::mutator_lock_);
    227 
    228   // Return true if we inserted the oat file, false if it already exists.
    229   bool InsertOatFile(const OatFile* oat_file)
    230       REQUIRES(!lock_)
    231       REQUIRES_SHARED(Locks::mutator_lock_);
    232 
    233   // Combines all of the tables into one class set.
    234   size_t WriteToMemory(uint8_t* ptr) const
    235       REQUIRES(!lock_)
    236       REQUIRES_SHARED(Locks::mutator_lock_);
    237 
    238   // Read a table from ptr and put it at the front of the class set.
    239   size_t ReadFromMemory(uint8_t* ptr)
    240       REQUIRES(!lock_)
    241       REQUIRES_SHARED(Locks::mutator_lock_);
    242 
    243   // Add a class set to the front of classes.
    244   void AddClassSet(ClassSet&& set)
    245       REQUIRES(!lock_)
    246       REQUIRES_SHARED(Locks::mutator_lock_);
    247 
    248   // Clear strong roots (other than classes themselves).
    249   void ClearStrongRoots()
    250       REQUIRES(!lock_)
    251       REQUIRES_SHARED(Locks::mutator_lock_);
    252 
    253   // Filter strong roots (other than classes themselves).
    254   template <typename Filter>
    255   void RemoveStrongRoots(const Filter& filter)
    256       REQUIRES(!lock_)
    257       REQUIRES_SHARED(Locks::mutator_lock_);
    258 
    259   ReaderWriterMutex& GetLock() {
    260     return lock_;
    261   }
    262 
    263  private:
    264   // Only copies classes.
    265   void CopyWithoutLocks(const ClassTable& source_table) NO_THREAD_SAFETY_ANALYSIS;
    266   void InsertWithoutLocks(ObjPtr<mirror::Class> klass) NO_THREAD_SAFETY_ANALYSIS;
    267 
    268   size_t CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
    269                                     const ClassSet& set) const
    270       REQUIRES(lock_)
    271       REQUIRES_SHARED(Locks::mutator_lock_);
    272 
    273   // Return true if we inserted the oat file, false if it already exists.
    274   bool InsertOatFileLocked(const OatFile* oat_file)
    275       REQUIRES(lock_)
    276       REQUIRES_SHARED(Locks::mutator_lock_);
    277 
    278   // Lock to guard inserting and removing.
    279   mutable ReaderWriterMutex lock_;
    280   // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot.
    281   std::vector<ClassSet> classes_ GUARDED_BY(lock_);
    282   // Extra strong roots that can be either dex files or dex caches. Dex files used by the class
    283   // loader which may not be owned by the class loader must be held strongly live. Also dex caches
    284   // are held live to prevent them being unloading once they have classes in them.
    285   std::vector<GcRoot<mirror::Object>> strong_roots_ GUARDED_BY(lock_);
    286   // Keep track of oat files with GC roots associated with dex caches in `strong_roots_`.
    287   std::vector<const OatFile*> oat_files_ GUARDED_BY(lock_);
    288 
    289   friend class ImageWriter;  // for InsertWithoutLocks.
    290 };
    291 
    292 }  // namespace art
    293 
    294 #endif  // ART_RUNTIME_CLASS_TABLE_H_
    295