Initial import of Epsilon sources from jdk10/sandbox epsilon-gc-branch
authorshade
Mon, 06 Nov 2017 18:53:38 +0100
branchepsilon-gc-branch
changeset 55767 8e22715afabc
parent 47701 be620a591379
child 55778 a977fcca316b
Initial import of Epsilon sources from jdk10/sandbox
src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
src/hotspot/cpu/aarch64/templateTable_aarch64.cpp
src/hotspot/cpu/arm/stubGenerator_arm.cpp
src/hotspot/cpu/arm/templateTable_arm.cpp
src/hotspot/cpu/ppc/stubGenerator_ppc.cpp
src/hotspot/cpu/ppc/templateTable_ppc_64.cpp
src/hotspot/cpu/s390/stubGenerator_s390.cpp
src/hotspot/cpu/s390/templateTable_s390.cpp
src/hotspot/cpu/sparc/stubGenerator_sparc.cpp
src/hotspot/cpu/sparc/templateTable_sparc.cpp
src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
src/hotspot/cpu/x86/stubGenerator_x86_32.cpp
src/hotspot/cpu/x86/stubGenerator_x86_64.cpp
src/hotspot/cpu/x86/templateTable_x86.cpp
src/hotspot/share/c1/c1_LIRGenerator.cpp
src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp
src/hotspot/share/gc/epsilon/epsilonCollectedHeap.cpp
src/hotspot/share/gc/epsilon/epsilonCollectedHeap.hpp
src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp
src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp
src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.hpp
src/hotspot/share/gc/epsilon/epsilon_globals.cpp
src/hotspot/share/gc/epsilon/epsilon_globals.hpp
src/hotspot/share/gc/shared/barrierSet.hpp
src/hotspot/share/gc/shared/collectedHeap.hpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/opto/graphKit.cpp
src/hotspot/share/precompiled/precompiled.hpp
src/hotspot/share/runtime/arguments.cpp
src/hotspot/share/runtime/arguments.hpp
src/hotspot/share/runtime/commandLineFlagConstraintList.cpp
src/hotspot/share/runtime/commandLineFlagRangeList.cpp
src/hotspot/share/runtime/commandLineFlagWriteableList.cpp
src/hotspot/share/runtime/globals.cpp
src/hotspot/share/runtime/globals.hpp
src/hotspot/share/runtime/globals_extension.hpp
src/hotspot/share/services/epsilonMemoryPool.cpp
src/hotspot/share/services/epsilonMemoryPool.hpp
src/hotspot/share/services/memoryManager.cpp
src/hotspot/share/services/memoryManager.hpp
src/hotspot/share/services/memoryService.cpp
src/hotspot/share/services/memoryService.hpp
src/hotspot/share/utilities/vmError.cpp
test/hotspot/jtreg/TEST.groups
test/hotspot/jtreg/gc/epsilon/AbstractEpsilonTest.java
test/hotspot/jtreg/gc/epsilon/TestAlwaysPretouch.java
test/hotspot/jtreg/gc/epsilon/TestByteArrays.java
test/hotspot/jtreg/gc/epsilon/TestDieDefault.java
test/hotspot/jtreg/gc/epsilon/TestDieWithHeapDump.java
test/hotspot/jtreg/gc/epsilon/TestDieWithOnError.java
test/hotspot/jtreg/gc/epsilon/TestEpsilonEnabled.java
test/hotspot/jtreg/gc/epsilon/TestHelloWorld.java
test/hotspot/jtreg/gc/epsilon/TestLogTrace.java
test/hotspot/jtreg/gc/epsilon/TestManyThreads.java
test/hotspot/jtreg/gc/epsilon/TestMemoryMXBeans.java
test/hotspot/jtreg/gc/epsilon/TestMemoryPools.java
test/hotspot/jtreg/gc/epsilon/TestObjects.java
test/hotspot/jtreg/gc/epsilon/TestRefArrays.java
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -655,6 +655,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
@@ -719,6 +720,9 @@
           __ br(Assembler::GE, L_loop);
         }
         break;
+      case BarrierSet::Epsilon:
+        // No barriers.
+        break;
       default:
         ShouldNotReachHere();
 
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -202,6 +202,7 @@
       }
       break;
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       if (val == noreg) {
         __ store_heap_oop_null(obj);
       } else {
--- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -2990,6 +2990,7 @@
       }
       break;
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       break;
     default:
       ShouldNotReachHere();
--- a/src/hotspot/cpu/arm/templateTable_arm.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/arm/templateTable_arm.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -244,6 +244,14 @@
         }
       }
       break;
+    case BarrierSet::Epsilon:
+      if (is_null) {
+        __ store_heap_oop_null(new_val, obj);
+      } else {
+        __ store_heap_oop(new_val, obj); // blows new_val:
+        new_val = noreg;
+      }
+      break;
     case BarrierSet::ModRef:
       ShouldNotReachHere();
       break;
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -666,6 +666,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
@@ -734,6 +735,7 @@
         }
       break;
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -139,6 +139,9 @@
         __ bind(Ldone);
       }
       break;
+    case BarrierSet::Epsilon:
+      Unimplemented(); // Should look like CardTableForRS without card mark?
+      break;
     case BarrierSet::ModRef:
       ShouldNotReachHere();
       break;
--- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -725,6 +725,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
@@ -859,6 +860,7 @@
         }
         break;
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         if (!branchToEnd) { __ z_br(Z_R14); }
         break;
       default:
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -275,6 +275,13 @@
       }
     }
     break;
