Merge epsilon-gc-branch
authorshade
Tue, 12 Jun 2018 14:25:13 +0200
branchepsilon-gc-branch
changeset 56746 6d3a485a01dc
parent 56743 774caae3a3ce (diff)
parent 50520 12be4323b0a5 (current diff)
Merge
--- a/make/autoconf/hotspot.m4	Tue Jun 12 11:11:59 2018 +0000
+++ b/make/autoconf/hotspot.m4	Tue Jun 12 14:25:13 2018 +0200
@@ -25,7 +25,7 @@
 
 # All valid JVM features, regardless of platform
 VALID_JVM_FEATURES="compiler1 compiler2 zero minimal dtrace jvmti jvmci \
-    graal vm-structs jni-check services management cmsgc g1gc parallelgc serialgc nmt cds \
+    graal vm-structs jni-check services management cmsgc g1gc parallelgc serialgc epsilongc nmt cds \
     static-build link-time-opt aot jfr"
 
 # Deprecated JVM features (these are ignored, but with a warning)
@@ -410,7 +410,7 @@
   fi
 
   # All variants but minimal (and custom) get these features
-  NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cmsgc g1gc parallelgc serialgc jni-check jvmti management nmt services vm-structs"
+  NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cmsgc g1gc parallelgc serialgc epsilongc jni-check jvmti management nmt services vm-structs"
   if test "x$ENABLE_CDS" = "xtrue"; then
     NON_MINIMAL_FEATURES="$NON_MINIMAL_FEATURES cds"
   fi
--- a/make/hotspot/lib/JvmFeatures.gmk	Tue Jun 12 11:11:59 2018 +0000
+++ b/make/hotspot/lib/JvmFeatures.gmk	Tue Jun 12 14:25:13 2018 +0200
@@ -155,6 +155,11 @@
   JVM_EXCLUDE_FILES += psMarkSweep.cpp psMarkSweepDecorator.cpp
 endif
 
+ifneq ($(call check-jvm-feature, epsilongc), true)
+  JVM_CFLAGS_FEATURES += -DINCLUDE_EPSILONGC=0
+  JVM_EXCLUDE_PATTERNS += gc/epsilon
+endif
+
 ifneq ($(call check-jvm-feature, jfr), true)
   JVM_CFLAGS_FEATURES += -DINCLUDE_JFR=0
   JVM_EXCLUDE_PATTERNS += jfr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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/epsilon/epsilonArguments.hpp"
