--- old/src/share/vm/gc/shared/space.cpp 2016-04-13 16:05:18.155285303 +0200 +++ new/src/share/vm/gc/shared/space.cpp 2016-04-13 16:05:18.031285298 +0200 @@ -411,22 +411,6 @@ return compact_top; } - -bool CompactibleSpace::insert_deadspace(size_t& allowed_deadspace_words, - HeapWord* q, size_t deadlength) { - if (allowed_deadspace_words >= deadlength) { - allowed_deadspace_words -= deadlength; - CollectedHeap::fill_with_object(q, deadlength); - oop(q)->set_mark(oop(q)->mark()->set_marked()); - assert((int) deadlength == oop(q)->size(), "bad filler object size"); - // Recall that we required "q == compaction_top". - return true; - } else { - allowed_deadspace_words = 0; - return false; - } -} - void ContiguousSpace::prepare_for_compaction(CompactPoint* cp) { scan_and_forward(this, cp); } --- old/src/share/vm/gc/shared/space.hpp 2016-04-13 16:05:18.391285313 +0200 +++ new/src/share/vm/gc/shared/space.hpp 2016-04-13 16:05:18.259285308 +0200 @@ -455,16 +455,6 @@ return end(); } - // Requires "allowed_deadspace_words > 0", that "q" is the start of a - // free block of the given "word_len", and that "q", were it an object, - // would not move if forwarded. If the size allows, fill the free - // block with an object, to prevent excessive compaction. Returns "true" - // iff the free region was made deadspace, and modifies - // "allowed_deadspace_words" to reflect the number of available deadspace - // words remaining after this operation. - bool insert_deadspace(size_t& allowed_deadspace_words, HeapWord* q, - size_t word_len); - // Below are template functions for scan_and_* algorithms (avoiding virtual calls). // The space argument should be a subclass of CompactibleSpace, implementing // scan_limit(), scanned_block_is_obj(), and scanned_block_size(), --- old/src/share/vm/gc/shared/space.inline.hpp 2016-04-13 16:05:18.635285323 +0200 +++ new/src/share/vm/gc/shared/space.inline.hpp 2016-04-13 16:05:18.499285318 +0200 @@ -31,6 +31,7 @@ #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" #include "memory/universe.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepoint.hpp" @@ -75,6 +76,57 @@ return oop(addr)->size(); } +class DeadSpacer : StackObj { + size_t _allowed_deadspace_words; + bool _active; + CompactibleSpace* _space; + +public: + DeadSpacer(CompactibleSpace* space) : _space(space), _allowed_deadspace_words(0) { + size_t ratio = _space->allowed_dead_ratio(); + _active = ratio > 0; + + if (_active) { + assert(!UseG1GC, "G1 should not be using dead space"); + + // We allow some amount of garbage towards the bottom of the space, so + // we don't start compacting before there is a significant gain to be made. + // Occasionally, we want to ensure a full compaction, which is determined + // by the MarkSweepAlwaysCompactCount parameter. + if ((MarkSweep::total_invocations() % MarkSweepAlwaysCompactCount) != 0) { + _allowed_deadspace_words = (space->capacity() * ratio / 100) / HeapWordSize; + } else { + _active = false; + } + } + } + + + bool insert_deadspace(HeapWord* dead_start, HeapWord* dead_end) { + if (!_active) { + return false; + } + + size_t dead_length = pointer_delta(dead_end, dead_start); + if (_allowed_deadspace_words >= dead_length) { + _allowed_deadspace_words -= dead_length; + CollectedHeap::fill_with_object(dead_start, dead_length); + oop obj = oop(dead_start); + obj->set_mark(obj->mark()->set_marked()); + + assert(dead_length == (size_t)obj->size(), "bad filler object size"); + log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b", + p2i(dead_start), p2i(dead_end), dead_length * HeapWordSize); + + return true; + } else { + _active = false; + return false; + } + } + +}; + template inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) { // Compute the new addresses for the live objects and store it in the mark @@ -95,18 +147,7 @@ HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to. - // We allow some amount of garbage towards the bottom of the space, so - // we don't start compacting before there is a significant gain to be made. - // Occasionally, we want to ensure a full compaction, which is determined - // by the MarkSweepAlwaysCompactCount parameter. - uint invocations = MarkSweep::total_invocations(); - bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0); - - size_t allowed_deadspace = 0; - if (skip_dead) { - const size_t ratio = space->allowed_dead_ratio(); - allowed_deadspace = (space->capacity() * ratio / 100) / HeapWordSize; - } + DeadSpacer dead_spacer(space); HeapWord* end_of_live = space->bottom(); // One byte beyond the last byte of the last live object. HeapWord* first_dead = NULL; // The first dead object. @@ -122,7 +163,7 @@ oop(cur_obj)->mark()->has_bias_pattern(), "these are the only valid states during a mark sweep"); if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) { - // prefetch beyond q + // prefetch beyond cur_obj Prefetch::write(cur_obj, interval); size_t size = space->scanned_block_size(cur_obj); compact_top = cp->space->forward(oop(cur_obj), size, cp, compact_top); @@ -139,27 +180,22 @@ // see if we might want to pretend this object is alive so that // we don't have to compact quite as often. - if (allowed_deadspace > 0 && cur_obj == compact_top) { - assert(!UseG1GC, "G1 should not be allowing dead space"); - size_t sz = pointer_delta(end, cur_obj); - if (space->insert_deadspace(allowed_deadspace, cur_obj, sz)) { - compact_top = cp->space->forward(oop(cur_obj), sz, cp, compact_top); - cur_obj = end; - end_of_live = end; - continue; + if (cur_obj == compact_top && dead_spacer.insert_deadspace(cur_obj, end)) { + oop obj = oop(cur_obj); + compact_top = cp->space->forward(obj, obj->size(), cp, compact_top); + end_of_live = end; + } else { + // otherwise, it really is a free region. + + // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. + *(HeapWord**)cur_obj = end; + + // see if this is the first dead region. + if (first_dead == NULL) { + first_dead = cur_obj; } } - // otherwise, it really is a free region. - - // cur_obj is a pointer to a dead object. Use this dead memory to store a pointer to the next live object. - *(HeapWord**)cur_obj = end; - - // see if this is the first dead region. - if (first_dead == NULL) { - first_dead = cur_obj; - } - // move on to the next object cur_obj = end; }