+  case BarrierSet::Epsilon:
+    if (val_is_null) {
+      __ store_heap_oop_null(val, offset, base);
+    } else {
+      __ store_heap_oop(val, offset, base);
+    }
+    break;
   case BarrierSet::ModRef:
     // fall through
   default:
--- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -861,6 +861,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
@@ -917,6 +918,7 @@
         }
         break;
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
--- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -112,6 +112,14 @@
         }
       }
       break;
+    case BarrierSet::Epsilon:
+      if (index == noreg) {
+        assert(Assembler::is_simm13(offset), "fix this code");
+        __ store_heap_oop(val, base, offset);
+      } else {
+        __ store_heap_oop(val, base, index);
+      }
+      break;
     case BarrierSet::ModRef:
       ShouldNotReachHere();
       break;
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1675,16 +1675,23 @@
 
     case g1_post_barrier_slow_id:
       {
+        BarrierSet* bs = Universe::heap()->barrier_set();
+        if (bs->kind() != BarrierSet::G1SATBCT &&
+            bs->kind() != BarrierSet::G1SATBCTLogging) {
+          __ movptr(rax, (int)id);
+          __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);
+          __ should_not_reach_here();
+          break;
+        }
+
+        CardTableModRefBS* ct = barrier_set_cast<CardTableModRefBS>(bs);
+        assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
+
         StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
 
-
         // arg0: store_address
         Address store_addr(rbp, 2*BytesPerWord);
 
-        CardTableModRefBS* ct =
-          barrier_set_cast<CardTableModRefBS>(Universe::heap()->barrier_set());
-        assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
-
         Label done;
         Label enqueued;
         Label runtime;
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -688,6 +688,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default      :
         ShouldNotReachHere();
@@ -740,6 +741,7 @@
         }
         break;
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default      :
         ShouldNotReachHere();
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1221,6 +1221,7 @@
       case BarrierSet::CardTableForRS:
       case BarrierSet::CardTableExtension:
       case BarrierSet::ModRef:
+      case BarrierSet::Epsilon:
         break;
       default:
         ShouldNotReachHere();
@@ -1282,6 +1283,9 @@
           __ jcc(Assembler::greaterEqual, L_loop);
         }
         break;
