xref: /aosp_15_r20/art/runtime/intern_table.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_INTERN_TABLE_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_INTERN_TABLE_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "base/dchecked_vector.h"
21*795d594fSAndroid Build Coastguard Worker #include "base/gc_visited_arena_pool.h"
22*795d594fSAndroid Build Coastguard Worker #include "base/hash_set.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
25*795d594fSAndroid Build Coastguard Worker #include "gc/weak_root_state.h"
26*795d594fSAndroid Build Coastguard Worker #include "gc_root.h"
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker class IsMarkedVisitor;
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker namespace gc {
33*795d594fSAndroid Build Coastguard Worker namespace space {
34*795d594fSAndroid Build Coastguard Worker class ImageSpace;
35*795d594fSAndroid Build Coastguard Worker }  // namespace space
36*795d594fSAndroid Build Coastguard Worker }  // namespace gc
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker enum VisitRootFlags : uint8_t;
39*795d594fSAndroid Build Coastguard Worker 
40*795d594fSAndroid Build Coastguard Worker namespace linker {
41*795d594fSAndroid Build Coastguard Worker class ImageWriter;
42*795d594fSAndroid Build Coastguard Worker }  // namespace linker
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker namespace mirror {
45*795d594fSAndroid Build Coastguard Worker class String;
46*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
47*795d594fSAndroid Build Coastguard Worker class Transaction;
48*795d594fSAndroid Build Coastguard Worker 
49*795d594fSAndroid Build Coastguard Worker /**
50*795d594fSAndroid Build Coastguard Worker  * Used to intern strings.
51*795d594fSAndroid Build Coastguard Worker  *
52*795d594fSAndroid Build Coastguard Worker  * There are actually two tables: one that holds strong references to its strings, and one that
53*795d594fSAndroid Build Coastguard Worker  * holds weak references. The former is used for string literals, for which there is an effective
54*795d594fSAndroid Build Coastguard Worker  * reference from the constant pool. The latter is used for strings interned at runtime via
55*795d594fSAndroid Build Coastguard Worker  * String.intern. Some code (XML parsers being a prime example) relies on being able to intern
56*795d594fSAndroid Build Coastguard Worker  * arbitrarily many strings for the duration of a parse without permanently increasing the memory
57*795d594fSAndroid Build Coastguard Worker  * footprint.
58*795d594fSAndroid Build Coastguard Worker  */
59*795d594fSAndroid Build Coastguard Worker class InternTable {
60*795d594fSAndroid Build Coastguard Worker  public:
61*795d594fSAndroid Build Coastguard Worker   // Modified UTF-8-encoded string treated as UTF16.
62*795d594fSAndroid Build Coastguard Worker   class Utf8String {
63*795d594fSAndroid Build Coastguard Worker    public:
Utf8String(uint32_t utf16_length,const char * utf8_data)64*795d594fSAndroid Build Coastguard Worker     Utf8String(uint32_t utf16_length, const char* utf8_data)
65*795d594fSAndroid Build Coastguard Worker         : utf16_length_(utf16_length), utf8_data_(utf8_data) { }
66*795d594fSAndroid Build Coastguard Worker 
GetHash()67*795d594fSAndroid Build Coastguard Worker     uint32_t GetHash() const { return Hash(utf16_length_, utf8_data_); }
GetUtf16Length()68*795d594fSAndroid Build Coastguard Worker     uint32_t GetUtf16Length() const { return utf16_length_; }
GetUtf8Data()69*795d594fSAndroid Build Coastguard Worker     const char* GetUtf8Data() const { return utf8_data_; }
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker     static uint32_t Hash(uint32_t utf16_length, const char* utf8_data);
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker    private:
74*795d594fSAndroid Build Coastguard Worker     uint32_t utf16_length_;
75*795d594fSAndroid Build Coastguard Worker     const char* utf8_data_;
76*795d594fSAndroid Build Coastguard Worker   };
77*795d594fSAndroid Build Coastguard Worker 
78*795d594fSAndroid Build Coastguard Worker   class StringHash {
79*795d594fSAndroid Build Coastguard Worker    public:
80*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions.
81*795d594fSAndroid Build Coastguard Worker     size_t operator()(const GcRoot<mirror::String>& root) const NO_THREAD_SAFETY_ANALYSIS;
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker     // Utf8String can be used for lookup. While we're passing the hash explicitly to all
84*795d594fSAndroid Build Coastguard Worker     // `HashSet<>` functions, they `DCHECK()` the supplied hash against the hash we provide here.
operator()85*795d594fSAndroid Build Coastguard Worker     size_t operator()(const Utf8String& key) const {
86*795d594fSAndroid Build Coastguard Worker       static_assert(std::is_same_v<uint32_t, decltype(key.GetHash())>);
87*795d594fSAndroid Build Coastguard Worker       return key.GetHash();
88*795d594fSAndroid Build Coastguard Worker     }
89*795d594fSAndroid Build Coastguard Worker   };
90*795d594fSAndroid Build Coastguard Worker 
91*795d594fSAndroid Build Coastguard Worker   class StringEquals {
92*795d594fSAndroid Build Coastguard Worker    public:
93*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions.
94*795d594fSAndroid Build Coastguard Worker     bool operator()(const GcRoot<mirror::String>& a, const GcRoot<mirror::String>& b) const
95*795d594fSAndroid Build Coastguard Worker         NO_THREAD_SAFETY_ANALYSIS;
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker     // Utf8String can be used for lookup.
98*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS: Used from unannotated `HashSet<>` functions.
99*795d594fSAndroid Build Coastguard Worker     bool operator()(const GcRoot<mirror::String>& a, const Utf8String& b) const
100*795d594fSAndroid Build Coastguard Worker         NO_THREAD_SAFETY_ANALYSIS;
101*795d594fSAndroid Build Coastguard Worker   };
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   class GcRootEmptyFn {
104*795d594fSAndroid Build Coastguard Worker    public:
MakeEmpty(GcRoot<mirror::String> & item)105*795d594fSAndroid Build Coastguard Worker     void MakeEmpty(GcRoot<mirror::String>& item) const {
106*795d594fSAndroid Build Coastguard Worker       item = GcRoot<mirror::String>();
107*795d594fSAndroid Build Coastguard Worker     }
IsEmpty(const GcRoot<mirror::String> & item)108*795d594fSAndroid Build Coastguard Worker     bool IsEmpty(const GcRoot<mirror::String>& item) const {
109*795d594fSAndroid Build Coastguard Worker       return item.IsNull();
110*795d594fSAndroid Build Coastguard Worker     }
111*795d594fSAndroid Build Coastguard Worker   };
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   using UnorderedSet =
114*795d594fSAndroid Build Coastguard Worker       HashSet<GcRoot<mirror::String>,
115*795d594fSAndroid Build Coastguard Worker               GcRootEmptyFn,
116*795d594fSAndroid Build Coastguard Worker               StringHash,
117*795d594fSAndroid Build Coastguard Worker               StringEquals,
118*795d594fSAndroid Build Coastguard Worker               GcRootArenaAllocator<GcRoot<mirror::String>, kAllocatorTagInternTable>>;
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker   EXPORT InternTable();
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker   // Interns a potentially new string in the 'strong' table. May cause thread suspension.
123*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<mirror::String> InternStrong(uint32_t utf16_length, const char* utf8_data)
124*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   // Interns a potentially new string in the 'strong' table. May cause thread suspension.
127*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<mirror::String> InternStrong(const char* utf8_data)
128*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   // Interns a potentially new string in the 'strong' table. May cause thread suspension.
131*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<mirror::String> InternStrong(ObjPtr<mirror::String> s)
132*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker   // Interns a potentially new string in the 'weak' table. May cause thread suspension.
135*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> InternWeak(const char* utf8_data) REQUIRES_SHARED(Locks::mutator_lock_)
136*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Roles::uninterruptible_);
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker   // Interns a potentially new string in the 'weak' table. May cause thread suspension.
139*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> InternWeak(ObjPtr<mirror::String> s) REQUIRES_SHARED(Locks::mutator_lock_)
140*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Roles::uninterruptible_);
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   void SweepInternTableWeaks(IsMarkedVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_)
143*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_);
144*795d594fSAndroid Build Coastguard Worker 
145*795d594fSAndroid Build Coastguard Worker   // Lookup a strong intern, returns null if not found.
146*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> LookupStrong(Thread* self, ObjPtr<mirror::String> s)
147*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_)
148*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
149*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> LookupStrong(Thread* self, uint32_t utf16_length, const char* utf8_data)
150*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_)
151*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
152*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> LookupStrongLocked(ObjPtr<mirror::String> s)
153*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
154*795d594fSAndroid Build Coastguard Worker 
155*795d594fSAndroid Build Coastguard Worker   // Lookup a weak intern, returns null if not found.
156*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> LookupWeak(Thread* self, ObjPtr<mirror::String> s)
157*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_)
158*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
159*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> LookupWeakLocked(ObjPtr<mirror::String> s)
160*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   // Total number of interned strings.
163*795d594fSAndroid Build Coastguard Worker   EXPORT size_t Size() const REQUIRES(!Locks::intern_table_lock_);
164*795d594fSAndroid Build Coastguard Worker 
165*795d594fSAndroid Build Coastguard Worker   // Total number of weakly live interned strings.
166*795d594fSAndroid Build Coastguard Worker   size_t StrongSize() const REQUIRES(!Locks::intern_table_lock_);
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker   // Total number of strongly live interned strings.
169*795d594fSAndroid Build Coastguard Worker   size_t WeakSize() const REQUIRES(!Locks::intern_table_lock_);
170*795d594fSAndroid Build Coastguard Worker 
171*795d594fSAndroid Build Coastguard Worker   EXPORT void VisitRoots(RootVisitor* visitor, VisitRootFlags flags)
172*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker   // Visit all of the interns in the table.
175*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
176*795d594fSAndroid Build Coastguard Worker   void VisitInterns(const Visitor& visitor,
177*795d594fSAndroid Build Coastguard Worker                     bool visit_boot_images,
178*795d594fSAndroid Build Coastguard Worker                     bool visit_non_boot_images)
179*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker   // Count the number of intern strings in the table.
182*795d594fSAndroid Build Coastguard Worker   size_t CountInterns(bool visit_boot_images, bool visit_non_boot_images) const
183*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker   void DumpForSigQuit(std::ostream& os) const REQUIRES(!Locks::intern_table_lock_);
186*795d594fSAndroid Build Coastguard Worker 
187*795d594fSAndroid Build Coastguard Worker   void BroadcastForNewInterns();
188*795d594fSAndroid Build Coastguard Worker 
189*795d594fSAndroid Build Coastguard Worker   // Add all of the strings in the image's intern table into this intern table. This is required so
190*795d594fSAndroid Build Coastguard Worker   // the intern table is correct.
191*795d594fSAndroid Build Coastguard Worker   // The visitor arg type is UnorderedSet
192*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
193*795d594fSAndroid Build Coastguard Worker   void AddImageStringsToTable(gc::space::ImageSpace* image_space,
194*795d594fSAndroid Build Coastguard Worker                               const Visitor& visitor)
195*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker   // Add a new intern table for inserting to, previous intern tables are still there but no
198*795d594fSAndroid Build Coastguard Worker   // longer inserted into and ideally unmodified. This is done to prevent dirty pages.
199*795d594fSAndroid Build Coastguard Worker   void AddNewTable()
200*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::intern_table_lock_);
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   // Change the weak root state. May broadcast to waiters.
203*795d594fSAndroid Build Coastguard Worker   void ChangeWeakRootState(gc::WeakRootState new_state)
204*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_);
205*795d594fSAndroid Build Coastguard Worker 
206*795d594fSAndroid Build Coastguard Worker  private:
207*795d594fSAndroid Build Coastguard Worker   // Table which holds pre zygote and post zygote interned strings. There is one instance for
208*795d594fSAndroid Build Coastguard Worker   // weak interns and strong interns.
209*795d594fSAndroid Build Coastguard Worker   class Table {
210*795d594fSAndroid Build Coastguard Worker    public:
211*795d594fSAndroid Build Coastguard Worker     class InternalTable {
212*795d594fSAndroid Build Coastguard Worker      public:
213*795d594fSAndroid Build Coastguard Worker       InternalTable() = default;
InternalTable(UnorderedSet && set,bool is_boot_image)214*795d594fSAndroid Build Coastguard Worker       InternalTable(UnorderedSet&& set, bool is_boot_image)
215*795d594fSAndroid Build Coastguard Worker           : set_(std::move(set)), is_boot_image_(is_boot_image) {}
216*795d594fSAndroid Build Coastguard Worker 
Empty()217*795d594fSAndroid Build Coastguard Worker       bool Empty() const {
218*795d594fSAndroid Build Coastguard Worker         return set_.empty();
219*795d594fSAndroid Build Coastguard Worker       }
220*795d594fSAndroid Build Coastguard Worker 
Size()221*795d594fSAndroid Build Coastguard Worker       size_t Size() const {
222*795d594fSAndroid Build Coastguard Worker         return set_.size();
223*795d594fSAndroid Build Coastguard Worker       }
224*795d594fSAndroid Build Coastguard Worker 
IsBootImage()225*795d594fSAndroid Build Coastguard Worker       bool IsBootImage() const {
226*795d594fSAndroid Build Coastguard Worker         return is_boot_image_;
227*795d594fSAndroid Build Coastguard Worker       }
228*795d594fSAndroid Build Coastguard Worker 
229*795d594fSAndroid Build Coastguard Worker      private:
230*795d594fSAndroid Build Coastguard Worker       UnorderedSet set_;
231*795d594fSAndroid Build Coastguard Worker       bool is_boot_image_ = false;
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker       friend class InternTable;
234*795d594fSAndroid Build Coastguard Worker       friend class linker::ImageWriter;
235*795d594fSAndroid Build Coastguard Worker       friend class Table;
236*795d594fSAndroid Build Coastguard Worker       ART_FRIEND_TEST(InternTableTest, CrossHash);
237*795d594fSAndroid Build Coastguard Worker     };
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker     Table();
240*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::String> Find(ObjPtr<mirror::String> s,
241*795d594fSAndroid Build Coastguard Worker                                 uint32_t hash,
242*795d594fSAndroid Build Coastguard Worker                                 size_t num_searched_frozen_tables = 0u)
243*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
244*795d594fSAndroid Build Coastguard Worker     ObjPtr<mirror::String> Find(const Utf8String& string, uint32_t hash)
245*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
246*795d594fSAndroid Build Coastguard Worker     void Insert(ObjPtr<mirror::String> s, uint32_t hash)
247*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
248*795d594fSAndroid Build Coastguard Worker     void Remove(ObjPtr<mirror::String> s, uint32_t hash)
249*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
250*795d594fSAndroid Build Coastguard Worker     void VisitRoots(RootVisitor* visitor)
251*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
252*795d594fSAndroid Build Coastguard Worker     void SweepWeaks(IsMarkedVisitor* visitor)
253*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
254*795d594fSAndroid Build Coastguard Worker     // Add a new intern table that will only be inserted into from now on.
255*795d594fSAndroid Build Coastguard Worker     void AddNewTable() REQUIRES(Locks::intern_table_lock_);
256*795d594fSAndroid Build Coastguard Worker     size_t Size() const REQUIRES(Locks::intern_table_lock_);
257*795d594fSAndroid Build Coastguard Worker     // Read and add an intern table from ptr.
258*795d594fSAndroid Build Coastguard Worker     // Tables read are inserted at the front of the table array. Only checks for conflicts in
259*795d594fSAndroid Build Coastguard Worker     // debug builds. Returns how many bytes were read.
260*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS for the visitor that may require locks.
261*795d594fSAndroid Build Coastguard Worker     template <typename Visitor>
262*795d594fSAndroid Build Coastguard Worker     size_t AddTableFromMemory(const uint8_t* ptr, const Visitor& visitor, bool is_boot_image)
263*795d594fSAndroid Build Coastguard Worker         REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker    private:
266*795d594fSAndroid Build Coastguard Worker     void SweepWeaks(UnorderedSet* set, IsMarkedVisitor* visitor)
267*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
268*795d594fSAndroid Build Coastguard Worker 
269*795d594fSAndroid Build Coastguard Worker     // Add a table to the front of the tables vector.
270*795d594fSAndroid Build Coastguard Worker     void AddInternStrings(UnorderedSet&& intern_strings, bool is_boot_image)
271*795d594fSAndroid Build Coastguard Worker         REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
272*795d594fSAndroid Build Coastguard Worker 
273*795d594fSAndroid Build Coastguard Worker     // We call AddNewTable when we create the zygote to reduce private dirty pages caused by
274*795d594fSAndroid Build Coastguard Worker     // modifying the zygote intern table. The back of table is modified when strings are interned.
275*795d594fSAndroid Build Coastguard Worker     dchecked_vector<InternalTable> tables_;
276*795d594fSAndroid Build Coastguard Worker 
277*795d594fSAndroid Build Coastguard Worker     friend class InternTable;
278*795d594fSAndroid Build Coastguard Worker     friend class linker::ImageWriter;
279*795d594fSAndroid Build Coastguard Worker     ART_FRIEND_TEST(InternTableTest, CrossHash);
280*795d594fSAndroid Build Coastguard Worker   };
281*795d594fSAndroid Build Coastguard Worker 
282*795d594fSAndroid Build Coastguard Worker   // Insert if non null, otherwise return null. Must be called holding the mutator lock.
283*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::String> Insert(ObjPtr<mirror::String> s,
284*795d594fSAndroid Build Coastguard Worker                                 uint32_t hash,
285*795d594fSAndroid Build Coastguard Worker                                 bool is_strong,
286*795d594fSAndroid Build Coastguard Worker                                 size_t num_searched_strong_frozen_tables = 0u)
287*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker   // Add a table from memory to the strong interns.
290*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
291*795d594fSAndroid Build Coastguard Worker   size_t AddTableFromMemory(const uint8_t* ptr, const Visitor& visitor, bool is_boot_image)
292*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
293*795d594fSAndroid Build Coastguard Worker 
294*795d594fSAndroid Build Coastguard Worker   // Note: Transaction rollback calls these helper functions directly.
295*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<mirror::String> InsertStrong(ObjPtr<mirror::String> s, uint32_t hash)
296*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
297*795d594fSAndroid Build Coastguard Worker   EXPORT ObjPtr<mirror::String> InsertWeak(ObjPtr<mirror::String> s, uint32_t hash)
298*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
299*795d594fSAndroid Build Coastguard Worker   EXPORT void RemoveStrong(ObjPtr<mirror::String> s, uint32_t hash)
300*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
301*795d594fSAndroid Build Coastguard Worker   void EXPORT RemoveWeak(ObjPtr<mirror::String> s, uint32_t hash)
302*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::intern_table_lock_);
303*795d594fSAndroid Build Coastguard Worker 
304*795d594fSAndroid Build Coastguard Worker   // Change the weak root state. May broadcast to waiters.
305*795d594fSAndroid Build Coastguard Worker   void ChangeWeakRootStateLocked(gc::WeakRootState new_state)
306*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_);
307*795d594fSAndroid Build Coastguard Worker 
308*795d594fSAndroid Build Coastguard Worker   // Wait until we can read weak roots.
309*795d594fSAndroid Build Coastguard Worker   void WaitUntilAccessible(Thread* self)
310*795d594fSAndroid Build Coastguard Worker       REQUIRES(Locks::intern_table_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker   bool log_new_roots_ GUARDED_BY(Locks::intern_table_lock_);
313*795d594fSAndroid Build Coastguard Worker   ConditionVariable weak_intern_condition_ GUARDED_BY(Locks::intern_table_lock_);
314*795d594fSAndroid Build Coastguard Worker   // Since this contains (strong) roots, they need a read barrier to
315*795d594fSAndroid Build Coastguard Worker   // enable concurrent intern table (strong) root scan. Do not
316*795d594fSAndroid Build Coastguard Worker   // directly access the strings in it. Use functions that contain
317*795d594fSAndroid Build Coastguard Worker   // read barriers.
318*795d594fSAndroid Build Coastguard Worker   Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_);
319*795d594fSAndroid Build Coastguard Worker   dchecked_vector<GcRoot<mirror::String>> new_strong_intern_roots_
320*795d594fSAndroid Build Coastguard Worker       GUARDED_BY(Locks::intern_table_lock_);
321*795d594fSAndroid Build Coastguard Worker   // Since this contains (weak) roots, they need a read barrier. Do
322*795d594fSAndroid Build Coastguard Worker   // not directly access the strings in it. Use functions that contain
323*795d594fSAndroid Build Coastguard Worker   // read barriers.
324*795d594fSAndroid Build Coastguard Worker   Table weak_interns_ GUARDED_BY(Locks::intern_table_lock_);
325*795d594fSAndroid Build Coastguard Worker   // Weak root state, used for concurrent system weak processing and more.
326*795d594fSAndroid Build Coastguard Worker   gc::WeakRootState weak_root_state_ GUARDED_BY(Locks::intern_table_lock_);
327*795d594fSAndroid Build Coastguard Worker 
328*795d594fSAndroid Build Coastguard Worker   friend class gc::space::ImageSpace;
329*795d594fSAndroid Build Coastguard Worker   friend class linker::ImageWriter;
330*795d594fSAndroid Build Coastguard Worker   friend class Transaction;
331*795d594fSAndroid Build Coastguard Worker   ART_FRIEND_TEST(InternTableTest, CrossHash);
332*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(InternTable);
333*795d594fSAndroid Build Coastguard Worker };
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker }  // namespace art
336*795d594fSAndroid Build Coastguard Worker 
337*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_INTERN_TABLE_H_
338