From cc5ebdf29ea47e24e79279169e0192dfc08b38c8 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Mon, 27 Jul 2015 11:19:43 -0700 Subject: Split the class table for each class loader Each class loader now has its own class table. This makes it easier to mark classes when a classloader is marked. Fixed a bug in LookupClass where we used to look ignore the return value of InsertClass. Bug: 22720414 Change-Id: If2cd717989a20a6e245ebec24ad52dc47dd3207d --- runtime/class_table.h | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 runtime/class_table.h (limited to 'runtime/class_table.h') diff --git a/runtime/class_table.h b/runtime/class_table.h new file mode 100644 index 0000000000..af25131ab4 --- /dev/null +++ b/runtime/class_table.h @@ -0,0 +1,117 @@ +/* + * 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 +#include +#include + +#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 + +typedef bool (ClassVisitor)(mirror::Class* c, void* arg); + +// 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 REQUIRES(Locks::classlinker_classes_lock_); + + // Returns all off the classes in the lastest snapshot. + size_t NumNonZygoteClasses() const 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_); + + void VisitRoots(RootVisitor* visitor, VisitRootFlags flags) + REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); + + // Return false if the callback told us to exit. + bool Visit(ClassVisitor* visitor, void* arg) + REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(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_); + + private: + class ClassDescriptorHashEquals { + public: + // Same class loader and descriptor. + std::size_t operator()(const GcRoot& root) const NO_THREAD_SAFETY_ANALYSIS; + bool operator()(const GcRoot& a, const GcRoot& b) const + NO_THREAD_SAFETY_ANALYSIS;; + // Same descriptor. + bool operator()(const GcRoot& a, const char* descriptor) const + NO_THREAD_SAFETY_ANALYSIS; + std::size_t operator()(const char* descriptor) const NO_THREAD_SAFETY_ANALYSIS; + }; + class GcRootEmptyFn { + public: + void MakeEmpty(GcRoot& item) const { + item = GcRoot(); + } + bool IsEmpty(const GcRoot& item) const { + return item.IsNull(); + } + }; + // hash set which hashes class descriptor, and compares descriptors nad class loaders. Results + // should be compared for a matching Class descriptor and class loader. + typedef HashSet, GcRootEmptyFn, ClassDescriptorHashEquals, + ClassDescriptorHashEquals, TrackingAllocator, kAllocatorTagClassTable>> + ClassSet; + + // TODO: shard lock to have one per class loader. + std::vector classes_ GUARDED_BY(Locks::classlinker_classes_lock_); +}; + +} // namespace art + +#endif // ART_RUNTIME_CLASS_TABLE_H_ -- cgit v1.2.3-59-g8ed1b