+      case BarrierSet::Epsilon:
+        // No barriers
+        break;
       default:
         ShouldNotReachHere();
 
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -216,6 +216,7 @@
       }
       break;
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       if (val == noreg) {
         __ store_heap_oop_null(obj);
       } else {
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1466,6 +1466,7 @@
       // No pre barriers
       break;
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       // No pre barriers
       break;
     default      :
@@ -1486,6 +1487,7 @@
       CardTableModRef_post_barrier(addr,  new_val);
       break;
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       // No post barriers
       break;
     default      :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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/collectorPolicy.hpp"
+#include "gc/shared/barrierSet.hpp"
+
+// Most are no-ops.
+class EpsilonBarrierSet: public ModRefBarrierSet {
+  friend class VMStructs;
+
+public:
+  EpsilonBarrierSet() :
+          ModRefBarrierSet(BarrierSet::FakeRtti(BarrierSet::Epsilon)) {};
+
+  virtual bool has_write_ref_barrier()     { return false; }
+  virtual bool has_write_ref_pre_barrier() { return false; }
+  virtual bool has_write_ref_array_opt()   { return true;  } // claim we have these, and then do noop
+  virtual bool has_write_region_opt()      { return true;  } // claim we have these, and then do noop
+
+  virtual bool is_aligned(HeapWord *addr)  { Unimplemented(); return true; } // no calls for it?
+
+  virtual void resize_covered_region(MemRegion new_region) {}
+  virtual void print_on(outputStream *st) const {}
+
+protected:
+  virtual void write_ref_field_work(void *field, oop new_val, bool release) {}
+  virtual void write_ref_array_work(MemRegion mr) {}
+  virtual void write_region_work(MemRegion mr) {}
+
+public:
+  virtual void invalidate(MemRegion mr) {}
+  virtual void clear(MemRegion mr) {}
+};
+
+template<>
+struct BarrierSet::GetName<EpsilonBarrierSet> {
+  static const BarrierSet::Name value = BarrierSet::Epsilon;
+};
+
+#endif // SHARE_VM_GC_EPSILON_BARRIERSET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonCollectedHeap.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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 "oops/oop.hpp"
+#include "oops/oop.inline.hpp"
+#include "gc/epsilon/epsilonCollectedHeap.hpp"
+
+jint EpsilonCollectedHeap::initialize() {
+  CollectedHeap::pre_initialize();
+
+  size_t init_byte_size = _policy->initial_heap_byte_size();
+  size_t max_byte_size = _policy->max_heap_byte_size();
+  size_t align = _policy->heap_alignment();
+
+  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, true, true);
+
+  EpsilonBarrierSet* bs = new EpsilonBarrierSet();
+  set_barrier_set(bs);
+
+  _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize);
+
+  _monitoring_support = new EpsilonMonitoringSupport(this);
+  _last_counter_update = 0;
+
+  if (init_byte_size != max_byte_size) {
+    log_info(gc)("Initialized with " SIZE_FORMAT "M heap, resizeable to up to " SIZE_FORMAT "M heap with " SIZE_FORMAT "M steps",
+                 init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M);
+  } else {
+    log_info(gc)("Initialized with " SIZE_FORMAT "M non-resizeable heap", init_byte_size / M);
+  }
+  if (UseTLAB) {
+    log_info(gc)("Using TLAB allocation; min: " SIZE_FORMAT "K, max: " SIZE_FORMAT "K",
+                                ThreadLocalAllocBuffer::min_size()*HeapWordSize / K,
+                                _max_tlab_size*HeapWordSize / K);
+  } else {
+    log_info(gc)("Not using TLAB allocation");
+  }
+
+  return JNI_OK;
+}
+
+size_t EpsilonCollectedHeap::unsafe_max_tlab_alloc(Thread *thr) const {
+  // This is the only way we can control TLAB sizes without having safepoints.
+  // Implement exponential expansion within [MinTLABSize; _max_tlab_size], based
+  // on previously "used" TLAB size.
+
+  size_t size = MIN2(_max_tlab_size * HeapWordSize, MAX2(MinTLABSize, thr->tlab().used() * HeapWordSize * 2));
+
+  if (log_is_enabled(Trace, gc)) {
+    ResourceMark rm;
+    log_trace(gc)(
+            "Selecting TLAB size for \"%s\" (Desired: " SIZE_FORMAT "K, Used: " SIZE_FORMAT "K) -> " SIZE_FORMAT "K",
+            Thread::current()->name(),
+            thr->tlab().desired_size() * HeapWordSize / K,
+            thr->tlab().used() * HeapWordSize / K,
+            size / K);
+  }
+
+  return size;
+}
+
+EpsilonCollectedHeap* EpsilonCollectedHeap::heap() {
+  CollectedHeap* heap = Universe::heap();
+  assert(heap != NULL, "Uninitialized access to EpsilonCollectedHeap::heap()");
+  assert(heap->kind() == CollectedHeap::EpsilonCollectedHeap, "Not a EpsilonCollectedHeap");
+  return (EpsilonCollectedHeap*)heap;
+}
+
+HeapWord* EpsilonCollectedHeap::allocate_work(size_t size) {
+  HeapWord* res = _space->par_allocate(size);
+
+  while (res == NULL) {
+    // Allocation failed, attempt expansion, and retry:
+    MutexLockerEx ml(Heap_lock);
+    if (!_virtual_space.expand_by(MAX2(size, EpsilonMinHeapExpand))) {
+      return NULL;
+    }
+    _space->set_end((HeapWord *) _virtual_space.high());
+    res = _space->par_allocate(size);
+  }
+
+  size_t used = _space->used();
+  if (used - _last_counter_update >= 1024 * 1024) {
+    _last_counter_update = used;
+    _monitoring_support->update_counters();
+  }
+  return res;
+}
+
+HeapWord* EpsilonCollectedHeap::allocate_new_tlab(size_t size) {
+  return allocate_work(size);
+}
+
+HeapWord* EpsilonCollectedHeap::mem_allocate(size_t size, bool *gc_overhead_limit_was_exceeded) {
+  *gc_overhead_limit_was_exceeded = false;
+  return allocate_work(size);
+}
+
+void EpsilonCollectedHeap::collect(GCCause::Cause cause) {
+  log_info(gc)("GC was triggered with cause \"%s\". Ignoring.", GCCause::to_string(cause));
+  _monitoring_support->update_counters();
+}
+
+void EpsilonCollectedHeap::do_full_collection(bool clear_all_soft_refs) {
+  log_info(gc)("Full GC was triggered with cause \"%s\". Ignoring.", GCCause::to_string(gc_cause()));
+  _monitoring_support->update_counters();
+}
+
+void EpsilonCollectedHeap::safe_object_iterate(ObjectClosure *cl) {
+  _space->safe_object_iterate(cl);
+}
+
+void EpsilonCollectedHeap::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 EpsilonCollectedHeap::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",
+           allocated_kb * NANOSECS_PER_SEC / os::elapsed_counter());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonCollectedHeap.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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/space.hpp"
+#include "gc/epsilon/epsilonCollectorPolicy.hpp"
+#include "gc/epsilon/epsilonMonitoringSupport.hpp"
+#include "gc/epsilon/epsilonBarrierSet.hpp"
+#include "gc/epsilon/epsilon_globals.hpp"
+
+class EpsilonCollectedHeap : public CollectedHeap {
+private:
+  EpsilonCollectorPolicy* _policy;
+  EpsilonMonitoringSupport* _monitoring_support;
+  ContiguousSpace* _space;
+  VirtualSpace _virtual_space;
+  size_t _max_tlab_size;
+  size_t _last_counter_update;
+public:
+  EpsilonCollectedHeap(EpsilonCollectorPolicy* p) : _policy(p) {};
+
+  virtual Name kind() const {
+    return CollectedHeap::EpsilonCollectedHeap;
+  }
+
+  virtual const char *name() const {
+    return "Epsilon GC";
+  }
+
+  virtual jint initialize();
+
+  virtual void post_initialize() {}
+
+  static EpsilonCollectedHeap* heap();
+
+  virtual size_t capacity()     const { return _virtual_space.committed_size(); }
+  virtual size_t used()         const { return _space->used(); }
+  virtual size_t max_capacity() const { return _virtual_space.reserved_size(); }
+
+  virtual bool is_maximal_no_gc() const {
+    // No GC is going to happen, unless we are at capacity.
+    // At which point we will fail anyway.
+    return used() == capacity();
+  }
+
+  virtual bool is_in(const void *p) const { return _space->is_in(p); }
+
+  virtual bool is_scavengable(oop obj) {
+    // Epsilon does not move objects, no objects are scavengable.
+    return false;
+  }
+
+  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 size);
+
+  // TLAB allocations
+  virtual bool supports_tlab_allocation()           const { return UseTLAB; }
+  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 bool can_elide_tlab_store_barriers() const {
+    // No store barriers for Epsilon, allow elision
+    return true;
+  }
+
+  virtual bool can_elide_initializing_store_barrier(oop new_obj) {
+    // No card marks for Epsilon, can elide them all.
+    return true;
+  }
+
+  virtual bool card_mark_must_follow_store() const {
+    // No card marks for Epsilon.
+    return false;
+  }
+
+  virtual void collect(GCCause::Cause cause);
+  virtual void do_full_collection(bool clear_all_soft_refs);
+
+  virtual AdaptiveSizePolicy *size_policy() {
+    // No such thing for Epsilon
+    return NULL;
+  }
+
+  virtual CollectorPolicy *collector_policy() const {
+    return _policy;
+  }
+
+  virtual void object_iterate(ObjectClosure *cl) {
+    safe_object_iterate(cl);
+  }
+
+  virtual void safe_object_iterate(ObjectClosure *cl);
+
+  virtual HeapWord* block_start(const void *addr) const {
+    // Epsilon does not support block parsing.
+    return NULL;
+  }
+
+  virtual size_t block_size(const HeapWord *addr) const {
+    // Epsilon does not support block parsing.
+    return 0;
+  }
+
+  virtual bool block_is_obj(const HeapWord *addr) const {
+    // Epsilon does not support block parsing.
+    return false;
+  }
+
+  virtual jlong millis_since_last_gc() {
+    // Report time since the VM start
+    return os::elapsed_counter() / NANOSECS_PER_MILLISEC;
+  }
+
+  virtual void prepare_for_verify() {
+    // No heap verification.
+  }
+
+  virtual void print_gc_threads_on(outputStream *st) const {
+    // No GC threads.
+  }
+
+  virtual void gc_threads_do(ThreadClosure *tc) const {
+    // No GC threads.
+  }
+
+  virtual void print_on(outputStream *st) const;
+  virtual void print_tracing_info() const;
+
+  virtual void verify(VerifyOption option) {
+    // No heap verification for Epsilon.
+  }
+
+};
+
+#endif // SHARE_VM_GC_EPSILON_COLLECTEDHEAP_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonCollectorPolicy.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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();
+    _space_alignment = page_size;
+    _heap_alignment = page_size;
+  }
+
+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/epsilonMonitoringSupport.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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 "services/memoryService.hpp"
+#include "gc/shared/generationCounters.hpp"
+#include "gc/epsilon/epsilonMonitoringSupport.hpp"
+#include "gc/epsilon/epsilonCollectedHeap.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 EpsilonYoungGenerationCounters : public GenerationCounters {
+public:
+  EpsilonYoungGenerationCounters() :
+          GenerationCounters("Young", 0, 0, 0, (size_t)0, (size_t)0) {};
+
+  virtual void update_all() {
+    // no update
+  }
+};
+
+class EpsilonGenerationCounters : public GenerationCounters {
+private:
+  EpsilonCollectedHeap* _heap;
+public:
+  EpsilonGenerationCounters(EpsilonCollectedHeap* 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(EpsilonCollectedHeap* heap) {
+  // We report young gen as unused.
+  _young_counters = new EpsilonYoungGenerationCounters();
+  _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) {
+    EpsilonCollectedHeap* heap = EpsilonCollectedHeap::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();
+  }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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 EpsilonCollectedHeap;
+
+class EpsilonMonitoringSupport : public CHeapObj<mtGC> {
+private:
+  GenerationCounters* _young_counters;
+  GenerationCounters* _heap_counters;
+  EpsilonSpaceCounters* _space_counters;
+
+public:
+  EpsilonMonitoringSupport(EpsilonCollectedHeap* heap);
+  void update_counters();
+};
+
+#endif // SHARE_VM_GC_EPSILON_EPSILONMONITORINGSUPPORT_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilon_globals.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/epsilon/epsilon_globals.hpp"
+
+EPSILON_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+         MATERIALIZE_PD_DEVELOPER_FLAG, \
+         MATERIALIZE_PRODUCT_FLAG, \
+         MATERIALIZE_PD_PRODUCT_FLAG,     \
+         MATERIALIZE_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_PD_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_EXPERIMENTAL_FLAG, \
+         MATERIALIZE_NOTPRODUCT_FLAG,  \
+         MATERIALIZE_MANAGEABLE_FLAG, \
+         MATERIALIZE_PRODUCT_RW_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT, \
+         IGNORE_WRITEABLE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/epsilon/epsilon_globals.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ *
+ */
+
+#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 EPSILON_FLAGS(develop, \
+                 develop_pd, \
+                 product, \
+                 product_pd, \
+                 diagnostic, \
+                 diagnostic_pd, \
+                 experimental, \
+                 notproduct, \
+                 manageable, \
+                 product_rw, \
+                 range, \
+                 constraint, \
+                 writeable) \
+                                                                            \
+  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(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)
+
+EPSILON_FLAGS(DECLARE_DEVELOPER_FLAG, \
+         DECLARE_PD_DEVELOPER_FLAG, \
+         DECLARE_PRODUCT_FLAG, \
+         DECLARE_PD_PRODUCT_FLAG, \
+         DECLARE_DIAGNOSTIC_FLAG, \
+         DECLARE_PD_DIAGNOSTIC_FLAG, \
+         DECLARE_EXPERIMENTAL_FLAG, \
+         DECLARE_NOTPRODUCT_FLAG, \
+         DECLARE_MANAGEABLE_FLAG, \
+         DECLARE_PRODUCT_RW_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT, \
+         IGNORE_WRITEABLE)
+
+#endif // SHARE_VM_GC_EPSILON_GLOBALS_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -52,7 +52,8 @@
     CardTableForRS,             // CardTableModRefBSForCTRS
     CardTableExtension,         // CardTableExtension
     G1SATBCT,                   // G1SATBCardTableModRefBS
-    G1SATBCTLogging             // G1SATBCardTableLoggingModRefBS
+    G1SATBCTLogging,            // G1SATBCardTableLoggingModRefBS
+    Epsilon,                    // EpsilonBarrierSet
   };
 
 protected:
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -196,7 +196,8 @@
     GenCollectedHeap,
     ParallelScavengeHeap,
     G1CollectedHeap,
