From 5547815dafba9a52f0915a9b219089ee69cb6403 Mon Sep 17 00:00:00 2001 From: "erik.corry@gmail.com" Date: Wed, 26 Sep 2012 08:55:19 +0000 Subject: [PATCH] Revert 12609 (Allow partial scanning of large arrays) due to crashes in unbox-double-arrays.js test. Review URL: https://chromiumcodereview.appspot.com/10996017 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12610 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/incremental-marking.cc | 206 +++++++++++++-------------------------------- src/mark-compact.cc | 66 --------------- src/mark-compact.h | 33 -------- src/spaces.cc | 4 +- src/spaces.h | 35 +------- 5 files changed, 65 insertions(+), 279 deletions(-) diff --git a/src/incremental-marking.cc b/src/incremental-marking.cc index 098f9e0..154799b 100644 --- a/src/incremental-marking.cc +++ b/src/incremental-marking.cc @@ -192,41 +192,6 @@ class IncrementalMarkingMarkingVisitor void>::Visit(map, object); } - static const int kScanningChunk = 32 * 1024; - - static int VisitHugeArray(FixedArray* array) { - Heap* heap = array->GetHeap(); - MemoryChunk* chunk = MemoryChunk::FromAddress(array->address()); - Object** start = array->data_start(); - int length = array->length(); - - if (chunk->owner()->identity() != LO_SPACE) { - VisitPointers(heap, start, start + length); - return length; - } - - int from = - chunk->IsPartiallyScanned() ? chunk->PartiallyScannedProgress() : 0; - int to = Min(from + kScanningChunk, length); - - VisitPointers(heap, start + from, start + to); - - if (to == length) { - // If it went from black to grey while it was waiting for the next bit to - // be scanned then we have to start the scan again. - MarkBit mark_bit = Marking::MarkBitFrom(array); - if (!Marking::IsBlack(mark_bit)) { - ASSERT(Marking::IsGrey(mark_bit)); - chunk->SetPartiallyScannedProgress(0); - } else { - chunk->SetCompletelyScanned(); - } - } else { - chunk->SetPartiallyScannedProgress(to); - } - return to - from; - } - static inline void VisitJSFunction(Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); // Iterate over all fields in the body but take care in dealing with @@ -656,8 +621,7 @@ void IncrementalMarking::UpdateMarkingDequeAfterScavenge() { #ifdef DEBUG MarkBit mark_bit = Marking::MarkBitFrom(obj); ASSERT(Marking::IsGrey(mark_bit) || - (obj->IsFiller() && Marking::IsWhite(mark_bit)) || - MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); + (obj->IsFiller() && Marking::IsWhite(mark_bit))); #endif } } @@ -680,57 +644,36 @@ void IncrementalMarking::Hurry() { // was stopped. Map* filler_map = heap_->one_pointer_filler_map(); Map* native_context_map = heap_->native_context_map(); - do { - while (!marking_deque_.IsEmpty()) { - HeapObject* obj = marking_deque_.Pop(); - - // Explicitly skip one word fillers. Incremental markbit patterns are - // correct only for objects that occupy at least two words. - Map* map = obj->map(); - if (map == filler_map) { - continue; - } else if (map == native_context_map) { - // Native contexts have weak fields. - IncrementalMarkingMarkingVisitor::VisitNativeContext(map, obj); - ASSERT(!Marking::IsBlack(Marking::MarkBitFrom(obj))); - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); - } else if (map->instance_type() == FIXED_ARRAY_TYPE && - FixedArray::cast(obj)->length() > - IncrementalMarkingMarkingVisitor::kScanningChunk) { - MarkBit map_mark_bit = Marking::MarkBitFrom(map); - if (Marking::IsWhite(map_mark_bit)) { - WhiteToGreyAndPush(map, map_mark_bit); - } - MarkBit mark_bit = Marking::MarkBitFrom(obj); - if (!Marking::IsBlack(mark_bit)) { - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); - } else { - ASSERT( - MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); - } - IncrementalMarkingMarkingVisitor::VisitHugeArray( - FixedArray::cast(obj)); - } else { - MarkBit map_mark_bit = Marking::MarkBitFrom(map); - if (Marking::IsWhite(map_mark_bit)) { - WhiteToGreyAndPush(map, map_mark_bit); - } - IncrementalMarkingMarkingVisitor::IterateBody(map, obj); - ASSERT(!Marking::IsBlack(Marking::MarkBitFrom(obj))); - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); + while (!marking_deque_.IsEmpty()) { + HeapObject* obj = marking_deque_.Pop(); + + // Explicitly skip one word fillers. Incremental markbit patterns are + // correct only for objects that occupy at least two words. + Map* map = obj->map(); + if (map == filler_map) { + continue; + } else if (map == native_context_map) { + // Native contexts have weak fields. + IncrementalMarkingMarkingVisitor::VisitNativeContext(map, obj); + } else { + MarkBit map_mark_bit = Marking::MarkBitFrom(map); + if (Marking::IsWhite(map_mark_bit)) { + WhiteToGreyAndPush(map, map_mark_bit); } - - MarkBit mark_bit = Marking::MarkBitFrom(obj); - Marking::MarkBlack(mark_bit); + IncrementalMarkingMarkingVisitor::IterateBody(map, obj); } - state_ = COMPLETE; - if (FLAG_trace_incremental_marking) { - double end = OS::TimeCurrentMillis(); - PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", - static_cast(end - start)); - } - MarkCompactCollector::ProcessLargePostponedArrays(heap_, &marking_deque_); - } while (!marking_deque_.IsEmpty()); + + MarkBit mark_bit = Marking::MarkBitFrom(obj); + ASSERT(!Marking::IsBlack(mark_bit)); + Marking::MarkBlack(mark_bit); + MemoryChunk::IncrementLiveBytesFromGC(obj->address(), obj->Size()); + } + state_ = COMPLETE; + if (FLAG_trace_incremental_marking) { + double end = OS::TimeCurrentMillis(); + PrintF("[IncrementalMarking] Complete (hurry), spent %d ms.\n", + static_cast(end - start)); + } } if (FLAG_cleanup_code_caches_at_gc) { @@ -851,71 +794,42 @@ void IncrementalMarking::Step(intptr_t allocated_bytes, } else if (state_ == MARKING) { Map* filler_map = heap_->one_pointer_filler_map(); Map* native_context_map = heap_->native_context_map(); - while (true) { - while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { - HeapObject* obj = marking_deque_.Pop(); - - // Explicitly skip one word fillers. Incremental markbit patterns are - // correct only for objects that occupy at least two words. - Map* map = obj->map(); - if (map == filler_map) continue; + while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { + HeapObject* obj = marking_deque_.Pop(); + + // Explicitly skip one word fillers. Incremental markbit patterns are + // correct only for objects that occupy at least two words. + Map* map = obj->map(); + if (map == filler_map) continue; + + int size = obj->SizeFromMap(map); + bytes_to_process -= size; + MarkBit map_mark_bit = Marking::MarkBitFrom(map); + if (Marking::IsWhite(map_mark_bit)) { + WhiteToGreyAndPush(map, map_mark_bit); + } - int size = obj->SizeFromMap(map); - MarkBit map_mark_bit = Marking::MarkBitFrom(map); - if (Marking::IsWhite(map_mark_bit)) { - WhiteToGreyAndPush(map, map_mark_bit); - } + // TODO(gc) switch to static visitor instead of normal visitor. + if (map == native_context_map) { + // Native contexts have weak fields. + Context* ctx = Context::cast(obj); - // TODO(gc) switch to static visitor instead of normal visitor. - if (map == native_context_map) { - // Native contexts have weak fields. - Context* ctx = Context::cast(obj); - - // We will mark cache black with a separate pass - // when we finish marking. - MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); - - IncrementalMarkingMarkingVisitor::VisitNativeContext(map, ctx); - bytes_to_process -= size; - SLOW_ASSERT(Marking::IsGrey(Marking::MarkBitFrom(obj))); - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); - } else if (map->instance_type() == FIXED_ARRAY_TYPE && - FixedArray::cast(obj)->length() > - IncrementalMarkingMarkingVisitor::kScanningChunk) { - SLOW_ASSERT( - Marking::IsGrey(Marking::MarkBitFrom(obj)) || - MemoryChunk::FromAddress(obj->address())->IsPartiallyScanned()); - bytes_to_process -= - IncrementalMarkingMarkingVisitor::VisitHugeArray( - FixedArray::cast(obj)); - MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); - if (!Marking::IsBlack(obj_mark_bit)) { - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); - } - } else { - IncrementalMarkingMarkingVisitor::IterateBody(map, obj); - bytes_to_process -= size; - SLOW_ASSERT( - Marking::IsGrey(Marking::MarkBitFrom(obj)) || - (obj->IsFiller() && Marking::IsWhite(Marking::MarkBitFrom(obj)))); - MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); - } + // We will mark cache black with a separate pass + // when we finish marking. + MarkObjectGreyDoNotEnqueue(ctx->normalized_map_cache()); - MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); - Marking::MarkBlack(obj_mark_bit); + IncrementalMarkingMarkingVisitor::VisitNativeContext(map, ctx); + } else { + IncrementalMarkingMarkingVisitor::IterateBody(map, obj); } - if (marking_deque_.IsEmpty()) { - MarkCompactCollector::ProcessLargePostponedArrays(heap_, - &marking_deque_); - if (marking_deque_.IsEmpty()) { - MarkingComplete(action); - break; - } - } else { - ASSERT(bytes_to_process <= 0); - break; - } + + MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); + SLOW_ASSERT(Marking::IsGrey(obj_mark_bit) || + (obj->IsFiller() && Marking::IsWhite(obj_mark_bit))); + Marking::MarkBlack(obj_mark_bit); + MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); } + if (marking_deque_.IsEmpty()) MarkingComplete(action); } allocated_ = 0; diff --git a/src/mark-compact.cc b/src/mark-compact.cc index ae22778..1fdc005 100644 --- a/src/mark-compact.cc +++ b/src/mark-compact.cc @@ -1066,30 +1066,6 @@ class MarkCompactMarkingVisitor } } - static void VisitHugeFixedArray(Heap* heap, FixedArray* array, int length); - - // The deque is contiguous and we use new space, it is therefore contained in - // one page minus the header. It also has a size that is a power of two so - // it is half the size of a page. We want to scan a number of array entries - // that is less than the number of entries in the deque, so we divide by 2 - // once more. - static const int kScanningChunk = Page::kPageSize / 4 / kPointerSize; - - INLINE(static void VisitFixedArray(Map* map, HeapObject* object)) { - FixedArray* array = FixedArray::cast(object); - int length = array->length(); - Heap* heap = map->GetHeap(); - - if (length < kScanningChunk || - MemoryChunk::FromAddress(array->address())->owner()->identity() != - LO_SPACE) { - Object** start = array->data_start(); - VisitPointers(heap, start, start + length); - } else { - VisitHugeFixedArray(heap, array, length); - } - } - // Marks the object black and pushes it on the marking stack. INLINE(static void MarkObject(Heap* heap, HeapObject* object)) { MarkBit mark = Marking::MarkBitFrom(object); @@ -1528,27 +1504,6 @@ class MarkCompactMarkingVisitor }; -void MarkCompactMarkingVisitor::VisitHugeFixedArray(Heap* heap, - FixedArray* array, - int length) { - MemoryChunk* chunk = MemoryChunk::FromAddress(array->address()); - - ASSERT(chunk->owner()->identity() == LO_SPACE); - - Object** start = array->data_start(); - int from = - chunk->IsPartiallyScanned() ? chunk->PartiallyScannedProgress() : 0; - int to = Min(from + kScanningChunk, length); - VisitPointers(heap, start + from, start + to); - - if (to == length) { - chunk->SetCompletelyScanned(); - } else { - chunk->SetPartiallyScannedProgress(to); - } -} - - void MarkCompactMarkingVisitor::ObjectStatsCountFixedArray( FixedArrayBase* fixed_array, FixedArraySubInstanceType fast_type, @@ -1690,9 +1645,6 @@ void MarkCompactMarkingVisitor::Initialize() { table_.Register(kVisitJSRegExp, &VisitRegExpAndFlushCode); - table_.Register(kVisitFixedArray, - &VisitFixedArray); - if (FLAG_track_gc_object_stats) { // Copy the visitor table to make call-through possible. non_count_table_.CopyFrom(&table_); @@ -2176,7 +2128,6 @@ void MarkCompactCollector::EmptyMarkingDeque() { MarkCompactMarkingVisitor::IterateBody(map, object); } - ProcessLargePostponedArrays(heap(), &marking_deque_); // Process encountered weak maps, mark objects only reachable by those // weak maps and repeat until fix-point is reached. @@ -2185,29 +2136,12 @@ void MarkCompactCollector::EmptyMarkingDeque() { } -void MarkCompactCollector::ProcessLargePostponedArrays(Heap* heap, - MarkingDeque* deque) { - ASSERT(deque->IsEmpty()); - LargeObjectIterator it(heap->lo_space()); - for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { - if (!obj->IsFixedArray()) continue; - MemoryChunk* p = MemoryChunk::FromAddress(obj->address()); - if (p->IsPartiallyScanned()) { - deque->PushBlack(obj); - } - } -} - - // Sweep the heap for overflowed objects, clear their overflow bits, and // push them on the marking stack. Stop early if the marking stack fills // before sweeping completes. If sweeping completes, there are no remaining // overflowed objects in the heap so the overflow flag on the markings stack // is cleared. void MarkCompactCollector::RefillMarkingDeque() { - if (FLAG_trace_gc) { - PrintPID("Marking queue overflowed\n"); - } ASSERT(marking_deque_.overflowed()); SemiSpaceIterator new_it(heap()->new_space()); diff --git a/src/mark-compact.h b/src/mark-compact.h index ac26ce8..374981c 100644 --- a/src/mark-compact.h +++ b/src/mark-compact.h @@ -240,35 +240,6 @@ class MarkingDeque { int mask() { return mask_; } void set_top(int top) { top_ = top; } - int space_left() { - // If we already overflowed we may as well just say there is lots of - // space left. - if (overflowed_) return mask_ + 1; - if (IsEmpty()) return mask_ + 1; - if (IsFull()) return 0; - return (bottom_ - top_) & mask_; - } - -#ifdef DEBUG - const char* Status() { - if (overflowed_) return "Overflowed"; - if (IsEmpty()) return "Empty"; - if (IsFull()) return "Full"; - int oct = (((top_ - bottom_) & mask_) * 8) / (mask_ + 1); - switch (oct) { - case 0: return "Almost empty"; - case 1: return "1/8 full"; - case 2: return "2/8 full"; - case 3: return "3/8 full"; - case 4: return "4/8 full"; - case 5: return "5/8 full"; - case 6: return "6/8 full"; - case 7: return "7/8 full"; - } - return "??"; - } -#endif - private: HeapObject** array_; // array_[(top - 1) & mask_] is the top element in the deque. The Deque is @@ -595,10 +566,6 @@ class MarkCompactCollector { bool is_compacting() const { return compacting_; } - // Find the large objects that are not completely scanned, but have been - // postponed to later. - static void ProcessLargePostponedArrays(Heap* heap, MarkingDeque* deque); - private: MarkCompactCollector(); ~MarkCompactCollector(); diff --git a/src/spaces.cc b/src/spaces.cc index 7a6a864..ce62877 100644 --- a/src/spaces.cc +++ b/src/spaces.cc @@ -2678,10 +2678,12 @@ MaybeObject* LargeObjectSpace::AllocateRaw(int object_size, HeapObject* object = page->GetObject(); - // Make the object consistent so the large object space can be traversed. +#ifdef DEBUG + // Make the object consistent so the heap can be vefified in OldSpaceStep. reinterpret_cast(object->address())[0] = heap()->fixed_array_map(); reinterpret_cast(object->address())[1] = Smi::FromInt(0); +#endif heap()->incremental_marking()->OldSpaceStep(object_size); return object; diff --git a/src/spaces.h b/src/spaces.h index dd9ccd5..2062f5f 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -393,15 +393,6 @@ class MemoryChunk { WAS_SWEPT_PRECISELY, WAS_SWEPT_CONSERVATIVELY, - // Used for large objects only. Indicates that the object has been - // partially scanned by the incremental mark-sweep GC. Objects that have - // been partially scanned are marked black so that the write barrier - // triggers for them, and they are counted as live bytes. If the mutator - // writes to them they may be turned grey and subtracted from the live byte - // list. They move back to the marking deque either by an iteration over - // the large object space or in the write barrier. - IS_PARTIALLY_SCANNED, - // Last flag, keep at bottom. NUM_MEMORY_CHUNK_FLAGS }; @@ -422,25 +413,6 @@ class MemoryChunk { (1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE); - static const int kIsPartiallyScannedMask = 1 << IS_PARTIALLY_SCANNED; - - void SetPartiallyScannedProgress(int progress) { - SetFlag(IS_PARTIALLY_SCANNED); - partially_scanned_progress_ = progress; - } - - bool IsPartiallyScanned() { - return IsFlagSet(IS_PARTIALLY_SCANNED); - } - - void SetCompletelyScanned() { - ClearFlag(IS_PARTIALLY_SCANNED); - } - - int PartiallyScannedProgress() { - ASSERT(IsPartiallyScanned()); - return partially_scanned_progress_; - } void SetFlag(int flag) { flags_ |= static_cast(1) << flag; @@ -516,10 +488,8 @@ class MemoryChunk { static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize; - static const size_t kPartiallyScannedProgress = - kSlotsBufferOffset + kPointerSize + kPointerSize; - - static const size_t kHeaderSize = kPartiallyScannedProgress + kIntSize; + static const size_t kHeaderSize = + kSlotsBufferOffset + kPointerSize + kPointerSize; static const int kBodyOffset = CODE_POINTER_ALIGN(MAP_POINTER_ALIGN(kHeaderSize + Bitmap::kSize)); @@ -655,7 +625,6 @@ class MemoryChunk { int live_byte_count_; SlotsBuffer* slots_buffer_; SkipList* skip_list_; - int partially_scanned_progress_; static MemoryChunk* Initialize(Heap* heap, Address base, -- 2.7.4