Ai
52 Star 223 Fork 1.1K

OpenHarmony/arkcompiler_ets_runtime
关闭

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ecma_string_table_optimization.cpp 31.18 KB
一键复制 编辑 原始数据 按行查看 历史
wuxiesaber 提交于 2025-09-11 16:45 +08:00 . fix repeat using of std::move
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/ecma_string_table.h"
#include "common_components/objects/string_table/hashtriemap-inl.h"
#include "common_components/taskpool/taskpool.h"
#include "ecmascript/ecma_string-inl.h"
#include "ecmascript/ecma_string_table_optimization-inl.h"
#include "ecmascript/jspandafile/js_pandafile.h"
namespace panda::ecmascript {
#if ENABLE_NEXT_OPTIMIZATION
void EcmaStringTableCleaner::PostSweepWeakRefTask(const WeakRootVisitor &visitor)
{
StartSweepWeakRefTask();
iter_ = std::make_shared<std::atomic<uint32_t>>(0U);
const uint32_t postTaskCount = common::Taskpool::GetCurrentTaskpool()->GetTotalThreadNum();
for (uint32_t i = 0U; i < postTaskCount; ++i) {
common::Taskpool::GetCurrentTaskpool()->PostTask(std::make_unique<SweepWeakRefTask>(iter_, this, visitor));
}
}
void EcmaStringTableCleaner::JoinAndWaitSweepWeakRefTask(const WeakRootVisitor &visitor)
{
ProcessSweepWeakRef(iter_, this, visitor);
WaitSweepWeakRefTask();
iter_.reset();
}
void EcmaStringTableCleaner::ProcessSweepWeakRef(IteratorPtr &iter, EcmaStringTableCleaner *cleaner,
const WeakRootVisitor &visitor)
{
uint32_t index = 0U;
while ((index = GetNextIndexId(iter)) < common::TrieMapConfig::ROOT_SIZE) {
cleaner->stringTable_->SweepWeakRef(visitor, index);
if (ReduceCountAndCheckFinish(cleaner)) {
cleaner->SignalSweepWeakRefTask();
}
}
}
void EcmaStringTableCleaner::StartSweepWeakRefTask()
{
// No need lock here, only the daemon thread will reset the state.
sweepWeakRefFinished_ = false;
PendingTaskCount_.store(common::TrieMapConfig::ROOT_SIZE, std::memory_order_relaxed);
}
void EcmaStringTableCleaner::WaitSweepWeakRefTask()
{
LockHolder holder(sweepWeakRefMutex_);
while (!sweepWeakRefFinished_) {
sweepWeakRefCV_.Wait(&sweepWeakRefMutex_);
}
}
void EcmaStringTableCleaner::SignalSweepWeakRefTask()
{
LockHolder holder(sweepWeakRefMutex_);
sweepWeakRefFinished_ = true;
sweepWeakRefCV_.SignalAll();
}
bool EcmaStringTableCleaner::SweepWeakRefTask::Run([[maybe_unused]] uint32_t threadIndex)
{
ProcessSweepWeakRef(iter_, cleaner_, visitor_);
return true;
}
template class EcmaStringTableImpl<DisableCMCGCTrait>;
template class EcmaStringTableImpl<EnableCMCGCTrait>;
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternFlattenString(EcmaVM* vm, EcmaString* string)
{
ASSERT(EcmaStringAccessor(string).NotTreeString());
if (EcmaStringAccessor(string).IsInternString()) {
return string;
}
JSThread *thread = vm->GetAssociatedJSThread();
uint32_t hashcode = EcmaStringAccessor(string).GetHashcode(thread);
ASSERT(!EcmaStringAccessor(string).IsInternString());
ASSERT(EcmaStringAccessor(string).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(string->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InSharedHeap());
}
auto readBarrierForLoad = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
auto loadResult = stringTable_.template Load(std::move(readBarrierForLoad), hashcode, string->ToBaseString());
if (loadResult.value != nullptr) {
return EcmaString::FromBaseString(loadResult.value);
}
JSHandle<EcmaString> stringHandle(thread, string);
ThreadType* holder = GetThreadHolder(thread);
auto readBarrierForStoreOrLoad = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
BaseString *result = stringTable_.template StoreOrLoad<
true, decltype(readBarrierForStoreOrLoad), common::ReadOnlyHandle<BaseString>>(
holder, std::move(readBarrierForStoreOrLoad), hashcode, loadResult, stringHandle);
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternFlattenStringNoGC(EcmaVM* vm, EcmaString* string)
{
ASSERT(EcmaStringAccessor(string).NotTreeString());
if (EcmaStringAccessor(string).IsInternString()) {
return string;
}
JSThread *thread = vm->GetAssociatedJSThread();
uint32_t hashcode = EcmaStringAccessor(string).GetHashcode(thread);
ASSERT(!EcmaStringAccessor(string).IsInternString());
ASSERT(EcmaStringAccessor(string).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(string->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InSharedHeap());
}
auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
auto loadResult = stringTable_.template Load(readBarrier, hashcode, string->ToBaseString());
if (loadResult.value != nullptr) {
return EcmaString::FromBaseString(loadResult.value);
}
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
JSHandle<EcmaString> stringHandle(thread, string);
BaseString* result = stringTable_.template StoreOrLoad<
false, decltype(readBarrier), common::ReadOnlyHandle<BaseString>>(
holder, std::move(readBarrier), hashcode, loadResult, stringHandle);
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternStringFromCompressedSubString(
EcmaVM* vm, const JSHandle<EcmaString>& string, uint32_t offset, uint32_t utf8Len)
{
const uint8_t* utf8Data = EcmaStringAccessor(string).GetDataUtf8() + offset;
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, true);
JSThread *thread = vm->GetAssociatedJSThread();
auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
auto loadResult = stringTable_.template Load(std::move(readBarrier), hashcode, string, offset, utf8Len);
if (loadResult.value != nullptr) {
return EcmaString::FromBaseString(loadResult.value);
}
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.template StoreOrLoad(
holder, hashcode, loadResult,
[vm, string, offset, utf8Len, hashcode]() -> common::ReadOnlyHandle<BaseString> {
EcmaString* str = EcmaStringAccessor::CreateFromUtf8CompressedSubString(vm, string, offset, utf8Len,
MemSpaceType::SHARED_OLD_SPACE);
str->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(str).IsInternString());
ASSERT(EcmaStringAccessor(str).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(str->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(str))->InSharedHeap());
}
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> strHandle(thread, str);
return strHandle;
},
[vm, utf8Len, string, offset](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
const uint8_t *utf8Data = EcmaStringAccessor(string).GetDataUtf8() + offset;
return EcmaStringAccessor::StringIsEqualUint8Data(thread, EcmaString::FromBaseString(foundString), utf8Data,
utf8Len, true);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString *EcmaStringTableImpl<Traits>::GetOrInternString(EcmaVM *vm, EcmaString *string)
{
if (EcmaStringAccessor(string).IsInternString()) {
return string;
}
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> stringHandle(thread, string);
// may gc
EcmaString *strFlat = EcmaStringAccessor::Flatten(vm, stringHandle, MemSpaceType::SHARED_OLD_SPACE);
if (EcmaStringAccessor(strFlat).IsInternString()) {
return strFlat;
}
uint32_t hashcode = EcmaStringAccessor(strFlat).GetHashcode(thread);
auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
auto loadResult = stringTable_.template Load(readBarrier, hashcode, strFlat->ToBaseString());
if (loadResult.value != nullptr) {
return EcmaString::FromBaseString(loadResult.value);
}
JSHandle<EcmaString> strFlatHandle(thread, strFlat);
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString* result = stringTable_.template StoreOrLoad<
true, decltype(readBarrier), common::ReadOnlyHandle<BaseString>>(
holder, std::move(readBarrier), hashcode, loadResult, strFlatHandle);
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternString(EcmaVM* vm, const JSHandle<EcmaString>& firstString,
const JSHandle<EcmaString>& secondString)
{
bool signalState = vm->GetJsDebuggerManager()->GetSignalState();
if (UNLIKELY(signalState)) {
return GetOrInternStringThreadUnsafe(vm, firstString, secondString);
}
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> firstFlat(thread, EcmaStringAccessor::Flatten(vm, firstString));
JSHandle<EcmaString> secondFlat(thread, EcmaStringAccessor::Flatten(vm, secondString));
uint32_t hashcode = EcmaStringAccessor::CalculateAllConcatHashCode(thread, firstFlat, secondFlat);
ASSERT(EcmaStringAccessor(firstFlat).NotTreeString());
ASSERT(EcmaStringAccessor(secondFlat).NotTreeString());
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.template LoadOrStore<true>(
holder, hashcode,
[vm, hashcode, thread, firstFlat, secondFlat]() {
JSHandle<EcmaString> concatHandle(
thread, EcmaStringAccessor::Concat(vm, firstFlat, secondFlat, MemSpaceType::SHARED_OLD_SPACE));
EcmaString *value = EcmaStringAccessor::Flatten(vm, concatHandle, MemSpaceType::SHARED_OLD_SPACE);
value->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(value).IsInternString());
ASSERT(EcmaStringAccessor(value).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(value->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value))->InSharedHeap());
}
JSHandle<EcmaString> stringHandle(thread, value);
return stringHandle;
},
[thread, firstFlat, secondFlat](BaseString *foundString) {
EcmaString *firstStr = *firstFlat;
EcmaString *secondStr = *secondFlat;
return EcmaStringAccessor(EcmaString::FromBaseString(foundString))
.EqualToSplicedString(thread, firstStr, secondStr);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternString(EcmaVM* vm, const uint8_t* utf8Data, uint32_t utf8Len,
bool canBeCompress, [[maybe_unused]] MemSpaceType type)
{
ASSERT(IsSMemSpace(type));
bool signalState = vm->GetJsDebuggerManager()->GetSignalState();
if (UNLIKELY(signalState)) {
return GetOrInternStringThreadUnsafe(vm, utf8Data, utf8Len, canBeCompress);
}
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress);
BaseString *result = stringTable_.template LoadOrStore<true>(
holder, hashcode,
[vm, hashcode, utf8Data, utf8Len, canBeCompress, type]() {
EcmaString* value = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type);
value->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(value).IsInternString());
ASSERT(EcmaStringAccessor(value).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(value->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value))->InSharedHeap());
}
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> stringHandle(thread, value);
return stringHandle;
},
[vm, utf8Data, utf8Len, canBeCompress](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor::StringIsEqualUint8Data(thread, EcmaString::FromBaseString(foundString), utf8Data,
utf8Len, canBeCompress);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternString(EcmaVM* vm, const uint8_t* utf8Data, uint32_t utf16Len,
MemSpaceType type)
{
ASSERT(IsSMemSpace(type));
ASSERT(type == MemSpaceType::SHARED_NON_MOVABLE || type == MemSpaceType::SHARED_OLD_SPACE);
JSThread* thread = vm->GetJSThread();
EcmaString* str = EcmaStringAccessor::CreateUtf16StringFromUtf8(vm, utf8Data, utf16Len, type);
uint32_t hashcode = EcmaStringAccessor(str).GetHashcode(thread);
auto readBarrierForLoad = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
auto loadResult = stringTable_.template Load(std::move(readBarrierForLoad), hashcode, str->ToBaseString());
if (loadResult.value != nullptr) {
return EcmaString::FromBaseString(loadResult.value);
}
JSHandle<EcmaString> strHandle(thread, str);
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
auto readBarrierForStoreOrLoad = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
BaseString* result = stringTable_.template StoreOrLoad<
true, decltype(readBarrierForStoreOrLoad), common::ReadOnlyHandle<BaseString>>(
holder, std::move(readBarrierForStoreOrLoad), hashcode, loadResult, strHandle);
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternString(EcmaVM* vm, const uint16_t* utf16Data, uint32_t utf16Len,
bool canBeCompress)
{
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf16(const_cast<uint16_t*>(utf16Data), utf16Len);
BaseString *result = stringTable_.template LoadOrStore<true>(
holder, hashcode,
[vm, utf16Data, utf16Len, canBeCompress, hashcode]() {
EcmaString* value = EcmaStringAccessor::CreateFromUtf16(vm, utf16Data, utf16Len, canBeCompress,
MemSpaceType::SHARED_OLD_SPACE);
value->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(value).IsInternString());
ASSERT(EcmaStringAccessor(value).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(value->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value))->InSharedHeap());
}
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> stringHandle(thread, value);
return stringHandle;
},
[vm, utf16Data, utf16Len](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor::StringsAreEqualUtf16(thread, EcmaString::FromBaseString(foundString), utf16Data,
utf16Len);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
EcmaString *EcmaStringTableImpl<Traits>::TryGetInternString(JSThread *thread, const JSHandle<EcmaString> &string)
{
uint32_t hashcode = EcmaStringAccessor(*string).GetHashcode(thread);
EcmaString *str = *string;
auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
return EcmaString::FromBaseString(
stringTable_.template Load<false>(std::move(readBarrier), hashcode, str->ToBaseString()));
}
// used in jit thread, which unsupport create jshandle
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternStringWithoutJSHandleForJit(EcmaVM* vm, const uint8_t* utf8Data,
uint32_t utf8Len, bool canBeCompress, MemSpaceType type)
{
ASSERT(IsSMemSpace(type));
ASSERT(type == MemSpaceType::SHARED_NON_MOVABLE || type == MemSpaceType::SHARED_OLD_SPACE);
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress);
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.LoadOrStoreForJit(
holder, hashcode,
[vm, utf8Data, utf8Len, canBeCompress, type, hashcode]() {
EcmaString *value = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress, type);
value->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(value).IsInternString());
ASSERT(EcmaStringAccessor(value).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(value->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value))->InSharedHeap());
}
return value->ToBaseString();
},
[vm, utf8Data, utf8Len, canBeCompress](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor::StringIsEqualUint8Data(thread, EcmaString::FromBaseString(foundString), utf8Data,
utf8Len, canBeCompress);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
// used in jit thread, which unsupport create jshandle
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternStringWithoutJSHandleForJit(EcmaVM* vm, const uint8_t* utf8Data,
uint32_t utf16Len, MemSpaceType type)
{
ASSERT(vm->GetJSThread()->IsJitThread());
ASSERT(IsSMemSpace(type));
type = (type == MemSpaceType::SHARED_NON_MOVABLE) ? type : MemSpaceType::SHARED_OLD_SPACE;
CVector<uint16_t> u16Buffer(utf16Len);
utf::ConvertRegionMUtf8ToUtf16(utf8Data, u16Buffer.data(), utf::Mutf8Size(utf8Data), utf16Len, 0);
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf16(u16Buffer.data(), utf16Len);
const uint16_t *utf16Data = u16Buffer.data();
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.LoadOrStoreForJit(
holder, hashcode,
[vm, u16Buffer, utf16Len, hashcode, type]() {
EcmaString *value = EcmaStringAccessor::CreateFromUtf16(vm, u16Buffer.data(), utf16Len, false, type);
value->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(value).IsInternString());
ASSERT(EcmaStringAccessor(value).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(value->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(value))->InSharedHeap());
}
return value->ToBaseString();
},
[vm, utf16Data, utf16Len](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor::StringsAreEqualUtf16(thread, EcmaString::FromBaseString(foundString), utf16Data,
utf16Len);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
template <typename Traits>
void EcmaStringTableImpl<Traits>::SweepWeakRef(const WeakRootVisitor &visitor, uint32_t rootID)
{
ASSERT(rootID >= 0 && rootID < common::TrieMapConfig::ROOT_SIZE);
auto *root_node = stringTable_.root_[rootID].load(std::memory_order_relaxed);
if (root_node == nullptr) {
return;
}
for (uint32_t index = 0; index < common::TrieMapConfig::INDIRECT_SIZE; ++index) {
stringTable_.ClearNodeFromGC(root_node, index, visitor);
}
}
template <typename Traits>
bool EcmaStringTableImpl<Traits>::CheckStringTableValidity(JSThread *thread)
{
bool isValid = true;
auto readBarrier = [thread](const void *obj, size_t offset) -> TaggedObject* {
return Barriers::GetTaggedObject(thread, obj, offset);
};
stringTable_.Range(std::move(readBarrier), isValid);
return isValid;
}
JSTaggedValue SingleCharTable::CreateSingleCharTable(JSThread *thread)
{
auto table = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(MAX_ONEBYTE_CHARCODE, JSTaggedValue::Undefined(),
MemSpaceType::SHARED_NON_MOVABLE);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
for (uint32_t i = 1; i < MAX_ONEBYTE_CHARCODE; ++i) {
std::string tmp(1, i + 0X00); // 1: size
table->Set(thread, i, factory->NewFromASCIIReadOnly(tmp).GetTaggedValue());
}
return table.GetTaggedValue();
}
// This should only call in Debugger Signal, and need to fix and remove
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternStringThreadUnsafe(
EcmaVM* vm, const JSHandle<EcmaString> firstString,
const JSHandle<EcmaString> secondString)
{
ASSERT(vm->GetJsDebuggerManager()->GetSignalState());
JSThread *thread = vm->GetJSThreadNoCheck();
JSHandle<EcmaString> firstFlat(thread, EcmaStringAccessor::Flatten(vm, firstString));
JSHandle<EcmaString> secondFlat(thread, EcmaStringAccessor::Flatten(vm, secondString));
uint32_t hashcode = EcmaStringAccessor::CalculateAllConcatHashCode(thread, firstFlat, secondFlat);
ASSERT(EcmaStringAccessor(firstFlat).NotTreeString());
ASSERT(EcmaStringAccessor(secondFlat).NotTreeString());
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.template LoadOrStore<false>(
holder, hashcode,
[hashcode, thread, vm, firstFlat, secondFlat]() {
JSHandle<EcmaString> concatHandle(
thread, EcmaStringAccessor::Concat(vm, firstFlat, secondFlat, MemSpaceType::SHARED_OLD_SPACE));
EcmaString *concatString = EcmaStringAccessor::Flatten(vm, concatHandle, MemSpaceType::SHARED_OLD_SPACE);
concatString->SetMixHashcode(hashcode);
ASSERT(!EcmaStringAccessor(concatString).IsInternString());
ASSERT(EcmaStringAccessor(concatString).NotTreeString());
// Strings in string table should not be in the young space.
if constexpr (Traits::EnableCMCGC) {
ASSERT(concatString->IsInSharedHeap());
} else {
ASSERT(Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(concatString))->InSharedHeap());
}
JSHandle<EcmaString> stringHandle(thread, concatString);
return stringHandle;
},
[vm, firstFlat, secondFlat](BaseString *foundString) {
EcmaString *firstStr = *firstFlat;
EcmaString *secondStr = *secondFlat;
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor(EcmaString::FromBaseString(foundString))
.EqualToSplicedString(thread, firstStr, secondStr);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
// This should only call in Debugger Signal, and need to fix and remove
template <typename Traits>
EcmaString* EcmaStringTableImpl<Traits>::GetOrInternStringThreadUnsafe(EcmaVM* vm, const uint8_t* utf8Data,
uint32_t utf8Len, bool canBeCompress)
{
ASSERT(vm->GetJsDebuggerManager()->GetSignalState());
uint32_t hashcode = EcmaStringAccessor::ComputeHashcodeUtf8(utf8Data, utf8Len, canBeCompress);
ThreadType* holder = GetThreadHolder(vm->GetJSThread());
BaseString *result = stringTable_.template LoadOrStore<false>(
holder, hashcode,
[vm, utf8Data, utf8Len, canBeCompress, hashcode]() {
EcmaString *value = EcmaStringAccessor::CreateFromUtf8(vm, utf8Data, utf8Len, canBeCompress,
MemSpaceType::SHARED_OLD_SPACE);
value->SetMixHashcode(hashcode);
JSThread *thread = vm->GetJSThread();
JSHandle<EcmaString> stringHandle(thread, value);
return stringHandle;
},
[vm, utf8Data, utf8Len, canBeCompress](BaseString *foundString) {
JSThread *thread = vm->GetAssociatedJSThread();
return EcmaStringAccessor::StringIsEqualUint8Data(thread, EcmaString::FromBaseString(foundString), utf8Data,
utf8Len, canBeCompress);
});
ASSERT(result != nullptr);
return EcmaString::FromBaseString(result);
}
EcmaString* EcmaStringTable::GetOrInternFlattenString(EcmaVM* vm, EcmaString* string)
{
return visitImpl([&](auto& impl) { return impl.GetOrInternFlattenString(vm, string); });
}
EcmaString* EcmaStringTable::GetOrInternFlattenStringNoGC(EcmaVM* vm, EcmaString* string)
{
return visitImpl([&](auto& impl) { return impl.GetOrInternFlattenStringNoGC(vm, string); });
}
EcmaString* EcmaStringTable::GetOrInternStringFromCompressedSubString(EcmaVM* vm, const JSHandle<EcmaString>& string,
uint32_t offset, uint32_t utf8Len)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternStringFromCompressedSubString(vm, string, offset, utf8Len);
});
}
EcmaString* EcmaStringTable::GetOrInternString(EcmaVM* vm, EcmaString* string)
{
return visitImpl([&](auto& impl) { return impl.GetOrInternString(vm, string); });
}
EcmaString* EcmaStringTable::GetOrInternString(EcmaVM* vm, const JSHandle<EcmaString>& firstString,
const JSHandle<EcmaString>& secondString)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternString(vm, firstString, secondString);
});
}
EcmaString* EcmaStringTable::GetOrInternString(EcmaVM* vm, const uint8_t* utf8Data, uint32_t utf8Len,
bool canBeCompress,
MemSpaceType type)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternString(vm, utf8Data, utf8Len, canBeCompress, type);
});
}
EcmaString* EcmaStringTable::GetOrInternString(EcmaVM* vm, const uint8_t* utf8Data, uint32_t utf16Len,
MemSpaceType type)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternString(vm, utf8Data, utf16Len, type);
});
}
EcmaString* EcmaStringTable::GetOrInternString(EcmaVM* vm, const uint16_t* utf16Data, uint32_t utf16Len,
bool canBeCompress)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternString(vm, utf16Data, utf16Len, canBeCompress);
});
}
// This is ONLY for JIT Thread, since JIT could not create JSHandle so need to allocate String with holding
// lock_ --- need to support JSHandle
EcmaString* EcmaStringTable::GetOrInternStringWithoutJSHandleForJit(EcmaVM* vm, const uint8_t* utf8Data,
uint32_t utf16Len,
MemSpaceType type)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternStringWithoutJSHandleForJit(vm, utf8Data, utf16Len, type);
});
}
EcmaString* EcmaStringTable::GetOrInternStringWithoutJSHandleForJit(EcmaVM* vm, const uint8_t* utf8Data,
uint32_t utf8Len,
bool canBeCompress, MemSpaceType type)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternStringWithoutJSHandleForJit(vm, utf8Data, utf8Len, canBeCompress, type);
});
}
EcmaString *EcmaStringTable::TryGetInternString(JSThread *thread, const JSHandle<EcmaString> &string)
{
return visitImpl([&](auto &impl) { return impl.TryGetInternString(thread, string); });
}
void EcmaStringTable::SweepWeakRef(const WeakRootVisitor& visitor, uint32_t rootID)
{
if (std::holds_alternative<EcmaStringTableImpl<DisableCMCGCTrait>>(impl_)) {
return std::get<EcmaStringTableImpl<DisableCMCGCTrait>>(impl_).SweepWeakRef(visitor, rootID);
}
UNREACHABLE();
}
bool EcmaStringTable::CheckStringTableValidity(JSThread *thread)
{
return visitImpl([&](auto &impl) { return impl.CheckStringTableValidity(thread); });
}
EcmaString* EcmaStringTable::GetOrInternStringThreadUnsafe(EcmaVM* vm, const JSHandle<EcmaString> firstString,
const JSHandle<EcmaString> secondString)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternStringThreadUnsafe(vm, firstString, secondString);
});
}
// This should only call in Debugger Signal, and need to fix and remove
EcmaString* EcmaStringTable::GetOrInternStringThreadUnsafe(EcmaVM* vm, const uint8_t* utf8Data, uint32_t utf8Len,
bool canBeCompress)
{
return visitImpl([&](auto& impl) {
return impl.GetOrInternStringThreadUnsafe(vm, utf8Data, utf8Len, canBeCompress);
});
}
#endif
} // namespace panda::ecmascript
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/openharmony/arkcompiler_ets_runtime.git
git@gitee.com:openharmony/arkcompiler_ets_runtime.git
openharmony
arkcompiler_ets_runtime
arkcompiler_ets_runtime
master

搜索帮助