Compact zygote.

We now start out using the bump pointer allocator and switch to
the free list collector (ROSAlloc) after the zygote forks.

Before compaction:
Zygote size: 9060352

After compaction
Zygote size: 8425864

The main reason the size doesn't reduce more is that most of the
zygote space is non-movable objects allocated by
VMRuntime.newNonMovableObject. The objects which are non-movable
but could be movable include around 10000 classes and some number
of fields and methods.

Bug: 8981901

Change-Id: Iea21b70fb7af27cb7e92d72070d278a5cd4026ac
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 740babd..90e2c65 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -525,7 +525,7 @@
 
   // Return to write header at start of image with future location of image_roots. At this point,
   // image_end_ is the size of the image (excluding bitmaps).
-  const size_t heap_bytes_per_bitmap_byte = 8 * gc::accounting::SpaceBitmap::kAlignment;
+  const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * gc::accounting::SpaceBitmap::kAlignment;
   const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) /
       heap_bytes_per_bitmap_byte;
   ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_),
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 1cff719..33e6bfd 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -62,6 +62,9 @@
 #include "well_known_classes.h"
 
 namespace art {
+
+extern void SetQuickAllocEntryPointsAllocator(gc::AllocatorType allocator);
+
 namespace gc {
 
 static constexpr bool kGCALotMode = false;
@@ -69,6 +72,8 @@
 static constexpr bool kDumpGcPerformanceOnShutdown = false;
 // Minimum amount of remaining bytes before a concurrent GC is triggered.
 static constexpr size_t kMinConcurrentRemainingBytes = 128 * KB;
+static constexpr AllocatorType kDefaultPreZygoteAllocator = kAllocatorTypeFreeList;
+static constexpr AllocatorType kDefaultPostZygoteAllocator = kAllocatorTypeFreeList;
 
 Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
            double target_utilization, size_t capacity, const std::string& image_file_name,
@@ -76,7 +81,7 @@
            bool low_memory_mode, size_t long_pause_log_threshold, size_t long_gc_log_threshold,
            bool ignore_max_footprint)
     : non_moving_space_(nullptr),
-      concurrent_gc_(!kMovingCollector && concurrent_gc),
+      concurrent_gc_(concurrent_gc),
       parallel_gc_threads_(parallel_gc_threads),
       conc_gc_threads_(conc_gc_threads),
       low_memory_mode_(low_memory_mode),
@@ -149,24 +154,25 @@
   if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
     LOG(INFO) << "Heap() entering";
   }
-
+  // If we aren't the zygote, switch to the default non zygote allocator. This may update the
+  // entrypoints.
+  if (!Runtime::Current()->IsZygote()) {
+    ChangeAllocator(kDefaultPreZygoteAllocator);
+  }
   live_bitmap_.reset(new accounting::HeapBitmap(this));
   mark_bitmap_.reset(new accounting::HeapBitmap(this));
-
   // Requested begin for the alloc space, to follow the mapped image and oat files
-  byte* requested_alloc_space_begin = NULL;
+  byte* requested_alloc_space_begin = nullptr;
   if (!image_file_name.empty()) {
     space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str());
-    CHECK(image_space != NULL) << "Failed to create space for " << image_file_name;
+    CHECK(image_space != nullptr) << "Failed to create space for " << image_file_name;
     AddSpace(image_space);
     // Oat files referenced by image files immediately follow them in memory, ensure alloc space
     // isn't going to get in the middle
     byte* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd();
     CHECK_GT(oat_file_end_addr, image_space->End());
     if (oat_file_end_addr > requested_alloc_space_begin) {
-      requested_alloc_space_begin =
-          reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_file_end_addr),
-                                          kPageSize));
+      requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
     }
   }
 
@@ -252,20 +258,19 @@
   CHECK_NE(max_allowed_footprint_, 0U);
 
   // Create our garbage collectors.
