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