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