| Index: src/heap/mark-compact.cc
|
| diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
| index 931206ff43538020c457e9b98d18484e5ac69db2..1bbe0e11cc67a7fa923aae0509be776abaf48875 100644
|
| --- a/src/heap/mark-compact.cc
|
| +++ b/src/heap/mark-compact.cc
|
| @@ -474,9 +474,7 @@ void MarkCompactCollector::ClearMarkbits() {
|
|
|
| LargeObjectIterator it(heap_->lo_space());
|
| for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
|
| - MarkBit mark_bit = Marking::MarkBitFrom(obj);
|
| - mark_bit.Clear();
|
| - mark_bit.Next().Clear();
|
| + Marking::MarkWhite(Marking::MarkBitFrom(obj));
|
| Page::FromAddress(obj->address())->ResetProgressBar();
|
| Page::FromAddress(obj->address())->ResetLiveBytes();
|
| }
|
| @@ -563,6 +561,34 @@ void MarkCompactCollector::RefillFreeList(PagedSpace* space) {
|
| }
|
|
|
|
|
| +void Marking::SetAllMarkBitsInRange(MarkBit start, MarkBit end) {
|
| + MarkBit::CellType* start_cell = start.cell();
|
| + MarkBit::CellType* end_cell = end.cell();
|
| + MarkBit::CellType start_mask = ~(start.mask() - 1);
|
| + MarkBit::CellType end_mask = (end.mask() << 1) - 1;
|
| +
|
| + if (start_cell == end_cell) {
|
| + *start_cell |= start_mask & end_mask;
|
| + } else {
|
| + *start_cell |= start_mask;
|
| + for (MarkBit::CellType* cell = start_cell + 1; cell < end_cell; cell++) {
|
| + *cell = ~0;
|
| + }
|
| + *end_cell |= end_mask;
|
| + }
|
| +}
|
| +
|
| +
|
| +void Marking::ClearAllMarkBitsOfCellsContainedInRange(MarkBit start,
|
| + MarkBit end) {
|
| + MarkBit::CellType* start_cell = start.cell();
|
| + MarkBit::CellType* end_cell = end.cell();
|
| + for (MarkBit::CellType* cell = start_cell; cell <= end_cell; cell++) {
|
| + *cell = 0;
|
| + }
|
| +}
|
| +
|
| +
|
| void Marking::TransferMark(Address old_start, Address new_start) {
|
| // This is only used when resizing an object.
|
| DCHECK(MemoryChunk::FromAddress(old_start) ==
|
| @@ -583,14 +609,11 @@ void Marking::TransferMark(Address old_start, Address new_start) {
|
| #endif
|
|
|
| if (Marking::IsBlack(old_mark_bit)) {
|
| - old_mark_bit.Clear();
|
| - DCHECK(IsWhite(old_mark_bit));
|
| + Marking::BlackToWhite(old_mark_bit);
|
| Marking::MarkBlack(new_mark_bit);
|
| return;
|
| } else if (Marking::IsGrey(old_mark_bit)) {
|
| - old_mark_bit.Clear();
|
| - old_mark_bit.Next().Clear();
|
| - DCHECK(IsWhite(old_mark_bit));
|
| + Marking::GreyToWhite(old_mark_bit);
|
| heap_->incremental_marking()->WhiteToGreyAndPush(
|
| HeapObject::FromAddress(new_start), new_mark_bit);
|
| heap_->incremental_marking()->RestartIfNotMarking();
|
| @@ -970,7 +993,7 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
|
|
|
| Code* code = shared->code();
|
| MarkBit code_mark = Marking::MarkBitFrom(code);
|
| - if (!code_mark.Get()) {
|
| + if (Marking::IsWhite(code_mark)) {
|
| if (FLAG_trace_code_flushing && shared->is_compiled()) {
|
| PrintF("[code-flushing clears: ");
|
| shared->ShortPrint();
|
| @@ -979,6 +1002,7 @@ void CodeFlusher::ProcessJSFunctionCandidates() {
|
| shared->set_code(lazy_compile);
|
| candidate->set_code(lazy_compile);
|
| } else {
|
| + DCHECK(Marking::IsBlack(code_mark));
|
| candidate->set_code(code);
|
| }
|
|
|
| @@ -1012,7 +1036,7 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
|
|
|
| Code* code = candidate->code();
|
| MarkBit code_mark = Marking::MarkBitFrom(code);
|
| - if (!code_mark.Get()) {
|
| + if (Marking::IsWhite(code_mark)) {
|
| if (FLAG_trace_code_flushing && candidate->is_compiled()) {
|
| PrintF("[code-flushing clears: ");
|
| candidate->ShortPrint();
|
| @@ -1050,8 +1074,8 @@ void CodeFlusher::ProcessOptimizedCodeMaps() {
|
| i += SharedFunctionInfo::kEntryLength) {
|
| Code* code =
|
| Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset));
|
| - if (!Marking::MarkBitFrom(code).Get()) continue;
|
| -
|
| + if (Marking::IsWhite(Marking::MarkBitFrom(code))) continue;
|
| + DCHECK(Marking::IsBlack(Marking::MarkBitFrom(code)));
|
| // Move every slot in the entry.
|
| for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) {
|
| int dst_index = new_length++;
|
| @@ -1327,7 +1351,7 @@ class MarkCompactMarkingVisitor
|
| // Returns true if object needed marking and false otherwise.
|
| INLINE(static bool MarkObjectWithoutPush(Heap* heap, HeapObject* object)) {
|
| MarkBit mark_bit = Marking::MarkBitFrom(object);
|
| - if (!mark_bit.Get()) {
|
| + if (Marking::IsWhite(mark_bit)) {
|
| heap->mark_compact_collector()->SetMark(object, mark_bit);
|
| return true;
|
| }
|
| @@ -1378,7 +1402,7 @@ class MarkCompactMarkingVisitor
|
| collector->RecordSlot(start, p, o);
|
| HeapObject* obj = HeapObject::cast(o);
|
| MarkBit mark = Marking::MarkBitFrom(obj);
|
| - if (mark.Get()) continue;
|
| + if (Marking::IsBlackOrGrey(mark)) continue;
|
| VisitUnmarkedObject(collector, obj);
|
| }
|
| return true;
|
| @@ -1723,7 +1747,7 @@ class RootMarkingVisitor : public ObjectVisitor {
|
| // Replace flat cons strings in place.
|
| HeapObject* object = ShortCircuitConsString(p);
|
| MarkBit mark_bit = Marking::MarkBitFrom(object);
|
| - if (mark_bit.Get()) return;
|
| + if (Marking::IsBlackOrGrey(mark_bit)) return;
|
|
|
| Map* map = object->map();
|
| // Mark the object.
|
| @@ -1754,7 +1778,7 @@ class StringTableCleaner : public ObjectVisitor {
|
| for (Object** p = start; p < end; p++) {
|
| Object* o = *p;
|
| if (o->IsHeapObject() &&
|
| - !Marking::MarkBitFrom(HeapObject::cast(o)).Get()) {
|
| + Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(o)))) {
|
| if (finalize_external_strings) {
|
| DCHECK(o->IsExternalString());
|
| heap_->FinalizeExternalString(String::cast(*p));
|
| @@ -1787,7 +1811,8 @@ typedef StringTableCleaner<true> ExternalStringTableCleaner;
|
| class MarkCompactWeakObjectRetainer : public WeakObjectRetainer {
|
| public:
|
| virtual Object* RetainAs(Object* object) {
|
| - if (Marking::MarkBitFrom(HeapObject::cast(object)).Get()) {
|
| + if (Marking::IsBlackOrGrey(
|
| + Marking::MarkBitFrom(HeapObject::cast(object)))) {
|
| return object;
|
| } else if (object->IsAllocationSite() &&
|
| !(AllocationSite::cast(object)->IsZombie())) {
|
| @@ -1901,14 +1926,15 @@ int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage(
|
| offset += trailing_zeros;
|
| Address address = cell_base + offset * kPointerSize;
|
| HeapObject* object = HeapObject::FromAddress(address);
|
| + DCHECK(Marking::IsBlack(Marking::MarkBitFrom(object)));
|
|
|
| int size = object->Size();
|
| survivors_size += size;
|
|
|
| Heap::UpdateAllocationSiteFeedback(object, Heap::RECORD_SCRATCHPAD_SLOT);
|
|
|
| - offset++;
|
| - current_cell >>= 1;
|
| + offset += 2;
|
| + current_cell >>= 2;
|
|
|
| // TODO(hpayer): Refactor EvacuateObject and call this function instead.
|
| if (heap()->ShouldBePromoted(object->address(), size) &&
|
| @@ -1966,7 +1992,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) {
|
| if (!o->IsHeapObject()) return false;
|
| HeapObject* heap_object = HeapObject::cast(o);
|
| MarkBit mark = Marking::MarkBitFrom(heap_object);
|
| - return !mark.Get();
|
| + return Marking::IsWhite(mark);
|
| }
|
|
|
|
|
| @@ -1976,7 +2002,7 @@ bool MarkCompactCollector::IsUnmarkedHeapObjectWithHeap(Heap* heap,
|
| DCHECK(o->IsHeapObject());
|
| HeapObject* heap_object = HeapObject::cast(o);
|
| MarkBit mark = Marking::MarkBitFrom(heap_object);
|
| - return !mark.Get();
|
| + return Marking::IsWhite(mark);
|
| }
|
|
|
|
|
| @@ -1984,7 +2010,7 @@ void MarkCompactCollector::MarkStringTable(RootMarkingVisitor* visitor) {
|
| StringTable* string_table = heap()->string_table();
|
| // Mark the string table itself.
|
| MarkBit string_table_mark = Marking::MarkBitFrom(string_table);
|
| - if (!string_table_mark.Get()) {
|
| + if (Marking::IsWhite(string_table_mark)) {
|
| // String table could have already been marked by visiting the handles list.
|
| SetMark(string_table, string_table_mark);
|
| }
|
| @@ -2174,21 +2200,21 @@ void MarkCompactCollector::RetainMaps() {
|
| int new_age;
|
| Map* map = Map::cast(cell->value());
|
| MarkBit map_mark = Marking::MarkBitFrom(map);
|
| - if (!map_mark.Get()) {
|
| + if (Marking::IsWhite(map_mark)) {
|
| if (age == 0) {
|
| // The map has aged. Do not retain this map.
|
| continue;
|
| }
|
| Object* constructor = map->GetConstructor();
|
| - if (!constructor->IsHeapObject() ||
|
| - !Marking::MarkBitFrom(HeapObject::cast(constructor)).Get()) {
|
| + if (!constructor->IsHeapObject() || Marking::IsWhite(Marking::MarkBitFrom(
|
| + HeapObject::cast(constructor)))) {
|
| // The constructor is dead, no new objects with this map can
|
| // be created. Do not retain this map.
|
| continue;
|
| }
|
| Object* prototype = map->prototype();
|
| if (prototype->IsHeapObject() &&
|
| - !Marking::MarkBitFrom(HeapObject::cast(prototype)).Get()) {
|
| + Marking::IsWhite(Marking::MarkBitFrom(HeapObject::cast(prototype)))) {
|
| // The prototype is not marked, age the map.
|
| new_age = age - 1;
|
| } else {
|
| @@ -2402,7 +2428,7 @@ void MarkCompactCollector::ClearNonLiveReferences() {
|
| ClearNonLivePrototypeTransitions(map);
|
| ClearNonLiveMapTransitions(map, map_mark);
|
|
|
| - if (!map_mark.Get()) {
|
| + if (Marking::IsWhite(map_mark)) {
|
| have_code_to_deoptimize_ |=
|
| map->dependent_code()->MarkCodeForDeoptimization(
|
| isolate(), DependentCode::kWeakCodeGroup);
|
| @@ -2470,8 +2496,8 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
|
|
|
| // Follow back pointer, check whether we are dealing with a map transition
|
| // from a live map to a dead path and in case clear transitions of parent.
|
| - bool current_is_alive = map_mark.Get();
|
| - bool parent_is_alive = Marking::MarkBitFrom(parent).Get();
|
| + bool current_is_alive = Marking::IsBlackOrGrey(map_mark);
|
| + bool parent_is_alive = Marking::IsBlackOrGrey(Marking::MarkBitFrom(parent));
|
| if (!current_is_alive && parent_is_alive) {
|
| ClearMapTransitions(parent, map);
|
| }
|
| @@ -2481,7 +2507,7 @@ void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map,
|
| // Clear a possible back pointer in case the transition leads to a dead map.
|
| // Return true in case a back pointer has been cleared and false otherwise.
|
| bool MarkCompactCollector::ClearMapBackPointer(Map* target) {
|
| - if (Marking::MarkBitFrom(target).Get()) return false;
|
| + if (Marking::IsBlackOrGrey(Marking::MarkBitFrom(target))) return false;
|
| target->SetBackPointer(heap_->undefined_value(), SKIP_WRITE_BARRIER);
|
| return true;
|
| }
|
| @@ -3550,31 +3576,18 @@ static bool SetMarkBitsUnderInvalidatedCode(Code* code, bool value) {
|
| uint32_t end_index =
|
| MemoryChunk::FastAddressToMarkbitIndex(code_end - kPointerSize);
|
|
|
| + // TODO(hpayer): Filter out invalidated code in
|
| + // ClearInvalidSlotsBufferEntries.
|
| Bitmap* b = p->markbits();
|
|
|
| MarkBit start_mark_bit = b->MarkBitFromIndex(start_index);
|
| MarkBit end_mark_bit = b->MarkBitFromIndex(end_index);
|
|
|
| - MarkBit::CellType* start_cell = start_mark_bit.cell();
|
| - MarkBit::CellType* end_cell = end_mark_bit.cell();
|
| -
|
| if (value) {
|
| - MarkBit::CellType start_mask = ~(start_mark_bit.mask() - 1);
|
| - MarkBit::CellType end_mask = (end_mark_bit.mask() << 1) - 1;
|
| -
|
| - if (start_cell == end_cell) {
|
| - *start_cell |= start_mask & end_mask;
|
| - } else {
|
| - *start_cell |= start_mask;
|
| - for (MarkBit::CellType* cell = start_cell + 1; cell < end_cell; cell++) {
|
| - *cell = ~0;
|
| - }
|
| - *end_cell |= end_mask;
|
| - }
|
| + Marking::SetAllMarkBitsInRange(start_mark_bit, end_mark_bit);
|
| } else {
|
| - for (MarkBit::CellType* cell = start_cell; cell <= end_cell; cell++) {
|
| - *cell = 0;
|
| - }
|
| + Marking::ClearAllMarkBitsOfCellsContainedInRange(start_mark_bit,
|
| + end_mark_bit);
|
| }
|
|
|
| return true;
|
| @@ -3595,7 +3608,7 @@ static bool IsOnInvalidatedCodeObject(Address addr) {
|
| MarkBit mark_bit =
|
| p->markbits()->MarkBitFromIndex(Page::FastAddressToMarkbitIndex(addr));
|
|
|
| - return mark_bit.Get();
|
| + return Marking::IsBlackOrGrey(mark_bit);
|
| }
|
|
|
|
|
|
|