-    CMSHeap
+    CMSHeap,
+    EpsilonCollectedHeap,
   };
 
   static inline size_t filler_array_max_size() {
--- a/src/hotspot/share/memory/universe.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/memory/universe.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -88,6 +88,8 @@
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
 #include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/epsilon/epsilonCollectedHeap.hpp"
+#include "gc/epsilon/epsilonCollectorPolicy.hpp"
 #include "gc/shared/adaptiveSizePolicy.hpp"
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_CDS
@@ -753,6 +755,8 @@
     fatal("UseG1GC not supported in this VM.");
   } else if (UseConcMarkSweepGC) {
     fatal("UseConcMarkSweepGC not supported in this VM.");
+  } else if (UseEpsilonGC) {
+    fatal("UseEpsilonGC not supported in this VM.");
 #else
   if (UseParallelGC) {
     return Universe::create_heap_with_policy<ParallelScavengeHeap, GenerationSizer>();
@@ -760,6 +764,8 @@
     return Universe::create_heap_with_policy<G1CollectedHeap, G1CollectorPolicy>();
   } else if (UseConcMarkSweepGC) {
     return Universe::create_heap_with_policy<CMSHeap, ConcurrentMarkSweepPolicy>();
+  } else if (UseEpsilonGC) {
+    return Universe::create_heap_with_policy<EpsilonCollectedHeap, EpsilonCollectorPolicy>();
 #endif
   } else if (UseSerialGC) {
     return Universe::create_heap_with_policy<GenCollectedHeap, MarkSweepPolicy>();
--- a/src/hotspot/share/opto/graphKit.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/opto/graphKit.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1565,6 +1565,7 @@
     case BarrierSet::CardTableForRS:
     case BarrierSet::CardTableExtension:
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       break;
 
     default      :
@@ -1582,6 +1583,7 @@
     case BarrierSet::CardTableForRS:
     case BarrierSet::CardTableExtension:
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       return true; // There is no pre-barrier
 
     default      :
@@ -1611,6 +1613,7 @@
       break;
 
     case BarrierSet::ModRef:
+    case BarrierSet::Epsilon:
       break;
 
     default      :
--- a/src/hotspot/share/precompiled/precompiled.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/precompiled/precompiled.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -299,6 +299,7 @@
 # include "gc/cms/parOopClosures.hpp"
 # include "gc/cms/promotionInfo.hpp"
 # include "gc/cms/yieldingWorkgroup.hpp"
+# include "gc/epsilon/epsilon_globals.hpp"
 # include "gc/g1/dirtyCardQueue.hpp"
 # include "gc/g1/g1BlockOffsetTable.hpp"
 # include "gc/g1/g1OopClosures.hpp"
--- a/src/hotspot/share/runtime/arguments.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/arguments.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1768,7 +1768,7 @@
 
 bool Arguments::gc_selected() {
 #if INCLUDE_ALL_GCS
-  return UseSerialGC || UseParallelGC || UseParallelOldGC || UseConcMarkSweepGC || UseG1GC;
+  return UseSerialGC || UseParallelGC || UseParallelOldGC || UseConcMarkSweepGC || UseG1GC || UseEpsilonGC;
 #else
   return UseSerialGC;
 #endif // INCLUDE_ALL_GCS
@@ -1997,6 +1997,22 @@
   log_trace(gc)("MarkStackSize: %uk  MarkStackSizeMax: %uk", (unsigned int) (MarkStackSize / K), (uint) (MarkStackSizeMax / K));
 }
 
+void Arguments::set_epsilon_flags() {
+  assert(UseEpsilonGC, "Error");
+
+  // Forcefully exit when OOME is detected. Nothing we can do at that point.
+  if (FLAG_IS_DEFAULT(ExitOnOutOfMemoryError)) {
+    FLAG_SET_DEFAULT(ExitOnOutOfMemoryError, true);
+  }
+
+#if INCLUDE_ALL_GCS
+  if (EpsilonMaxTLABSize < MinTLABSize) {
+    warning("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
+    EpsilonMaxTLABSize = MinTLABSize;
+  }
+#endif
+}
+
 void Arguments::set_gc_specific_flags() {
 #if INCLUDE_ALL_GCS
   // Set per-collector flags
@@ -2006,6 +2022,8 @@
     set_cms_and_parnew_gc_flags();
   } else if (UseG1GC) {
     set_g1_gc_flags();
+  } else if (UseEpsilonGC) {
+    set_epsilon_flags();
   }
   if (AssumeMP && !UseSerialGC) {
     if (FLAG_IS_DEFAULT(ParallelGCThreads) && ParallelGCThreads == 1) {
@@ -2380,6 +2398,7 @@
   if (UseConcMarkSweepGC)                i++;
   if (UseParallelGC || UseParallelOldGC) i++;
   if (UseG1GC)                           i++;
+  if (UseEpsilonGC)                      i++;
   if (i > 1) {
     jio_fprintf(defaultStream::error_stream(),
                 "Conflicting collector combinations in option list; "
--- a/src/hotspot/share/runtime/arguments.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/arguments.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -468,6 +468,8 @@
   static void set_parallel_gc_flags();
   // Garbage-First (UseG1GC)
   static void set_g1_gc_flags();
+  // Epsilon
+  static void set_epsilon_flags();
   // GC ergonomics
   static void set_conservative_max_heap_alignment();
   static void set_use_compressed_oops();
--- a/src/hotspot/share/runtime/commandLineFlagConstraintList.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/commandLineFlagConstraintList.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -348,6 +348,19 @@
                                    IGNORE_RANGE,
                                    EMIT_CONSTRAINT_CHECK,
                                    IGNORE_WRITEABLE));
+  emit_constraint_no(NULL EPSILON_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_MANAGEABLE_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
+                                   IGNORE_RANGE,
+                                   EMIT_CONSTRAINT_CHECK,
+                                   IGNORE_WRITEABLE));
 #endif // INCLUDE_ALL_GCS
 }
 
--- a/src/hotspot/share/runtime/commandLineFlagRangeList.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/commandLineFlagRangeList.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -416,6 +416,19 @@
                               EMIT_RANGE_CHECK,
                               IGNORE_CONSTRAINT,
                               IGNORE_WRITEABLE));
+  emit_range_no(NULL EPSILON_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                              EMIT_RANGE_PD_DEVELOPER_FLAG,
+                              EMIT_RANGE_PRODUCT_FLAG,
+                              EMIT_RANGE_PD_PRODUCT_FLAG,
+                              EMIT_RANGE_DIAGNOSTIC_FLAG,
+                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
+                              EMIT_RANGE_EXPERIMENTAL_FLAG,
+                              EMIT_RANGE_NOTPRODUCT_FLAG,
+                              EMIT_RANGE_MANAGEABLE_FLAG,
+                              EMIT_RANGE_PRODUCT_RW_FLAG,
+                              EMIT_RANGE_CHECK,
+                              IGNORE_CONSTRAINT,
+                              IGNORE_WRITEABLE));
 #endif // INCLUDE_ALL_GCS
 }
 
