# HG changeset patch # User shade # Date 1510148403 -3600 # Wed Nov 08 14:40:03 2017 +0100 # Node ID 301b9daffecf883e1e9290a72567de11bef315a8 # Parent 8015f8f73cde7b4bffb37a99748d77245ba1b932 imported patch epsilon-base diff --git a/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/src/cpu/ppc/vm/stubGenerator_ppc.cpp --- a/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -648,6 +648,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default: ShouldNotReachHere(); @@ -724,6 +725,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: if (!branchToEnd) __ blr(); break; default: diff --git a/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/src/cpu/ppc/vm/templateTable_ppc_64.cpp --- a/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -141,6 +141,9 @@ __ bind(Ldone); } break; + case BarrierSet::Epsilon: + Unimplemented(); // Should look like CardTableForRS without card mark? + break; case BarrierSet::ModRef: case BarrierSet::Other: ShouldNotReachHere(); diff --git a/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/src/cpu/sparc/vm/stubGenerator_sparc.cpp --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -985,6 +985,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default: ShouldNotReachHere(); @@ -1042,6 +1043,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default: ShouldNotReachHere(); diff --git a/src/cpu/sparc/vm/templateTable_sparc.cpp b/src/cpu/sparc/vm/templateTable_sparc.cpp --- a/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -113,6 +113,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: case BarrierSet::Other: ShouldNotReachHere(); diff --git a/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/src/cpu/x86/vm/c1_Runtime1_x86.cpp --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1703,11 +1703,18 @@ { StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments); + 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; + } // arg0: store_address Address store_addr(rbp, 2*BytesPerWord); - BarrierSet* bs = Universe::heap()->barrier_set(); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); diff --git a/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/src/cpu/x86/vm/stubGenerator_x86_32.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -719,6 +719,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : ShouldNotReachHere(); @@ -772,6 +773,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : ShouldNotReachHere(); diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -1205,6 +1205,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default: ShouldNotReachHere(); @@ -1267,6 +1268,9 @@ __ jcc(Assembler::greaterEqual, L_loop); } break; + case BarrierSet::Epsilon: + // No barriers + break; default: ShouldNotReachHere(); diff --git a/src/cpu/x86/vm/templateTable_x86_32.cpp b/src/cpu/x86/vm/templateTable_x86_32.cpp --- a/src/cpu/x86/vm/templateTable_x86_32.cpp +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp @@ -184,6 +184,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: case BarrierSet::Other: if (val == noreg) { __ movptr(obj, NULL_WORD); diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -192,6 +192,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: case BarrierSet::Other: if (val == noreg) { __ store_heap_oop_null(obj); diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1428,6 +1428,7 @@ // No pre barriers break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: case BarrierSet::Other: // No pre barriers break; @@ -1450,6 +1451,7 @@ CardTableModRef_post_barrier(addr, new_val); break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: case BarrierSet::Other: // No post barriers break; diff --git a/src/share/vm/gc_implementation/epsilon/epsilonBarrierSet.hpp b/src/share/vm/gc_implementation/epsilon/epsilonBarrierSet.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonBarrierSet.hpp @@ -0,0 +1,65 @@ +/* + * 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 "memory/collectorPolicy.hpp" +#include "memory/barrierSet.hpp" + +// Most are no-ops. +class EpsilonBarrierSet: public ModRefBarrierSet { + friend class VMStructs; + +public: + EpsilonBarrierSet() : ModRefBarrierSet() { + _kind = BarrierSet::Epsilon; + } + + bool is_a(BarrierSet::Name bsn) { + return bsn == 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 {} + + virtual void invalidate(MemRegion mr, bool whole_heap = false) {} + +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) {} +}; + +#endif // SHARE_VM_GC_EPSILON_BARRIERSET_HPP diff --git a/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.cpp b/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.cpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.cpp @@ -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. + * + */ + +#include "precompiled.hpp" +#include "oops/oop.hpp" +#include "oops/oop.inline.hpp" +#include "gc_implementation/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()); + + _reserved.set_word_size(0); + _reserved.set_start((HeapWord*)heap_rs.base()); + _reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size())); + + _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) { + gclog_or_tty->print_cr("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 { + gclog_or_tty->print_cr("Initialized with " SIZE_FORMAT "M non-resizeable heap", init_byte_size / M); + } + if (UseTLAB) { + gclog_or_tty->print_cr("Using TLAB allocation; min: " SIZE_FORMAT "K, max: " SIZE_FORMAT "K", + ThreadLocalAllocBuffer::min_size()*HeapWordSize / K, + _max_tlab_size*HeapWordSize / K); + } else { + gclog_or_tty->print_cr("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) { + gclog_or_tty->print_cr("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) { + gclog_or_tty->print_cr("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 { + size_t allocated_kb = used() / K; + gclog_or_tty->print_cr("Total allocated: " SIZE_FORMAT " KB", + allocated_kb); + gclog_or_tty->print_cr("Average allocation rate: " SIZE_FORMAT " KB/sec", + allocated_kb * NANOSECS_PER_SEC / os::elapsed_counter()); +} diff --git a/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.hpp b/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonCollectedHeap.hpp @@ -0,0 +1,189 @@ +/* + * 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_interface/collectedHeap.hpp" +#include "memory/space.hpp" +#include "gc_implementation/epsilon/epsilonCollectorPolicy.hpp" +#include "gc_implementation/epsilon/epsilonMonitoringSupport.hpp" +#include "gc_implementation/epsilon/epsilonBarrierSet.hpp" +#include "gc_implementation/epsilon/epsilon_globals.hpp" + +class EpsilonCollectedHeap : public SharedHeap { +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) : SharedHeap(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(const void *p) { + // 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(bool silent, VerifyOption option) { + // No heap verification for Epsilon. + } + + virtual bool supports_heap_inspection() const { + return true; // TODO: Really? + } + + virtual void space_iterate(SpaceClosure *cl) { + Unimplemented(); // TODO: Implement + } + + virtual Space *space_containing(const void *addr) const { + Unimplemented(); // TODO: Implement + } + + virtual void gc_prologue(bool full) { + // No need. + } + + virtual void gc_epilogue(bool full) { + // No need. + } + + virtual bool is_in_partial_collection(const void *p) { + Unimplemented(); + } + + void oop_iterate(ExtendedOopClosure* cl) { + Unimplemented(); + } + +}; + +#endif // SHARE_VM_GC_EPSILON_COLLECTEDHEAP_HPP diff --git a/src/share/vm/gc_implementation/epsilon/epsilonCollectorPolicy.hpp b/src/share/vm/gc_implementation/epsilon/epsilonCollectorPolicy.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonCollectorPolicy.hpp @@ -0,0 +1,59 @@ +/* + * 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 "memory/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() {}; + + virtual BarrierSet::Name barrier_set_name() { + return BarrierSet::Epsilon; + } + + virtual HeapWord *mem_allocate_work(size_t size, bool is_tlab, bool *gc_overhead_limit_was_exceeded) { + guarantee(false, "Not using this policy feature yet."); + return NULL; + } + + virtual HeapWord *satisfy_failed_allocation(size_t size, bool is_tlab) { + guarantee(false, "Not using this policy feature yet."); + return NULL; + } + + virtual void post_heap_initialize() { + // do nothing + } +}; + +#endif // SHARE_VM_GC_EPSILON_COLLECTORPOLICY_HPP diff --git a/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.cpp b/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.cpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.cpp @@ -0,0 +1,129 @@ +/* + * 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_implementation/shared/generationCounters.hpp" +#include "gc_implementation/epsilon/epsilonMonitoringSupport.hpp" +#include "gc_implementation/epsilon/epsilonCollectedHeap.hpp" + +class EpsilonSpaceCounters: public CHeapObj { + 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, mtGC); + } + } + + 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(); + } +} + diff --git a/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.hpp b/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilonMonitoringSupport.hpp @@ -0,0 +1,45 @@ +/* + * 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 { +private: + GenerationCounters* _young_counters; + GenerationCounters* _heap_counters; + EpsilonSpaceCounters* _space_counters; + +public: + EpsilonMonitoringSupport(EpsilonCollectedHeap* heap); + void update_counters(); +}; + +#endif // SHARE_VM_GC_EPSILON_EPSILONMONITORINGSUPPORT_HPP + diff --git a/src/share/vm/gc_implementation/epsilon/epsilon_globals.cpp b/src/share/vm/gc_implementation/epsilon/epsilon_globals.cpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilon_globals.cpp @@ -0,0 +1,33 @@ +/* + * 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_implementation/epsilon/epsilon_globals.hpp" + + +EPSILON_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, \ + MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, \ + MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_EXPERIMENTAL_FLAG, \ + MATERIALIZE_NOTPRODUCT_FLAG, \ + MATERIALIZE_MANAGEABLE_FLAG, MATERIALIZE_PRODUCT_RW_FLAG) diff --git a/src/share/vm/gc_implementation/epsilon/epsilon_globals.hpp b/src/share/vm/gc_implementation/epsilon/epsilon_globals.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/gc_implementation/epsilon/epsilon_globals.hpp @@ -0,0 +1,46 @@ +/* + * 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, experimental, notproduct, manageable, product_rw) \ + \ + 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") \ + \ + experimental(size_t, EpsilonMinHeapExpand, 128 * M, \ + "Min expansion step for heap. Larger value improves performance " \ + "at the potential expense of memory waste.") \ + +EPSILON_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG) + +#endif // SHARE_VM_GC_EPSILON_GLOBALS_HPP diff --git a/src/share/vm/gc_interface/collectedHeap.hpp b/src/share/vm/gc_interface/collectedHeap.hpp --- a/src/share/vm/gc_interface/collectedHeap.hpp +++ b/src/share/vm/gc_interface/collectedHeap.hpp @@ -188,7 +188,8 @@ SharedHeap, GenCollectedHeap, ParallelScavengeHeap, - G1CollectedHeap + G1CollectedHeap, + EpsilonCollectedHeap, }; static inline size_t filler_array_max_size() { diff --git a/src/share/vm/memory/barrierSet.hpp b/src/share/vm/memory/barrierSet.hpp --- a/src/share/vm/memory/barrierSet.hpp +++ b/src/share/vm/memory/barrierSet.hpp @@ -40,6 +40,7 @@ CardTableExtension, G1SATBCT, G1SATBCTLogging, + Epsilon, Other, Uninit }; diff --git a/src/share/vm/memory/universe.cpp b/src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp +++ b/src/share/vm/memory/universe.cpp @@ -77,6 +77,8 @@ #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" +#include "gc_implementation/epsilon/epsilonCollectedHeap.hpp" +#include "gc_implementation/epsilon/epsilonCollectorPolicy.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy_ext.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" @@ -815,6 +817,15 @@ fatal("UseG1GC not supported in java kernel vm."); #endif // INCLUDE_ALL_GCS + } else if (UseEpsilonGC) { +#if INCLUDE_ALL_GCS + EpsilonCollectorPolicy* gc_policy = new EpsilonCollectorPolicy(); + gc_policy->initialize_all(); + Universe::_collectedHeap = new EpsilonCollectedHeap(gc_policy); +#else // INCLUDE_ALL_GCS + fatal("UseEpsilonGC not supported in java kernel vm."); +#endif // INCLUDE_ALL_GCS + } else { GenCollectorPolicy *gc_policy; diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -1539,6 +1539,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; case BarrierSet::Other: @@ -1558,6 +1559,7 @@ case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: return true; // There is no pre-barrier case BarrierSet::Other: @@ -1589,6 +1591,7 @@ break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; case BarrierSet::Other: diff --git a/src/share/vm/precompiled/precompiled.hpp b/src/share/vm/precompiled/precompiled.hpp --- a/src/share/vm/precompiled/precompiled.hpp +++ b/src/share/vm/precompiled/precompiled.hpp @@ -301,6 +301,7 @@ # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" # include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" # include "gc_implementation/concurrentMarkSweep/promotionInfo.hpp" +# include "gc_implementation/epsilon/epsilon_globals.hpp" # include "gc_implementation/g1/dirtyCardQueue.hpp" # include "gc_implementation/g1/g1BlockOffsetTable.hpp" # include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp" diff --git a/src/share/vm/runtime/arguments.cpp b/src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp +++ b/src/share/vm/runtime/arguments.cpp @@ -1723,6 +1723,22 @@ #endif // ASSERT #endif // INCLUDE_ALL_GCS +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 @@ -1734,6 +1750,8 @@ set_parnew_gc_flags(); } else if (UseG1GC) { set_g1_gc_flags(); + } else if (UseEpsilonGC) { + set_epsilon_flags(); } check_deprecated_gcs(); check_deprecated_gc_flags(); @@ -2120,6 +2138,7 @@ if (UseConcMarkSweepGC || UseParNewGC) 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; " diff --git a/src/share/vm/runtime/arguments.hpp b/src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp +++ b/src/share/vm/runtime/arguments.hpp @@ -335,6 +335,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(); @@ -611,7 +613,7 @@ bool Arguments::gc_selected() { return UseConcMarkSweepGC || UseG1GC || UseParallelGC || UseParallelOldGC || - UseParNewGC || UseSerialGC; + UseParNewGC || UseSerialGC || UseEpsilonGC; } #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff --git a/src/share/vm/runtime/globals.cpp b/src/share/vm/runtime/globals.cpp --- a/src/share/vm/runtime/globals.cpp +++ b/src/share/vm/runtime/globals.cpp @@ -33,6 +33,7 @@ #include "utilities/top.hpp" #include "trace/tracing.hpp" #if INCLUDE_ALL_GCS +#include "gc_implementation/epsilon/epsilon_globals.hpp" #include "gc_implementation/g1/g1_globals.hpp" #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 @@ -480,6 +481,7 @@ RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) #if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) + 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_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -1411,6 +1411,9 @@ product(bool, UseParallelOldGC, false, \ "Use the Parallel Old garbage collector") \ \ + develop(bool, UseEpsilonGC, false, \ + "Use the Epsilon garbage collector") \ + \ product(uintx, HeapMaximumCompactionInterval, 20, \ "How often should we maximally compact the heap (not allowing " \ "any dead space)") \ diff --git a/src/share/vm/runtime/globals_extension.hpp b/src/share/vm/runtime/globals_extension.hpp --- a/src/share/vm/runtime/globals_extension.hpp +++ b/src/share/vm/runtime/globals_extension.hpp @@ -76,6 +76,7 @@ RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) #if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) + 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_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_DIAGNOSTIC_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) @@ -156,6 +157,15 @@ RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) + 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_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE, + RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, + RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, + RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE, diff --git a/src/share/vm/services/epsilonMemoryPool.cpp b/src/share/vm/services/epsilonMemoryPool.cpp new file mode 100644 --- /dev/null +++ b/src/share/vm/services/epsilonMemoryPool.cpp @@ -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_implementation/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); +} diff --git a/src/share/vm/services/epsilonMemoryPool.hpp b/src/share/vm/services/epsilonMemoryPool.hpp new file mode 100644 --- /dev/null +++ b/src/share/vm/services/epsilonMemoryPool.hpp @@ -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_implementation/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 diff --git a/src/share/vm/services/memoryManager.cpp b/src/share/vm/services/memoryManager.cpp --- a/src/share/vm/services/memoryManager.cpp +++ b/src/share/vm/services/memoryManager.cpp @@ -98,6 +98,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. diff --git a/src/share/vm/services/memoryManager.hpp b/src/share/vm/services/memoryManager.hpp --- a/src/share/vm/services/memoryManager.hpp +++ b/src/share/vm/services/memoryManager.hpp @@ -64,7 +64,8 @@ PSScavenge, PSMarkSweep, G1YoungGen, - G1OldGen + G1OldGen, + Epsilon, }; MemoryManager(); @@ -98,7 +99,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 { @@ -284,4 +285,13 @@ const char* name() { return "G1 Old Generation"; } }; +class EpsilonMemoryManager : public GCMemoryManager { +private: +public: + EpsilonMemoryManager() : GCMemoryManager() {} + + MemoryManager::Name kind() { return MemoryManager::Epsilon; } + const char* name() { return "Epsilon Generation"; } +}; + #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP diff --git a/src/share/vm/services/memoryService.cpp b/src/share/vm/services/memoryService.cpp --- a/src/share/vm/services/memoryService.cpp +++ b/src/share/vm/services/memoryService.cpp @@ -54,6 +54,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "services/g1MemoryPool.hpp" #include "services/psMemoryPool.hpp" +#include "services/epsilonMemoryPool.hpp" #endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = @@ -96,6 +97,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, diff --git a/src/share/vm/services/memoryService.hpp b/src/share/vm/services/memoryService.hpp --- a/src/share/vm/services/memoryService.hpp +++ b/src/share/vm/services/memoryService.hpp @@ -46,6 +46,7 @@ class GenCollectedHeap; class ParallelScavengeHeap; class G1CollectedHeap; +class EpsilonCollectedHeap; // VM Monitoring and Management Support @@ -120,6 +121,7 @@ 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); diff --git a/src/share/vm/utilities/top.hpp b/src/share/vm/utilities/top.hpp --- a/src/share/vm/utilities/top.hpp +++ b/src/share/vm/utilities/top.hpp @@ -35,6 +35,7 @@ #include "utilities/sizes.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" +#include "gc_implementation/epsilon/epsilon_globals.hpp" #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" diff --git a/test/TEST.groups b/test/TEST.groups --- a/test/TEST.groups +++ b/test/TEST.groups @@ -146,6 +146,10 @@ :hotspot_gc \ :hotspot_runtime \ :hotspot_serviceability + +hotspot_gc_epsilon = \ + gc/epsilon/ + # Tests that require compact3 API's # needs_compact3 = \ diff --git a/test/gc/epsilon/AbstractEpsilonTest.java b/test/gc/epsilon/AbstractEpsilonTest.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/AbstractEpsilonTest.java @@ -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; + } +} diff --git a/test/gc/epsilon/TestAlwaysPretouch.java b/test/gc/epsilon/TestAlwaysPretouch.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestAlwaysPretouch.java @@ -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 + } +} diff --git a/test/gc/epsilon/TestByteArrays.java b/test/gc/epsilon/TestByteArrays.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestByteArrays.java @@ -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 TestByteArrays + * @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); + } + } + } + } +} diff --git a/test/gc/epsilon/TestDieDefault.java b/test/gc/epsilon/TestDieDefault.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestDieDefault.java @@ -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 /testlibrary + * @run main TestDieDefault + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.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(); + } + } + } + +} diff --git a/test/gc/epsilon/TestDieWithHeapDump.java b/test/gc/epsilon/TestDieWithHeapDump.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestDieWithHeapDump.java @@ -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 /testlibrary + * @run main TestDieWithHeapDump + */ + +import java.io.*; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.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(); + } + } + } + +} diff --git a/test/gc/epsilon/TestDieWithOnError.java b/test/gc/epsilon/TestDieWithOnError.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestDieWithOnError.java @@ -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 /testlibrary + * @run main TestDieWithOnError + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.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(); + } + } + } + +} diff --git a/test/gc/epsilon/TestEpsilonEnabled.java b/test/gc/epsilon/TestEpsilonEnabled.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestEpsilonEnabled.java @@ -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 /testlibrary + * @summary Basic sanity test for Epsilon + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+UseEpsilonGC TestEpsilonEnabled + */ + +import com.oracle.java.testlibrary.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"); + } + } +} diff --git a/test/gc/epsilon/TestHelloWorld.java b/test/gc/epsilon/TestHelloWorld.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestHelloWorld.java @@ -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"); + } +} diff --git a/test/gc/epsilon/TestLogTrace.java b/test/gc/epsilon/TestLogTrace.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestLogTrace.java @@ -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"); + } +} diff --git a/test/gc/epsilon/TestManyThreads.java b/test/gc/epsilon/TestManyThreads.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestManyThreads.java @@ -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; + } + } + +} diff --git a/test/gc/epsilon/TestMemoryMXBeans.java b/test/gc/epsilon/TestMemoryMXBeans.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestMemoryMXBeans.java @@ -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); + } + } + +} diff --git a/test/gc/epsilon/TestMemoryPools.java b/test/gc/epsilon/TestMemoryPools.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestMemoryPools.java @@ -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 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"); + } + } + } + } +} diff --git a/test/gc/epsilon/TestObjects.java b/test/gc/epsilon/TestObjects.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestObjects.java @@ -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; + } + } +} diff --git a/test/gc/epsilon/TestRefArrays.java b/test/gc/epsilon/TestRefArrays.java new file mode 100644 --- /dev/null +++ b/test/gc/epsilon/TestRefArrays.java @@ -0,0 +1,88 @@ +/* + * 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 + * @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; + } + } +} # HG changeset patch # User shade # Date 1510155063 -3600 # Wed Nov 08 16:31:03 2017 +0100 # Node ID e79796ddff90e393c9fdfef9174e2b32c0bd8ab7 # Parent 301b9daffecf883e1e9290a72567de11bef315a8 [mq]: enable-experimental diff --git a/src/share/vm/runtime/globals.hpp b/src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp +++ b/src/share/vm/runtime/globals.hpp @@ -1411,7 +1411,7 @@ product(bool, UseParallelOldGC, false, \ "Use the Parallel Old garbage collector") \ \ - develop(bool, UseEpsilonGC, false, \ + experimental(bool, UseEpsilonGC, false, \ "Use the Epsilon garbage collector") \ \ product(uintx, HeapMaximumCompactionInterval, 20, \ diff --git a/test/gc/epsilon/TestEpsilonEnabled.java b/test/gc/epsilon/TestEpsilonEnabled.java --- a/test/gc/epsilon/TestEpsilonEnabled.java +++ b/test/gc/epsilon/TestEpsilonEnabled.java @@ -35,8 +35,8 @@ 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"); + if (!Platform.isDebugBuild() && !isEpsilonEnabled()) { + throw new IllegalStateException("Non-debug builds should have Epsilon enabled"); } } }