class StringHash { public: // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions.
size_t operator()(const GcRoot<mirror::String>& root) const NO_THREAD_SAFETY_ANALYSIS;
// Utf8String can be used for lookup. While we're passing the hash explicitly to all // `HashSet<>` functions, they `DCHECK()` the supplied hash against the hash we provide here.
size_t operator()(const Utf8String& key) const {
static_assert(std::is_same_v<uint32_t, decltype(key.GetHash())>); return key.GetHash();
}
};
class StringEquals { public: // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions. booloperator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
NO_THREAD_SAFETY_ANALYSIS;
// Utf8String can be used for lookup. // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions. booloperator()(const GcRoot<mirror::String>& a, const Utf8String& b) const
NO_THREAD_SAFETY_ANALYSIS;
};
using UnorderedSet =
HashSet<GcRoot<mirror::String>,
GcRootEmptyFn,
StringHash,
StringEquals,
GcRootArenaAllocator<GcRoot<mirror::String>, kAllocatorTagInternTable>>;
EXPORT InternTable();
// Interns a potentially new string in the 'strong' table. May cause thread suspension.
EXPORT ObjPtr<mirror::String> InternStrong(uint32_t utf16_length, constchar* utf8_data)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Interns a potentially new string in the 'strong' table. May cause thread suspension.
ObjPtr<mirror::String> InternStrong(ObjPtr<mirror::String> s)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Interns a potentially new string in the 'weak' table. May cause thread suspension.
ObjPtr<mirror::String> InternWeak(uint32_t utf16_length, constchar* utf8_data)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Interns a potentially new string in the 'weak' table. May cause thread suspension.
EXPORT ObjPtr<mirror::String> InternWeak(ObjPtr<mirror::String> s)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Visit all of the interns in the table. template <typename Visitor> void VisitInterns(const Visitor& visitor, bool visit_boot_images, bool visit_non_boot_images)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
// Count the number of intern strings in the table.
size_t CountInterns(bool visit_boot_images, bool visit_non_boot_images) const
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
// Add all of the strings in the image's intern table into this intern table. This is required so // the intern table is correct. // The visitor arg type is UnorderedSet template <typename Visitor> void AddImageStringsToTable(gc::space::ImageSpace* image_space, const Visitor& visitor)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
// Add a new intern table for inserting to, previous intern tables are still there but no // longer inserted into and ideally unmodified. This is done to prevent dirty pages. void AddNewTable()
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
// Change the weak root state. May broadcast to waiters. void ChangeWeakRootState(gc::WeakRootState new_state)
REQUIRES(!Locks::intern_table_lock_);
private: // Table which holds pre zygote and post zygote interned strings. There is one instance for // weak interns and strong interns. class Table { public: class InternalTable { public:
InternalTable() = default;
InternalTable(UnorderedSet&& set, bool is_boot_image)
: set_(std::move(set)), is_boot_image_(is_boot_image) {}
Table();
ObjPtr<mirror::String> Find(ObjPtr<mirror::String> s,
uint32_t hash,
size_t num_searched_frozen_tables = 0u)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
ObjPtr<mirror::String> Find(const Utf8String& string, uint32_t hash)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); void Insert(ObjPtr<mirror::String> s, uint32_t hash)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); void Remove(ObjPtr<mirror::String> s, uint32_t hash)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); void VisitRoots(RootVisitor* visitor)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); void SweepWeaks(IsMarkedVisitor* visitor)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_); // Add a new intern table that will only be inserted into from now on. void AddNewTable() REQUIRES(Locks::intern_table_lock_);
size_t Size() const REQUIRES(Locks::intern_table_lock_); // Read and add an intern table from ptr. // Tables read are inserted at the front of the table array. Only checks for conflicts in // debug builds. Returns how many bytes were read. // NO_THREAD_SAFETY_ANALYSIS for the visitor that may require locks. template <typename Visitor>
size_t AddTableFromMemory(const uint8_t* ptr, const Visitor& visitor, bool is_boot_image)
REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
// Add a table to the front of the tables vector. void AddInternStrings(UnorderedSet&& intern_strings, bool is_boot_image)
REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
// We call AddNewTable when we create the zygote to reduce private dirty pages caused by // modifying the zygote intern table. The back of table is modified when strings are interned.
dchecked_vector<InternalTable> tables_;
// Insert if non null, otherwise return null. Must be called holding the mutator lock.
ObjPtr<mirror::String> Insert(ObjPtr<mirror::String> s,
uint32_t hash, bool is_strong,
size_t num_searched_strong_frozen_tables = 0u)
REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
// Add a table from memory to the strong interns. template <typename Visitor>
size_t AddTableFromMemory(const uint8_t* ptr, const Visitor& visitor, bool is_boot_image)
REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
// Helper function for `InternStrong()` and `InternWeak()` with `utf16_length` and `utf8_data`.
ObjPtr<mirror::String> Intern(uint32_t utf16_length, constchar* utf8_data, bool is_strong)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Change the weak root state. May broadcast to waiters. void ChangeWeakRootStateLocked(gc::WeakRootState new_state)
REQUIRES(Locks::intern_table_lock_);
// Wait until we can read weak roots. void WaitUntilAccessible(Thread* self)
REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
bool log_new_roots_ GUARDED_BY(Locks::intern_table_lock_);
ConditionVariable weak_intern_condition_ GUARDED_BY(Locks::intern_table_lock_); // Since this contains (strong) roots, they need a read barrier to // enable concurrent intern table (strong) root scan. Do not // directly access the strings in it. Use functions that contain // read barriers.
Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_);
dchecked_vector<GcRoot<mirror::String>> new_strong_intern_roots_
GUARDED_BY(Locks::intern_table_lock_); // Since this contains (weak) roots, they need a read barrier. Do // not directly access the strings in it. Use functions that contain // read barriers.
Table weak_interns_ GUARDED_BY(Locks::intern_table_lock_); // Weak root state, used for concurrent system weak processing and more.
gc::WeakRootState weak_root_state_ GUARDED_BY(Locks::intern_table_lock_);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.