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