--- old/src/cpu/x86/vm/c1_Runtime1_x86.cpp 2017-02-13 21:50:15.093743067 +0100 +++ new/src/cpu/x86/vm/c1_Runtime1_x86.cpp 2017-02-13 21:50:15.033743239 +0100 @@ -1664,6 +1664,10 @@ case g1_post_barrier_slow_id: { + // avoid touching CardTableModRefBS if not G1 + // FIXME: This looks like an upstream bug. + if (!UseG1GC) break; + StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments); --- old/src/cpu/x86/vm/stubGenerator_x86_32.cpp 2017-02-13 21:50:15.317742425 +0100 +++ new/src/cpu/x86/vm/stubGenerator_x86_32.cpp 2017-02-13 21:50:15.257742597 +0100 @@ -688,6 +688,7 @@ case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : ShouldNotReachHere(); @@ -740,6 +741,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : ShouldNotReachHere(); --- old/src/cpu/x86/vm/stubGenerator_x86_64.cpp 2017-02-13 21:50:15.565741715 +0100 +++ new/src/cpu/x86/vm/stubGenerator_x86_64.cpp 2017-02-13 21:50:15.505741886 +0100 @@ -1220,6 +1220,7 @@ case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default: ShouldNotReachHere(); @@ -1281,6 +1282,9 @@ __ jcc(Assembler::greaterEqual, L_loop); } break; + case BarrierSet::Epsilon: + // TODO: why are we here at all? + break; default: ShouldNotReachHere(); --- old/src/cpu/x86/vm/templateTable_x86.cpp 2017-02-13 21:50:15.813741004 +0100 +++ new/src/cpu/x86/vm/templateTable_x86.cpp 2017-02-13 21:50:15.753741176 +0100 @@ -216,6 +216,7 @@ } break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: if (val == noreg) { __ store_heap_oop_null(obj); } else { --- old/src/share/vm/c1/c1_LIRGenerator.cpp 2017-02-13 21:50:16.053740317 +0100 +++ new/src/share/vm/c1/c1_LIRGenerator.cpp 2017-02-13 21:50:15.993740489 +0100 @@ -1462,6 +1462,7 @@ // No pre barriers break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: // No pre barriers break; default : @@ -1482,6 +1483,7 @@ CardTableModRef_post_barrier(addr, new_val); break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: // No post barriers break; default : --- old/src/share/vm/gc/shared/barrierSet.hpp 2017-02-13 21:50:16.293739630 +0100 +++ new/src/share/vm/gc/shared/barrierSet.hpp 2017-02-13 21:50:16.233739801 +0100 @@ -52,7 +52,8 @@ CardTableForRS, // CardTableModRefBSForCTRS CardTableExtension, // CardTableExtension G1SATBCT, // G1SATBCardTableModRefBS - G1SATBCTLogging // G1SATBCardTableLoggingModRefBS + G1SATBCTLogging, // G1SATBCardTableLoggingModRefBS + Epsilon, // EpsilonBarrierSet }; protected: --- old/src/share/vm/gc/shared/collectedHeap.hpp 2017-02-13 21:50:16.513739001 +0100 +++ new/src/share/vm/gc/shared/collectedHeap.hpp 2017-02-13 21:50:16.453739172 +0100 @@ -191,7 +191,8 @@ enum Name { GenCollectedHeap, ParallelScavengeHeap, - G1CollectedHeap + G1CollectedHeap, + EpsilonCollectedHeap, }; static inline size_t filler_array_max_size() { --- old/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2017-02-13 21:50:16.729738381 +0100 +++ new/src/share/vm/jvmci/jvmciCompilerToVM.cpp 2017-02-13 21:50:16.669738553 +0100 @@ -174,6 +174,7 @@ break; } case BarrierSet::ModRef: + case BarrierSet::Epsilon: cardtable_start_address = 0; cardtable_shift = 0; // No post barriers --- old/src/share/vm/memory/universe.cpp 2017-02-13 21:50:16.953737741 +0100 +++ new/src/share/vm/memory/universe.cpp 2017-02-13 21:50:16.893737913 +0100 @@ -82,6 +82,8 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" +#include "gc/epsilon/epsilonCollectedHeap.hpp" +#include "gc/epsilon/epsilonCollectorPolicy.hpp" #include "gc/shared/adaptiveSizePolicy.hpp" #endif // INCLUDE_ALL_GCS #if INCLUDE_CDS @@ -733,6 +735,8 @@ #endif } else if (UseSerialGC) { return Universe::create_heap_with_policy(); + } else if (UseEpsilonGC) { + return Universe::create_heap_with_policy(); } ShouldNotReachHere(); --- old/src/share/vm/opto/graphKit.cpp 2017-02-13 21:50:17.181737087 +0100 +++ new/src/share/vm/opto/graphKit.cpp 2017-02-13 21:50:17.117737271 +0100 @@ -1538,6 +1538,7 @@ case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : @@ -1555,6 +1556,7 @@ case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: case BarrierSet::ModRef: + case BarrierSet::Epsilon: return true; // There is no pre-barrier default : @@ -1584,6 +1586,7 @@ break; case BarrierSet::ModRef: + case BarrierSet::Epsilon: break; default : --- old/src/share/vm/runtime/arguments.cpp 2017-02-13 21:50:17.429736377 +0100 +++ new/src/share/vm/runtime/arguments.cpp 2017-02-13 21:50:17.361736572 +0100 @@ -1760,7 +1760,7 @@ bool Arguments::gc_selected() { #if INCLUDE_ALL_GCS - return UseSerialGC || UseParallelGC || UseParallelOldGC || UseConcMarkSweepGC || UseG1GC; + return UseSerialGC || UseParallelGC || UseParallelOldGC || UseConcMarkSweepGC || UseG1GC || UseEpsilonGC; #else return UseSerialGC; #endif // INCLUDE_ALL_GCS @@ -2304,6 +2304,7 @@ if (UseConcMarkSweepGC) i++; if (UseParallelGC || UseParallelOldGC) i++; if (UseG1GC) i++; + if (UseEpsilonGC) i++; if (i > 1) { jio_fprintf(defaultStream::error_stream(), "Conflicting collector combinations in option list; " --- old/src/share/vm/runtime/globals.hpp 2017-02-13 21:50:17.685735645 +0100 +++ new/src/share/vm/runtime/globals.hpp 2017-02-13 21:50:17.613735850 +0100 @@ -1399,6 +1399,9 @@ product(bool, UseParallelOldGC, false, \ "Use the Parallel Old garbage collector") \ \ + experimental(bool, UseEpsilonGC, false, \ + "Use the Epsilon (no-op) garbage collector") \ + \ product(uintx, HeapMaximumCompactionInterval, 20, \ "How often should we maximally compact the heap (not allowing " \ "any dead space)") \ --- old/src/share/vm/services/memoryManager.cpp 2017-02-13 21:50:17.925734957 +0100 +++ new/src/share/vm/services/memoryManager.cpp 2017-02-13 21:50:17.865735129 +0100 @@ -91,6 +91,10 @@ return (GCMemoryManager*) new G1OldGenMemoryManager(); } +GCMemoryManager* MemoryManager::get_epsilon_memory_manager() { + return (GCMemoryManager*) new EpsilonMemoryManager(); +} + instanceOop MemoryManager::get_memory_manager_instance(TRAPS) { // Must do an acquire so as to force ordering of subsequent // loads from anything _memory_mgr_obj points to or implies. --- old/src/share/vm/services/memoryManager.hpp 2017-02-13 21:50:18.145734326 +0100 +++ new/src/share/vm/services/memoryManager.hpp 2017-02-13 21:50:18.085734498 +0100 @@ -83,6 +83,7 @@ static GCMemoryManager* get_psMarkSweep_memory_manager(); static GCMemoryManager* get_g1YoungGen_memory_manager(); static GCMemoryManager* get_g1OldGen_memory_manager(); + static GCMemoryManager* get_epsilon_memory_manager(); }; class CodeCacheMemoryManager : public MemoryManager { @@ -253,4 +254,12 @@ const char* name() { return "G1 Old Generation"; } }; +class EpsilonMemoryManager : public GCMemoryManager { +private: +public: + EpsilonMemoryManager() : GCMemoryManager() {} + + const char* name() { return "Epsilon Generation"; } +}; + #endif // SHARE_VM_SERVICES_MEMORYMANAGER_HPP --- old/src/share/vm/services/memoryService.cpp 2017-02-13 21:50:18.361733709 +0100 +++ new/src/share/vm/services/memoryService.cpp 2017-02-13 21:50:18.301733881 +0100 @@ -99,6 +99,10 @@ add_g1_heap_info(G1CollectedHeap::heap()); break; } + case CollectedHeap::EpsilonCollectedHeap : { + add_epsilon_heap_info(); + break; + } #endif // INCLUDE_ALL_GCS default: { guarantee(false, "Unrecognized kind of heap"); @@ -188,6 +192,18 @@ 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() { + 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); +// TODO: fix these? +// add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); +// add_g1OldGen_memory_pool(g1h, _major_gc_manager); +} #endif // INCLUDE_ALL_GCS MemoryPool* MemoryService::add_gen(Generation* gen, --- old/src/share/vm/services/memoryService.hpp 2017-02-13 21:50:18.577733089 +0100 +++ new/src/share/vm/services/memoryService.hpp 2017-02-13 21:50:18.517733261 +0100 @@ -116,6 +116,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(); public: static void set_universe_heap(CollectedHeap* heap); --- old/src/share/vm/utilities/vmError.cpp 2017-02-13 21:50:18.793732472 +0100 +++ new/src/share/vm/utilities/vmError.cpp 2017-02-13 21:50:18.733732643 +0100 @@ -246,6 +246,7 @@ if (UseParallelGC) return "parallel gc"; if (UseConcMarkSweepGC) return "concurrent mark sweep gc"; if (UseSerialGC) return "serial gc"; + if (UseEpsilonGC) return "epsilon gc"; return "ERROR in GC mode"; } --- /dev/null 2017-02-09 18:28:35.238523416 +0100 +++ new/src/share/vm/gc/epsilon/epsilonBarrierSet.hpp 2017-02-13 21:50:18.953732013 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef HOTSPOT_EPSILONBARRIERSET_HPP_H +#define HOTSPOT_EPSILONBARRIERSET_HPP_H + +#include "gc/shared/collectorPolicy.hpp" +#include "gc/shared/barrierSet.hpp" + +// Most are no-ops. +class EpsilonBarrierSet: public ModRefBarrierSet { + friend class VMStructs; + +public: + EpsilonBarrierSet() : + ModRefBarrierSet(BarrierSet::FakeRtti(BarrierSet::Epsilon)) {}; + + virtual bool has_write_ref_barrier() { return false; } + virtual bool has_write_ref_pre_barrier() { return false; } + virtual bool has_write_ref_array_opt() { return true; } // TODO: why? + virtual bool has_write_region_opt() { return true; } // TODO: why? + + virtual bool is_aligned(HeapWord *addr) { return true; } // TODO: Safe? + + virtual void resize_covered_region(MemRegion new_region) {} + virtual void print_on(outputStream *st) const {} + +protected: + virtual void write_ref_field_work(void *field, oop new_val, bool release) {} + virtual void write_ref_array_work(MemRegion mr) {} + virtual void write_region_work(MemRegion mr) {} + +public: + virtual void invalidate(MemRegion mr) {} + virtual void clear(MemRegion mr) {} +}; + +template<> +struct BarrierSet::GetName { + static const BarrierSet::Name value = BarrierSet::Epsilon; +}; + +#endif --- /dev/null 2017-02-09 18:28:35.238523416 +0100 +++ new/src/share/vm/gc/epsilon/epsilonCollectedHeap.cpp 2017-02-13 21:50:19.161731418 +0100 @@ -0,0 +1,94 @@ +/* + * 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 "utilities/copy.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "epsilonCollectedHeap.hpp" +#include "epsilonBarrierSet.hpp" + +jint EpsilonCollectedHeap::initialize() { + 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); + + _start = (HeapWord *) heap_rs.base(); + _current = _start; + _end = (HeapWord *) (heap_rs.base() + heap_rs.size()); + + size_t size = pointer_delta(_end, _start); + + initialize_reserved_region(_start, _end); + os::commit_memory((char*)_start, size*HeapWordSize, align, false); + + log_info(gc)("Heap space: [" PTR_FORMAT ", " PTR_FORMAT "] (" SIZE_FORMAT "M)", + p2i(_start), p2i(_end), size*HeapWordSize / M); + + EpsilonBarrierSet* bs = new EpsilonBarrierSet(); + set_barrier_set(bs); + + log_info(gc)("Ready to go. See you at your next OutOfMemoryError."); + + return JNI_OK; +} + +HeapWord* EpsilonCollectedHeap::allocate_new_tlab(size_t size) { + bool trap; + return mem_allocate(size, &trap); +} + +HeapWord* EpsilonCollectedHeap::mem_allocate(size_t size, bool *gc_overhead_limit_was_exceeded) { + *gc_overhead_limit_was_exceeded = false; + do { + HeapWord* obj = (HeapWord *) _current; + if (pointer_delta(_end, obj) >= size) { + HeapWord* new_current = obj + size; + HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_current, &_current, obj); + if (result != obj) { + continue; + } + assert(is_object_aligned((intptr_t)obj), "object is aligned"); + assert(is_object_aligned((intptr_t)new_current), "current is aligned"); + return obj; + } else { + log_warning(gc)("Heap is exhausted, goodbye."); + vm_abort(false); // TODO: Throw the actual OOME; + } + } while (true); +} + +void EpsilonCollectedHeap::collect_as_vm_thread(GCCause::Cause cause) { + log_warning(gc)("GC was triggered for VM thread with cause \"%s\", unable to handle. Goodbye.", GCCause::to_string(cause)); + vm_abort(false); +} + +void EpsilonCollectedHeap::collect(GCCause::Cause cause) { + log_warning(gc)("GC was triggered with cause \"%s\", unable to handle. Goodbye.", GCCause::to_string(cause)); + vm_abort(false); +} + +void EpsilonCollectedHeap::do_full_collection(bool clear_all_soft_refs) { + log_warning(gc)("Full GC was triggered, unable to handle. Goodbye."); + vm_abort(false); +} --- /dev/null 2017-02-09 18:28:35.238523416 +0100 +++ new/src/share/vm/gc/epsilon/epsilonCollectedHeap.hpp 2017-02-13 21:50:19.365730834 +0100 @@ -0,0 +1,151 @@ +/* + * 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 "gc/shared/collectedHeap.hpp" +#include "gc/epsilon/epsilonCollectorPolicy.hpp" +#include "gc/epsilon/epsilonBarrierSet.hpp" + +class EpsilonCollectedHeap : public CollectedHeap { +private: + EpsilonCollectorPolicy* _policy; + HeapWord* _start; + HeapWord* _end; + volatile HeapWord* _current; +public: + EpsilonCollectedHeap(EpsilonCollectorPolicy* p) : _policy(p) {}; + + virtual Name kind() const { + return CollectedHeap::EpsilonCollectedHeap; + } + + virtual const char *name() const { + return "Epsilon GC"; + } + + virtual jint initialize(); + + virtual void post_initialize() {} + + virtual size_t capacity() const { return pointer_delta(_end, _start); } + virtual size_t used() const { return pointer_delta((HeapWord*)_current, _start); } + virtual size_t max_capacity() const { return capacity(); } + + virtual bool is_maximal_no_gc() const { return used() == capacity(); } // TODO: Really? + + virtual bool is_in(const void *p) const { return (_start <= p) && (p < _end); } + + virtual bool is_scavengable(const void *p) { return true; } // TODO: Why? + + 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 true; } + virtual size_t tlab_capacity(Thread *thr) const { return capacity(); } + virtual size_t tlab_used(Thread *thr) const { return used(); } // TODO: Should probably record the TLAB? + virtual size_t unsafe_max_tlab_alloc(Thread *thr) const { + // TODO: hook up in TLAB policy better. pointer_delta(_current, _end); + return HeapWordSize * 128 * K; + } + + virtual bool can_elide_tlab_store_barriers() const { + return true; // TODO: Really? + } + + virtual bool can_elide_initializing_store_barrier(oop new_obj) { + return true; // TODO: Really? + } + + virtual bool card_mark_must_follow_store() const { + return true; // TODO: Really? + } + + virtual void collect_as_vm_thread(GCCause::Cause cause); + 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) { + Unimplemented(); + } + + virtual void safe_object_iterate(ObjectClosure *cl) { + // TODO: Enable heap dumps by implementing this. + Unimplemented(); + } + + virtual HeapWord *block_start(const void *addr) const { + Unimplemented(); + return NULL; + } + + virtual size_t block_size(const HeapWord *addr) const { + Unimplemented(); + return 0; + } + + virtual bool block_is_obj(const HeapWord *addr) const { + Unimplemented(); + return false; + } + + virtual jlong millis_since_last_gc() { + return os::elapsed_counter(); // since the VM start + } + + virtual void prepare_for_verify() { + // No heap verification. + } + + virtual void print_on(outputStream *st) const { + // Print nothing. + } + + 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_tracing_info() const { + Log(gc) log; + log.info("Epsilon: yup, we are still alive."); + log.info("Allocated " SIZE_FORMAT "K in this session.", + pointer_delta((HeapWord*)_current, _start) * HeapWordSize / K); + } + + virtual void verify(VerifyOption option) { + // No heap verification for Epsilon. + } + +}; --- /dev/null 2017-02-09 18:28:35.238523416 +0100 +++ new/src/share/vm/gc/epsilon/epsilonCollectorPolicy.hpp 2017-02-13 21:50:19.573730237 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef HOTSPOT_EPSILONCOLLECTORPOLICY_HPP_H +#define HOTSPOT_EPSILONCOLLECTORPOLICY_HPP_H + +#include "gc/shared/collectorPolicy.hpp" + +class EpsilonCollectorPolicy: public CollectorPolicy { +protected: + virtual void initialize_alignments() { + size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size(); + _space_alignment = page_size; + _heap_alignment = page_size; + } + +public: + EpsilonCollectorPolicy() : CollectorPolicy() {}; +}; + +#endif