1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_INTERN_TABLE_INL_H_ 18 #define ART_RUNTIME_INTERN_TABLE_INL_H_ 19 20 #include "intern_table.h" 21 22 // Required for ToModifiedUtf8 below. 23 #include "mirror/string-inl.h" 24 25 namespace art { 26 27 template <typename Visitor> 28 inline void InternTable::AddImageStringsToTable(gc::space::ImageSpace* image_space, 29 const Visitor& visitor) { 30 DCHECK(image_space != nullptr); 31 // Only add if we have the interned strings section. 32 const ImageHeader& header = image_space->GetImageHeader(); 33 const ImageSection& section = header.GetInternedStringsSection(); 34 if (section.Size() > 0) { 35 AddTableFromMemory(image_space->Begin() + section.Offset(), visitor, !header.IsAppImage()); 36 } 37 } 38 39 template <typename Visitor> 40 inline size_t InternTable::AddTableFromMemory(const uint8_t* ptr, 41 const Visitor& visitor, 42 bool is_boot_image) { 43 size_t read_count = 0; 44 UnorderedSet set(ptr, /*make copy*/false, &read_count); 45 { 46 // Hold the lock while calling the visitor to prevent possible race 47 // conditions with another thread adding intern strings. 48 MutexLock mu(Thread::Current(), *Locks::intern_table_lock_); 49 // Visit the unordered set, may remove elements. 50 visitor(set); 51 if (!set.empty()) { 52 strong_interns_.AddInternStrings(std::move(set), is_boot_image); 53 } 54 } 55 return read_count; 56 } 57 58 inline void InternTable::Table::AddInternStrings(UnorderedSet&& intern_strings, 59 bool is_boot_image) { 60 static constexpr bool kCheckDuplicates = kIsDebugBuild; 61 if (kCheckDuplicates) { 62 // Avoid doing read barriers since the space might not yet be added to the heap. 63 // See b/117803941 64 for (GcRoot<mirror::String>& string : intern_strings) { 65 CHECK(Find(string.Read<kWithoutReadBarrier>()) == nullptr) 66 << "Already found " << string.Read<kWithoutReadBarrier>()->ToModifiedUtf8() 67 << " in the intern table"; 68 } 69 } 70 // Insert at the front since we add new interns into the back. 71 tables_.insert(tables_.begin(), 72 InternalTable(std::move(intern_strings), is_boot_image)); 73 } 74 75 template <typename Visitor> 76 inline void InternTable::VisitInterns(const Visitor& visitor, 77 bool visit_boot_images, 78 bool visit_non_boot_images) { 79 auto visit_tables = [&](std::vector<Table::InternalTable>& tables) 80 NO_THREAD_SAFETY_ANALYSIS { 81 for (Table::InternalTable& table : tables) { 82 // Determine if we want to visit the table based on the flags.. 83 const bool visit = 84 (visit_boot_images && table.IsBootImage()) || 85 (visit_non_boot_images && !table.IsBootImage()); 86 if (visit) { 87 for (auto& intern : table.set_) { 88 visitor(intern); 89 } 90 } 91 } 92 }; 93 visit_tables(strong_interns_.tables_); 94 visit_tables(weak_interns_.tables_); 95 } 96 97 inline size_t InternTable::CountInterns(bool visit_boot_images, 98 bool visit_non_boot_images) const { 99 size_t ret = 0u; 100 auto visit_tables = [&](const std::vector<Table::InternalTable>& tables) 101 NO_THREAD_SAFETY_ANALYSIS { 102 for (const Table::InternalTable& table : tables) { 103 // Determine if we want to visit the table based on the flags.. 104 const bool visit = 105 (visit_boot_images && table.IsBootImage()) || 106 (visit_non_boot_images && !table.IsBootImage()); 107 if (visit) { 108 ret += table.set_.size(); 109 } 110 } 111 }; 112 visit_tables(strong_interns_.tables_); 113 visit_tables(weak_interns_.tables_); 114 return ret; 115 } 116 117 } // namespace art 118 119 #endif // ART_RUNTIME_INTERN_TABLE_INL_H_ 120