1 /** 2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef PANDA_RUNTIME_STRING_TABLE_H_ 16 #define PANDA_RUNTIME_STRING_TABLE_H_ 17 18 #include <cstdint> 19 20 #include "libpandabase/mem/mem.h" 21 #include "libpandabase/os/mutex.h" 22 #include "runtime/include/coretypes/string.h" 23 #include "runtime/include/language_context.h" 24 #include "runtime/include/mem/panda_containers.h" 25 26 namespace panda { 27 28 namespace mem::test { 29 class MultithreadedInternStringTableTest; 30 } // namespace mem::test 31 32 class StringTable { 33 public: StringTable(mem::InternalAllocatorPtr allocator)34 explicit StringTable(mem::InternalAllocatorPtr allocator) : internal_table_(allocator), table_(allocator) {} 35 StringTable() = default; 36 virtual ~StringTable() = default; 37 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, 38 const LanguageContext &ctx); 39 virtual coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 40 const LanguageContext &ctx); 41 coretypes::String *GetOrInternString(coretypes::String *string, const LanguageContext &ctx); 42 43 coretypes::String *GetOrInternInternalString(const panda_file::File &pf, panda_file::File::EntityId id, 44 const LanguageContext &ctx); 45 GetInternalStringFast(const panda_file::File & pf,panda_file::File::EntityId id)46 coretypes::String *GetInternalStringFast(const panda_file::File &pf, panda_file::File::EntityId id) 47 { 48 return internal_table_.GetStringFast(pf, id); 49 } 50 51 using StringVisitor = std::function<void(ObjectHeader *)>; 52 53 void VisitRoots(const StringVisitor &visitor, mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL) 54 { 55 internal_table_.VisitRoots(visitor, flags); 56 } 57 VisitStrings(const StringVisitor & visitor)58 void VisitStrings(const StringVisitor &visitor) 59 { 60 table_.VisitStrings(visitor); 61 } 62 63 virtual void Sweep(const GCObjectVisitor &gc_object_visitor); 64 65 bool UpdateMoved(); 66 67 size_t Size(); 68 69 protected: 70 class Table { 71 public: Table(mem::InternalAllocatorPtr allocator)72 explicit Table(mem::InternalAllocatorPtr allocator) : table_(allocator->Adapter()) {} 73 Table() = default; 74 virtual ~Table() = default; 75 76 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, 77 bool can_be_compressed, const LanguageContext &ctx); 78 virtual coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 79 const LanguageContext &ctx); 80 coretypes::String *GetOrInternString(coretypes::String *string, const LanguageContext &ctx); 81 virtual void Sweep(const GCObjectVisitor &gc_object_visitor); 82 83 bool UpdateMoved(); 84 85 void VisitStrings(const StringVisitor &visitor); 86 87 size_t Size(); 88 89 coretypes::String *GetString(const uint8_t *utf8_data, uint32_t utf16_length, bool can_be_compressed, 90 const LanguageContext &ctx); 91 coretypes::String *GetString(const uint16_t *utf16_data, uint32_t utf16_length, const LanguageContext &ctx); 92 coretypes::String *GetString(coretypes::String *string, const LanguageContext &ctx); 93 94 coretypes::String *InternString(coretypes::String *string, const LanguageContext &ctx); 95 void ForceInternString(coretypes::String *string, const LanguageContext &ctx); 96 97 protected: 98 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) GUARDED_BY(table_lock_)99 PandaUnorderedMultiMap<uint32_t, coretypes::String *> table_ GUARDED_BY(table_lock_) {}; 100 os::memory::RWLock table_lock_; // NOLINT(misc-non-private-member-variables-in-classes) 101 102 private: 103 NO_COPY_SEMANTIC(Table); 104 NO_MOVE_SEMANTIC(Table); 105 106 // Required to clear intern string in test 107 friend class mem::test::MultithreadedInternStringTableTest; 108 }; 109 110 class InternalTable : public Table { 111 public: 112 InternalTable() = default; InternalTable(mem::InternalAllocatorPtr allocator)113 explicit InternalTable(mem::InternalAllocatorPtr allocator) 114 : Table(allocator), new_string_table_(allocator->Adapter()) 115 { 116 } 117 ~InternalTable() override = default; 118 119 coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, bool can_be_compressed, 120 const LanguageContext &ctx) override; 121 122 coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 123 const LanguageContext &ctx) override; 124 125 coretypes::String *GetOrInternString(const panda_file::File &pf, panda_file::File::EntityId id, 126 const LanguageContext &ctx); 127 128 coretypes::String *GetStringFast(const panda_file::File &pf, panda_file::File::EntityId id); 129 130 void VisitRoots(const StringVisitor &visitor, 131 mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL); 132 133 protected: 134 coretypes::String *InternStringNonMovable(coretypes::String *string, const LanguageContext &ctx); 135 136 private: 137 bool record_new_string_ {false}; GUARDED_BY(table_lock_)138 PandaVector<coretypes::String *> new_string_table_ GUARDED_BY(table_lock_) {}; 139 class EntityIdEqual { 140 public: operator()141 uint32_t operator()(const panda_file::File::EntityId &id) const 142 { 143 return id.GetOffset(); 144 } 145 }; 146 PandaUnorderedMap<const panda_file::File *, 147 PandaUnorderedMap<panda_file::File::EntityId, coretypes::String *, EntityIdEqual>> 148 maps_ GUARDED_BY(maps_lock_); 149 150 os::memory::RWLock maps_lock_; 151 152 NO_COPY_SEMANTIC(InternalTable); 153 NO_MOVE_SEMANTIC(InternalTable); 154 }; 155 156 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 157 InternalTable internal_table_; // Used for string in panda file. 158 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 159 Table table_; 160 161 private: 162 NO_COPY_SEMANTIC(StringTable); 163 NO_MOVE_SEMANTIC(StringTable); 164 165 // Required to clear intern string in test 166 friend class mem::test::MultithreadedInternStringTableTest; 167 }; 168 169 } // namespace panda 170 171 #endif // PANDA_RUNTIME_STRING_TABLE_H_ 172