|  | /* | 
|  | * 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/allocator.h" | 
|  | #include "base/hash_set.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/mutex.h" | 
|  | #include "dex_file.h" | 
|  | #include "gc_root.h" | 
|  | #include "object_callbacks.h" | 
|  | #include "runtime.h" | 
|  |  | 
|  | namespace art { | 
|  |  | 
|  | namespace mirror { | 
|  | class ClassLoader; | 
|  | }  // namespace mirror | 
|  |  | 
|  | class ClassVisitor { | 
|  | public: | 
|  | virtual ~ClassVisitor() {} | 
|  | // Return true to continue visiting. | 
|  | virtual bool Visit(mirror::Class* klass) = 0; | 
|  | }; | 
|  |  | 
|  | // Each loader has a ClassTable | 
|  | class ClassTable { | 
|  | public: | 
|  | ClassTable(); | 
|  |  | 
|  | // Used by image writer for checking. | 
|  | bool Contains(mirror::Class* klass) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // 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(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // Returns the number of classes in previous snapshots. | 
|  | size_t NumZygoteClasses() const SHARED_REQUIRES(Locks::classlinker_classes_lock_); | 
|  |  | 
|  | // Returns all off the classes in the lastest snapshot. | 
|  | size_t NumNonZygoteClasses() const SHARED_REQUIRES(Locks::classlinker_classes_lock_); | 
|  |  | 
|  | // Update a class in the table with the new class. Returns the existing class which was replaced. | 
|  | mirror::Class* UpdateClass(const char* descriptor, mirror::Class* new_klass, size_t hash) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // NO_THREAD_SAFETY_ANALYSIS for object marking requiring heap bitmap lock. | 
|  | template<class Visitor> | 
|  | void VisitRoots(Visitor& visitor) | 
|  | NO_THREAD_SAFETY_ANALYSIS | 
|  | SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_); | 
|  | template<class Visitor> | 
|  | void VisitRoots(const Visitor& visitor) | 
|  | NO_THREAD_SAFETY_ANALYSIS | 
|  | SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_); | 
|  |  | 
|  | // Return false if the callback told us to exit. | 
|  | bool Visit(ClassVisitor* visitor) | 
|  | SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_); | 
|  |  | 
|  | mirror::Class* Lookup(const char* descriptor, size_t hash) | 
|  | SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_); | 
|  |  | 
|  | void Insert(mirror::Class* klass) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  | void InsertWithHash(mirror::Class* klass, size_t hash) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // Returns true if the class was found and removed, false otherwise. | 
|  | bool Remove(const char* descriptor) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // Return true if we inserted the dex file, false if it already exists. | 
|  | bool InsertDexFile(mirror::Object* dex_file) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | // Combines all of the tables into one class set. | 
|  | size_t WriteToMemory(uint8_t* ptr) const | 
|  | SHARED_REQUIRES(Locks::classlinker_classes_lock_, Locks::mutator_lock_); | 
|  | size_t ReadFromMemory(uint8_t* ptr) | 
|  | REQUIRES(Locks::classlinker_classes_lock_) | 
|  | SHARED_REQUIRES(Locks::mutator_lock_); | 
|  |  | 
|  | private: | 
|  | class ClassDescriptorHashEquals { | 
|  | public: | 
|  | // uint32_t for cross compilation. | 
|  | uint32_t operator()(const GcRoot<mirror::Class>& root) const NO_THREAD_SAFETY_ANALYSIS; | 
|  | // Same class loader and descriptor. | 
|  | bool operator()(const GcRoot<mirror::Class>& a, const GcRoot<mirror::Class>& b) const | 
|  | NO_THREAD_SAFETY_ANALYSIS;; | 
|  | // Same descriptor. | 
|  | bool operator()(const GcRoot<mirror::Class>& a, const char* descriptor) const | 
|  | NO_THREAD_SAFETY_ANALYSIS; | 
|  | // uint32_t for cross compilation. | 
|  | uint32_t operator()(const char* descriptor) const NO_THREAD_SAFETY_ANALYSIS; | 
|  | }; | 
|  | class GcRootEmptyFn { | 
|  | public: | 
|  | void MakeEmpty(GcRoot<mirror::Class>& item) const { | 
|  | item = GcRoot<mirror::Class>(); | 
|  | } | 
|  | bool IsEmpty(const GcRoot<mirror::Class>& item) const { | 
|  | return item.IsNull(); | 
|  | } | 
|  | }; | 
|  | // hash set which hashes class descriptor, and compares descriptors and class loaders. Results | 
|  | // should be compared for a matching Class descriptor and class loader. | 
|  | typedef HashSet<GcRoot<mirror::Class>, GcRootEmptyFn, ClassDescriptorHashEquals, | 
|  | ClassDescriptorHashEquals, TrackingAllocator<GcRoot<mirror::Class>, kAllocatorTagClassTable>> | 
|  | ClassSet; | 
|  |  | 
|  | // TODO: shard lock to have one per class loader. | 
|  | // We have a vector to help prevent dirty pages after the zygote forks by calling FreezeSnapshot. | 
|  | std::vector<ClassSet> classes_ GUARDED_BY(Locks::classlinker_classes_lock_); | 
|  | // Dex files used by the class loader which may not be owned by the class loader. We keep these | 
|  | // live so that we do not have issues closing any of the dex files. | 
|  | std::vector<GcRoot<mirror::Object>> dex_files_ GUARDED_BY(Locks::classlinker_classes_lock_); | 
|  | }; | 
|  |  | 
|  | }  // namespace art | 
|  |  | 
|  | #endif  // ART_RUNTIME_CLASS_TABLE_H_ |