src/hotspot/share/gc/shared/gcConfig.cpp
changeset 49629 b786280276dc
child 49922 3a64eea72624
child 56422 b09629f4b243
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp	Wed Mar 28 11:38:47 2018 +0200
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/serial/serialArguments.hpp"
+#include "gc/shared/gcConfig.hpp"
+#include "runtime/java.hpp"
+#include "runtime/os.hpp"
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/parallel/parallelArguments.hpp"
+#include "gc/cms/cmsArguments.hpp"
+#include "gc/g1/g1Arguments.hpp"
+#endif // INCLUDE_ALL_GCS
+
+struct SupportedGC {
+  bool&               _flag;
+  CollectedHeap::Name _name;
+  GCArguments&        _arguments;
+
+  SupportedGC(bool& flag, CollectedHeap::Name name, GCArguments& arguments) :
+      _flag(flag), _name(name), _arguments(arguments) {}
+};
+
+static SerialArguments   serialArguments;
+#if INCLUDE_ALL_GCS
+static ParallelArguments parallelArguments;
+static CMSArguments      cmsArguments;
+static G1Arguments       g1Arguments;
+#endif // INCLUDE_ALL_GCS
+
+// Table of supported GCs, for translating between command
+// line flag, CollectedHeap::Name and GCArguments instance.
+static const SupportedGC SupportedGCs[] = {
+  SupportedGC(UseSerialGC,        CollectedHeap::Serial,   serialArguments),
+#if INCLUDE_ALL_GCS
+  SupportedGC(UseParallelGC,      CollectedHeap::Parallel, parallelArguments),
+  SupportedGC(UseParallelOldGC,   CollectedHeap::Parallel, parallelArguments),
+  SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS,      cmsArguments),
+  SupportedGC(UseG1GC,            CollectedHeap::G1,       g1Arguments),
+#endif // INCLUDE_ALL_GCS
+};
+
+GCArguments* GCConfig::_arguments = NULL;
+bool GCConfig::_gc_selected_ergonomically = false;
+
+void GCConfig::select_gc_ergonomically() {
+#if INCLUDE_ALL_GCS
+  if (os::is_server_class_machine()) {
+    FLAG_SET_ERGO_IF_DEFAULT(bool, UseG1GC, true);
+  } else {
+    FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
+  }
+#else
+  UNSUPPORTED_OPTION(UseG1GC);
+  UNSUPPORTED_OPTION(UseParallelGC);
+  UNSUPPORTED_OPTION(UseParallelOldGC);
+  UNSUPPORTED_OPTION(UseConcMarkSweepGC);
+  FLAG_SET_ERGO_IF_DEFAULT(bool, UseSerialGC, true);
+#endif // INCLUDE_ALL_GCS
+}
+
+bool GCConfig::is_no_gc_selected() {
+  for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
+    if (SupportedGCs[i]._flag) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool GCConfig::is_exactly_one_gc_selected() {
+  CollectedHeap::Name selected = CollectedHeap::None;
+
+  for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
+    if (SupportedGCs[i]._flag) {
+      if (SupportedGCs[i]._name == selected || selected == CollectedHeap::None) {
+        // Selected
+        selected = SupportedGCs[i]._name;
+      } else {
+        // More than one selected
+        return false;
+      }
+    }
+  }
+
+  return selected != CollectedHeap::None;
+}
+
+GCArguments* GCConfig::select_gc() {
+  if (is_no_gc_selected()) {
+    // Try select GC ergonomically
+    select_gc_ergonomically();
+
+    if (is_no_gc_selected()) {
+      // Failed to select GC ergonomically
+      vm_exit_during_initialization("Garbage collector not selected "
+                                    "(default collector explicitly disabled)", NULL);
+    }
+
+    // Succeeded to select GC ergonomically
+    _gc_selected_ergonomically = true;
+  }
+
+  if (is_exactly_one_gc_selected()) {
+    // Exacly one GC selected
+    for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
+      if (SupportedGCs[i]._flag) {
+        return &SupportedGCs[i]._arguments;
+      }
+    }
+  }
+
+  // More than one GC selected
+  vm_exit_during_initialization("Multiple garbage collectors selected", NULL);
+
+  return NULL;
+}
+
+void GCConfig::initialize() {
+  assert(_arguments == NULL, "Already initialized");
+  _arguments = select_gc();
+}
+
+bool GCConfig::is_gc_supported(CollectedHeap::Name name) {
+  for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
+    if (SupportedGCs[i]._name == name) {
+      // Supported
+      return true;
+    }
+  }
+
+  // Not supported
+  return false;
+}
+
+bool GCConfig::is_gc_selected(CollectedHeap::Name name) {
+  for (size_t i = 0; i < ARRAY_SIZE(SupportedGCs); i++) {
+    if (SupportedGCs[i]._name == name && SupportedGCs[i]._flag) {
+      // Selected
+      return true;
+    }
+  }
+
+  // Not selected
+  return false;
+}
+
+bool GCConfig::is_gc_selected_ergonomically() {
+  return _gc_selected_ergonomically;
+}
+
+GCArguments* GCConfig::arguments() {
+  assert(_arguments != NULL, "Not initialized");
+  return _arguments;
+}