Revision: 8192
Author:   [email protected]
Date:     Mon Jun  6 23:55:11 2011
Log: Changes that anticipate making semispaces contain more than one page.

Use an anchor page for each semispace in anticipation of having a real linked list of pages.
Made NewSpacePage be owned by the semispace, not NewSpace.
Added validation for semispaces.

Review URL: http://codereview.chromium.org/7027030
http://code.google.com/p/v8/source/detail?r=8192

Modified:
 /branches/experimental/gc/src/spaces.cc
 /branches/experimental/gc/src/spaces.h

=======================================
--- /branches/experimental/gc/src/spaces.cc     Mon Jun  6 04:22:38 2011
+++ /branches/experimental/gc/src/spaces.cc     Mon Jun  6 23:55:11 2011
@@ -396,16 +396,16 @@

 NewSpacePage* NewSpacePage::Initialize(Heap* heap,
                                        Address start,
-                                       SemiSpaceId semispace_id) {
+                                       SemiSpace* semi_space) {
   MemoryChunk* chunk = MemoryChunk::Initialize(heap,
                                                start,
                                                Page::kPageSize,
                                                NOT_EXECUTABLE,
-                                               heap->new_space());
+                                               semi_space);
   chunk->set_next_chunk(NULL);
   chunk->set_prev_chunk(NULL);
   chunk->initialize_scan_on_scavenge(true);
-  bool in_to_space = (semispace_id != kFromSpace);
+  bool in_to_space = (semi_space->id() != kFromSpace);
   chunk->SetFlag(in_to_space ? MemoryChunk::IN_TO_SPACE
                              : MemoryChunk::IN_FROM_SPACE);
   ASSERT(!chunk->IsFlagSet(in_to_space ? MemoryChunk::IN_FROM_SPACE
@@ -413,6 +413,13 @@
   heap->incremental_marking()->SetNewSpacePageFlags(chunk);
   return static_cast<NewSpacePage*>(chunk);
 }
+
+
+void NewSpacePage::InitializeAsAnchor(SemiSpace* semi_space) {
+  set_owner(semi_space);
+  set_next_chunk(this);
+  set_prev_chunk(this);
+}


 MemoryChunk* MemoryChunk::Initialize(Heap* heap,
@@ -939,15 +946,7 @@


 void NewSpace::Flip() {
-  SemiSpace tmp = from_space_;
-  from_space_ = to_space_;
-  to_space_ = tmp;
-
-  // Copy GC flags from old active space (from-space) to new (to-space).
-  intptr_t flags = from_space_.current_page()->GetFlags();
-  to_space_.Flip(flags, NewSpacePage::kCopyOnFlipFlagsMask);
-
-  from_space_.Flip(0, 0);
+  SemiSpace::Swap(&from_space_, &to_space_);
 }


@@ -993,7 +992,8 @@


 void NewSpace::ResetAllocationInfo() {
-  allocation_info_.top = to_space_.low();
+  to_space_.Reset();
+  allocation_info_.top = to_space_.page_low();
   allocation_info_.limit = to_space_.high();
   ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
 }
@@ -1015,12 +1015,12 @@
     // The first word should be a map, and we expect all map pointers to
     // be in map space.
     Map* map = object->map();
-    ASSERT(map->IsMap());
-    ASSERT(heap()->map_space()->Contains(map));
+    CHECK(map->IsMap());
+    CHECK(heap()->map_space()->Contains(map));

     // The object should not be code or a map.
-    ASSERT(!object->IsMap());
-    ASSERT(!object->IsCode());
+    CHECK(!object->IsMap());
+    CHECK(!object->IsCode());

     // The object itself should look OK.
     object->Verify();
@@ -1035,6 +1035,12 @@

   // The allocation pointer should not be in the middle of an object.
   ASSERT(current == top());
+
+  // Check semi-spaces.
+  ASSERT_EQ(from_space_.id(), kFromSpace);
+  ASSERT_EQ(to_space_.id(), kToSpace);
+  from_space_.Verify();
+  to_space_.Verify();
 }
 #endif

@@ -1048,7 +1054,9 @@
   committed_ = true;
   // TODO(gc): When more than one page is present, initialize and
   // chain them all.
-  current_page_ = NewSpacePage::Initialize(heap(), start_, id_);
+  NewSpacePage* page = NewSpacePage::Initialize(heap(), start_, this);
+  page->InsertAfter(&anchor_);
+  current_page_ = anchor_.next_page();
   return true;
 }

@@ -1062,6 +1070,33 @@
   committed_ = false;
   return true;
 }
+
+
+void SemiSpace::Reset() {
+  ASSERT(anchor_.next_page() != &anchor_);
+  current_page_ = anchor_.next_page();
+}
+
+
+void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) {
+  // We won't be swapping semispaces without data in them.
+  ASSERT(from->anchor_.next_page() != &from->anchor_);
+  ASSERT(to->anchor_.next_page() != &to->anchor_);
+
+  // Swap bits.
+  SemiSpace tmp = *from;
+  *from = *to;
+  *to = tmp;
+
+  // Fixup back-pointers to the page list anchor now that its address
+  // has changed.
+  // Swap to/from-space bits on pages.
+  // Copy GC flags from old active space (from-space) to new (to-space).
+  intptr_t flags = from->current_page()->GetFlags();
+  to->FlipPages(flags, NewSpacePage::kCopyOnFlipFlagsMask);
+
+  from->FlipPages(0, 0);
+}


// -----------------------------------------------------------------------------
@@ -1147,11 +1182,18 @@
 }


