blob: aa27ace4401ce65a629892d704001b9c73a221b3 [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 Hughes410c0c82011-09-01 17:58:25 -070018void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
Brian Carlstrom7e93b502011-08-04 14:16:22 -070019 MutexLock mu(intern_table_lock_);
20 typedef Table::const_iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -070021 for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
Elliott Hughes410c0c82011-09-01 17:58:25 -070022 visitor(it->second, arg);
Brian Carlstrom7e93b502011-08-04 14:16:22 -070023 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070024 // Note: we deliberately don't visit the weak_interns_ table.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070025}
26
Brian Carlstromc74255f2011-09-11 22:47:39 -070027String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070028 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070029 typedef Table::const_iterator It; // TODO: C++0x auto
30 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
Brian Carlstromc74255f2011-09-11 22:47:39 -070031 String* existing_string = it->second;
Elliott Hughescf4c6c42011-09-01 15:16:42 -070032 if (existing_string->Equals(s)) {
33 return existing_string;
Brian Carlstrom7e93b502011-08-04 14:16:22 -070034 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070035 }
36 return NULL;
37}
38
Brian Carlstromc74255f2011-09-11 22:47:39 -070039String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070040 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070041 table.insert(std::make_pair(hash_code, s));
42 return s;
43}
44
Brian Carlstromc74255f2011-09-11 22:47:39 -070045void InternTable::RegisterStrong(String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070046 MutexLock mu(intern_table_lock_);
47 Insert(strong_interns_, s, s->GetHashCode());
48}
49
50void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) {
Elliott Hughes8daa0922011-09-11 13:46:25 -070051 intern_table_lock_.AssertHeld();
Elliott Hughescf4c6c42011-09-01 15:16:42 -070052 typedef Table::const_iterator It; // TODO: C++0x auto
53 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
54 if (it->second == s) {
55 table.erase(it);
56 return;
57 }
Brian Carlstrom7e93b502011-08-04 14:16:22 -070058 }
59}
60
Brian Carlstromc74255f2011-09-11 22:47:39 -070061String* InternTable::Insert(String* s, bool is_strong) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070062 MutexLock mu(intern_table_lock_);
63
64 DCHECK(s != NULL);
65 uint32_t hash_code = s->GetHashCode();
66
67 if (is_strong) {
68 // Check the strong table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070069 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070070 if (strong != NULL) {
71 return strong;
72 }
73
74 // There is no match in the strong table, check the weak table.
Brian Carlstromc74255f2011-09-11 22:47:39 -070075 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070076 if (weak != NULL) {
77 // A match was found in the weak table. Promote to the strong table.
78 Remove(weak_interns_, weak, hash_code);
79 return Insert(strong_interns_, weak, hash_code);
80 }
81
82 // No match in the strong table or the weak table. Insert into the strong table.
83 return Insert(strong_interns_, s, hash_code);
84 }
85
86 // Check the strong table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070087 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070088 if (strong != NULL) {
89 return strong;
90 }
91 // Check the weak table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070092 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070093 if (weak != NULL) {
94 return weak;
95 }
96 // Insert into the weak table.
97 return Insert(weak_interns_, s, hash_code);
98}
99
Brian Carlstromc74255f2011-09-11 22:47:39 -0700100String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700101 return Insert(String::AllocFromModifiedUtf8(utf16_length, utf8_data), true);
102}
103
Brian Carlstromc74255f2011-09-11 22:47:39 -0700104String* InternTable::InternStrong(const char* utf8_data) {
105 return Insert(String::AllocFromModifiedUtf8(utf8_data), true);
106}
107
108String* InternTable::InternStrong(String* s) {
109 return Insert(s, true);
110}
111
112String* InternTable::InternWeak(String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700113 return Insert(s, false);
114}
115
Brian Carlstromc74255f2011-09-11 22:47:39 -0700116bool InternTable::ContainsWeak(String* s) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700117 MutexLock mu(intern_table_lock_);
118 const String* found = Lookup(weak_interns_, s, s->GetHashCode());
119 return found == s;
120}
121
Elliott Hughes410c0c82011-09-01 17:58:25 -0700122void InternTable::RemoveWeakIf(const Predicate& predicate) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700123 MutexLock mu(intern_table_lock_);
124 typedef Table::const_iterator It; // TODO: C++0x auto
125 for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
126 if (predicate(it->second)) {
127 weak_interns_.erase(it++);
128 } else {
129 ++it;
130 }
131 }
Brian Carlstroma663ea52011-08-19 23:33:41 -0700132}
133
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700134} // namespace art