mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
!6268 Work serialize optimization
Merge pull request !6268 from dingwen/master
This commit is contained in:
commit
92b478ab09
@ -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;
|
||||
}
|
||||
|
@ -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()); \
|
||||
} \
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ void GlobalIndexMap::InitGlobalIndexMap(const JSThread *thread,
|
||||
JSMutableHandle<PointerToIndexDictionary> globalIndexMap)
|
||||
{
|
||||
if (globalIndexMap.GetTaggedValue().IsHeapObject()) {
|
||||
return ;
|
||||
return;
|
||||
}
|
||||
globalIndexMap.Update(PointerToIndexDictionary::Create(thread));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user