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:
yingguofeng@huawei.com 2022-02-26 16:48:29 +08:00
parent edce0512b0
commit 92948f92c4
11 changed files with 94 additions and 60 deletions

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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
{

View File

@ -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

View File

@ -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;

View File

@ -124,6 +124,11 @@ public:
return heap_;
}
Space *GetSpace() const
{
return space_;
}
void ResetFlag()
{
flags_ = 0;

View File

@ -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)

View File

@ -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);

View File

@ -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_;

View File

@ -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_);
}
}