opt string table

Signed-off-by: xiongluo <xiongluo@huawei.com>
Change-Id: I6f10e8fcb0f9120c2cdba929b9731e4286a6ab8a
This commit is contained in:
xiongluo 2023-08-01 21:36:27 +08:00
parent 76086af929
commit d622c14fca
6 changed files with 98 additions and 24 deletions

View File

@ -21,32 +21,43 @@
namespace panda::ecmascript {
EcmaString *EcmaString::Concat(const EcmaVM *vm,
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right)
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, MemSpaceType type)
{
// allocator may trig gc and move src, need to hold it
EcmaString *strLeft = *left;
EcmaString *strRight = *right;
uint32_t leftLength = strLeft->GetLength();
if (leftLength == 0) {
return strRight;
}
bool compressed = (strLeft->IsUtf8() && strRight->IsUtf8());
uint32_t rightLength = strRight->GetLength();
if (rightLength == 0) {
return strLeft;
}
uint32_t newLength = leftLength + rightLength;
if (newLength == 0) {
return vm->GetFactory()->GetEmptyString().GetObject<EcmaString>();
}
bool compressed = (strLeft->IsUtf8() && strRight->IsUtf8());
if (leftLength == 0) {
if (type == MemSpaceType::OLD_SPACE) {
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*right));
if (objectRegion->InYoungSpace()) {
return CopyStringToOldSpace(vm, right, rightLength, compressed);
}
}
return strRight;
}
if (rightLength == 0) {
if (type == MemSpaceType::OLD_SPACE) {
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(*left));
if (objectRegion->InYoungSpace()) {
return CopyStringToOldSpace(vm, left, leftLength, compressed);
}
}
return strLeft;
}
// if the result string is small, make a LineString
if (newLength < TreeEcmaString::MIN_TREE_ECMASTRING_LENGTH) {
ASSERT(strLeft->IsLineOrConstantString());
ASSERT(strRight->IsLineOrConstantString());
auto newString = CreateLineString(vm, newLength, compressed);
auto newString = CreateLineStringWithSpaceType(vm, newLength, compressed, type);
// retrieve strings after gc
strLeft = *left;
strRight = *right;
@ -83,6 +94,38 @@ EcmaString *EcmaString::Concat(const EcmaVM *vm,
return CreateTreeString(vm, left, right, newLength, compressed);
}
/* static */
EcmaString *EcmaString::CopyStringToOldSpace(const EcmaVM *vm, const JSHandle<EcmaString> &original,
uint32_t length, bool compressed)
{
EcmaString *strOrigin = *original;
ASSERT(strOrigin->IsLineOrConstantString());
EcmaString *newString = nullptr;
if (strOrigin->IsLineString()) {
newString = CreateLineStringWithSpaceType(vm, length, compressed, MemSpaceType::OLD_SPACE);
} else if (strOrigin->IsConstantString()){
return CreateConstantString(vm, strOrigin->GetDataUtf8(), length, MemSpaceType::OLD_SPACE);
}
strOrigin = *original;
if (compressed) {
// copy
Span<uint8_t> sp(newString->GetDataUtf8Writable(), length);
Span<const uint8_t> srcSp(strOrigin->GetDataUtf8(), length);
EcmaString::MemCopyChars(sp, length, srcSp, length);
} else {
// copy left part
Span<uint16_t> sp(newString->GetDataUtf16Writable(), length);
if (strOrigin->IsUtf8()) {
EcmaString::CopyChars(sp.data(), strOrigin->GetDataUtf8(), length);
} else {
Span<const uint16_t> srcSp(strOrigin->GetDataUtf16(), length);
EcmaString::MemCopyChars(sp, length << 1U, srcSp, length << 1U);
}
}
ASSERT_PRINT(compressed == CanBeCompressed(newString), "compressed does not match the real value!");
return newString;
}
/* static */
EcmaString *EcmaString::FastSubString(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length)

View File

@ -89,8 +89,10 @@ private:
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right, uint32_t length, bool compressed);
static EcmaString *CreateConstantString(const EcmaVM *vm, const uint8_t *utf8Data,
size_t length, bool compressed, MemSpaceType type = MemSpaceType::SEMI_SPACE, uint32_t idOffset = 0);
static EcmaString *Concat(const EcmaVM *vm,
const JSHandle<EcmaString> &left, const JSHandle<EcmaString> &right);
static EcmaString *Concat(const EcmaVM *vm, const JSHandle<EcmaString> &left,
const JSHandle<EcmaString> &right, MemSpaceType type = MemSpaceType::SEMI_SPACE);
static EcmaString *CopyStringToOldSpace(const EcmaVM *vm, const JSHandle<EcmaString> &original,
uint32_t length, bool compressed);
static EcmaString *FastSubString(const EcmaVM *vm,
const JSHandle<EcmaString> &src, uint32_t start, uint32_t length);
// require src is LineString
@ -759,10 +761,16 @@ public:
return EcmaString::CreateFromUtf16(vm, utf16Data, utf16Len, canBeCompress, type);
}
static EcmaString *Concat(const EcmaVM *vm,
const JSHandle<EcmaString> &str1Handle, const JSHandle<EcmaString> &str2Handle)
static EcmaString *Concat(const EcmaVM *vm, const JSHandle<EcmaString> &str1Handle,
const JSHandle<EcmaString> &str2Handle, MemSpaceType type = MemSpaceType::SEMI_SPACE)
{
return EcmaString::Concat(vm, str1Handle, str2Handle);
return EcmaString::Concat(vm, str1Handle, str2Handle, type);
}
static EcmaString *CopyStringToOldSpace(const EcmaVM *vm, const JSHandle<EcmaString> &original,
uint32_t length, bool compressed)
{
return EcmaString::CopyStringToOldSpace(vm, original, length, compressed);
}
// can change src data structure

