blob: 9abbca846093b10b8c4cef2f2fc3dd9e2fc28519 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
2 * Copyright (C) 2011 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 */
Brian Carlstrom7e93b502011-08-04 14:16:22 -070016
17#include "intern_table.h"
18
Ian Rogers700a4022014-05-19 16:49:03 -070019#include <memory>
20
Mathieu Chartiere401d142015-04-22 13:56:20 -070021#include "gc_root-inl.h"
Ian Rogers7dfb28c2013-08-22 08:18:36 -070022#include "gc/space/image_space.h"
23#include "mirror/dex_cache.h"
24#include "mirror/object_array-inl.h"
25#include "mirror/object-inl.h"
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070026#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include "thread.h"
Elliott Hughes814e4032011-08-23 12:07:56 -070028#include "utf.h"
Brian Carlstrom7e93b502011-08-04 14:16:22 -070029
30namespace art {
31
Ian Rogers7dfb28c2013-08-22 08:18:36 -070032InternTable::InternTable()
Mathieu Chartiereb175f72014-10-31 11:49:27 -070033 : image_added_to_intern_table_(false), log_new_roots_(false),
34 allow_new_interns_(true),
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010035 new_intern_condition_("New intern condition", *Locks::intern_table_lock_) {
Mathieu Chartierc11d9b82013-09-19 10:01:59 -070036}
Elliott Hughesde69d7f2011-08-18 16:49:37 -070037
Brian Carlstroma663ea52011-08-19 23:33:41 -070038size_t InternTable::Size() const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010039 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070040 return strong_interns_.Size() + weak_interns_.Size();
Brian Carlstroma663ea52011-08-19 23:33:41 -070041}
42
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070043size_t InternTable::StrongSize() const {
44 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070045 return strong_interns_.Size();
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070046}
47
48size_t InternTable::WeakSize() const {
49 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070050 return weak_interns_.Size();
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070051}
52
Elliott Hughescac6cc72011-11-03 20:31:21 -070053void InternTable::DumpForSigQuit(std::ostream& os) const {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070054 os << "Intern table: " << StrongSize() << " strong; " << WeakSize() << " weak\n";
Elliott Hughescac6cc72011-11-03 20:31:21 -070055}
56
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070057void InternTable::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010058 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartier893263b2014-03-04 11:07:42 -080059 if ((flags & kVisitRootFlagAllRoots) != 0) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070060 strong_interns_.VisitRoots(visitor);
Mathieu Chartier893263b2014-03-04 11:07:42 -080061 } else if ((flags & kVisitRootFlagNewRoots) != 0) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070062 for (auto& root : new_strong_intern_roots_) {
63 mirror::String* old_ref = root.Read<kWithoutReadBarrier>();
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070064 root.VisitRoot(visitor, RootInfo(kRootInternedString));
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070065 mirror::String* new_ref = root.Read<kWithoutReadBarrier>();
Mathieu Chartierc2e20622014-11-03 11:41:47 -080066 if (new_ref != old_ref) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070067 // The GC moved a root in the log. Need to search the strong interns and update the
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070068 // corresponding object. This is slow, but luckily for us, this may only happen with a
69 // concurrent moving GC.
Mathieu Chartiereb175f72014-10-31 11:49:27 -070070 strong_interns_.Remove(old_ref);
71 strong_interns_.Insert(new_ref);
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070072 }
73 }
Mathieu Chartier893263b2014-03-04 11:07:42 -080074 }
Mathieu Chartier893263b2014-03-04 11:07:42 -080075 if ((flags & kVisitRootFlagClearRootLog) != 0) {
76 new_strong_intern_roots_.clear();
77 }
78 if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) {
79 log_new_roots_ = true;
80 } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) {
81 log_new_roots_ = false;
Ian Rogers1d54e732013-05-02 21:10:01 -070082 }
Mathieu Chartier423d2a32013-09-12 17:33:56 -070083 // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070084}
85
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070086mirror::String* InternTable::LookupStrong(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070087 return strong_interns_.Find(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -070088}
89
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070090mirror::String* InternTable::LookupWeak(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070091 return weak_interns_.Find(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -070092}
93
Mathieu Chartiereb175f72014-10-31 11:49:27 -070094void InternTable::SwapPostZygoteWithPreZygote() {
95 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
96 weak_interns_.SwapPostZygoteWithPreZygote();
97 strong_interns_.SwapPostZygoteWithPreZygote();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070098}
99
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700100mirror::String* InternTable::InsertStrong(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100101 Runtime* runtime = Runtime::Current();
102 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700103 runtime->RecordStrongStringInsertion(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100104 }
Mathieu Chartier893263b2014-03-04 11:07:42 -0800105 if (log_new_roots_) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700106 new_strong_intern_roots_.push_back(GcRoot<mirror::String>(s));
Mathieu Chartier893263b2014-03-04 11:07:42 -0800107 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700108 strong_interns_.Insert(s);
Mathieu Chartier893263b2014-03-04 11:07:42 -0800109 return s;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100110}
111
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700112mirror::String* InternTable::InsertWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100113 Runtime* runtime = Runtime::Current();
114 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700115 runtime->RecordWeakStringInsertion(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100116 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700117 weak_interns_.Insert(s);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700118 return s;
119}
120
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700121void InternTable::RemoveStrong(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700122 strong_interns_.Remove(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -0700123}
124
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700125void InternTable::RemoveWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100126 Runtime* runtime = Runtime::Current();
127 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700128 runtime->RecordWeakStringRemoval(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100129 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700130 weak_interns_.Remove(s);
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700131}
132
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100133// Insert/remove methods used to undo changes made during an aborted transaction.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700134mirror::String* InternTable::InsertStrongFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100135 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700136 return InsertStrong(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700138mirror::String* InternTable::InsertWeakFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100139 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700140 return InsertWeak(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100141}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700142void InternTable::RemoveStrongFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100143 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700144 RemoveStrong(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100145}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700146void InternTable::RemoveWeakFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100147 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700148 RemoveWeak(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100149}
150
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700151void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space) {
Mathieu Chartierbc58ede2014-11-17 12:36:24 -0800152 CHECK(image_space != nullptr);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700153 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
154 if (!image_added_to_intern_table_) {
155 mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
156 mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
157 for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
158 mirror::DexCache* dex_cache = dex_caches->Get(i);
159 const DexFile* dex_file = dex_cache->GetDexFile();
160 const size_t num_strings = dex_file->NumStringIds();
161 for (size_t j = 0; j < num_strings; ++j) {
162 mirror::String* image_string = dex_cache->GetResolvedString(j);
163 if (image_string != nullptr) {
164 mirror::String* found = LookupStrong(image_string);
165 if (found == nullptr) {
166 InsertStrong(image_string);
167 } else {
168 DCHECK_EQ(found, image_string);
169 }
170 }
171 }
172 }
173 image_added_to_intern_table_ = true;
174 }
175}
176
177mirror::String* InternTable::LookupStringFromImage(mirror::String* s)
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700178 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700179 if (image_added_to_intern_table_) {
180 return nullptr;
181 }
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700182 gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetImageSpace();
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700183 if (image == nullptr) {
184 return nullptr; // No image present.
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700185 }
186 mirror::Object* root = image->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
187 mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
188 const std::string utf8 = s->ToModifiedUtf8();
189 for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
190 mirror::DexCache* dex_cache = dex_caches->Get(i);
191 const DexFile* dex_file = dex_cache->GetDexFile();
192 // Binary search the dex file for the string index.
193 const DexFile::StringId* string_id = dex_file->FindStringId(utf8.c_str());
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800194 if (string_id != nullptr) {
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700195 uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
Hiroshi Yamauchi2cd334a2015-01-09 14:03:35 -0800196 // GetResolvedString() contains a RB.
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800197 mirror::String* image_string = dex_cache->GetResolvedString(string_idx);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700198 if (image_string != nullptr) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800199 return image_string;
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700200 }
201 }
202 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800203 return nullptr;
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700204}
205
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700206void InternTable::AllowNewInterns() {
207 Thread* self = Thread::Current();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100208 MutexLock mu(self, *Locks::intern_table_lock_);
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700209 allow_new_interns_ = true;
210 new_intern_condition_.Broadcast(self);
211}
212
213void InternTable::DisallowNewInterns() {
214 Thread* self = Thread::Current();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100215 MutexLock mu(self, *Locks::intern_table_lock_);
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700216 allow_new_interns_ = false;
217}
218
Hiroshi Yamauchi2cd334a2015-01-09 14:03:35 -0800219void InternTable::EnsureNewInternsDisallowed() {
220 // Lock and unlock once to ensure that no threads are still in the
221 // middle of adding new interns.
222 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
223 CHECK(!allow_new_interns_);
224}
225
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800226mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800227 if (s == nullptr) {
228 return nullptr;
229 }
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700230 Thread* self = Thread::Current();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100231 MutexLock mu(self, *Locks::intern_table_lock_);
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700232 while (UNLIKELY(!allow_new_interns_)) {
233 new_intern_condition_.WaitHoldingLocks(self);
234 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700235 // Check the strong table for a match.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700236 mirror::String* strong = LookupStrong(s);
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800237 if (strong != nullptr) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700238 return strong;
239 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800240 // There is no match in the strong table, check the weak table.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700241 mirror::String* weak = LookupWeak(s);
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800242 if (weak != nullptr) {
243 if (is_strong) {
244 // A match was found in the weak table. Promote to the strong table.
245 RemoveWeak(weak);
246 return InsertStrong(weak);
247 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700248 return weak;
249 }
nikolay serdjuka446d862015-04-17 19:27:56 +0600250 // Check the image for a match.
251 mirror::String* image = LookupStringFromImage(s);
252 if (image != nullptr) {
253 return is_strong ? InsertStrong(image) : InsertWeak(image);
254 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800255 // No match in the strong table or the weak table. Insert into the strong / weak table.
256 return is_strong ? InsertStrong(s) : InsertWeak(s);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700257}
258
Mathieu Chartiered0fc1d2014-03-21 14:09:35 -0700259mirror::String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
260 DCHECK(utf8_data != nullptr);
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700261 return InternStrong(mirror::String::AllocFromModifiedUtf8(
262 Thread::Current(), utf16_length, utf8_data));
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700263}
264
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800265mirror::String* InternTable::InternStrong(const char* utf8_data) {
Mathieu Chartiered0fc1d2014-03-21 14:09:35 -0700266 DCHECK(utf8_data != nullptr);
267 return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data));
Brian Carlstromc74255f2011-09-11 22:47:39 -0700268}
269
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800270mirror::String* InternTable::InternStrong(mirror::String* s) {
Brian Carlstromc74255f2011-09-11 22:47:39 -0700271 return Insert(s, true);
272}
273
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800274mirror::String* InternTable::InternWeak(mirror::String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700275 return Insert(s, false);
276}
277
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800278bool InternTable::ContainsWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100279 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700280 return LookupWeak(s) == s;
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700281}
282
Mathieu Chartier83c8ee02014-01-28 14:50:23 -0800283void InternTable::SweepInternTableWeaks(IsMarkedCallback* callback, void* arg) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100284 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700285 weak_interns_.SweepWeaks(callback, arg);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700286}
287
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800288std::size_t InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& root) const {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700289 if (kIsDebugBuild) {
290 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
291 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800292 return static_cast<size_t>(root.Read()->GetHashCode());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700293}
294
295bool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800296 const GcRoot<mirror::String>& b) const {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700297 if (kIsDebugBuild) {
298 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
299 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800300 return a.Read()->Equals(b.Read());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700301}
302
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700303void InternTable::Table::Remove(mirror::String* s) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800304 auto it = post_zygote_table_.Find(GcRoot<mirror::String>(s));
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700305 if (it != post_zygote_table_.end()) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800306 post_zygote_table_.Erase(it);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700307 } else {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800308 it = pre_zygote_table_.Find(GcRoot<mirror::String>(s));
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700309 DCHECK(it != pre_zygote_table_.end());
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800310 pre_zygote_table_.Erase(it);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700311 }
312}
313
314mirror::String* InternTable::Table::Find(mirror::String* s) {
315 Locks::intern_table_lock_->AssertHeld(Thread::Current());
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800316 auto it = pre_zygote_table_.Find(GcRoot<mirror::String>(s));
317 if (it != pre_zygote_table_.end()) {
318 return it->Read();
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700319 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800320 it = post_zygote_table_.Find(GcRoot<mirror::String>(s));
321 if (it != post_zygote_table_.end()) {
322 return it->Read();
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700323 }
324 return nullptr;
325}
326
327void InternTable::Table::SwapPostZygoteWithPreZygote() {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800328 CHECK(pre_zygote_table_.Empty());
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700329 std::swap(pre_zygote_table_, post_zygote_table_);
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800330 VLOG(heap) << "Swapping " << pre_zygote_table_.Size() << " interns to the pre zygote table";
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700331}
332
333void InternTable::Table::Insert(mirror::String* s) {
334 // Always insert the post zygote table, this gets swapped when we create the zygote to be the
335 // pre zygote table.
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800336 post_zygote_table_.Insert(GcRoot<mirror::String>(s));
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700337}
338
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700339void InternTable::Table::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier4809d0a2015-04-07 10:39:04 -0700340 BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
341 visitor, RootInfo(kRootInternedString));
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700342 for (auto& intern : pre_zygote_table_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700343 buffered_visitor.VisitRoot(intern);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700344 }
345 for (auto& intern : post_zygote_table_) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700346 buffered_visitor.VisitRoot(intern);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700347 }
348}
349
350void InternTable::Table::SweepWeaks(IsMarkedCallback* callback, void* arg) {
351 SweepWeaks(&pre_zygote_table_, callback, arg);
352 SweepWeaks(&post_zygote_table_, callback, arg);
353}
354
355void InternTable::Table::SweepWeaks(UnorderedSet* set, IsMarkedCallback* callback, void* arg) {
356 for (auto it = set->begin(), end = set->end(); it != end;) {
357 // This does not need a read barrier because this is called by GC.
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800358 mirror::Object* object = it->Read<kWithoutReadBarrier>();
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700359 mirror::Object* new_object = callback(object, arg);
360 if (new_object == nullptr) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800361 it = set->Erase(it);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700362 } else {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800363 *it = GcRoot<mirror::String>(new_object->AsString());
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700364 ++it;
365 }
366 }
367}
368
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800369size_t InternTable::Table::Size() const {
370 return pre_zygote_table_.Size() + post_zygote_table_.Size();
371}
372
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700373} // namespace art