12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
167e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
177e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "intern_table.h"
187e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
19700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory>
20700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers
21e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "gc_root-inl.h"
2297509954404d031594b2ecbda607314d169d512eMathieu Chartier#include "gc/collector/garbage_collector.h"
237dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers#include "gc/space/image_space.h"
2414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier#include "gc/weak_root_state.h"
254a26f17b055cadc949c3e9fdfa637fe5656339d9Mathieu Chartier#include "image-inl.h"
2605792b98980741111b4d0a24d68cff2a8e070a3aVladimir Marko#include "mirror/dex_cache-inl.h"
277dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers#include "mirror/object_array-inl.h"
287dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers#include "mirror/object-inl.h"
29cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier#include "mirror/string-inl.h"
302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "thread.h"
31814e40397fe6c8a2c645bae99f356dbddd6dbe18Elliott Hughes#include "utf.h"
327e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
337e93b50433cde2a44d99212e8040299bde498546Brian Carlstromnamespace art {
347e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
357dfb28c066159e6cde8181720f0c451a700ef966Ian RogersInternTable::InternTable()
36ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    : images_added_to_intern_table_(false),
37ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      log_new_roots_(false),
3814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier      weak_intern_condition_("New intern condition", *Locks::intern_table_lock_),
3914c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier      weak_root_state_(gc::kWeakRootStateNormal) {
40c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier}
41de69d7f8c32be83c405bf5a9c5f15fc655f578faElliott Hughes
42a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstromsize_t InternTable::Size() const {
43d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
44eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  return strong_interns_.Size() + weak_interns_.Size();
45a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom}
46a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
47a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchisize_t InternTable::StrongSize() const {
48a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
49eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  return strong_interns_.Size();
50a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi}
51a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi
52a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchisize_t InternTable::WeakSize() const {
53a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
54eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  return weak_interns_.Size();
55a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi}
56a91a4bc1f8960f64c5f7e4616d46e21b8e1bfba2Hiroshi Yamauchi
57cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughesvoid InternTable::DumpForSigQuit(std::ostream& os) const {
58eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  os << "Intern table: " << StrongSize() << " strong; " << WeakSize() << " weak\n";
59cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes}
60cac6cc72c3331257fa6437b36a131e5d551e2f3cElliott Hughes
61bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid InternTable::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) {
62d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
63893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  if ((flags & kVisitRootFlagAllRoots) != 0) {
64bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier    strong_interns_.VisitRoots(visitor);
65893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  } else if ((flags & kVisitRootFlagNewRoots) != 0) {
66cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    for (auto& root : new_strong_intern_roots_) {
67cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier      mirror::String* old_ref = root.Read<kWithoutReadBarrier>();
68bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartier      root.VisitRoot(visitor, RootInfo(kRootInternedString));
69cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier      mirror::String* new_ref = root.Read<kWithoutReadBarrier>();
70c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      if (new_ref != old_ref) {
71cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier        // The GC moved a root in the log. Need to search the strong interns and update the
7294f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi        // corresponding object. This is slow, but luckily for us, this may only happen with a
7394f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi        // concurrent moving GC.
74eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier        strong_interns_.Remove(old_ref);
75eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier        strong_interns_.Insert(new_ref);
7694f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi      }
7794f7b49578b6aaa80de8ffed230648d601393905Hiroshi Yamauchi    }
78893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  }
79893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  if ((flags & kVisitRootFlagClearRootLog) != 0) {
80893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier    new_strong_intern_roots_.clear();
81893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  }
82893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) {
83893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier    log_new_roots_ = true;
84893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) {
85893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier    log_new_roots_ = false;
861d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  }
87423d2a3dcbb260b020efb5da59f784c9f02accbfMathieu Chartier  // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots.
88cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
89cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
90fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiermirror::String* InternTable::LookupWeak(Thread* self, mirror::String* s) {
91fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  MutexLock mu(self, *Locks::intern_table_lock_);
92fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return LookupWeakLocked(s);
93fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
94fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
95fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiermirror::String* InternTable::LookupStrong(Thread* self, mirror::String* s) {
96fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  MutexLock mu(self, *Locks::intern_table_lock_);
97fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return LookupStrongLocked(s);
981bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi}
991bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi
100cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markomirror::String* InternTable::LookupStrong(Thread* self,
101cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                          uint32_t utf16_length,
102cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                          const char* utf8_data) {
103cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  DCHECK_EQ(utf16_length, CountModifiedUtf8Chars(utf8_data));
104cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Utf8String string(utf16_length,
105cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                    utf8_data,
106cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                    ComputeUtf16HashFromModifiedUtf8(utf8_data, utf16_length));
107cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  MutexLock mu(self, *Locks::intern_table_lock_);
108cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  return strong_interns_.Find(string);
109cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
110cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
111fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiermirror::String* InternTable::LookupWeakLocked(mirror::String* s) {
112eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  return weak_interns_.Find(s);
1131bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi}
1141bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi
115fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiermirror::String* InternTable::LookupStrongLocked(mirror::String* s) {
116fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return strong_interns_.Find(s);
117fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
118fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
119ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiervoid InternTable::AddNewTable() {
120eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
121ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  weak_interns_.AddNewTable();
122ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  strong_interns_.AddNewTable();
123cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
124cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
125cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiermirror::String* InternTable::InsertStrong(mirror::String* s) {
126d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Runtime* runtime = Runtime::Current();
127d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (runtime->IsActiveTransaction()) {
128cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    runtime->RecordStrongStringInsertion(s);
129d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
130893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  if (log_new_roots_) {
131cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    new_strong_intern_roots_.push_back(GcRoot<mirror::String>(s));
132893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  }
133eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  strong_interns_.Insert(s);
134893263b7d5bc2ca43a91ecb8071867f5134fc60aMathieu Chartier  return s;
135d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
136d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
137cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiermirror::String* InternTable::InsertWeak(mirror::String* s) {
138d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Runtime* runtime = Runtime::Current();
139d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (runtime->IsActiveTransaction()) {
140cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    runtime->RecordWeakStringInsertion(s);
141d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
142eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  weak_interns_.Insert(s);
143cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  return s;
144cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
145cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
146cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiervoid InternTable::RemoveStrong(mirror::String* s) {
147eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  strong_interns_.Remove(s);
1481bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi}
1491bd4872773184fb9f5f152c7bbf9856a8235d2afHiroshi Yamauchi
150cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiervoid InternTable::RemoveWeak(mirror::String* s) {
151d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  Runtime* runtime = Runtime::Current();
152d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  if (runtime->IsActiveTransaction()) {
153cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    runtime->RecordWeakStringRemoval(s);
154d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  }
155eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  weak_interns_.Remove(s);
1567e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom}
1577e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
158d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz// Insert/remove methods used to undo changes made during an aborted transaction.
159cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiermirror::String* InternTable::InsertStrongFromTransaction(mirror::String* s) {
160d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(!Runtime::Current()->IsActiveTransaction());
161cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  return InsertStrong(s);
162d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
163cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiermirror::String* InternTable::InsertWeakFromTransaction(mirror::String* s) {
164d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(!Runtime::Current()->IsActiveTransaction());
165cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  return InsertWeak(s);
166d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
167cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiervoid InternTable::RemoveStrongFromTransaction(mirror::String* s) {
168d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(!Runtime::Current()->IsActiveTransaction());
169cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  RemoveStrong(s);
170d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
171cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartiervoid InternTable::RemoveWeakFromTransaction(mirror::String* s) {
172d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  DCHECK(!Runtime::Current()->IsActiveTransaction());
173cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  RemoveWeak(s);
174d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz}
175d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz
176205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartiervoid InternTable::AddImagesStringsToTable(const std::vector<gc::space::ImageSpace*>& image_spaces) {
177eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
178205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier  for (gc::space::ImageSpace* image_space : image_spaces) {
179205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier    const ImageHeader* const header = &image_space->GetImageHeader();
180205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier    // Check if we have the interned strings section.
181205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier    const ImageSection& section = header->GetImageSection(ImageHeader::kSectionInternedStrings);
182205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier    if (section.Size() > 0) {
183205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier      AddTableFromMemoryLocked(image_space->Begin() + section.Offset());
184205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier    } else {
185205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier      // TODO: Delete this logic?
186205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier      mirror::Object* root = header->GetImageRoot(ImageHeader::kDexCaches);
187205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier      mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
188205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier      for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
189205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier        mirror::DexCache* dex_cache = dex_caches->Get(i);
190205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier        const size_t num_strings = dex_cache->NumStrings();
191205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier        for (size_t j = 0; j < num_strings; ++j) {
192205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier          mirror::String* image_string = dex_cache->GetResolvedString(j);
193205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier          if (image_string != nullptr) {
194fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier            mirror::String* found = LookupStrongLocked(image_string);
195205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier            if (found == nullptr) {
196205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier              InsertStrong(image_string);
197205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier            } else {
198205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier              DCHECK_EQ(found, image_string);
199205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier            }
200eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier          }
201eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier        }
202eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier      }
203eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    }
204eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  }
205ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  images_added_to_intern_table_ = true;
206eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
207eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
20814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartiermirror::String* InternTable::LookupStringFromImage(mirror::String* s) {
209205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier  DCHECK(!images_added_to_intern_table_);
210ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  const std::vector<gc::space::ImageSpace*>& image_spaces =
211dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      Runtime::Current()->GetHeap()->GetBootImageSpaces();
212dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao  if (image_spaces.empty()) {
213eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    return nullptr;  // No image present.
2147dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers  }
2157dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers  const std::string utf8 = s->ToModifiedUtf8();
216dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao  for (gc::space::ImageSpace* image_space : image_spaces) {
217dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao    mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
218dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao    mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>();
219dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao    for (int32_t i = 0; i < dex_caches->GetLength(); ++i) {
220dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      mirror::DexCache* dex_cache = dex_caches->Get(i);
221dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      const DexFile* dex_file = dex_cache->GetDexFile();
222dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      // Binary search the dex file for the string index.
223dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      const DexFile::StringId* string_id = dex_file->FindStringId(utf8.c_str());
224dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao      if (string_id != nullptr) {
225dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
226dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        // GetResolvedString() contains a RB.
227dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        mirror::String* image_string = dex_cache->GetResolvedString(string_idx);
228dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        if (image_string != nullptr) {
229dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao          return image_string;
230dcdc85bbd569f0ee66c331b4219c19304a616214Jeff Hao        }
2317dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers      }
2327dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers    }
2337dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers  }
234c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  return nullptr;
2357dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers}
2367dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers
2370b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchivoid InternTable::BroadcastForNewInterns() {
2380b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi  CHECK(kUseReadBarrier);
2390b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi  Thread* self = Thread::Current();
2400b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi  MutexLock mu(self, *Locks::intern_table_lock_);
24114c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  weak_intern_condition_.Broadcast(self);
24214c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier}
24314c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier
24414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartiervoid InternTable::WaitUntilAccessible(Thread* self) {
24514c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  Locks::intern_table_lock_->ExclusiveUnlock(self);
246f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier  {
247f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    ScopedThreadSuspension sts(self, kWaitingWeakGcRootRead);
248f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    MutexLock mu(self, *Locks::intern_table_lock_);
249f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    while (weak_root_state_ == gc::kWeakRootStateNoReadsOrWrites) {
250f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier      weak_intern_condition_.Wait(self);
251f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier    }
25214c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  }
25314c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  Locks::intern_table_lock_->ExclusiveLock(self);
2540b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi}
2550b71357fb52be9bb06d35396a3042b4381b01041Hiroshi Yamauchi
25614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartiermirror::String* InternTable::Insert(mirror::String* s, bool is_strong, bool holding_locks) {
257c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  if (s == nullptr) {
258c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier    return nullptr;
259c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  }
26014c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  Thread* const self = Thread::Current();
261d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(self, *Locks::intern_table_lock_);
26214c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  if (kDebugLocking && !holding_locks) {
26314c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    Locks::mutator_lock_->AssertSharedHeld(self);
26414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    CHECK_EQ(2u, self->NumberOfHeldMutexes()) << "may only safely hold the mutator lock";
265c11d9b8870de5f860b13c84003ade7b3f3125a52Mathieu Chartier  }
26614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  while (true) {
26790ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    if (holding_locks) {
26890ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier      if (!kUseReadBarrier) {
26990ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier        CHECK_EQ(weak_root_state_, gc::kWeakRootStateNormal);
27090ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier      } else {
27190ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier        CHECK(self->GetWeakRefAccessEnabled());
27290ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier      }
27390ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    }
27414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    // Check the strong table for a match.
275fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    mirror::String* strong = LookupStrongLocked(s);
27614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    if (strong != nullptr) {
27714c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier      return strong;
27814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    }
27990ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    if ((!kUseReadBarrier && weak_root_state_ != gc::kWeakRootStateNoReadsOrWrites) ||
28090ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier        (kUseReadBarrier && self->GetWeakRefAccessEnabled())) {
28190ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier      break;
28290ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    }
28314c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    // weak_root_state_ is set to gc::kWeakRootStateNoReadsOrWrites in the GC pause but is only
28414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    // cleared after SweepSystemWeaks has completed. This is why we need to wait until it is
28514c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    // cleared.
28614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    CHECK(!holding_locks);
28714c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    StackHandleScope<1> hs(self);
28814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    auto h = hs.NewHandleWrapper(&s);
28914c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    WaitUntilAccessible(self);
290cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
29190ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier  if (!kUseReadBarrier) {
29290ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    CHECK_EQ(weak_root_state_, gc::kWeakRootStateNormal);
29390ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier  } else {
29490ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier    CHECK(self->GetWeakRefAccessEnabled());
29590ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartier  }
296c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  // There is no match in the strong table, check the weak table.
297fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  mirror::String* weak = LookupWeakLocked(s);
298c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  if (weak != nullptr) {
299c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier    if (is_strong) {
300c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      // A match was found in the weak table. Promote to the strong table.
301c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      RemoveWeak(weak);
302c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      return InsertStrong(weak);
303c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier    }
304cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes    return weak;
305cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes  }
306a446d8671b30438003472c1de1363fc0699a7f7bnikolay serdjuk  // Check the image for a match.
307ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  if (!images_added_to_intern_table_) {
308ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    mirror::String* const image_string = LookupStringFromImage(s);
309ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    if (image_string != nullptr) {
310ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      return is_strong ? InsertStrong(image_string) : InsertWeak(image_string);
311ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
312a446d8671b30438003472c1de1363fc0699a7f7bnikolay serdjuk  }
313c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  // No match in the strong table or the weak table. Insert into the strong / weak table.
314c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  return is_strong ? InsertStrong(s) : InsertWeak(s);
315cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
316cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
317ed0fc1d42f097be7bed090f19abdf7c0fd227820Mathieu Chartiermirror::String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) {
318ed0fc1d42f097be7bed090f19abdf7c0fd227820Mathieu Chartier  DCHECK(utf8_data != nullptr);
3197dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers  return InternStrong(mirror::String::AllocFromModifiedUtf8(
3207dfb28c066159e6cde8181720f0c451a700ef966Ian Rogers      Thread::Current(), utf16_length, utf8_data));
3217e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom}
3227e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom
3232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersmirror::String* InternTable::InternStrong(const char* utf8_data) {
324ed0fc1d42f097be7bed090f19abdf7c0fd227820Mathieu Chartier  DCHECK(utf8_data != nullptr);
325ed0fc1d42f097be7bed090f19abdf7c0fd227820Mathieu Chartier  return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data));
326c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom}
327c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom
32890ef3db4bd1d4865f5f9cb95c8e7d9afb46994f9Mathieu Chartiermirror::String* InternTable::InternStrongImageString(mirror::String* s) {
32914c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  // May be holding the heap bitmap lock.
33014c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  return Insert(s, true, true);
33114c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier}
33214c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier
3332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersmirror::String* InternTable::InternStrong(mirror::String* s) {
33414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  return Insert(s, true, false);
335c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom}
336c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom
3372dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersmirror::String* InternTable::InternWeak(mirror::String* s) {
33814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  return Insert(s, false, false);
339cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
340cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
3412dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogersbool InternTable::ContainsWeak(mirror::String* s) {
342fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return LookupWeak(Thread::Current(), s) == s;
343cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes}
344cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes
34597509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid InternTable::SweepInternTableWeaks(IsMarkedVisitor* visitor) {
346d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
34797509954404d031594b2ecbda607314d169d512eMathieu Chartier  weak_interns_.SweepWeaks(visitor);
348a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom}
349a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
350ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiersize_t InternTable::AddTableFromMemory(const uint8_t* ptr) {
351d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
352ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  return AddTableFromMemoryLocked(ptr);
353d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}
354d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier
355ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiersize_t InternTable::AddTableFromMemoryLocked(const uint8_t* ptr) {
356ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  return strong_interns_.AddTableFromMemory(ptr);
357d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}
358d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier
359d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartiersize_t InternTable::WriteToMemory(uint8_t* ptr) {
360d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
361ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  return strong_interns_.WriteToMemory(ptr);
362d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}
363d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier
364c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartierstd::size_t InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& root) const {
365cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  if (kIsDebugBuild) {
366cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
367cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  }
368c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  return static_cast<size_t>(root.Read()->GetHashCode());
369cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier}
370cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier
371cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartierbool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
372c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier                                               const GcRoot<mirror::String>& b) const {
373cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  if (kIsDebugBuild) {
374cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
375cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier  }
376c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier  return a.Read()->Equals(b.Read());
377cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier}
378cdfd39f579574a75b98e7ad48c69826b00361b27Mathieu Chartier
379cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markobool InternTable::StringHashEquals::operator()(const GcRoot<mirror::String>& a,
380cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko                                               const Utf8String& b) const {
381cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (kIsDebugBuild) {
382cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
383cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
384cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  mirror::String* a_string = a.Read();
385cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  uint32_t a_length = static_cast<uint32_t>(a_string->GetLength());
386cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  if (a_length != b.GetUtf16Length()) {
387cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    return false;
388cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
389cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  const uint16_t* a_value = a_string->GetValue();
390cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  return CompareModifiedUtf8ToUtf16AsCodePointValues(b.GetUtf8Data(), a_value, a_length) == 0;
391cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
392cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
393ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiersize_t InternTable::Table::AddTableFromMemory(const uint8_t* ptr) {
394d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier  size_t read_count = 0;
395ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  UnorderedSet set(ptr, /*make copy*/false, &read_count);
3965ef868c8332db11bb90284887a7f676f5dbef373Mathieu Chartier  if (set.Empty()) {
3975ef868c8332db11bb90284887a7f676f5dbef373Mathieu Chartier    // Avoid inserting empty sets.
3985ef868c8332db11bb90284887a7f676f5dbef373Mathieu Chartier    return read_count;
3995ef868c8332db11bb90284887a7f676f5dbef373Mathieu Chartier  }
400ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  // TODO: Disable this for app images if app images have intern tables.
401ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  static constexpr bool kCheckDuplicates = true;
402ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  if (kCheckDuplicates) {
403ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    for (GcRoot<mirror::String>& string : set) {
404ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      CHECK(Find(string.Read()) == nullptr) << "Already found " << string.Read()->ToModifiedUtf8();
405ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
406ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  }
4075ef868c8332db11bb90284887a7f676f5dbef373Mathieu Chartier  // Insert at the front since we add new interns into the back.
408ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  tables_.insert(tables_.begin(), std::move(set));
409d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier  return read_count;
410d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}
411d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier
412ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiersize_t InternTable::Table::WriteToMemory(uint8_t* ptr) {
413ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  if (tables_.empty()) {
414ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    return 0;
415ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  }
416ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  UnorderedSet* table_to_write;
417ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  UnorderedSet combined;
418ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  if (tables_.size() > 1) {
419ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    table_to_write = &combined;
420ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    for (UnorderedSet& table : tables_) {
421ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      for (GcRoot<mirror::String>& string : table) {
422ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier        combined.Insert(string);
423ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      }
424ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
425ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  } else {
426ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    table_to_write = &tables_.back();
427ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  }
428ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  return table_to_write->WriteToMemory(ptr);
429d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier}
430d39645e22b8db1767cf64dc1200a9e4b2f939ed2Mathieu Chartier
431eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartiervoid InternTable::Table::Remove(mirror::String* s) {
432ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  for (UnorderedSet& table : tables_) {
433ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    auto it = table.Find(GcRoot<mirror::String>(s));
434ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    if (it != table.end()) {
435ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      table.Erase(it);
436ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      return;
437ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
438eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  }
439ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  LOG(FATAL) << "Attempting to remove non-interned string " << s->ToModifiedUtf8();
440eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
441eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
442eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartiermirror::String* InternTable::Table::Find(mirror::String* s) {
443eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  Locks::intern_table_lock_->AssertHeld(Thread::Current());
444ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  for (UnorderedSet& table : tables_) {
445ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    auto it = table.Find(GcRoot<mirror::String>(s));
446ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    if (it != table.end()) {
447ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      return it->Read();
448ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
449eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  }
450eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  return nullptr;
451eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
452eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
453cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Markomirror::String* InternTable::Table::Find(const Utf8String& string) {
454cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  Locks::intern_table_lock_->AssertHeld(Thread::Current());
455cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  for (UnorderedSet& table : tables_) {
456cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    auto it = table.Find(string);
457cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    if (it != table.end()) {
458cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      return it->Read();
459cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    }
460cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
461cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  return nullptr;
462cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko}
463cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
464ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartiervoid InternTable::Table::AddNewTable() {
465ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  tables_.push_back(UnorderedSet());
466eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
467eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
468eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartiervoid InternTable::Table::Insert(mirror::String* s) {
469ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  // Always insert the last table, the image tables are before and we avoid inserting into these
470ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  // to prevent dirty pages.
471ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  DCHECK(!tables_.empty());
472ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  tables_.back().Insert(GcRoot<mirror::String>(s));
473eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
474eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
475bb87e0f1a52de656bc77cb01cb887e51a0e5198bMathieu Chartiervoid InternTable::Table::VisitRoots(RootVisitor* visitor) {
4764809d0a8a5fca85a67dd0588ead5dfbd0f1acf96Mathieu Chartier  BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(
4774809d0a8a5fca85a67dd0588ead5dfbd0f1acf96Mathieu Chartier      visitor, RootInfo(kRootInternedString));
478ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  for (UnorderedSet& table : tables_) {
479ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    for (auto& intern : table) {
480ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier      buffered_visitor.VisitRoot(intern);
481ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    }
482eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  }
483eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
484eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
48597509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid InternTable::Table::SweepWeaks(IsMarkedVisitor* visitor) {
486ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  for (UnorderedSet& table : tables_) {
487ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier    SweepWeaks(&table, visitor);
488ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  }
489eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
490eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
49197509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid InternTable::Table::SweepWeaks(UnorderedSet* set, IsMarkedVisitor* visitor) {
492eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  for (auto it = set->begin(), end = set->end(); it != end;) {
493eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    // This does not need a read barrier because this is called by GC.
494c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier    mirror::Object* object = it->Read<kWithoutReadBarrier>();
49597509954404d031594b2ecbda607314d169d512eMathieu Chartier    mirror::Object* new_object = visitor->IsMarked(object);
496eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    if (new_object == nullptr) {
497c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      it = set->Erase(it);
498eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    } else {
499c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier      *it = GcRoot<mirror::String>(new_object->AsString());
500eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier      ++it;
501eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier    }
502eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier  }
503eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier}
504eb175f70ef352ce0b9bcafdf06c5ac22b0ff626aMathieu Chartier
505c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartiersize_t InternTable::Table::Size() const {
506ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  return std::accumulate(tables_.begin(),
507ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier                         tables_.end(),
508205b7624e434050125ada92a318cdc2655ac7b4aMathieu Chartier                         0U,
509ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier                         [](size_t sum, const UnorderedSet& set) {
510ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier                           return sum + set.Size();
511ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier                         });
512c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier}
513c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier
51414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartiervoid InternTable::ChangeWeakRootState(gc::WeakRootState new_state) {
51514c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
51614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  ChangeWeakRootStateLocked(new_state);
51714c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier}
51814c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier
51914c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartiervoid InternTable::ChangeWeakRootStateLocked(gc::WeakRootState new_state) {
520fdbd13c7af91a042eda753e436eeebf0e1937250Hiroshi Yamauchi  CHECK(!kUseReadBarrier);
52114c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  weak_root_state_ = new_state;
52214c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  if (new_state != gc::kWeakRootStateNoReadsOrWrites) {
52314c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier    weak_intern_condition_.Broadcast(Thread::Current());
52414c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier  }
52514c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier}
52614c3bf91b2ec434295ec84d6446f495fb7de6d5cMathieu Chartier
52732cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu ChartierInternTable::Table::Table() {
52832cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier  Runtime* const runtime = Runtime::Current();
529ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  // Initial table.
530ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  tables_.push_back(UnorderedSet());
531ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier  tables_.back().SetLoadFactor(runtime->GetHashTableMinLoadFactor(),
532ea0831f60d26e3297e6463634a9fbb6384f00661Mathieu Chartier                               runtime->GetHashTableMaxLoadFactor());
53332cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier}
53432cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier
5357e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom}  // namespace art
536