--- a/src/hotspot/share/runtime/commandLineFlagWriteableList.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/commandLineFlagWriteableList.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -203,6 +203,19 @@
                               IGNORE_RANGE,
                               IGNORE_CONSTRAINT,
                               EMIT_WRITEABLE));
+  emit_writeable_no(NULL EPSILON_FLAGS(EMIT_WRITEABLE_DEVELOPER_FLAG,
+                              EMIT_WRITEABLE_PD_DEVELOPER_FLAG,
+                              EMIT_WRITEABLE_PRODUCT_FLAG,
+                              EMIT_WRITEABLE_PD_PRODUCT_FLAG,
+                              EMIT_WRITEABLE_DIAGNOSTIC_FLAG,
+                              EMIT_WRITEABLE_PD_DIAGNOSTIC_FLAG,
+                              EMIT_WRITEABLE_EXPERIMENTAL_FLAG,
+                              EMIT_WRITEABLE_NOTPRODUCT_FLAG,
+                              EMIT_WRITEABLE_MANAGEABLE_FLAG,
+                              EMIT_WRITEABLE_PRODUCT_RW_FLAG,
+                              IGNORE_RANGE,
+                              IGNORE_CONSTRAINT,
+                              EMIT_WRITEABLE));
 #endif // INCLUDE_ALL_GCS
 }
 
