mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Bugfix:Fix application bug that found by monkey testing
Description:The Type of Size field in FreeObject modified to JSTaggedValue. Nonmovable And HugeObject Space OOM bugfix issue: https://gitee.com/openharmony/ark_js_runtime/issues/I4VE6U Signed-off-by: yingguofeng@huawei.com <yingguofeng@huawei.com> Change-Id: If4f046d26500e6d7635a3b6e7e7b1c5817027f08
This commit is contained in:
parent
edce0512b0
commit
92948f92c4
@ -47,7 +47,7 @@ public:
|
||||
inline void SetAvailable(uint32_t size)
|
||||
{
|
||||
if (size >= SIZE) {
|
||||
SetSize(size);
|
||||
SetSize(JSTaggedValue(size));
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,7 +57,8 @@ public:
|
||||
if (hclass->IsFreeObjectWithShortField()) {
|
||||
return hclass->GetObjectSize();
|
||||
}
|
||||
return GetSize();
|
||||
ASSERT(GetSize().IsInt());
|
||||
return GetSize().GetInt();
|
||||
}
|
||||
|
||||
inline bool IsFreeObject() const
|
||||
@ -67,7 +68,8 @@ public:
|
||||
|
||||
static constexpr size_t NEXT_OFFSET = TaggedObjectSize();
|
||||
ACCESSORS_FIXED_SIZE_FIELD(Next, FreeObject *, JSTaggedType, NEXT_OFFSET, SIZE_OFFSET)
|
||||
ACCESSORS_FIXED_SIZE_FIELD(Size, uint32_t, JSTaggedType, SIZE_OFFSET, SIZE)
|
||||
// TaggedArray visitor may be error while concurrent marking
|
||||
ACCESSORS(Size, SIZE_OFFSET, SIZE)
|
||||
};
|
||||
|
||||
static_assert((FreeObject::SIZE % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
|
||||
|
@ -78,7 +78,7 @@ void ConcurrentMarker::HandleMarkFinished() // js-thread wait for sweep
|
||||
{
|
||||
os::memory::LockHolder lock(waitMarkingFinishedMutex_);
|
||||
if (notifyMarkingFinished_) {
|
||||
heap_->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
heap_->CollectGarbage(TriggerGCType::SEMI_GC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +99,15 @@ void ConcurrentMarker::Reset(bool isRevertCSet)
|
||||
if (isRevertCSet) {
|
||||
// Mix space gc clear cset when evacuation allocator finalize
|
||||
heap_->GetOldSpace()->RevertCSet();
|
||||
auto callback = [](Region *region) {
|
||||
region->ClearMarkBitmap();
|
||||
region->ClearCrossRegionRememberedSet();
|
||||
};
|
||||
if (heap_->IsFullMark()) {
|
||||
heap_->EnumerateRegions(callback);
|
||||
} else {
|
||||
heap_->EnumerateNewSpaceRegions(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,12 +55,10 @@ void FullGC::InitializePhase()
|
||||
heap_->Prepare();
|
||||
auto callback = [](Region *current) {
|
||||
// ensure mark bitmap
|
||||
current->ClearMarkBitmap();
|
||||
auto rememberset = current->GetOldToNewRememberedSet();
|
||||
if (rememberset != nullptr) {
|
||||
rememberset->ClearAllBits();
|
||||
}
|
||||
current->ClearCrossRegionRememberedSet();
|
||||
};
|
||||
heap_->EnumerateNonMovableRegions(callback);
|
||||
heap_->SwapNewSpace();
|
||||
|
@ -55,6 +55,12 @@ void Heap::EnumerateNonNewSpaceRegions(const Callback &cb) const
|
||||
machineCodeSpace_->EnumerateRegions(cb);
|
||||
}
|
||||
|
||||
template<class Callback>
|
||||
void Heap::EnumerateNewSpaceRegions(const Callback &cb) const
|
||||
{
|
||||
toSpace_->EnumerateRegions(cb);
|
||||
}
|
||||
|
||||
template<class Callback>
|
||||
void Heap::EnumerateNonMovableRegions(const Callback &cb) const
|
||||
{
|
||||
|
@ -236,10 +236,6 @@ void Heap::CollectGarbage(TriggerGCType gcType)
|
||||
LOG(FATAL, GC) << "Before gc heap corrupted and " << failCount << " corruptions";
|
||||
}
|
||||
isVerifying_ = false;
|
||||
// verify need semiGC or fullGC.
|
||||
if (gcType != TriggerGCType::SEMI_GC) {
|
||||
gcType = TriggerGCType::FULL_GC;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ECMASCRIPT_SWITCH_GC_MODE_TO_FULL_GC
|
||||
@ -261,9 +257,13 @@ void Heap::CollectGarbage(TriggerGCType gcType)
|
||||
mixGC_->RunPhases();
|
||||
break;
|
||||
case TriggerGCType::OLD_GC:
|
||||
if (!concurrentMarkingEnabled_) {
|
||||
SetMarkType(MarkType::FULL_MARK);
|
||||
if (concurrentMarkingEnabled_ && markType_ == MarkType::SEMI_MARK) {
|
||||
bool concurrentMark = CheckConcurrentMark();
|
||||
if (concurrentMark) {
|
||||
GetConcurrentMarker()->Reset();
|
||||
}
|
||||
}
|
||||
SetMarkType(MarkType::FULL_MARK);
|
||||
mixGC_->RunPhases();
|
||||
break;
|
||||
case TriggerGCType::FULL_GC:
|
||||
@ -620,6 +620,7 @@ size_t Heap::GetArrayBufferSize() const
|
||||
bool Heap::IsLive(TaggedObject *object) const
|
||||
{
|
||||
if (!ContainObject(object)) {
|
||||
LOG(ERROR, RUNTIME) << "The region is already free";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -627,7 +628,13 @@ bool Heap::IsLive(TaggedObject *object) const
|
||||
if (region->InHugeObjectGeneration()) {
|
||||
return true;
|
||||
}
|
||||
return !FreeObject::Cast(ToUintPtr(object))->IsFreeObject();
|
||||
bool isFree = FreeObject::Cast(ToUintPtr(object))->IsFreeObject();
|
||||
if (isFree) {
|
||||
LOG(ERROR, RUNTIME) << "The object " << object << " in "
|
||||
<< ToSpaceTypeName(region->GetSpace()->GetSpaceType())
|
||||
<< " already free";
|
||||
}
|
||||
return !isFree;
|
||||
}
|
||||
|
||||
bool Heap::ContainObject(TaggedObject *object) const
|
||||
|
@ -185,6 +185,9 @@ public:
|
||||
template<class Callback>
|
||||
void EnumerateNonNewSpaceRegions(const Callback &cb) const;
|
||||
|
||||
template<class Callback>
|
||||
void EnumerateNewSpaceRegions(const Callback &cb) const;
|
||||
|
||||
template<class Callback>
|
||||
void EnumerateSnapShotSpaceRegions(const Callback &cb) const;
|
||||
|
||||
|
@ -124,6 +124,11 @@ public:
|
||||
return heap_;
|
||||
}
|
||||
|
||||
Space *GetSpace() const
|
||||
{
|
||||
return space_;
|
||||
}
|
||||
|
||||
void ResetFlag()
|
||||
{
|
||||
flags_ = 0;
|
||||
|
@ -50,6 +50,7 @@ void Space::ReclaimRegions()
|
||||
void Space::ClearAndFreeRegion(Region *region)
|
||||
{
|
||||
LOG_ECMA_MEM(DEBUG) << "Clear region from:" << region << " to " << ToSpaceTypeName(spaceType_);
|
||||
region->SetSpace(nullptr);
|
||||
region->DeleteMarkBitmap();
|
||||
region->DeleteCrossRegionRememberedSet();
|
||||
region->DeleteOldToNewRememberedSet();
|
||||
@ -64,15 +65,8 @@ void Space::ClearAndFreeRegion(Region *region)
|
||||
|
||||
bool Space::ContainObject(TaggedObject *object) const
|
||||
{
|
||||
auto region = GetRegionList().GetFirst();
|
||||
while (region != nullptr) {
|
||||
if (region->InRange(ToUintPtr(object))) {
|
||||
return true;
|
||||
}
|
||||
region = region->GetNext();
|
||||
}
|
||||
|
||||
return false;
|
||||
Region *region = Region::ObjectAddressToRange(object);
|
||||
return region->GetSpace() == this;
|
||||
}
|
||||
|
||||
HugeObjectSpace::HugeObjectSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacity)
|
||||
|
@ -50,48 +50,34 @@ void SparseSpace::Reset()
|
||||
ReclaimRegions();
|
||||
}
|
||||
|
||||
uintptr_t SparseSpace::Allocate(size_t size)
|
||||
uintptr_t SparseSpace::Allocate(size_t size, bool isAllowGC)
|
||||
{
|
||||
auto object = allocator_->Allocate(size);
|
||||
if (object == 0) {
|
||||
if (sweepState_ == SweepState::SWEEPING) {
|
||||
MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), ConcurrentSweepingWait);
|
||||
if (FillSweptRegion()) {
|
||||
object = allocator_->Allocate(size);
|
||||
if (object != 0) {
|
||||
liveObjectSize_ += size;
|
||||
return object;
|
||||
}
|
||||
}
|
||||
// Parallel
|
||||
heap_->GetSweeper()->EnsureTaskFinished(spaceType_);
|
||||
object = allocator_->Allocate(size);
|
||||
if (object != 0) {
|
||||
liveObjectSize_ += size;
|
||||
return object;
|
||||
}
|
||||
}
|
||||
CHECK_OBJECT_AND_INC_OBJ_SIZE(size);
|
||||
|
||||
if (Expand()) {
|
||||
object = allocator_->Allocate(size);
|
||||
} else {
|
||||
heap_->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
if (Expand()) {
|
||||
object = allocator_->Allocate(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (object != 0) {
|
||||
liveObjectSize_ += size;
|
||||
if (sweepState_ == SweepState::SWEEPING) {
|
||||
object = AllocateAfterSweepingCompleted(size);
|
||||
CHECK_OBJECT_AND_INC_OBJ_SIZE(size);
|
||||
}
|
||||
|
||||
if (Expand()) {
|
||||
object = allocator_->Allocate(size);
|
||||
CHECK_OBJECT_AND_INC_OBJ_SIZE(size);
|
||||
return object;
|
||||
}
|
||||
|
||||
if (isAllowGC) {
|
||||
heap_->CollectGarbage(TriggerGCType::OLD_GC);
|
||||
object = Allocate(size, false);
|
||||
// Size is already increment
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
bool SparseSpace::Expand()
|
||||
{
|
||||
if (committedSize_ >= initialCapacity_) {
|
||||
LOG_ECMA_MEM(FATAL) << "Expand::Committed size " << committedSize_ << " of old space is too big. ";
|
||||
LOG_ECMA_MEM(INFO) << "Expand::Committed size " << committedSize_ << " of old space is too big. ";
|
||||
return false;
|
||||
}
|
||||
Region *region = heapRegionAllocator_->AllocateAlignedRegion(this, DEFAULT_REGION_SIZE);
|
||||
@ -106,6 +92,22 @@ bool SparseSpace::Expand()
|
||||
return true;
|
||||
}
|
||||
|
||||
uintptr_t SparseSpace::AllocateAfterSweepingCompleted(size_t size)
|
||||
{
|
||||
ASSERT(sweepState_ == SweepState::SWEEPING);
|
||||
MEM_ALLOCATE_AND_GC_TRACE(heap_->GetEcmaVM(), ConcurrentSweepingWait);
|
||||
if (FillSweptRegion()) {
|
||||
auto object = allocator_->Allocate(size);
|
||||
if (object != 0) {
|
||||
liveObjectSize_ += size;
|
||||
return object;
|
||||
}
|
||||
}
|
||||
// Parallel
|
||||
heap_->GetSweeper()->EnsureTaskFinished(spaceType_);
|
||||
return allocator_->Allocate(size);
|
||||
}
|
||||
|
||||
void SparseSpace::PrepareSweeping()
|
||||
{
|
||||
liveObjectSize_ = 0;
|
||||
@ -358,7 +360,7 @@ void OldSpace::CheckRegionSize()
|
||||
size_t available = allocator_->GetAvailableSize();
|
||||
size_t wasted = allocator_->GetWastedSize();
|
||||
if (GetHeapObjectSize() + wasted + available != objectSize_) {
|
||||
LOG(ERROR, RUNTIME) << "Actual live object size:" << GetHeapObjectSize()
|
||||
LOG(DEBUG, RUNTIME) << "Actual live object size:" << GetHeapObjectSize()
|
||||
<< ", free object size:" << available
|
||||
<< ", wasted size:" << wasted
|
||||
<< ", but exception totoal size:" << objectSize_;
|
||||
@ -382,6 +384,7 @@ void OldSpace::RevertCSet()
|
||||
void OldSpace::ReclaimCSet()
|
||||
{
|
||||
EnumerateCollectRegionSet([this](Region *region) {
|
||||
region->SetSpace(nullptr);
|
||||
region->DeleteMarkBitmap();
|
||||
region->DeleteCrossRegionRememberedSet();
|
||||
region->DeleteOldToNewRememberedSet();
|
||||
@ -398,7 +401,7 @@ LocalSpace::LocalSpace(Heap *heap, size_t initialCapacity, size_t maximumCapacit
|
||||
bool LocalSpace::AddRegionToList(Region *region)
|
||||
{
|
||||
if (committedSize_ >= maximumCapacity_) {
|
||||
LOG_ECMA_MEM(FATAL) << "Expand::Committed size " << committedSize_ << " of old space is too big. ";
|
||||
LOG_ECMA_MEM(FATAL) << "AddRegionTotList::Committed size " << committedSize_ << " of local space is too big.";
|
||||
return false;
|
||||
}
|
||||
region->SetSpace(this);
|
||||
|
@ -18,6 +18,12 @@
|
||||
|
||||
#include "ecmascript/mem/space-inl.h"
|
||||
|
||||
#define CHECK_OBJECT_AND_INC_OBJ_SIZE(size) \
|
||||
if (object != 0) { \
|
||||
IncrementLiveObjectSize(size); \
|
||||
return object; \
|
||||
}
|
||||
|
||||
enum class SweepState : uint8_t {
|
||||
NO_SWEEP,
|
||||
SWEEPING,
|
||||
@ -37,8 +43,7 @@ public:
|
||||
void Initialize() override;
|
||||
void Reset();
|
||||
|
||||
uintptr_t Allocate(size_t size);
|
||||
|
||||
uintptr_t Allocate(size_t size, bool isAllowGC = true);
|
||||
bool Expand();
|
||||
|
||||
// For sweeping
|
||||
@ -80,6 +85,8 @@ protected:
|
||||
|
||||
private:
|
||||
// For sweeping
|
||||
uintptr_t AllocateAfterSweepingCompleted(size_t size);
|
||||
|
||||
os::memory::Mutex lock_;
|
||||
std::vector<Region *> sweepingList_;
|
||||
std::vector<Region *> sweptList_;
|
||||
|
@ -30,14 +30,14 @@ void VerifyObjectVisitor::VisitAllObjects(TaggedObject *obj)
|
||||
JSTaggedValue value(slot.GetTaggedType());
|
||||
if (value.IsWeak()) {
|
||||
if (!heap_->IsLive(value.GetTaggedWeakRef())) {
|
||||
LOG(ERROR, RUNTIME) << "Heap verify detected a dead object at " << value.GetTaggedObject()
|
||||
<< "at object:" << slot.SlotAddress();
|
||||
LOG(ERROR, RUNTIME) << "Heap verify detected a dead weak object " << value.GetTaggedObject()
|
||||
<< " at object:" << slot.SlotAddress();
|
||||
++(*failCount_);
|
||||
}
|
||||
} else if (value.IsHeapObject()) {
|
||||
if (!heap_->IsLive(value.GetTaggedObject())) {
|
||||
LOG(ERROR, RUNTIME) << "Heap verify detected a dead object at " << value.GetTaggedObject()
|
||||
<< "at object:" << slot.SlotAddress();
|
||||
<< " at object:" << slot.SlotAddress();
|
||||
++(*failCount_);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user