!6268 Work serialize optimization

Merge pull request !6268 from dingwen/master
This commit is contained in:
openharmony_ci 2024-02-27 14:07:40 +00:00 committed by Gitee
commit 92b478ab09
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
7 changed files with 81 additions and 59 deletions

View File

@ -232,14 +232,15 @@ bool EcmaVM::Initialize()
auto context = new EcmaContext(thread_);
thread_->PushContext(context);
[[maybe_unused]] EcmaHandleScope scope(thread_);
snapshotEnv_ = new SnapshotEnv(this);
context->Initialize();
snapshotEnv_->AddGlobalConstToMap();
thread_->SetGlueGlobalEnv(reinterpret_cast<GlobalEnv *>(context->GetGlobalEnv().GetTaggedType()));
thread_->SetGlobalObject(GetGlobalEnv()->GetGlobalObject());
thread_->SetCurrentEcmaContext(context);
SingleCharTable::CreateSingleCharTable(thread_);
GenerateInternalNativeMethods();
quickFixManager_ = new QuickFixManager();
snapshotEnv_ = new SnapshotEnv(this);
if (options_.GetEnableAsmInterpreter()) {
thread_->GetCurrentEcmaContext()->LoadStubFile();
}
@ -343,6 +344,7 @@ EcmaVM::~EcmaVM()
}
if (snapshotEnv_ != nullptr) {
snapshotEnv_->ClearEnvMap();
delete snapshotEnv_;
snapshotEnv_ = nullptr;
}

View File

@ -22,6 +22,7 @@
#include "ecmascript/js_handle.h"
#include "ecmascript/global_env_constants-inl.h"
#include "ecmascript/global_env_fields.h"
#include "ecmascript/snapshot/mem/snapshot_env.h"
namespace panda::ecmascript {
class JSThread;
@ -94,6 +95,33 @@ public:
*reinterpret_cast<JSThread**>(address) = thread;
}
// For work serialize, add initialized global env object to snapshot env map
void AddValueToSnapshotEnv(const JSThread *thread, JSTaggedValue value, uint8_t index, uint32_t offset)
{
if (!value.IsInternalAccessor()) {
SnapshotEnv *snapshotEnv = thread->GetEcmaVM()->GetSnapshotEnv();
if (!RemoveValueFromSnapshotEnv(snapshotEnv, value, offset)) {
return;
}
size_t globalConstCount = thread->GlobalConstants()->GetConstantCount();
snapshotEnv->Push(value.GetRawData(), index + globalConstCount);
}
}
// For work serialize, remove old value from snapshot env map
bool RemoveValueFromSnapshotEnv(SnapshotEnv *snapshotEnv, JSTaggedValue value, uint32_t offset)
{
JSTaggedValue oldValue(Barriers::GetValue<JSTaggedType>(this, offset));
if (oldValue == value) {
return false;
}
if (oldValue.IsHeapObject() && !oldValue.IsInternalAccessor()) {
// Remove old value
snapshotEnv->Remove(oldValue.GetRawData());
}
return true;
}
JSHandle<JSTaggedValue> GetSymbol(JSThread *thread, const JSHandle<JSTaggedValue> &string);
JSHandle<JSTaggedValue> GetStringFunctionByName(JSThread *thread, const char *name);
JSHandle<JSTaggedValue> GetStringPrototypeFunctionByName(JSThread *thread, const char *name);
@ -142,8 +170,11 @@ public:
{ \
uint32_t offset = HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \
if (mode == WRITE_BARRIER && value.GetTaggedValue().IsHeapObject()) { \
AddValueToSnapshotEnv(thread, value.GetTaggedValue(), index, offset); \
Barriers::SetObject<true>(thread, this, offset, value.GetTaggedValue().GetRawData()); \
} else { \
SnapshotEnv *snapshotEnv = thread->GetEcmaVM()->GetSnapshotEnv(); \
RemoveValueFromSnapshotEnv(snapshotEnv, value.GetTaggedValue(), offset); \
Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetTaggedValue().GetRawData()); \
} \
} \
@ -151,8 +182,11 @@ public:
{ \
uint32_t offset = HEADER_SIZE + index * JSTaggedValue::TaggedTypeSize(); \
if (mode == WRITE_BARRIER && value.IsHeapObject()) { \
AddValueToSnapshotEnv(thread, value, index, offset); \
Barriers::SetObject<true>(thread, this, offset, value.GetRawData()); \
} else { \
SnapshotEnv *snapshotEnv = thread->GetEcmaVM()->GetSnapshotEnv(); \
RemoveValueFromSnapshotEnv(snapshotEnv, value, offset); \
Barriers::SetPrimitive<JSTaggedType>(this, offset, value.GetRawData()); \
} \
}