+#include "gc/epsilon/epsilonHeap.hpp"
+#include "gc/epsilon/epsilonCollectorPolicy.hpp"
+#include "gc/shared/gcArguments.inline.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
+#include "runtime/vm_version.hpp"
+#include "utilities/macros.hpp"
+
+size_t EpsilonArguments::conservative_max_heap_alignment() {
+  return UseLargePages ? os::large_page_size() : os::vm_page_size();
+}
+
+void EpsilonArguments::initialize() {
+  GCArguments::initialize();
+
+  assert(UseEpsilonGC, "Sanity");
+
+  // Forcefully exit when OOME is detected. Nothing we can do at that point.
+  if (FLAG_IS_DEFAULT(ExitOnOutOfMemoryError)) {
+    FLAG_SET_DEFAULT(ExitOnOutOfMemoryError, true);
+  }
+
+  if (EpsilonMaxTLABSize < MinTLABSize) {
+    warning("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
+    EpsilonMaxTLABSize = MinTLABSize;
+  }
+
+  if (!EpsilonElasticTLAB && EpsilonElasticTLABDecay) {
+    warning("Disabling EpsilonElasticTLABDecay because EpsilonElasticTLAB is disabled");
+    FLAG_SET_DEFAULT(EpsilonElasticTLABDecay, false);
+  }
+
+#ifdef COMPILER2
+  // Enable loop strip mining: there are still non-GC safepoints, no need to make it worse
+  if (FLAG_IS_DEFAULT(UseCountedLoopSafepoints)) {
+    FLAG_SET_DEFAULT(UseCountedLoopSafepoints, true);
+    if (FLAG_IS_DEFAULT(LoopStripMiningIter)) {
+      FLAG_SET_DEFAULT(LoopStripMiningIter, 1000);
+    }
+  }
+#endif
+}
+
+CollectedHeap* EpsilonArguments::create_heap() {
+  return create_heap_with_policy<EpsilonHeap, EpsilonCollectorPolicy>();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonArguments.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ *
+ */
+
+#ifndef SHARE_GC_EPSILON_EPSILONARGUMENTS_HPP
+#define SHARE_GC_EPSILON_EPSILONARGUMENTS_HPP
+
+#include "gc/shared/gcArguments.hpp"
+
+class CollectedHeap;
+
+class EpsilonArguments : public GCArguments {
+public:
+  virtual void initialize();
+  virtual size_t conservative_max_heap_alignment();
+  virtual CollectedHeap* create_heap();
+};
+
+#endif // SHARE_GC_EPSILON_EPSILONARGUMENTS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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 "runtime/thread.hpp"
+#include "gc/epsilon/epsilonBarrierSet.hpp"
+#include "gc/epsilon/epsilonThreadLocalData.hpp"
+#include "gc/shared/collectorPolicy.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "gc/shared/c1/barrierSetC1.hpp"
+#endif
+#ifdef COMPILER2
+#include "gc/shared/c2/barrierSetC2.hpp"
+#endif
+
+EpsilonBarrierSet::EpsilonBarrierSet() : BarrierSet(
+          make_barrier_set_assembler<BarrierSetAssembler>(),
+          make_barrier_set_c1<BarrierSetC1>(),
+          make_barrier_set_c2<BarrierSetC2>(),
+          BarrierSet::FakeRtti(BarrierSet::EpsilonBarrierSet)) {};
+
+void EpsilonBarrierSet::on_thread_create(Thread *thread) {
+  EpsilonThreadLocalData::create(thread);
+}
+
+void EpsilonBarrierSet::on_thread_destroy(Thread *thread) {
+  EpsilonThreadLocalData::destroy(thread);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_BARRIERSET_HPP
+#define SHARE_VM_GC_EPSILON_BARRIERSET_HPP
+
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "gc/shared/barrierSet.hpp"
+
+// No interaction with application is required for Epsilon, and therefore
+// the barrier set is empty.
+class EpsilonBarrierSet: public BarrierSet {
+  friend class VMStructs;
+
+public:
+  EpsilonBarrierSet();
+
+  virtual void print_on(outputStream *st) const {}
+
+  virtual void on_thread_create(Thread* thread);
+  virtual void on_thread_destroy(Thread* thread);
+
+  template <DecoratorSet decorators, typename BarrierSetT = EpsilonBarrierSet>
+  class AccessBarrier: public BarrierSet::AccessBarrier<decorators, BarrierSetT> {};
+};
+
+template<>
+struct BarrierSet::GetName<EpsilonBarrierSet> {
+  static const BarrierSet::Name value = BarrierSet::EpsilonBarrierSet;
+};
+
+template<>
+struct BarrierSet::GetType<BarrierSet::EpsilonBarrierSet> {
+  typedef ::EpsilonBarrierSet type;
+};
+
+#endif // SHARE_VM_GC_EPSILON_BARRIERSET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_COLLECTORPOLICY_HPP
+#define SHARE_VM_GC_EPSILON_COLLECTORPOLICY_HPP
+
+#include "gc/shared/collectorPolicy.hpp"
+
+class EpsilonCollectorPolicy: public CollectorPolicy {
+protected:
+  virtual void initialize_alignments() {
+    size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
+    size_t align = MAX2((size_t)os::vm_allocation_granularity(), page_size);
+    _space_alignment = align;
+    _heap_alignment  = align;
+  }
+
+public:
+  EpsilonCollectorPolicy() : CollectorPolicy() {};
+};
+
+#endif // SHARE_VM_GC_EPSILON_COLLECTORPOLICY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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/epsilon/epsilonHeap.hpp"
+#include "gc/epsilon/epsilonMemoryPool.hpp"
+#include "gc/epsilon/epsilonThreadLocalData.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/resourceArea.hpp"
+
+jint EpsilonHeap::initialize() {
+  size_t align = _policy->heap_alignment();
+  size_t init_byte_size = align_up(_policy->initial_heap_byte_size(), align);
+  size_t max_byte_size  = align_up(_policy->max_heap_byte_size(), align);
+
+  // Initialize backing storage
+  ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, align);
+  _virtual_space.initialize(heap_rs, init_byte_size);
+
+  MemRegion committed_region((HeapWord*)_virtual_space.low(),          (HeapWord*)_virtual_space.high());
+  MemRegion  reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary());
+
+  initialize_reserved_region(reserved_region.start(), reserved_region.end());
+
+  _space = new ContiguousSpace();
+  _space->initialize(committed_region, /* clear_space = */ true, /* mangle_space = */ true);
+
+  // Precompute hot fields
+  _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize);
+  _step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep);
+  _step_heap_print = (EpsilonPrintHeapSteps == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapSteps);
+  _decay_time_ns = (int64_t) EpsilonTLABDecayTime * NANOSECS_PER_MILLISEC;
+
+  // Enable monitoring
+  _monitoring_support = new EpsilonMonitoringSupport(this);
+  _last_counter_update = 0;
+  _last_heap_print = 0;
+
+  // Install barrier set
+  BarrierSet::set_barrier_set(new EpsilonBarrierSet());
+
+  // All done, print out the configuration
+  if (init_byte_size != max_byte_size) {
+    log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M",
+                 init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M);
+  } else {
+    log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M);
+  }
+
+  if (UseTLAB) {
+    log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K);
+    if (EpsilonElasticTLAB) {
+      log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity);
+    }
+    if (EpsilonElasticTLABDecay) {
+      log_info(gc)("Elastic TLABs decay enabled; decay time: " SIZE_FORMAT "ms", EpsilonTLABDecayTime);
+    }
+  } else {
+    log_info(gc)("Not using TLAB allocation");
+  }
+
+  return JNI_OK;
+}
+
+void EpsilonHeap::post_initialize() {
+  CollectedHeap::post_initialize();
+}
+
+void EpsilonHeap::initialize_serviceability() {
+  _pool = new EpsilonMemoryPool(this);
+  _memory_manager.add_pool(_pool);
+}
+
+GrowableArray<GCMemoryManager*> EpsilonHeap::memory_managers() {
+  GrowableArray<GCMemoryManager*> memory_managers(1);
+  memory_managers.append(&_memory_manager);
+  return memory_managers;
+}
+
+GrowableArray<MemoryPool*> EpsilonHeap::memory_pools() {
+  GrowableArray<MemoryPool*> memory_pools(1);
+  memory_pools.append(_pool);
+  return memory_pools;
+}
+
+size_t EpsilonHeap::unsafe_max_tlab_alloc(Thread* thr) const {
+  // Return max allocatable TLAB size, and let allocation path figure out
+  // the actual TLAB allocation size.
+  return _max_tlab_size;
+}
+
+EpsilonHeap* EpsilonHeap::heap() {
+  CollectedHeap* heap = Universe::heap();
+  assert(heap != NULL, "Uninitialized access to EpsilonHeap::heap()");
+  assert(heap->kind() == CollectedHeap::Epsilon, "Not an Epsilon heap");
+  return (EpsilonHeap*)heap;
+}
+
+HeapWord* EpsilonHeap::allocate_work(size_t size) {
+  HeapWord* res = _space->par_allocate(size);
+
+  while (res == NULL) {
+    // Allocation failed, attempt expansion, and retry:
+    MutexLockerEx ml(Heap_lock);
+
+    size_t space_left = max_capacity() - capacity();
+    size_t want_space = MAX2(size, EpsilonMinHeapExpand);
+
+    if (want_space < space_left) {
+      // Enough space to expand in bulk:
+      bool expand = _virtual_space.expand_by(want_space);
+      assert(expand, "Should be able to expand");
+    } else if (size < space_left) {
+      // No space to expand in bulk, and this allocation is still possible,
+      // take all the remaining space:
+      bool expand = _virtual_space.expand_by(space_left);
+      assert(expand, "Should be able to expand");
+    } else {
+      // No space left:
+      return NULL;
+    }
+
+    _space->set_end((HeapWord *) _virtual_space.high());
+    res = _space->par_allocate(size);
+  }
+
+  size_t used = _space->used();
+
+  // Allocation successful, update counters
+  {
+    size_t last = _last_counter_update;
+    if ((used - last >= _step_counter_update) && Atomic::cmpxchg(used, &_last_counter_update, last) == last) {
+      _monitoring_support->update_counters();
+    }
+  }
+
+  // ...and print the occupancy line, if needed
+  {
+    size_t last = _last_heap_print;
+    if ((used - last >= _step_heap_print) && Atomic::cmpxchg(used, &_last_heap_print, last) == last) {
+      log_info(gc)("Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M (%.2f%%) committed, " SIZE_FORMAT "M (%.2f%%) used",
+                   max_capacity() / M,
+                   capacity() / M,
+                   capacity() * 100.0 / max_capacity(),
+                   used / M,
+                   used * 100.0 / max_capacity());
+    }
+  }
+
+  return res;
+}
+
+HeapWord* EpsilonHeap::allocate_new_tlab(size_t min_size,
+                                         size_t requested_size,
+                                         size_t* actual_size) {
+  Thread* thread = Thread::current();
+
+  // Defaults in case elastic paths are not taken
+  bool fits = true;
+  size_t size = requested_size;
+  size_t ergo_tlab = requested_size;
+  int64_t time = 0;
+
+  if (EpsilonElasticTLAB) {
+    ergo_tlab = EpsilonThreadLocalData::ergo_tlab_size(thread);
+
+    if (EpsilonElasticTLABDecay) {
+      int64_t last_time = EpsilonThreadLocalData::last_tlab_time(thread);
+      time = (int64_t) os::javaTimeNanos();
+
+      assert(last_time <= time, "time should be monotonic");
+
+      // If the thread had not allocated recently, retract the ergonomic size.
+      // This conserves memory when the thread had initial burst of allocations,
+      // and then started allocating only sporadically.
+      if (last_time != 0 && (time - last_time > _decay_time_ns)) {
+        ergo_tlab = 0;
+        EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0);
+      }
+    }
+
+    // If we can fit the allocation under current TLAB size, do so.
+    // Otherwise, we want to elastically increase the TLAB size.
+    fits = (requested_size <= ergo_tlab);
+    if (!fits) {
+      size = (size_t) (ergo_tlab * EpsilonTLABElasticity);
+    }
+  }
+
+  // Always honor boundaries
+  size = MAX2(min_size, MIN2(_max_tlab_size, size));
+
+  if (log_is_enabled(Trace, gc)) {
+    ResourceMark rm;
+    log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
+                          "K, Max: " SIZE_FORMAT "K, Ergo: " SIZE_FORMAT "K) -> " SIZE_FORMAT "K",
+                  thread->name(),
+                  requested_size * HeapWordSize / K,
+                  min_size * HeapWordSize / K,
+                  _max_tlab_size * HeapWordSize / K,
+                  ergo_tlab * HeapWordSize / K,
+                  size * HeapWordSize / K);
+  }
+
+  // All prepared, let's do it!
+  HeapWord* res = allocate_work(size);
+
+  if (res != NULL) {
+    // Allocation successful
+    *actual_size = size;
+    if (EpsilonElasticTLABDecay) {
+      EpsilonThreadLocalData::set_last_tlab_time(thread, time);
+    }
+    if (EpsilonElasticTLAB && !fits) {
+      // If we requested expansion, this is our new ergonomic TLAB size
+      EpsilonThreadLocalData::set_ergo_tlab_size(thread, size);
+    }
+  } else {
+    // Allocation failed, reset ergonomics to try and fit smaller TLABs
+    if (EpsilonElasticTLAB) {
+      EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0);
+    }
+  }
+
+  return res;
+}
+
+HeapWord* EpsilonHeap::mem_allocate(size_t size, bool *gc_overhead_limit_was_exceeded) {
+  *gc_overhead_limit_was_exceeded = false;
+  return allocate_work(size);
+}
+
+void EpsilonHeap::collect(GCCause::Cause cause) {
+  log_info(gc)("GC request for \"%s\" is ignored", GCCause::to_string(cause));
+  _monitoring_support->update_counters();
+}
+
+void EpsilonHeap::do_full_collection(bool clear_all_soft_refs) {
+  log_info(gc)("Full GC request for \"%s\" is ignored", GCCause::to_string(gc_cause()));
+  _monitoring_support->update_counters();
+}
+
+void EpsilonHeap::safe_object_iterate(ObjectClosure *cl) {
+  _space->safe_object_iterate(cl);
+}
+
+void EpsilonHeap::print_on(outputStream *st) const {
+  st->print_cr("Epsilon Heap");
+
+  // Cast away constness:
+  ((VirtualSpace)_virtual_space).print_on(st);
+
+  st->print_cr("Allocation space:");
+  _space->print_on(st);
+}
+
+void EpsilonHeap::print_tracing_info() const {
+  Log(gc) log;
+  size_t allocated_kb = used() / K;
+  log.info("Total allocated: " SIZE_FORMAT " KB",
+           allocated_kb);
+  log.info("Average allocation rate: " SIZE_FORMAT " KB/sec",
+           (size_t)(allocated_kb * NANOSECS_PER_SEC / os::elapsed_counter()));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonHeap.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_COLLECTEDHEAP_HPP
+#define SHARE_VM_GC_EPSILON_COLLECTEDHEAP_HPP
+
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/softRefPolicy.hpp"
+#include "gc/shared/space.hpp"
+#include "services/memoryManager.hpp"
+#include "gc/epsilon/epsilonCollectorPolicy.hpp"
+#include "gc/epsilon/epsilonMonitoringSupport.hpp"
+#include "gc/epsilon/epsilonBarrierSet.hpp"
+#include "gc/epsilon/epsilon_globals.hpp"
+
+class EpsilonHeap : public CollectedHeap {
+  friend class VMStructs;
+private:
+  EpsilonCollectorPolicy* _policy;
+  SoftRefPolicy _soft_ref_policy;
+  EpsilonMonitoringSupport* _monitoring_support;
+  MemoryPool* _pool;
+  GCMemoryManager _memory_manager;
+  ContiguousSpace* _space;
+  VirtualSpace _virtual_space;
+  size_t _max_tlab_size;
+  size_t _step_counter_update;
+  size_t _step_heap_print;
+  int64_t _decay_time_ns;
+  volatile size_t _last_counter_update;
+  volatile size_t _last_heap_print;
+
+public:
+  static EpsilonHeap* heap();
+
+  EpsilonHeap(EpsilonCollectorPolicy* p) :
+          _policy(p),
+          _memory_manager("Epsilon Heap", "") {};
+
+  virtual Name kind() const {
+    return CollectedHeap::Epsilon;
+  }
+
+  virtual const char* name() const {
+    return "Epsilon";
+  }
+
+  virtual CollectorPolicy* collector_policy() const {
+    return _policy;
+  }
+
+  virtual SoftRefPolicy* soft_ref_policy() {
+    return &_soft_ref_policy;
+  }
+
+  virtual jint initialize();
+  virtual void post_initialize();
+  virtual void initialize_serviceability();
+
+  virtual GrowableArray<GCMemoryManager*> memory_managers();
+  virtual GrowableArray<MemoryPool*> memory_pools();
+
+  virtual size_t max_capacity() const { return _virtual_space.reserved_size();  }
+  virtual size_t capacity()     const { return _virtual_space.committed_size(); }
+  virtual size_t used()         const { return _space->used(); }
+
+  virtual bool is_in(const void* p) const {
+    return _space->is_in(p);
+  }
+
+  virtual bool is_scavengable(oop obj) {
+    // No GC is going to happen, therefore no objects ever move.
+    return false;
+  }
+
+  virtual bool is_maximal_no_gc() const {
+    // No GC is going to happen. Return "we are at max", when we are about to fail.
+    return used() == capacity();
+  }
+
+  // Allocation
+  HeapWord* allocate_work(size_t size);
+  virtual HeapWord* mem_allocate(size_t size, bool* gc_overhead_limit_was_exceeded);
+  virtual HeapWord* allocate_new_tlab(size_t min_size,
+                                      size_t requested_size,
+                                      size_t* actual_size);
+
+  // TLAB allocation
+  virtual bool supports_tlab_allocation()           const { return true;           }
+  virtual size_t tlab_capacity(Thread* thr)         const { return capacity();     }
+  virtual size_t tlab_used(Thread* thr)             const { return used();         }
+  virtual size_t max_tlab_size()                    const { return _max_tlab_size; }
+  virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;
+
+  virtual void collect(GCCause::Cause cause);
+  virtual void do_full_collection(bool clear_all_soft_refs);
+
+  // Heap walking support
+  virtual void safe_object_iterate(ObjectClosure* cl);
+  virtual void object_iterate(ObjectClosure* cl) {
+    safe_object_iterate(cl);
+  }
+
+  // No support for block parsing.
+  virtual HeapWord* block_start(const void* addr) const { return NULL;  }
+  virtual size_t block_size(const HeapWord* addr) const { return 0;     }
+  virtual bool block_is_obj(const HeapWord* addr) const { return false; }
+
+  // No GC threads
+  virtual void print_gc_threads_on(outputStream* st) const {}
+  virtual void gc_threads_do(ThreadClosure* tc) const {}
+
+  // No heap verification
+  virtual void prepare_for_verify() {}
+  virtual void verify(VerifyOption option) {}
+
+  virtual jlong millis_since_last_gc() {
+    // Report time since the VM start
+    return os::elapsed_counter() / NANOSECS_PER_MILLISEC;
+  }
+
+  virtual void print_on(outputStream* st) const;
+  virtual void print_tracing_info() const;
+
+};
+
+#endif // SHARE_VM_GC_EPSILON_COLLECTEDHEAP_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonMemoryPool.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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/epsilon/epsilonHeap.hpp"
+#include "gc/epsilon/epsilonMemoryPool.hpp"
+
+EpsilonMemoryPool::EpsilonMemoryPool(EpsilonHeap* heap) :
+        _heap(heap),
+        CollectedMemoryPool("Epsilon Heap",
+                            heap->capacity(),
+                            heap->max_capacity(),
+                            false) {
+  assert(UseEpsilonGC, "sanity");
+}
+
+MemoryUsage EpsilonMemoryPool::get_memory_usage() {
+  size_t initial_sz = initial_size();
+  size_t max_sz     = max_size();
+  size_t used       = used_in_bytes();
+  size_t committed  = committed_in_bytes();
+
+  return MemoryUsage(initial_sz, used, committed, max_sz);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonMemoryPool.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_EPSILONMEMORYPOOL_HPP
+#define SHARE_VM_GC_EPSILON_EPSILONMEMORYPOOL_HPP
+
+#include "gc/epsilon/epsilonHeap.hpp"
+#include "services/memoryPool.hpp"
+#include "services/memoryUsage.hpp"
+#include "utilities/macros.hpp"
+
+class EpsilonMemoryPool : public CollectedMemoryPool {
+private:
+  EpsilonHeap* _heap;
+
+public:
+  EpsilonMemoryPool(EpsilonHeap* heap);
+  size_t committed_in_bytes() { return _heap->capacity();     }
+  size_t used_in_bytes()      { return _heap->used();         }
+  size_t max_size()     const { return _heap->max_capacity(); }
+  MemoryUsage get_memory_usage();
+};
+
+#endif // SHARE_VM_GC_EPSILON_EPSILONMEMORYPOOL_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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/epsilon/epsilonMonitoringSupport.hpp"
+#include "gc/epsilon/epsilonHeap.hpp"
+#include "gc/shared/generationCounters.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/metaspaceCounters.hpp"
+#include "memory/resourceArea.hpp"
+#include "services/memoryService.hpp"
+
+class EpsilonSpaceCounters: public CHeapObj<mtGC> {
+  friend class VMStructs;
+
+private:
+  PerfVariable* _capacity;
+  PerfVariable* _used;
+  char*         _name_space;
+
+public:
+  EpsilonSpaceCounters(const char* name,
+                 int ordinal,
+                 size_t max_size,
+                 size_t initial_capacity,
+                 GenerationCounters* gc) {
+    if (UsePerfData) {
+      EXCEPTION_MARK;
+      ResourceMark rm;
+
+      const char* cns = PerfDataManager::name_space(gc->name_space(), "space", ordinal);
+
+      _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
+      strcpy(_name_space, cns);
+
+      const char* cname = PerfDataManager::counter_name(_name_space, "name");
+      PerfDataManager::create_string_constant(SUN_GC, cname, name, CHECK);
+
+      cname = PerfDataManager::counter_name(_name_space, "maxCapacity");
+      PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, (jlong)max_size, CHECK);
+
+      cname = PerfDataManager::counter_name(_name_space, "capacity");
+      _capacity = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, initial_capacity, CHECK);
+
+      cname = PerfDataManager::counter_name(_name_space, "used");
+      _used = PerfDataManager::create_variable(SUN_GC, cname, PerfData::U_Bytes, (jlong) 0, CHECK);
+
+      cname = PerfDataManager::counter_name(_name_space, "initCapacity");
+      PerfDataManager::create_constant(SUN_GC, cname, PerfData::U_Bytes, initial_capacity, CHECK);
+    }
+  }
+
+  ~EpsilonSpaceCounters() {
+    if (_name_space != NULL) {
+      FREE_C_HEAP_ARRAY(char, _name_space);
+    }
+  }
+
+  inline void update_all(size_t capacity, size_t used) {
+    _capacity->set_value(capacity);
+    _used->set_value(used);
+  }
+};
+
+class EpsilonGenerationCounters : public GenerationCounters {
+private:
+  EpsilonHeap* _heap;
+public:
+  EpsilonGenerationCounters(EpsilonHeap* heap) :
+          GenerationCounters("Heap", 1, 1, 0, heap->max_capacity(), heap->capacity()),
+          _heap(heap)
+  {};
+
+  virtual void update_all() {
+    _current_size->set_value(_heap->capacity());
+  }
+};
+
+EpsilonMonitoringSupport::EpsilonMonitoringSupport(EpsilonHeap* heap) {
+  _heap_counters  = new EpsilonGenerationCounters(heap);
+  _space_counters = new EpsilonSpaceCounters("Heap", 0, heap->max_capacity(), 0, _heap_counters);
+}
+
+void EpsilonMonitoringSupport::update_counters() {
+  MemoryService::track_memory_usage();
+
+  if (UsePerfData) {
+    EpsilonHeap* heap = EpsilonHeap::heap();
+    size_t used = heap->used();
+    size_t capacity = heap->capacity();
+    _heap_counters->update_all();
+    _space_counters->update_all(capacity, used);
+    MetaspaceCounters::update_performance_counters();
+    CompressedClassSpaceCounters::update_performance_counters();
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_EPSILONMONITORINGSUPPORT_HPP
+#define SHARE_VM_GC_EPSILON_EPSILONMONITORINGSUPPORT_HPP
+
+#include "memory/allocation.hpp"
+
+class GenerationCounters;
+class EpsilonSpaceCounters;
+class EpsilonHeap;
+
+class EpsilonMonitoringSupport : public CHeapObj<mtGC> {
+private:
+  GenerationCounters*   _heap_counters;
+  EpsilonSpaceCounters* _space_counters;
+
+public:
+  EpsilonMonitoringSupport(EpsilonHeap* heap);
+  void update_counters();
+};
+
+#endif // SHARE_VM_GC_EPSILON_EPSILONMONITORINGSUPPORT_HPP
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonThreadLocalData.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_EPSILONTHREADLOCALDATA_HPP
+#define SHARE_VM_GC_EPSILON_EPSILONTHREADLOCALDATA_HPP
+
+#include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
+
+class EpsilonThreadLocalData {
+private:
+  size_t _ergo_tlab_size;
+  int64_t _last_tlab_time;
+
+  EpsilonThreadLocalData() :
+          _ergo_tlab_size(0),
+          _last_tlab_time(0) {}
+
+  static EpsilonThreadLocalData* data(Thread* thread) {
+    assert(UseEpsilonGC, "Sanity");
+    return thread->gc_data<EpsilonThreadLocalData>();
+  }
+
+public:
+  static void create(Thread* thread) {
+    new (data(thread)) EpsilonThreadLocalData();
+  }
+
+  static void destroy(Thread* thread) {
+    data(thread)->~EpsilonThreadLocalData();
+  }
+
+  static size_t ergo_tlab_size(Thread *thread) {
+    return data(thread)->_ergo_tlab_size;
+  }
+
+  static int64_t last_tlab_time(Thread *thread) {
+    return data(thread)->_last_tlab_time;
+  }
+
+  static void set_ergo_tlab_size(Thread *thread, size_t val) {
+    data(thread)->_ergo_tlab_size = val;
+  }
+
+  static void set_last_tlab_time(Thread *thread, int64_t time) {
+    data(thread)->_last_tlab_time = time;
+  }
+};
+
+#endif // SHARE_VM_GC_EPSILON_EPSILONTHREADLOCALDATA_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilon_globals.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_EPSILON_GLOBALS_HPP
+#define SHARE_VM_GC_EPSILON_GLOBALS_HPP
+
+#include "runtime/globals.hpp"
+//
+// Defines all globals flags used by the Epsilon GC.
+//
+
+#define GC_EPSILON_FLAGS(develop,                                           \
+                    develop_pd,                                             \
+                    product,                                                \
+                    product_pd,                                             \
+                    diagnostic,                                             \
+                    diagnostic_pd,                                          \
+                    experimental,                                           \
+                    notproduct,                                             \
+                    manageable,                                             \
+                    product_rw,                                             \
+                    lp64_product,                                           \
+                    range,                                                  \
+                    constraint,                                             \
+                    writeable)                                              \
+                                                                            \
+  experimental(size_t, EpsilonPrintHeapSteps, 20,                           \
+          "Print heap occupancy stats with this number of steps. "          \
+          "0 turns the printing off.")                                      \
+          range(0, max_intx)                                                \
+                                                                            \
+  experimental(size_t, EpsilonUpdateCountersStep, 1 * M,                    \
+          "Update heap occupancy counters after allocating this much "      \
+          "memory. Higher values would make allocations faster at "         \
+          "the expense of lower resolution in heap counters.")              \
+          range(1, max_intx)                                                \
+                                                                            \
+  experimental(size_t, EpsilonMaxTLABSize, 4 * M,                           \
+          "Max TLAB size to use with Epsilon GC. Larger value improves "    \
+          "performance at the expense of per-thread memory waste. This "    \
+          "asks TLAB machinery to cap TLAB sizes at this value.")           \
+          range(1, max_intx)                                                \
+                                                                            \
+  experimental(bool, EpsilonElasticTLAB, true,                              \
+          "Use elastic policy to manage TLAB sizes. This conserves memory " \
+          "for non-actively allocating threads, even when they request "    \
+          "large TLABs for themselves. Active threads would experience "    \
+          "smaller TLABs until policy catches up.")                         \
+                                                                            \
+  experimental(bool, EpsilonElasticTLABDecay, true,                         \
+          "Use timed decays to shrik TLAB sizes. This conserves memory "    \
+          "for the threads that allocate in bursts of different sizes, "    \
+          "for example the small/rare allocations coming after the initial "\
+          "large burst.")                                                   \
+                                                                            \
+  experimental(double, EpsilonTLABElasticity, 1.1,                          \
+          "Multiplier to use when deciding on next TLAB size. Larger value "\
+          "improves performance at the expense of per-thread memory waste. "\
+          "Lower value improves memory footprint, but penalizes actively "  \
+          "allocating threads.")                                            \
+          range(1, max_intx)                                                \
+                                                                            \
+  experimental(size_t, EpsilonTLABDecayTime, 1000,                          \
+          "TLAB sizing policy decays to initial size after thread had not " \
+          "allocated for this long. Time is in milliseconds. Lower value "  \
+          "improves memory footprint, but penalizes actively allocating "   \
+          "threads.")                                                       \
+          range(1, max_intx)                                                \
+                                                                            \
+  experimental(size_t, EpsilonMinHeapExpand, 128 * M,                       \
+          "Min expansion step for heap. Larger value improves performance " \
+          "at the potential expense of memory waste.")                      \
+          range(1, max_intx)
+
+#endif // SHARE_VM_GC_EPSILON_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/vmStructs_epsilon.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, Red Hat Inc. 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.
+ *
+ */
+
+#ifndef SHARE_GC_EPSILON_VMSTRUCTS_HPP
+#define SHARE_GC_EPSILON_VMSTRUCTS_HPP
+
+#include "gc/epsilon/epsilonHeap.hpp"
+#include "gc/shared/space.hpp"
+#include "memory/virtualspace.hpp"
+
+#define VM_STRUCTS_EPSILONGC(nonstatic_field,                       \
+                            volatile_nonstatic_field,               \
+                            static_field)                           \
+  nonstatic_field(EpsilonHeap, _virtual_space, VirtualSpace)        \
+  nonstatic_field(EpsilonHeap, _space, ContiguousSpace*)
+
+#define VM_TYPES_EPSILONGC(declare_type,                            \
+                          declare_toplevel_type,                    \
+                          declare_integer_type)                     \
+  declare_type(EpsilonHeap, CollectedHeap)
+
+#define VM_INT_CONSTANTS_EPSILONGC(declare_constant,                \
+                                  declare_constant_with_value)
+
+#endif // SHARE_GC_EPSILON_VMSTRUCTS_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -103,17 +103,17 @@
   ~BarrierSet() { }
 
   template <class BarrierSetAssemblerT>
