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