// Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
}
-mirror::String* InternTable::Lookup(Table& table, mirror::String* s, int32_t hash_code) {
+mirror::String* InternTable::LookupStrong(mirror::String* s, int32_t hash_code) {
+ return Lookup<kWithoutReadBarrier>(&strong_interns_, s, hash_code);
+}
+
+mirror::String* InternTable::LookupWeak(mirror::String* s, int32_t hash_code) {
+ // Weak interns need a read barrier because they are weak roots.
+ return Lookup<kWithReadBarrier>(&weak_interns_, s, hash_code);
+}
+
+template<ReadBarrierOption kReadBarrierOption>
+mirror::String* InternTable::Lookup(Table* table, mirror::String* s, int32_t hash_code) {
+ CHECK_EQ(table == &weak_interns_, kReadBarrierOption == kWithReadBarrier)
+ << "Only weak_interns_ needs a read barrier.";
Locks::intern_table_lock_->AssertHeld(Thread::Current());
- for (auto it = table.lower_bound(hash_code), end = table.end();
+ for (auto it = table->lower_bound(hash_code), end = table->end();
it != end && it->first == hash_code; ++it) {
- mirror::String* existing_string = it->second;
+ mirror::String** weak_root = &it->second;
+ mirror::String* existing_string =
+ ReadBarrier::BarrierForWeakRoot<mirror::String, kReadBarrierOption>(weak_root);
if (existing_string->Equals(s)) {
return existing_string;
}
return s;
}
+void InternTable::RemoveStrong(mirror::String* s, int32_t hash_code) {
+ Remove<kWithoutReadBarrier>(&strong_interns_, s, hash_code);
+}
+
void InternTable::RemoveWeak(mirror::String* s, int32_t hash_code) {
Runtime* runtime = Runtime::Current();
if (runtime->IsActiveTransaction()) {
runtime->RecordWeakStringRemoval(s, hash_code);
}
- Remove(weak_interns_, s, hash_code);
+ Remove<kWithReadBarrier>(&weak_interns_, s, hash_code);
}
-void InternTable::Remove(Table& table, mirror::String* s, int32_t hash_code) {
- for (auto it = table.lower_bound(hash_code), end = table.end();
+template<ReadBarrierOption kReadBarrierOption>
+void InternTable::Remove(Table* table, mirror::String* s, int32_t hash_code) {
+ CHECK_EQ(table == &weak_interns_, kReadBarrierOption == kWithReadBarrier)
+ << "Only weak_interns_ needs a read barrier.";
+ for (auto it = table->lower_bound(hash_code), end = table->end();
it != end && it->first == hash_code; ++it) {
- if (it->second == s) {
- table.erase(it);
+ mirror::String** weak_root = &it->second;
+ mirror::String* existing_string =
+ ReadBarrier::BarrierForWeakRoot<mirror::String, kReadBarrierOption>(weak_root);
+ if (existing_string == s) {
+ table->erase(it);
return;
}
}
}
void InternTable::RemoveStrongFromTransaction(mirror::String* s, int32_t hash_code) {
DCHECK(!Runtime::Current()->IsActiveTransaction());
- Remove(strong_interns_, s, hash_code);
+ RemoveStrong(s, hash_code);
}
void InternTable::RemoveWeakFromTransaction(mirror::String* s, int32_t hash_code) {
DCHECK(!Runtime::Current()->IsActiveTransaction());
- Remove(weak_interns_, s, hash_code);
+ RemoveWeak(s, hash_code);
}
static mirror::String* LookupStringFromImage(mirror::String* s)
if (is_strong) {
// Check the strong table for a match.
- mirror::String* strong = Lookup(strong_interns_, s, hash_code);
+ mirror::String* strong = LookupStrong(s, hash_code);
if (strong != NULL) {
return strong;
}
}
// There is no match in the strong table, check the weak table.
- mirror::String* weak = Lookup(weak_interns_, s, hash_code);
+ mirror::String* weak = LookupWeak(s, hash_code);
if (weak != NULL) {
// A match was found in the weak table. Promote to the strong table.
RemoveWeak(weak, hash_code);
}
// Check the strong table for a match.
- mirror::String* strong = Lookup(strong_interns_, s, hash_code);
+ mirror::String* strong = LookupStrong(s, hash_code);
if (strong != NULL) {
return strong;
}
return InsertWeak(image, hash_code);
}
// Check the weak table for a match.
- mirror::String* weak = Lookup(weak_interns_, s, hash_code);
+ mirror::String* weak = LookupWeak(s, hash_code);
if (weak != NULL) {
return weak;
}
bool InternTable::ContainsWeak(mirror::String* s) {
MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
- const mirror::String* found = Lookup(weak_interns_, s, s->GetHashCode());
+ const mirror::String* found = LookupWeak(s, s->GetHashCode());
return found == s;
}
void InternTable::SweepInternTableWeaks(IsMarkedCallback* callback, void* arg) {
MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
for (auto it = weak_interns_.begin(), end = weak_interns_.end(); it != end;) {
+ // This does not need a read barrier because this is called by GC.
mirror::Object* object = it->second;
mirror::Object* new_object = callback(object, arg);
if (new_object == nullptr) {
LOCKS_EXCLUDED(Locks::intern_table_lock_)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::String* Lookup(Table& table, mirror::String* s, int32_t hash_code)
+ mirror::String* LookupStrong(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ mirror::String* LookupWeak(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ mirror::String* Lookup(Table* table, mirror::String* s, int32_t hash_code)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::String* InsertStrong(mirror::String* s, int32_t hash_code)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
mirror::String* InsertWeak(mirror::String* s, int32_t hash_code)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
+ void RemoveStrong(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
void RemoveWeak(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
- void Remove(Table& table, mirror::String* s, int32_t hash_code)
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
+ void Remove(Table* table, mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
// Transaction rollback access.
mirror::String* InsertWeakFromTransaction(mirror::String* s, int32_t hash_code)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
void RemoveStrongFromTransaction(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
void RemoveWeakFromTransaction(mirror::String* s, int32_t hash_code)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
EXCLUSIVE_LOCKS_REQUIRED(Locks::intern_table_lock_);
friend class Transaction;
Table strong_interns_ GUARDED_BY(Locks::intern_table_lock_);
std::vector<std::pair<int32_t, mirror::String*>> new_strong_intern_roots_
GUARDED_BY(Locks::intern_table_lock_);
+ // Since weak_interns_ contain weak roots, they need a read
+ // barrier. Do not directly access the strings in it. Use functions
+ // that contain read barriers.
Table weak_interns_ GUARDED_BY(Locks::intern_table_lock_);
};