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