-  if (!kMovingCollector) {
-    for (size_t i = 0; i < 2; ++i) {
-      const bool concurrent = i != 0;
-      garbage_collectors_.push_back(new collector::MarkSweep(this, concurrent));
-      garbage_collectors_.push_back(new collector::PartialMarkSweep(this, concurrent));
-      garbage_collectors_.push_back(new collector::StickyMarkSweep(this, concurrent));
-    }
-    gc_plan_.push_back(collector::kGcTypeSticky);
-    gc_plan_.push_back(collector::kGcTypePartial);
-    gc_plan_.push_back(collector::kGcTypeFull);
-  } else {
+  for (size_t i = 0; i < 2; ++i) {
+    const bool concurrent = i != 0;
+    garbage_collectors_.push_back(new collector::MarkSweep(this, concurrent));
+    garbage_collectors_.push_back(new collector::PartialMarkSweep(this, concurrent));
+    garbage_collectors_.push_back(new collector::StickyMarkSweep(this, concurrent));
+  }
+  gc_plan_.push_back(collector::kGcTypeSticky);
+  gc_plan_.push_back(collector::kGcTypePartial);
+  gc_plan_.push_back(collector::kGcTypeFull);
+  if (kMovingCollector) {
+    // TODO: Clean this up.
     semi_space_collector_ = new collector::SemiSpace(this);
     garbage_collectors_.push_back(semi_space_collector_);
-    gc_plan_.push_back(collector::kGcTypeFull);
   }
 
   if (running_on_valgrind_) {
@@ -277,6 +282,15 @@
   }
 }
 