-  BarrierSetAssembler* make_barrier_set_assembler() {
+  static BarrierSetAssembler* make_barrier_set_assembler() {
     return NOT_ZERO(new BarrierSetAssemblerT()) ZERO_ONLY(NULL);
   }
 
   template <class BarrierSetC1T>
-  BarrierSetC1* make_barrier_set_c1() {
+  static BarrierSetC1* make_barrier_set_c1() {
     return COMPILER1_PRESENT(new BarrierSetC1T()) NOT_COMPILER1(NULL);
   }
 
   template <class BarrierSetC2T>
-  BarrierSetC2* make_barrier_set_c2() {
+  static BarrierSetC2* make_barrier_set_c2() {
     return COMPILER2_PRESENT(new BarrierSetC2T()) NOT_COMPILER2(NULL);
   }
 
--- a/src/hotspot/share/gc/shared/barrierSetConfig.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/barrierSetConfig.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -30,6 +30,7 @@
 // Do something for each concrete barrier set part of the build.
 #define FOR_EACH_CONCRETE_BARRIER_SET_DO(f)          \
   f(CardTableBarrierSet)                             \
+  EPSILONGC_ONLY(f(EpsilonBarrierSet))               \
   G1GC_ONLY(f(G1BarrierSet))
 
 #define FOR_EACH_ABSTRACT_BARRIER_SET_DO(f)          \
--- a/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/barrierSetConfig.inline.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -30,6 +30,9 @@
 #include "gc/shared/modRefBarrierSet.inline.hpp"
 #include "gc/shared/cardTableBarrierSet.inline.hpp"
 
+#if INCLUDE_EPSILONGC
+#include "gc/epsilon/epsilonBarrierSet.hpp" // Epsilon support
+#endif
 #if INCLUDE_G1GC
 #include "gc/g1/g1BarrierSet.inline.hpp" // G1 support
 #endif
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -206,7 +206,8 @@
     Serial,
     Parallel,
     CMS,
-    G1
+    G1,
+    Epsilon
   };
 
   static inline size_t filler_array_max_size() {
--- a/src/hotspot/share/gc/shared/gcConfig.cpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/gcConfig.cpp	Tue Jun 12 14:25:13 2018 +0200
@@ -31,6 +31,9 @@
 #if INCLUDE_CMSGC
 #include "gc/cms/cmsArguments.hpp"
 #endif
+#if INCLUDE_EPSILONGC
+#include "gc/epsilon/epsilonArguments.hpp"
+#endif
 #if INCLUDE_G1GC
 #include "gc/g1/g1Arguments.hpp"
 #endif
@@ -52,6 +55,7 @@
 };
 
      CMSGC_ONLY(static CMSArguments      cmsArguments;)
+ EPSILONGC_ONLY(static EpsilonArguments  epsilonArguments;)
       G1GC_ONLY(static G1Arguments       g1Arguments;)
 PARALLELGC_ONLY(static ParallelArguments parallelArguments;)
   SERIALGC_ONLY(static SerialArguments   serialArguments;)
@@ -60,6 +64,7 @@
 // line flag, CollectedHeap::Name and GCArguments instance.
 static const SupportedGC SupportedGCs[] = {
        CMSGC_ONLY_ARG(SupportedGC(UseConcMarkSweepGC, CollectedHeap::CMS,      cmsArguments,      "concurrent mark sweep gc"))
+   EPSILONGC_ONLY_ARG(SupportedGC(UseEpsilonGC,       CollectedHeap::Epsilon,  epsilonArguments,  "epsilon gc"))
         G1GC_ONLY_ARG(SupportedGC(UseG1GC,            CollectedHeap::G1,       g1Arguments,       "g1 gc"))
   PARALLELGC_ONLY_ARG(SupportedGC(UseParallelGC,      CollectedHeap::Parallel, parallelArguments, "parallel gc"))
   PARALLELGC_ONLY_ARG(SupportedGC(UseParallelOldGC,   CollectedHeap::Parallel, parallelArguments, "parallel gc"))
@@ -88,6 +93,7 @@
   }
 
   NOT_CMSGC(     UNSUPPORTED_OPTION(UseConcMarkSweepGC));
+  NOT_EPSILONGC( UNSUPPORTED_OPTION(UseEpsilonGC);)
   NOT_G1GC(      UNSUPPORTED_OPTION(UseG1GC);)
   NOT_PARALLELGC(UNSUPPORTED_OPTION(UseParallelGC);)
   NOT_PARALLELGC(UNSUPPORTED_OPTION(UseParallelOldGC));
--- a/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -29,6 +29,9 @@
 #if INCLUDE_CMSGC
 #include "gc/cms/cms_globals.hpp"
 #endif
+#if INCLUDE_EPSILONGC
+#include "gc/epsilon/epsilon_globals.hpp"
+#endif
 #if INCLUDE_G1GC
 #include "gc/g1/g1_globals.hpp"
 #endif
@@ -70,6 +73,22 @@
     constraint,                                                             \
     writeable))                                                             \
                                                                             \
