blob: a8487614b57f19798a0cd78dda863b69f003dd63 [file] [log] [blame]
Brian Carlstrom7e93b502011-08-04 14:16:22 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "intern_table.h"
4
Elliott Hughes90a33692011-08-30 13:27:07 -07005#include "UniquePtr.h"
Elliott Hughes814e4032011-08-23 12:07:56 -07006#include "utf.h"
Brian Carlstrom7e93b502011-08-04 14:16:22 -07007
8namespace art {
9
Elliott Hughes8daa0922011-09-11 13:46:25 -070010InternTable::InternTable() : intern_table_lock_("InternTable lock") {
Elliott Hughesde69d7f2011-08-18 16:49:37 -070011}
12
Brian Carlstroma663ea52011-08-19 23:33:41 -070013size_t InternTable::Size() const {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070014 MutexLock mu(intern_table_lock_);
15 return strong_interns_.size() + weak_interns_.size();
Brian Carlstroma663ea52011-08-19 23:33:41 -070016}
17
Elliott Hughescac6cc72011-11-03 20:31:21 -070018void InternTable::DumpForSigQuit(std::ostream& os) const {
19 MutexLock mu(intern_table_lock_);
20 os << "Intern table: " << strong_interns_.size() << " strong; "
21 << weak_interns_.size() << " weak; "
22 << image_strong_interns_.size() << " image strong\n";
23}
24
Elliott Hughes410c0c82011-09-01 17:58:25 -070025void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
Brian Carlstrom7e93b502011-08-04 14:16:22 -070026 MutexLock mu(intern_table_lock_);
27 typedef Table::const_iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -070028 for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
Elliott Hughes410c0c82011-09-01 17:58:25 -070029 visitor(it->second, arg);
Brian Carlstrom7e93b502011-08-04 14:16:22 -070030 }
Ian Rogers5d76c432011-10-31 21:42:49 -070031 // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070032}
33
Brian Carlstromc74255f2011-09-11 22:47:39 -070034String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070035 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070036 typedef Table::const_iterator It; // TODO: C++0x auto
37 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
Brian Carlstromc74255f2011-09-11 22:47:39 -070038 String* existing_string = it->second;
Elliott Hughescf4c6c42011-09-01 15:16:42 -070039 if (existing_string->Equals(s)) {
40 return existing_string;
Brian Carlstrom7e93b502011-08-04 14:16:22 -070041 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070042 }
43 return NULL;
44}
45
Brian Carlstromc74255f2011-09-11 22:47:39 -070046String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070047 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070048 table.insert(std::make_pair(hash_code, s));
49 return s;
50}
51
Brian Carlstromc74255f2011-09-11 22:47:39 -070052void InternTable::RegisterStrong(String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070053 MutexLock mu(intern_table_lock_);
Ian Rogers5d76c432011-10-31 21:42:49 -070054 Insert(image_strong_interns_, s, s->GetHashCode());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070055}
56
57void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070058 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070059 typedef Table::const_iterator It; // TODO: C++0x auto
60 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
61 if (it->second == s) {
62 table.erase(it);
63 return;
64 }
Brian Carlstrom7e93b502011-08-04 14:16:22 -070065 }
66}
67
Brian Carlstromc74255f2011-09-11 22:47:39 -070068String* InternTable::Insert(String* s, bool is_strong) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070069 MutexLock mu(intern_table_lock_);
70
71 DCHECK(s != NULL);
72 uint32_t hash_code = s->GetHashCode();
73
74 if (is_strong) {
Ian Rogers5d76c432011-10-31 21:42:49 -070075 // Check the strong tables for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070076 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070077 if (strong != NULL) {
78 return strong;
79 }
Ian Rogers5d76c432011-10-31 21:42:49 -070080 strong = Lookup(image_strong_interns_, s, hash_code);
81 if (strong != NULL) {
82 return strong;
83 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070084
85 // There is no match in the strong table, check the weak table.
Brian Carlstromc74255f2011-09-11 22:47:39 -070086 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070087 if (weak != NULL) {
88 // A match was found in the weak table. Promote to the strong table.
89 Remove(weak_interns_, weak, hash_code);
90 return Insert(strong_interns_, weak, hash_code);
91 }
92
93 // No match in the strong table or the weak table. Insert into the strong table.
94 return Insert(strong_interns_, s, hash_code);
95 }
96
97 // Check the strong table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070098 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070099 if (strong != NULL) {
100 return strong;
101 }
102 // Check the weak table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -0700103 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700104 if (weak != NULL) {
105 return weak;
106 }
107 // Insert into the weak table.
108 return Insert(weak_interns_, s, hash_code);
109}
110
Brian Carlstromc74255f2011-09-11 22:47:39 -0700111String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700112 return InternStrong(String::AllocFromModifiedUtf8(utf16_length, utf8_data));
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700113}
114
Brian Carlstromc74255f2011-09-11 22:47:39 -0700115String* InternTable::InternStrong(const char* utf8_data) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700116 return InternStrong(String::AllocFromModifiedUtf8(utf8_data));
Brian Carlstromc74255f2011-09-11 22:47:39 -0700117}
118
119String* InternTable::InternStrong(String* s) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700120 if (s == NULL) {
121 return NULL;
122 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700123 return Insert(s, true);
124}
125
126String* InternTable::InternWeak(String* s) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700127 if (s == NULL) {
128 return NULL;
129 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700130 return Insert(s, false);
131}
132
Brian Carlstromc74255f2011-09-11 22:47:39 -0700133bool InternTable::ContainsWeak(String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700134 MutexLock mu(intern_table_lock_);
135 const String* found = Lookup(weak_interns_, s, s->GetHashCode());
136 return found == s;
137}
138
Elliott Hughesc33a32b2011-10-11 18:18:07 -0700139void InternTable::SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700140 MutexLock mu(intern_table_lock_);
141 typedef Table::const_iterator It; // TODO: C++0x auto
142 for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
Elliott Hughesc33a32b2011-10-11 18:18:07 -0700143 Object* object = it->second;
144 if (!is_marked(object, arg)) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700145 weak_interns_.erase(it++);
146 } else {
147 ++it;
148 }
149 }
Brian Carlstroma663ea52011-08-19 23:33:41 -0700150}
151
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700152} // namespace art