< prev index next >
src/share/vm/gc/shared/space.inline.hpp
Print this page
*** 29,38 ****
--- 29,39 ----
#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/generation.hpp"
#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"
inline HeapWord* Space::block_start(const void* p) {
return block_start_const(p);
*** 73,82 ****
--- 74,134 ----
size_t CompactibleSpace::obj_size(const HeapWord* addr) const {
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 <class SpaceType>
inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* cp) {
// Compute the new addresses for the live objects and store it in the mark
// Used by universe::mark_sweep_phase2()
*** 93,114 ****
cp->space->set_compaction_top(cp->space->bottom());
}
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;
! }
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.
const intx interval = PrefetchScanIntervalInBytes;
--- 145,155 ----
cp->space->set_compaction_top(cp->space->bottom());
}
HeapWord* compact_top = cp->space->compaction_top(); // This is where we are currently compacting to.
! 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.
const intx interval = PrefetchScanIntervalInBytes;
*** 120,130 ****
assert(!space->scanned_block_is_obj(cur_obj) ||
oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() ||
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::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);
cur_obj += size;
end_of_live = cur_obj;
--- 161,171 ----
assert(!space->scanned_block_is_obj(cur_obj) ||
oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() ||
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 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);
cur_obj += size;
end_of_live = cur_obj;
*** 137,166 ****
end += space->scanned_block_size(end);
} while (end < scan_limit && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked()));
// 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;
! }
! }
!
// 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;
}
}
--- 178,202 ----
end += space->scanned_block_size(end);
} while (end < scan_limit && (!space->scanned_block_is_obj(end) || !oop(end)->is_gc_marked()));
// see if we might want to pretend this object is alive so that
// we don't have to compact quite as often.
! 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;
}
+ }
// move on to the next object
cur_obj = end;
}
}
< prev index next >