+  EPSILONGC_ONLY(GC_EPSILON_FLAGS(                                          \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable))                                                             \
+                                                                            \
   G1GC_ONLY(GC_G1_FLAGS(                                                    \
     develop,                                                                \
     develop_pd,                                                             \
@@ -135,6 +154,9 @@
   product(bool, UseParallelOldGC, false,                                    \
           "Use the Parallel Old garbage collector")                         \
                                                                             \
+  experimental(bool, UseEpsilonGC, false,                                   \
+          "Use the Epsilon (no-op) garbage collector")                      \
+                                                                            \
   product(uint, ParallelGCThreads, 0,                                       \
           "Number of parallel threads parallel gc will use")                \
           constraint(ParallelGCThreadsConstraintFunc,AfterErgo)             \
--- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -37,6 +37,9 @@
 #if INCLUDE_CMSGC
 #include "gc/cms/vmStructs_cms.hpp"
 #endif
+#if INCLUDE_EPSILONGC
+#include "gc/epsilon/vmStructs_epsilon.hpp"
+#endif
 #if INCLUDE_G1GC
 #include "gc/g1/vmStructs_g1.hpp"
 #endif
@@ -55,6 +58,9 @@
   CMSGC_ONLY(VM_STRUCTS_CMSGC(nonstatic_field,                                                                                       \
                               volatile_nonstatic_field,                                                                              \
                               static_field))                                                                                         \
+  EPSILONGC_ONLY(VM_STRUCTS_EPSILONGC(nonstatic_field,                                                                               \
+                                      volatile_nonstatic_field,                                                                      \
+                                      static_field))                                                                                 \
   G1GC_ONLY(VM_STRUCTS_G1GC(nonstatic_field,                                                                                         \
                             volatile_nonstatic_field,                                                                                \
                             static_field))                                                                                           \
@@ -153,6 +159,9 @@
   CMSGC_ONLY(VM_TYPES_CMSGC(declare_type,                                 \
                             declare_toplevel_type,                        \
                             declare_integer_type))                        \
+  EPSILONGC_ONLY(VM_TYPES_EPSILONGC(declare_type,                         \
+                                    declare_toplevel_type,                \
+                                    declare_integer_type))                \
   G1GC_ONLY(VM_TYPES_G1GC(declare_type,                                   \
                           declare_toplevel_type,                          \
                           declare_integer_type))                          \
@@ -225,6 +234,8 @@
                             declare_constant_with_value)                    \
   CMSGC_ONLY(VM_INT_CONSTANTS_CMSGC(declare_constant,                       \
                                     declare_constant_with_value))           \
+  EPSILONGC_ONLY(VM_INT_CONSTANTS_EPSILONGC(declare_constant,               \
+                                            declare_constant_with_value))   \
   G1GC_ONLY(VM_INT_CONSTANTS_G1GC(declare_constant,                         \
                                   declare_constant_with_value))             \
   PARALLELGC_ONLY(VM_INT_CONSTANTS_PARALLELGC(declare_constant,             \
--- a/src/hotspot/share/utilities/macros.hpp	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/hotspot/share/utilities/macros.hpp	Tue Jun 12 14:25:13 2018 +0200
@@ -149,6 +149,24 @@
 #define NOT_CMSGC_RETURN_(code) { return code; }
 #endif // INCLUDE_CMSGC
 
+#ifndef INCLUDE_EPSILONGC
+#define INCLUDE_EPSILONGC 1
+#endif // INCLUDE_EPSILONGC
+
+#if INCLUDE_EPSILONGC
+#define EPSILONGC_ONLY(x) x
+#define EPSILONGC_ONLY_ARG(arg) arg,
+#define NOT_EPSILONGC(x)
+#define NOT_EPSILONGC_RETURN        /* next token must be ; */
+#define NOT_EPSILONGC_RETURN_(code) /* next token must be ; */
+#else
+#define EPSILONGC_ONLY(x)
+#define EPSILONGC_ONLY_ARG(arg)
+#define NOT_EPSILONGC(x) x
+#define NOT_EPSILONGC_RETURN        {}
+#define NOT_EPSILONGC_RETURN_(code) { return code; }
+#endif // INCLUDE_EPSILONGC
+
 #ifndef INCLUDE_G1GC
 #define INCLUDE_G1GC 1
 #endif // INCLUDE_G1GC
@@ -203,7 +221,7 @@
 #define NOT_SERIALGC_RETURN_(code) { return code; }
 #endif // INCLUDE_SERIALGC
 
-#if INCLUDE_CMSGC || INCLUDE_G1GC || INCLUDE_PARALLELGC
+#if INCLUDE_CMSGC || INCLUDE_EPSILONGC || INCLUDE_G1GC || INCLUDE_PARALLELGC
 #define INCLUDE_NOT_ONLY_SERIALGC 1
 #else
 #define INCLUDE_NOT_ONLY_SERIALGC 0
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HSDB.java	Tue Jun 12 14:25:13 2018 +0200
@@ -33,6 +33,7 @@
 import sun.jvm.hotspot.code.*;
 import sun.jvm.hotspot.compiler.*;
 import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.gc.epsilon.*;
 import sun.jvm.hotspot.gc.parallel.*;
 import sun.jvm.hotspot.gc.shared.*;
 import sun.jvm.hotspot.gc.g1.*;
@@ -1108,6 +1109,9 @@
                             anno = "PSOldGen ";
                             bad = false;
                           }
+                        } else if (collHeap instanceof EpsilonHeap) {
+                          anno = "Epsilon ";
+                          bad = false;
                         } else {
                           // Optimistically assume the oop isn't bad
                           anno = "[Unknown generation] ";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/epsilon/EpsilonHeap.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ * 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.
+ *
+ */
+
+package sun.jvm.hotspot.gc.epsilon;
+
+import java.io.*;
+import java.util.*;
+
+import sun.jvm.hotspot.gc.shared.*;
+import sun.jvm.hotspot.code.*;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.runtime.*;
+import sun.jvm.hotspot.types.*;
+import sun.jvm.hotspot.memory.*;
+
+public class EpsilonHeap extends CollectedHeap {
+
+  private static AddressField spaceField;
+  private static Field virtualSpaceField;
+  private ContiguousSpace space;
+  private VirtualSpace virtualSpace;
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    Type type = db.lookupType("EpsilonHeap");
+    spaceField = type.getAddressField("_space");
+    virtualSpaceField = type.getField("_virtual_space");
+  }
+
+  public EpsilonHeap(Address addr) {
+    super(addr);
+    space = new ContiguousSpace(spaceField.getValue(addr));
+    virtualSpace = new VirtualSpace(addr.addOffsetTo(virtualSpaceField.getOffset()));
+  }
+
+  @Override
+  public CollectedHeapName kind() {
+    return CollectedHeapName.EPSILON;
+  }
+
+  public ContiguousSpace space() {
+    return space;
+  }
+
+  @Override
+  public void printOn(PrintStream tty) {
+     MemRegion mr = reservedRegion();
+     tty.println("Epsilon heap");
+     tty.println(" reserved:  [" + mr.start() + ", " + mr.end() + "]");
+     tty.println(" committed: [" + virtualSpace.low() + ", " + virtualSpace.high() + "]");
+     tty.println(" used:      [" + space.bottom() + ", " + space.top() + "]");
+  }
+
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/CollectedHeapName.java	Tue Jun 12 14:25:13 2018 +0200
@@ -35,6 +35,7 @@
   public static final CollectedHeapName PARALLEL = new CollectedHeapName("Parallel");
   public static final CollectedHeapName CMS = new CollectedHeapName("CMS");
   public static final CollectedHeapName G1 = new CollectedHeapName("G1");
+  public static final CollectedHeapName EPSILON = new CollectedHeapName("Epsilon");
 
   public String toString() {
     return name;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java	Tue Jun 12 14:25:13 2018 +0200
@@ -31,6 +31,7 @@
 import sun.jvm.hotspot.gc.serial.SerialHeap;
 import sun.jvm.hotspot.gc.shared.*;
 import sun.jvm.hotspot.gc.g1.G1CollectedHeap;
+import sun.jvm.hotspot.gc.epsilon.EpsilonHeap;
 import sun.jvm.hotspot.gc.parallel.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.types.*;
@@ -82,6 +83,7 @@
     heapConstructor.addMapping("SerialHeap", SerialHeap.class);
     heapConstructor.addMapping("ParallelScavengeHeap", ParallelScavengeHeap.class);
     heapConstructor.addMapping("G1CollectedHeap", G1CollectedHeap.class);
+    heapConstructor.addMapping("EpsilonHeap", EpsilonHeap.class);
 
     mainThreadGroupField   = type.getOopField("_main_thread_group");
     systemThreadGroupField = type.getOopField("_system_thread_group");
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java	Tue Jun 12 14:25:13 2018 +0200
@@ -34,6 +34,7 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.gc.cms.*;
 import sun.jvm.hotspot.gc.shared.*;
+import sun.jvm.hotspot.gc.epsilon.*;
 import sun.jvm.hotspot.gc.g1.*;
 import sun.jvm.hotspot.gc.parallel.*;
 import sun.jvm.hotspot.memory.*;
@@ -438,11 +439,13 @@
     } else if (heap instanceof G1CollectedHeap) {
         G1CollectedHeap g1h = (G1CollectedHeap) heap;
         g1h.heapRegionIterate(lrc);
+    } else if (heap instanceof EpsilonHeap) {
+       EpsilonHeap eh = (EpsilonHeap) heap;
+       liveRegions.add(eh.space().top());
+       liveRegions.add(eh.space().bottom());
     } else {
        if (Assert.ASSERTS_ENABLED) {
-          Assert.that(false, "Expecting GenCollectedHeap, G1CollectedHeap, " +
-                      "or ParallelScavengeHeap, but got " +
-                      heap.getClass().getName());
+          Assert.that(false, "Unexpected CollectedHeap type: " + heap.getClass().getName());
        }
     }
 
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Tue Jun 12 14:25:13 2018 +0200
@@ -25,6 +25,7 @@
 package sun.jvm.hotspot.tools;
 
 import java.util.*;
+import sun.jvm.hotspot.gc.epsilon.*;
 import sun.jvm.hotspot.gc.g1.*;
 import sun.jvm.hotspot.gc.parallel.*;
 import sun.jvm.hotspot.gc.serial.*;
@@ -124,6 +125,9 @@
          printValMB("used     = ", oldGen.used());
          printValMB("free     = ", oldFree);
          System.out.println(alignment + (double)oldGen.used() * 100.0 / oldGen.capacity() + "% used");
+      } else if (heap instanceof EpsilonHeap) {
+         EpsilonHeap eh = (EpsilonHeap) heap;
+         printSpace(eh.space());
       } else {
          throw new RuntimeException("unknown CollectedHeap type : " + heap.getClass());
       }
@@ -161,6 +165,12 @@
            return;
        }
 