--- a/src/hotspot/share/runtime/globals.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/globals.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -40,6 +40,7 @@
 #include "utilities/ostream.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1_globals.hpp"
+#include "gc/epsilon/epsilon_globals.hpp"
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
@@ -789,6 +790,19 @@
           IGNORE_RANGE, \
           IGNORE_CONSTRAINT, \
           IGNORE_WRITEABLE)
+ EPSILON_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
+          RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
+          RUNTIME_PRODUCT_FLAG_STRUCT, \
+          RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
+          RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
+          RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
+          RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
+          RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
+          RUNTIME_MANAGEABLE_FLAG_STRUCT, \
+          RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT, \
+          IGNORE_WRITEABLE)
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
--- a/src/hotspot/share/runtime/globals.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/globals.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -1411,6 +1411,9 @@
   product(bool, UseParallelOldGC, false,                                    \
           "Use the Parallel Old garbage collector")                         \
                                                                             \
+  develop(bool, UseEpsilonGC, false,                                        \
+          "Use the Epsilon (no-op) garbage collector")                      \
+                                                                            \
   product(uintx, HeapMaximumCompactionInterval, 20,                         \
           "How often should we maximally compact the heap (not allowing "   \
           "any dead space)")                                                \
--- a/src/hotspot/share/runtime/globals_extension.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/runtime/globals_extension.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -30,6 +30,7 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1_globals.hpp"
+#include "gc/epsilon/epsilon_globals.hpp"
 #endif
 #if INCLUDE_JVMCI
 #include "jvmci/jvmci_globals.hpp"
@@ -134,6 +135,19 @@
           IGNORE_RANGE, \
           IGNORE_CONSTRAINT, \
           IGNORE_WRITEABLE)
+ EPSILON_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
+          RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER, \
+          RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
+          RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
+          RUNTIME_MANAGEABLE_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT, \
+          IGNORE_WRITEABLE)
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER, \
@@ -277,6 +291,19 @@
           IGNORE_RANGE,
           IGNORE_CONSTRAINT,
           IGNORE_WRITEABLE)
