Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Unified Diff: src/mark-compact.cc

Issue 6088012: Separate markbits from heap object map words into bitmaps. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: profiler related code reenabled Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 8b07b59bf387ce6a2b8992a0c35abf6d67296d27..a7b71280a4ae7cef65203833ee2a534ac15a5941 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -46,10 +46,8 @@ bool MarkCompactCollector::force_compaction_ = false;
bool MarkCompactCollector::compacting_collection_ = false;
bool MarkCompactCollector::compact_on_next_gc_ = false;
-int MarkCompactCollector::previous_marked_count_ = 0;
GCTracer* MarkCompactCollector::tracer_ = NULL;
-
#ifdef DEBUG
MarkCompactCollector::CollectorState MarkCompactCollector::state_ = IDLE;
@@ -66,6 +64,30 @@ int MarkCompactCollector::live_lo_objects_size_ = 0;
#endif
+Marking::NewSpaceMarkbitsBitmap* Marking::new_space_bitmap_ = NULL;
+
+
+bool Marking::Setup() {
+ if (new_space_bitmap_ == NULL) {
+ int markbits_per_newspace =
+ (2*Heap::MaxSemiSpaceSize()) >> kPointerSizeLog2;
+
+ new_space_bitmap_ =
+ BitmapStorageDescriptor::Allocate(
+ NewSpaceMarkbitsBitmap::CellsForLength(markbits_per_newspace));
+ }
+ return new_space_bitmap_ != NULL;
+}
+
+
+void Marking::TearDown() {
+ if (new_space_bitmap_ != NULL) {
+ BitmapStorageDescriptor::Free(new_space_bitmap_);
+ new_space_bitmap_ = NULL;
+ }
+}
+
+
void MarkCompactCollector::CollectGarbage() {
// Make sure that Prepare() has been called. The individual steps below will
// update the state as they proceed.
@@ -86,14 +108,33 @@ void MarkCompactCollector::CollectGarbage() {
Finish();
- // Save the count of marked objects remaining after the collection and
+ // Check that swept all marked objects and
Erik Corry 2011/01/07 12:13:21 that swept -> that we swept Also formatting is off
// null out the GC tracer.
- previous_marked_count_ = tracer_->marked_count();
- ASSERT(previous_marked_count_ == 0);
+ ASSERT(tracer_->marked_count() == 0);
tracer_ = NULL;
}
+#ifdef DEBUG
+static void VerifyMarkbitsAreClean(PagedSpace* space) {
+ PageIterator it(space, PageIterator::PAGES_IN_USE);
+
+ while (it.has_next()) {
+ Page* p = it.next();
+ ASSERT(p->markbits()->IsClean());
+ }
+}
+
+static void VerifyMarkbitsAreClean() {
+ VerifyMarkbitsAreClean(Heap::old_pointer_space());
+ VerifyMarkbitsAreClean(Heap::old_data_space());
+ VerifyMarkbitsAreClean(Heap::code_space());
+ VerifyMarkbitsAreClean(Heap::cell_space());
+ VerifyMarkbitsAreClean(Heap::map_space());
+}
+#endif
+
+
void MarkCompactCollector::Prepare(GCTracer* tracer) {
FLAG_flush_code = false;
FLAG_always_compact = false;
@@ -124,7 +165,14 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
space->PrepareForMarkCompact(compacting_collection_);
}
+ Address new_space_top = Heap::new_space()->top();
+ Address new_space_bottom = Heap::new_space()->bottom();
+ Marking::ClearRange(new_space_bottom,
+ static_cast<int>(new_space_top - new_space_bottom));
+
#ifdef DEBUG
+ VerifyMarkbitsAreClean();
+
live_bytes_ = 0;
live_young_objects_size_ = 0;
live_old_pointer_objects_size_ = 0;
@@ -241,7 +289,7 @@ class FlushCode : public AllStatic {
SharedFunctionInfo* shared = candidate->unchecked_shared();
Code* code = shared->unchecked_code();
- if (!code->IsMarked()) {
+ if (!Marking::IsMarked(code->address())) {
shared->set_code(lazy_compile);
candidate->set_code(lazy_compile);
} else {
@@ -265,7 +313,7 @@ class FlushCode : public AllStatic {
SetNextCandidate(candidate, NULL);
Code* code = candidate->unchecked_code();
- if (!code->IsMarked()) {
+ if (!Marking::IsMarked(code->address())) {
candidate->set_code(lazy_compile);
}
@@ -337,9 +385,7 @@ static inline HeapObject* ShortCircuitConsString(Object** p) {
// except the maps for the object and its possible substrings might be
// marked.
HeapObject* object = HeapObject::cast(*p);
- MapWord map_word = object->map_word();
- map_word.ClearMark();
- InstanceType type = map_word.ToMap()->instance_type();
+ InstanceType type = object->map()->instance_type();
if ((type & kShortcutTypeMask) != kShortcutTypeTag) return object;
Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
@@ -494,7 +540,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
static inline void VisitUnmarkedObject(HeapObject* obj) {
#ifdef DEBUG
ASSERT(Heap::Contains(obj));
- ASSERT(!obj->IsMarked());
+ ASSERT(!Marking::IsMarked(obj->address()));
Erik Corry 2011/01/07 12:13:21 I wonder whether the compiler can work out that th
#endif
Map* map = obj->map();
MarkCompactCollector::SetMark(obj);
@@ -514,7 +560,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
for (Object** p = start; p < end; p++) {
if (!(*p)->IsHeapObject()) continue;
HeapObject* obj = HeapObject::cast(*p);
- if (obj->IsMarked()) continue;
+ if (Marking::IsMarked(obj)) continue;
VisitUnmarkedObject(obj);
}
return true;
@@ -575,7 +621,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
- if (function->unchecked_code()->IsMarked()) {
+ if (Marking::IsMarked(function->unchecked_code())) {
shared_info->set_code_age(0);
return false;
}
@@ -591,7 +637,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
inline static bool IsFlushable(SharedFunctionInfo* shared_info) {
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
- if (shared_info->unchecked_code()->IsMarked()) {
+ if (Marking::IsMarked(shared_info->unchecked_code())) {
shared_info->set_code_age(0);
return false;
}
@@ -643,10 +689,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
static inline Map* SafeMap(Object* obj) {
Erik Corry 2011/01/07 12:13:21 Get rid of this function?
- MapWord map_word = HeapObject::cast(obj)->map_word();
- map_word.ClearMark();
- map_word.ClearOverflow();
- return map_word.ToMap();
+ return HeapObject::cast(obj)->map();
}
@@ -782,7 +825,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
// Visit shared function info to avoid double checking of it's
// flushability.
SharedFunctionInfo* shared_info = object->unchecked_shared();
- if (!shared_info->IsMarked()) {
+ if (!Marking::IsMarked(shared_info)) {
Map* shared_info_map = shared_info->map();
MarkCompactCollector::SetMark(shared_info);
MarkCompactCollector::MarkObject(shared_info_map);
@@ -928,7 +971,7 @@ class RootMarkingVisitor : public ObjectVisitor {
// Replace flat cons strings in place.
HeapObject* object = ShortCircuitConsString(p);
- if (object->IsMarked()) return;
+ if (Marking::IsMarked(object)) return;
Map* map = object->map();
// Mark the object.
@@ -953,7 +996,8 @@ class SymbolTableCleaner : public ObjectVisitor {
virtual void VisitPointers(Object** start, Object** end) {
// Visit all HeapObject pointers in [start, end).
for (Object** p = start; p < end; p++) {
- if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) {
+ if ((*p)->IsHeapObject() &&
+ !Marking::IsMarked(HeapObject::cast(*p))) {
// Check if the symbol being pruned is an external symbol. We need to
// delete the associated external data as this symbol is going away.
@@ -982,8 +1026,7 @@ class SymbolTableCleaner : public ObjectVisitor {
class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
public:
virtual Object* RetainAs(Object* object) {
- MapWord first_word = HeapObject::cast(object)->map_word();
- if (first_word.IsMarked()) {
+ if (Marking::IsMarked(HeapObject::cast(object))) {
return object;
} else {
return NULL;
@@ -992,15 +1035,14 @@ class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
};
-void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
- ASSERT(!object->IsMarked());
+void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
+ ASSERT(Marking::IsMarked(object));
ASSERT(Heap::Contains(object));
if (object->IsMap()) {
Map* map = Map::cast(object);
if (FLAG_cleanup_caches_in_maps_at_gc) {
map->ClearCodeCache();
}
- SetMark(map);
if (FLAG_collect_maps &&
map->instance_type() >= FIRST_JS_OBJECT_TYPE &&
map->instance_type() <= JS_FUNCTION_TYPE) {
@@ -1009,7 +1051,6 @@ void MarkCompactCollector::MarkUnmarkedObject(HeapObject* object) {
marking_stack.Push(map);
}
} else {
- SetMark(object);
marking_stack.Push(object);
}
}
@@ -1033,7 +1074,7 @@ void MarkCompactCollector::MarkMapContents(Map* map) {
void MarkCompactCollector::MarkDescriptorArray(
DescriptorArray* descriptors) {
- if (descriptors->IsMarked()) return;
+ if (Marking::IsMarked(descriptors)) return;
// Empty descriptor array is marked as a root before any maps are marked.
ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array());
SetMark(descriptors);
@@ -1041,7 +1082,7 @@ void MarkCompactCollector::MarkDescriptorArray(
FixedArray* contents = reinterpret_cast<FixedArray*>(
descriptors->get(DescriptorArray::kContentArrayIndex));
ASSERT(contents->IsHeapObject());
- ASSERT(!contents->IsMarked());
+ ASSERT(!Marking::IsMarked(contents));
ASSERT(contents->IsFixedArray());
ASSERT(contents->length() >= 2);
SetMark(contents);
@@ -1056,7 +1097,7 @@ void MarkCompactCollector::MarkDescriptorArray(
PropertyDetails details(Smi::cast(contents->get(i + 1)));
if (details.type() < FIRST_PHANTOM_PROPERTY_TYPE) {
HeapObject* object = reinterpret_cast<HeapObject*>(contents->get(i));
- if (object->IsHeapObject() && !object->IsMarked()) {
+ if (object->IsHeapObject() && !Marking::IsMarked(object)) {
SetMark(object);
marking_stack.Push(object);
}
@@ -1088,10 +1129,7 @@ void MarkCompactCollector::CreateBackPointers() {
static int OverflowObjectSize(HeapObject* obj) {
// Recover the normal map pointer, it might be marked as live and
// overflowed.
- MapWord map_word = obj->map_word();
- map_word.ClearMark();
- map_word.ClearOverflow();
- return obj->SizeFromMap(map_word.ToMap());
+ return obj->Size();
}
@@ -1100,6 +1138,7 @@ static int OverflowObjectSize(HeapObject* obj) {
// is reached, whichever comes first.
template<class T>
static void ScanOverflowedObjects(T* it) {
+#if 0
// The caller should ensure that the marking stack is initially not full,
// so that we don't waste effort pointlessly scanning for objects.
ASSERT(!marking_stack.is_full());
@@ -1107,17 +1146,20 @@ static void ScanOverflowedObjects(T* it) {
for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
if (object->IsOverflowed()) {
object->ClearOverflow();
- ASSERT(object->IsMarked());
+ ASSERT(Marking::IsMarked(object));
ASSERT(Heap::Contains(object));
marking_stack.Push(object);
if (marking_stack.is_full()) return;
}
}
+#endif
+ UNREACHABLE();
}
bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
- return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked();
+ return (*p)->IsHeapObject() &&
+ !Marking::IsMarked(HeapObject::cast(*p));
}
@@ -1159,7 +1201,7 @@ void MarkCompactCollector::MarkObjectGroups() {
bool group_marked = false;
for (int j = 0; j < objects.length(); j++) {
Object* object = *objects[j];
- if (object->IsHeapObject() && HeapObject::cast(object)->IsMarked()) {
+ if (object->IsHeapObject() && Marking::IsMarked(HeapObject::cast(object))) {
group_marked = true;
break;
}
@@ -1191,14 +1233,12 @@ void MarkCompactCollector::EmptyMarkingStack() {
HeapObject* object = marking_stack.Pop();
ASSERT(object->IsHeapObject());
ASSERT(Heap::Contains(object));
- ASSERT(object->IsMarked());
+ ASSERT(Marking::IsMarked(object));
ASSERT(!object->IsOverflowed());
// Because the object is marked, we have to recover the original map
Erik Corry 2011/01/07 12:13:21 comment out of date
// pointer and use it to mark the object's body.
- MapWord map_word = object->map_word();
- map_word.ClearMark();
- Map* map = map_word.ToMap();
+ Map* map = object->map();
MarkObject(map);
StaticMarkingVisitor::IterateBody(map, object);
@@ -1379,9 +1419,7 @@ void MarkCompactCollector::SweepLargeObjectSpace() {
// Safe to use during marking phase only.
bool MarkCompactCollector::SafeIsMap(HeapObject* object) {
Erik Corry 2011/01/07 12:13:21 Remove or rename?
- MapWord metamap = object->map_word();
- metamap.ClearMark();
- return metamap.ToMap()->instance_type() == MAP_TYPE;
+ return object->map()->instance_type() == MAP_TYPE;
}
@@ -1400,14 +1438,15 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
for (HeapObject* obj = map_iterator.next();
obj != NULL; obj = map_iterator.next()) {
Map* map = reinterpret_cast<Map*>(obj);
- if (!map->IsMarked() && map->IsByteArray()) continue;
+ if (!Marking::IsMarked(map) && map->IsByteArray()) continue;
ASSERT(SafeIsMap(map));
// Only JSObject and subtypes have map transitions and back pointers.
if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue;
if (map->instance_type() > JS_FUNCTION_TYPE) continue;
- if (map->IsMarked() && map->attached_to_shared_function_info()) {
+ if (Marking::IsMarked(map) &&
+ map->attached_to_shared_function_info()) {
// This map is used for inobject slack tracking and has been detached
// from SharedFunctionInfo during the mark phase.
// Since it survived the GC, reattach it now.
@@ -1425,16 +1464,16 @@ void MarkCompactCollector::ClearNonLiveTransitions() {
// Follow back pointers, setting them to prototype,
// clearing map transitions when necessary.
current = map;
- bool on_dead_path = !current->IsMarked();
+ bool on_dead_path = !Marking::IsMarked(current);
Object* next;
while (SafeIsMap(current)) {
next = current->prototype();
// There should never be a dead map above a live map.
- ASSERT(on_dead_path || current->IsMarked());
+ ASSERT(on_dead_path || Marking::IsMarked(current));
// A live map above a dead map indicates a dead transition.
// This test will always be false on the first iteration.
- if (on_dead_path && current->IsMarked()) {
+ if (on_dead_path && Marking::IsMarked(current)) {
on_dead_path = false;
current->ClearNonLiveTransitions(real_prototype);
}
@@ -1583,7 +1622,7 @@ static bool TryPromoteObject(HeapObject* object, int object_size) {
}
-static void SweepNewSpace(NewSpace* space) {
+void MarkCompactCollector::SweepNewSpace(NewSpace* space) {
Heap::CheckNewSpaceExpansionCriteria();
Address from_bottom = space->bottom();
@@ -1602,8 +1641,8 @@ static void SweepNewSpace(NewSpace* space) {
for (Address current = from_bottom; current < from_top; current += size) {
HeapObject* object = HeapObject::FromAddress(current);
- if (object->IsMarked()) {
- object->ClearMark();
+ if (Marking::IsMarked(object)) {
+ Marking::ClearMark(object);
MarkCompactCollector::tracer()->decrement_marked_count();
size = object->Size();
@@ -1677,7 +1716,7 @@ static void SweepNewSpace(NewSpace* space) {
}
-static void SweepSpace(PagedSpace* space) {
+void MarkCompactCollector::SweepSpace(PagedSpace* space) {
PageIterator it(space, PageIterator::PAGES_IN_USE);
// During sweeping of paged space we are trying to find longest sequences
@@ -1713,8 +1752,8 @@ static void SweepSpace(PagedSpace* space) {
current < p->AllocationTop();
current += object->Size()) {
object = HeapObject::FromAddress(current);
- if (object->IsMarked()) {
- object->ClearMark();
+ if (Marking::IsMarked(object)) {
+ Marking::ClearMark(object);
MarkCompactCollector::tracer()->decrement_marked_count();
if (!is_previous_alive) { // Transition from free to live.
@@ -1907,9 +1946,7 @@ void MarkCompactCollector::ReportDeleteIfNeeded(HeapObject* obj) {
int MarkCompactCollector::SizeOfMarkedObject(HeapObject* obj) {
Erik Corry 2011/01/07 12:13:21 This function is not needed
- MapWord map_word = obj->map_word();
- map_word.ClearMark();
- return obj->SizeFromMap(map_word.ToMap());
+ return obj->Size();
}

Powered by Google App Engine
This is Rietveld 408576698