Mark pages created during bootstrapping as never-evacuate.
authoryangguo <yangguo@chromium.org>
Thu, 12 Feb 2015 16:47:50 +0000 (08:47 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 12 Feb 2015 16:47:56 +0000 (16:47 +0000)
This is to ensure that immutable immortal objects created during
bootstrapping are not relocated.

R=hpayer@chromium.org

Review URL: https://codereview.chromium.org/905773004

Cr-Commit-Position: refs/heads/master@{#26625}

src/heap/heap.cc
src/heap/mark-compact.cc
src/heap/spaces.cc
src/heap/spaces.h

index 45a15a2..07b47b0 100644 (file)
@@ -5620,7 +5620,17 @@ void Heap::SetStackLimits() {
 }
 
 
-void Heap::NotifyDeserializationComplete() { deserialization_complete_ = true; }
+void Heap::NotifyDeserializationComplete() {
+  deserialization_complete_ = true;
+#ifdef DEBUG
+  // All pages right after bootstrapping must be marked as never-evacuate.
+  PagedSpaces spaces(this);
+  for (PagedSpace* s = spaces.next(); s != NULL; s = spaces.next()) {
+    PageIterator it(s);
+    while (it.has_next()) CHECK(it.next()->NeverEvacuate());
+  }
+#endif  // DEBUG
+}
 
 
 void Heap::TearDown() {
index e4e5258..de0b0af 100644 (file)
@@ -242,6 +242,7 @@ void MarkCompactCollector::TearDown() {
 
 
 void MarkCompactCollector::AddEvacuationCandidate(Page* p) {
+  DCHECK(!p->NeverEvacuate());
   p->MarkEvacuationCandidate();
   evacuation_candidates_.Add(p);
 }
@@ -719,10 +720,9 @@ void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) {
   Candidate* least = NULL;
 
   PageIterator it(space);
-  if (it.has_next()) it.next();  // Never compact the first page.
-
   while (it.has_next()) {
     Page* p = it.next();
+    if (p->NeverEvacuate()) continue;
     p->ClearEvacuationCandidate();
 
     if (FLAG_stress_compaction) {
index 1a0d0bb..de752f3 100644 (file)
@@ -1032,6 +1032,9 @@ bool PagedSpace::Expand() {
                                                                 executable());
   if (p == NULL) return false;
 
+  // Pages created during bootstrapping may contain immortal immovable objects.
+  if (!heap()->deserialization_complete()) p->MarkNeverEvacuate();
+
   DCHECK(Capacity() <= max_capacity_);
 
   p->InsertAfter(anchor_.prev_page());
index efb784c..3a6bd30 100644 (file)
@@ -373,6 +373,7 @@ class MemoryChunk {
     CONTAINS_ONLY_DATA,
     EVACUATION_CANDIDATE,
     RESCAN_ON_EVACUATION,
+    NEVER_EVACUATE,  // May contain immortal immutables.
 
     // WAS_SWEPT indicates that marking bits have been cleared by the sweeper,
     // otherwise marking bits are still intact.
@@ -604,7 +605,14 @@ class MemoryChunk {
 
   static const int kFlagsOffset = kPointerSize;
 
-  bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); }
+  bool NeverEvacuate() { return IsFlagSet(NEVER_EVACUATE); }
+
+  void MarkNeverEvacuate() { SetFlag(NEVER_EVACUATE); }
+
+  bool IsEvacuationCandidate() {
+    DCHECK(!(IsFlagSet(NEVER_EVACUATE) && IsFlagSet(EVACUATION_CANDIDATE)));
+    return IsFlagSet(EVACUATION_CANDIDATE);
+  }
 
   bool ShouldSkipEvacuationSlotRecording() {
     return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0;
@@ -619,6 +627,7 @@ class MemoryChunk {
   inline SlotsBuffer** slots_buffer_address() { return &slots_buffer_; }
 
   void MarkEvacuationCandidate() {
+    DCHECK(!IsFlagSet(NEVER_EVACUATE));
     DCHECK(slots_buffer_ == NULL);
     SetFlag(EVACUATION_CANDIDATE);
   }