+ EPSILON_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
+          RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
+          IGNORE_RANGE,
+          IGNORE_CONSTRAINT,
+          IGNORE_WRITEABLE)
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/services/epsilonMemoryPool.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/epsilon/epsilonCollectedHeap.hpp"
+#include "services/epsilonMemoryPool.hpp"
+
+EpsilonDummyMemoryPool::EpsilonDummyMemoryPool() :
+        CollectedMemoryPool("Epsilon Dummy",
+                            MemoryPool::Heap,
+                            0,
+                            0,
+                            false /* support_usage_threshold */) {}
+
+EpsilonMemoryPool::EpsilonMemoryPool(EpsilonCollectedHeap* heap) :
+        _heap(heap),
+        CollectedMemoryPool("Epsilon Heap",
+                            MemoryPool::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/services/epsilonMemoryPool.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * 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_SERVICES_EPSILON_COLLECTORPOLICY_HPP
+#define SHARE_VM_SERVICES_EPSILON_COLLECTORPOLICY_HPP
+
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/epsilon/epsilonCollectedHeap.hpp"
+#include "services/memoryPool.hpp"
+#include "services/memoryUsage.hpp"
+#endif // INCLUDE_ALL_GCS
+
+class EpsilonDummyMemoryPool : public CollectedMemoryPool {
+public:
+  EpsilonDummyMemoryPool();
+  MemoryUsage get_memory_usage()      { return MemoryUsage(0, 0, 0, 0); }
+  size_t used_in_bytes()              { return 0; }
+  size_t max_size() const             { return 0; }
+};
+
+class EpsilonMemoryPool : public CollectedMemoryPool {
+private:
+  const static size_t _undefined_max = (size_t) -1;
+  EpsilonCollectedHeap* _heap;
+
+public:
+  EpsilonMemoryPool(EpsilonCollectedHeap* 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_SERVICES_EPSILON_COLLECTORPOLICY_HPP
--- a/src/hotspot/share/services/memoryManager.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/services/memoryManager.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -91,6 +91,10 @@
   return (GCMemoryManager*) new G1OldGenMemoryManager();
 }
 
+GCMemoryManager* MemoryManager::get_epsilon_memory_manager() {
+  return (GCMemoryManager*) new EpsilonMemoryManager();
+}
+
 instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {
   // Must do an acquire so as to force ordering of subsequent
   // loads from anything _memory_mgr_obj points to or implies.
--- a/src/hotspot/share/services/memoryManager.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/services/memoryManager.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -83,6 +83,7 @@
   static GCMemoryManager* get_psMarkSweep_memory_manager();
   static GCMemoryManager* get_g1YoungGen_memory_manager();
   static GCMemoryManager* get_g1OldGen_memory_manager();
+  static GCMemoryManager* get_epsilon_memory_manager();
 };
 
 class CodeCacheMemoryManager : public MemoryManager {
@@ -253,4 +254,12 @@
   const char* name() { return "G1 Old Generation"; }
 };
 
+class EpsilonMemoryManager : public GCMemoryManager {
+private:
+public:
+  EpsilonMemoryManager() : GCMemoryManager() {}
+
+  const char* name() { return "Epsilon Generation"; }
+};
+
 #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP
--- a/src/hotspot/share/services/memoryService.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/services/memoryService.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -55,6 +55,7 @@
 #include "gc/parallel/psYoungGen.hpp"
 #include "services/g1MemoryPool.hpp"
 #include "services/psMemoryPool.hpp"
+#include "services/epsilonMemoryPool.hpp"
 #endif // INCLUDE_ALL_GCS
 
 GrowableArray<MemoryPool*>* MemoryService::_pools_list =
@@ -100,6 +101,10 @@
       add_g1_heap_info(G1CollectedHeap::heap());
       break;
     }
+    case CollectedHeap::EpsilonCollectedHeap : {
+      add_epsilon_heap_info(EpsilonCollectedHeap::heap());
+      break;
+    }
 #endif // INCLUDE_ALL_GCS
     default: {
       guarantee(false, "Unrecognized kind of heap");
@@ -189,6 +194,23 @@
   add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager);
   add_g1OldGen_memory_pool(g1h, _major_gc_manager);
 }
+
+void MemoryService::add_epsilon_heap_info(EpsilonCollectedHeap* eh) {
+  assert(UseEpsilonGC, "sanity");
+
+  _minor_gc_manager = MemoryManager::get_epsilon_memory_manager();
+  _major_gc_manager = MemoryManager::get_epsilon_memory_manager();
+  _managers_list->append(_minor_gc_manager);
+  _managers_list->append(_major_gc_manager);
+
+  EpsilonDummyMemoryPool* dummy = new EpsilonDummyMemoryPool();
+  _minor_gc_manager->add_pool(dummy);
+  _pools_list->append(dummy);
+
+  EpsilonMemoryPool* pool = new EpsilonMemoryPool(eh);
+  _major_gc_manager->add_pool(pool);
+  _pools_list->append(pool);
+}
 #endif // INCLUDE_ALL_GCS
 
 MemoryPool* MemoryService::add_gen(Generation* gen,
@@ -387,6 +409,7 @@
   mgr->add_pool(old_gen);
   _pools_list->append(old_gen);
 }
+
 #endif // INCLUDE_ALL_GCS
 
 void MemoryService::add_code_heap_memory_pool(CodeHeap* heap, const char* name) {
--- a/src/hotspot/share/services/memoryService.hpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/services/memoryService.hpp	Mon Nov 06 18:53:38 2017 +0100
@@ -47,6 +47,7 @@
 class GenCollectedHeap;
 class ParallelScavengeHeap;
 class G1CollectedHeap;
+class EpsilonCollectedHeap;
 
 // VM Monitoring and Management Support
 
@@ -113,9 +114,11 @@
                                    size_t max_size,
                                    bool support_usage_threshold);
 
