[heap] Untangle Marking and friends from heap dependencies.
BUG= Review-Url: https://codereview.chromium.org/2139133003 Cr-Commit-Position: refs/heads/master@{#37685}
This commit is contained in:
parent
0ddd158b74
commit
ea90556a2f
1
BUILD.gn
1
BUILD.gn
@ -1229,6 +1229,7 @@ v8_source_set("v8_base") {
|
||||
"src/heap/mark-compact-inl.h",
|
||||
"src/heap/mark-compact.cc",
|
||||
"src/heap/mark-compact.h",
|
||||
"src/heap/marking.h",
|
||||
"src/heap/memory-reducer.cc",
|
||||
"src/heap/memory-reducer.h",
|
||||
"src/heap/object-stats.cc",
|
||||
|
@ -20,7 +20,7 @@ void LocalArrayBufferTracker::Free() {
|
||||
it != array_buffers_.end();) {
|
||||
JSArrayBuffer* buffer = reinterpret_cast<JSArrayBuffer*>(it->first);
|
||||
if ((free_mode == kFreeAll) ||
|
||||
Marking::IsWhite(Marking::MarkBitFrom(buffer))) {
|
||||
Marking::IsWhite(ObjectMarking::MarkBitFrom(buffer))) {
|
||||
const size_t len = it->second;
|
||||
heap_->isolate()->array_buffer_allocator()->Free(buffer->backing_store(),
|
||||
len);
|
||||
|
@ -254,7 +254,7 @@ AllocationResult Heap::AllocateRaw(int size_in_bytes, AllocationSpace space,
|
||||
|
||||
if (!old_gen_exhausted_ && incremental_marking()->black_allocation() &&
|
||||
space != OLD_SPACE) {
|
||||
Marking::MarkBlack(Marking::MarkBitFrom(object));
|
||||
Marking::MarkBlack(ObjectMarking::MarkBitFrom(object));
|
||||
MemoryChunk::IncrementLiveBytesFromGC(object, size_in_bytes);
|
||||
}
|
||||
return allocation;
|
||||
@ -399,7 +399,7 @@ bool Heap::ShouldBePromoted(Address old_address, int object_size) {
|
||||
Address age_mark = new_space_.age_mark();
|
||||
|
||||
if (promotion_mode == PROMOTE_MARKED) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(old_address);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(old_address);
|
||||
if (!Marking::IsWhite(mark_bit)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -3112,7 +3112,7 @@ void Heap::AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode) {
|
||||
lo_space()->AdjustLiveBytes(by);
|
||||
} else if (!in_heap_iterator() &&
|
||||
!mark_compact_collector()->sweeping_in_progress() &&
|
||||
Marking::IsBlack(Marking::MarkBitFrom(object->address()))) {
|
||||
Marking::IsBlack(ObjectMarking::MarkBitFrom(object->address()))) {
|
||||
if (mode == SEQUENTIAL_TO_SWEEPER) {
|
||||
MemoryChunk::IncrementLiveBytesFromGC(object, by);
|
||||
} else {
|
||||
@ -3169,7 +3169,7 @@ FixedArrayBase* Heap::LeftTrimFixedArray(FixedArrayBase* object,
|
||||
new_object, FixedArrayBase::kLengthOffset));
|
||||
|
||||
// Maintain consistency of live bytes during incremental marking
|
||||
Marking::TransferMark(this, object->address(), new_start);
|
||||
IncrementalMarking::TransferMark(this, object->address(), new_start);
|
||||
AdjustLiveBytes(new_object, -bytes_to_trim, Heap::CONCURRENT_TO_SWEEPER);
|
||||
|
||||
// Notify the heap profiler of change in object layout.
|
||||
@ -4191,7 +4191,7 @@ void Heap::RegisterReservationsForBlackAllocation(Reservation* reservations) {
|
||||
Address addr = chunk.start;
|
||||
while (addr < chunk.end) {
|
||||
HeapObject* obj = HeapObject::FromAddress(addr);
|
||||
Marking::MarkBlack(Marking::MarkBitFrom(obj));
|
||||
Marking::MarkBlack(ObjectMarking::MarkBitFrom(obj));
|
||||
MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
|
||||
addr += obj->Size();
|
||||
}
|
||||
@ -4711,7 +4711,7 @@ void Heap::IteratePromotedObject(HeapObject* target, int size,
|
||||
// it would be a violation of the invariant to record it's slots.
|
||||
bool record_slots = false;
|
||||
if (incremental_marking()->IsCompacting()) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(target);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(target);
|
||||
record_slots = Marking::IsBlack(mark_bit);
|
||||
}
|
||||
|
||||
@ -5889,7 +5889,7 @@ class UnreachableObjectsFilter : public HeapObjectsFilter {
|
||||
|
||||
bool SkipObject(HeapObject* object) {
|
||||
if (object->IsFiller()) return true;
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
|
||||
return Marking::IsWhite(mark_bit);
|
||||
}
|
||||
|
||||
@ -5902,7 +5902,7 @@ class UnreachableObjectsFilter : public HeapObjectsFilter {
|
||||
for (Object** p = start; p < end; p++) {
|
||||
if (!(*p)->IsHeapObject()) continue;
|
||||
HeapObject* obj = HeapObject::cast(*p);
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
if (Marking::IsWhite(mark_bit)) {
|
||||
Marking::WhiteToBlack(mark_bit);
|
||||
marking_stack_.Add(obj);
|
||||
|
@ -49,10 +49,10 @@ IncrementalMarking::IncrementalMarking(Heap* heap)
|
||||
|
||||
bool IncrementalMarking::BaseRecordWrite(HeapObject* obj, Object* value) {
|
||||
HeapObject* value_heap_obj = HeapObject::cast(value);
|
||||
MarkBit value_bit = Marking::MarkBitFrom(value_heap_obj);
|
||||
MarkBit value_bit = ObjectMarking::MarkBitFrom(value_heap_obj);
|
||||
DCHECK(!Marking::IsImpossible(value_bit));
|
||||
|
||||
MarkBit obj_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit obj_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
DCHECK(!Marking::IsImpossible(obj_bit));
|
||||
bool is_black = Marking::IsBlack(obj_bit);
|
||||
|
||||
@ -150,7 +150,7 @@ void IncrementalMarking::WhiteToGreyAndPush(HeapObject* obj, MarkBit mark_bit) {
|
||||
static void MarkObjectGreyDoNotEnqueue(Object* obj) {
|
||||
if (obj->IsHeapObject()) {
|
||||
HeapObject* heap_obj = HeapObject::cast(obj);
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj));
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(HeapObject::cast(obj));
|
||||
if (Marking::IsBlack(mark_bit)) {
|
||||
MemoryChunk::IncrementLiveBytesFromGC(heap_obj, -heap_obj->Size());
|
||||
}
|
||||
@ -158,6 +158,44 @@ static void MarkObjectGreyDoNotEnqueue(Object* obj) {
|
||||
}
|
||||
}
|
||||
|
||||
void IncrementalMarking::TransferMark(Heap* heap, Address old_start,
|
||||
Address new_start) {
|
||||
// This is only used when resizing an object.
|
||||
DCHECK(MemoryChunk::FromAddress(old_start) ==
|
||||
MemoryChunk::FromAddress(new_start));
|
||||
|
||||
if (!heap->incremental_marking()->IsMarking() ||
|
||||
Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE))
|
||||
return;
|
||||
|
||||
// If the mark doesn't move, we don't check the color of the object.
|
||||
// It doesn't matter whether the object is black, since it hasn't changed
|
||||
// size, so the adjustment to the live data count will be zero anyway.
|
||||
if (old_start == new_start) return;
|
||||
|
||||
MarkBit new_mark_bit = ObjectMarking::MarkBitFrom(new_start);
|
||||
MarkBit old_mark_bit = ObjectMarking::MarkBitFrom(old_start);
|
||||
|
||||
#ifdef DEBUG
|
||||
Marking::ObjectColor old_color = Marking::Color(old_mark_bit);
|
||||
#endif
|
||||
|
||||
if (Marking::IsBlack(old_mark_bit)) {
|
||||
Marking::BlackToWhite(old_mark_bit);
|
||||
Marking::MarkBlack(new_mark_bit);
|
||||
return;
|
||||
} else if (Marking::IsGrey(old_mark_bit)) {
|
||||
Marking::GreyToWhite(old_mark_bit);
|
||||
heap->incremental_marking()->WhiteToGreyAndPush(
|
||||
HeapObject::FromAddress(new_start), new_mark_bit);
|
||||
heap->incremental_marking()->RestartIfNotMarking();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Marking::ObjectColor new_color = Marking::Color(new_mark_bit);
|
||||
DCHECK(new_color == old_color);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void MarkBlackOrKeepBlack(HeapObject* heap_object,
|
||||
MarkBit mark_bit, int size) {
|
||||
@ -167,7 +205,6 @@ static inline void MarkBlackOrKeepBlack(HeapObject* heap_object,
|
||||
MemoryChunk::IncrementLiveBytesFromGC(heap_object, size);
|
||||
}
|
||||
|
||||
|
||||
class IncrementalMarkingMarkingVisitor
|
||||
: public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> {
|
||||
public:
|
||||
@ -214,10 +251,10 @@ class IncrementalMarkingMarkingVisitor
|
||||
} while (scan_until_end && start_offset < object_size);
|
||||
chunk->set_progress_bar(start_offset);
|
||||
if (start_offset < object_size) {
|
||||
if (Marking::IsGrey(Marking::MarkBitFrom(object))) {
|
||||
if (Marking::IsGrey(ObjectMarking::MarkBitFrom(object))) {
|
||||
heap->mark_compact_collector()->marking_deque()->Unshift(object);
|
||||
} else {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
heap->mark_compact_collector()->UnshiftBlack(object);
|
||||
}
|
||||
heap->incremental_marking()->NotifyIncompleteScanOfObject(
|
||||
@ -269,7 +306,7 @@ class IncrementalMarkingMarkingVisitor
|
||||
// Returns true if object needed marking and false otherwise.
|
||||
INLINE(static bool MarkObjectWithoutPush(Heap* heap, Object* obj)) {
|
||||
HeapObject* heap_object = HeapObject::cast(obj);
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object);
|
||||
if (Marking::IsWhite(mark_bit)) {
|
||||
Marking::MarkBlack(mark_bit);
|
||||
MemoryChunk::IncrementLiveBytesFromGC(heap_object, heap_object->Size());
|
||||
@ -280,7 +317,7 @@ class IncrementalMarkingMarkingVisitor
|
||||
};
|
||||
|
||||
void IncrementalMarking::IterateBlackObject(HeapObject* object) {
|
||||
if (IsMarking() && Marking::IsBlack(Marking::MarkBitFrom(object))) {
|
||||
if (IsMarking() && Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) {
|
||||
Page* page = Page::FromAddress(object->address());
|
||||
if ((page->owner() != nullptr) && (page->owner()->identity() == LO_SPACE)) {
|
||||
// IterateBlackObject requires us to visit the whole object.
|
||||
@ -654,7 +691,8 @@ bool ShouldRetainMap(Map* map, int age) {
|
||||
}
|
||||
Object* constructor = map->GetConstructor();
|
||||
if (!constructor->IsHeapObject() ||
|
||||
Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(constructor)))) {
|
||||
Marking::IsWhite(
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(constructor)))) {
|
||||
// The constructor is dead, no new objects with this map can
|
||||
// be created. Do not retain this map.
|
||||
return false;
|
||||
@ -683,7 +721,7 @@ void IncrementalMarking::RetainMaps() {
|
||||
int age = Smi::cast(retained_maps->Get(i + 1))->value();
|
||||
int new_age;
|
||||
Map* map = Map::cast(cell->value());
|
||||
MarkBit map_mark = Marking::MarkBitFrom(map);
|
||||
MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
|
||||
if (i >= number_of_disposed_maps && !map_retaining_is_disabled &&
|
||||
Marking::IsWhite(map_mark)) {
|
||||
if (ShouldRetainMap(map, age)) {
|
||||
@ -691,7 +729,8 @@ void IncrementalMarking::RetainMaps() {
|
||||
}
|
||||
Object* prototype = map->prototype();
|
||||
if (age > 0 && prototype->IsHeapObject() &&
|
||||
Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) {
|
||||
Marking::IsWhite(
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(prototype)))) {
|
||||
// The prototype is not marked, age the map.
|
||||
new_age = age - 1;
|
||||
} else {
|
||||
@ -803,7 +842,7 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() {
|
||||
new_top = ((new_top + 1) & mask);
|
||||
DCHECK(new_top != marking_deque->bottom());
|
||||
#ifdef DEBUG
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
DCHECK(Marking::IsGrey(mark_bit) ||
|
||||
(obj->IsFiller() && Marking::IsWhite(mark_bit)));
|
||||
#endif
|
||||
@ -815,7 +854,7 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() {
|
||||
new_top = ((new_top + 1) & mask);
|
||||
DCHECK(new_top != marking_deque->bottom());
|
||||
#ifdef DEBUG
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
|
||||
DCHECK(Marking::IsGrey(mark_bit) ||
|
||||
(obj->IsFiller() && Marking::IsWhite(mark_bit)) ||
|
||||
@ -833,7 +872,7 @@ void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) {
|
||||
|
||||
IncrementalMarkingMarkingVisitor::IterateBody(map, obj);
|
||||
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
#if ENABLE_SLOW_DCHECKS
|
||||
MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
|
||||
SLOW_DCHECK(Marking::IsGrey(mark_bit) ||
|
||||
@ -846,7 +885,7 @@ void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) {
|
||||
|
||||
|
||||
void IncrementalMarking::MarkObject(Heap* heap, HeapObject* obj) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
if (Marking::IsWhite(mark_bit)) {
|
||||
heap->incremental_marking()->WhiteToGreyAndPush(obj, mark_bit);
|
||||
}
|
||||
@ -933,7 +972,7 @@ void IncrementalMarking::Hurry() {
|
||||
HeapObject* cache = HeapObject::cast(
|
||||
Context::cast(context)->get(Context::NORMALIZED_MAP_CACHE_INDEX));
|
||||
if (!cache->IsUndefined(heap_->isolate())) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(cache);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(cache);
|
||||
if (Marking::IsGrey(mark_bit)) {
|
||||
Marking::GreyToBlack(mark_bit);
|
||||
MemoryChunk::IncrementLiveBytesFromGC(cache, cache->Size());
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "src/execution.h"
|
||||
#include "src/heap/heap.h"
|
||||
#include "src/heap/incremental-marking-job.h"
|
||||
#include "src/heap/mark-compact.h"
|
||||
#include "src/heap/spaces.h"
|
||||
#include "src/objects.h"
|
||||
|
||||
@ -205,6 +206,25 @@ class IncrementalMarking {
|
||||
|
||||
static void MarkObject(Heap* heap, HeapObject* object);
|
||||
|
||||
static void TransferMark(Heap* heap, Address old_start, Address new_start);
|
||||
|
||||
// Returns true if the transferred color is black.
|
||||
INLINE(static bool TransferColor(HeapObject* from, HeapObject* to)) {
|
||||
if (Page::FromAddress(to->address())->IsFlagSet(Page::BLACK_PAGE))
|
||||
return true;
|
||||
MarkBit from_mark_bit = ObjectMarking::MarkBitFrom(from);
|
||||
MarkBit to_mark_bit = ObjectMarking::MarkBitFrom(to);
|
||||
DCHECK(Marking::IsWhite(to_mark_bit));
|
||||
if (from_mark_bit.Get()) {
|
||||
to_mark_bit.Set();
|
||||
if (from_mark_bit.Next().Get()) {
|
||||
to_mark_bit.Next().Set();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IterateBlackObject(HeapObject* object);
|
||||
|
||||
Heap* heap() const { return heap_; }
|
||||
|
@ -13,26 +13,28 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void MarkCompactCollector::PushBlack(HeapObject* obj) {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(obj)));
|
||||
if (marking_deque_.Push(obj)) {
|
||||
MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
|
||||
} else {
|
||||
Marking::BlackToGrey(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
Marking::BlackToGrey(mark_bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MarkCompactCollector::UnshiftBlack(HeapObject* obj) {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(obj)));
|
||||
if (!marking_deque_.Unshift(obj)) {
|
||||
MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size());
|
||||
Marking::BlackToGrey(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
Marking::BlackToGrey(mark_bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
|
||||
DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
|
||||
DCHECK(ObjectMarking::MarkBitFrom(obj) == mark_bit);
|
||||
if (Marking::IsWhite(mark_bit)) {
|
||||
Marking::WhiteToBlack(mark_bit);
|
||||
DCHECK(obj->GetIsolate()->heap()->Contains(obj));
|
||||
@ -43,7 +45,7 @@ void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
|
||||
|
||||
void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
|
||||
DCHECK(Marking::IsWhite(mark_bit));
|
||||
DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
|
||||
DCHECK(ObjectMarking::MarkBitFrom(obj) == mark_bit);
|
||||
Marking::WhiteToBlack(mark_bit);
|
||||
MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
|
||||
}
|
||||
@ -52,7 +54,7 @@ void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
|
||||
bool MarkCompactCollector::IsMarked(Object* obj) {
|
||||
DCHECK(obj->IsHeapObject());
|
||||
HeapObject* heap_object = HeapObject::cast(obj);
|
||||
return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object));
|
||||
return Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(heap_object));
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +64,7 @@ void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot,
|
||||
Page* source_page = Page::FromAddress(reinterpret_cast<Address>(object));
|
||||
if (target_page->IsEvacuationCandidate() &&
|
||||
!ShouldSkipEvacuationSlotRecording(object)) {
|
||||
DCHECK(Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)));
|
||||
DCHECK(Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(object)));
|
||||
RememberedSet<OLD_TO_OLD>::Insert(source_page,
|
||||
reinterpret_cast<Address>(slot));
|
||||
}
|
||||
|
@ -37,9 +37,8 @@ const char* Marking::kBlackBitPattern = "11";
|
||||
const char* Marking::kGreyBitPattern = "10";
|
||||
const char* Marking::kImpossibleBitPattern = "01";
|
||||
|
||||
|
||||
// The following has to hold in order for {Marking::MarkBitFrom} to not produce
|
||||
// invalid {kImpossibleBitPattern} in the marking bitmap by overlapping.
|
||||
// The following has to hold in order for {ObjectMarking::MarkBitFrom} to not
|
||||
// produce invalid {kImpossibleBitPattern} in the marking bitmap by overlapping.
|
||||
STATIC_ASSERT(Heap::kMinObjectSizeInWords >= 2);
|
||||
|
||||
|
||||
@ -109,7 +108,7 @@ static void VerifyMarking(Heap* heap, Address bottom, Address top) {
|
||||
for (Address current = bottom; current < top; current += kPointerSize) {
|
||||
object = HeapObject::FromAddress(current);
|
||||
if (MarkCompactCollector::IsMarked(object)) {
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
CHECK(current >= next_object_must_be_here_or_later);
|
||||
object->Iterate(&visitor);
|
||||
next_object_must_be_here_or_later = current + object->Size();
|
||||
@ -124,7 +123,7 @@ static void VerifyMarkingBlackPage(Heap* heap, Page* page) {
|
||||
VerifyMarkingVisitor visitor(heap);
|
||||
HeapObjectIterator it(page);
|
||||
for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
object->Iterate(&visitor);
|
||||
}
|
||||
}
|
||||
@ -377,7 +376,7 @@ void MarkCompactCollector::VerifyMarkbitsAreClean() {
|
||||
|
||||
LargeObjectIterator it(heap_->lo_space());
|
||||
for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(obj);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK_EQ(0, Page::FromAddress(obj->address())->LiveBytes());
|
||||
}
|
||||
@ -408,7 +407,7 @@ void MarkCompactCollector::VerifyOmittedMapChecks() {
|
||||
|
||||
static void ClearMarkbitsInPagedSpace(PagedSpace* space) {
|
||||
for (Page* p : *space) {
|
||||
Bitmap::Clear(p);
|
||||
p->ClearLiveness();
|
||||
if (p->IsFlagSet(Page::BLACK_PAGE)) {
|
||||
p->ClearFlag(Page::BLACK_PAGE);
|
||||
}
|
||||
@ -418,7 +417,7 @@ static void ClearMarkbitsInPagedSpace(PagedSpace* space) {
|
||||
|
||||
static void ClearMarkbitsInNewSpace(NewSpace* space) {
|
||||
for (Page* page : *space) {
|
||||
Bitmap::Clear(page);
|
||||
page->ClearLiveness();
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,7 +430,7 @@ void MarkCompactCollector::ClearMarkbits() {
|
||||
|
||||
LargeObjectIterator it(heap_->lo_space());
|
||||
for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
|
||||
Marking::MarkWhite(Marking::MarkBitFrom(obj));
|
||||
Marking::MarkWhite(ObjectMarking::MarkBitFrom(obj));
|
||||
MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address());
|
||||
chunk->ResetProgressBar();
|
||||
chunk->ResetLiveBytes();
|
||||
@ -584,45 +583,6 @@ bool MarkCompactCollector::Sweeper::IsSweepingCompleted() {
|
||||
return num_sweeping_tasks_.Value() == 0;
|
||||
}
|
||||
|
||||
void Marking::TransferMark(Heap* heap, Address old_start, Address new_start) {
|
||||
// This is only used when resizing an object.
|
||||
DCHECK(MemoryChunk::FromAddress(old_start) ==
|
||||
MemoryChunk::FromAddress(new_start));
|
||||
|
||||
if (!heap->incremental_marking()->IsMarking() ||
|
||||
Page::FromAddress(old_start)->IsFlagSet(Page::BLACK_PAGE))
|
||||
return;
|
||||
|
||||
// If the mark doesn't move, we don't check the color of the object.
|
||||
// It doesn't matter whether the object is black, since it hasn't changed
|
||||
// size, so the adjustment to the live data count will be zero anyway.
|
||||
if (old_start == new_start) return;
|
||||
|
||||
MarkBit new_mark_bit = MarkBitFrom(new_start);
|
||||
MarkBit old_mark_bit = MarkBitFrom(old_start);
|
||||
|
||||
#ifdef DEBUG
|
||||
ObjectColor old_color = Color(old_mark_bit);
|
||||
#endif
|
||||
|
||||
if (Marking::IsBlack(old_mark_bit)) {
|
||||
Marking::BlackToWhite(old_mark_bit);
|
||||
Marking::MarkBlack(new_mark_bit);
|
||||
return;
|
||||
} else if (Marking::IsGrey(old_mark_bit)) {
|
||||
Marking::GreyToWhite(old_mark_bit);
|
||||
heap->incremental_marking()->WhiteToGreyAndPush(
|
||||
HeapObject::FromAddress(new_start), new_mark_bit);
|
||||
heap->incremental_marking()->RestartIfNotMarking();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
ObjectColor new_color = Color(new_mark_bit);
|
||||
DCHECK(new_color == old_color);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
const char* AllocationSpaceName(AllocationSpace space) {
|
||||
switch (space) {
|
||||
case NEW_SPACE:
|
||||
@ -972,7 +932,7 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
|
||||
SharedFunctionInfo* shared = candidate->shared();
|
||||
|
||||
Code* code = shared->code();
|
||||
MarkBit code_mark = Marking::MarkBitFrom(code);
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(code);
|
||||
if (Marking::IsWhite(code_mark)) {
|
||||
if (FLAG_trace_code_flushing && shared->is_compiled()) {
|
||||
PrintF("[code-flushing clears: ");
|
||||
@ -1019,7 +979,7 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
|
||||
ClearNextCandidate(candidate);
|
||||
|
||||
Code* code = candidate->code();
|
||||
MarkBit code_mark = Marking::MarkBitFrom(code);
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(code);
|
||||
if (Marking::IsWhite(code_mark)) {
|
||||
if (FLAG_trace_code_flushing && candidate->is_compiled()) {
|
||||
PrintF("[code-flushing clears: ");
|
||||
@ -1156,14 +1116,14 @@ class MarkCompactMarkingVisitor
|
||||
|
||||
// Marks the object black and pushes it on the marking stack.
|
||||
INLINE(static void MarkObject(Heap* heap, HeapObject* object)) {
|
||||
MarkBit mark = Marking::MarkBitFrom(object);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(object);
|
||||
heap->mark_compact_collector()->MarkObject(object, mark);
|
||||
}
|
||||
|
||||
// Marks the object black without pushing it on the marking stack.
|
||||
// Returns true if object needed marking and false otherwise.
|
||||
INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
|
||||
if (Marking::IsWhite(mark_bit)) {
|
||||
heap->mark_compact_collector()->SetMark(object, mark_bit);
|
||||
return true;
|
||||
@ -1177,7 +1137,7 @@ class MarkCompactMarkingVisitor
|
||||
if (!(*p)->IsHeapObject()) return;
|
||||
HeapObject* target_object = HeapObject::cast(*p);
|
||||
collector->RecordSlot(object, p, target_object);
|
||||
MarkBit mark = Marking::MarkBitFrom(target_object);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(target_object);
|
||||
collector->MarkObject(target_object, mark);
|
||||
}
|
||||
|
||||
@ -1191,10 +1151,10 @@ class MarkCompactMarkingVisitor
|
||||
#endif
|
||||
Map* map = obj->map();
|
||||
Heap* heap = obj->GetHeap();
|
||||
MarkBit mark = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(obj);
|
||||
heap->mark_compact_collector()->SetMark(obj, mark);
|
||||
// Mark the map pointer and the body.
|
||||
MarkBit map_mark = Marking::MarkBitFrom(map);
|
||||
MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
|
||||
heap->mark_compact_collector()->MarkObject(map, map_mark);
|
||||
IterateBody(map, obj);
|
||||
}
|
||||
@ -1214,7 +1174,7 @@ class MarkCompactMarkingVisitor
|
||||
if (!o->IsHeapObject()) continue;
|
||||
collector->RecordSlot(object, p, o);
|
||||
HeapObject* obj = HeapObject::cast(o);
|
||||
MarkBit mark = Marking::MarkBitFrom(obj);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(obj);
|
||||
if (Marking::IsBlackOrGrey(mark)) continue;
|
||||
VisitUnmarkedObject(collector, obj);
|
||||
}
|
||||
@ -1248,7 +1208,7 @@ class MarkCompactMarkingVisitor
|
||||
// was marked through the compilation cache before marker reached JSRegExp
|
||||
// object.
|
||||
FixedArray* data = FixedArray::cast(re->data());
|
||||
if (Marking::IsBlackOrGrey(Marking::MarkBitFrom(data))) {
|
||||
if (Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(data))) {
|
||||
Object** slot =
|
||||
data->data_start() + JSRegExp::saved_code_index(is_one_byte);
|
||||
heap->mark_compact_collector()->RecordSlot(data, slot, code);
|
||||
@ -1336,8 +1296,8 @@ class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
|
||||
Object* obj = *slot;
|
||||
if (obj->IsSharedFunctionInfo()) {
|
||||
SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
|
||||
MarkBit shared_mark = Marking::MarkBitFrom(shared);
|
||||
MarkBit code_mark = Marking::MarkBitFrom(shared->code());
|
||||
MarkBit shared_mark = ObjectMarking::MarkBitFrom(shared);
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(shared->code());
|
||||
collector_->MarkObject(shared->code(), code_mark);
|
||||
collector_->MarkObject(shared, shared_mark);
|
||||
}
|
||||
@ -1357,11 +1317,11 @@ void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate,
|
||||
// actual optimized code object.
|
||||
StackFrame* frame = it.frame();
|
||||
Code* code = frame->unchecked_code();
|
||||
MarkBit code_mark = Marking::MarkBitFrom(code);
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(code);
|
||||
MarkObject(code, code_mark);
|
||||
if (frame->is_optimized()) {
|
||||
Code* optimized_code = frame->LookupCode();
|
||||
MarkBit optimized_code_mark = Marking::MarkBitFrom(optimized_code);
|
||||
MarkBit optimized_code_mark = ObjectMarking::MarkBitFrom(optimized_code);
|
||||
MarkObject(optimized_code, optimized_code_mark);
|
||||
}
|
||||
}
|
||||
@ -1413,7 +1373,7 @@ class RootMarkingVisitor : public ObjectVisitor {
|
||||
|
||||
HeapObject* object = HeapObject::cast(*p);
|
||||
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
|
||||
if (Marking::IsBlackOrGrey(mark_bit)) return;
|
||||
|
||||
Map* map = object->map();
|
||||
@ -1421,7 +1381,7 @@ class RootMarkingVisitor : public ObjectVisitor {
|
||||
collector_->SetMark(object, mark_bit);
|
||||
|
||||
// Mark the map pointer and body, and push them on the marking stack.
|
||||
MarkBit map_mark = Marking::MarkBitFrom(map);
|
||||
MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
|
||||
collector_->MarkObject(map, map_mark);
|
||||
MarkCompactMarkingVisitor::IterateBody(map, object);
|
||||
|
||||
@ -1449,7 +1409,7 @@ class StringTableCleaner : public ObjectVisitor {
|
||||
for (Object** p = start; p < end; p++) {
|
||||
Object* o = *p;
|
||||
if (o->IsHeapObject()) {
|
||||
if (Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(o)))) {
|
||||
if (Marking::IsWhite(ObjectMarking::MarkBitFrom(HeapObject::cast(o)))) {
|
||||
if (finalize_external_strings) {
|
||||
DCHECK(o->IsExternalString());
|
||||
heap_->FinalizeExternalString(String::cast(*p));
|
||||
@ -1486,7 +1446,7 @@ typedef StringTableCleaner<true, false> ExternalStringTableCleaner;
|
||||
class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
|
||||
public:
|
||||
virtual Object* RetainAs(Object* object) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(object));
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(HeapObject::cast(object));
|
||||
DCHECK(!Marking::IsGrey(mark_bit));
|
||||
if (Marking::IsBlack(mark_bit)) {
|
||||
return object;
|
||||
@ -1516,7 +1476,7 @@ void MarkCompactCollector::DiscoverGreyObjectsWithIterator(T* it) {
|
||||
|
||||
Map* filler_map = heap()->one_pointer_filler_map();
|
||||
for (HeapObject* object = it->Next(); object != NULL; object = it->Next()) {
|
||||
MarkBit markbit = Marking::MarkBitFrom(object);
|
||||
MarkBit markbit = ObjectMarking::MarkBitFrom(object);
|
||||
if ((object->map() != filler_map) && Marking::IsGrey(markbit)) {
|
||||
Marking::GreyToBlack(markbit);
|
||||
PushBlack(object);
|
||||
@ -1530,7 +1490,7 @@ void MarkCompactCollector::DiscoverGreyObjectsOnPage(MemoryChunk* p) {
|
||||
LiveObjectIterator<kGreyObjects> it(p);
|
||||
HeapObject* object = NULL;
|
||||
while ((object = it.Next()) != NULL) {
|
||||
MarkBit markbit = Marking::MarkBitFrom(object);
|
||||
MarkBit markbit = ObjectMarking::MarkBitFrom(object);
|
||||
DCHECK(Marking::IsGrey(markbit));
|
||||
Marking::GreyToBlack(markbit);
|
||||
PushBlack(object);
|
||||
@ -1976,7 +1936,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
|
||||
Object* o = *p;
|
||||
if (!o->IsHeapObject()) return false;
|
||||
HeapObject* heap_object = HeapObject::cast(o);
|
||||
MarkBit mark = Marking::MarkBitFrom(heap_object);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(heap_object);
|
||||
return Marking::IsWhite(mark);
|
||||
}
|
||||
|
||||
@ -1986,7 +1946,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
|
||||
Object* o = *p;
|
||||
DCHECK(o->IsHeapObject());
|
||||
HeapObject* heap_object = HeapObject::cast(o);
|
||||
MarkBit mark = Marking::MarkBitFrom(heap_object);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(heap_object);
|
||||
return Marking::IsWhite(mark);
|
||||
}
|
||||
|
||||
@ -1994,7 +1954,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
|
||||
void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) {
|
||||
StringTable* string_table = heap()->string_table();
|
||||
// Mark the string table itself.
|
||||
MarkBit string_table_mark = Marking::MarkBitFrom(string_table);
|
||||
MarkBit string_table_mark = ObjectMarking::MarkBitFrom(string_table);
|
||||
if (Marking::IsWhite(string_table_mark)) {
|
||||
// String table could have already been marked by visiting the handles list.
|
||||
SetMark(string_table, string_table_mark);
|
||||
@ -2006,7 +1966,7 @@ void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) {
|
||||
|
||||
|
||||
void MarkCompactCollector::MarkAllocationSite(AllocationSite* site) {
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(site);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(site);
|
||||
SetMark(site, mark_bit);
|
||||
}
|
||||
|
||||
@ -2073,9 +2033,9 @@ void MarkCompactCollector::EmptyMarkingDeque() {
|
||||
|
||||
DCHECK(object->IsHeapObject());
|
||||
DCHECK(heap()->Contains(object));
|
||||
DCHECK(!Marking::IsWhite(Marking::MarkBitFrom(object)));
|
||||
DCHECK(!Marking::IsWhite(ObjectMarking::MarkBitFrom(object)));
|
||||
|
||||
MarkBit map_mark = Marking::MarkBitFrom(map);
|
||||
MarkBit map_mark = ObjectMarking::MarkBitFrom(map);
|
||||
MarkObject(map, map_mark);
|
||||
|
||||
MarkCompactMarkingVisitor::IterateBody(map, object);
|
||||
@ -2278,7 +2238,7 @@ void MarkCompactCollector::RegisterExternallyReferencedObject(Object** object) {
|
||||
DCHECK(in_use());
|
||||
HeapObject* heap_object = HeapObject::cast(*object);
|
||||
DCHECK(heap_->Contains(heap_object));
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(heap_object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(heap_object);
|
||||
MarkObject(heap_object, mark_bit);
|
||||
}
|
||||
|
||||
@ -2521,11 +2481,11 @@ void MarkCompactCollector::ClearSimpleMapTransitions(
|
||||
while (weak_cell_obj != Smi::FromInt(0)) {
|
||||
WeakCell* weak_cell = WeakCell::cast(weak_cell_obj);
|
||||
Map* map = Map::cast(weak_cell->value());
|
||||
DCHECK(Marking::IsWhite(Marking::MarkBitFrom(map)));
|
||||
DCHECK(Marking::IsWhite(ObjectMarking::MarkBitFrom(map)));
|
||||
Object* potential_parent = map->constructor_or_backpointer();
|
||||
if (potential_parent->IsMap()) {
|
||||
Map* parent = Map::cast(potential_parent);
|
||||
if (Marking::IsBlackOrGrey(Marking::MarkBitFrom(parent)) &&
|
||||
if (Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(parent)) &&
|
||||
parent->raw_transitions() == weak_cell) {
|
||||
ClearSimpleMapTransition(parent, map);
|
||||
}
|
||||
@ -2565,7 +2525,7 @@ void MarkCompactCollector::ClearFullMapTransitions() {
|
||||
Map* map = array->GetTarget(0);
|
||||
Map* parent = Map::cast(map->constructor_or_backpointer());
|
||||
bool parent_is_alive =
|
||||
Marking::IsBlackOrGrey(Marking::MarkBitFrom(parent));
|
||||
Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(parent));
|
||||
DescriptorArray* descriptors =
|
||||
parent_is_alive ? parent->instance_descriptors() : nullptr;
|
||||
bool descriptors_owner_died =
|
||||
@ -2590,7 +2550,7 @@ bool MarkCompactCollector::CompactTransitionArray(
|
||||
for (int i = 0; i < num_transitions; ++i) {
|
||||
Map* target = transitions->GetTarget(i);
|
||||
DCHECK_EQ(target->constructor_or_backpointer(), map);
|
||||
if (Marking::IsWhite(Marking::MarkBitFrom(target))) {
|
||||
if (Marking::IsWhite(ObjectMarking::MarkBitFrom(target))) {
|
||||
if (descriptors != nullptr &&
|
||||
target->instance_descriptors() == descriptors) {
|
||||
descriptors_owner_died = true;
|
||||
@ -2767,7 +2727,7 @@ void MarkCompactCollector::ClearWeakCells(Object** non_live_map_list,
|
||||
if (cell_value->IsHeapObject() &&
|
||||
MarkCompactCollector::IsMarked(HeapObject::cast(cell_value))) {
|
||||
// Resurrect the cell.
|
||||
MarkBit mark = Marking::MarkBitFrom(value);
|
||||
MarkBit mark = ObjectMarking::MarkBitFrom(value);
|
||||
SetMark(value, mark);
|
||||
Object** slot = HeapObject::RawField(value, Cell::kValueOffset);
|
||||
RecordSlot(value, slot, *slot);
|
||||
@ -3002,7 +2962,7 @@ bool MarkCompactCollector::IsSlotInBlackObject(MemoryChunk* p, Address slot) {
|
||||
Bitmap::kBitsPerCell * kPointerSize;
|
||||
Address address = base_address + offset * kPointerSize;
|
||||
HeapObject* object = HeapObject::FromAddress(address);
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
CHECK(object->address() < reinterpret_cast<Address>(slot));
|
||||
if ((object->address() + kPointerSize) <= slot &&
|
||||
(object->address() + object->Size()) > slot) {
|
||||
@ -3414,7 +3374,7 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
||||
LiveObjectIterator<kBlackObjects> it(p);
|
||||
HeapObject* object = NULL;
|
||||
while ((object = it.Next()) != NULL) {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
Address free_end = object->address();
|
||||
if (free_end != free_start) {
|
||||
int size = static_cast<int>(free_end - free_start);
|
||||
@ -3445,7 +3405,7 @@ int MarkCompactCollector::Sweeper::RawSweep(
|
||||
}
|
||||
|
||||
// Clear the mark bits of that page and reset live bytes count.
|
||||
Bitmap::Clear(p);
|
||||
p->ClearLiveness();
|
||||
|
||||
if (free_start != p->area_end()) {
|
||||
int size = static_cast<int>(p->area_end() - free_start);
|
||||
@ -3478,7 +3438,7 @@ void MarkCompactCollector::InvalidateCode(Code* code) {
|
||||
DCHECK(compacting_);
|
||||
|
||||
// If the object is white than no slots were recorded on it yet.
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(code);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(code);
|
||||
if (Marking::IsWhite(mark_bit)) return;
|
||||
|
||||
// Ignore all slots that might have been recorded in the body of the
|
||||
@ -3500,7 +3460,7 @@ static void VerifyAllBlackObjects(MemoryChunk* page) {
|
||||
LiveObjectIterator<kAllLiveObjects> it(page);
|
||||
HeapObject* object = NULL;
|
||||
while ((object = it.Next()) != NULL) {
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
}
|
||||
}
|
||||
#endif // VERIFY_HEAP
|
||||
@ -3515,7 +3475,7 @@ bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, Visitor* visitor,
|
||||
LiveObjectIterator<kBlackObjects> it(page);
|
||||
HeapObject* object = nullptr;
|
||||
while ((object = it.Next()) != nullptr) {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
if (!visitor->Visit(object)) {
|
||||
if (mode == kClearMarkbits) {
|
||||
page->markbits()->ClearRange(
|
||||
@ -3535,7 +3495,7 @@ bool MarkCompactCollector::VisitLiveObjects(MemoryChunk* page, Visitor* visitor,
|
||||
}
|
||||
}
|
||||
if (mode == kClearMarkbits) {
|
||||
Bitmap::Clear(page);
|
||||
page->ClearLiveness();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -3561,7 +3521,7 @@ void MarkCompactCollector::VisitLiveObjectsBody(Page* page,
|
||||
LiveObjectIterator<kBlackObjects> it(page);
|
||||
HeapObject* object = NULL;
|
||||
while ((object = it.Next()) != NULL) {
|
||||
DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
DCHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
Map* map = object->synchronized_map();
|
||||
int size = object->SizeFromMap(map);
|
||||
object->IterateBody(map->instance_type(), size, visitor);
|
||||
@ -3715,7 +3675,7 @@ class PointerUpdateJobTraits {
|
||||
// there is no forwarding information present we need to check the
|
||||
// markbits to determine liveness.
|
||||
if (Marking::IsBlack(
|
||||
Marking::MarkBitFrom(reinterpret_cast<HeapObject*>(*slot))))
|
||||
ObjectMarking::MarkBitFrom(reinterpret_cast<HeapObject*>(*slot))))
|
||||
return KEEP_SLOT;
|
||||
} else {
|
||||
DCHECK(!heap->InNewSpace(*slot));
|
||||
@ -3961,7 +3921,7 @@ void MarkCompactCollector::StartSweepSpace(PagedSpace* space) {
|
||||
// We can not sweep black pages, since all mark bits are set for these
|
||||
// pages.
|
||||
if (p->IsFlagSet(Page::BLACK_PAGE)) {
|
||||
Bitmap::Clear(p);
|
||||
p->ClearLiveness();
|
||||
p->concurrent_sweeping_state().SetValue(Page::kSweepingDone);
|
||||
p->ClearFlag(Page::BLACK_PAGE);
|
||||
// Area above the high watermark is free.
|
||||
@ -4080,7 +4040,7 @@ void MarkCompactCollector::RecordCodeTargetPatch(Address pc, Code* target) {
|
||||
Code* host =
|
||||
isolate()->inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(
|
||||
pc);
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(host);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(host);
|
||||
if (Marking::IsBlack(mark_bit)) {
|
||||
RelocInfo rinfo(isolate(), pc, RelocInfo::CODE_TARGET, 0, host);
|
||||
// The target is always in old space, we don't have to record the slot in
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <deque>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/heap/marking.h"
|
||||
#include "src/heap/spaces.h"
|
||||
#include "src/heap/store-buffer.h"
|
||||
|
||||
@ -28,7 +29,7 @@ class MarkCompactCollector;
|
||||
class MarkingVisitor;
|
||||
class RootMarkingVisitor;
|
||||
|
||||
class Marking : public AllStatic {
|
||||
class ObjectMarking : public AllStatic {
|
||||
public:
|
||||
INLINE(static MarkBit MarkBitFrom(Address addr)) {
|
||||
MemoryChunk* p = MemoryChunk::FromAddress(addr);
|
||||
@ -39,143 +40,14 @@ class Marking : public AllStatic {
|
||||
return MarkBitFrom(reinterpret_cast<Address>(obj));
|
||||
}
|
||||
|
||||
// Impossible markbits: 01
|
||||
static const char* kImpossibleBitPattern;
|
||||
INLINE(static bool IsImpossible(MarkBit mark_bit)) {
|
||||
return !mark_bit.Get() && mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// Black markbits: 11
|
||||
static const char* kBlackBitPattern;
|
||||
INLINE(static bool IsBlack(MarkBit mark_bit)) {
|
||||
return mark_bit.Get() && mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// White markbits: 00 - this is required by the mark bit clearer.
|
||||
static const char* kWhiteBitPattern;
|
||||
INLINE(static bool IsWhite(MarkBit mark_bit)) {
|
||||
DCHECK(!IsImpossible(mark_bit));
|
||||
return !mark_bit.Get();
|
||||
}
|
||||
|
||||
// Grey markbits: 10
|
||||
static const char* kGreyBitPattern;
|
||||
INLINE(static bool IsGrey(MarkBit mark_bit)) {
|
||||
return mark_bit.Get() && !mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// IsBlackOrGrey assumes that the first bit is set for black or grey
|
||||
// objects.
|
||||
INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) { return mark_bit.Get(); }
|
||||
|
||||
INLINE(static void MarkBlack(MarkBit mark_bit)) {
|
||||
mark_bit.Set();
|
||||
mark_bit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void MarkWhite(MarkBit mark_bit)) {
|
||||
mark_bit.Clear();
|
||||
mark_bit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void BlackToWhite(MarkBit markbit)) {
|
||||
DCHECK(IsBlack(markbit));
|
||||
markbit.Clear();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void GreyToWhite(MarkBit markbit)) {
|
||||
DCHECK(IsGrey(markbit));
|
||||
markbit.Clear();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void BlackToGrey(MarkBit markbit)) {
|
||||
DCHECK(IsBlack(markbit));
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void WhiteToGrey(MarkBit markbit)) {
|
||||
DCHECK(IsWhite(markbit));
|
||||
markbit.Set();
|
||||
}
|
||||
|
||||
INLINE(static void WhiteToBlack(MarkBit markbit)) {
|
||||
DCHECK(IsWhite(markbit));
|
||||
markbit.Set();
|
||||
markbit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void GreyToBlack(MarkBit markbit)) {
|
||||
DCHECK(IsGrey(markbit));
|
||||
markbit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void BlackToGrey(HeapObject* obj)) {
|
||||
BlackToGrey(MarkBitFrom(obj));
|
||||
}
|
||||
|
||||
INLINE(static void AnyToGrey(MarkBit markbit)) {
|
||||
markbit.Set();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
static void TransferMark(Heap* heap, Address old_start, Address new_start);
|
||||
|
||||
#ifdef DEBUG
|
||||
enum ObjectColor {
|
||||
BLACK_OBJECT,
|
||||
WHITE_OBJECT,
|
||||
GREY_OBJECT,
|
||||
IMPOSSIBLE_COLOR
|
||||
};
|
||||
|
||||
static const char* ColorName(ObjectColor color) {
|
||||
switch (color) {
|
||||
case BLACK_OBJECT:
|
||||
return "black";
|
||||
case WHITE_OBJECT:
|
||||
return "white";
|
||||
case GREY_OBJECT:
|
||||
return "grey";
|
||||
case IMPOSSIBLE_COLOR:
|
||||
return "impossible";
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
static ObjectColor Color(HeapObject* obj) {
|
||||
return Color(Marking::MarkBitFrom(obj));
|
||||
}
|
||||
|
||||
static ObjectColor Color(MarkBit mark_bit) {
|
||||
if (IsBlack(mark_bit)) return BLACK_OBJECT;
|
||||
if (IsWhite(mark_bit)) return WHITE_OBJECT;
|
||||
if (IsGrey(mark_bit)) return GREY_OBJECT;
|
||||
UNREACHABLE();
|
||||
return IMPOSSIBLE_COLOR;
|
||||
static Marking::ObjectColor Color(HeapObject* obj) {
|
||||
return Marking::Color(ObjectMarking::MarkBitFrom(obj));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns true if the transferred color is black.
|
||||
INLINE(static bool TransferColor(HeapObject* from, HeapObject* to)) {
|
||||
if (Page::FromAddress(to->address())->IsFlagSet(Page::BLACK_PAGE))
|
||||
return true;
|
||||
MarkBit from_mark_bit = MarkBitFrom(from);
|
||||
MarkBit to_mark_bit = MarkBitFrom(to);
|
||||
DCHECK(Marking::IsWhite(to_mark_bit));
|
||||
if (from_mark_bit.Get()) {
|
||||
to_mark_bit.Set();
|
||||
if (from_mark_bit.Next().Get()) {
|
||||
to_mark_bit.Next().Set();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Marking);
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectMarking);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
314
src/heap/marking.h
Normal file
314
src/heap/marking.h
Normal file
@ -0,0 +1,314 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_MARKING_H
|
||||
#define V8_MARKING_H
|
||||
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class MarkBit {
|
||||
public:
|
||||
typedef uint32_t CellType;
|
||||
|
||||
inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool operator==(const MarkBit& other) {
|
||||
return cell_ == other.cell_ && mask_ == other.mask_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
inline CellType* cell() { return cell_; }
|
||||
inline CellType mask() { return mask_; }
|
||||
|
||||
inline MarkBit Next() {
|
||||
CellType new_mask = mask_ << 1;
|
||||
if (new_mask == 0) {
|
||||
return MarkBit(cell_ + 1, 1);
|
||||
} else {
|
||||
return MarkBit(cell_, new_mask);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Set() { *cell_ |= mask_; }
|
||||
inline bool Get() { return (*cell_ & mask_) != 0; }
|
||||
inline void Clear() { *cell_ &= ~mask_; }
|
||||
|
||||
CellType* cell_;
|
||||
CellType mask_;
|
||||
|
||||
friend class IncrementalMarking;
|
||||
friend class Marking;
|
||||
};
|
||||
|
||||
// Bitmap is a sequence of cells each containing fixed number of bits.
|
||||
class Bitmap {
|
||||
public:
|
||||
static const uint32_t kBitsPerCell = 32;
|
||||
static const uint32_t kBitsPerCellLog2 = 5;
|
||||
static const uint32_t kBitIndexMask = kBitsPerCell - 1;
|
||||
static const uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte;
|
||||
static const uint32_t kBytesPerCellLog2 = kBitsPerCellLog2 - kBitsPerByteLog2;
|
||||
|
||||
static const size_t kLength = (1 << kPageSizeBits) >> (kPointerSizeLog2);
|
||||
|
||||
static const size_t kSize = (1 << kPageSizeBits) >>
|
||||
(kPointerSizeLog2 + kBitsPerByteLog2);
|
||||
|
||||
static int CellsForLength(int length) {
|
||||
return (length + kBitsPerCell - 1) >> kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
int CellsCount() { return CellsForLength(kLength); }
|
||||
|
||||
static int SizeFor(int cells_count) {
|
||||
return sizeof(MarkBit::CellType) * cells_count;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t IndexToCell(uint32_t index)) {
|
||||
return index >> kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
V8_INLINE static uint32_t IndexInCell(uint32_t index) {
|
||||
return index & kBitIndexMask;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t CellToIndex(uint32_t index)) {
|
||||
return index << kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t CellAlignIndex(uint32_t index)) {
|
||||
return (index + kBitIndexMask) & ~kBitIndexMask;
|
||||
}
|
||||
|
||||
INLINE(MarkBit::CellType* cells()) {
|
||||
return reinterpret_cast<MarkBit::CellType*>(this);
|
||||
}
|
||||
|
||||
INLINE(Address address()) { return reinterpret_cast<Address>(this); }
|
||||
|
||||
INLINE(static Bitmap* FromAddress(Address addr)) {
|
||||
return reinterpret_cast<Bitmap*>(addr);
|
||||
}
|
||||
|
||||
inline MarkBit MarkBitFromIndex(uint32_t index) {
|
||||
MarkBit::CellType mask = 1u << IndexInCell(index);
|
||||
MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
|
||||
return MarkBit(cell, mask);
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
for (int i = 0; i < CellsCount(); i++) cells()[i] = 0;
|
||||
}
|
||||
|
||||
void SetAllBits() {
|
||||
for (int i = 0; i < CellsCount(); i++) cells()[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
static void PrintWord(uint32_t word, uint32_t himask = 0) {
|
||||
for (uint32_t mask = 1; mask != 0; mask <<= 1) {
|
||||
if ((mask & himask) != 0) PrintF("[");
|
||||
PrintF((mask & word) ? "1" : "0");
|
||||
if ((mask & himask) != 0) PrintF("]");
|
||||
}
|
||||
}
|
||||
|
||||
class CellPrinter {
|
||||
public:
|
||||
CellPrinter() : seq_start(0), seq_type(0), seq_length(0) {}
|
||||
|
||||
void Print(uint32_t pos, uint32_t cell) {
|
||||
if (cell == seq_type) {
|
||||
seq_length++;
|
||||
return;
|
||||
}
|
||||
|
||||
Flush();
|
||||
|
||||
if (IsSeq(cell)) {
|
||||
seq_start = pos;
|
||||
seq_length = 0;
|
||||
seq_type = cell;
|
||||
return;
|
||||
}
|
||||
|
||||
PrintF("%d: ", pos);
|
||||
PrintWord(cell);
|
||||
PrintF("\n");
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
if (seq_length > 0) {
|
||||
PrintF("%d: %dx%d\n", seq_start, seq_type == 0 ? 0 : 1,
|
||||
seq_length * kBitsPerCell);
|
||||
seq_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSeq(uint32_t cell) { return cell == 0 || cell == 0xFFFFFFFF; }
|
||||
|
||||
private:
|
||||
uint32_t seq_start;
|
||||
uint32_t seq_type;
|
||||
uint32_t seq_length;
|
||||
};
|
||||
|
||||
void Print() {
|
||||
CellPrinter printer;
|
||||
for (int i = 0; i < CellsCount(); i++) {
|
||||
printer.Print(i, cells()[i]);
|
||||
}
|
||||
printer.Flush();
|
||||
PrintF("\n");
|
||||
}
|
||||
|
||||
bool IsClean() {
|
||||
for (int i = 0; i < CellsCount(); i++) {
|
||||
if (cells()[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clears all bits starting from {cell_base_index} up to and excluding
|
||||
// {index}. Note that {cell_base_index} is required to be cell aligned.
|
||||
void ClearRange(uint32_t cell_base_index, uint32_t index) {
|
||||
DCHECK_EQ(IndexInCell(cell_base_index), 0u);
|
||||
DCHECK_GE(index, cell_base_index);
|
||||
uint32_t start_cell_index = IndexToCell(cell_base_index);
|
||||
uint32_t end_cell_index = IndexToCell(index);
|
||||
DCHECK_GE(end_cell_index, start_cell_index);
|
||||
// Clear all cells till the cell containing the last index.
|
||||
for (uint32_t i = start_cell_index; i < end_cell_index; i++) {
|
||||
cells()[i] = 0;
|
||||
}
|
||||
// Clear all bits in the last cell till the last bit before index.
|
||||
uint32_t clear_mask = ~((1u << IndexInCell(index)) - 1);
|
||||
cells()[end_cell_index] &= clear_mask;
|
||||
}
|
||||
};
|
||||
|
||||
class Marking : public AllStatic {
|
||||
public:
|
||||
// Impossible markbits: 01
|
||||
static const char* kImpossibleBitPattern;
|
||||
INLINE(static bool IsImpossible(MarkBit mark_bit)) {
|
||||
return !mark_bit.Get() && mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// Black markbits: 11
|
||||
static const char* kBlackBitPattern;
|
||||
INLINE(static bool IsBlack(MarkBit mark_bit)) {
|
||||
return mark_bit.Get() && mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// White markbits: 00 - this is required by the mark bit clearer.
|
||||
static const char* kWhiteBitPattern;
|
||||
INLINE(static bool IsWhite(MarkBit mark_bit)) {
|
||||
DCHECK(!IsImpossible(mark_bit));
|
||||
return !mark_bit.Get();
|
||||
}
|
||||
|
||||
// Grey markbits: 10
|
||||
static const char* kGreyBitPattern;
|
||||
INLINE(static bool IsGrey(MarkBit mark_bit)) {
|
||||
return mark_bit.Get() && !mark_bit.Next().Get();
|
||||
}
|
||||
|
||||
// IsBlackOrGrey assumes that the first bit is set for black or grey
|
||||
// objects.
|
||||
INLINE(static bool IsBlackOrGrey(MarkBit mark_bit)) { return mark_bit.Get(); }
|
||||
|
||||
INLINE(static void MarkBlack(MarkBit mark_bit)) {
|
||||
mark_bit.Set();
|
||||
mark_bit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void MarkWhite(MarkBit mark_bit)) {
|
||||
mark_bit.Clear();
|
||||
mark_bit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void BlackToWhite(MarkBit markbit)) {
|
||||
DCHECK(IsBlack(markbit));
|
||||
markbit.Clear();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void GreyToWhite(MarkBit markbit)) {
|
||||
DCHECK(IsGrey(markbit));
|
||||
markbit.Clear();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void BlackToGrey(MarkBit markbit)) {
|
||||
DCHECK(IsBlack(markbit));
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
INLINE(static void WhiteToGrey(MarkBit markbit)) {
|
||||
DCHECK(IsWhite(markbit));
|
||||
markbit.Set();
|
||||
}
|
||||
|
||||
INLINE(static void WhiteToBlack(MarkBit markbit)) {
|
||||
DCHECK(IsWhite(markbit));
|
||||
markbit.Set();
|
||||
markbit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void GreyToBlack(MarkBit markbit)) {
|
||||
DCHECK(IsGrey(markbit));
|
||||
markbit.Next().Set();
|
||||
}
|
||||
|
||||
INLINE(static void AnyToGrey(MarkBit markbit)) {
|
||||
markbit.Set();
|
||||
markbit.Next().Clear();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
enum ObjectColor {
|
||||
BLACK_OBJECT,
|
||||
WHITE_OBJECT,
|
||||
GREY_OBJECT,
|
||||
IMPOSSIBLE_COLOR
|
||||
};
|
||||
|
||||
static const char* ColorName(ObjectColor color) {
|
||||
switch (color) {
|
||||
case BLACK_OBJECT:
|
||||
return "black";
|
||||
case WHITE_OBJECT:
|
||||
return "white";
|
||||
case GREY_OBJECT:
|
||||
return "grey";
|
||||
case IMPOSSIBLE_COLOR:
|
||||
return "impossible";
|
||||
}
|
||||
return "error";
|
||||
}
|
||||
|
||||
static ObjectColor Color(MarkBit mark_bit) {
|
||||
if (IsBlack(mark_bit)) return BLACK_OBJECT;
|
||||
if (IsWhite(mark_bit)) return WHITE_OBJECT;
|
||||
if (IsGrey(mark_bit)) return GREY_OBJECT;
|
||||
UNREACHABLE();
|
||||
return IMPOSSIBLE_COLOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Marking);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_MARKING_H_
|
@ -570,7 +570,7 @@ bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(Heap* heap,
|
||||
|
||||
// Code is either on stack, in compilation cache or referenced
|
||||
// by optimized version of function.
|
||||
MarkBit code_mark = Marking::MarkBitFrom(function->code());
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(function->code());
|
||||
if (Marking::IsBlackOrGrey(code_mark)) {
|
||||
return false;
|
||||
}
|
||||
@ -594,7 +594,7 @@ bool StaticMarkingVisitor<StaticVisitor>::IsFlushable(
|
||||
Heap* heap, SharedFunctionInfo* shared_info) {
|
||||
// Code is either on stack, in compilation cache or referenced
|
||||
// by optimized version of function.
|
||||
MarkBit code_mark = Marking::MarkBitFrom(shared_info->code());
|
||||
MarkBit code_mark = ObjectMarking::MarkBitFrom(shared_info->code());
|
||||
if (Marking::IsBlackOrGrey(code_mark)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ void RememberedSet<direction>::ClearInvalidSlots(Heap* heap) {
|
||||
if (slots != nullptr) {
|
||||
slots->Iterate(
|
||||
[heap, chunk](SlotType type, Address host_addr, Address addr) {
|
||||
if (Marking::IsBlack(Marking::MarkBitFrom(host_addr))) {
|
||||
if (Marking::IsBlack(ObjectMarking::MarkBitFrom(host_addr))) {
|
||||
return KEEP_SLOT;
|
||||
} else {
|
||||
return REMOVE_SLOT;
|
||||
@ -88,7 +88,7 @@ bool RememberedSet<direction>::IsValidSlot(Heap* heap, MemoryChunk* chunk,
|
||||
HeapObject* heap_object = HeapObject::cast(object);
|
||||
// If the target object is not black, the source slot must be part
|
||||
// of a non-black (dead) object.
|
||||
return Marking::IsBlack(Marking::MarkBitFrom(heap_object)) &&
|
||||
return Marking::IsBlack(ObjectMarking::MarkBitFrom(heap_object)) &&
|
||||
heap->mark_compact_collector()->IsSlotInBlackObject(
|
||||
chunk, reinterpret_cast<Address>(slot));
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ class ScavengingVisitor : public StaticVisitorBase {
|
||||
}
|
||||
|
||||
if (marks_handling == TRANSFER_MARKS) {
|
||||
if (Marking::TransferColor(source, target)) {
|
||||
if (IncrementalMarking::TransferColor(source, target)) {
|
||||
MemoryChunk::IncrementLiveBytesFromGC(target, size);
|
||||
}
|
||||
}
|
||||
@ -191,7 +191,7 @@ class ScavengingVisitor : public StaticVisitorBase {
|
||||
if (object_contents == POINTER_OBJECT) {
|
||||
heap->promotion_queue()->insert(
|
||||
target, object_size,
|
||||
Marking::IsBlack(Marking::MarkBitFrom(object)));
|
||||
Marking::IsBlack(ObjectMarking::MarkBitFrom(object)));
|
||||
}
|
||||
heap->IncrementPromotedObjectsSize(object_size);
|
||||
return true;
|
||||
@ -238,7 +238,7 @@ class ScavengingVisitor : public StaticVisitorBase {
|
||||
DCHECK(map_word.IsForwardingAddress());
|
||||
HeapObject* target = map_word.ToForwardingAddress();
|
||||
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(target);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(target);
|
||||
if (Marking::IsBlack(mark_bit)) {
|
||||
// This object is black and it might not be rescanned by marker.
|
||||
// We should explicitly record code entry slot for compaction because
|
||||
|
@ -34,21 +34,6 @@ NewSpacePageRange::NewSpacePageRange(Address start, Address limit)
|
||||
SemiSpace::AssertValidRange(start, limit);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Bitmap
|
||||
|
||||
void Bitmap::Clear(MemoryChunk* chunk) {
|
||||
Bitmap* bitmap = chunk->markbits();
|
||||
for (int i = 0; i < bitmap->CellsCount(); i++) bitmap->cells()[i] = 0;
|
||||
chunk->ResetLiveBytes();
|
||||
}
|
||||
|
||||
void Bitmap::SetAllBits(MemoryChunk* chunk) {
|
||||
Bitmap* bitmap = chunk->markbits();
|
||||
for (int i = 0; i < bitmap->CellsCount(); i++)
|
||||
bitmap->cells()[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// SemiSpaceIterator
|
||||
|
@ -500,7 +500,7 @@ MemoryChunk* MemoryChunk::Initialize(Heap* heap, Address base, size_t size,
|
||||
chunk->available_in_free_list_ = 0;
|
||||
chunk->wasted_memory_ = 0;
|
||||
chunk->ResetLiveBytes();
|
||||
Bitmap::Clear(chunk);
|
||||
chunk->ClearLiveness();
|
||||
chunk->set_next_chunk(nullptr);
|
||||
chunk->set_prev_chunk(nullptr);
|
||||
chunk->local_tracker_ = nullptr;
|
||||
@ -1060,6 +1060,11 @@ void MemoryChunk::ReleaseLocalTracker() {
|
||||
local_tracker_ = nullptr;
|
||||
}
|
||||
|
||||
void MemoryChunk::ClearLiveness() {
|
||||
markbits()->Clear();
|
||||
ResetLiveBytes();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// PagedSpace implementation
|
||||
|
||||
@ -1228,7 +1233,7 @@ bool PagedSpace::Expand() {
|
||||
// black.
|
||||
if (heap()->incremental_marking()->black_allocation() &&
|
||||
identity() == OLD_SPACE) {
|
||||
Bitmap::SetAllBits(p);
|
||||
p->markbits()->SetAllBits();
|
||||
p->SetFlag(Page::BLACK_PAGE);
|
||||
if (FLAG_trace_incremental_marking) {
|
||||
PrintIsolate(heap()->isolate(), "Added black page %p\n",
|
||||
@ -1327,7 +1332,7 @@ void PagedSpace::Verify(ObjectVisitor* visitor) {
|
||||
int size = object->Size();
|
||||
object->IterateBody(map->instance_type(), size, visitor);
|
||||
if (!page->IsFlagSet(Page::BLACK_PAGE) &&
|
||||
Marking::IsBlack(Marking::MarkBitFrom(object))) {
|
||||
Marking::IsBlack(ObjectMarking::MarkBitFrom(object))) {
|
||||
black_size += size;
|
||||
}
|
||||
|
||||
@ -1462,7 +1467,7 @@ bool SemiSpace::EnsureCurrentCapacity() {
|
||||
if (current_page == nullptr) return false;
|
||||
DCHECK_NOT_NULL(current_page);
|
||||
current_page->InsertAfter(anchor());
|
||||
Bitmap::Clear(current_page);
|
||||
current_page->ClearLiveness();
|
||||
current_page->SetFlags(anchor()->prev_page()->GetFlags(),
|
||||
Page::kCopyAllFlags);
|
||||
heap()->CreateFillerObjectAt(current_page->area_start(),
|
||||
@ -1530,7 +1535,7 @@ void NewSpace::ResetAllocationInfo() {
|
||||
UpdateAllocationInfo();
|
||||
// Clear all mark-bits in the to-space.
|
||||
for (Page* p : to_space_) {
|
||||
Bitmap::Clear(p);
|
||||
p->ClearLiveness();
|
||||
}
|
||||
InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0);
|
||||
}
|
||||
@ -1828,7 +1833,7 @@ bool SemiSpace::GrowTo(int new_capacity) {
|
||||
return false;
|
||||
}
|
||||
new_page->InsertAfter(last_page);
|
||||
Bitmap::Clear(new_page);
|
||||
new_page->ClearLiveness();
|
||||
// Duplicate the flags that was set on the old page.
|
||||
new_page->SetFlags(last_page->GetFlags(), Page::kCopyOnFlipFlagsMask);
|
||||
last_page = new_page;
|
||||
@ -2909,7 +2914,7 @@ void LargeObjectSpace::ClearMarkingStateOfLiveObjects() {
|
||||
LargePage* current = first_page_;
|
||||
while (current != NULL) {
|
||||
HeapObject* object = current->GetObject();
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
|
||||
DCHECK(Marking::IsBlack(mark_bit));
|
||||
Marking::BlackToWhite(mark_bit);
|
||||
Page::FromAddress(object->address())->ResetProgressBar();
|
||||
@ -2953,7 +2958,7 @@ void LargeObjectSpace::FreeUnmarkedObjects() {
|
||||
LargePage* current = first_page_;
|
||||
while (current != NULL) {
|
||||
HeapObject* object = current->GetObject();
|
||||
MarkBit mark_bit = Marking::MarkBitFrom(object);
|
||||
MarkBit mark_bit = ObjectMarking::MarkBitFrom(object);
|
||||
DCHECK(!Marking::IsGrey(mark_bit));
|
||||
if (Marking::IsBlack(mark_bit)) {
|
||||
Address free_start;
|
||||
@ -3085,7 +3090,7 @@ void Page::Print() {
|
||||
unsigned mark_size = 0;
|
||||
for (HeapObject* object = objects.Next(); object != NULL;
|
||||
object = objects.Next()) {
|
||||
bool is_marked = Marking::IsBlackOrGrey(Marking::MarkBitFrom(object));
|
||||
bool is_marked = Marking::IsBlackOrGrey(ObjectMarking::MarkBitFrom(object));
|
||||
PrintF(" %c ", (is_marked ? '!' : ' ')); // Indent a little.
|
||||
if (is_marked) {
|
||||
mark_size += object->Size();
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "src/base/hashmap.h"
|
||||
#include "src/base/platform/mutex.h"
|
||||
#include "src/flags.h"
|
||||
#include "src/heap/marking.h"
|
||||
#include "src/list.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/utils.h"
|
||||
@ -110,187 +111,6 @@ class Space;
|
||||
#define DCHECK_PAGE_OFFSET(offset) \
|
||||
DCHECK((Page::kObjectStartOffset <= offset) && (offset <= Page::kPageSize))
|
||||
|
||||
class MarkBit {
|
||||
public:
|
||||
typedef uint32_t CellType;
|
||||
|
||||
inline MarkBit(CellType* cell, CellType mask) : cell_(cell), mask_(mask) {}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool operator==(const MarkBit& other) {
|
||||
return cell_ == other.cell_ && mask_ == other.mask_;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
inline CellType* cell() { return cell_; }
|
||||
inline CellType mask() { return mask_; }
|
||||
|
||||
inline MarkBit Next() {
|
||||
CellType new_mask = mask_ << 1;
|
||||
if (new_mask == 0) {
|
||||
return MarkBit(cell_ + 1, 1);
|
||||
} else {
|
||||
return MarkBit(cell_, new_mask);
|
||||
}
|
||||
}
|
||||
|
||||
inline void Set() { *cell_ |= mask_; }
|
||||
inline bool Get() { return (*cell_ & mask_) != 0; }
|
||||
inline void Clear() { *cell_ &= ~mask_; }
|
||||
|
||||
CellType* cell_;
|
||||
CellType mask_;
|
||||
|
||||
friend class Marking;
|
||||
};
|
||||
|
||||
|
||||
// Bitmap is a sequence of cells each containing fixed number of bits.
|
||||
class Bitmap {
|
||||
public:
|
||||
static const uint32_t kBitsPerCell = 32;
|
||||
static const uint32_t kBitsPerCellLog2 = 5;
|
||||
static const uint32_t kBitIndexMask = kBitsPerCell - 1;
|
||||
static const uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte;
|
||||
static const uint32_t kBytesPerCellLog2 = kBitsPerCellLog2 - kBitsPerByteLog2;
|
||||
|
||||
static const size_t kLength = (1 << kPageSizeBits) >> (kPointerSizeLog2);
|
||||
|
||||
static const size_t kSize =
|
||||
(1 << kPageSizeBits) >> (kPointerSizeLog2 + kBitsPerByteLog2);
|
||||
|
||||
|
||||
static int CellsForLength(int length) {
|
||||
return (length + kBitsPerCell - 1) >> kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
int CellsCount() { return CellsForLength(kLength); }
|
||||
|
||||
static int SizeFor(int cells_count) {
|
||||
return sizeof(MarkBit::CellType) * cells_count;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t IndexToCell(uint32_t index)) {
|
||||
return index >> kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
V8_INLINE static uint32_t IndexInCell(uint32_t index) {
|
||||
return index & kBitIndexMask;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t CellToIndex(uint32_t index)) {
|
||||
return index << kBitsPerCellLog2;
|
||||
}
|
||||
|
||||
INLINE(static uint32_t CellAlignIndex(uint32_t index)) {
|
||||
return (index + kBitIndexMask) & ~kBitIndexMask;
|
||||
}
|
||||
|
||||
INLINE(MarkBit::CellType* cells()) {
|
||||
return reinterpret_cast<MarkBit::CellType*>(this);
|
||||
}
|
||||
|
||||
INLINE(Address address()) { return reinterpret_cast<Address>(this); }
|
||||
|
||||
INLINE(static Bitmap* FromAddress(Address addr)) {
|
||||
return reinterpret_cast<Bitmap*>(addr);
|
||||
}
|
||||
|
||||
inline MarkBit MarkBitFromIndex(uint32_t index) {
|
||||
MarkBit::CellType mask = 1u << IndexInCell(index);
|
||||
MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
|
||||
return MarkBit(cell, mask);
|
||||
}
|
||||
|
||||
static inline void Clear(MemoryChunk* chunk);
|
||||
|
||||
static inline void SetAllBits(MemoryChunk* chunk);
|
||||
|
||||
static void PrintWord(uint32_t word, uint32_t himask = 0) {
|
||||
for (uint32_t mask = 1; mask != 0; mask <<= 1) {
|
||||
if ((mask & himask) != 0) PrintF("[");
|
||||
PrintF((mask & word) ? "1" : "0");
|
||||
if ((mask & himask) != 0) PrintF("]");
|
||||
}
|
||||
}
|
||||
|
||||
class CellPrinter {
|
||||
public:
|
||||
CellPrinter() : seq_start(0), seq_type(0), seq_length(0) {}
|
||||
|
||||
void Print(uint32_t pos, uint32_t cell) {
|
||||
if (cell == seq_type) {
|
||||
seq_length++;
|
||||
return;
|
||||
}
|
||||
|
||||
Flush();
|
||||
|
||||
if (IsSeq(cell)) {
|
||||
seq_start = pos;
|
||||
seq_length = 0;
|
||||
seq_type = cell;
|
||||
return;
|
||||
}
|
||||
|
||||
PrintF("%d: ", pos);
|
||||
PrintWord(cell);
|
||||
PrintF("\n");
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
if (seq_length > 0) {
|
||||
PrintF("%d: %dx%d\n", seq_start, seq_type == 0 ? 0 : 1,
|
||||
seq_length * kBitsPerCell);
|
||||
seq_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSeq(uint32_t cell) { return cell == 0 || cell == 0xFFFFFFFF; }
|
||||
|
||||
private:
|
||||
uint32_t seq_start;
|
||||
uint32_t seq_type;
|
||||
uint32_t seq_length;
|
||||
};
|
||||
|
||||
void Print() {
|
||||
CellPrinter printer;
|
||||
for (int i = 0; i < CellsCount(); i++) {
|
||||
printer.Print(i, cells()[i]);
|
||||
}
|
||||
printer.Flush();
|
||||
PrintF("\n");
|
||||
}
|
||||
|
||||
bool IsClean() {
|
||||
for (int i = 0; i < CellsCount(); i++) {
|
||||
if (cells()[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clears all bits starting from {cell_base_index} up to and excluding
|
||||
// {index}. Note that {cell_base_index} is required to be cell aligned.
|
||||
void ClearRange(uint32_t cell_base_index, uint32_t index) {
|
||||
DCHECK_EQ(IndexInCell(cell_base_index), 0u);
|
||||
DCHECK_GE(index, cell_base_index);
|
||||
uint32_t start_cell_index = IndexToCell(cell_base_index);
|
||||
uint32_t end_cell_index = IndexToCell(index);
|
||||
DCHECK_GE(end_cell_index, start_cell_index);
|
||||
// Clear all cells till the cell containing the last index.
|
||||
for (uint32_t i = start_cell_index; i < end_cell_index; i++) {
|
||||
cells()[i] = 0;
|
||||
}
|
||||
// Clear all bits in the last cell till the last bit before index.
|
||||
uint32_t clear_mask = ~((1u << IndexInCell(index)) - 1);
|
||||
cells()[end_cell_index] &= clear_mask;
|
||||
}
|
||||
};
|
||||
|
||||
enum FreeListCategoryType {
|
||||
kTiniest,
|
||||
kTiny,
|
||||
@ -697,6 +517,8 @@ class MemoryChunk {
|
||||
return this->address() + (index << kPointerSizeLog2);
|
||||
}
|
||||
|
||||
void ClearLiveness();
|
||||
|
||||
void PrintMarkbits() { markbits()->Print(); }
|
||||
|
||||
void SetFlag(int flag) { flags_ |= static_cast<uintptr_t>(1) << flag; }
|
||||
|
@ -866,6 +866,7 @@
|
||||
'heap/mark-compact-inl.h',
|
||||
'heap/mark-compact.cc',
|
||||
'heap/mark-compact.h',
|
||||
'heap/marking.h',
|
||||
'heap/object-stats.cc',
|
||||
'heap/object-stats.h',
|
||||
'heap/objects-visiting-inl.h',
|
||||
|
@ -720,7 +720,7 @@ TEST(DoNotPromoteWhiteObjectsOnScavenge) {
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> white = factory->NewStringFromStaticChars("white");
|
||||
|
||||
CHECK(Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(*white))));
|
||||
CHECK(Marking::IsWhite(ObjectMarking::MarkBitFrom(HeapObject::cast(*white))));
|
||||
|
||||
heap->CollectGarbage(NEW_SPACE);
|
||||
|
||||
@ -739,7 +739,8 @@ TEST(PromoteGreyOrBlackObjectsOnScavenge) {
|
||||
IncrementalMarking* marking = heap->incremental_marking();
|
||||
marking->Stop();
|
||||
heap->StartIncrementalMarking();
|
||||
while (Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(*marked)))) {
|
||||
while (
|
||||
Marking::IsWhite(ObjectMarking::MarkBitFrom(HeapObject::cast(*marked)))) {
|
||||
marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD,
|
||||
IncrementalMarking::FORCE_MARKING,
|
||||
IncrementalMarking::DO_NOT_FORCE_COMPLETION);
|
||||
@ -2632,7 +2633,7 @@ TEST(InstanceOfStubWriteBarrier) {
|
||||
|
||||
CHECK(f->IsOptimized());
|
||||
|
||||
while (!Marking::IsBlack(Marking::MarkBitFrom(f->code())) &&
|
||||
while (!Marking::IsBlack(ObjectMarking::MarkBitFrom(f->code())) &&
|
||||
!marking->IsStopped()) {
|
||||
// Discard any pending GC requests otherwise we will get GC when we enter
|
||||
// code below.
|
||||
@ -5765,7 +5766,7 @@ TEST(Regress3631) {
|
||||
v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(result));
|
||||
Handle<JSWeakCollection> weak_map(reinterpret_cast<JSWeakCollection*>(*obj));
|
||||
while (!Marking::IsBlack(
|
||||
Marking::MarkBitFrom(HeapObject::cast(weak_map->table()))) &&
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(weak_map->table()))) &&
|
||||
!marking->IsStopped()) {
|
||||
marking->Step(MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD);
|
||||
}
|
||||
@ -6680,10 +6681,10 @@ TEST(Regress598319) {
|
||||
}
|
||||
|
||||
CHECK(heap->lo_space()->Contains(arr.get()));
|
||||
CHECK(Marking::IsWhite(Marking::MarkBitFrom(arr.get())));
|
||||
CHECK(Marking::IsWhite(ObjectMarking::MarkBitFrom(arr.get())));
|
||||
for (int i = 0; i < arr.get()->length(); i++) {
|
||||
CHECK(Marking::IsWhite(
|
||||
Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
}
|
||||
|
||||
// Start incremental marking.
|
||||
@ -6697,7 +6698,7 @@ TEST(Regress598319) {
|
||||
// Check that we have not marked the interesting array during root scanning.
|
||||
for (int i = 0; i < arr.get()->length(); i++) {
|
||||
CHECK(Marking::IsWhite(
|
||||
Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
}
|
||||
|
||||
// Now we search for a state where we are in incremental marking and have
|
||||
@ -6731,7 +6732,7 @@ TEST(Regress598319) {
|
||||
// progress bar, we would fail here.
|
||||
for (int i = 0; i < arr.get()->length(); i++) {
|
||||
CHECK(Marking::IsBlack(
|
||||
Marking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
ObjectMarking::MarkBitFrom(HeapObject::cast(arr.get()->get(i)))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ TEST(DoScavengeWithIncrementalWriteBarrier) {
|
||||
// in compacting mode and |obj_value|'s page is an evacuation candidate).
|
||||
IncrementalMarking* marking = heap->incremental_marking();
|
||||
CHECK(marking->IsCompacting());
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(*obj)));
|
||||
CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
|
||||
|
||||
// Trigger GCs so that |obj| moves to old gen.
|
||||
@ -1467,8 +1467,8 @@ static void TestIncrementalWriteBarrier(Handle<Map> map, Handle<Map> new_map,
|
||||
// still active and |obj_value|'s page is indeed an evacuation candidate).
|
||||
IncrementalMarking* marking = heap->incremental_marking();
|
||||
CHECK(marking->IsMarking());
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj)));
|
||||
CHECK(Marking::IsBlack(Marking::MarkBitFrom(*obj_value)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(*obj)));
|
||||
CHECK(Marking::IsBlack(ObjectMarking::MarkBitFrom(*obj_value)));
|
||||
CHECK(MarkCompactCollector::IsOnEvacuationCandidate(*obj_value));
|
||||
|
||||
// Trigger incremental write barrier, which should add a slot to remembered
|
||||
|
114
test/unittests/heap/marking-unittest.cc
Normal file
114
test/unittests/heap/marking-unittest.cc
Normal file
@ -0,0 +1,114 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "src/globals.h"
|
||||
#include "src/heap/marking.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
TEST(Marking, MarkWhiteBlackWhite) {
|
||||
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
|
||||
calloc(Bitmap::kSize / kPointerSize, kPointerSize));
|
||||
const int kLocationsSize = 3;
|
||||
int position[kLocationsSize] = {
|
||||
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
|
||||
for (int i = 0; i < kLocationsSize; i++) {
|
||||
MarkBit mark_bit = bitmap->MarkBitFromIndex(position[i]);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::MarkBlack(mark_bit);
|
||||
CHECK(Marking::IsBlack(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::MarkWhite(mark_bit);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
}
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
TEST(Marking, TransitionWhiteBlackWhite) {
|
||||
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
|
||||
calloc(Bitmap::kSize / kPointerSize, kPointerSize));
|
||||
const int kLocationsSize = 3;
|
||||
int position[kLocationsSize] = {
|
||||
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
|
||||
for (int i = 0; i < kLocationsSize; i++) {
|
||||
MarkBit mark_bit = bitmap->MarkBitFromIndex(position[i]);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::WhiteToBlack(mark_bit);
|
||||
CHECK(Marking::IsBlack(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::BlackToWhite(mark_bit);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
}
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
TEST(Marking, TransitionAnyToGrey) {
|
||||
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
|
||||
calloc(Bitmap::kSize / kPointerSize, kPointerSize));
|
||||
const int kLocationsSize = 3;
|
||||
int position[kLocationsSize] = {
|
||||
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
|
||||
for (int i = 0; i < kLocationsSize; i++) {
|
||||
MarkBit mark_bit = bitmap->MarkBitFromIndex(position[i]);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::AnyToGrey(mark_bit);
|
||||
CHECK(Marking::IsGrey(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::MarkBlack(mark_bit);
|
||||
CHECK(Marking::IsBlack(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::AnyToGrey(mark_bit);
|
||||
CHECK(Marking::IsGrey(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::MarkWhite(mark_bit);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
}
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
TEST(Marking, TransitionWhiteGreyBlackGrey) {
|
||||
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
|
||||
calloc(Bitmap::kSize / kPointerSize, kPointerSize));
|
||||
const int kLocationsSize = 3;
|
||||
int position[kLocationsSize] = {
|
||||
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
|
||||
for (int i = 0; i < kLocationsSize; i++) {
|
||||
MarkBit mark_bit = bitmap->MarkBitFromIndex(position[i]);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::WhiteToGrey(mark_bit);
|
||||
CHECK(Marking::IsGrey(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::GreyToBlack(mark_bit);
|
||||
CHECK(Marking::IsBlack(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::BlackToGrey(mark_bit);
|
||||
CHECK(Marking::IsGrey(mark_bit));
|
||||
CHECK(Marking::IsBlackOrGrey(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
Marking::MarkWhite(mark_bit);
|
||||
CHECK(Marking::IsWhite(mark_bit));
|
||||
CHECK(!Marking::IsImpossible(mark_bit));
|
||||
}
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -99,6 +99,7 @@
|
||||
'heap/bitmap-unittest.cc',
|
||||
'heap/gc-idle-time-handler-unittest.cc',
|
||||
'heap/gc-tracer-unittest.cc',
|
||||
'heap/marking-unittest.cc',
|
||||
'heap/memory-reducer-unittest.cc',
|
||||
'heap/heap-unittest.cc',
|
||||
'heap/scavenge-job-unittest.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user