1 /* 2 * Copyright (c) 2021 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 16 #ifndef PANDA_RUNTIME_STRING_TABLE_H_ 17 #define PANDA_RUNTIME_STRING_TABLE_H_ 18 19 #include <cstdint> 20 21 #include "libpandabase/mem/mem.h" 22 #include "libpandabase/os/mutex.h" 23 #include "runtime/include/coretypes/string.h" 24 #include "runtime/include/language_context.h" 25 #include "runtime/include/mem/panda_containers.h" 26 27 namespace panda { 28 29 namespace mem::test { 30 class MultithreadedInternStringTableTest; 31 } // namespace mem::test 32 33 class StringTable { 34 public: StringTable(mem::InternalAllocatorPtr allocator)35 explicit StringTable(mem::InternalAllocatorPtr allocator) : internal_table_(allocator), table_(allocator) {} 36 StringTable() = default; 37 virtual ~StringTable() = default; 38 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, LanguageContext ctx); 39 virtual coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 40 LanguageContext ctx); 41 coretypes::String *GetOrInternString(coretypes::String *string, LanguageContext ctx); 42 43 coretypes::String *GetOrInternInternalString(const panda_file::File &pf, panda_file::File::EntityId id, 44 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(coretypes::String *)>; 52 53 void VisitRoots(const StringVisitor &visitor, mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL) 54 { 55 internal_table_.VisitRoots(visitor, flags); 56 } 57 58 virtual void Sweep(const GCObjectVisitor &gc_object_visitor); 59 60 bool UpdateMoved(); 61 62 size_t Size(); 63 64 protected: 65 class Table { 66 public: Table(mem::InternalAllocatorPtr allocator)67 explicit Table(mem::InternalAllocatorPtr allocator) : table_(allocator->Adapter()) {} 68 Table() = default; 69 virtual ~Table() = default; 70 71 virtual coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, 72 bool can_be_compressed, LanguageContext ctx); 73 virtual coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 74 LanguageContext ctx); 75 coretypes::String *GetOrInternString(coretypes::String *string, LanguageContext ctx); 76 virtual void Sweep(const GCObjectVisitor &gc_object_visitor); 77 78 bool UpdateMoved(); 79 80 size_t Size(); 81 82 coretypes::String *GetString(const uint8_t *utf8_data, uint32_t utf16_length, bool can_be_compressed, 83 LanguageContext ctx); 84 coretypes::String *GetString(const uint16_t *utf16_data, uint32_t utf16_length, LanguageContext ctx); 85 coretypes::String *GetString(coretypes::String *string, LanguageContext ctx); 86 87 coretypes::String *InternString(coretypes::String *string, LanguageContext ctx); 88 void ForceInternString(coretypes::String *string, LanguageContext ctx); 89 90 protected: 91 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) GUARDED_BY(table_lock_)92 PandaUnorderedMultiMap<uint32_t, coretypes::String *> table_ GUARDED_BY(table_lock_) {}; 93 os::memory::RWLock table_lock_; // NOLINT(misc-non-private-member-variables-in-classes) 94 private: 95 NO_COPY_SEMANTIC(Table); 96 NO_MOVE_SEMANTIC(Table); 97 98 // Required to clear intern string in test 99 friend class mem::test::MultithreadedInternStringTableTest; 100 }; 101 102 class InternalTable : public Table { 103 public: 104 InternalTable() = default; InternalTable(mem::InternalAllocatorPtr allocator)105 explicit InternalTable(mem::InternalAllocatorPtr allocator) 106 : Table(allocator), new_string_table_(allocator->Adapter()) 107 { 108 } 109 ~InternalTable() override = default; 110 111 coretypes::String *GetOrInternString(const uint8_t *mutf8_data, uint32_t utf16_length, bool can_be_compressed, 112 LanguageContext ctx) override; 113 114 coretypes::String *GetOrInternString(const uint16_t *utf16_data, uint32_t utf16_length, 115 LanguageContext ctx) override; 116 117 coretypes::String *GetOrInternString(const panda_file::File &pf, panda_file::File::EntityId id, 118 LanguageContext ctx); 119 120 coretypes::String *GetStringFast(const panda_file::File &pf, panda_file::File::EntityId id); 121 122 void VisitRoots(const StringVisitor &visitor, 123 mem::VisitGCRootFlags flags = mem::VisitGCRootFlags::ACCESS_ROOT_ALL); 124 125 protected: 126 coretypes::String *InternStringNonMovable(coretypes::String *string, LanguageContext ctx); 127 128 private: 129 bool record_new_string_ {false}; GUARDED_BY(table_lock_)130 PandaVector<coretypes::String *> new_string_table_ GUARDED_BY(table_lock_) {}; 131 class EntityIdEqual { 132 public: operator()133 uint32_t operator()(const panda_file::File::EntityId &id) const 134 { 135 return id.GetOffset(); 136 } 137 }; 138 PandaUnorderedMap<const panda_file::File *, 139 PandaUnorderedMap<panda_file::File::EntityId, coretypes::String *, EntityIdEqual>> 140 maps_ GUARDED_BY(maps_lock_); 141 142 os::memory::RWLock maps_lock_; 143 144 NO_COPY_SEMANTIC(InternalTable); 145 NO_MOVE_SEMANTIC(InternalTable); 146 }; 147 148 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 149 InternalTable internal_table_; // Used for string in panda file. 150 // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 151 Table table_; 152 153 private: 154 NO_COPY_SEMANTIC(StringTable); 155 NO_MOVE_SEMANTIC(StringTable); 156 157 // Required to clear intern string in test 158 friend class mem::test::MultithreadedInternStringTableTest; 159 }; 160 161 } // namespace panda 162 163 #endif // PANDA_RUNTIME_STRING_TABLE_H_ 164