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

Unified Diff: src/mark-compact.cc

Issue 6713075: Create an abstraction (MarkBit) object to hold the location of the... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 9 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
===================================================================
--- src/mark-compact.cc (revision 7247)
+++ src/mark-compact.cc (working copy)
@@ -98,7 +98,7 @@
for (Object** current = start; current < end; current++) {
if ((*current)->IsHeapObject()) {
HeapObject* object = HeapObject::cast(*current);
- ASSERT(Marking::IsMarked(object));
+ ASSERT(MarkCompactCollector::IsMarked(object));
}
}
}
@@ -114,7 +114,7 @@
current < top;
current += kPointerSize) {
object = HeapObject::FromAddress(current);
- if (Marking::IsMarked(object)) {
+ if (MarkCompactCollector::IsMarked(object)) {
ASSERT(current >= next_object_must_be_here_or_later);
object->Iterate(&visitor);
next_object_must_be_here_or_later = current + object->Size();
@@ -238,23 +238,33 @@
void Marking::TransferMark(Address old_start, Address new_start) {
if (old_start == new_start) return;
+ MarkBit new_mark_bit = Marking::MarkBitFrom(new_start);
+
if (!IncrementalMarking::IsStopped()) {
- if (IncrementalMarking::IsBlack(HeapObject::FromAddress(old_start))) {
- IncrementalMarking::MarkBlack(HeapObject::FromAddress(new_start));
- ClearMark(old_start);
- } else if (IncrementalMarking::IsGrey(HeapObject::FromAddress(old_start))) {
- ClearMark(old_start + kPointerSize);
- IncrementalMarking::WhiteToGrey(HeapObject::FromAddress(new_start));
+ MarkBit old_mark_bit = Marking::MarkBitFrom(old_start);
+ if (IncrementalMarking::IsBlack(old_mark_bit)) {
+ IncrementalMarking::MarkBlack(old_mark_bit);
Vyacheslav Egorov (Chromium) 2011/03/21 17:16:30 new_mark_bit
Erik Corry 2011/03/21 20:48:53 Good catch.
+ old_mark_bit.Clear();
+ } else if (IncrementalMarking::IsGrey(old_mark_bit)) {
+ old_mark_bit.Next().Clear();
+ IncrementalMarking::WhiteToGrey(HeapObject::FromAddress(new_start),
+ new_mark_bit);
IncrementalMarking::RestartIfNotMarking();
// TODO(gc): if we shift huge array in the loop we might end up pushing
// to much to marking stack. maybe we should check one or two elements
// on top of it to see whether they are equal to old_start.
}
} else {
- if (Heap::InNewSpace(old_start) || !IsMarked(old_start)) {
+ ASSERT(IncrementalMarking::IsStopped());
+ if (Heap::InNewSpace(old_start)) {
return;
+ } else {
+ MarkBit old_mark_bit = Marking::MarkBitFrom(old_start);
+ if (!old_mark_bit.Get()) {
+ return;
+ }
}
- SetMark(new_start);
+ new_mark_bit.Set();
}
}
@@ -302,11 +312,11 @@
}
if (IncrementalMarking::state() == IncrementalMarking::STOPPED) {
- Address new_space_top = Heap::new_space()->top();
Address new_space_bottom = Heap::new_space()->bottom();
+ uintptr_t new_space_size =
+ RoundUp(Heap::new_space()->top() - new_space_bottom, 32 * kPointerSize);
- Marking::ClearRange(new_space_bottom,
- static_cast<int>(new_space_top - new_space_bottom));
+ Marking::ClearRange(new_space_bottom, new_space_size);
ClearMarkbits();
#ifdef DEBUG
@@ -431,7 +441,8 @@
SharedFunctionInfo* shared = candidate->unchecked_shared();
Code* code = shared->unchecked_code();
- if (!Marking::IsMarked(code->address())) {
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ if (!code_mark.Get()) {
shared->set_code(lazy_compile);
candidate->set_code(lazy_compile);
} else {
@@ -455,7 +466,8 @@
SetNextCandidate(candidate, NULL);
Code* code = candidate->unchecked_code();
- if (!Marking::IsMarked(code->address())) {
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ if (!code_mark.Get()) {
candidate->set_code(lazy_compile);
}
@@ -650,7 +662,8 @@
// Please note targets for cleared inline cached do not have to be
// marked since they are contained in Heap::non_monomorphic_cache().
} else {
- MarkCompactCollector::MarkObject(code);
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ MarkCompactCollector::MarkObject(code, code_mark);
}
}
@@ -671,26 +684,30 @@
(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
rinfo->IsPatchedDebugBreakSlotSequence()));
HeapObject* code = Code::GetCodeFromTargetAddress(rinfo->call_address());
- MarkCompactCollector::MarkObject(code);
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ MarkCompactCollector::MarkObject(code, code_mark);
}
// Mark object pointed to by p.
INLINE(static void MarkObjectByPointer(Object** p)) {
if (!(*p)->IsHeapObject()) return;
HeapObject* object = ShortCircuitConsString(p);
- MarkCompactCollector::MarkObject(object);
+ MarkBit mark = Marking::MarkBitFrom(object);
+ MarkCompactCollector::MarkObject(object, mark);
}
// Visit an unmarked object.
static inline void VisitUnmarkedObject(HeapObject* obj) {
#ifdef DEBUG
ASSERT(Heap::Contains(obj));
- ASSERT(!Marking::IsMarked(obj->address()));
+ ASSERT(!MarkCompactCollector::IsMarked(obj));
#endif
Map* map = obj->map();
- MarkCompactCollector::SetMark(obj);
+ MarkBit mark = Marking::MarkBitFrom(obj);
+ MarkCompactCollector::SetMark(obj, mark);
// Mark the map pointer and the body.
- MarkCompactCollector::MarkObject(map);
+ MarkBit map_mark = Marking::MarkBitFrom(map);
+ MarkCompactCollector::MarkObject(map, map_mark);
IterateBody(map, obj);
}
@@ -703,9 +720,11 @@
// Visit the unmarked objects.
for (Object** p = start; p < end; p++) {
- if (!(*p)->IsHeapObject()) continue;
- HeapObject* obj = HeapObject::cast(*p);
- if (Marking::IsMarked(obj)) continue;
+ Object* o = *p;
+ if (!o->IsHeapObject()) continue;
+ HeapObject* obj = HeapObject::cast(o);
+ MarkBit mark = Marking::MarkBitFrom(obj);
+ if (mark.Get()) continue;
VisitUnmarkedObject(obj);
}
return true;
@@ -766,7 +785,8 @@
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
- if (Marking::IsMarked(function->unchecked_code())) {
+ MarkBit code_mark = Marking::MarkBitFrom(function->unchecked_code());
+ if (code_mark.Get()) {
shared_info->set_code_age(0);
return false;
}
@@ -782,7 +802,8 @@
inline static bool IsFlushable(SharedFunctionInfo* shared_info) {
// Code is either on stack, in compilation cache or referenced
// by optimized version of function.
- if (Marking::IsMarked(shared_info->unchecked_code())) {
+ MarkBit code_mark = Marking::MarkBitFrom(shared_info->unchecked_code());
+ if (code_mark.Get()) {
shared_info->set_code_age(0);
return false;
}
@@ -916,8 +937,9 @@
}
if (!flush_code_candidate) {
- MarkCompactCollector::MarkObject(
- jsfunction->unchecked_shared()->unchecked_code());
+ Code* code = jsfunction->unchecked_shared()->unchecked_code();
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ MarkCompactCollector::MarkObject(code, code_mark);
if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) {
// For optimized functions we should retain both non-optimized version
@@ -933,8 +955,9 @@
i < count;
i++) {
JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i));
- MarkCompactCollector::MarkObject(
- inlined->unchecked_shared()->unchecked_code());
+ Code* inlined_code = inlined->unchecked_shared()->unchecked_code();
Vyacheslav Egorov (Chromium) 2011/03/21 17:16:30 I think we will need to kill all unchecked_* gette
Erik Corry 2011/03/21 20:48:53 Done.
+ MarkBit inlined_code_mark = Marking::MarkBitFrom(inlined_code);
+ MarkCompactCollector::MarkObject(inlined_code, inlined_code_mark);
}
}
}
@@ -970,10 +993,12 @@
// Visit shared function info to avoid double checking of it's
// flushability.
SharedFunctionInfo* shared_info = object->unchecked_shared();
- if (!Marking::IsMarked(shared_info)) {
+ MarkBit shared_info_mark = Marking::MarkBitFrom(shared_info);
+ if (!shared_info_mark.Get()) {
Map* shared_info_map = shared_info->map();
- MarkCompactCollector::SetMark(shared_info);
- MarkCompactCollector::MarkObject(shared_info_map);
+ MarkBit shared_info_map_mark = Marking::MarkBitFrom(shared_info_map);
+ MarkCompactCollector::SetMark(shared_info, shared_info_mark);
+ MarkCompactCollector::MarkObject(shared_info_map, shared_info_map_mark);
VisitSharedFunctionInfoAndFlushCodeGeneric(shared_info_map,
shared_info,
true);
@@ -1040,7 +1065,9 @@
public:
void VisitThread(ThreadLocalTop* top) {
for (StackFrameIterator it(top); !it.done(); it.Advance()) {
- MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
+ Code* code = it.frame()->unchecked_code();
+ MarkBit code_bit = Marking::MarkBitFrom(code);
+ MarkCompactCollector::MarkObject(it.frame()->unchecked_code(), code_bit);
}
}
};
@@ -1056,8 +1083,10 @@
Object* obj = *slot;
if (obj->IsSharedFunctionInfo()) {
SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj);
- MarkCompactCollector::MarkObject(shared->unchecked_code());
- MarkCompactCollector::MarkObject(shared);
+ MarkBit shared_mark = Marking::MarkBitFrom(shared);
+ MarkBit code_mark = Marking::MarkBitFrom(shared->unchecked_code());
+ MarkCompactCollector::MarkObject(shared->unchecked_code(), code_mark);
+ MarkCompactCollector::MarkObject(shared, shared_mark);
}
}
};
@@ -1079,11 +1108,15 @@
// Ensure that empty descriptor array is marked. Method MarkDescriptorArray
// relies on it being marked before any other descriptor array.
- MarkObject(Heap::raw_unchecked_empty_descriptor_array());
+ HeapObject* descriptor_array = Heap::raw_unchecked_empty_descriptor_array();
+ MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array);
+ MarkObject(descriptor_array, descriptor_array_mark);
// Make sure we are not referencing the code from the stack.
for (StackFrameIterator it; !it.done(); it.Advance()) {
- MarkObject(it.frame()->unchecked_code());
+ Code* code = it.frame()->unchecked_code();
+ MarkBit code_mark = Marking::MarkBitFrom(code);
+ MarkObject(code, code_mark);
}
// Iterate the archived stacks in all threads to check if
@@ -1116,14 +1149,16 @@
// Replace flat cons strings in place.
HeapObject* object = ShortCircuitConsString(p);
- if (Marking::IsMarked(object)) return;
+ MarkBit mark_bit = Marking::MarkBitFrom(object);
+ if (mark_bit.Get()) return;
Map* map = object->map();
// Mark the object.
- MarkCompactCollector::SetMark(object);
+ MarkCompactCollector::SetMark(object, mark_bit);
// Mark the map pointer and body, and push them on the marking stack.
- MarkCompactCollector::MarkObject(map);
+ MarkBit map_mark = Marking::MarkBitFrom(map);
+ MarkCompactCollector::MarkObject(map, map_mark);
StaticMarkingVisitor::IterateBody(map, object);
// Mark all the objects reachable from the map and body. May leave
@@ -1141,15 +1176,16 @@
virtual void VisitPointers(Object** start, Object** end) {
// Visit all HeapObject pointers in [start, end).
for (Object** p = start; p < end; p++) {
- if ((*p)->IsHeapObject() &&
- !Marking::IsMarked(HeapObject::cast(*p))) {
+ Object* o = *p;
+ if (o->IsHeapObject() &&
+ !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) {
// Check if the symbol being pruned is an external symbol. We need to
// delete the associated external data as this symbol is going away.
// Since no objects have yet been moved we can safely access the map of
// the object.
- if ((*p)->IsExternalString()) {
- Heap::FinalizeExternalString(String::cast(*p));
+ if (o->IsExternalString()) {
+ Heap::FinalizeExternalString(String::cast(o));
}
// Set the entry to null_value (as deleted).
*p = Heap::raw_unchecked_null_value();
@@ -1171,7 +1207,7 @@
class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
public:
virtual Object* RetainAs(Object* object) {
- if (Marking::IsMarked(HeapObject::cast(object))) {
+ if (Marking::MarkBitFrom(HeapObject::cast(object)).Get()) {
return object;
} else {
return NULL;
@@ -1181,7 +1217,7 @@
void MarkCompactCollector::ProcessNewlyMarkedObject(HeapObject* object) {
- ASSERT(Marking::IsMarked(object));
+ ASSERT(IsMarked(object));
ASSERT(Heap::Contains(object));
if (object->IsMap()) {
Map* map = Map::cast(object);
@@ -1219,18 +1255,20 @@
void MarkCompactCollector::MarkDescriptorArray(
DescriptorArray* descriptors) {
- if (Marking::IsMarked(descriptors)) return;
+ MarkBit descriptors_mark = Marking::MarkBitFrom(descriptors);
+ if (descriptors_mark.Get()) return;
// Empty descriptor array is marked as a root before any maps are marked.
ASSERT(descriptors != Heap::raw_unchecked_empty_descriptor_array());
- SetMark(descriptors);
+ SetMark(descriptors, descriptors_mark);
FixedArray* contents = reinterpret_cast<FixedArray*>(
descriptors->get(DescriptorArray::kContentArrayIndex));
ASSERT(contents->IsHeapObject());
- ASSERT(!Marking::IsMarked(contents));
+ ASSERT(!IsMarked(contents));
ASSERT(contents->IsFixedArray());
ASSERT(contents->length() >= 2);
- SetMark(contents);
+ MarkBit contents_mark = Marking::MarkBitFrom(contents);
+ SetMark(contents, contents_mark);
// Contents contains (value, details) pairs. If the details say that
// the type of descriptor is MAP_TRANSITION, CONSTANT_TRANSITION, or
// NULL_DESCRIPTOR, we don't mark the value as live. Only for
@@ -1242,9 +1280,12 @@
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() && !Marking::IsMarked(object)) {
- SetMark(object);
- marking_stack.Push(object);
+ if (object->IsHeapObject()) {
+ MarkBit mark = Marking::MarkBitFrom(HeapObject::cast(object));
+ if (!mark.Get()) {
+ SetMark(HeapObject::cast(object), mark);
+ marking_stack.Push(object);
+ }
}
}
}
@@ -1291,7 +1332,7 @@
for (HeapObject* object = it->next(); object != NULL; object = it->next()) {
if (object->IsOverflowed()) {
object->ClearOverflow();
- ASSERT(Marking::IsMarked(object));
+ ASSERT(MarkCompactCollector::IsMarked(object));
ASSERT(Heap::Contains(object));
marking_stack.Push(object);
if (marking_stack.is_full()) return;
@@ -1303,15 +1344,19 @@
bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
- return (*p)->IsHeapObject() &&
- !Marking::IsMarked(HeapObject::cast(*p));
+ Object* o = *p;
+ if (!o->IsHeapObject()) return false;
+ HeapObject* heap_object = HeapObject::cast(o);
+ MarkBit mark = Marking::MarkBitFrom(heap_object);
+ return !mark.Get();
}
void MarkCompactCollector::MarkSymbolTable() {
SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table();
// Mark the symbol table itself.
- SetMark(symbol_table);
+ MarkBit symbol_table_mark = Marking::MarkBitFrom(symbol_table);
+ SetMark(symbol_table, symbol_table_mark);
// Explicitly mark the prefix.
MarkingVisitor marker;
symbol_table->IteratePrefix(&marker);
@@ -1346,23 +1391,29 @@
bool group_marked = false;
for (int j = 0; j < objects.length(); j++) {
Object* object = *objects[j];
- if (object->IsHeapObject()
- && Marking::IsMarked(HeapObject::cast(object))) {
- group_marked = true;
- break;
+ if (object->IsHeapObject()) {
+ HeapObject* heap_object = HeapObject::cast(object);
+ MarkBit mark = Marking::MarkBitFrom(heap_object);
+ if (mark.Get()) {
+ group_marked = true;
+ break;
+ }
}
}
if (!group_marked) continue;
- // An object in the group is marked, so mark as gray all white heap
+ // An object in the group is marked, so mark as grey all white heap
// objects in the group.
for (int j = 0; j < objects.length(); ++j) {
- if ((*objects[j])->IsHeapObject()) {
- MarkObject(HeapObject::cast(*objects[j]));
+ Object* object = *objects[j];
+ if (object->IsHeapObject()) {
+ HeapObject* heap_object = HeapObject::cast(object);
+ MarkBit mark = Marking::MarkBitFrom(heap_object);
+ MarkObject(heap_object, mark);
}
}
- // Once the entire group has been colored gray, set the object group
+ // Once the entire group has been colored grey, set the object group
// to NULL so it won't be processed again.
delete object_groups->at(i);
object_groups->at(i) = NULL;
@@ -1379,13 +1430,12 @@
HeapObject* object = marking_stack.Pop();
ASSERT(object->IsHeapObject());
ASSERT(Heap::Contains(object));
- ASSERT(Marking::IsMarked(object));
+ ASSERT(IsMarked(object));
ASSERT(!object->IsOverflowed());
- // Because the object is marked, we have to recover the original map
- // pointer and use it to mark the object's body.
Map* map = object->map();
- MarkObject(map);
+ MarkBit map_mark = Marking::MarkBitFrom(map);
+ MarkObject(map, map_mark);
StaticMarkingVisitor::IterateBody(map, object);
}
@@ -1583,14 +1633,15 @@
for (HeapObject* obj = map_iterator.Next();
obj != NULL; obj = map_iterator.Next()) {
Map* map = reinterpret_cast<Map*>(obj);
- if (!Marking::IsMarked(map) && map->IsFreeSpace()) continue;
+ MarkBit map_mark = Marking::MarkBitFrom(map);
+ if (!map_mark.Get() && map->IsFreeSpace()) 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 (Marking::IsMarked(map) &&
+ if (map_mark.Get() &&
map->attached_to_shared_function_info()) {
// This map is used for inobject slack tracking and has been detached
// from SharedFunctionInfo during the mark phase.
@@ -1608,17 +1659,17 @@
// Follow back pointers, setting them to prototype,
// clearing map transitions when necessary.
- current = map;
- bool on_dead_path = !Marking::IsMarked(current);
+ bool on_dead_path = !map_mark.Get();
Object* next;
while (SafeIsMap(current)) {
next = current->prototype();
// There should never be a dead map above a live map.
- ASSERT(on_dead_path || Marking::IsMarked(current));
+ MarkBit current_mark = Marking::MarkBitFrom(current);
+ ASSERT(on_dead_path || current_mark.Get());
// 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 && Marking::IsMarked(current)) {
+ if (on_dead_path && current_mark.Get()) {
on_dead_path = false;
current->ClearNonLiveTransitions(real_prototype);
}
@@ -1793,8 +1844,10 @@
for (Address current = from_bottom; current < from_top; current += size) {
HeapObject* object = HeapObject::FromAddress(current);
- if (Marking::IsMarked(object)) {
- Marking::ClearMark(object);
+
+ MarkBit mark_bit = Marking::MarkBitFromNewSpace(object);
+ if (mark_bit.Get()) {
+ mark_bit.Clear();
MarkCompactCollector::tracer()->decrement_marked_count();
size = object->Size();
@@ -2219,8 +2272,7 @@
// spaces will not contain the free space map.
static void SweepConservatively(PagedSpace* space,
Page* p) {
- Page::MarkbitsBitmap* markbits = p->markbits();
- Page::MarkbitsBitmap::CellType* cells = markbits->cells();
+ MarkBit::CellType* cells = p->markbits()->cells();
p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
@@ -2302,8 +2354,7 @@
// over it. Map space is swept precisely, because it is not compacted.
static void SweepPrecisely(PagedSpace* space,
Page* p) {
- Page::MarkbitsBitmap* markbits = p->markbits();
- Page::MarkbitsBitmap::CellType* cells = markbits->cells();
+ MarkBit::CellType* cells = p->markbits()->cells();
p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);

Powered by Google App Engine
This is Rietveld 408576698