blob: 817ce1e5e12f8eeb0cd7137c75f5fb3b85f4fcdd [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
Elliott Hughes90a33692011-08-30 13:27:07 -070019#include "UniquePtr.h"
Elliott Hughes814e4032011-08-23 12:07:56 -070020#include "utf.h"
Brian Carlstrom7e93b502011-08-04 14:16:22 -070021
22namespace art {
23
Mathieu Chartier9ebae1f2012-10-15 17:38:16 -070024InternTable::InternTable() : intern_table_lock_("InternTable lock"), is_dirty_(false) {
Elliott Hughesde69d7f2011-08-18 16:49:37 -070025}
26
Brian Carlstroma663ea52011-08-19 23:33:41 -070027size_t InternTable::Size() const {
Ian Rogers50b35e22012-10-04 10:09:15 -070028 MutexLock mu(Thread::Current(), intern_table_lock_);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070029 return strong_interns_.size() + weak_interns_.size();
Brian Carlstroma663ea52011-08-19 23:33:41 -070030}
31
Elliott Hughescac6cc72011-11-03 20:31:21 -070032void InternTable::DumpForSigQuit(std::ostream& os) const {
Ian Rogers50b35e22012-10-04 10:09:15 -070033 MutexLock mu(Thread::Current(), intern_table_lock_);
Elliott Hughescac6cc72011-11-03 20:31:21 -070034 os << "Intern table: " << strong_interns_.size() << " strong; "
35 << weak_interns_.size() << " weak; "
36 << image_strong_interns_.size() << " image strong\n";
37}
38
Mathieu Chartier9ebae1f2012-10-15 17:38:16 -070039void InternTable::VisitRoots(Heap::RootVisitor* visitor, void* arg) {
Ian Rogers50b35e22012-10-04 10:09:15 -070040 MutexLock mu(Thread::Current(), intern_table_lock_);
Brian Carlstrom7e93b502011-08-04 14:16:22 -070041 typedef Table::const_iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -070042 for (It it = strong_interns_.begin(), end = strong_interns_.end(); it != end; ++it) {
Elliott Hughes410c0c82011-09-01 17:58:25 -070043 visitor(it->second, arg);
Brian Carlstrom7e93b502011-08-04 14:16:22 -070044 }
Mathieu Chartier9ebae1f2012-10-15 17:38:16 -070045 is_dirty_ = false;
Ian Rogers5d76c432011-10-31 21:42:49 -070046 // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
Brian Carlstrom7e93b502011-08-04 14:16:22 -070047}
48
Brian Carlstromc74255f2011-09-11 22:47:39 -070049String* InternTable::Lookup(Table& table, String* s, uint32_t hash_code) {
Ian Rogers50b35e22012-10-04 10:09:15 -070050 intern_table_lock_.AssertHeld(Thread::Current());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070051 typedef Table::const_iterator It; // TODO: C++0x auto
52 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
Brian Carlstromc74255f2011-09-11 22:47:39 -070053 String* existing_string = it->second;
Elliott Hughescf4c6c42011-09-01 15:16:42 -070054 if (existing_string->Equals(s)) {
55 return existing_string;
Brian Carlstrom7e93b502011-08-04 14:16:22 -070056 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070057 }
58 return NULL;
59}
60
Brian Carlstromc74255f2011-09-11 22:47:39 -070061String* InternTable::Insert(Table& table, String* s, uint32_t hash_code) {
Ian Rogers50b35e22012-10-04 10:09:15 -070062 intern_table_lock_.AssertHeld(Thread::Current());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070063 table.insert(std::make_pair(hash_code, s));
64 return s;
65}
66
Brian Carlstromc74255f2011-09-11 22:47:39 -070067void InternTable::RegisterStrong(String* s) {
Ian Rogers50b35e22012-10-04 10:09:15 -070068 MutexLock mu(Thread::Current(), intern_table_lock_);
Ian Rogers5d76c432011-10-31 21:42:49 -070069 Insert(image_strong_interns_, s, s->GetHashCode());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070070}
71
72void InternTable::Remove(Table& table, const String* s, uint32_t hash_code) {
Ian Rogers50b35e22012-10-04 10:09:15 -070073 intern_table_lock_.AssertHeld(Thread::Current());
Elliott Hughese5448b52012-01-18 16:44:06 -080074 typedef Table::iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -070075 for (It it = table.find(hash_code), end = table.end(); it != end; ++it) {
76 if (it->second == s) {
77 table.erase(it);
78 return;
79 }
Brian Carlstrom7e93b502011-08-04 14:16:22 -070080 }
81}
82
Brian Carlstromc74255f2011-09-11 22:47:39 -070083String* InternTable::Insert(String* s, bool is_strong) {
Ian Rogers50b35e22012-10-04 10:09:15 -070084 MutexLock mu(Thread::Current(), intern_table_lock_);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070085
86 DCHECK(s != NULL);
87 uint32_t hash_code = s->GetHashCode();
88
89 if (is_strong) {
jeffhaob1c6f342012-03-20 17:57:26 -070090 // Check the strong table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -070091 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -070092 if (strong != NULL) {
93 return strong;
94 }
jeffhaob1c6f342012-03-20 17:57:26 -070095 // Check the image table for a match.
96 String* image = Lookup(image_strong_interns_, s, hash_code);
97 if (image != NULL) {
98 return image;
Ian Rogers5d76c432011-10-31 21:42:49 -070099 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700100
Mathieu Chartier9ebae1f2012-10-15 17:38:16 -0700101 // Mark as dirty so that we rescan the roots.
102 Dirty();
103
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700104 // There is no match in the strong table, check the weak table.
Brian Carlstromc74255f2011-09-11 22:47:39 -0700105 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700106 if (weak != NULL) {
107 // A match was found in the weak table. Promote to the strong table.
108 Remove(weak_interns_, weak, hash_code);
109 return Insert(strong_interns_, weak, hash_code);
110 }
111
112 // No match in the strong table or the weak table. Insert into the strong table.
113 return Insert(strong_interns_, s, hash_code);
114 }
115
116 // Check the strong table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -0700117 String* strong = Lookup(strong_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700118 if (strong != NULL) {
119 return strong;
120 }
jeffhaob1c6f342012-03-20 17:57:26 -0700121 // Check the image table for a match.
122 String* image = Lookup(image_strong_interns_, s, hash_code);
123 if (image != NULL) {
124 return image;
125 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700126 // Check the weak table for a match.
Brian Carlstromc74255f2011-09-11 22:47:39 -0700127 String* weak = Lookup(weak_interns_, s, hash_code);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700128 if (weak != NULL) {
129 return weak;
130 }
131 // Insert into the weak table.
132 return Insert(weak_interns_, s, hash_code);
133}
134
Brian Carlstromc74255f2011-09-11 22:47:39 -0700135String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700136 return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf16_length, utf8_data));
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700137}
138
Brian Carlstromc74255f2011-09-11 22:47:39 -0700139String* InternTable::InternStrong(const char* utf8_data) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700140 return InternStrong(String::AllocFromModifiedUtf8(Thread::Current(), utf8_data));
Brian Carlstromc74255f2011-09-11 22:47:39 -0700141}
142
143String* InternTable::InternStrong(String* s) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700144 if (s == NULL) {
145 return NULL;
146 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700147 return Insert(s, true);
148}
149
150String* InternTable::InternWeak(String* s) {
Elliott Hughes37d4e6b2011-10-13 12:05:20 -0700151 if (s == NULL) {
152 return NULL;
153 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700154 return Insert(s, false);
155}
156
Brian Carlstromc74255f2011-09-11 22:47:39 -0700157bool InternTable::ContainsWeak(String* s) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700158 MutexLock mu(Thread::Current(), intern_table_lock_);
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700159 const String* found = Lookup(weak_interns_, s, s->GetHashCode());
160 return found == s;
161}
162
Elliott Hughesc33a32b2011-10-11 18:18:07 -0700163void InternTable::SweepInternTableWeaks(Heap::IsMarkedTester is_marked, void* arg) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700164 MutexLock mu(Thread::Current(), intern_table_lock_);
Elliott Hughese5448b52012-01-18 16:44:06 -0800165 typedef Table::iterator It; // TODO: C++0x auto
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700166 for (It it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
Elliott Hughesc33a32b2011-10-11 18:18:07 -0700167 Object* object = it->second;
168 if (!is_marked(object, arg)) {
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700169 weak_interns_.erase(it++);
170 } else {
171 ++it;
172 }
173 }
Brian Carlstroma663ea52011-08-19 23:33:41 -0700174}
175
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700176} // namespace art