// Copyright 2012 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_HEAP_MARK_COMPACT_INL_H_ #define V8_HEAP_MARK_COMPACT_INL_H_ #include "src/heap/mark-compact.h" #include "src/heap/slots-buffer.h" #include "src/isolate.h" namespace v8 { namespace internal { void MarkCompactCollector::PushBlack(HeapObject* obj) { DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj))); if (marking_deque_.Push(obj)) { MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size()); } else { Marking::BlackToGrey(obj); } } void MarkCompactCollector::UnshiftBlack(HeapObject* obj) { DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj))); if (!marking_deque_.Unshift(obj)) { MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size()); Marking::BlackToGrey(obj); } } void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) { DCHECK(Marking::MarkBitFrom(obj) == mark_bit); if (Marking::IsWhite(mark_bit)) { Marking::WhiteToBlack(mark_bit); DCHECK(obj->GetIsolate()->heap()->Contains(obj)); PushBlack(obj); } } void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) { DCHECK(Marking::IsWhite(mark_bit)); DCHECK(Marking::MarkBitFrom(obj) == mark_bit); Marking::WhiteToBlack(mark_bit); MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size()); } bool MarkCompactCollector::IsMarked(Object* obj) { DCHECK(obj->IsHeapObject()); HeapObject* heap_object = HeapObject::cast(obj); return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object)); } void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot, Object* target) { Page* target_page = Page::FromAddress(reinterpret_cast
(target)); if (target_page->IsEvacuationCandidate() && !ShouldSkipEvacuationSlotRecording(object)) { if (!SlotsBuffer::AddTo(slots_buffer_allocator_, target_page->slots_buffer_address(), slot, SlotsBuffer::FAIL_ON_OVERFLOW)) { EvictPopularEvacuationCandidate(target_page); } } } void MarkCompactCollector::ForceRecordSlot(HeapObject* object, Object** slot, Object* target) { Page* target_page = Page::FromAddress(reinterpret_cast(target)); if (target_page->IsEvacuationCandidate() && !ShouldSkipEvacuationSlotRecording(object)) { CHECK(SlotsBuffer::AddTo(slots_buffer_allocator_, target_page->slots_buffer_address(), slot, SlotsBuffer::IGNORE_OVERFLOW)); } } void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) { if (GetNextCandidate(shared_info) == NULL) { SetNextCandidate(shared_info, shared_function_info_candidates_head_); shared_function_info_candidates_head_ = shared_info; } } void CodeFlusher::AddCandidate(JSFunction* function) { DCHECK(function->code() == function->shared()->code()); if (GetNextCandidate(function)->IsUndefined()) { SetNextCandidate(function, jsfunction_candidates_head_); jsfunction_candidates_head_ = function; } } JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) { return reinterpret_cast