blob: 7d5be299ccfb28ddb454bd7094849ae99d04e3a6 [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
10InternTable::InternTable() {
11 intern_table_lock_ = Mutex::Create("InternTable::Lock");
12}
13
Elliott Hughesde69d7f2011-08-18 16:49:37 -070014InternTable::~InternTable() {
15 delete intern_table_lock_;
16}
17
Brian Carlstroma663ea52011-08-19 23:33:41 -070018size_t InternTable::Size() const {
Elliott Hughescf4c6c42011-09-01 15:16:42 -070019 MutexLock mu(intern_table_lock_);
20 return strong_interns_.size() + weak_interns_.size();
Brian Carlstroma663ea52011-08-19 23:33:41 -070021}
22
23void InternTable::VisitRoots(Heap::RootVistor* root_visitor, void* arg) const {
Brian Carlstrom7e93b502011-08-04 14:16:22 -070024 MutexLock mu(intern_table_lock_);
25 typedef Table::const_iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -070026 for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
Brian Carlstroma663ea52011-08-19 23:33:41 -070027 root_visitor(it->second, arg);
Brian Carlstrom7e93b502011-08-04 14:16:22 -070028 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070029 // Note: we deliberately don't visit the weak_interns_ table.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070030}
31
Elliott Hughescf4c6c42011-09-01 15:16:42 -070032const String* InternTable::Lookup(Table& table, const String* s, uint32_t hash_code) {
33 // Requires the intern_table_lock_.
34 typedef Table::const_iterator It; // TODO: C++0x auto
35 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
36 const String* existing_string = it->second;
37 if (existing_string->Equals(s)) {
38 return existing_string;
Brian Carlstrom7e93b502011-08-04 14:16:22 -070039 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070040 }
41 return NULL;
42}
43
44const String* InternTable::Insert(Table& table, const String* s, uint32_t hash_code) {
45 // Requires the intern_table_lock_.
46 table.insert(std::make_pair(hash_code, s));
47 return s;
48}
49
50void InternTable::RegisterStrong(const String* s) {
51 MutexLock mu(intern_table_lock_);
52 Insert(strong_interns_, s, s->GetHashCode());
53}
54
55void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) {
56 // Requires the intern_table_lock_.
57 typedef Table::const_iterator It; // TODO: C++0x auto
58 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
59 if (it->second == s) {
60 table.erase(it);
61 return;
62 }
Brian Carlstrom7e93b502011-08-04 14:16:22 -070063 }
64}
65
Elliott Hughescf4c6c42011-09-01 15:16:42 -070066const String* InternTable::Insert(const String* s, bool is_strong) {
67 MutexLock mu(intern_table_lock_);
68
69 DCHECK(s != NULL);
70 uint32_t hash_code = s->GetHashCode();
71
72 if (is_strong) {
73 // Check the strong table for a match.
74 const String* strong = Lookup(strong_interns_, s, hash_code);
75 if (strong != NULL) {
76 return strong;
77 }
78
79 // There is no match in the strong table, check the weak table.
80 const String* weak = Lookup(weak_interns_, s, hash_code);
81 if (weak != NULL) {
82 // A match was found in the weak table. Promote to the strong table.
83 Remove(weak_interns_, weak, hash_code);
84 return Insert(strong_interns_, weak, hash_code);
85 }
86
87 // No match in the strong table or the weak table. Insert into the strong table.
88 return Insert(strong_interns_, s, hash_code);
89 }
90
91 // Check the strong table for a match.
92 const String* strong = Lookup(strong_interns_, s, hash_code);
93 if (strong != NULL) {
94 return strong;
95 }
96 // Check the weak table for a match.
97 const String* weak = Lookup(weak_interns_, s, hash_code);
98 if (weak != NULL) {
99 return weak;
100 }
101 // Insert into the weak table.
102 return Insert(weak_interns_, s, hash_code);
103}
104
105const String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
106 return Insert(String::AllocFromModifiedUtf8(utf16_length, utf8_data), true);
107}
108
109const String* InternTable::InternWeak(const String* s) {
110 return Insert(s, false);
111}
112
113bool InternTable::ContainsWeak(const String* s) {
114 MutexLock mu(intern_table_lock_);
115 const String* found = Lookup(weak_interns_, s, s->GetHashCode());
116 return found == s;
117}
118
119void InternTable::RemoveWeakIf(bool (*predicate)(const String*)) {
120 MutexLock mu(intern_table_lock_);
121 typedef Table::const_iterator It; // TODO: C++0x auto
122 for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
123 if (predicate(it->second)) {
124 weak_interns_.erase(it++);
125 } else {
126 ++it;
127 }
128 }
Brian Carlstroma663ea52011-08-19 23:33:41 -0700129}
130
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700131} // namespace art