blob: 68d7ebd0d52dbc00d34105d24befc752ddd420c0 [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"
Mathieu Chartier97509952015-07-13 14:35:43 -070022#include "gc/collector/garbage_collector.h"
Ian Rogers7dfb28c2013-08-22 08:18:36 -070023#include "gc/space/image_space.h"
Mathieu Chartier14c3bf92015-07-13 14:35:43 -070024#include "gc/weak_root_state.h"
Vladimir Marko05792b92015-08-03 11:56:49 +010025#include "mirror/dex_cache-inl.h"
Ian Rogers7dfb28c2013-08-22 08:18:36 -070026#include "mirror/object_array-inl.h"
27#include "mirror/object-inl.h"
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070028#include "mirror/string-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "thread.h"
Elliott Hughes814e4032011-08-23 12:07:56 -070030#include "utf.h"
Brian Carlstrom7e93b502011-08-04 14:16:22 -070031
32namespace art {
33
Ian Rogers7dfb28c2013-08-22 08:18:36 -070034InternTable::InternTable()
Mathieu Chartierea0831f2015-12-29 13:17:37 -080035 : images_added_to_intern_table_(false),
36 log_new_roots_(false),
Mathieu Chartier14c3bf92015-07-13 14:35:43 -070037 weak_intern_condition_("New intern condition", *Locks::intern_table_lock_),
38 weak_root_state_(gc::kWeakRootStateNormal) {
Mathieu Chartierc11d9b82013-09-19 10:01:59 -070039}
Elliott Hughesde69d7f2011-08-18 16:49:37 -070040
Brian Carlstroma663ea52011-08-19 23:33:41 -070041size_t InternTable::Size() const {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010042 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070043 return strong_interns_.Size() + weak_interns_.Size();
Brian Carlstroma663ea52011-08-19 23:33:41 -070044}
45
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070046size_t InternTable::StrongSize() const {
47 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070048 return strong_interns_.Size();
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070049}
50
51size_t InternTable::WeakSize() const {
52 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -070053 return weak_interns_.Size();
Hiroshi Yamauchia91a4bc2014-06-13 16:44:55 -070054}
55
Elliott Hughescac6cc72011-11-03 20:31:21 -070056void InternTable::DumpForSigQuit(std::ostream& os) const {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070057 os << "Intern table: " << StrongSize() << " strong; " << WeakSize() << " weak\n";
Elliott Hughescac6cc72011-11-03 20:31:21 -070058}
59
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070060void InternTable::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010061 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartier893263b2014-03-04 11:07:42 -080062 if ((flags & kVisitRootFlagAllRoots) != 0) {
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070063 strong_interns_.VisitRoots(visitor);
Mathieu Chartier893263b2014-03-04 11:07:42 -080064 } else if ((flags & kVisitRootFlagNewRoots) != 0) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070065 for (auto& root : new_strong_intern_roots_) {
66 mirror::String* old_ref = root.Read<kWithoutReadBarrier>();
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -070067 root.VisitRoot(visitor, RootInfo(kRootInternedString));
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070068 mirror::String* new_ref = root.Read<kWithoutReadBarrier>();
Mathieu Chartierc2e20622014-11-03 11:41:47 -080069 if (new_ref != old_ref) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070070 // The GC moved a root in the log. Need to search the strong interns and update the
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070071 // corresponding object. This is slow, but luckily for us, this may only happen with a
72 // concurrent moving GC.
Mathieu Chartiereb175f72014-10-31 11:49:27 -070073 strong_interns_.Remove(old_ref);
74 strong_interns_.Insert(new_ref);
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070075 }
76 }
Mathieu Chartier893263b2014-03-04 11:07:42 -080077 }
Mathieu Chartier893263b2014-03-04 11:07:42 -080078 if ((flags & kVisitRootFlagClearRootLog) != 0) {
79 new_strong_intern_roots_.clear();
80 }
81 if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) {
82 log_new_roots_ = true;
83 } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) {
84 log_new_roots_ = false;
Ian Rogers1d54e732013-05-02 21:10:01 -070085 }
Mathieu Chartier423d2a32013-09-12 17:33:56 -070086 // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070087}
88
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070089mirror::String* InternTable::LookupStrong(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070090 return strong_interns_.Find(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -070091}
92
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -070093mirror::String* InternTable::LookupWeak(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070094 return weak_interns_.Find(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -070095}
96
Mathieu Chartierea0831f2015-12-29 13:17:37 -080097void InternTable::AddNewTable() {
Mathieu Chartiereb175f72014-10-31 11:49:27 -070098 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartierea0831f2015-12-29 13:17:37 -080099 weak_interns_.AddNewTable();
100 strong_interns_.AddNewTable();
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700101}
102
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700103mirror::String* InternTable::InsertStrong(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100104 Runtime* runtime = Runtime::Current();
105 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700106 runtime->RecordStrongStringInsertion(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100107 }
Mathieu Chartier893263b2014-03-04 11:07:42 -0800108 if (log_new_roots_) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700109 new_strong_intern_roots_.push_back(GcRoot<mirror::String>(s));
Mathieu Chartier893263b2014-03-04 11:07:42 -0800110 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700111 strong_interns_.Insert(s);
Mathieu Chartier893263b2014-03-04 11:07:42 -0800112 return s;
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100113}
114
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700115mirror::String* InternTable::InsertWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100116 Runtime* runtime = Runtime::Current();
117 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700118 runtime->RecordWeakStringInsertion(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100119 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700120 weak_interns_.Insert(s);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700121 return s;
122}
123
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700124void InternTable::RemoveStrong(mirror::String* s) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700125 strong_interns_.Remove(s);
Hiroshi Yamauchi1bd48722014-05-23 19:58:15 -0700126}
127
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700128void InternTable::RemoveWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100129 Runtime* runtime = Runtime::Current();
130 if (runtime->IsActiveTransaction()) {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700131 runtime->RecordWeakStringRemoval(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100132 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700133 weak_interns_.Remove(s);
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700134}
135
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100136// Insert/remove methods used to undo changes made during an aborted transaction.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700137mirror::String* InternTable::InsertStrongFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100138 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700139 return InsertStrong(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100140}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700141mirror::String* InternTable::InsertWeakFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100142 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700143 return InsertWeak(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100144}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700145void InternTable::RemoveStrongFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100146 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700147 RemoveStrong(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100148}
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700149void InternTable::RemoveWeakFromTransaction(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100150 DCHECK(!Runtime::Current()->IsActiveTransaction());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700151 RemoveWeak(s);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100152}
153
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700154void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space) {
Mathieu Chartierbc58ede2014-11-17 12:36:24 -0800155 CHECK(image_space != nullptr);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700156 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800157 const ImageHeader* const header = &image_space->GetImageHeader();
158 // Check if we have the interned strings section.
159 const ImageSection& section = header->GetImageSection(ImageHeader::kSectionInternedStrings);
160 if (section.Size() > 0) {
161 AddTableFromMemoryLocked(image_space->Begin() + section.Offset());
162 } else {
163 // TODO: Delete this logic?
164 mirror::Object* root = header->GetImageRoot(ImageHeader::kDexCaches);
165 mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
166 for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
167 mirror::DexCache* dex_cache = dex_caches->Get(i);
168 const size_t num_strings = dex_cache->NumStrings();
169 for (size_t j = 0; j < num_strings; ++j) {
170 mirror::String* image_string = dex_cache->GetResolvedString(j);
171 if (image_string != nullptr) {
172 mirror::String* found = LookupStrong(image_string);
173 if (found == nullptr) {
174 InsertStrong(image_string);
175 } else {
176 DCHECK_EQ(found, image_string);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700177 }
178 }
179 }
180 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700181 }
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800182 images_added_to_intern_table_ = true;
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700183}
184
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700185mirror::String* InternTable::LookupStringFromImage(mirror::String* s) {
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800186 const std::vector<gc::space::ImageSpace*>& image_spaces =
Jeff Haodcdc85b2015-12-04 14:06:18 -0800187 Runtime::Current()->GetHeap()->GetBootImageSpaces();
188 if (image_spaces.empty()) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700189 return nullptr; // No image present.
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700190 }
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700191 const std::string utf8 = s->ToModifiedUtf8();
Jeff Haodcdc85b2015-12-04 14:06:18 -0800192 for (gc::space::ImageSpace* image_space : image_spaces) {
193 mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
194 mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
195 for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
196 mirror::DexCache* dex_cache = dex_caches->Get(i);
197 const DexFile* dex_file = dex_cache->GetDexFile();
198 // Binary search the dex file for the string index.
199 const DexFile::StringId* string_id = dex_file->FindStringId(utf8.c_str());
200 if (string_id != nullptr) {
201 uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
202 // GetResolvedString() contains a RB.
203 mirror::String* image_string = dex_cache->GetResolvedString(string_idx);
204 if (image_string != nullptr) {
205 return image_string;
206 }
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700207 }
208 }
209 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800210 return nullptr;
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700211}
212
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -0700213void InternTable::BroadcastForNewInterns() {
214 CHECK(kUseReadBarrier);
215 Thread* self = Thread::Current();
216 MutexLock mu(self, *Locks::intern_table_lock_);
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700217 weak_intern_condition_.Broadcast(self);
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -0700218}
219
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700220void InternTable::WaitUntilAccessible(Thread* self) {
221 Locks::intern_table_lock_->ExclusiveUnlock(self);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700222 {
223 ScopedThreadSuspension sts(self, kWaitingWeakGcRootRead);
224 MutexLock mu(self, *Locks::intern_table_lock_);
225 while (weak_root_state_ == gc::kWeakRootStateNoReadsOrWrites) {
226 weak_intern_condition_.Wait(self);
227 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700228 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700229 Locks::intern_table_lock_->ExclusiveLock(self);
230}
231
232mirror::String* InternTable::Insert(mirror::String* s, bool is_strong, bool holding_locks) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800233 if (s == nullptr) {
234 return nullptr;
235 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700236 Thread* const self = Thread::Current();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100237 MutexLock mu(self, *Locks::intern_table_lock_);
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700238 if (kDebugLocking && !holding_locks) {
239 Locks::mutator_lock_->AssertSharedHeld(self);
240 CHECK_EQ(2u, self->NumberOfHeldMutexes()) << "may only safely hold the mutator lock";
Mathieu Chartierc11d9b82013-09-19 10:01:59 -0700241 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700242 while (true) {
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700243 if (holding_locks) {
244 if (!kUseReadBarrier) {
245 CHECK_EQ(weak_root_state_, gc::kWeakRootStateNormal);
246 } else {
247 CHECK(self->GetWeakRefAccessEnabled());
248 }
249 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700250 // Check the strong table for a match.
251 mirror::String* strong = LookupStrong(s);
252 if (strong != nullptr) {
253 return strong;
254 }
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700255 if ((!kUseReadBarrier && weak_root_state_ != gc::kWeakRootStateNoReadsOrWrites) ||
256 (kUseReadBarrier && self->GetWeakRefAccessEnabled())) {
257 break;
258 }
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700259 // weak_root_state_ is set to gc::kWeakRootStateNoReadsOrWrites in the GC pause but is only
260 // cleared after SweepSystemWeaks has completed. This is why we need to wait until it is
261 // cleared.
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700262 CHECK(!holding_locks);
263 StackHandleScope<1> hs(self);
264 auto h = hs.NewHandleWrapper(&s);
265 WaitUntilAccessible(self);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700266 }
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700267 if (!kUseReadBarrier) {
268 CHECK_EQ(weak_root_state_, gc::kWeakRootStateNormal);
269 } else {
270 CHECK(self->GetWeakRefAccessEnabled());
271 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800272 // There is no match in the strong table, check the weak table.
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700273 mirror::String* weak = LookupWeak(s);
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800274 if (weak != nullptr) {
275 if (is_strong) {
276 // A match was found in the weak table. Promote to the strong table.
277 RemoveWeak(weak);
278 return InsertStrong(weak);
279 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700280 return weak;
281 }
nikolay serdjuka446d862015-04-17 19:27:56 +0600282 // Check the image for a match.
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800283 if (!images_added_to_intern_table_) {
284 mirror::String* const image_string = LookupStringFromImage(s);
285 if (image_string != nullptr) {
286 return is_strong ? InsertStrong(image_string) : InsertWeak(image_string);
287 }
nikolay serdjuka446d862015-04-17 19:27:56 +0600288 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800289 // No match in the strong table or the weak table. Insert into the strong / weak table.
290 return is_strong ? InsertStrong(s) : InsertWeak(s);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700291}
292
Mathieu Chartiered0fc1d2014-03-21 14:09:35 -0700293mirror::String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
294 DCHECK(utf8_data != nullptr);
Ian Rogers7dfb28c2013-08-22 08:18:36 -0700295 return InternStrong(mirror::String::AllocFromModifiedUtf8(
296 Thread::Current(), utf16_length, utf8_data));
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700297}
298
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800299mirror::String* InternTable::InternStrong(const char* utf8_data) {
Mathieu Chartiered0fc1d2014-03-21 14:09:35 -0700300 DCHECK(utf8_data != nullptr);
301 return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data));
Brian Carlstromc74255f2011-09-11 22:47:39 -0700302}
303
Mathieu Chartier90ef3db2015-08-04 15:19:41 -0700304mirror::String* InternTable::InternStrongImageString(mirror::String* s) {
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700305 // May be holding the heap bitmap lock.
306 return Insert(s, true, true);
307}
308
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800309mirror::String* InternTable::InternStrong(mirror::String* s) {
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700310 return Insert(s, true, false);
Brian Carlstromc74255f2011-09-11 22:47:39 -0700311}
312
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800313mirror::String* InternTable::InternWeak(mirror::String* s) {
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700314 return Insert(s, false, false);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700315}
316
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800317bool InternTable::ContainsWeak(mirror::String* s) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100318 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700319 return LookupWeak(s) == s;
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700320}
321
Mathieu Chartier97509952015-07-13 14:35:43 -0700322void InternTable::SweepInternTableWeaks(IsMarkedVisitor* visitor) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100323 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartier97509952015-07-13 14:35:43 -0700324 weak_interns_.SweepWeaks(visitor);
Brian Carlstroma663ea52011-08-19 23:33:41 -0700325}
326
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800327size_t InternTable::AddTableFromMemory(const uint8_t* ptr) {
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700328 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800329 return AddTableFromMemoryLocked(ptr);
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700330}
331
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800332size_t InternTable::AddTableFromMemoryLocked(const uint8_t* ptr) {
333 return strong_interns_.AddTableFromMemory(ptr);
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700334}
335
336size_t InternTable::WriteToMemory(uint8_t* ptr) {
337 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800338 return strong_interns_.WriteToMemory(ptr);
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700339}
340
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800341std::size_t InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& root) const {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700342 if (kIsDebugBuild) {
343 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
344 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800345 return static_cast<size_t>(root.Read()->GetHashCode());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700346}
347
348bool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800349 const GcRoot<mirror::String>& b) const {
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700350 if (kIsDebugBuild) {
351 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
352 }
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800353 return a.Read()->Equals(b.Read());
Mathieu Chartiercdfd39f2014-08-29 18:16:58 -0700354}
355
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800356size_t InternTable::Table::AddTableFromMemory(const uint8_t* ptr) {
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700357 size_t read_count = 0;
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800358 UnorderedSet set(ptr, /*make copy*/false, &read_count);
359 // TODO: Disable this for app images if app images have intern tables.
360 static constexpr bool kCheckDuplicates = true;
361 if (kCheckDuplicates) {
362 for (GcRoot<mirror::String>& string : set) {
363 CHECK(Find(string.Read()) == nullptr) << "Already found " << string.Read()->ToModifiedUtf8();
364 }
365 }
366 // Insert at the front since we insert into the back.
367 tables_.insert(tables_.begin(), std::move(set));
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700368 return read_count;
369}
370
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800371size_t InternTable::Table::WriteToMemory(uint8_t* ptr) {
372 if (tables_.empty()) {
373 return 0;
374 }
375 UnorderedSet* table_to_write;
376 UnorderedSet combined;
377 if (tables_.size() > 1) {
378 table_to_write = &combined;
379 for (UnorderedSet& table : tables_) {
380 for (GcRoot<mirror::String>& string : table) {
381 combined.Insert(string);
382 }
383 }
384 } else {
385 table_to_write = &tables_.back();
386 }
387 return table_to_write->WriteToMemory(ptr);
Mathieu Chartierd39645e2015-06-09 17:50:29 -0700388}
389
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700390void InternTable::Table::Remove(mirror::String* s) {
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800391 for (UnorderedSet& table : tables_) {
392 auto it = table.Find(GcRoot<mirror::String>(s));
393 if (it != table.end()) {
394 table.Erase(it);
395 return;
396 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700397 }
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800398 LOG(FATAL) << "Attempting to remove non-interned string " << s->ToModifiedUtf8();
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700399}
400
401mirror::String* InternTable::Table::Find(mirror::String* s) {
402 Locks::intern_table_lock_->AssertHeld(Thread::Current());
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800403 for (UnorderedSet& table : tables_) {
404 auto it = table.Find(GcRoot<mirror::String>(s));
405 if (it != table.end()) {
406 return it->Read();
407 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700408 }
409 return nullptr;
410}
411
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800412void InternTable::Table::AddNewTable() {
413 tables_.push_back(UnorderedSet());
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700414}
415
416void InternTable::Table::Insert(mirror::String* s) {
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800417 // Always insert the last table, the image tables are before and we avoid inserting into these
418 // to prevent dirty pages.
419 DCHECK(!tables_.empty());
420 tables_.back().Insert(GcRoot<mirror::String>(s));
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700421}
422
Mathieu Chartierbb87e0f2015-04-03 11:21:55 -0700423void InternTable::Table::VisitRoots(RootVisitor* visitor) {
Mathieu Chartier4809d0a2015-04-07 10:39:04 -0700424 BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
425 visitor, RootInfo(kRootInternedString));
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800426 for (UnorderedSet& table : tables_) {
427 for (auto& intern : table) {
428 buffered_visitor.VisitRoot(intern);
429 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700430 }
431}
432
Mathieu Chartier97509952015-07-13 14:35:43 -0700433void InternTable::Table::SweepWeaks(IsMarkedVisitor* visitor) {
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800434 for (UnorderedSet& table : tables_) {
435 SweepWeaks(&table, visitor);
436 }
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700437}
438
Mathieu Chartier97509952015-07-13 14:35:43 -0700439void InternTable::Table::SweepWeaks(UnorderedSet* set, IsMarkedVisitor* visitor) {
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700440 for (auto it = set->begin(), end = set->end(); it != end;) {
441 // This does not need a read barrier because this is called by GC.
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800442 mirror::Object* object = it->Read<kWithoutReadBarrier>();
Mathieu Chartier97509952015-07-13 14:35:43 -0700443 mirror::Object* new_object = visitor->IsMarked(object);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700444 if (new_object == nullptr) {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800445 it = set->Erase(it);
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700446 } else {
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800447 *it = GcRoot<mirror::String>(new_object->AsString());
Mathieu Chartiereb175f72014-10-31 11:49:27 -0700448 ++it;
449 }
450 }
451}
452
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800453size_t InternTable::Table::Size() const {
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800454 return std::accumulate(tables_.begin(),
455 tables_.end(),
456 size_t(0),
457 [](size_t sum, const UnorderedSet& set) {
458 return sum + set.Size();
459 });
Mathieu Chartierc2e20622014-11-03 11:41:47 -0800460}
461
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700462void InternTable::ChangeWeakRootState(gc::WeakRootState new_state) {
463 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
464 ChangeWeakRootStateLocked(new_state);
465}
466
467void InternTable::ChangeWeakRootStateLocked(gc::WeakRootState new_state) {
Hiroshi Yamauchifdbd13c2015-09-02 16:16:58 -0700468 CHECK(!kUseReadBarrier);
Mathieu Chartier14c3bf92015-07-13 14:35:43 -0700469 weak_root_state_ = new_state;
470 if (new_state != gc::kWeakRootStateNoReadsOrWrites) {
471 weak_intern_condition_.Broadcast(Thread::Current());
472 }
473}
474
Mathieu Chartier32cc9ee2015-10-15 09:19:15 -0700475InternTable::Table::Table() {
476 Runtime* const runtime = Runtime::Current();
Mathieu Chartierea0831f2015-12-29 13:17:37 -0800477 // Initial table.
478 tables_.push_back(UnorderedSet());
479 tables_.back().SetLoadFactor(runtime->GetHashTableMinLoadFactor(),
480 runtime->GetHashTableMaxLoadFactor());
Mathieu Chartier32cc9ee2015-10-15 09:19:15 -0700481}
482
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700483} // namespace art