1 /* 2 * Copyright (c) 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 16 #ifndef COMMON_COMPONENTS_OBJECTS_STRING_TABLE_INTERNAL_H 17 #define COMMON_COMPONENTS_OBJECTS_STRING_TABLE_INTERNAL_H 18 19 #include "common_components/base/globals.h" 20 #include "common_components/platform/mutex.h" 21 #include "common_interfaces/thread/thread_holder.h" 22 #include "common_interfaces/objects/base_string_table.h" 23 #include "common_components/objects/string_table/hashtriemap.h" 24 #include "common_components/taskpool/task.h" 25 26 namespace common { 27 28 class BaseStringTableMutex { 29 public: mtx_(isInit)30 explicit BaseStringTableMutex(bool isInit = true) : mtx_(isInit) {} 31 LockWithThreadState(ThreadHolder * holder)32 void LockWithThreadState(ThreadHolder* holder) 33 { 34 if (mtx_.TryLock()) { 35 return; 36 } 37 #ifndef NDEBUG 38 BaseRuntime::RequestGC(GC_REASON_USER, true, GC_TYPE_FULL); // Trigger CMC FULL GC 39 #endif 40 ThreadStateTransitionScope<ThreadHolder, ThreadState::WAIT> ts(holder); 41 mtx_.Lock(); 42 } 43 Lock()44 void Lock() 45 { 46 return mtx_.Lock(); 47 } 48 Unlock()49 void Unlock() 50 { 51 return mtx_.Unlock(); 52 } 53 54 private: 55 Mutex mtx_; 56 }; 57 58 template<bool ConcurrentSweep> 59 class BaseStringTableInternal; 60 61 class BaseStringTableCleaner { 62 public: 63 using IteratorPtr = std::shared_ptr<std::atomic<uint32_t>>; BaseStringTableCleaner(BaseStringTableInternal<true> * stringTable)64 BaseStringTableCleaner(BaseStringTableInternal<true>* stringTable) : stringTable_(stringTable) {} ~BaseStringTableCleaner()65 ~BaseStringTableCleaner() 66 { 67 stringTable_ = nullptr; 68 } 69 void PostSweepWeakRefTask(const WeakRefFieldVisitor &visitor); 70 void JoinAndWaitSweepWeakRefTask(const WeakRefFieldVisitor &visitor); 71 72 void CleanUp(); 73 private: 74 NO_COPY_SEMANTIC(BaseStringTableCleaner); 75 NO_MOVE_SEMANTIC(BaseStringTableCleaner); 76 static void ProcessSweepWeakRef(IteratorPtr &iter, 77 BaseStringTableCleaner *cleaner, 78 const WeakRefFieldVisitor &visitor); 79 80 void StartSweepWeakRefTask(); 81 void WaitSweepWeakRefTask(); 82 void SignalSweepWeakRefTask(); 83 GetNextIndexId(IteratorPtr & iter)84 static inline uint32_t GetNextIndexId(IteratorPtr &iter) 85 { 86 return iter->fetch_add(1U, std::memory_order_relaxed); 87 } 88 ReduceCountAndCheckFinish(BaseStringTableCleaner * cleaner)89 static inline bool ReduceCountAndCheckFinish(BaseStringTableCleaner *cleaner) 90 { 91 return (cleaner->PendingTaskCount_.fetch_sub(1U, std::memory_order_relaxed) == 1U); 92 } 93 94 class CMCSweepWeakRefTask : public Task { 95 public: CMCSweepWeakRefTask(IteratorPtr iter,BaseStringTableCleaner * cleaner,const WeakRefFieldVisitor & visitor)96 CMCSweepWeakRefTask(IteratorPtr iter, BaseStringTableCleaner *cleaner, 97 const WeakRefFieldVisitor &visitor) 98 : Task(0), iter_(iter), cleaner_(cleaner), visitor_(visitor) {} 99 ~CMCSweepWeakRefTask() = default; 100 101 bool Run(uint32_t threadIndex) override; 102 103 NO_COPY_SEMANTIC(CMCSweepWeakRefTask); 104 NO_MOVE_SEMANTIC(CMCSweepWeakRefTask); 105 106 private: 107 IteratorPtr iter_; 108 BaseStringTableCleaner *cleaner_; 109 const WeakRefFieldVisitor &visitor_; 110 }; 111 112 IteratorPtr iter_{}; 113 BaseStringTableInternal<true>* stringTable_; 114 std::atomic<uint32_t> PendingTaskCount_{0U}; 115 std::array<std::vector<HashTrieMapEntry*>, TrieMapConfig::ROOT_SIZE> waitFreeEntries_{}; 116 Mutex sweepWeakRefMutex_{}; 117 bool sweepWeakRefFinished_{true}; 118 ConditionVariable sweepWeakRefCV_{}; 119 }; 120 121 template<bool ConcurrentSweep> 122 class BaseStringTableInternal { 123 public: 124 using HandleCreator = BaseStringTableInterface<BaseStringTableImpl>::HandleCreator; 125 using HashTrieMapType = std::conditional_t<ConcurrentSweep, 126 HashTrieMap<BaseStringTableMutex, ThreadHolder, TrieMapConfig::NeedSlotBarrier>, 127 HashTrieMap<BaseStringTableMutex, ThreadHolder, TrieMapConfig::NoSlotBarrier>>; 128 129 template <bool B = ConcurrentSweep, std::enable_if_t<B, int> = 0> BaseStringTableInternal()130 BaseStringTableInternal(): cleaner_(new BaseStringTableCleaner(this)) {} 131 132 template <bool B = ConcurrentSweep, std::enable_if_t<!B, int> = 0> BaseStringTableInternal()133 BaseStringTableInternal() {} 134 ~BaseStringTableInternal()135 ~BaseStringTableInternal() 136 { 137 if constexpr (ConcurrentSweep) { 138 delete cleaner_; 139 } 140 } 141 142 BaseString *GetOrInternFlattenString(ThreadHolder *holder, const HandleCreator &handleCreator, BaseString *string); 143 144 BaseString *GetOrInternStringFromCompressedSubString(ThreadHolder *holder, const HandleCreator &handleCreator, 145 const ReadOnlyHandle<BaseString> &string, uint32_t offset, 146 uint32_t utf8Len); 147 148 BaseString *GetOrInternString(ThreadHolder *holder, const HandleCreator &handleCreator, const uint8_t *utf8Data, 149 uint32_t utf8Len, bool canBeCompress); 150 151 BaseString *GetOrInternString(ThreadHolder *holder, const HandleCreator &handleCreator, const uint16_t *utf16Data, 152 uint32_t utf16Len, bool canBeCompress); 153 154 BaseString *TryGetInternString(const ReadOnlyHandle<BaseString> &string); 155 GetHashTrieMap()156 HashTrieMapType &GetHashTrieMap() 157 { 158 return stringTable_; 159 } 160 GetCleaner()161 BaseStringTableCleaner *GetCleaner() 162 { 163 return cleaner_; 164 } 165 166 template <bool B = ConcurrentSweep, std::enable_if_t<B, int> = 0> 167 void SweepWeakRef(const WeakRefFieldVisitor& visitor, uint32_t rootID, 168 std::vector<HashTrieMapEntry*>& waitDeleteEntries); 169 170 template <bool B = ConcurrentSweep, std::enable_if_t<B, int> = 0> 171 void CleanUp(); 172 173 template <bool B = ConcurrentSweep, std::enable_if_t<!B, int> = 0> 174 void SweepWeakRef(const WeakRefFieldVisitor& visitor); 175 private: 176 177 HashTrieMapType stringTable_{}; 178 BaseStringTableCleaner* cleaner_ = nullptr; 179 static BaseString* AllocateLineStringObject(size_t size); 180 static constexpr size_t MAX_REGULAR_HEAP_OBJECT_SIZE = 32 * KB; 181 }; 182 183 class BaseStringTableImpl : public BaseStringTableInterface<BaseStringTableImpl> { 184 public: 185 BaseString* GetOrInternFlattenString(ThreadHolder* holder, const HandleCreator& handleCreator, BaseString* string); 186 187 BaseString* GetOrInternStringFromCompressedSubString(ThreadHolder* holder, const HandleCreator& handleCreator, 188 const ReadOnlyHandle<BaseString>& string, uint32_t offset, 189 uint32_t utf8Len); 190 191 BaseString* GetOrInternString(ThreadHolder* holder, const HandleCreator& handleCreator, const uint8_t* utf8Data, 192 uint32_t utf8Len, bool canBeCompress); 193 194 BaseString* GetOrInternString(ThreadHolder* holder, const HandleCreator& handleCreator, const uint16_t* utf16Data, 195 uint32_t utf16Len, bool canBeCompress); 196 197 BaseString* TryGetInternString(const ReadOnlyHandle<BaseString>& string); 198 GetInternalTable()199 auto* GetInternalTable() 200 { 201 return &stringTable_; 202 } 203 private: 204 #ifndef GC_STW_STRINGTABLE 205 BaseStringTableInternal<true> stringTable_{}; 206 #else 207 BaseStringTableInternal<false> stringTable_{}; 208 #endif 209 }; 210 } 211 #endif //COMMON_COMPONENTS_OBJECTS_STRING_TABLE_INTERNAL_H 212