mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-11-23 18:20:04 +00:00
Serialize adapt shared heap
Description:Serialize adapt shared heap Issue:https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I94V01?from=project-issue Signed-off-by: dingwen <dingwen6@huawei.com> Change-Id: Ie0e00fbb7dd854fb8e5f7d2b93d4ffebe1af53a8
This commit is contained in:
parent
c95533cc50
commit
5b9ef75fed
2
BUILD.gn
2
BUILD.gn
@ -137,7 +137,7 @@ group("ark_unittest") {
|
||||
"ecmascript/pgo_profiler/tests:host_unittest",
|
||||
"ecmascript/regexp/tests:host_unittest",
|
||||
"ecmascript/require/tests:host_unittest",
|
||||
# "ecmascript/serializer/tests:host_unittest",
|
||||
"ecmascript/serializer/tests:host_unittest",
|
||||
"ecmascript/snapshot/tests:host_unittest",
|
||||
"ecmascript/tests:host_unittest",
|
||||
"ecmascript/ts_types/tests:host_unittest",
|
||||
|
@ -325,6 +325,16 @@ public:
|
||||
return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_READ_ONLY_SPACE;
|
||||
}
|
||||
|
||||
bool InSharedOldSpace() const
|
||||
{
|
||||
return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_OLD_SPACE;
|
||||
}
|
||||
|
||||
bool InSharedNonMovableSpace() const
|
||||
{
|
||||
return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_NON_MOVABLE;
|
||||
}
|
||||
|
||||
bool InSharedHugeObjectSpace() const
|
||||
{
|
||||
return packedData_.flags_.spaceFlag_ == RegionSpaceFlag::IN_SHARED_HUGE_OBJECT_SPACE;
|
||||
|
@ -50,6 +50,7 @@ void SharedGC::Initialize()
|
||||
void SharedGC::Mark()
|
||||
{
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGC::Mark");
|
||||
sHeap_->GetSharedGCMarker()->MarkSerializeRoots(MAIN_THREAD_INDEX);
|
||||
Runtime::GetInstance()->GCIterateThreadList([&](JSThread *thread) {
|
||||
ASSERT(!thread->IsInRunningState());
|
||||
auto vm = thread->GetEcmaVM();
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "ecmascript/mem/object_xray.h"
|
||||
#include "ecmascript/mem/visitor.h"
|
||||
#include "ecmascript/runtime.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
void SharedGCMarker::MarkRoots(uint32_t threadId, EcmaVM *localVm)
|
||||
@ -32,6 +33,14 @@ void SharedGCMarker::MarkRoots(uint32_t threadId, EcmaVM *localVm)
|
||||
sWorkManager_->PushWorkNodeToGlobal(threadId, false);
|
||||
}
|
||||
|
||||
void SharedGCMarker::MarkSerializeRoots(uint32_t threadId)
|
||||
{
|
||||
ECMA_BYTRACE_NAME(HITRACE_TAG_ARK, "SharedGCMarker::MarkSerializeRoots");
|
||||
auto callback =
|
||||
std::bind(&SharedGCMarker::HandleRoots, this, threadId, std::placeholders::_1, std::placeholders::_2);
|
||||
Runtime::GetInstance()->IterateSerializeRoot(callback);
|
||||
}
|
||||
|
||||
void SharedGCMarker::ProcessMarkStack(uint32_t threadId)
|
||||
{
|
||||
auto cb = [&](ObjectSlot slot) {
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
void ResetWorkManager(SharedGCWorkManager *workManager);
|
||||
void MarkRoots(uint32_t threadId, EcmaVM *localVm);
|
||||
void MarkSerializeRoots(uint32_t threadId);
|
||||
void ProcessMarkStack(uint32_t threadId);
|
||||
template <typename Callback>
|
||||
inline bool VisitBodyInObj(TaggedObject *root, ObjectSlot start, ObjectSlot end, Callback callback);
|
||||
|
@ -38,6 +38,11 @@ void SharedSparseSpace::Reset()
|
||||
liveObjectSize_ = 0;
|
||||
}
|
||||
|
||||
void SharedSparseSpace::ResetTopPointer(uintptr_t top)
|
||||
{
|
||||
allocator_->ResetTopPointer(top);
|
||||
}
|
||||
|
||||
// only used in share heap initialize before first vmThread created.
|
||||
uintptr_t SharedSparseSpace::AllocateWithoutGC(size_t size)
|
||||
{
|
||||
@ -71,6 +76,18 @@ uintptr_t SharedSparseSpace::Allocate(JSThread *thread, size_t size, bool allowG
|
||||
return object;
|
||||
}
|
||||
|
||||
uintptr_t SharedSparseSpace::AllocateNoGCAndExpand([[maybe_unused]] JSThread *thread, size_t size)
|
||||
{
|
||||
ASSERT(thread->IsInRunningState());
|
||||
uintptr_t object = TryAllocate(size);
|
||||
CHECK_SOBJECT_AND_INC_OBJ_SIZE(size);
|
||||
if (sweepState_ == SweepState::SWEEPING) {
|
||||
object = AllocateAfterSweepingCompleted(size);
|
||||
CHECK_SOBJECT_AND_INC_OBJ_SIZE(size);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
uintptr_t SharedSparseSpace::TryAllocate(size_t size)
|
||||
{
|
||||
LockHolder lock(allocateLock_);
|
||||
@ -90,7 +107,7 @@ uintptr_t SharedSparseSpace::AllocateWithExpand(JSThread *thread, size_t size)
|
||||
|
||||
bool SharedSparseSpace::Expand(JSThread *thread)
|
||||
{
|
||||
if (committedSize_ >= maximumCapacity_ + outOfMemoryOvershootSize_) {
|
||||
if (CommittedSizeExceed()) {
|
||||
LOG_ECMA_MEM(INFO) << "Expand::Committed size " << committedSize_ << " of Sparse Space is too big. ";
|
||||
return false;
|
||||
}
|
||||
@ -101,6 +118,24 @@ bool SharedSparseSpace::Expand(JSThread *thread)
|
||||
return true;
|
||||
}
|
||||
|
||||
Region *SharedSparseSpace::AllocateDeserializeRegion(JSThread *thread)
|
||||
{
|
||||
Region *region = heapRegionAllocator_->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE, thread, sHeap_);
|
||||
region->InitializeFreeObjectSets();
|
||||
return region;
|
||||
}
|
||||
|
||||
void SharedSparseSpace::MergeDeserializeAllocateRegions(const std::vector<Region *> &allocateRegions)
|
||||
{
|
||||
LockHolder lock(allocateLock_);
|
||||
for (auto region : allocateRegions) {
|
||||
AddRegion(region);
|
||||
allocator_->AddFree(region);
|
||||
allocator_->ResetTopPointer(region->GetHighWaterMark());
|
||||
region->SetHighWaterMark(region->GetEnd());
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t SharedSparseSpace::AllocateAfterSweepingCompleted(size_t size)
|
||||
{
|
||||
LockHolder lock(allocateLock_);
|
||||
|
@ -59,6 +59,12 @@ public:
|
||||
|
||||
uintptr_t Allocate(JSThread *thread, size_t size, bool allowGC = true);
|
||||
|
||||
// For work deserialize
|
||||
void ResetTopPointer(uintptr_t top);
|
||||
uintptr_t AllocateNoGCAndExpand(JSThread *thread, size_t size);
|
||||
Region *AllocateDeserializeRegion(JSThread *thread);
|
||||
void MergeDeserializeAllocateRegions(const std::vector<Region *> &allocateRegions);
|
||||
|
||||
// For sweeping
|
||||
void PrepareSweeping();
|
||||
void AsyncSweep(bool isMain);
|
||||
@ -91,6 +97,11 @@ public:
|
||||
liveObjectSize_ -= size;
|
||||
}
|
||||
|
||||
bool CommittedSizeExceed()
|
||||
{
|
||||
return committedSize_ >= maximumCapacity_ + outOfMemoryOvershootSize_;
|
||||
}
|
||||
|
||||
size_t GetTotalAllocatedSize() const;
|
||||
|
||||
void InvokeAllocationInspector(Address object, size_t size, size_t alignedSize);
|
||||
|
@ -166,4 +166,13 @@ void Runtime::ResumeAllThreadsImpl(JSThread *current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Runtime::IterateSerializeRoot(const RootVisitor &v)
|
||||
{
|
||||
for (auto &it : serializeRootMap_) {
|
||||
for (auto &rootObj : it.second) {
|
||||
v(Root::ROOT_VM, ObjectSlot(reinterpret_cast<uintptr_t>(&rootObj)));
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace panda::ecmascript
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
|
||||
void SuspendAll(JSThread *current);
|
||||
void ResumeAll(JSThread *current);
|
||||
void IterateSerializeRoot(const RootVisitor &v);
|
||||
|
||||
MutatorLock *GetMutatorLock()
|
||||
{
|
||||
@ -81,6 +82,25 @@ public:
|
||||
return stringTable_.get();
|
||||
}
|
||||
|
||||
uint32_t PushSerializationRoot([[maybe_unused]] JSThread *thread, std::vector<TaggedObject *> &rootSet)
|
||||
{
|
||||
ASSERT(thread->IsInManagedState());
|
||||
LockHolder lock(serializeLock_);
|
||||
uint32_t index = GetSerializeDataIndex();
|
||||
ASSERT(serializeRootMap_.find(index) == serializeRootMap_.end());
|
||||
serializeRootMap_.emplace(index, rootSet);
|
||||
return index;
|
||||
}
|
||||
|
||||
void RemoveSerializationRoot([[maybe_unused]] JSThread *thread, uint32_t index)
|
||||
{
|
||||
ASSERT(thread->IsInManagedState());
|
||||
LockHolder lock(serializeLock_);
|
||||
ASSERT(serializeRootMap_.find(index) != serializeRootMap_.end());
|
||||
serializeRootMap_.erase(index);
|
||||
serializeDataIndexVector_.emplace_back(index);
|
||||
}
|
||||
|
||||
private:
|
||||
Runtime() = default;
|
||||
~Runtime() = default;
|
||||
@ -90,9 +110,21 @@ private:
|
||||
void PreInitialization(const EcmaVM *vm);
|
||||
void PostInitialization(const EcmaVM *vm);
|
||||
|
||||
uint32_t GetSerializeDataIndex()
|
||||
{
|
||||
if (!serializeDataIndexVector_.empty()) {
|
||||
uint32_t index = serializeDataIndexVector_.back();
|
||||
serializeDataIndexVector_.pop_back();
|
||||
return index;
|
||||
}
|
||||
return ++serializeDataIndex_;
|
||||
}
|
||||
|
||||
Mutex threadsLock_;
|
||||
Mutex serializeLock_;
|
||||
std::list<JSThread*> threads_;
|
||||
uint32_t suspendNewCount_ {0};
|
||||
uint32_t serializeDataIndex_ {0};
|
||||
MutatorLock mutatorLock_;
|
||||
|
||||
const GlobalEnvConstants *globalConstants_ {nullptr};
|
||||
@ -103,6 +135,8 @@ private:
|
||||
std::unique_ptr<HeapRegionAllocator> heapRegionAllocator_;
|
||||
// for stringTable.
|
||||
std::unique_ptr<EcmaStringTable> stringTable_;
|
||||
std::unordered_map<uint32_t, std::vector<TaggedObject *>> serializeRootMap_;
|
||||
std::vector<uint32_t> serializeDataIndexVector_;
|
||||
|
||||
// Runtime instance and VMs creation.
|
||||
static int32_t vmCount_;
|
||||
|
@ -33,7 +33,10 @@ namespace panda::ecmascript {
|
||||
(uint8_t)SerializedObjectSpace::OLD_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::NON_MOVABLE_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::MACHINE_CODE_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::HUGE_SPACE
|
||||
case (uint8_t)SerializedObjectSpace::HUGE_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::SHARED_OLD_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE: \
|
||||
case (uint8_t)SerializedObjectSpace::SHARED_HUGE_SPACE
|
||||
|
||||
JSHandle<JSTaggedValue> BaseDeserializer::ReadValue()
|
||||
{
|
||||
@ -400,6 +403,12 @@ size_t BaseDeserializer::ReadSingleEncodeData(uint8_t encodeFlag, uintptr_t objA
|
||||
handledFieldSize = 0;
|
||||
break;
|
||||
}
|
||||
case (uint8_t)EncodeFlag::SHARED_OBJECT: {
|
||||
JSTaggedType value = data_->ReadJSTaggedType();
|
||||
objectVector_.push_back(value);
|
||||
UpdateMaybeWeak(slot, value, GetAndResetWeak());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
@ -435,15 +444,42 @@ uintptr_t BaseDeserializer::RelocateObjectAddr(SerializedObjectSpace space, size
|
||||
ASSERT(machineCodeRegionIndex_ < regionVector_.size());
|
||||
machineCodeSpaceBeginAddr_ = regionVector_[machineCodeRegionIndex_++]->GetBegin();
|
||||
}
|
||||
res = nonMovableSpaceBeginAddr_;
|
||||
nonMovableSpaceBeginAddr_ += objSize;
|
||||
res = machineCodeSpaceBeginAddr_;
|
||||
machineCodeSpaceBeginAddr_ += objSize;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case SerializedObjectSpace::HUGE_SPACE: {
|
||||
// no gc for this allocate
|
||||
res = heap_->GetHugeObjectSpace()->Allocate(objSize, thread_);
|
||||
break;
|
||||
}
|
||||
case SerializedObjectSpace::SHARED_OLD_SPACE: {
|
||||
if (sOldSpaceBeginAddr_ + objSize > AlignUp(sOldSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
|
||||
ASSERT(sOldRegionIndex_ < regionVector_.size());
|
||||
sOldSpaceBeginAddr_ = regionVector_[sOldRegionIndex_++]->GetBegin();
|
||||
}
|
||||
res = sOldSpaceBeginAddr_;
|
||||
sOldSpaceBeginAddr_ += objSize;
|
||||
break;
|
||||
}
|
||||
case SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE: {
|
||||
if (sNonMovableSpaceBeginAddr_ + objSize > AlignUp(sNonMovableSpaceBeginAddr_, DEFAULT_REGION_SIZE)) {
|
||||
ASSERT(sNonMovableRegionIndex_ < regionVector_.size());
|
||||
sNonMovableSpaceBeginAddr_ = regionVector_[sNonMovableRegionIndex_++]->GetBegin();
|
||||
}
|
||||
res = sNonMovableSpaceBeginAddr_;
|
||||
sNonMovableSpaceBeginAddr_ += objSize;
|
||||
break;
|
||||
}
|
||||
case SerializedObjectSpace::SHARED_HUGE_SPACE: {
|
||||
// no gc for this allocate
|
||||
res = sheap_->GetHugeObjectSpace()->Allocate(thread_, objSize);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -538,6 +574,16 @@ void BaseDeserializer::AllocateToDifferentSpaces()
|
||||
heap_->GetMachineCodeSpace()->IncreaseLiveObjectSize(machineCodeSpaceSize);
|
||||
AllocateToMachineCodeSpace(machineCodeSpaceSize);
|
||||
}
|
||||
size_t sOldSpaceSize = data_->GetSharedOldSpaceSize();
|
||||
if (sOldSpaceSize > 0) {
|
||||
sheap_->GetOldSpace()->IncreaseLiveObjectSize(sOldSpaceSize);
|
||||
AllocateToSharedOldSpace(sOldSpaceSize);
|
||||
}
|
||||
size_t sNonMovableSpaceSize = data_->GetSharedNonMovableSpaceSize();
|
||||
if (sNonMovableSpaceSize > 0) {
|
||||
sheap_->GetNonMovableSpace()->IncreaseLiveObjectSize(sNonMovableSpaceSize);
|
||||
AllocateToSharedNonMovableSpace(sNonMovableSpaceSize);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex)
|
||||
@ -558,6 +604,32 @@ void BaseDeserializer::AllocateMultiRegion(SparseSpace *space, size_t spaceObjSi
|
||||
space->ResetTopPointer(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
|
||||
}
|
||||
|
||||
Region *BaseDeserializer::AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex)
|
||||
{
|
||||
regionIndex = regionVector_.size();
|
||||
size_t regionAlignedSize = SerializeData::AlignUpRegionAvailableSize(spaceObjSize);
|
||||
size_t regionNum = regionAlignedSize / Region::GetRegionAvailableSize();
|
||||
std::vector<size_t> regionRemainSizeVector = data_->GetRegionRemainSizeVector();
|
||||
std::vector<Region *> allocateRegions;
|
||||
while (regionNum > 0) {
|
||||
if (space->CommittedSizeExceed()) {
|
||||
LOG_ECMA(FATAL) << "BaseDeserializer::OutOfMemory when deserialize";
|
||||
}
|
||||
Region *region = space->AllocateDeserializeRegion(thread_);
|
||||
if (regionNum == 1) { // 1: Last allocate region
|
||||
size_t lastRegionRemainSize = regionAlignedSize - spaceObjSize;
|
||||
region->SetHighWaterMark(space->GetCurrentRegion()->GetEnd() - lastRegionRemainSize);
|
||||
} else {
|
||||
region->SetHighWaterMark(region->GetEnd() - regionRemainSizeVector[regionRemainSizeIndex_++]);
|
||||
}
|
||||
regionVector_.push_back(region);
|
||||
allocateRegions.push_back(region);
|
||||
regionNum--;
|
||||
}
|
||||
space->MergeDeserializeAllocateRegions(allocateRegions);
|
||||
return allocateRegions.front();
|
||||
}
|
||||
|
||||
void BaseDeserializer::AllocateToOldSpace(size_t oldSpaceSize)
|
||||
{
|
||||
SparseSpace *space = heap_->GetOldSpace();
|
||||
@ -603,5 +675,29 @@ void BaseDeserializer::AllocateToMachineCodeSpace(size_t machineCodeSpaceSize)
|
||||
}
|
||||
}
|
||||
|
||||
void BaseDeserializer::AllocateToSharedOldSpace(size_t sOldSpaceSize)
|
||||
{
|
||||
SharedSparseSpace *space = sheap_->GetOldSpace();
|
||||
uintptr_t object = space->AllocateNoGCAndExpand(thread_, sOldSpaceSize);
|
||||
if (UNLIKELY(object == 0U)) {
|
||||
Region *region = AllocateMultiSharedRegion(space, sOldSpaceSize, sOldRegionIndex_);
|
||||
sOldSpaceBeginAddr_ = region->GetBegin();
|
||||
} else {
|
||||
sOldSpaceBeginAddr_ = object;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseDeserializer::AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize)
|
||||
{
|
||||
SharedNonMovableSpace *space = sheap_->GetNonMovableSpace();
|
||||
uintptr_t object = space->AllocateNoGCAndExpand(thread_, sNonMovableSpaceSize);
|
||||
if (UNLIKELY(object == 0U)) {
|
||||
Region *region = AllocateMultiSharedRegion(space, sNonMovableSpaceSize, sNonMovableRegionIndex_);
|
||||
sNonMovableSpaceBeginAddr_ = region->GetBegin();
|
||||
} else {
|
||||
sNonMovableSpaceBeginAddr_ = object;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace panda::ecmascript
|
||||
|
||||
|
@ -105,7 +105,10 @@ struct JSErrorInfo {
|
||||
class BaseDeserializer {
|
||||
public:
|
||||
explicit BaseDeserializer(JSThread *thread, SerializeData *data, void *hint = nullptr)
|
||||
: thread_(thread), heap_(const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())), data_(data), engine_(hint) {}
|
||||
: thread_(thread), heap_(const_cast<Heap *>(thread->GetEcmaVM()->GetHeap())), data_(data), engine_(hint)
|
||||
{
|
||||
sheap_ = SharedHeap::GetInstance();
|
||||
}
|
||||
~BaseDeserializer()
|
||||
{
|
||||
data_->ResetPosition();
|
||||
@ -137,9 +140,12 @@ private:
|
||||
|
||||
void AllocateToDifferentSpaces();
|
||||
void AllocateMultiRegion(SparseSpace *space, size_t spaceObjSize, size_t ®ionIndex);
|
||||
Region *AllocateMultiSharedRegion(SharedSparseSpace *space, size_t spaceObjSize, size_t ®ionIndex);
|
||||
void AllocateToOldSpace(size_t oldSpaceSize);
|
||||
void AllocateToNonMovableSpace(size_t nonMovableSpaceSize);
|
||||
void AllocateToMachineCodeSpace(size_t machineCodeSpaceSize);
|
||||
void AllocateToSharedOldSpace(size_t sOldSpaceSize);
|
||||
void AllocateToSharedNonMovableSpace(size_t sNonMovableSpaceSize);
|
||||
|
||||
bool GetAndResetWeak()
|
||||
{
|
||||
@ -214,16 +220,21 @@ private:
|
||||
private:
|
||||
JSThread *thread_;
|
||||
Heap *heap_;
|
||||
SharedHeap *sheap_;
|
||||
SerializeData* data_;
|
||||
void *engine_;
|
||||
uintptr_t oldSpaceBeginAddr_ {0};
|
||||
uintptr_t nonMovableSpaceBeginAddr_ {0};
|
||||
uintptr_t machineCodeSpaceBeginAddr_ {0};
|
||||
uintptr_t sOldSpaceBeginAddr_ {0};
|
||||
uintptr_t sNonMovableSpaceBeginAddr_ {0};
|
||||
CVector<uintptr_t> objectVector_;
|
||||
CVector<Region *> regionVector_;
|
||||
size_t oldRegionIndex_ {0};
|
||||
size_t nonMovableRegionIndex_ {0};
|
||||
size_t machineCodeRegionIndex_ {0};
|
||||
size_t sOldRegionIndex_ {0};
|
||||
size_t sNonMovableRegionIndex_ {0};
|
||||
size_t regionRemainSizeIndex_ {0};
|
||||
bool isWeak_ {false};
|
||||
bool isTransferArrayBuffer_ {false};
|
||||
|
@ -24,8 +24,7 @@ namespace panda::ecmascript {
|
||||
SerializedObjectSpace BaseSerializer::GetSerializedObjectSpace(TaggedObject *object) const
|
||||
{
|
||||
auto region = Region::ObjectAddressToRange(object);
|
||||
// TODO(lukai) allocateToSharedSpace please!
|
||||
if (region->InYoungOrOldSpace() || region->InAppSpawnSpace() || region->InSharedHeap()) {
|
||||
if (region->InYoungOrOldSpace() || region->InAppSpawnSpace()) {
|
||||
return SerializedObjectSpace::OLD_SPACE;
|
||||
}
|
||||
if (region->InNonMovableSpace() || region->InReadOnlySpace()) {
|
||||
@ -37,6 +36,15 @@ SerializedObjectSpace BaseSerializer::GetSerializedObjectSpace(TaggedObject *obj
|
||||
if (region->InHugeObjectSpace()) {
|
||||
return SerializedObjectSpace::HUGE_SPACE;
|
||||
}
|
||||
if (region->InSharedOldSpace()) {
|
||||
return SerializedObjectSpace::SHARED_OLD_SPACE;
|
||||
}
|
||||
if (region->InSharedNonMovableSpace()) {
|
||||
return SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE;
|
||||
}
|
||||
if (region->InSharedHugeObjectSpace()) {
|
||||
return SerializedObjectSpace::SHARED_HUGE_SPACE;
|
||||
}
|
||||
LOG_ECMA(FATAL) << "this branch is unreachable";
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -88,6 +96,14 @@ bool BaseSerializer::SerializeRootObject(TaggedObject *object)
|
||||
return false;
|
||||
}
|
||||
|
||||
void BaseSerializer::SerializeSharedObject(TaggedObject *object)
|
||||
{
|
||||
data_->WriteEncodeFlag(EncodeFlag::SHARED_OBJECT);
|
||||
data_->WriteJSTaggedType(reinterpret_cast<JSTaggedType>(object));
|
||||
referenceMap_.emplace(object, objectIndex_++);
|
||||
sharedObjects_.emplace_back(object);
|
||||
}
|
||||
|
||||
bool BaseSerializer::SerializeSpecialObjIndividually(JSType objectType, TaggedObject *root,
|
||||
ObjectSlot start, ObjectSlot end)
|
||||
{
|
||||
|
@ -50,6 +50,7 @@ protected:
|
||||
void SerializeTaggedObject(TaggedObject *object);
|
||||
bool SerializeReference(TaggedObject *object);
|
||||
bool SerializeRootObject(TaggedObject *object);
|
||||
void SerializeSharedObject(TaggedObject *object);
|
||||
template<SerializeType serializeType>
|
||||
void SerializeObjectField(TaggedObject *object);
|
||||
bool SerializeSpecialObjIndividually(JSType objectType, TaggedObject *root, ObjectSlot start, ObjectSlot end);
|
||||
@ -68,6 +69,7 @@ protected:
|
||||
EcmaVM *vm_;
|
||||
std::unique_ptr<SerializeData> data_;
|
||||
CUnorderedMap<TaggedObject *, uint32_t> referenceMap_;
|
||||
std::vector<TaggedObject *> sharedObjects_;
|
||||
size_t objectIndex_ {0};
|
||||
static constexpr size_t PARENT_ENV_SLOT = sizeof(TaggedObject);
|
||||
static constexpr size_t SCOPE_INFO_SLOT = PARENT_ENV_SLOT * 2; // 2: the second object slot of lexical env
|
||||
|
@ -18,19 +18,23 @@
|
||||
|
||||
#include "ecmascript/js_tagged_value-inl.h"
|
||||
#include "ecmascript/mem/dyn_chunk.h"
|
||||
#include "ecmascript/runtime.h"
|
||||
#include "ecmascript/snapshot/mem/snapshot_env.h"
|
||||
|
||||
namespace panda::ecmascript {
|
||||
constexpr size_t INITIAL_CAPACITY = 64;
|
||||
constexpr int CAPACITY_INCREASE_RATE = 2;
|
||||
enum class EncodeFlag : uint8_t {
|
||||
// 0x00~0x03 represent new object to different space:
|
||||
// 0x00~0x06 represent new object to different space:
|
||||
// 0x00: old space
|
||||
// 0x01: non movable space
|
||||
// 0x02: machine code space
|
||||
// 0x03: huge space
|
||||
// 0x04: shared old space
|
||||
// 0x05: shared non movable space
|
||||
// 0x06: shared huge space
|
||||
NEW_OBJECT = 0x00,
|
||||
REFERENCE = 0x04,
|
||||
REFERENCE = 0x07,
|
||||
WEAK,
|
||||
PRIMITIVE,
|
||||
MULTI_RAW_DATA,
|
||||
@ -43,6 +47,7 @@ enum class EncodeFlag : uint8_t {
|
||||
JS_ERROR,
|
||||
JS_REG_EXP,
|
||||
JS_FUNCTION_IN_SHARED,
|
||||
SHARED_OBJECT,
|
||||
LAST
|
||||
};
|
||||
|
||||
@ -50,7 +55,10 @@ enum class SerializedObjectSpace : uint8_t {
|
||||
OLD_SPACE = 0,
|
||||
NON_MOVABLE_SPACE,
|
||||
MACHINE_CODE_SPACE,
|
||||
HUGE_SPACE
|
||||
HUGE_SPACE,
|
||||
SHARED_OLD_SPACE,
|
||||
SHARED_NON_MOVABLE_SPACE,
|
||||
SHARED_HUGE_SPACE
|
||||
};
|
||||
|
||||
enum class SerializeType : uint8_t {
|
||||
@ -65,6 +73,9 @@ public:
|
||||
{
|
||||
regionRemainSizeVector_.clear();
|
||||
free(buffer_);
|
||||
if (!incompleteData_) {
|
||||
Runtime::GetInstance()->RemoveSerializationRoot(thread_, dataIndex_);
|
||||
}
|
||||
}
|
||||
NO_COPY_SEMANTIC(SerializeData);
|
||||
NO_MOVE_SEMANTIC(SerializeData);
|
||||
@ -285,6 +296,16 @@ public:
|
||||
return machineCodeSpaceSize_;
|
||||
}
|
||||
|
||||
size_t GetSharedOldSpaceSize() const
|
||||
{
|
||||
return sharedOldSpaceSize_;
|
||||
}
|
||||
|
||||
size_t GetSharedNonMovableSpaceSize() const
|
||||
{
|
||||
return sharedNonMovableSpaceSize_;
|
||||
}
|
||||
|
||||
void CalculateSerializedObjectSize(SerializedObjectSpace space, size_t objectSize)
|
||||
{
|
||||
switch (space) {
|
||||
@ -297,6 +318,12 @@ public:
|
||||
case SerializedObjectSpace::MACHINE_CODE_SPACE:
|
||||
AlignSpaceObjectSize(machineCodeSpaceSize_, objectSize);
|
||||
break;
|
||||
case SerializedObjectSpace::SHARED_OLD_SPACE:
|
||||
AlignSpaceObjectSize(sharedOldSpaceSize_, objectSize);
|
||||
break;
|
||||
case SerializedObjectSpace::SHARED_NON_MOVABLE_SPACE:
|
||||
AlignSpaceObjectSize(sharedNonMovableSpaceSize_, objectSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -318,12 +345,23 @@ public:
|
||||
position_ = 0;
|
||||
}
|
||||
|
||||
void SetDataIndex(uint32_t dataIndex)
|
||||
{
|
||||
dataIndex_ = dataIndex;
|
||||
}
|
||||
|
||||
uint32_t GetDataIndex() const
|
||||
{
|
||||
return dataIndex_;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t U8_SIZE = 1;
|
||||
static constexpr size_t U16_SIZE = 2;
|
||||
static constexpr size_t U32_SIZE = 4;
|
||||
static constexpr size_t U64_SIZE = 8;
|
||||
JSThread *thread_;
|
||||
uint32_t dataIndex_;
|
||||
uint8_t *buffer_ = nullptr;
|
||||
uint64_t sizeLimit_ = 0;
|
||||
size_t bufferSize_ = 0;
|
||||
@ -331,6 +369,8 @@ private:
|
||||
size_t oldSpaceSize_ {0};
|
||||
size_t nonMovableSpaceSize_ {0};
|
||||
size_t machineCodeSpaceSize_ {0};
|
||||
size_t sharedOldSpaceSize_ {0};
|
||||
size_t sharedNonMovableSpaceSize_ {0};
|
||||
size_t position_ {0};
|
||||
bool incompleteData_ {false};
|
||||
std::vector<size_t> regionRemainSizeVector_;
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
|
||||
EXPECT_FALSE(res.IsEmpty());
|
||||
EXPECT_TRUE(res->IsLineString());
|
||||
EXPECT_TRUE(res->IsTreeString());
|
||||
|
||||
Destroy();
|
||||
}
|
||||
@ -134,7 +134,7 @@ public:
|
||||
ecmaVm->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
|
||||
EXPECT_FALSE(res.IsEmpty());
|
||||
EXPECT_TRUE(res->IsLineString());
|
||||
EXPECT_TRUE(res->IsSlicedString());
|
||||
|
||||
Destroy();
|
||||
}
|
||||
|
@ -126,6 +126,11 @@ bool ValueSerializer::WriteValue(JSThread *thread,
|
||||
data_->SetIncompleteData(true);
|
||||
return false;
|
||||
}
|
||||
// Push share root object to runtime map
|
||||
if (!sharedObjects_.empty()) {
|
||||
uint32_t index = Runtime::GetInstance()->PushSerializationRoot(thread_, sharedObjects_);
|
||||
data_->SetDataIndex(index);
|
||||
}
|
||||
size_t maxSerializerSize = vm_->GetEcmaParamConfiguration().GetMaxJSSerializerSize();
|
||||
if (data_->Size() > maxSerializerSize) {
|
||||
LOG_ECMA(ERROR) << "The serialization data size has exceed limit Size, current size is: " << data_->Size()
|
||||
@ -151,6 +156,12 @@ void ValueSerializer::SerializeObjectImpl(TaggedObject *object, bool isWeak)
|
||||
if (SerializeReference(object) || SerializeRootObject(object)) {
|
||||
return;
|
||||
}
|
||||
Region *region = Region::ObjectAddressToRange(object);
|
||||
if (object->GetClass()->IsString() || region->InSharedReadOnlySpace() ||
|
||||
(serializeSharedEvent_ == 0 && region->InSharedHeap())) {
|
||||
SerializeSharedObject(object);
|
||||
return;
|
||||
}
|
||||
if (object->GetClass()->IsNativeBindingObject()) {
|
||||
SerializeNativeBindingObject(object);
|
||||
return;
|
||||
@ -180,10 +191,6 @@ void ValueSerializer::SerializeObjectImpl(TaggedObject *object, bool isWeak)
|
||||
array->SetTrackInfo(thread_, JSTaggedValue::Undefined());
|
||||
break;
|
||||
}
|
||||
case JSType::TREE_STRING:
|
||||
case JSType::SLICED_STRING:
|
||||
object = EcmaStringAccessor::FlattenNoGC(vm_, EcmaString::Cast(object));
|
||||
break;
|
||||
case JSType::JS_REG_EXP:
|
||||
SerializeJSRegExpPrologue(reinterpret_cast<JSRegExp *>(object));
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user