[heap] Support for minor MC marking during incremental marking part 1

First part of relanding d2c093bcaf.

BUG=chromium:651354

Change-Id: I34ebea331d482d5039626ccff48b11ad175793ee
Reviewed-on: https://chromium-review.googlesource.com/448518
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43541}
This commit is contained in:
Michael Lippautz 2017-03-02 13:53:25 +01:00 committed by Commit Bot
parent 4a80642e54
commit 12963af725
4 changed files with 91 additions and 68 deletions

View File

@ -1332,12 +1332,12 @@ void MarkCompactCollector::PrepareForCodeFlushing() {
heap()->isolate()->compilation_cache()->IterateFunctions(&visitor);
heap()->isolate()->handle_scope_implementer()->Iterate(&visitor);
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
}
// Visitor class for marking heap roots.
template <MarkCompactMode mode>
template <MarkingMode mode>
class RootMarkingVisitor : public ObjectVisitor {
public:
explicit RootMarkingVisitor(Heap* heap)
@ -1359,7 +1359,7 @@ class RootMarkingVisitor : public ObjectVisitor {
HeapObject* object = HeapObject::cast(*p);
if (mode == MarkCompactMode::YOUNG_GENERATION &&
if (mode == MarkingMode::YOUNG_GENERATION &&
!collector_->heap()->InNewSpace(object))
return;
@ -1367,15 +1367,15 @@ class RootMarkingVisitor : public ObjectVisitor {
Map* map = object->map();
// Mark the object.
ObjectMarking::WhiteToBlack(object);
ObjectMarking::WhiteToBlack<mode>(object);
switch (mode) {
case MarkCompactMode::FULL: {
case MarkingMode::FULL: {
// Mark the map pointer and body, and push them on the marking stack.
collector_->MarkObject(map);
MarkCompactMarkingVisitor::IterateBody(map, object);
} break;
case MarkCompactMode::YOUNG_GENERATION:
case MarkingMode::YOUNG_GENERATION:
StaticYoungGenerationMarkingVisitor::IterateBody(map, object);
break;
}
@ -1950,7 +1950,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
}
void MarkCompactCollector::MarkStringTable(
RootMarkingVisitor<MarkCompactMode::FULL>* visitor) {
RootMarkingVisitor<MarkingMode::FULL>* visitor) {
StringTable* string_table = heap()->string_table();
// Mark the string table itself.
if (ObjectMarking::IsWhite(string_table)) {
@ -1959,11 +1959,11 @@ void MarkCompactCollector::MarkStringTable(
}
// Explicitly mark the prefix.
string_table->IteratePrefix(visitor);
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
}
void MarkCompactCollector::MarkRoots(
RootMarkingVisitor<MarkCompactMode::FULL>* visitor) {
RootMarkingVisitor<MarkingMode::FULL>* visitor) {
// Mark the heap roots including global variables, stack variables,
// etc., and all objects reachable from them.
heap()->IterateStrongRoots(visitor, VISIT_ONLY_STRONG);
@ -1973,8 +1973,8 @@ void MarkCompactCollector::MarkRoots(
// There may be overflowed objects in the heap. Visit them now.
while (marking_deque()->overflowed()) {
RefillMarkingDeque<MarkCompactMode::FULL>();
EmptyMarkingDeque<MarkCompactMode::FULL>();
RefillMarkingDeque<MarkingMode::FULL>();
EmptyMarkingDeque<MarkingMode::FULL>();
}
}
@ -2014,7 +2014,7 @@ void MarkCompactCollector::MarkImplicitRefGroups(
// Before: the marking stack contains zero or more heap object pointers.
// After: the marking stack is empty, and all objects reachable from the
// marking stack have been marked, or are overflowed in the heap.
template <MarkCompactMode mode>
template <MarkingMode mode>
void MarkCompactCollector::EmptyMarkingDeque() {
while (!marking_deque()->IsEmpty()) {
HeapObject* object = marking_deque()->Pop();
@ -2026,11 +2026,11 @@ void MarkCompactCollector::EmptyMarkingDeque() {
Map* map = object->map();
switch (mode) {
case MarkCompactMode::FULL: {
case MarkingMode::FULL: {
MarkObject(map);
MarkCompactMarkingVisitor::IterateBody(map, object);
} break;
case MarkCompactMode::YOUNG_GENERATION: {
case MarkingMode::YOUNG_GENERATION: {
DCHECK(ObjectMarking::IsBlack(object));
StaticYoungGenerationMarkingVisitor::IterateBody(map, object);
} break;
@ -2044,7 +2044,7 @@ void MarkCompactCollector::EmptyMarkingDeque() {
// before sweeping completes. If sweeping completes, there are no remaining
// overflowed objects in the heap so the overflow flag on the markings stack
// is cleared.
template <MarkCompactMode mode>
template <MarkingMode mode>
void MarkCompactCollector::RefillMarkingDeque() {
isolate()->CountUsage(v8::Isolate::UseCounterFeature::kMarkDequeOverflow);
DCHECK(marking_deque()->overflowed());
@ -2052,7 +2052,7 @@ void MarkCompactCollector::RefillMarkingDeque() {
DiscoverGreyObjectsInNewSpace();
if (marking_deque()->IsFull()) return;
if (mode == MarkCompactMode::FULL) {
if (mode == MarkingMode::FULL) {
DiscoverGreyObjectsInSpace(heap()->old_space());
if (marking_deque()->IsFull()) return;
DiscoverGreyObjectsInSpace(heap()->code_space());
@ -2072,7 +2072,7 @@ void MarkCompactCollector::RefillMarkingDeque() {
// stack. Before: the marking stack contains zero or more heap object
// pointers. After: the marking stack is empty and there are no overflowed
// objects in the heap.
template <MarkCompactMode mode>
template <MarkingMode mode>
void MarkCompactCollector::ProcessMarkingDeque() {
EmptyMarkingDeque<mode>();
while (marking_deque()->overflowed()) {
@ -2112,7 +2112,7 @@ void MarkCompactCollector::ProcessEphemeralMarking(
}
ProcessWeakCollections();
work_to_do = !marking_deque()->IsEmpty();
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
}
CHECK(marking_deque()->IsEmpty());
CHECK_EQ(0, heap()->local_embedder_heap_tracer()->NumberOfWrappersToTrace());
@ -2129,7 +2129,7 @@ void MarkCompactCollector::ProcessTopOptimizedFrame(ObjectVisitor* visitor) {
if (!code->CanDeoptAt(it.frame()->pc())) {
Code::BodyDescriptor::IterateBody(code, visitor);
}
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
return;
}
}
@ -2313,7 +2313,7 @@ void MarkCompactCollector::MarkLiveObjectsInYoungGeneration() {
PostponeInterruptsScope postpone(isolate());
StaticYoungGenerationMarkingVisitor::Initialize(heap());
RootMarkingVisitor<MarkCompactMode::YOUNG_GENERATION> root_visitor(heap());
RootMarkingVisitor<MarkingMode::YOUNG_GENERATION> root_visitor(heap());
marking_deque()->StartUsing();
@ -2323,7 +2323,7 @@ void MarkCompactCollector::MarkLiveObjectsInYoungGeneration() {
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_ROOTS);
heap()->IterateRoots(&root_visitor, VISIT_ALL_IN_SCAVENGE);
ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
ProcessMarkingDeque<MarkingMode::YOUNG_GENERATION>();
}
{
@ -2340,20 +2340,20 @@ void MarkCompactCollector::MarkLiveObjectsInYoungGeneration() {
reinterpret_cast<Address>(addr));
});
});
ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
ProcessMarkingDeque<MarkingMode::YOUNG_GENERATION>();
}
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MINOR_MC_MARK_WEAK);
heap()->VisitEncounteredWeakCollections(&root_visitor);
ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
ProcessMarkingDeque<MarkingMode::YOUNG_GENERATION>();
}
if (is_code_flushing_enabled()) {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MINOR_MC_MARK_CODE_FLUSH_CANDIDATES);
code_flusher()->IteratePointersToFromSpace(&root_visitor);
ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
ProcessMarkingDeque<MarkingMode::YOUNG_GENERATION>();
}
{
@ -2364,7 +2364,7 @@ void MarkCompactCollector::MarkLiveObjectsInYoungGeneration() {
->global_handles()
->IterateNewSpaceWeakUnmodifiedRoots<GlobalHandles::VISIT_OTHERS>(
&root_visitor);
ProcessMarkingDeque<MarkCompactMode::YOUNG_GENERATION>();
ProcessMarkingDeque<MarkingMode::YOUNG_GENERATION>();
}
marking_deque()->StopUsing();
@ -2401,7 +2401,7 @@ void MarkCompactCollector::MarkLiveObjects() {
PrepareForCodeFlushing();
}
RootMarkingVisitor<MarkCompactMode::FULL> root_visitor(heap());
RootMarkingVisitor<MarkingMode::FULL> root_visitor(heap());
{
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_ROOTS);
@ -2433,7 +2433,7 @@ void MarkCompactCollector::MarkLiveObjects() {
GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_HANDLES);
heap()->isolate()->global_handles()->IdentifyWeakHandles(
&IsUnmarkedHeapObject);
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
}
// Then we mark the objects.
@ -2441,7 +2441,7 @@ void MarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_MARK_WEAK_CLOSURE_WEAK_ROOTS);
heap()->isolate()->global_handles()->IterateWeakRoots(&root_visitor);
ProcessMarkingDeque<MarkCompactMode::FULL>();
ProcessMarkingDeque<MarkingMode::FULL>();
}
// Repeat Harmony weak maps marking to mark unmarked objects reachable from

View File

@ -17,8 +17,6 @@
namespace v8 {
namespace internal {
enum class MarkCompactMode { FULL, YOUNG_GENERATION };
// Callback function, returns whether an object is alive. The heap size
// of the object is returned in size. It optionally updates the offset
// to the first live object in the page (only used for old and map objects).
@ -31,87 +29,103 @@ typedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object);
class CodeFlusher;
class MarkCompactCollector;
class MarkingVisitor;
template <MarkCompactMode mode>
template <MarkingMode mode>
class RootMarkingVisitor;
class ObjectMarking : public AllStatic {
public:
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static MarkBit MarkBitFrom(HeapObject* obj) {
const Address address = obj->address();
MemoryChunk* p = MemoryChunk::FromAddress(address);
return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(address));
const MemoryChunk* p = MemoryChunk::FromAddress(address);
return p->markbits<mode>()->MarkBitFromIndex(
p->AddressToMarkbitIndex(address));
}
template <MarkingMode mode = MarkingMode::FULL>
static Marking::ObjectColor Color(HeapObject* obj) {
return Marking::Color(ObjectMarking::MarkBitFrom(obj));
return Marking::Color(ObjectMarking::MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static bool IsImpossible(HeapObject* obj) {
return Marking::IsImpossible(MarkBitFrom(obj));
return Marking::IsImpossible(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static bool IsBlack(HeapObject* obj) {
return Marking::IsBlack(MarkBitFrom(obj));
return Marking::IsBlack(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static bool IsWhite(HeapObject* obj) {
return Marking::IsWhite(MarkBitFrom(obj));
return Marking::IsWhite(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static bool IsGrey(HeapObject* obj) {
return Marking::IsGrey(MarkBitFrom(obj));
return Marking::IsGrey(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static bool IsBlackOrGrey(HeapObject* obj) {
return Marking::IsBlackOrGrey(MarkBitFrom(obj));
return Marking::IsBlackOrGrey(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void ClearMarkBit(HeapObject* obj) {
Marking::MarkWhite(MarkBitFrom(obj));
Marking::MarkWhite(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void BlackToWhite(HeapObject* obj) {
DCHECK(IsBlack(obj));
MarkBit markbit = MarkBitFrom(obj);
DCHECK(IsBlack<mode>(obj));
MarkBit markbit = MarkBitFrom<mode>(obj);
Marking::BlackToWhite(markbit);
MemoryChunk::IncrementLiveBytes(obj, -obj->Size());
MemoryChunk::IncrementLiveBytes<mode>(obj, -obj->Size());
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void GreyToWhite(HeapObject* obj) {
DCHECK(IsGrey(obj));
Marking::GreyToWhite(MarkBitFrom(obj));
DCHECK(IsGrey<mode>(obj));
Marking::GreyToWhite(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void BlackToGrey(HeapObject* obj) {
DCHECK(IsBlack(obj));
MarkBit markbit = MarkBitFrom(obj);
DCHECK(IsBlack<mode>(obj));
MarkBit markbit = MarkBitFrom<mode>(obj);
Marking::BlackToGrey(markbit);
MemoryChunk::IncrementLiveBytes(obj, -obj->Size());
MemoryChunk::IncrementLiveBytes<mode>(obj, -obj->Size());
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void WhiteToGrey(HeapObject* obj) {
DCHECK(IsWhite(obj));
Marking::WhiteToGrey(MarkBitFrom(obj));
DCHECK(IsWhite<mode>(obj));
Marking::WhiteToGrey(MarkBitFrom<mode>(obj));
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void WhiteToBlack(HeapObject* obj) {
DCHECK(IsWhite(obj));
MarkBit markbit = MarkBitFrom(obj);
DCHECK(IsWhite<mode>(obj));
MarkBit markbit = MarkBitFrom<mode>(obj);
Marking::WhiteToBlack(markbit);
MemoryChunk::IncrementLiveBytes(obj, obj->Size());
MemoryChunk::IncrementLiveBytes<mode>(obj, obj->Size());
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void GreyToBlack(HeapObject* obj) {
DCHECK(IsGrey(obj));
MarkBit markbit = MarkBitFrom(obj);
DCHECK(IsGrey<mode>(obj));
MarkBit markbit = MarkBitFrom<mode>(obj);
Marking::GreyToBlack(markbit);
MemoryChunk::IncrementLiveBytes(obj, obj->Size());
MemoryChunk::IncrementLiveBytes<mode>(obj, obj->Size());
}
template <MarkingMode mode = MarkingMode::FULL>
V8_INLINE static void AnyToGrey(HeapObject* obj) {
MarkBit markbit = MarkBitFrom(obj);
MarkBit markbit = MarkBitFrom<mode>(obj);
if (Marking::IsBlack(markbit)) {
MemoryChunk::IncrementLiveBytes(obj, -obj->Size());
MemoryChunk::IncrementLiveBytes<mode>(obj, -obj->Size());
}
Marking::AnyToGrey(markbit);
}
@ -631,7 +645,7 @@ class MarkCompactCollector {
friend class MarkCompactMarkingVisitor;
friend class MarkingVisitor;
friend class RecordMigratedSlotVisitor;
template <MarkCompactMode mode>
template <MarkingMode mode>
friend class RootMarkingVisitor;
friend class SharedFunctionInfoMarkingVisitor;
friend class StaticYoungGenerationMarkingVisitor;
@ -660,15 +674,15 @@ class MarkCompactCollector {
INLINE(void MarkObject(HeapObject* obj));
// Mark the heap roots and all objects reachable from them.
void MarkRoots(RootMarkingVisitor<MarkCompactMode::FULL>* visitor);
void MarkRoots(RootMarkingVisitor<MarkingMode::FULL>* visitor);
// Mark the string table specially. References to internalized strings from
// the string table are weak.
void MarkStringTable(RootMarkingVisitor<MarkCompactMode::FULL>* visitor);
void MarkStringTable(RootMarkingVisitor<MarkingMode::FULL>* visitor);
// Mark objects reachable (transitively) from objects in the marking stack
// or overflowed in the heap.
template <MarkCompactMode mode>
template <MarkingMode mode>
void ProcessMarkingDeque();
// Mark objects reachable (transitively) from objects in the marking stack
@ -692,13 +706,13 @@ class MarkCompactCollector {
// stack. This function empties the marking stack, but may leave
// overflowed objects in the heap, in which case the marking stack's
// overflow flag will be set.
template <MarkCompactMode mode>
template <MarkingMode mode>
void EmptyMarkingDeque();
// Refill the marking stack with overflowed objects from the heap. This
// function either leaves the marking stack full or clears the overflow
// flag on the marking stack.
template <MarkCompactMode mode>
template <MarkingMode mode>
void RefillMarkingDeque();
// Helper methods for refilling the marking stack by discovering grey objects

View File

@ -226,6 +226,7 @@ void Page::InitializeFreeListCategories() {
}
}
template <MarkingMode mode>
void MemoryChunk::IncrementLiveBytes(HeapObject* object, int by) {
MemoryChunk::FromAddress(object->address())->IncrementLiveBytes(by);
}

View File

@ -224,6 +224,10 @@ class FreeListCategory {
friend class PagedSpace;
};
// MarkingMode determines which bitmaps and counters should be used when
// accessing marking information on MemoryChunk.
enum class MarkingMode { FULL, YOUNG_GENERATION };
// MemoryChunk represents a memory region owned by a specific space.
// It is divided into the header and the body. Chunk start is always
// 1MB aligned. Start of the body is aligned so it can accommodate
@ -370,6 +374,7 @@ class MemoryChunk {
static const int kAllocatableMemory = kPageSize - kObjectStartOffset;
template <MarkingMode mode = MarkingMode::FULL>
static inline void IncrementLiveBytes(HeapObject* object, int by);
// Only works if the pointer is in the first kPageSize of the MemoryChunk.
@ -395,7 +400,9 @@ class MemoryChunk {
static bool IsValid(MemoryChunk* chunk) { return chunk != nullptr; }
Address address() { return reinterpret_cast<Address>(this); }
Address address() const {
return reinterpret_cast<Address>(const_cast<MemoryChunk*>(this));
}
base::Mutex* mutex() { return mutex_; }
@ -489,15 +496,16 @@ class MemoryChunk {
}
}
inline Bitmap* markbits() {
template <MarkingMode mode = MarkingMode::FULL>
inline Bitmap* markbits() const {
return Bitmap::FromAddress(address() + kHeaderSize);
}
inline uint32_t AddressToMarkbitIndex(Address addr) {
inline uint32_t AddressToMarkbitIndex(Address addr) const {
return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2;
}
inline Address MarkbitIndexToAddress(uint32_t index) {
inline Address MarkbitIndexToAddress(uint32_t index) const {
return this->address() + (index << kPointerSizeLog2);
}