1 /** 2 * Copyright (c) 2021-2025 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 ark { 27 28 namespace mem::test { 29 class MultithreadedInternStringTableTest; 30 } // namespace mem::test 31 32 class PANDA_PUBLIC_API StringTable { 33 public: StringTable(mem::InternalAllocatorPtr allocator)34 explicit StringTable(mem::InternalAllocatorPtr allocator) : internalTable_(allocator), table_(allocator) {} 35 StringTable() = default; 36 virtual ~StringTable() = default; 37 38 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8Data, uint32_t utf16Length, 39 const LanguageContext &ctx); 40 virtual coretypes::String *GetOrInternString(const uint16_t *utf16Data, uint32_t utf16Length, 41 const LanguageContext &ctx); 42 coretypes::String *GetOrInternString(coretypes::String *string, const LanguageContext &ctx); 43 44 coretypes::String *GetOrInternInternalString(const panda_file::File &pf, panda_file::File::EntityId id, 45 const LanguageContext &ctx); 46 GetInternalStringFast(const panda_file::File & pf,panda_file::File::EntityId id)47 coretypes::String *GetInternalStringFast(const panda_file::File &pf, panda_file::File::EntityId id) 48 { 49 return internalTable_.GetStringFast(pf, id); 50 } 51 52 using StringVisitor = std::function<void(ObjectHeader *)>; 53 54 void VisitRoots(const StringVisitor &visitor, mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL) 55 { 56 internalTable_.VisitRoots(visitor, flags); 57 } 58 VisitStrings(const StringVisitor & visitor)59 void VisitStrings(const StringVisitor &visitor) 60 { 61 table_.VisitStrings(visitor); 62 } 63 64 virtual void Sweep(const GCObjectVisitor &gcObjectVisitor); 65 66 bool UpdateMoved(const GCRootUpdater &gcRootUpdater); 67 68 size_t Size(); 69 70 protected: 71 class PANDA_PUBLIC_API Table { 72 public: Table(mem::InternalAllocatorPtr allocator)73 explicit Table(mem::InternalAllocatorPtr allocator) : table_(allocator->Adapter()) {} 74 Table() = default; 75 virtual ~Table() = default; 76 77 void PreBarrierOnGet(coretypes::String *str); 78 79 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8Data, uint32_t utf16Length, 80 bool canBeCompressed, const LanguageContext &ctx); 81 virtual coretypes::String *GetOrInternString(const uint16_t *utf16Data, uint32_t utf16Length, 82 const LanguageContext &ctx); 83 virtual coretypes::String *GetOrInternString(coretypes::String *string, const LanguageContext &ctx); 84 virtual void Sweep(const GCObjectVisitor &gcObjectVisitor); 85 86 bool UpdateMoved(const GCRootUpdater &gcRootUpdater); 87 88 void VisitStrings(const StringVisitor &visitor); 89 90 size_t Size(); 91 92 coretypes::String *GetString(const uint8_t *utf8Data, uint32_t utf16Length, bool canBeCompressed, 93 const LanguageContext &ctx); 94 coretypes::String *GetString(const uint16_t *utf16Data, uint32_t utf16Length, const LanguageContext &ctx); 95 coretypes::String *GetString(coretypes::String *string, const LanguageContext &ctx); 96 97 coretypes::String *InternString(coretypes::String *string, const LanguageContext &ctx); 98 void ForceInternString(coretypes::String *string, const LanguageContext &ctx); 99 100 protected: 101 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) GUARDED_BY(tableLock_)102 PandaUnorderedMultiMap<uint32_t, coretypes::String *> table_ GUARDED_BY(tableLock_) {}; 103 os::memory::RWLock tableLock_; // NOLINT(misc-non-private-member-variables-in-classes) 104 105 private: 106 NO_COPY_SEMANTIC(Table); 107 NO_MOVE_SEMANTIC(Table); 108 109 // Required to clear intern string in test 110 friend class mem::test::MultithreadedInternStringTableTest; 111 }; 112 113 class PANDA_PUBLIC_API InternalTable : public Table { 114 public: 115 InternalTable() = default; InternalTable(mem::InternalAllocatorPtr allocator)116 explicit InternalTable(mem::InternalAllocatorPtr allocator) 117 : Table(allocator), newStringTable_(allocator->Adapter()) 118 { 119 } 120 ~InternalTable() override = default; 121 122 void PreBarrierOnGet(coretypes::String *str) = delete; 123 124 coretypes::String *GetOrInternString(const uint8_t *mutf8Data, uint32_t utf16Length, bool canBeCompressed, 125 const LanguageContext &ctx) override; 126 127 coretypes::String *GetOrInternString(const uint16_t *utf16Data, uint32_t utf16Length, 128 const LanguageContext &ctx) override; 129 130 coretypes::String *GetOrInternString(coretypes::String *string, const LanguageContext &ctx) override; 131 132 coretypes::String *GetOrInternString(const panda_file::File &pf, panda_file::File::EntityId id, 133 const LanguageContext &ctx); 134 135 coretypes::String *GetStringFast(const panda_file::File &pf, panda_file::File::EntityId id); 136 137 void VisitRoots(const StringVisitor &visitor, 138 mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL); 139 140 protected: 141 coretypes::String *InternStringNonMovable(coretypes::String *string, const LanguageContext &ctx); 142 143 private: 144 bool recordNewString_ {false}; GUARDED_BY(tableLock_)145 PandaVector<coretypes::String *> newStringTable_ GUARDED_BY(tableLock_) {}; 146 class EntityIdEqual { 147 public: operator()148 uint32_t operator()(const panda_file::File::EntityId &id) const 149 { 150 return id.GetOffset(); 151 } 152 }; 153 PandaUnorderedMap<const panda_file::File *, 154 PandaUnorderedMap<panda_file::File::EntityId, coretypes::String *, EntityIdEqual>> 155 maps_ GUARDED_BY(mapsLock_); 156 157 os::memory::RWLock mapsLock_; 158 159 NO_COPY_SEMANTIC(InternalTable); 160 NO_MOVE_SEMANTIC(InternalTable); 161 }; 162 163 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 164 InternalTable internalTable_; // Used for string in panda file. 165 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 166 Table table_; 167 168 private: 169 NO_COPY_SEMANTIC(StringTable); 170 NO_MOVE_SEMANTIC(StringTable); 171 172 // Required to clear intern string in test 173 friend class mem::test::MultithreadedInternStringTableTest; 174 }; 175 176 } // namespace ark 177 178 #endif // PANDA_RUNTIME_STRING_TABLE_H_ 179