+       l = getFlagValue("UseEpsilonGC", flagMap);
+       if (l == 1L) {
+           System.out.println("Epsilon (no-op) GC");
+           return;
+       }
+
        System.out.println("Mark Sweep Compact GC");
    }
 
--- a/test/hotspot/jtreg/TEST.ROOT	Tue Jun 12 11:11:59 2018 +0000
+++ b/test/hotspot/jtreg/TEST.ROOT	Tue Jun 12 14:25:13 2018 +0200
@@ -45,6 +45,7 @@
     vm.gc.Serial \
     vm.gc.Parallel \
     vm.gc.ConcMarkSweep \
+    vm.gc.Epsilon \
     vm.jvmci \
     vm.emulatedClient \
     vm.cpu.features \
--- a/test/hotspot/jtreg/TEST.groups	Tue Jun 12 11:11:59 2018 +0000
+++ b/test/hotspot/jtreg/TEST.groups	Tue Jun 12 14:25:13 2018 +0200
@@ -174,12 +174,14 @@
   -:tier1_gc
 
 tier1_gc_1 = \
+  gc/epsilon/ \
   gc/g1/ \
   -gc/g1/ihop/TestIHOPErgo.java
 
 tier1_gc_2 = \
   sanity/ExecuteInternalVMTests.java \
   gc/ \
