--- old/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java 2014-06-25 13:43:33.179418042 +0200 +++ new/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java 2014-06-25 13:43:33.071413638 +0200 @@ -24,23 +24,26 @@ package sun.jvm.hotspot.gc_implementation.g1; +import java.util.ArrayList; +import java.util.List; import java.util.Observable; import java.util.Observer; - import sun.jvm.hotspot.debugger.Address; -import sun.jvm.hotspot.memory.ContiguousSpace; +import sun.jvm.hotspot.memory.CompactibleSpace; +import sun.jvm.hotspot.memory.MemRegion; import sun.jvm.hotspot.runtime.VM; +import sun.jvm.hotspot.types.AddressField; import sun.jvm.hotspot.types.CIntegerField; import sun.jvm.hotspot.types.Type; import sun.jvm.hotspot.types.TypeDataBase; // Mirror class for HeapRegion. Currently we don't actually include -// any of its fields but only iterate over it (which we get "for free" -// as HeapRegion ultimately inherits from ContiguousSpace). +// any of its fields but only iterate over it. -public class HeapRegion extends ContiguousSpace { +public class HeapRegion extends CompactibleSpace { // static int GrainBytes; static private CIntegerField grainBytesField; + static private AddressField topField; static { VM.registerVMInitializedObserver(new Observer() { @@ -54,6 +57,8 @@ Type type = db.lookupType("HeapRegion"); grainBytesField = type.getCIntegerField("GrainBytes"); + topField = type.getAddressField("_top"); + } static public long grainBytes() { @@ -63,4 +68,25 @@ public HeapRegion(Address addr) { super(addr); } + + public Address top() { + return topField.getValue(addr); + } + + @Override + public List getLiveRegions() { + List res = new ArrayList(); + res.add(new MemRegion(bottom(), top())); + return res; + } + + @Override + public long used() { + return top().minus(bottom()); + } + + @Override + public long free() { + return end().minus(top()); + } } --- old/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp 2014-06-25 13:43:33.851445446 +0200 +++ new/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp 2014-06-25 13:43:33.747441204 +0200 @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCREGION_INLINE_HPP #include "gc_implementation/g1/g1AllocRegion.hpp" +#include "gc_implementation/g1/heapRegion.inline.hpp" inline HeapWord* G1AllocRegion::allocate(HeapRegion* alloc_region, size_t word_size, --- old/src/share/vm/gc_implementation/g1/heapRegion.cpp 2014-06-25 13:43:34.495471706 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.cpp 2014-06-25 13:43:34.391467465 +0200 @@ -1038,6 +1038,7 @@ void G1OffsetTableContigSpace::clear(bool mangle_space) { set_top(bottom()); + set_saved_mark_word(bottom()); CompactibleSpace::clear(mangle_space); _offsets.zero_bottom_entry(); _offsets.initialize_threshold(); @@ -1108,11 +1109,10 @@ void G1OffsetTableContigSpace::object_iterate(ObjectClosure* blk) { HeapWord* p = bottom(); - if (!block_is_obj(p)) { - p += block_size(p); - } while (p < top()) { - blk->do_object(oop(p)); + if (block_is_obj(p)) { + blk->do_object(oop(p)); + } p += block_size(p); } } @@ -1126,7 +1126,6 @@ G1OffsetTableContigSpace:: G1OffsetTableContigSpace(G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) : - _top(bottom()), _offsets(sharedOffsetArray, mr), _par_alloc_lock(Mutex::leaf, "OffsetTableContigSpace par alloc lock", true), _gc_time_stamp(0) @@ -1134,6 +1133,7 @@ _offsets.set_space(this); // false ==> we'll do the clearing if there's clearing to be done. CompactibleSpace::initialize(mr, false, SpaceDecorator::Mangle); + _top = bottom(); _offsets.zero_bottom_entry(); _offsets.initialize_threshold(); } --- old/src/share/vm/gc_implementation/g1/heapRegion.hpp 2014-06-25 13:43:35.163498946 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.hpp 2014-06-25 13:43:35.055494542 +0200 @@ -127,8 +127,6 @@ friend class VMStructs; HeapWord* _top; protected: - inline HeapWord* cas_allocate_inner(size_t size); - inline HeapWord* allocate_inner(size_t size); G1BlockOffsetArrayContigSpace _offsets; Mutex _par_alloc_lock; volatile unsigned _gc_time_stamp; @@ -144,8 +142,16 @@ G1OffsetTableContigSpace(G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr); - inline void set_top(HeapWord* value) { _top = value; } + void set_top(HeapWord* value) { _top = value; } HeapWord* top() const { return _top; } + + protected: + HeapWord** top_addr() { return &_top; } + // Allocation helpers (return NULL if full). + inline HeapWord* allocate_impl(size_t word_size, HeapWord* end_value); + inline HeapWord* par_allocate_impl(size_t word_size, HeapWord* end_value); + + public: void reset_after_compaction() { set_top(compaction_top()); } size_t used() const { return byte_size(bottom(), top()); } @@ -364,7 +370,11 @@ ParMarkRootClaimValue = 9 }; + // All allocated blocks are occupied by objects in a HeapRegion bool block_is_obj(const HeapWord* p) const; + + // Returns the object size for all valid block starts + // and the amount of unallocated words if called on top() size_t block_size(const HeapWord* p) const; inline HeapWord* par_allocate_no_bot_updates(size_t word_size); --- old/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp 2014-06-25 13:43:35.811525370 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp 2014-06-25 13:43:35.707521129 +0200 @@ -31,38 +31,43 @@ #include "memory/space.hpp" #include "runtime/atomic.inline.hpp" -inline HeapWord* G1OffsetTableContigSpace::cas_allocate_inner(size_t size) { +// This version requires locking. +inline HeapWord* G1OffsetTableContigSpace::allocate_impl(size_t size, + HeapWord* const end_value) { HeapWord* obj = top(); + if (pointer_delta(end_value, obj) >= size) { + HeapWord* new_top = obj + size; + set_top(new_top); + assert(is_aligned(obj) && is_aligned(new_top), "checking alignment"); + return obj; + } else { + return NULL; + } +} + +// This version is lock-free. +inline HeapWord* G1OffsetTableContigSpace::par_allocate_impl(size_t size, + HeapWord* const end_value) { do { - if (pointer_delta(end(), obj) >= size) { + HeapWord* obj = top(); + if (pointer_delta(end_value, obj) >= size) { HeapWord* new_top = obj + size; - HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, &_top, obj); + HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj); + // result can be one of two: + // the old top value: the exchange succeeded + // otherwise: the new value of the top is returned. if (result == obj) { assert(is_aligned(obj) && is_aligned(new_top), "checking alignment"); return obj; } - obj = result; } else { - break; + return NULL; } } while (true); - return NULL; } -inline HeapWord* G1OffsetTableContigSpace::allocate_inner(size_t size) { - HeapWord* obj = top(); - if (pointer_delta(end(), obj) >= size) { - HeapWord* new_top = obj + size; - assert(is_aligned(obj) && is_aligned(new_top), "checking alignment"); - set_top(new_top); - return obj; - } - return NULL; -} - - inline HeapWord* G1OffsetTableContigSpace::allocate(size_t size) { - HeapWord* res = allocate_inner(size); + HeapWord* res = allocate_impl(size, end()); if (res != NULL) { _offsets.alloc_block(res, size); } @@ -104,12 +109,12 @@ inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) { assert(is_young(), "we can only skip BOT updates on young regions"); - return cas_allocate_inner(word_size); + return par_allocate_impl(word_size, end()); } inline HeapWord* HeapRegion::allocate_no_bot_updates(size_t word_size) { assert(is_young(), "we can only skip BOT updates on young regions"); - return allocate_inner(word_size); + return allocate_impl(word_size, end()); } inline void HeapRegion::note_start_of_marking() { --- old/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp 2014-06-25 13:43:36.459551795 +0200 +++ new/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp 2014-06-25 13:43:36.355547554 +0200 @@ -34,6 +34,8 @@ static_field(HeapRegion, GrainBytes, size_t) \ static_field(HeapRegion, LogOfHRGrainBytes, int) \ \ + nonstatic_field(G1OffsetTableContigSpace, _top, HeapWord*) \ + \ nonstatic_field(G1HeapRegionTable, _base, address) \ nonstatic_field(G1HeapRegionTable, _length, size_t) \ nonstatic_field(G1HeapRegionTable, _biased_base, address) \