View File

@ -33,7 +33,7 @@ void GlobalIndexMap::InitGlobalIndexMap(const JSThread *thread,
JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
{
if (globalIndexMap.GetTaggedValue().IsHeapObject()) {
return ;
return;
}
globalIndexMap.Update(PointerToIndexDictionary::Create(thread));
}

View File

@ -284,9 +284,9 @@ TaggedObject *Heap::AllocateHugeObject(size_t size)
// if allocate huge object OOM, temporarily increase space size to avoid vm crash
size_t oomOvershootSize = GetEcmaVM()->GetEcmaParamConfiguration().GetOutOfMemoryOvershootSize();
oldSpace_->IncreaseOutOfMemoryOvershootSize(oomOvershootSize);
object = reinterpret_cast<TaggedObject *>(hugeObjectSpace_->Allocate(size, thread_));
DumpHeapSnapshotBeforeOOM(true, size, "Heap::AllocateHugeObject", false);
StatisticHeapDetail();
object = reinterpret_cast<TaggedObject *>(hugeObjectSpace_->Allocate(size, thread_));
#ifndef ENABLE_DUMP_IN_FAULTLOG
ThrowOutOfMemoryError(size, "Heap::AllocateHugeObject");
#endif

View File

@ -109,18 +109,7 @@ bool ValueSerializer::WriteValue(JSThread *thread,
data_->SetIncompleteData(true);
return false;
}
if (value->IsHeapObject()) {
// Add fast path for string
if (value->IsString()) {
vm_->GetSnapshotEnv()->InitializeStringClass();
} else {
vm_->GetSnapshotEnv()->Initialize();
}
}
SerializeJSTaggedValue(value.GetTaggedValue());
if (value->IsHeapObject()) {
vm_->GetSnapshotEnv()->ClearEnvMap();
}
if (notSupport_) {
LOG_ECMA(ERROR) << "ValueSerialize: serialize data is incomplete";
data_->SetIncompleteData(true);

View File

@ -19,49 +19,50 @@
#include "ecmascript/global_env.h"
namespace panda::ecmascript {
void SnapshotEnv::Initialize()
{
InitGlobalConst();
InitGlobalEnv();
}
void SnapshotEnv::InitializeStringClass()
{
auto globalConst = const_cast<GlobalEnvConstants *>(vm_->GetJSThread()->GlobalConstants());
auto lineStringClass = globalConst->GetLineStringClass();
rootObjectMap_.emplace(ToUintPtr(lineStringClass.GetTaggedObject()), globalConst->GetLineStringClassIndex());
auto constStringClass = globalConst->GetConstantStringClass();
rootObjectMap_.emplace(ToUintPtr(constStringClass.GetTaggedObject()), globalConst->GetConstStringClassIndex());
}
void SnapshotEnv::InitGlobalConst()
void SnapshotEnv::AddGlobalConstToMap()
{
auto globalConst = const_cast<GlobalEnvConstants *>(vm_->GetJSThread()->GlobalConstants());
for (size_t index = 0; index < globalConst->GetConstantCount(); index++) {
JSTaggedValue objectValue = globalConst->GetGlobalConstantObject(index);
if (objectValue.IsHeapObject()) {
rootObjectMap_.emplace(ToUintPtr(objectValue.GetTaggedObject()), index);
if (objectValue.IsHeapObject() && !objectValue.IsString()) {
rootObjectMap_.emplace(objectValue.GetRawData(), index);
}
}
}
void SnapshotEnv::InitGlobalEnv()
JSTaggedType SnapshotEnv::RelocateRootObjectAddr(uint32_t index)
{
auto globalEnv = vm_->GetGlobalEnv();
auto globalConst = const_cast<GlobalEnvConstants *>(vm_->GetJSThread()->GlobalConstants());
size_t globalEnvIndexStart = globalConst->GetConstantCount();
for (size_t index = 0; index < globalEnv->GetGlobalEnvFieldSize(); index++) {
JSHandle<JSTaggedValue> objectValue = globalEnv->GetGlobalEnvObjectByIndex(index);
if (objectValue->IsHeapObject() && !objectValue->IsInternalAccessor()) {
rootObjectMap_.emplace(ToUintPtr(objectValue->GetTaggedObject()), index + globalEnvIndexStart);
}
size_t globalConstCount = globalConst->GetConstantCount();
if (index < globalConstCount) {
JSTaggedValue obj = globalConst->GetGlobalConstantObject(index);
return obj.GetRawData();
}
JSHandle<JSTaggedValue> value = vm_->GetGlobalEnv()->GetNoLazyEnvObjectByIndex(index - globalConstCount);
return value->GetRawData();
}
void SnapshotEnv::Iterate(const RootVisitor &v)
{
std::vector<std::pair<JSTaggedType, JSTaggedType>> updatedObjPair;
for (auto &it : rootObjectMap_) {
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&(it.first))));
auto objectAddr = it.first;
ObjectSlot slot(reinterpret_cast<uintptr_t>(&objectAddr));
v(Root::ROOT_VM, slot);
// Record updated obj addr after gc
if (slot.GetTaggedType() != it.first) {
updatedObjPair.emplace_back(std::make_pair(it.first, slot.GetTaggedType()));
}
}
// Update hashmap, erase old objAddr, emplace updated objAddr
while (!updatedObjPair.empty()) {
auto pair = updatedObjPair.back();
ASSERT(rootObjectMap_.find(pair.first) != rootObjectMap_.end());
uint32_t index = rootObjectMap_.find(pair.first)->second;
rootObjectMap_.erase(pair.first);
rootObjectMap_.emplace(pair.second, index);
updatedObjPair.pop_back();
}
}
} // namespace panda::ecmascript

View File

@ -18,20 +18,17 @@
#include <unordered_map>
#include "ecmascript/mem/object_xray.h"
#include "ecmascript/mem/visitor.h"
#include "libpandabase/macros.h"
namespace panda::ecmascript {
class EcmaVM;
class SnapshotEnv final {
public:
explicit SnapshotEnv(EcmaVM *vm) : vm_(vm), objXRay_(vm) {}
explicit SnapshotEnv(EcmaVM *vm) : vm_(vm) {}
~SnapshotEnv() = default;
void Initialize();
void InitializeStringClass();
void AddGlobalConstToMap();
void ClearEnvMap()
{
@ -40,7 +37,17 @@ public:
void Iterate(const RootVisitor &v);
uint32_t FindEnvObjectIndex(uintptr_t objectAddr) const
void Push(JSTaggedType objectAddr, uint32_t index)
{
rootObjectMap_.emplace(objectAddr, index);
}
void Remove(JSTaggedType objectAddr)
{
rootObjectMap_.erase(objectAddr);
}
uint32_t FindEnvObjectIndex(JSTaggedType objectAddr) const
{
if (rootObjectMap_.find(objectAddr) != rootObjectMap_.end()) {
return rootObjectMap_.find(objectAddr)->second;
@ -48,17 +55,7 @@ public:
return MAX_UINT_32;
}
JSTaggedType RelocateRootObjectAddr(uint32_t index)
{
auto globalConst = const_cast<GlobalEnvConstants *>(vm_->GetJSThread()->GlobalConstants());
size_t globalConstCount = globalConst->GetConstantCount();
if (index < globalConstCount) {
JSTaggedValue obj = globalConst->GetGlobalConstantObject(index);
return obj.GetRawData();
}
JSHandle<JSTaggedValue> value = vm_->GetGlobalEnv()->GetNoLazyEnvObjectByIndex(index - globalConstCount);
return value->GetRawData();
}
JSTaggedType RelocateRootObjectAddr(uint32_t index);
static constexpr size_t MAX_UINT_32 = 0xFFFFFFFF;
@ -70,8 +67,7 @@ private:
void InitGlobalEnv();
EcmaVM *vm_;
ObjectXRay objXRay_;
CUnorderedMap<uintptr_t, uint32_t> rootObjectMap_;
std::unordered_map<JSTaggedType, uint32_t> rootObjectMap_;
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_SNAPSHOT_MEM_SNAPSHOT_ENV_H