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

Unified Diff: src/incremental-marking.h

Issue 6542047: Basic implementation of incremental marking. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 10 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/incremental-marking.h
diff --git a/src/incremental-marking.h b/src/incremental-marking.h
new file mode 100644
index 0000000000000000000000000000000000000000..028591a411ce82255d863a610ec9dcaebcd0dfdf
--- /dev/null
+++ b/src/incremental-marking.h
@@ -0,0 +1,352 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
Erik Corry 2011/02/22 12:27:19 2011
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_INCREMENTAL_MARKING_H_
+#define V8_INCREMENTAL_MARKING_H_
+
+
+#include "execution.h"
+#include "mark-compact.h"
+#include "objects.h"
+
+namespace v8 {
+namespace internal {
+
+
+class IncrementalMarking : public AllStatic {
+ public:
+ enum State {
+ STOPPED,
+ MARKING,
+ COMPLETE
+ };
+
+ static void Start() {
Erik Corry 2011/02/22 12:27:19 I think it would be cleaner to move largish functi
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Start\n");
+ }
+ ASSERT(FLAG_incremental_marking);
+ ASSERT(state_ == STOPPED);
+ state_ = MARKING;
+
+ // Initialize marking stack.
+ marking_stack_.Initialize(Heap::new_space()->FromSpaceLow(),
+ Heap::new_space()->FromSpaceHigh());
+
+ // Clear markbits.
+ 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));
+
+ ClearMarkbits();
+
+#ifdef DEBUG
+ VerifyMarkbitsAreClean();
+#endif
+
+ // Mark strong roots grey.
+ RootMarkingVisitor visitor;
+ Heap::IterateStrongRoots(&visitor, VISIT_ONLY_STRONG);
+
+ // Ready to start incremental marking.
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Running\n");
+ }
+ }
+
+ static State state() {
+ ASSERT(state_ == STOPPED || FLAG_incremental_marking);
+ return state_;
+ }
+
+ static void Stop() {
+ state_ = STOPPED;
Erik Corry 2011/02/22 12:27:19 Fits on one line.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+ }
+
+ static void Hurry() {
+ if (state() == MARKING) {
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Hurry\n");
+ }
+ // TODO(gc) hurry can mark objects it encounters black as mutator
+ // was stopped.
+ while (!marking_stack_.is_empty()) {
+ HeapObject* obj = marking_stack_.Pop();
+ obj->Iterate(&visitor_);
+ MarkBlack(obj);
+ }
+ state_ = COMPLETE;
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Complete (hurry)\n");
+ }
+ }
+ }
+
+ static void Finalize() {
+ Hurry();
+ state_ = STOPPED;
+ ASSERT(marking_stack_.is_empty());
+ }
+
+
+ static void MarkingComplete() {
+ state_ = COMPLETE;
+ // We completed marking.
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Complete (normal)\n");
+ }
+ StackGuard::RequestGC();
+ }
+
+
+ static const intptr_t kAllocatedThreshold = 1024;
+ static const intptr_t kFactor = 8;
Erik Corry 2011/02/22 12:27:19 Perhaps call this kAllocationMarkingFactor.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+
+ static void Step(intptr_t allocated) {
+ if (state_ == MARKING) {
+ allocated_ += allocated;
+
+ if (allocated_ >= kAllocatedThreshold) {
+ intptr_t bytes_to_process = allocated_ * kFactor;
+ int count = 0;
+ double start = 0;
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Marking %d bytes\n", bytes_to_process);
+ start = OS::TimeCurrentMillis();
+ }
+ while (!marking_stack_.is_empty() && bytes_to_process > 0) {
+ HeapObject* obj = marking_stack_.Pop();
+ ASSERT(IsGrey(obj));
+ Map* map = obj->map();
+ int size = obj->SizeFromMap(map);
+ bytes_to_process -= size;
+ if (IsWhite(map)) WhiteToGrey(map);
+ obj->IterateBody(map->instance_type(), size, &visitor_);
+ MarkBlack(obj);
+ count++;
+ }
+ if (FLAG_trace_incremental_marking) {
+ double end = OS::TimeCurrentMillis();
+ PrintF("[IncrementalMarking] %d objects marked, spent %d ms\n",
+ count,
+ static_cast<int>(end - start));
+ }
+ allocated_ = 0;
+ if (marking_stack_.is_empty()) MarkingComplete();
+ }
+ }
+ }
+
+ static void RecordWrite(HeapObject* obj, Object* value) {
+ if (state_ != STOPPED && value->IsHeapObject()) {
+ if (IsBlack(obj) && IsWhite(HeapObject::cast(value))) {
+ BlackToGrey(obj);
+ if (state_ == COMPLETE) {
+ state_ = MARKING;
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
+ }
+ }
+ }
+ }
+ }
+
+ static void RecordWriteOf(HeapObject* value) {
+ if (state_ != STOPPED) {
+ if (IsWhite(value)) {
+ WhiteToGrey(value);
+ if (state_ == COMPLETE) {
+ state_ = MARKING;
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
+ }
+ }
+ }
+ }
+ }
+
+
+ static void RecordWrites(HeapObject* obj) {
+ if (state_ != STOPPED) {
+ if (IsBlack(obj)) {
+ BlackToGrey(obj);
+ if (state_ == COMPLETE) {
+ state_ = MARKING;
+ if (FLAG_trace_incremental_marking) {
+ PrintF("[IncrementalMarking] Restarting (new grey objects)\n");
+ }
+ }
+ }
+ }
+ }
+
+
+ // Black markbits: 10
+ static inline bool IsBlack(HeapObject* obj) {
+ return Marking::IsMarked(obj->address());
Erik Corry 2011/02/22 12:27:19 Assert that the other bit is not marked?
+ }
+
+ // White markbits: 00
+ static inline bool IsWhite(HeapObject* obj) {
+ return !Marking::IsMarked(obj->address()) &&
+ !Marking::IsMarked(obj->address() + kPointerSize);
+ }
+
+ // Grey markbits: 01
Erik Corry 2011/02/22 12:27:19 Probably should be 11 when we handle overflow.
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Yes. Will investigate when we start handling overf
+ static inline bool IsGrey(HeapObject* obj) {
+ return Marking::IsMarked(obj->address() + kPointerSize);
Erik Corry 2011/02/22 12:27:19 Assert that the other bit is not marked?
+ }
+
+ static inline void BlackToGrey(HeapObject* obj) {
+ ASSERT(IsBlack(obj));
+ Marking::ClearMark(obj->address());
+ Marking::SetMark(obj->address() + kPointerSize);
+ ASSERT(IsGrey(obj));
+
+ marking_stack_.Push(obj);
+ ASSERT(!marking_stack_.overflowed());
+ }
+
+ static inline void WhiteToGrey(HeapObject* obj) {
+ ASSERT(IsWhite(obj));
+ Marking::SetMark(obj->address() + kPointerSize);
+ ASSERT(IsGrey(obj));
+
+ marking_stack_.Push(obj);
+ ASSERT(!marking_stack_.overflowed());
+ }
+
+ static inline void MarkBlack(HeapObject* obj) {
+ Marking::SetMark(obj->address());
+ Marking::ClearMark(obj->address() + kPointerSize);
+ ASSERT(IsBlack(obj));
+ }
+
+ static inline const char* ColorStr(HeapObject* obj) {
+ if (IsBlack(obj)) return "black";
+ if (IsWhite(obj)) return "white";
+ if (IsGrey(obj)) return "grey";
+ return "???";
Erik Corry 2011/02/22 12:27:19 UNREACHABLE()?
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+ }
+
+ private:
+ static intptr_t allocated_;
+ static State state_;
+ static MarkingStack marking_stack_;
+
+ class MarkingVisitor : public ObjectVisitor {
+ public:
+ void VisitPointer(Object** p) {
+ MarkObjectByPointer(p);
+ }
+
+ void VisitPointers(Object** start, Object** end) {
+ for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+ }
+
+ private:
+ // Mark object pointed to by p.
+ INLINE(static void MarkObjectByPointer(Object** p)) {
+ if ((*p)->IsHeapObject()) {
+ HeapObject* object = HeapObject::cast(*p);
+ if (IsWhite(object)) WhiteToGrey(object);
+ }
+ }
+ };
+
+
+ class RootMarkingVisitor : public ObjectVisitor {
+ public:
+ void VisitPointer(Object** p) {
+ MarkObjectByPointer(p);
+ }
+
+ void VisitPointers(Object** start, Object** end) {
+ for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
+ }
+
+ private:
+ void MarkObjectByPointer(Object** p) {
+ if (!(*p)->IsHeapObject()) return;
+
+ HeapObject* object = HeapObject::cast(*p);
+ if (!IsWhite(object)) return;
+
+ Map* map = object->map();
+
+ WhiteToGrey(object);
Erik Corry 2011/02/22 12:27:19 This pushes the object onto the stack. When it is
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+
+ if (IsWhite(map)) WhiteToGrey(map);
Erik Corry 2011/02/22 12:27:19 Here we also mark the map. Aren't we doing it twi
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+ }
+ };
+
+
+ static void ClearMarkbits(PagedSpace* space) {
+ PageIterator it(space, PageIterator::PAGES_IN_USE);
+
+ while (it.has_next()) {
+ Page* p = it.next();
+ p->markbits()->Clear();
+ }
+ }
+
+
+ static void ClearMarkbits() {
+ // We are sweeping code and map spaces precisely so clearing is not required.
Erik Corry 2011/02/22 12:27:19 lint?
Vyacheslav Egorov (Chromium) 2011/02/23 14:31:46 Done.
+ ClearMarkbits(Heap::old_pointer_space());
+ ClearMarkbits(Heap::old_data_space());
+ ClearMarkbits(Heap::cell_space());
+ }
+
+
+#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
+
+ static MarkingVisitor visitor_;
+};
+
+} } // namespace v8::internal
+
+#endif // V8_INCREMENTAL_MARKING_H_

Powered by Google App Engine
This is Rietveld 408576698