View File

@ -86,8 +86,11 @@ void EcmaStringTable::InternString(EcmaString *string)
if (EcmaStringAccessor(string).IsInternString()) {
return;
}
// Strings in string table should not be in the young space.
ASSERT(!Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(string))->InYoungSpace());
ASSERT(EcmaStringAccessor(string).IsLineOrConstantString());
table_.emplace(EcmaStringAccessor(string).GetHashcode(), string);
auto hashcode = EcmaStringAccessor(string).GetHashcode();
table_.emplace(hashcode, string);
EcmaStringAccessor(string).SetInternString();
}
@ -105,8 +108,9 @@ EcmaString *EcmaStringTable::GetOrInternString(const JSHandle<EcmaString> &first
if (concatString != nullptr) {
return concatString;
}
JSHandle<EcmaString> concatHandle(vm_->GetJSThread(), EcmaStringAccessor::Concat(vm_, firstFlat, secondFlat));
concatString = EcmaStringAccessor::Flatten(vm_, concatHandle);
JSHandle<EcmaString> concatHandle(vm_->GetJSThread(),
EcmaStringAccessor::Concat(vm_, firstFlat, secondFlat, MemSpaceType::OLD_SPACE));
concatString = EcmaStringAccessor::FlattenNoGC(vm_, *concatHandle);
InternString(concatString);
return concatString;
}
@ -118,7 +122,7 @@ EcmaString *EcmaStringTable::GetOrInternString(const uint8_t *utf8Data, uint32_t
return result;
}
result = EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, canBeCompress);
result = EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, canBeCompress, MemSpaceType::OLD_SPACE);
InternString(result);
return result;
}
@ -146,7 +150,7 @@ EcmaString *EcmaStringTable::GetOrInternString(const uint16_t *utf16Data, uint32
return result;
}
result = EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, canBeCompress);
result = EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, canBeCompress, MemSpaceType::OLD_SPACE);
InternString(result);
return result;
}
@ -158,7 +162,7 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string)
}
JSHandle<EcmaString> strHandle(vm_->GetJSThread(), string);
// may gc
auto strFlat = EcmaStringAccessor::Flatten(vm_, strHandle);
auto strFlat = EcmaStringAccessor::FlattenNoGC(vm_, *strHandle);
if (EcmaStringAccessor(strFlat).IsInternString()) {
return strFlat;
}
@ -166,6 +170,15 @@ EcmaString *EcmaStringTable::GetOrInternString(EcmaString *string)
if (result != nullptr) {
return result;
}
if (EcmaStringAccessor(strFlat).IsLineOrConstantString()) {
Region *objectRegion = Region::ObjectAddressToRange(reinterpret_cast<TaggedObject *>(strFlat));
if (objectRegion->InYoungSpace()) {
JSHandle<EcmaString> resultHandle(vm_->GetJSThread(), strFlat);
strFlat = EcmaStringAccessor::CopyStringToOldSpace(vm_,
resultHandle, EcmaStringAccessor(strFlat).GetLength(), EcmaStringAccessor(strFlat).IsUtf8());
}
}
InternString(strFlat);
return strFlat;
}
@ -178,6 +191,7 @@ EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint8_t *utf8D
if (result != nullptr) {
return result;
}
type = type == MemSpaceType::NON_MOVABLE ? MemSpaceType::NON_MOVABLE : MemSpaceType::OLD_SPACE;
if (canBeCompress) {
// Constant string will be created in this branch.
result = EcmaStringAccessor::CreateFromUtf8(vm_, utf8Data, utf8Len, canBeCompress, type, isConstantString,
@ -196,7 +210,7 @@ EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint16_t *utf1
if (result != nullptr) {
return result;
}
type = type == MemSpaceType::NON_MOVABLE ? MemSpaceType::NON_MOVABLE : MemSpaceType::OLD_SPACE;
result = EcmaStringAccessor::CreateFromUtf16(vm_, utf16Data, utf16Len, canBeCompress, type);
InternString(result);
return result;
@ -205,8 +219,10 @@ EcmaString *EcmaStringTable::GetOrInternStringWithSpaceType(const uint16_t *utf1
void EcmaStringTable::SweepWeakReference(const WeakRootVisitor &visitor)
{
for (auto it = table_.begin(); it != table_.end();) {
// Strings in string table should not be in the young space. Only old gc will sweep string table.
auto *object = it->second;
auto fwd = visitor(object);
ASSERT(!Region::ObjectAddressToRange(object)->InYoungSpace());
if (fwd == nullptr) {
LOG_ECMA(VERBOSE) << "StringTable: delete string " << std::hex << object;
table_.erase(it++);

View File

@ -249,6 +249,10 @@ bool SemiSpace::AdjustCapacity(size_t allocatedSizeSinceGC)
if (initialCapacity_ <= minimumCapacity_) {
return false;
}
double speed = heap_->GetMemController()->GetNewSpaceAllocationThroughputPerMS();
if (speed > LOW_ALLOCATION_SPEED_PER_MS) {
return false;
}
size_t newCapacity = initialCapacity_ / GROWING_FACTOR;
SetInitialCapacity(std::max(newCapacity, minimumCapacity_));
return true;

View File

@ -60,7 +60,7 @@ static constexpr size_t DEFAULT_MARK_STACK_SIZE = 4_KB;
static constexpr double MIN_OBJECT_SURVIVAL_RATE = 0.75;
static constexpr double GROW_OBJECT_SURVIVAL_RATE = 0.8;
static constexpr double SHRINK_OBJECT_SURVIVAL_RATE = 0.2;
static constexpr double LOW_ALLOCATION_SPEED_PER_MS = 1000;
// Objects which are larger than half of the region size are huge objects.
// Regular objects will be allocated on regular regions and migrated on spaces.
// They will never be moved to huge object space. So we take half of a regular

View File

@ -296,8 +296,11 @@ void ParallelEvacuator::UpdateWeakReference()
}
return header;
};
if (isFullMark) {
// Only old gc will sweep string table.
stringTable->SweepWeakReference(gcUpdateWeak);
}
stringTable->SweepWeakReference(gcUpdateWeak);
heap_->GetEcmaVM()->GetJSThread()->IterateWeakEcmaGlobalStorage(gcUpdateWeak);
heap_->GetEcmaVM()->ProcessReferences(gcUpdateWeak);
}