+
   static void add_gen_collected_heap_info(GenCollectedHeap* heap);
   static void add_parallel_scavenge_heap_info(ParallelScavengeHeap* heap);
   static void add_g1_heap_info(G1CollectedHeap* g1h);
+  static void add_epsilon_heap_info(EpsilonCollectedHeap* eh);
 
 public:
   static void set_universe_heap(CollectedHeap* heap);
--- a/src/hotspot/share/utilities/vmError.cpp	Mon Oct 30 21:23:10 2017 +0100
+++ b/src/hotspot/share/utilities/vmError.cpp	Mon Nov 06 18:53:38 2017 +0100
@@ -306,6 +306,7 @@
   if (UseParallelGC)      return "parallel gc";
   if (UseConcMarkSweepGC) return "concurrent mark sweep gc";
   if (UseSerialGC)        return "serial gc";
+  if (UseEpsilonGC)       return "epsilon gc";
   return "ERROR in GC mode";
 }
 
--- a/test/hotspot/jtreg/TEST.groups	Mon Oct 30 21:23:10 2017 +0100
+++ b/test/hotspot/jtreg/TEST.groups	Mon Nov 06 18:53:38 2017 +0100
@@ -117,6 +117,9 @@
   -:hotspot_tier1_compiler_3 \
   -:hotspot_tier1_compiler_closed
 
+hotspot_gc_epsilon = \
+  gc/epsilon/
+
 hotspot_tier1_gc_1 = \
   gc/g1/
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/AbstractEpsilonTest.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+
+public class AbstractEpsilonTest {
+  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/TestAlwaysPretouch.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestAlwaysPretouch
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -Xmx1g -XX:+AlwaysPreTouch -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestByteArrays
+ * @library /test/lib
+ * @summary Epsilon is able to allocate arrays, and does not corrupt their state
+ *
+ * @run main/othervm -Xmx1g                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ *
+ * @run main/othervm -Xmx1g                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestByteArrays
+ */
+
+import java.util.Random;
+
+public class TestByteArrays extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestDieDefault
+ * @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 extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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:TieredStopAtLevel=4",
+             "-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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestDieWithHeapDump
+ * @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 extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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:TieredStopAtLevel=4",
+             "-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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestDieWithOnError
+ * @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 extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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:TieredStopAtLevel=4",
+             "-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/TestEpsilonEnabled.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestAlwaysPretouch
+ * @library /test/lib
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestEpsilonEnabled
+ */
+
+import jdk.test.lib.Platform;
+
+public class TestEpsilonEnabled extends AbstractEpsilonTest {
+  public static void main(String[] args) throws Exception {
+    if (Platform.isDebugBuild() && !isEpsilonEnabled()) {
+      throw new IllegalStateException("Debug builds should have Epsilon enabled");
+    }
+    if (!Platform.isDebugBuild() && isEpsilonEnabled()) {
+      throw new IllegalStateException("Non-debug builds should have Epsilon disabled");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestHelloWorld.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestHelloWorld
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestHelloWorld
+ */
+
+import java.util.LinkedList;
+
+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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestLogTrace
+ * @summary Basic sanity test for Epsilon
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC -Xlog:gc=trace TestLogTrace
+ */
+
+import java.util.LinkedList;
+
+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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestManyThreads
+ *
+ * @run main/othervm -Xmx128m -Xss512k                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ *
+ * @run main/othervm -Xmx128m -Xss512k                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ * @run main/othervm -Xmx128m -Xss512k -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestManyThreads
+ */
+
+import java.util.concurrent.atomic.*;
+
+public class TestManyThreads extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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
+ * @summary Test JMX memory beans
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC          -Xmx1g TestMemoryMXBeans   -1 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC -Xms1g   -Xmx1g TestMemoryMXBeans 1024 1024
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -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();
+        long heapUsed1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+        sink = new int[1024*1024];
+        long heapUsed2 = memoryMXBean.getHeapMemoryUsage().getUsed();
+
+        long diff = heapUsed2 - heapUsed1;
+        if (!(8 + 4*1024*1024 <= diff && diff <= 16 + 4*1024*1024)) {
+           throw new IllegalStateException("Allocation did not change used space right: " + diff);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/gc/epsilon/TestMemoryPools.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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
+ * @summary Test JMX memory pools
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -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	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestObjects
+ * @summary Epsilon is able to allocate objects, and does not corrupt their state
+ *
+ * @run main/othervm -Xmx128m                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ *
+ * @run main/othervm -Xmx128m                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ * @run main/othervm -Xmx128m -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestObjects
+ */
+
+import java.util.Random;
+
+public class TestObjects extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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/TestRefArrays.java	Mon Nov 06 18:53:38 2017 +0100
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test TestRefArrays
+ * @library /test/lib
+ * @summary Epsilon is able to allocate arrays, and does not corrupt their state
+ *
+ * @run main/othervm -Xmx1g                                        -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:+UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ *
+ * @run main/othervm -Xmx1g                                        -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xint                                  -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp                         -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=1 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ * @run main/othervm -Xmx1g -Xbatch -Xcomp -XX:TieredStopAtLevel=4 -XX:-UseTLAB -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestRefArrays
+ */
+
+import java.util.Random;
+
+public class TestRefArrays extends AbstractEpsilonTest {
+
+  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 {
+    if (!isEpsilonEnabled()) return;
+
+    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;
+    }
+  }
+}