+  -gc/epsilon/ \
   -gc/g1/ \
   -gc/logging/TestUnifiedLoggingSwitchStress.java \
   -gc/stress \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestAlwaysPretouch
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -Xmx1g -XX:+AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestAlwaysPretouch
+ */
+
+public class TestAlwaysPretouch {
+  public static void main(String[] args) throws Exception {
+    // everything should happen before entry point
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestByteArrays.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestByteArrays
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon is able to allocate arrays, and does not corrupt their state
+ *
+ * @run main/othervm -Xmx1g                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:-TieredCompilation  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ *
+ * @run main/othervm -Xmx1g                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:-TieredCompilation  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestByteArrays
+ */
+
+import java.util.Random;
+
+public class TestByteArrays {
+
+  static long SEED = Long.getLong("seed", System.nanoTime());
+  static int COUNT = Integer.getInteger("count", 3000); // ~500 MB allocation
+
+  static byte[][] arr;
+
+  public static void main(String[] args) throws Exception {
+    Random r = new Random(SEED);
+
+    arr = new byte[COUNT * 100][];
+    for (int c = 0; c < COUNT; c++) {
+      arr[c] = new byte[c * 100];
+      for (int v = 0; v < c; v++) {
+        arr[c][v] = (byte)(r.nextInt(255) & 0xFF);
+      }
+    }
+
+    r = new Random(SEED);
+    for (int c = 0; c < COUNT; c++) {
+      byte[] b = arr[c];
+      if (b.length != (c * 100)) {
+        throw new IllegalStateException("Failure: length = " + b.length + ", need = " + (c*100));
+      }
+      for (int v = 0; v < c; v++) {
+        byte actual = b[v];
+        byte expected = (byte)(r.nextInt(255) & 0xFF);
+        if (actual != expected) {
+          throw new IllegalStateException("Failure: expected = " + expected + ", actual = " + actual);
+        }
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestDieDefault.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestDieDefault
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon GC should die on heap exhaustion
+ * @library /test/lib
+ * @run main TestDieDefault
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestDieDefault {
+
+  public static void passWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer out = new OutputAnalyzer(pb.start());
+    out.shouldNotContain("OutOfMemoryError");
+    out.shouldHaveExitValue(0);
+  }
+
+  public static void failWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer out = new OutputAnalyzer(pb.start());
+    out.shouldContain("OutOfMemoryError");
+    if (out.getExitValue() == 0) {
+      throw new IllegalStateException("Should have failed with non-zero exit code");
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    passWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-Dcount=1",
+             TestDieDefault.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             TestDieDefault.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xint",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             TestDieDefault.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             TestDieDefault.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:TieredStopAtLevel=1",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             TestDieDefault.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:-TieredCompilation",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             TestDieDefault.Workload.class.getName());
+  }
+
+  public static class Workload {
+    static int COUNT = Integer.getInteger("count", 1_000_000_000); // ~24 GB allocation
+
+    static volatile Object sink;
+
+    public static void main(String... args) {
+      for (int c = 0; c < COUNT; c++) {
+        sink = new Object();
+      }
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestDieWithHeapDump
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon GC should die on heap exhaustion with error handler attached
+ * @library /test/lib
+ * @run main TestDieWithHeapDump
+ */
+
+import java.io.*;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestDieWithHeapDump {
+
+  public static void passWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer out = new OutputAnalyzer(pb.start());
+    out.shouldNotContain("OutOfMemoryError");
+    out.shouldHaveExitValue(0);
+  }
+
+  public static void failWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    Process p = pb.start();
+    OutputAnalyzer out = new OutputAnalyzer(p);
+    out.shouldContain("OutOfMemoryError");
+    if (out.getExitValue() == 0) {
+      throw new IllegalStateException("Should have failed with non-zero exit code");
+    }
+    String heapDump = "java_pid" + p.pid() + ".hprof";
+    if (!new File(heapDump).exists()) {
+      throw new IllegalStateException("Should have produced the heap dump at: " + heapDump);
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    passWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-Dcount=1",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xint",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:TieredStopAtLevel=1",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:-TieredCompilation",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:+HeapDumpOnOutOfMemoryError",
+             TestDieWithHeapDump.Workload.class.getName());
+  }
+
+  public static class Workload {
+    static int COUNT = Integer.getInteger("count", 1_000_000_000); // ~24 GB allocation
+
+    static volatile Object sink;
+
+    public static void main(String... args) {
+      for (int c = 0; c < COUNT; c++) {
+        sink = new Object();
+      }
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestDieWithOnError
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon GC should die on heap exhaustion with error handler attached
+ * @library /test/lib
+ * @run main TestDieWithOnError
+ */
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestDieWithOnError {
+
+  static String ON_ERR_MSG = "Epsilon error handler message";
+
+  public static void passWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer out = new OutputAnalyzer(pb.start());
+    out.shouldNotContain("OutOfMemoryError");
+    out.stdoutShouldNotMatch("^" + ON_ERR_MSG);
+    out.shouldHaveExitValue(0);
+  }
+
+  public static void failWith(String... args) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
+    OutputAnalyzer out = new OutputAnalyzer(pb.start());
+    out.shouldContain("OutOfMemoryError");
+    if (out.getExitValue() == 0) {
+      throw new IllegalStateException("Should have failed with non-zero exit code");
+    }
+    out.stdoutShouldMatch("^" + ON_ERR_MSG);
+  }
+
+  public static void main(String[] args) throws Exception {
+    passWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-Dcount=1",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xint",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:TieredStopAtLevel=1",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+
+    failWith("-Xmx128m",
+             "-Xbatch",
+             "-Xcomp",
+             "-XX:-TieredCompilation",
+             "-XX:+UnlockExperimentalVMOptions",
+             "-XX:+UseEpsilonGC",
+             "-XX:OnOutOfMemoryError=echo " + ON_ERR_MSG,
+             TestDieWithOnError.Workload.class.getName());
+  }
+
+  public static class Workload {
+    static int COUNT = Integer.getInteger("count", 1_000_000_000); // ~24 GB allocation
+
+    static volatile Object sink;
+
+    public static void main(String... args) {
+      for (int c = 0; c < COUNT; c++) {
+        sink = new Object();
+      }
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestElasticTLAB.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestElasticTLAB
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon is able to work with/without elastic TLABs
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:-EpsilonElasticTLAB                               TestElasticTLAB
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:EpsilonTLABElasticity=1   TestElasticTLAB
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:EpsilonTLABElasticity=1.1 TestElasticTLAB
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:EpsilonTLABElasticity=2.0 TestElasticTLAB
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:EpsilonTLABElasticity=42  TestElasticTLAB
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:EpsilonTLABElasticity=100 TestElasticTLAB
+ */
+
+import java.util.Random;
+
+public class TestElasticTLAB {
+
+  static long SEED = Long.getLong("seed", System.nanoTime());
+  static int COUNT = Integer.getInteger("count", 3000); // ~500 MB allocation
+
+  static byte[][] arr;
+
+  public static void main(String[] args) throws Exception {
+    Random r = new Random(SEED);
+
+    arr = new byte[COUNT * 100][];
+    for (int c = 0; c < COUNT; c++) {
+      arr[c] = new byte[c * 100];
+      for (int v = 0; v < c; v++) {
+        arr[c][v] = (byte)(r.nextInt(255) & 0xFF);
+      }
+    }
+
+    r = new Random(SEED);
+    for (int c = 0; c < COUNT; c++) {
+      byte[] b = arr[c];
+      if (b.length != (c * 100)) {
+        throw new IllegalStateException("Failure: length = " + b.length + ", need = " + (c*100));
+      }
+      for (int v = 0; v < c; v++) {
+        byte actual = b[v];
+        byte expected = (byte)(r.nextInt(255) & 0xFF);
+        if (actual != expected) {
+          throw new IllegalStateException("Failure: expected = " + expected + ", actual = " + actual);
+        }
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestElasticTLABDecay.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestElasticTLABDecay
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon is able to work with/without elastic TLABs
+ *
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:-EpsilonElasticTLABDecay                               TestElasticTLABDecay
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:+EpsilonElasticTLABDecay -XX:EpsilonTLABDecayTime=1    TestElasticTLABDecay
+ * @run main/othervm -Xmx1g -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -XX:+EpsilonElasticTLAB -XX:+EpsilonElasticTLABDecay -XX:EpsilonTLABDecayTime=100  TestElasticTLABDecay
+ */
+
+import java.util.Random;
+
+public class TestElasticTLABDecay {
+
+  static long SEED = Long.getLong("seed", System.nanoTime());
+  static int COUNT = Integer.getInteger("count", 3000); // ~500 MB allocation
+
+  static byte[][] arr;
+
+  public static void main(String[] args) throws Exception {
+    Random r = new Random(SEED);
+
+    arr = new byte[COUNT * 100][];
+    for (int c = 0; c < COUNT; c++) {
+      arr[c] = new byte[c * 100];
+      for (int v = 0; v < c; v++) {
+        arr[c][v] = (byte)(r.nextInt(255) & 0xFF);
+      }
+      Thread.sleep(5);
+    }
+
+    r = new Random(SEED);
+    for (int c = 0; c < COUNT; c++) {
+      byte[] b = arr[c];
+      if (b.length != (c * 100)) {
+        throw new IllegalStateException("Failure: length = " + b.length + ", need = " + (c*100));
+      }
+      for (int v = 0; v < c; v++) {
+        byte actual = b[v];
+        byte expected = (byte)(r.nextInt(255) & 0xFF);
+        if (actual != expected) {
+          throw new IllegalStateException("Failure: expected = " + expected + ", actual = " + actual);
+        }
+      }
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestEpsilonEnabled.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestAlwaysPretouch
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Basic sanity test for Epsilon
+ * @library /test/lib
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestEpsilonEnabled
+ */
+
+import jdk.test.lib.Platform;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+
+public class TestEpsilonEnabled {
+  public static void main(String[] args) throws Exception {
+    if (!isEpsilonEnabled()) {
+      throw new IllegalStateException("Debug builds should have Epsilon enabled");
+    }
+  }
+
+  public static boolean isEpsilonEnabled() {
+    for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
+      if (bean.getName().contains("Epsilon")) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestHelloWorld.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestHelloWorld
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestHelloWorld
+ */
+
+public class TestHelloWorld {
+  public static void main(String[] args) throws Exception {
+    System.out.println("Hello World");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestLogTrace.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestLogTrace
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Test that tracing does not crash Epsilon
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc*=trace TestLogTrace
+ */
+
+public class TestLogTrace {
+  public static void main(String[] args) throws Exception {
+    System.out.println("Hello World");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestManyThreads.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestManyThreads
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Test allocations from many threads
+ *
+ * @run main/othervm -Xmx128m -Xss512k                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:-TieredCompilation  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ *
+ * @run main/othervm -Xmx128m -Xss512k                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:-TieredCompilation  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestManyThreads
+ */
+
+import java.util.concurrent.atomic.*;
+
+public class TestManyThreads {
+
+  static int COUNT = Integer.getInteger("count", 128);  // 128 * 4M max tlabs = 512M, would overflow without TLAB sizing
+
+  static volatile Object sink;
+  static volatile Throwable failed;
+  static final AtomicInteger allocated = new AtomicInteger();
+
+  public static void workload() {
+    try {
+      sink = new Object();
+      allocated.incrementAndGet();
+      Thread.sleep(3600 * 1000);
+    } catch (Throwable e) {
+      failed = e;
+    }
+  }
+
+  public static void main(String[] args) throws Throwable {
+    for (int c = 0; c < COUNT; c++) {
+      Thread t = new Thread(TestManyThreads::workload);
+      t.setDaemon(true);
+      t.start();
+    }
+
+    while ((failed == null) && (allocated.get() != COUNT)) {
+        Thread.sleep(100);
+    }
+
+    if (failed != null) {
+      throw failed;
+    }
+  }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+/**
+ * @test TestMemoryMXBeans
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Test JMX memory beans
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC          -Xmx1g TestMemoryMXBeans   -1 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xms1g   -Xmx1g TestMemoryMXBeans 1024 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xms128m -Xmx1g TestMemoryMXBeans  128 1024
+ */
+
+import java.lang.management.*;
+import java.util.*;
+
+public class TestMemoryMXBeans {
+
+    static volatile Object sink;
+
+    public static void main(String[] args) throws Exception {
+        if (args.length < 2) {
+            throw new IllegalStateException("Should provide expected heap sizes");
+        }
+
+        long initSize = 1L * Integer.parseInt(args[0]) * 1024 * 1024;
+        long maxSize =  1L * Integer.parseInt(args[1]) * 1024 * 1024;
+
+        testMemoryBean(initSize, maxSize);
+        testAllocs();
+    }
+
+    public static void testMemoryBean(long initSize, long maxSize) {
+        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+        long heapInit = memoryMXBean.getHeapMemoryUsage().getInit();
+        long heapMax = memoryMXBean.getHeapMemoryUsage().getMax();
+        long nonHeapInit = memoryMXBean.getNonHeapMemoryUsage().getInit();
+        long nonHeapMax = memoryMXBean.getNonHeapMemoryUsage().getMax();
+
+        if (initSize > 0 && heapInit != initSize) {
+            throw new IllegalStateException("Init heap size is wrong: " + heapInit + " vs " + initSize);
+        }
+        if (maxSize > 0 && heapMax != maxSize) {
+            throw new IllegalStateException("Max heap size is wrong: " + heapMax + " vs " + maxSize);
+        }
+    }
+
+    public static void testAllocs() {
+        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+
+        // Do lazy inits first:
+        long heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+        sink = new int[1024*1024];
+        long heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+
+        // Compute how much we waste during the calls themselves:
+        heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+        heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+        long adj = heapUsed2 - heapUsed1;
+
+        heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+        sink = new int[1024*1024];
+        heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+
+        long diff = heapUsed2 - heapUsed1 - adj;
+        long min = 8 + 4*1024*1024;
+        long max = 16 + 4*1024*1024;
+        if (!(min <= diff && diff <= max)) {
+           throw new IllegalStateException("Allocation did not change used space right: " + diff + " should be in [" + min + ", " + max + "]");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestMemoryPools.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ *
+ */
+
+/**
+ * @test TestMemoryPools
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Test JMX memory pools
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xmx1g -Xms1g TestMemoryPools
+ */
+
+import java.lang.management.*;
+import java.util.*;
+
+public class TestMemoryPools {
+
+    public static void main(String[] args) throws Exception {
+        List<MemoryManagerMXBean> mms = ManagementFactory.getMemoryManagerMXBeans();
+        if (mms == null) {
+            throw new RuntimeException("getMemoryManagerMXBeans is null");
+        }
+        if (mms.isEmpty()) {
+            throw new RuntimeException("getMemoryManagerMXBeans is empty");
+        }
+        for (MemoryManagerMXBean mmBean : mms) {
+            String[] names = mmBean.getMemoryPoolNames();
+            if (names == null) {
+                throw new RuntimeException("getMemoryPoolNames() is null");
+            }
+            if (names.length == 0) {
+                throw new RuntimeException("getMemoryPoolNames() is empty");
+            }
+            for (String name : names) {
+                if (name == null) {
+                    throw new RuntimeException("pool name is null");
+                }
+                if (name.length() == 0) {
+                    throw new RuntimeException("pool name is empty");
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestObjects.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestObjects
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon is able to allocate objects, and does not corrupt their state
+ *
+ * @run main/othervm -Xmx128m                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:-TieredCompilation  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ *
+ * @run main/othervm -Xmx128m                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:-TieredCompilation  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestObjects
+ */
+
+import java.util.Random;
+
+public class TestObjects {
+
+  static long SEED = Long.getLong("seed", System.nanoTime());
+  static int COUNT = Integer.getInteger("count", 1_000_000); // ~24 MB allocation
+
+  static MyObject[] arr;
+
+  public static void main(String[] args) throws Exception {
+    Random r = new Random(SEED);
+
+    arr = new MyObject[COUNT];
+    for (int c = 0; c < COUNT; c++) {
+      arr[c] = new MyObject(r.nextInt());
+    }
+
+    r = new Random(SEED);
+    for (int c = 0; c < COUNT; c++) {
+      int expected = r.nextInt();
+      int actual = arr[c].id();
+      if (expected != actual) {
+        throw new IllegalStateException("Failure: expected = " + expected + ", actual = " + actual);
+      }
+    }
+  }
+
+  public static class MyObject {
+    int id;
+    public MyObject(int id) {
+      this.id = id;
+    }
+    public int id() {
+      return id;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestPrintHeapSteps.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestPrintSteps
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Tests -XX:EpsilonPrintHeapSteps works
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonPrintHeapSteps=0    TestPrintHeapSteps
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonPrintHeapSteps=1    TestPrintHeapSteps
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonPrintHeapSteps=1000 TestPrintHeapSteps
+ */
+
+public class TestPrintHeapSteps {
+  public static void main(String[] args) throws Exception {
+    System.out.println("Hello World");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestRefArrays.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestRefArrays
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Epsilon is able to allocate arrays, and does not corrupt their state
+ * @library /test/lib
+ *
+ * @run main/othervm -Xmx1g                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:-TieredCompilation  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ *
+ * @run main/othervm -Xmx1g                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:-TieredCompilation  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC TestRefArrays
+ */
+
+import java.util.Random;
+
+public class TestRefArrays {
+
+  static long SEED = Long.getLong("seed", System.nanoTime());
+  static int COUNT = Integer.getInteger("count", 1000); // ~500 MB allocation
+
+  static MyObject[][] arr;
+
+  public static void main(String[] args) throws Exception {
+    Random r = new Random(SEED);
+
+    arr = new MyObject[COUNT * 100][];
+    for (int c = 0; c < COUNT; c++) {
+      arr[c] = new MyObject[c * 100];
+      for (int v = 0; v < c; v++) {
+        arr[c][v] = new MyObject(r.nextInt());
+      }
+    }
+
+    r = new Random(SEED);
+    for (int c = 0; c < COUNT; c++) {
+      MyObject[] b = arr[c];
+      if (b.length != (c * 100)) {
+        throw new IllegalStateException("Failure: length = " + b.length + ", need = " + (c*100));
+      }
+      for (int v = 0; v < c; v++) {
+        int actual = b[v].id();
+        int expected = r.nextInt();
+        if (actual != expected) {
+          throw new IllegalStateException("Failure: expected = " + expected + ", actual = " + actual);
+        }
+      }
+    }
+  }
+
+  public static class MyObject {
+    int id;
+    public MyObject(int id) {
+      this.id = id;
+    }
+    public int id() {
+      return id;
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestUpdateCountersSteps.java	Tue Jun 12 14:25:13 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, 2018, Red Hat, Inc. 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.
+ */
+
+/**
+ * @test TestUpdateCountersSteps
+ * @key gc
+ * @requires vm.gc.Epsilon
+ * @summary Test EpsilonUpdateCountersStep works
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonUpdateCountersStep=1    TestUpdateCountersSteps
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonUpdateCountersStep=10   TestUpdateCountersSteps
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonUpdateCountersStep=100  TestUpdateCountersSteps
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -XX:EpsilonUpdateCountersStep=1000 TestUpdateCountersSteps
+ */
+
+public class TestUpdateCountersSteps {
+  public static void main(String[] args) throws Exception {
+    System.out.println("Hello World");
+  }
+}
--- a/test/hotspot/jtreg/serviceability/sa/TestUniverse.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/TestUniverse.java	Tue Jun 12 14:25:13 2018 +0200
@@ -106,13 +106,19 @@
             output.shouldContain("PSYoungGen");
             output.shouldContain("eden");
         }
-
+        if (gc.contains("UseEpsilonGC")) {
+            output.shouldContain("Epsilon heap");
+            output.shouldContain("reserved");
+            output.shouldContain("committed");
+            output.shouldContain("used");
+        }
     }
 
     public static void test(String gc) throws Exception {
         LingeredApp app = null;
         try {
             List<String> vmArgs = new ArrayList<String>();
+            vmArgs.add("-XX:+UnlockExperimentalVMOptions"); // unlock experimental GCs
             vmArgs.add(gc);
             app = LingeredApp.startApp(vmArgs);
             System.out.println ("Started LingeredApp with the GC option " + gc +
@@ -139,6 +145,7 @@
             if (!Compiler.isGraalEnabled()) { // Graal does not support CMS
               test("-XX:+UseConcMarkSweepGC");
             }
+            test("-XX:+UseEpsilonGC");
         } catch (Exception e) {
             throw new Error("Test failed with " + e);
         }
--- a/test/lib/sun/hotspot/gc/GC.java	Tue Jun 12 11:11:59 2018 +0000
+++ b/test/lib/sun/hotspot/gc/GC.java	Tue Jun 12 14:25:13 2018 +0200
@@ -36,7 +36,8 @@
     Serial(1),
     Parallel(2),
     ConcMarkSweep(3),
-    G1(4);
+    G1(4),
+    Epsilon(5);
 
     private static final WhiteBox WB = WhiteBox.getWhiteBox();