14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/ecma_string_table.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/ecma_string-inl.h" 194514f5e3Sopenharmony_ci#include "ecmascript/runtime_lock.h" 204514f5e3Sopenharmony_cinamespace panda::ecmascript { 214514f5e3Sopenharmony_civoid EcmaStringTableCleaner::PostSweepWeakRefTask(const WeakRootVisitor &visitor) 224514f5e3Sopenharmony_ci{ 234514f5e3Sopenharmony_ci StartSweepWeakRefTask(); 244514f5e3Sopenharmony_ci iter_ = std::make_shared<std::atomic<uint32_t>>(0U); 254514f5e3Sopenharmony_ci const uint32_t postTaskCount = Taskpool::GetCurrentTaskpool()->GetTotalThreadNum(); 264514f5e3Sopenharmony_ci for (uint32_t i = 0U; i < postTaskCount; ++i) { 274514f5e3Sopenharmony_ci Taskpool::GetCurrentTaskpool()->PostTask(std::make_unique<SweepWeakRefTask>(iter_, this, visitor)); 284514f5e3Sopenharmony_ci } 294514f5e3Sopenharmony_ci} 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_civoid EcmaStringTableCleaner::JoinAndWaitSweepWeakRefTask(const WeakRootVisitor &visitor) 324514f5e3Sopenharmony_ci{ 334514f5e3Sopenharmony_ci ProcessSweepWeakRef(iter_, this, visitor); 344514f5e3Sopenharmony_ci WaitSweepWeakRefTask(); 354514f5e3Sopenharmony_ci iter_.reset(); 364514f5e3Sopenharmony_ci} 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_civoid EcmaStringTableCleaner::ProcessSweepWeakRef(IteratorPtr& iter, EcmaStringTableCleaner *cleaner, 394514f5e3Sopenharmony_ci const WeakRootVisitor &visitor) 404514f5e3Sopenharmony_ci{ 414514f5e3Sopenharmony_ci uint32_t tableId = 0U; 424514f5e3Sopenharmony_ci while ((tableId = GetNextTableId(iter)) < EcmaStringTable::SEGMENT_COUNT) { 434514f5e3Sopenharmony_ci cleaner->stringTable_->SweepWeakRef(visitor, tableId); 444514f5e3Sopenharmony_ci if (ReduceCountAndCheckFinish(cleaner)) { 454514f5e3Sopenharmony_ci cleaner->SignalSweepWeakRefTask(); 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci } 484514f5e3Sopenharmony_ci} 494514f5e3Sopenharmony_ci 504514f5e3Sopenharmony_civoid EcmaStringTableCleaner::StartSweepWeakRefTask() 514514f5e3Sopenharmony_ci{ 524514f5e3Sopenharmony_ci // No need lock here, only the daemon thread will reset the state. 534514f5e3Sopenharmony_ci sweepWeakRefFinished_ = false; 544514f5e3Sopenharmony_ci PendingTaskCount_.store(EcmaStringTable::SEGMENT_COUNT, std::memory_order_relaxed); 554514f5e3Sopenharmony_ci} 564514f5e3Sopenharmony_ci 574514f5e3Sopenharmony_civoid EcmaStringTableCleaner::WaitSweepWeakRefTask() 584514f5e3Sopenharmony_ci{ 594514f5e3Sopenharmony_ci LockHolder holder(sweepWeakRefMutex_); 604514f5e3Sopenharmony_ci while (!sweepWeakRefFinished_) { 614514f5e3Sopenharmony_ci sweepWeakRefCV_.Wait(&sweepWeakRefMutex_); 624514f5e3Sopenharmony_ci } 634514f5e3Sopenharmony_ci} 644514f5e3Sopenharmony_ci 654514f5e3Sopenharmony_civoid EcmaStringTableCleaner::SignalSweepWeakRefTask() 664514f5e3Sopenharmony_ci{ 674514f5e3Sopenharmony_ci LockHolder holder(sweepWeakRefMutex_); 684514f5e3Sopenharmony_ci sweepWeakRefFinished_ = true; 694514f5e3Sopenharmony_ci sweepWeakRefCV_.SignalAll(); 704514f5e3Sopenharmony_ci} 714514f5e3Sopenharmony_ci 724514f5e3Sopenharmony_cibool EcmaStringTableCleaner::SweepWeakRefTask::Run([[maybe_unused]] uint32_t threadIndex) 734514f5e3Sopenharmony_ci{ 744514f5e3Sopenharmony_ci ProcessSweepWeakRef(iter_, cleaner_, visitor_); 754514f5e3Sopenharmony_ci return true; 764514f5e3Sopenharmony_ci} 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_cistd::pair<EcmaString *, uint32_t> EcmaStringTable::GetStringThreadUnsafe(const JSHandle<EcmaString> &firstString, 794514f5e3Sopenharmony_ci const JSHandle<EcmaString> &secondString, 804514f5e3Sopenharmony_ci uint32_t hashcode) const 814514f5e3Sopenharmony_ci{ 824514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(firstString).NotTreeString()); 834514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(secondString).NotTreeString()); 844514f5e3Sopenharmony_ci auto range = stringTable_[GetTableId(hashcode)].table_.equal_range(hashcode); 854514f5e3Sopenharmony_ci for (auto item = range.first; item != range.second;) { 864514f5e3Sopenharmony_ci auto foundString = (item++)->second; 874514f5e3Sopenharmony_ci if (EcmaStringAccessor(foundString).EqualToSplicedString(*firstString, *secondString)) { 884514f5e3Sopenharmony_ci return std::make_pair(foundString, hashcode); 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci } 914514f5e3Sopenharmony_ci return std::make_pair(nullptr, hashcode); 924514f5e3Sopenharmony_ci} 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_cistd::pair<EcmaString *, uint32_t> EcmaStringTable::GetStringThreadUnsafe(const uint8_t *utf8Data, uint32_t utf8Len, 954514f5e3Sopenharmony_ci bool canBeCompress, uint32_t hashcode) const 964514f5e3Sopenharmony_ci{ 974514f5e3Sopenharmony_ci auto range = stringTable_[GetTableId(hashcode)].table_.equal_range(hashcode); 984514f5e3Sopenharmony_ci for (auto item = range.first; item != range.second;) { 994514f5e3Sopenharmony_ci auto foundString = (item++)->second; 1004514f5e3Sopenharmony_ci if (EcmaStringAccessor::StringIsEqualUint8Data(foundString, utf8Data, utf8Len, canBeCompress)) { 1014514f5e3Sopenharmony_ci return std::make_pair(foundString, hashcode); 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci } 1044514f5e3Sopenharmony_ci return std::make_pair(nullptr, hashcode); 1054514f5e3Sopenharmony_ci} 1064514f5e3Sopenharmony_ci 1074514f5e3Sopenharmony_cistd::pair<EcmaString *, uint32_t> EcmaStringTable::GetStringThreadUnsafe(const uint16_t *utf16Data, 1084514f5e3Sopenharmony_ci uint32_t utf16Len, uint32_t hashcode) const 1094514f5e3Sopenharmony_ci{ 1104514f5e3Sopenharmony_ci auto range = stringTable_[GetTableId(hashcode)].table_.equal_range(hashcode); 1114514f5e3Sopenharmony_ci for (auto item = range.first; item != range.second;) { 1124514f5e3Sopenharmony_ci auto foundString = (item++)->second; 1134514f5e3Sopenharmony_ci if (EcmaStringAccessor::StringsAreEqualUtf16(foundString, utf16Data, utf16Len)) { 1144514f5e3Sopenharmony_ci return std::make_pair(foundString, hashcode); 1154514f5e3Sopenharmony_ci } 1164514f5e3Sopenharmony_ci } 1174514f5e3Sopenharmony_ci return std::make_pair(nullptr, hashcode); 1184514f5e3Sopenharmony_ci} 1194514f5e3Sopenharmony_ci 1204514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetStringWithHashThreadUnsafe(EcmaString *string, uint32_t hashcode) const 1214514f5e3Sopenharmony_ci{ 1224514f5e3Sopenharmony_ci auto range = stringTable_[GetTableId(hashcode)].table_.equal_range(hashcode); 1234514f5e3Sopenharmony_ci for (auto item = range.first; item != range.second;) { 1244514f5e3Sopenharmony_ci auto foundString = (item++)->second; 1254514f5e3Sopenharmony_ci if (EcmaStringAccessor::StringsAreEqual(foundString, string)) { 1264514f5e3Sopenharmony_ci return foundString; 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci } 1294514f5e3Sopenharmony_ci return nullptr; 1304514f5e3Sopenharmony_ci} 1314514f5e3Sopenharmony_ci 1324514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetStringThreadUnsafe(EcmaString *string, uint32_t hashcode) const 1334514f5e3Sopenharmony_ci{ 1344514f5e3Sopenharmony_ci auto range = stringTable_[GetTableId(hashcode)].table_.equal_range(hashcode); 1354514f5e3Sopenharmony_ci for (auto item = range.first; item != range.second;) { 1364514f5e3Sopenharmony_ci auto foundString = (item++)->second; 1374514f5e3Sopenharmony_ci if (EcmaStringAccessor::StringsAreEqual(foundString, string)) { 1384514f5e3Sopenharmony_ci return foundString; 1394514f5e3Sopenharmony_ci } 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci return nullptr; 1424514f5e3Sopenharmony_ci} 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_civoid EcmaStringTable::InternStringThreadUnsafe(EcmaString *string, uint32_t hashcode) 1454514f5e3Sopenharmony_ci{ 1464514f5e3Sopenharmony_ci if (EcmaStringAccessor(string).IsInternString()) { 1474514f5e3Sopenharmony_ci return; 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci // Strings in string table should not be in the young space. 1504514f5e3Sopenharmony_ci ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InSharedHeap()); 1514514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(string).NotTreeString()); 1524514f5e3Sopenharmony_ci stringTable_[GetTableId(hashcode)].table_.emplace(hashcode, string); 1534514f5e3Sopenharmony_ci EcmaStringAccessor(string).SetInternString(); 1544514f5e3Sopenharmony_ci} 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_civoid EcmaStringTable::InternEmptyString(JSThread *thread, EcmaString *emptyStr) 1574514f5e3Sopenharmony_ci{ 1584514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(emptyStr).GetHashcode(); 1594514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, stringTable_[GetTableId(hashcode)].mutex_); 1604514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 1614514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 1624514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 1634514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 1644514f5e3Sopenharmony_ci } 1654514f5e3Sopenharmony_ci#endif 1664514f5e3Sopenharmony_ci InternStringThreadUnsafe(emptyStr, hashcode); 1674514f5e3Sopenharmony_ci} 1684514f5e3Sopenharmony_ci 1694514f5e3Sopenharmony_civoid EcmaStringTable::InsertStringIfNotExistThreadUnsafe(EcmaString *string) 1704514f5e3Sopenharmony_ci{ 1714514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(string).GetHashcode(); 1724514f5e3Sopenharmony_ci EcmaString *str = GetStringThreadUnsafe(string, hashcode); 1734514f5e3Sopenharmony_ci if (str == nullptr) { 1744514f5e3Sopenharmony_ci InternStringThreadUnsafe(string, hashcode); 1754514f5e3Sopenharmony_ci } 1764514f5e3Sopenharmony_ci} 1774514f5e3Sopenharmony_ci 1784514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternString(EcmaVM *vm, const JSHandle<EcmaString> &firstString, 1794514f5e3Sopenharmony_ci const JSHandle<EcmaString> &secondString) 1804514f5e3Sopenharmony_ci{ 1814514f5e3Sopenharmony_ci JSThread *thread = nullptr; 1824514f5e3Sopenharmony_ci bool signalState = vm->GetJsDebuggerManager()->GetSignalState(); 1834514f5e3Sopenharmony_ci thread = signalState ? vm->GetJSThreadNoCheck() : vm->GetJSThread(); 1844514f5e3Sopenharmony_ci auto firstFlat = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(vm, firstString)); 1854514f5e3Sopenharmony_ci auto secondFlat = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(vm, secondString)); 1864514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::CalculateAllConcatHashCode(firstFlat, secondFlat); 1874514f5e3Sopenharmony_ci if (signalState) { 1884514f5e3Sopenharmony_ci return GetOrInternStringWithoutLock(thread, firstString, secondString, hashcode); 1894514f5e3Sopenharmony_ci } 1904514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, stringTable_[GetTableId(hashcode)].mutex_); 1914514f5e3Sopenharmony_ci return GetOrInternStringWithoutLock(thread, firstString, secondString, hashcode); 1924514f5e3Sopenharmony_ci} 1934514f5e3Sopenharmony_ci 1944514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringWithoutLock(JSThread *thread, const JSHandle<EcmaString> &firstString, 1954514f5e3Sopenharmony_ci const JSHandle<EcmaString> &secondString, uint32_t hashcode) 1964514f5e3Sopenharmony_ci{ 1974514f5e3Sopenharmony_ci EcmaVM *vm = thread->GetEcmaVM(); 1984514f5e3Sopenharmony_ci auto firstFlat = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(vm, firstString)); 1994514f5e3Sopenharmony_ci auto secondFlat = JSHandle<EcmaString>(thread, EcmaStringAccessor::Flatten(vm, secondString)); 2004514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 2014514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 2024514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci#endif 2054514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(firstFlat, secondFlat, hashcode); 2064514f5e3Sopenharmony_ci if (result.first != nullptr) { 2074514f5e3Sopenharmony_ci return result.first; 2084514f5e3Sopenharmony_ci } 2094514f5e3Sopenharmony_ci JSHandle<EcmaString> concatHandle(thread, 2104514f5e3Sopenharmony_ci EcmaStringAccessor::Concat(vm, firstFlat, secondFlat, MemSpaceType::SHARED_OLD_SPACE)); 2114514f5e3Sopenharmony_ci EcmaString *concatString = EcmaStringAccessor::Flatten(vm, concatHandle, MemSpaceType::SHARED_OLD_SPACE); 2124514f5e3Sopenharmony_ci concatString->SetMixHashcode(result.second); 2134514f5e3Sopenharmony_ci InternStringThreadUnsafe(concatString, hashcode); 2144514f5e3Sopenharmony_ci return concatString; 2154514f5e3Sopenharmony_ci} 2164514f5e3Sopenharmony_ci 2174514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternString(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, 2184514f5e3Sopenharmony_ci bool canBeCompress) 2194514f5e3Sopenharmony_ci{ 2204514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress); 2214514f5e3Sopenharmony_ci if (vm->GetJsDebuggerManager()->GetSignalState()) { 2224514f5e3Sopenharmony_ci return GetOrInternStringWithoutLock(vm, utf8Data, utf8Len, canBeCompress, hashcode); 2234514f5e3Sopenharmony_ci } else { 2244514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 2254514f5e3Sopenharmony_ci return GetOrInternStringWithoutLock(vm, utf8Data, utf8Len, canBeCompress, hashcode); 2264514f5e3Sopenharmony_ci } 2274514f5e3Sopenharmony_ci} 2284514f5e3Sopenharmony_ci 2294514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringWithoutLock(EcmaVM *vm, const uint8_t *utf8Data, 2304514f5e3Sopenharmony_ci uint32_t utf8Len, bool canBeCompress, uint32_t hashcode) 2314514f5e3Sopenharmony_ci{ 2324514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 2334514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 2344514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 2354514f5e3Sopenharmony_ci } 2364514f5e3Sopenharmony_ci#endif 2374514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf8Data, utf8Len, canBeCompress, hashcode); 2384514f5e3Sopenharmony_ci if (result.first != nullptr) { 2394514f5e3Sopenharmony_ci return result.first; 2404514f5e3Sopenharmony_ci } 2414514f5e3Sopenharmony_ci 2424514f5e3Sopenharmony_ci EcmaString *str = 2434514f5e3Sopenharmony_ci EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, MemSpaceType::SHARED_OLD_SPACE); 2444514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 2454514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 2464514f5e3Sopenharmony_ci return str; 2474514f5e3Sopenharmony_ci} 2484514f5e3Sopenharmony_ci 2494514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternCompressedSubString(EcmaVM *vm, const JSHandle<EcmaString> &string, 2504514f5e3Sopenharmony_ci uint32_t offset, uint32_t utf8Len) 2514514f5e3Sopenharmony_ci{ 2524514f5e3Sopenharmony_ci auto *utf8Data = EcmaStringAccessor(string).GetDataUtf8() + offset; 2534514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, true); 2544514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 2554514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 2564514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 2574514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 2584514f5e3Sopenharmony_ci } 2594514f5e3Sopenharmony_ci#endif 2604514f5e3Sopenharmony_ci // utf8data may be moved after shared full gc, so reload utf8Data here. 2614514f5e3Sopenharmony_ci utf8Data = EcmaStringAccessor(string).GetDataUtf8() + offset; 2624514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf8Data, utf8Len, true, hashcode); 2634514f5e3Sopenharmony_ci if (result.first != nullptr) { 2644514f5e3Sopenharmony_ci return result.first; 2654514f5e3Sopenharmony_ci } 2664514f5e3Sopenharmony_ci 2674514f5e3Sopenharmony_ci EcmaString *str = EcmaStringAccessor::CreateFromUtf8CompressedSubString( 2684514f5e3Sopenharmony_ci vm, string, offset, utf8Len, MemSpaceType::SHARED_OLD_SPACE); 2694514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 2704514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 2714514f5e3Sopenharmony_ci return str; 2724514f5e3Sopenharmony_ci} 2734514f5e3Sopenharmony_ci 2744514f5e3Sopenharmony_ci/* 2754514f5e3Sopenharmony_ci This function is used to create global constant strings from non-movable sapce only. 2764514f5e3Sopenharmony_ci It only inserts string into string-table and provides no string-table validity check. 2774514f5e3Sopenharmony_ci*/ 2784514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::CreateAndInternStringNonMovable(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len) 2794514f5e3Sopenharmony_ci{ 2804514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, true); 2814514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 2824514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 2834514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 2844514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 2854514f5e3Sopenharmony_ci } 2864514f5e3Sopenharmony_ci#endif 2874514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf8Data, utf8Len, true, hashcode); 2884514f5e3Sopenharmony_ci if (result.first != nullptr) { 2894514f5e3Sopenharmony_ci return result.first; 2904514f5e3Sopenharmony_ci } 2914514f5e3Sopenharmony_ci EcmaString *str = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, true, MemSpaceType::SHARED_NON_MOVABLE); 2924514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 2934514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 2944514f5e3Sopenharmony_ci return str; 2954514f5e3Sopenharmony_ci} 2964514f5e3Sopenharmony_ci 2974514f5e3Sopenharmony_ci/* 2984514f5e3Sopenharmony_ci This function is used to create global constant strings from read-only sapce only. 2994514f5e3Sopenharmony_ci It only inserts string into string-table and provides no string-table validity check. 3004514f5e3Sopenharmony_ci*/ 3014514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::CreateAndInternStringReadOnly(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, 3024514f5e3Sopenharmony_ci bool canBeCompress) 3034514f5e3Sopenharmony_ci{ 3044514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress); 3054514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 3064514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 3074514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 3084514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 3094514f5e3Sopenharmony_ci } 3104514f5e3Sopenharmony_ci#endif 3114514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf8Data, utf8Len, canBeCompress, hashcode); 3124514f5e3Sopenharmony_ci if (result.first != nullptr) { 3134514f5e3Sopenharmony_ci return result.first; 3144514f5e3Sopenharmony_ci } 3154514f5e3Sopenharmony_ci EcmaString *str = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, 3164514f5e3Sopenharmony_ci MemSpaceType::SHARED_READ_ONLY_SPACE); 3174514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 3184514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 3194514f5e3Sopenharmony_ci return str; 3204514f5e3Sopenharmony_ci} 3214514f5e3Sopenharmony_ci 3224514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternString(EcmaVM *vm, const uint16_t *utf16Data, uint32_t utf16Len, 3234514f5e3Sopenharmony_ci bool canBeCompress) 3244514f5e3Sopenharmony_ci{ 3254514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf16(const_cast<uint16_t *>(utf16Data), utf16Len); 3264514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 3274514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 3284514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 3294514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 3304514f5e3Sopenharmony_ci } 3314514f5e3Sopenharmony_ci#endif 3324514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf16Data, utf16Len, hashcode); 3334514f5e3Sopenharmony_ci if (result.first != nullptr) { 3344514f5e3Sopenharmony_ci return result.first; 3354514f5e3Sopenharmony_ci } 3364514f5e3Sopenharmony_ci 3374514f5e3Sopenharmony_ci EcmaString *str = 3384514f5e3Sopenharmony_ci EcmaStringAccessor::CreateFromUtf16(vm, utf16Data, utf16Len, canBeCompress, MemSpaceType::SHARED_OLD_SPACE); 3394514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 3404514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 3414514f5e3Sopenharmony_ci return str; 3424514f5e3Sopenharmony_ci} 3434514f5e3Sopenharmony_ci 3444514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternString(EcmaVM *vm, EcmaString *string) 3454514f5e3Sopenharmony_ci{ 3464514f5e3Sopenharmony_ci if (EcmaStringAccessor(string).IsInternString()) { 3474514f5e3Sopenharmony_ci return string; 3484514f5e3Sopenharmony_ci } 3494514f5e3Sopenharmony_ci auto thread = vm->GetJSThread(); 3504514f5e3Sopenharmony_ci JSHandle<EcmaString> strHandle(thread, string); 3514514f5e3Sopenharmony_ci // may gc 3524514f5e3Sopenharmony_ci auto strFlat = EcmaStringAccessor::Flatten(vm, strHandle, MemSpaceType::SHARED_OLD_SPACE); 3534514f5e3Sopenharmony_ci if (EcmaStringAccessor(strFlat).IsInternString()) { 3544514f5e3Sopenharmony_ci return strFlat; 3554514f5e3Sopenharmony_ci } 3564514f5e3Sopenharmony_ci JSHandle<EcmaString> strFlatHandle(thread, strFlat); 3574514f5e3Sopenharmony_ci // may gc 3584514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(strFlat).GetHashcode(); 3594514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, stringTable_[GetTableId(hashcode)].mutex_); 3604514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 3614514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 3624514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 3634514f5e3Sopenharmony_ci } 3644514f5e3Sopenharmony_ci#endif 3654514f5e3Sopenharmony_ci strFlat = *strFlatHandle; 3664514f5e3Sopenharmony_ci EcmaString *result = GetStringThreadUnsafe(strFlat, hashcode); 3674514f5e3Sopenharmony_ci if (result != nullptr) { 3684514f5e3Sopenharmony_ci return result; 3694514f5e3Sopenharmony_ci } 3704514f5e3Sopenharmony_ci 3714514f5e3Sopenharmony_ci InternStringThreadUnsafe(strFlat, hashcode); 3724514f5e3Sopenharmony_ci return strFlat; 3734514f5e3Sopenharmony_ci} 3744514f5e3Sopenharmony_ci 3754514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringThreadUnsafe(EcmaVM *vm, EcmaString *string) 3764514f5e3Sopenharmony_ci{ 3774514f5e3Sopenharmony_ci if (EcmaStringAccessor(string).IsInternString()) { 3784514f5e3Sopenharmony_ci return string; 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci JSHandle<EcmaString> strHandle(vm->GetJSThread(), string); 3814514f5e3Sopenharmony_ci EcmaString *strFlat = EcmaStringAccessor::Flatten(vm, strHandle, MemSpaceType::SHARED_OLD_SPACE); 3824514f5e3Sopenharmony_ci if (EcmaStringAccessor(strFlat).IsInternString()) { 3834514f5e3Sopenharmony_ci return strFlat; 3844514f5e3Sopenharmony_ci } 3854514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(strFlat).GetHashcode(); 3864514f5e3Sopenharmony_ci EcmaString *result = GetStringThreadUnsafe(strFlat, hashcode); 3874514f5e3Sopenharmony_ci if (result != nullptr) { 3884514f5e3Sopenharmony_ci return result; 3894514f5e3Sopenharmony_ci } 3904514f5e3Sopenharmony_ci 3914514f5e3Sopenharmony_ci InternStringThreadUnsafe(strFlat, hashcode); 3924514f5e3Sopenharmony_ci return strFlat; 3934514f5e3Sopenharmony_ci} 3944514f5e3Sopenharmony_ci 3954514f5e3Sopenharmony_civoid EcmaStringTable::InsertStringToTableWithHashThreadUnsafe(EcmaString* string, uint32_t hashcode) 3964514f5e3Sopenharmony_ci{ 3974514f5e3Sopenharmony_ci // Strings in string table should not be in the young space. 3984514f5e3Sopenharmony_ci ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InSharedHeap()); 3994514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(string).NotTreeString()); 4004514f5e3Sopenharmony_ci ASSERT(EcmaStringAccessor(string).GetHashcode() == hashcode); 4014514f5e3Sopenharmony_ci stringTable_[GetTableId(hashcode)].table_.emplace(hashcode, string); 4024514f5e3Sopenharmony_ci EcmaStringAccessor(string).SetInternString(); 4034514f5e3Sopenharmony_ci} 4044514f5e3Sopenharmony_ci 4054514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::InsertStringToTable(EcmaVM *vm, const JSHandle<EcmaString> &strHandle) 4064514f5e3Sopenharmony_ci{ 4074514f5e3Sopenharmony_ci auto strFlat = EcmaStringAccessor::Flatten(vm, strHandle, MemSpaceType::SHARED_OLD_SPACE); 4084514f5e3Sopenharmony_ci JSHandle<EcmaString> strFlatHandle(vm->GetJSThread(), strFlat); 4094514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(strFlat).GetHashcode(); 4104514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 4114514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 4124514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 4134514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 4144514f5e3Sopenharmony_ci } 4154514f5e3Sopenharmony_ci#endif 4164514f5e3Sopenharmony_ci strFlat = *strFlatHandle; 4174514f5e3Sopenharmony_ci InternStringThreadUnsafe(strFlat, hashcode); 4184514f5e3Sopenharmony_ci return strFlat; 4194514f5e3Sopenharmony_ci} 4204514f5e3Sopenharmony_ci 4214514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::TryGetInternString(JSThread *thread, const JSHandle<EcmaString> &string) 4224514f5e3Sopenharmony_ci{ 4234514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(*string).GetHashcode(); 4244514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, stringTable_[GetTableId(hashcode)].mutex_); 4254514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 4264514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 4274514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 4284514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 4294514f5e3Sopenharmony_ci } 4304514f5e3Sopenharmony_ci#endif 4314514f5e3Sopenharmony_ci return GetStringThreadUnsafe(*string, hashcode); 4324514f5e3Sopenharmony_ci} 4334514f5e3Sopenharmony_ci 4344514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf8Len, 4354514f5e3Sopenharmony_ci bool canBeCompress, MemSpaceType type, 4364514f5e3Sopenharmony_ci bool isConstantString, uint32_t idOffset) 4374514f5e3Sopenharmony_ci{ 4384514f5e3Sopenharmony_ci ASSERT(IsSMemSpace(type)); 4394514f5e3Sopenharmony_ci uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress); 4404514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 4414514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 4424514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 4434514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 4444514f5e3Sopenharmony_ci } 4454514f5e3Sopenharmony_ci#endif 4464514f5e3Sopenharmony_ci std::pair<EcmaString *, uint32_t> result = GetStringThreadUnsafe(utf8Data, utf8Len, canBeCompress, hashcode); 4474514f5e3Sopenharmony_ci if (result.first != nullptr) { 4484514f5e3Sopenharmony_ci return result.first; 4494514f5e3Sopenharmony_ci } 4504514f5e3Sopenharmony_ci type = (type == MemSpaceType::SHARED_NON_MOVABLE) ? type : MemSpaceType::SHARED_OLD_SPACE; 4514514f5e3Sopenharmony_ci EcmaString *str = nullptr; 4524514f5e3Sopenharmony_ci if (canBeCompress) { 4534514f5e3Sopenharmony_ci // Constant string will be created in this branch. 4544514f5e3Sopenharmony_ci str = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type, isConstantString, 4554514f5e3Sopenharmony_ci idOffset); 4564514f5e3Sopenharmony_ci } else { 4574514f5e3Sopenharmony_ci str = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type); 4584514f5e3Sopenharmony_ci } 4594514f5e3Sopenharmony_ci str->SetMixHashcode(result.second); 4604514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 4614514f5e3Sopenharmony_ci return str; 4624514f5e3Sopenharmony_ci} 4634514f5e3Sopenharmony_ci 4644514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(EcmaVM *vm, const uint8_t *utf8Data, uint32_t utf16Len, 4654514f5e3Sopenharmony_ci MemSpaceType type) 4664514f5e3Sopenharmony_ci{ 4674514f5e3Sopenharmony_ci ASSERT(IsSMemSpace(type)); 4684514f5e3Sopenharmony_ci type = (type == MemSpaceType::SHARED_NON_MOVABLE) ? type : MemSpaceType::SHARED_OLD_SPACE; 4694514f5e3Sopenharmony_ci EcmaString *str = EcmaStringAccessor::CreateUtf16StringFromUtf8(vm, utf8Data, utf16Len, type); 4704514f5e3Sopenharmony_ci JSHandle<EcmaString> stringHandle(vm->GetJSThread(), str); 4714514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(str).GetHashcode(); 4724514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 4734514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 4744514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 4754514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 4764514f5e3Sopenharmony_ci } 4774514f5e3Sopenharmony_ci#endif 4784514f5e3Sopenharmony_ci str = *stringHandle; 4794514f5e3Sopenharmony_ci EcmaString *result = GetStringThreadUnsafe(str, hashcode); 4804514f5e3Sopenharmony_ci if (result != nullptr) { 4814514f5e3Sopenharmony_ci return result; 4824514f5e3Sopenharmony_ci } 4834514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 4844514f5e3Sopenharmony_ci return str; 4854514f5e3Sopenharmony_ci} 4864514f5e3Sopenharmony_ci 4874514f5e3Sopenharmony_ci// used in jit thread, which unsupport create jshandle 4884514f5e3Sopenharmony_ciEcmaString *EcmaStringTable::GetOrInternStringWithSpaceTypeWithoutJSHandle(EcmaVM *vm, const uint8_t *utf8Data, 4894514f5e3Sopenharmony_ci uint32_t utf16Len, MemSpaceType type) 4904514f5e3Sopenharmony_ci{ 4914514f5e3Sopenharmony_ci ASSERT(IsSMemSpace(type)); 4924514f5e3Sopenharmony_ci type = (type == MemSpaceType::SHARED_NON_MOVABLE) ? type : MemSpaceType::SHARED_OLD_SPACE; 4934514f5e3Sopenharmony_ci CVector<uint16_t> u16Buffer(utf16Len); 4944514f5e3Sopenharmony_ci utf::ConvertRegionMUtf8ToUtf16(utf8Data, u16Buffer.data(), utf::Mutf8Size(utf8Data), utf16Len, 0); 4954514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor::ComputeHashcodeUtf16(u16Buffer.data(), utf16Len); 4964514f5e3Sopenharmony_ci RuntimeLockHolder locker(vm->GetJSThread(), stringTable_[GetTableId(hashcode)].mutex_); 4974514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 4984514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 4994514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 5004514f5e3Sopenharmony_ci } 5014514f5e3Sopenharmony_ci#endif 5024514f5e3Sopenharmony_ci auto result = GetStringThreadUnsafe(u16Buffer.data(), utf16Len, hashcode); 5034514f5e3Sopenharmony_ci if (result.first != nullptr) { 5044514f5e3Sopenharmony_ci return result.first; 5054514f5e3Sopenharmony_ci } 5064514f5e3Sopenharmony_ci EcmaString *str = EcmaStringAccessor::CreateFromUtf16(vm, u16Buffer.data(), utf16Len, false, type); 5074514f5e3Sopenharmony_ci str->SetMixHashcode(hashcode); 5084514f5e3Sopenharmony_ci InternStringThreadUnsafe(str, hashcode); 5094514f5e3Sopenharmony_ci return str; 5104514f5e3Sopenharmony_ci} 5114514f5e3Sopenharmony_ci 5124514f5e3Sopenharmony_civoid EcmaStringTable::SweepWeakRef(const WeakRootVisitor &visitor) 5134514f5e3Sopenharmony_ci{ 5144514f5e3Sopenharmony_ci // No need lock here, only shared gc will sweep string table, meanwhile other threads are suspended. 5154514f5e3Sopenharmony_ci for (uint32_t tableId = 0; tableId < stringTable_.size(); ++tableId) { 5164514f5e3Sopenharmony_ci SweepWeakRef(visitor, tableId); 5174514f5e3Sopenharmony_ci } 5184514f5e3Sopenharmony_ci} 5194514f5e3Sopenharmony_ci 5204514f5e3Sopenharmony_civoid EcmaStringTable::SweepWeakRef(const WeakRootVisitor &visitor, uint32_t tableId) 5214514f5e3Sopenharmony_ci{ 5224514f5e3Sopenharmony_ci ASSERT(tableId >= 0 && tableId < stringTable_.size()); 5234514f5e3Sopenharmony_ci auto &table = stringTable_[tableId].table_; 5244514f5e3Sopenharmony_ci for (auto it = table.begin(); it != table.end();) { 5254514f5e3Sopenharmony_ci auto *object = it->second; 5264514f5e3Sopenharmony_ci auto fwd = visitor(object); 5274514f5e3Sopenharmony_ci ASSERT(Region::ObjectAddressToRange(object)->InSharedHeap()); 5284514f5e3Sopenharmony_ci if (fwd == nullptr) { 5294514f5e3Sopenharmony_ci LOG_ECMA(VERBOSE) << "StringTable: delete string " << std::hex << object; 5304514f5e3Sopenharmony_ci it = table.erase(it); 5314514f5e3Sopenharmony_ci } else if (fwd != object) { 5324514f5e3Sopenharmony_ci it->second = static_cast<EcmaString *>(fwd); 5334514f5e3Sopenharmony_ci ++it; 5344514f5e3Sopenharmony_ci LOG_ECMA(VERBOSE) << "StringTable: forward " << std::hex << object << " -> " << fwd; 5354514f5e3Sopenharmony_ci } else { 5364514f5e3Sopenharmony_ci ++it; 5374514f5e3Sopenharmony_ci } 5384514f5e3Sopenharmony_ci } 5394514f5e3Sopenharmony_ci} 5404514f5e3Sopenharmony_ci 5414514f5e3Sopenharmony_civoid EcmaStringTable::RelocateConstantData(EcmaVM *vm, const JSPandaFile *jsPandaFile) 5424514f5e3Sopenharmony_ci{ 5434514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 5444514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 5454514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 5464514f5e3Sopenharmony_ci } 5474514f5e3Sopenharmony_ci#endif 5484514f5e3Sopenharmony_ci auto thread = vm->GetJSThread(); 5494514f5e3Sopenharmony_ci for (auto &[table, mutex] : stringTable_) { 5504514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, mutex); 5514514f5e3Sopenharmony_ci for (auto it = table.begin(); it != table.end();) { 5524514f5e3Sopenharmony_ci auto *object = it->second; 5534514f5e3Sopenharmony_ci if (!EcmaStringAccessor(object).IsConstantString()) { 5544514f5e3Sopenharmony_ci ++it; 5554514f5e3Sopenharmony_ci continue; 5564514f5e3Sopenharmony_ci } 5574514f5e3Sopenharmony_ci auto constantStr = ConstantString::Cast(object); 5584514f5e3Sopenharmony_ci if (constantStr->GetEntityId() < 0 || !jsPandaFile->Contain(constantStr->GetConstantData())) { 5594514f5e3Sopenharmony_ci // EntityId is -1, which means this str has been relocated. Or the data is not in pandafile. 5604514f5e3Sopenharmony_ci ++it; 5614514f5e3Sopenharmony_ci continue; 5624514f5e3Sopenharmony_ci } 5634514f5e3Sopenharmony_ci uint32_t id = constantStr->GetEntityIdU32(); 5644514f5e3Sopenharmony_ci panda_file::File::StringData sd = jsPandaFile->GetStringData(EntityId(id)); 5654514f5e3Sopenharmony_ci if (constantStr->GetConstantData() != sd.data) { 5664514f5e3Sopenharmony_ci LOG_ECMA(ERROR) << "ConstantString data pointer is inconsistent with sd.data"; 5674514f5e3Sopenharmony_ci ++it; 5684514f5e3Sopenharmony_ci continue; 5694514f5e3Sopenharmony_ci } 5704514f5e3Sopenharmony_ci uint32_t strLen = sd.utf16_length; 5714514f5e3Sopenharmony_ci if (UNLIKELY(strLen == 0)) { 5724514f5e3Sopenharmony_ci it->second = *(vm->GetFactory()->GetEmptyString()); 5734514f5e3Sopenharmony_ci } 5744514f5e3Sopenharmony_ci size_t byteLength = sd.is_ascii ? 1 : sizeof(uint16_t); 5754514f5e3Sopenharmony_ci JSMutableHandle<ByteArray> newData(vm->GetJSThread(), JSTaggedValue::Undefined()); 5764514f5e3Sopenharmony_ci newData.Update(vm->GetFactory()->NewByteArray( 5774514f5e3Sopenharmony_ci strLen, byteLength, reinterpret_cast<void *>(const_cast<uint8_t *>(sd.data)), 5784514f5e3Sopenharmony_ci MemSpaceType::SHARED_NON_MOVABLE)); 5794514f5e3Sopenharmony_ci constantStr->SetRelocatedData(thread, newData.GetTaggedValue()); 5804514f5e3Sopenharmony_ci constantStr->SetConstantData(static_cast<uint8_t *>(newData->GetData())); 5814514f5e3Sopenharmony_ci constantStr->SetEntityId(-1); 5824514f5e3Sopenharmony_ci ++it; 5834514f5e3Sopenharmony_ci } 5844514f5e3Sopenharmony_ci } 5854514f5e3Sopenharmony_ci} 5864514f5e3Sopenharmony_ci 5874514f5e3Sopenharmony_cibool EcmaStringTable::CheckStringTableValidity(JSThread *thread) 5884514f5e3Sopenharmony_ci{ 5894514f5e3Sopenharmony_ci#if ECMASCRIPT_ENABLE_SCOPE_LOCK_STAT 5904514f5e3Sopenharmony_ci auto vm = thread->GetEcmaVM(); 5914514f5e3Sopenharmony_ci if (vm->IsCollectingScopeLockStats()) { 5924514f5e3Sopenharmony_ci vm->IncreaseStringTableLockCount(); 5934514f5e3Sopenharmony_ci } 5944514f5e3Sopenharmony_ci#endif 5954514f5e3Sopenharmony_ci for (auto &[table, mutex] : stringTable_) { 5964514f5e3Sopenharmony_ci RuntimeLockHolder locker(thread, mutex); 5974514f5e3Sopenharmony_ci for (auto itemOuter = table.begin(); itemOuter != table.end(); ++itemOuter) { 5984514f5e3Sopenharmony_ci auto outerString = itemOuter->second; 5994514f5e3Sopenharmony_ci if (!EcmaStringAccessor(outerString).NotTreeString()) { 6004514f5e3Sopenharmony_ci return false; 6014514f5e3Sopenharmony_ci } 6024514f5e3Sopenharmony_ci int counter = 0; 6034514f5e3Sopenharmony_ci auto hashcode = EcmaStringAccessor(outerString).GetHashcode(); 6044514f5e3Sopenharmony_ci auto range = table.equal_range(hashcode); 6054514f5e3Sopenharmony_ci for (auto it = range.first; it != range.second; ++it) { 6064514f5e3Sopenharmony_ci auto foundString = it->second; 6074514f5e3Sopenharmony_ci counter += EcmaStringAccessor::StringsAreEqual(foundString, outerString) ? 1 : 0; 6084514f5e3Sopenharmony_ci } 6094514f5e3Sopenharmony_ci if (counter > 1) { 6104514f5e3Sopenharmony_ci return false; 6114514f5e3Sopenharmony_ci } 6124514f5e3Sopenharmony_ci } 6134514f5e3Sopenharmony_ci } 6144514f5e3Sopenharmony_ci return true; 6154514f5e3Sopenharmony_ci} 6164514f5e3Sopenharmony_ci 6174514f5e3Sopenharmony_ciJSTaggedValue SingleCharTable::CreateSingleCharTable(JSThread *thread) 6184514f5e3Sopenharmony_ci{ 6194514f5e3Sopenharmony_ci auto table = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(MAX_ONEBYTE_CHARCODE, 6204514f5e3Sopenharmony_ci JSTaggedValue::Undefined(), MemSpaceType::SHARED_NON_MOVABLE); 6214514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 6224514f5e3Sopenharmony_ci for (uint32_t i = 1; i < MAX_ONEBYTE_CHARCODE; ++i) { 6234514f5e3Sopenharmony_ci std::string tmp(1, i + 0X00); // 1: size 6244514f5e3Sopenharmony_ci table->Set(thread, i, factory->NewFromASCIIReadOnly(tmp).GetTaggedValue()); 6254514f5e3Sopenharmony_ci } 6264514f5e3Sopenharmony_ci return table.GetTaggedValue(); 6274514f5e3Sopenharmony_ci} 6284514f5e3Sopenharmony_ci} // namespace panda::ecmascript 629