+void Heap::ChangeAllocator(AllocatorType allocator) {
+  DCHECK_NE(allocator, kAllocatorTypeLOS);
+  if (current_allocator_ != allocator) {
+    current_allocator_ = allocator;
+    SetQuickAllocEntryPointsAllocator(current_allocator_);
+    Runtime::Current()->GetInstrumentation()->ResetQuickAllocEntryPoints();
+  }
+}
+
 bool Heap::IsCompilingBoot() const {
   for (const auto& space : continuous_spaces_) {
     if (space->IsImageSpace()) {
@@ -1207,8 +1221,11 @@
   // Trim the pages at the end of the non moving space.
   non_moving_space_->Trim();
   non_moving_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE);
-  // Create a new bump pointer space which we will compact into.
+  // Change the allocator to the post zygote one.
+  ChangeAllocator(kDefaultPostZygoteAllocator);
+  // TODO: Delete bump_pointer_space_ and temp_pointer_space_?
   if (semi_space_collector_ != nullptr) {
+    // Create a new bump pointer space which we will compact into.
     space::BumpPointerSpace target_space("zygote bump space", non_moving_space_->End(),
                                          non_moving_space_->Limit());
     // Compact the bump pointer space to a new zygote bump pointer space.
@@ -1290,7 +1307,7 @@
 void Heap::Compact(space::ContinuousMemMapAllocSpace* target_space,
                    space::ContinuousMemMapAllocSpace* source_space) {
   CHECK(kMovingCollector);
-  CHECK_NE(target_space, source_space) << "In-place compaction unsupported";
+  CHECK_NE(target_space, source_space) << "In-place compaction currently unsupported";
   if (target_space != source_space) {
     semi_space_collector_->SetFromSpace(source_space);
     semi_space_collector_->SetToSpace(target_space);
@@ -1360,22 +1377,25 @@
   DCHECK_NE(gc_type, collector::kGcTypeNone);
 
   collector::GarbageCollector* collector = nullptr;
-  if (kMovingCollector) {
+  // TODO: Clean this up.
+  if (current_allocator_ == kAllocatorTypeBumpPointer) {
     gc_type = semi_space_collector_->GetGcType();
     CHECK_EQ(temp_space_->GetObjectsAllocated(), 0U);
     semi_space_collector_->SetFromSpace(bump_pointer_space_);
     semi_space_collector_->SetToSpace(temp_space_);
     mprotect(temp_space_->Begin(), temp_space_->Capacity(), PROT_READ | PROT_WRITE);
-  }
-  for (const auto& cur_collector : garbage_collectors_) {
-    if (cur_collector->IsConcurrent() == concurrent_gc_ &&
-        cur_collector->GetGcType() == gc_type) {
-      collector = cur_collector;
-      break;
-    }
-  }
-  if (kMovingCollector) {
+    collector = semi_space_collector_;
     gc_type = collector::kGcTypeFull;
+  } else if (current_allocator_ == kAllocatorTypeFreeList) {
+    for (const auto& cur_collector : garbage_collectors_) {
+      if (cur_collector->IsConcurrent() == concurrent_gc_ &&
+          cur_collector->GetGcType() == gc_type) {
+        collector = cur_collector;
+        break;
+      }
+    }
+  } else {
+    LOG(FATAL) << "Invalid current allocator " << current_allocator_;
   }
   CHECK(collector != NULL)
       << "Could not find garbage collector with concurrent=" << concurrent_gc_
@@ -1930,7 +1950,6 @@
   const size_t bytes_allocated = GetBytesAllocated();
   last_gc_size_ = bytes_allocated;
   last_gc_time_ns_ = NanoTime();
-
   size_t target_size;
   if (gc_type != collector::kGcTypeSticky) {
     // Grow the heap for non sticky GC.
@@ -1950,7 +1969,6 @@
     } else {
       next_gc_type_ = collector::kGcTypePartial;
     }
-
     // If we have freed enough memory, shrink the heap back down.
     if (bytes_allocated + max_free_ < max_allowed_footprint_) {
       target_size = bytes_allocated + max_free_;
@@ -1958,11 +1976,9 @@
       target_size = std::max(bytes_allocated, max_allowed_footprint_);
     }
   }
-
   if (!ignore_max_footprint_) {
     SetIdealFootprint(target_size);
-
-    if (concurrent_gc_) {
+    if (concurrent_gc_ && AllocatorHasConcurrentGC(current_allocator_)) {
       // Calculate when to perform the next ConcurrentGC.
       // Calculate the estimated GC duration.
       double gc_duration_seconds = NsToMs(gc_duration) / 1000.0;
@@ -1978,7 +1994,8 @@
         // Start a concurrent GC when we get close to the estimated remaining bytes. When the
         // allocation rate is very high, remaining_bytes could tell us that we should start a GC
         // right away.
-        concurrent_start_bytes_ = std::max(max_allowed_footprint_ - remaining_bytes, bytes_allocated);
+        concurrent_start_bytes_ = std::max(max_allowed_footprint_ - remaining_bytes,
+                                           bytes_allocated);
       }
       DCHECK_LE(concurrent_start_bytes_, max_allowed_footprint_);
       DCHECK_LE(max_allowed_footprint_, growth_limit_);
@@ -1992,10 +2009,10 @@
 }
 
 void Heap::SetReferenceOffsets(MemberOffset reference_referent_offset,
-                                MemberOffset reference_queue_offset,
-                                MemberOffset reference_queueNext_offset,
-                                MemberOffset reference_pendingNext_offset,
-                                MemberOffset finalizer_reference_zombie_offset) {
+                               MemberOffset reference_queue_offset,
+                               MemberOffset reference_queueNext_offset,
+                               MemberOffset reference_pendingNext_offset,
+                               MemberOffset finalizer_reference_zombie_offset) {
   reference_referent_offset_ = reference_referent_offset;
   reference_queue_offset_ = reference_queue_offset;
   reference_queueNext_offset_ = reference_queueNext_offset;
@@ -2029,27 +2046,6 @@
       arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
 }
 
-void Heap::PrintReferenceQueue(std::ostream& os, mirror::Object** queue) {
-  os << "Refernece queue " << queue << "\n";
-  if (queue != nullptr) {
-    mirror::Object* list = *queue;
-    if (list != nullptr) {
-      mirror::Object* cur = list;
-      do {
-        mirror::Object* pending_next =
-            cur->GetFieldObject<mirror::Object*>(reference_pendingNext_offset_, false);
-        os << "PendingNext=" << pending_next;
-        if (cur->GetClass()->IsFinalizerReferenceClass()) {
-          os << " Zombie=" <<
-              cur->GetFieldObject<mirror::Object*>(finalizer_reference_zombie_offset_, false);
-        }
-        os << "\n";
-        cur = pending_next;
-      } while (cur != list);
-    }
-  }
-}
-
 void Heap::EnqueueClearedReferences() {
   if (!cleared_references_.IsEmpty()) {
     // When a runtime isn't started there are no reference queues to care about so ignore.
@@ -2203,7 +2199,7 @@
       // finalizers released native managed allocations.
       UpdateMaxNativeFootprint();
     } else if (!IsGCRequestPending()) {
-      if (concurrent_gc_) {
+      if (concurrent_gc_ && AllocatorHasConcurrentGC(current_allocator_)) {
         RequestConcurrentGC(self);
       } else {
         CollectGarbageInternal(gc_type, kGcCauseForAlloc, false);
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 6f94714..9215556 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -189,6 +189,9 @@
   void RegisterNativeAllocation(JNIEnv* env, int bytes);
   void RegisterNativeFree(JNIEnv* env, int bytes);
 
+  // Change the allocator, updates entrypoints.
+  void ChangeAllocator(AllocatorType allocator);
+
   // The given reference is believed to be to an object in the Java heap, check the soundness of it.
   void VerifyObjectImpl(const mirror::Object* o);
   void VerifyObject(const mirror::Object* o) {
@@ -541,8 +544,6 @@
   bool IsEnqueued(mirror::Object* ref) const;
   void DelayReferenceReferent(mirror::Class* klass, mirror::Object* obj, RootVisitor mark_visitor,
                               void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-  // Print a reference queue.
-  void PrintReferenceQueue(std::ostream& os, mirror::Object** queue);
 
   // Run the finalizers.
   void RunFinalization(JNIEnv* env);
@@ -628,7 +629,7 @@
 
   // What kind of concurrency behavior is the runtime after? True for concurrent mark sweep GC,
   // false for stop-the-world mark sweep.
-  const bool concurrent_gc_;
+  bool concurrent_gc_;
 
   // How many GC threads we may use for paused parts of garbage collection.
   const size_t parallel_gc_threads_;
@@ -776,7 +777,7 @@
   UniquePtr<accounting::ObjectStack> live_stack_;
 
   // Allocator type.
-  const AllocatorType current_allocator_;
+  AllocatorType current_allocator_;
   const AllocatorType current_non_moving_allocator_;
 
   // Which GCs we run in order when we an allocation fails.
diff --git a/runtime/globals.h b/runtime/globals.h
index 1a25dfa..c2fe67e 100644
--- a/runtime/globals.h
+++ b/runtime/globals.h
@@ -26,61 +26,61 @@
 typedef intptr_t word;
 typedef uintptr_t uword;
 
-const size_t KB = 1024;
-const size_t MB = KB * KB;
-const size_t GB = KB * KB * KB;
+static constexpr size_t KB = 1024;
+static constexpr size_t MB = KB * KB;
+static constexpr size_t GB = KB * KB * KB;
 
-const size_t kWordSize = sizeof(word);
-const size_t kPointerSize = sizeof(void*);
+static constexpr size_t kWordSize = sizeof(word);
+static constexpr size_t kPointerSize = sizeof(void*);
 
-const size_t kBitsPerByte = 8;
-const size_t kBitsPerByteLog2 = 3;
-const int kBitsPerWord = kWordSize * kBitsPerByte;
-const size_t kWordHighBitMask = 1 << (kBitsPerWord - 1);
+static constexpr size_t kBitsPerByte = 8;
+static constexpr size_t kBitsPerByteLog2 = 3;
+static constexpr int kBitsPerWord = kWordSize * kBitsPerByte;
+static constexpr size_t kWordHighBitMask = 1 << (kBitsPerWord - 1);
 
 // Required stack alignment
-const size_t kStackAlignment = 16;
+static constexpr size_t kStackAlignment = 16;
 
 // Required object alignment
-const size_t kObjectAlignment = 8;
+static constexpr size_t kObjectAlignment = 8;
 
 // ARM instruction alignment. ARM processors require code to be 4-byte aligned,
 // but ARM ELF requires 8..
-const size_t kArmAlignment = 8;
+static constexpr size_t kArmAlignment = 8;
 
 // MIPS instruction alignment.  MIPS processors require code to be 4-byte aligned.
 // TODO: Can this be 4?
-const size_t kMipsAlignment = 8;
+static constexpr size_t kMipsAlignment = 8;
 
 // X86 instruction alignment. This is the recommended alignment for maximum performance.
-const size_t kX86Alignment = 16;
+static constexpr size_t kX86Alignment = 16;
 
 // System page size. We check this against sysconf(_SC_PAGE_SIZE) at runtime, but use a simple
 // compile-time constant so the compiler can generate better code.
-const int kPageSize = 4096;
+static constexpr int kPageSize = 4096;
 
 // Whether or not this is a debug build. Useful in conditionals where NDEBUG isn't.
 #if defined(NDEBUG)
-const bool kIsDebugBuild = false;
+static constexpr bool kIsDebugBuild = false;
 #else
-const bool kIsDebugBuild = true;
+static constexpr bool kIsDebugBuild = true;
 #endif
 
 // Whether or not this is a target (vs host) build. Useful in conditionals where ART_TARGET isn't.
 #if defined(ART_TARGET)
-const bool kIsTargetBuild = true;
+static constexpr bool kIsTargetBuild = true;
 #else
-const bool kIsTargetBuild = false;
+static constexpr bool kIsTargetBuild = false;
 #endif
 
 #if defined(ART_USE_PORTABLE_COMPILER)
-constexpr bool kUsePortableCompiler = true;
+static constexpr bool kUsePortableCompiler = true;
 #else
-constexpr bool kUsePortableCompiler = false;
+static constexpr bool kUsePortableCompiler = false;
 #endif
 
 // Garbage collector constants.
-static constexpr bool kMovingCollector = false && !kUsePortableCompiler;
+static constexpr bool kMovingCollector = true && !kUsePortableCompiler;
 // True if we allow moving classes.
 static constexpr bool kMovingClasses = false;
 // True if we allow moving fields.