Add -xGc: MS, CMS, SS options to specify which GC to use.

Can be used for running tests or benchmarks with semispace,
marksweep or concurrent marksweep.

Change-Id: Ic9ab1220150f2c7c9c30df4ffee45b9d303094b3
diff --git a/runtime/gc/collector_type.h b/runtime/gc/collector_type.h
new file mode 100644
index 0000000..a42819b
--- /dev/null
+++ b/runtime/gc/collector_type.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_GC_COLLECTOR_TYPE_H_
+#define ART_RUNTIME_GC_COLLECTOR_TYPE_H_
+
+#include <ostream>
+
+namespace art {
+namespace gc {
+
+// Which types of collections are able to be performed.
+enum CollectorType {
+  kCollectorTypeMS,
+  kCollectorTypeCMS,
+  kCollectorTypeSS,
+};
+std::ostream& operator<<(std::ostream& os, const CollectorType& collector_type);
+
+}  // namespace gc
+}  // namespace art
+
+#endif  // ART_RUNTIME_GC_COLLECTOR_TYPE_H_
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index d1784fa..d8902f0 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -54,6 +54,7 @@
 #include "mirror/object_array-inl.h"
 #include "object_utils.h"
 #include "os.h"
+#include "runtime.h"
 #include "ScopedLocalRef.h"
 #include "scoped_thread_state_change.h"
 #include "sirt_ref.h"
@@ -72,15 +73,15 @@
 // 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,
-           bool concurrent_gc, size_t parallel_gc_threads, size_t conc_gc_threads,
+           CollectorType collector_type, size_t parallel_gc_threads, size_t conc_gc_threads,
            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_(concurrent_gc),
+      concurrent_gc_(collector_type == gc::kCollectorTypeCMS),
+      collector_type_(collector_type),
       parallel_gc_threads_(parallel_gc_threads),
       conc_gc_threads_(conc_gc_threads),
       low_memory_mode_(low_memory_mode),
@@ -156,7 +157,7 @@
   // If we aren't the zygote, switch to the default non zygote allocator. This may update the
   // entrypoints.
   if (!Runtime::Current()->IsZygote()) {
-    ChangeAllocator(kDefaultPreZygoteAllocator);
+    ChangeCollector(collector_type_);
   }
   live_bitmap_.reset(new accounting::HeapBitmap(this));
   mark_bitmap_.reset(new accounting::HeapBitmap(this));
@@ -1203,6 +1204,21 @@
   CollectGarbageInternal(collector::kGcTypeFull, kGcCauseExplicit, clear_soft_references);
 }
 
+void Heap::ChangeCollector(CollectorType collector_type) {
+  switch (collector_type) {
+    case kCollectorTypeSS: {
+      ChangeAllocator(kAllocatorTypeBumpPointer);
+      break;
+    }
+    case kCollectorTypeMS:
+      // Fall-through.
+    case kCollectorTypeCMS: {
+      ChangeAllocator(kAllocatorTypeFreeList);
+      break;
+    }
+  }
+}
+
 void Heap::PreZygoteFork() {
   static Mutex zygote_creation_lock_("zygote creation lock", kZygoteCreationLock);
   Thread* self = Thread::Current();
@@ -1218,7 +1234,7 @@
   non_moving_space_->Trim();
   non_moving_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE);
   // Change the allocator to the post zygote one.
-  ChangeAllocator(kDefaultPostZygoteAllocator);
+  ChangeCollector(collector_type_);
   // 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.
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 877df48..8c5746d 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -26,6 +26,7 @@
 #include "gc/accounting/atomic_stack.h"
 #include "gc/accounting/card_table.h"
 #include "gc/collector/gc_type.h"
+#include "gc/collector_type.h"
 #include "globals.h"
 #include "gtest/gtest.h"
 #include "jni.h"
@@ -143,7 +144,7 @@
   // ImageWriter output.
   explicit 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& original_image_file_name, bool concurrent_gc,
+                const std::string& original_image_file_name, CollectorType collector_type_,
                 size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode,
                 size_t long_pause_threshold, size_t long_gc_threshold,
                 bool ignore_max_footprint);
@@ -193,6 +194,9 @@
   // Change the allocator, updates entrypoints.
   void ChangeAllocator(AllocatorType allocator);
 
+  // Change the collector to be one of the possible options (MS, CMS, SS).
+  void ChangeCollector(CollectorType collector_type);
+
   // 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) {
@@ -630,7 +634,10 @@
 
   // What kind of concurrency behavior is the runtime after? True for concurrent mark sweep GC,
   // false for stop-the-world mark sweep.
-  bool concurrent_gc_;
+  const bool concurrent_gc_;
+
+  // The current collector type.
+  CollectorType collector_type_;
 
   // How many GC threads we may use for paused parts of garbage collection.
   const size_t parallel_gc_threads_;