-void SemiSpace::Flip(intptr_t flags, intptr_t mask) {
+void SemiSpace::FlipPages(intptr_t flags, intptr_t mask) {
+  anchor_.set_owner(this);
+  // Fixup back-pointers to anchor. Address of anchor changes
+  // when we swap.
+  anchor_.prev_page()->set_next_page(&anchor_);
+  anchor_.next_page()->set_prev_page(&anchor_);
+
   bool becomes_to_space = (id_ == kFromSpace);
   id_ = becomes_to_space ? kToSpace : kFromSpace;
-  NewSpacePage* page = NewSpacePage::FromAddress(start_);
-  while (page != NULL) {
+  NewSpacePage* page = anchor_.next_page();
+  while (page != &anchor_) {
+    page->set_owner(this);
     page->SetFlags(flags, mask);
     if (becomes_to_space) {
       page->ClearFlag(MemoryChunk::IN_FROM_SPACE);
@@ -1171,7 +1213,21 @@
 void SemiSpace::Print() { }


-void SemiSpace::Verify() { }
+void SemiSpace::Verify() {
+  bool is_from_space = (id_ == kFromSpace);
+  NewSpacePage* page = anchor_.next_page();
+  CHECK(anchor_.semi_space() == this);
+  while (page != &anchor_) {
+    CHECK(page->semi_space() == this);
+    CHECK(page->InNewSpace());
+    CHECK(page->IsFlagSet(is_from_space ? MemoryChunk::IN_FROM_SPACE
+                                        : MemoryChunk::IN_TO_SPACE));
+    CHECK(!page->IsFlagSet(is_from_space ? MemoryChunk::IN_TO_SPACE
+                                         : MemoryChunk::IN_FROM_SPACE));
+    CHECK(page->prev_page()->next_page() == page);
+    page = page->next_page();
+  }
+}
 #endif


=======================================
--- /branches/experimental/gc/src/spaces.h      Tue May 24 05:52:48 2011
+++ /branches/experimental/gc/src/spaces.h      Mon Jun  6 23:55:11 2011
@@ -362,6 +362,8 @@
   }

   Address body() { return address() + kObjectStartOffset; }
+
+  Address body_limit() { return address() + size(); }

   int body_size() { return size() - kObjectStartOffset; }

@@ -1475,6 +1477,9 @@
 };


+class SemiSpace;
+
+
 class NewSpacePage : public MemoryChunk {
  public:
   // GC related flags copied from from-space to to-space when
@@ -1491,7 +1496,24 @@
   inline void set_next_page(NewSpacePage* page) {
     set_next_chunk(page);
   }
+
+  inline NewSpacePage* prev_page() const {
+    return static_cast<NewSpacePage*>(prev_chunk());
+  }
+
+  inline void set_prev_page(NewSpacePage* page) {
+    set_prev_chunk(page);
+  }
+
+  SemiSpace* semi_space() {
+    return reinterpret_cast<SemiSpace*>(owner());
+  }
+
  private:
+  NewSpacePage(SemiSpace* owner) {
+    InitializeAsAnchor(owner);
+  }
+
   // Finds the NewSpacePage containg the given address.
   static NewSpacePage* FromAddress(Address address_in_page) {
     Address page_start =
@@ -1502,7 +1524,12 @@

   static NewSpacePage* Initialize(Heap* heap,
                                   Address start,
-                                  SemiSpaceId semispace);
+                                  SemiSpace* semi_space);
+
+  // Intialize a fake NewSpacePage used as sentinel at the ends
+  // of a doubly-linked list of real NewSpacePages.
+  // Only uses the prev/next links.
+  void InitializeAsAnchor(SemiSpace* owner);

   friend class SemiSpace;
   friend class SemiSpaceIterator;
@@ -1523,7 +1550,9 @@
     : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
       start_(NULL),
       age_mark_(NULL),
-      id_(semispace) { }
+      id_(semispace),
+      anchor_(this),
+      current_page_(NULL) { }

   // Sets up the semispace using the given chunk.
   bool Setup(Address start, int initial_capacity, int maximum_capacity);
@@ -1550,20 +1579,26 @@
   // semispace and less than the current capacity.
   bool ShrinkTo(int new_capacity);

-  // Flips the semispace between being from-space and to-space.
-  // Copies the flags into the masked positions on all pages in the space.
-  void Flip(intptr_t flags, intptr_t flag_mask);
-
-  // Returns the start address of the space.
+  // Returns the start address of the first page of the space.
   Address low() {
-    return NewSpacePage::FromAddress(start_)->body();
+    ASSERT(anchor_.next_page() != &anchor_);
+    return anchor_.next_page()->body();
+  }
+
+  // Returns the start address of the current page of the space.
+  Address page_low() {
+    ASSERT(anchor_.next_page() != &anchor_);
+    return current_page_->body();
   }

   // Returns one past the end address of the space.
   Address high() {
     // TODO(gc): Change when there is more than one page.
-    return current_page_->body() + current_page_->body_size();
-  }
+    return current_page_->body_limit();
+  }
+
+  // Resets the space to using the first page.
+  void Reset();

   // Age mark accessors.
   Address age_mark() { return age_mark_; }
@@ -1612,8 +1647,16 @@

   // Returns the initial capacity of the semi space.
   int InitialCapacity() { return initial_capacity_; }
+
+  SemiSpaceId id() { return id_; }
+
+  static void Swap(SemiSpace* from, SemiSpace* to);

  private:
+  // Flips the semispace between being from-space and to-space.
+  // Copies the flags into the masked positions on all pages in the space.
+  void FlipPages(intptr_t flags, intptr_t flag_mask);
+
   // The current and maximum capacity of the space.
   int capacity_;
   int maximum_capacity_;
@@ -1632,6 +1675,7 @@
   bool committed_;
   SemiSpaceId id_;

+  NewSpacePage anchor_;
   NewSpacePage* current_page_;

  public:

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to