mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8325259: Serial: Inline OldGenScanClosure during Young GC
Reviewed-by: stefank, tschatzl
This commit is contained in:
parent
ab5e94777c
commit
0ea75b28d4
@ -26,19 +26,18 @@
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "gc/serial/cardTableRS.hpp"
|
||||
#include "gc/serial/generation.hpp"
|
||||
#include "gc/serial/serialHeap.hpp"
|
||||
#include "gc/serial/tenuredGeneration.hpp"
|
||||
#include "gc/serial/serialHeap.inline.hpp"
|
||||
#include "gc/shared/space.inline.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
|
||||
void CardTableRS::younger_refs_in_space_iterate(TenuredSpace* sp,
|
||||
OopIterateClosure* cl) {
|
||||
void CardTableRS::scan_old_to_young_refs(TenuredSpace* sp) {
|
||||
verify_used_region_at_save_marks(sp);
|
||||
|
||||
const MemRegion urasm = sp->used_region_at_save_marks();
|
||||
if (!urasm.is_empty()) {
|
||||
non_clean_card_iterate(sp, urasm, cl, this);
|
||||
OldGenScanClosure cl(SerialHeap::heap()->young_gen());
|
||||
non_clean_card_iterate(sp, urasm, &cl, this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,7 +224,7 @@ static void prefetch_write(void *p) {
|
||||
}
|
||||
|
||||
static void scan_obj_with_limit(oop obj,
|
||||
OopIterateClosure* cl,
|
||||
OldGenScanClosure* cl,
|
||||
HeapWord* start,
|
||||
HeapWord* end) {
|
||||
if (!obj->is_typeArray()) {
|
||||
@ -236,7 +235,7 @@ static void scan_obj_with_limit(oop obj,
|
||||
|
||||
void CardTableRS::non_clean_card_iterate(TenuredSpace* sp,
|
||||
MemRegion mr,
|
||||
OopIterateClosure* cl,
|
||||
OldGenScanClosure* cl,
|
||||
CardTableRS* ct) {
|
||||
struct {
|
||||
HeapWord* start_addr;
|
||||
@ -267,7 +266,6 @@ void CardTableRS::non_clean_card_iterate(TenuredSpace* sp,
|
||||
|
||||
for (CardValue* current_card = start_card; current_card < end_card; /* empty */) {
|
||||
CardValue* const dirty_l = find_first_dirty_card(current_card, end_card);
|
||||
|
||||
if (dirty_l == end_card) {
|
||||
// No dirty cards to iterate.
|
||||
return;
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "memory/memRegion.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
|
||||
class OldGenScanClosure;
|
||||
class Space;
|
||||
class TenuredGeneration;
|
||||
class TenuredSpace;
|
||||
@ -61,7 +62,7 @@ class CardTableRS : public CardTable {
|
||||
public:
|
||||
CardTableRS(MemRegion whole_heap);
|
||||
|
||||
void younger_refs_in_space_iterate(TenuredSpace* sp, OopIterateClosure* cl);
|
||||
void scan_old_to_young_refs(TenuredSpace* sp);
|
||||
|
||||
virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
|
||||
|
||||
@ -88,7 +89,7 @@ public:
|
||||
// of mr. Clears the dirty cards as they are processed.
|
||||
void non_clean_card_iterate(TenuredSpace* sp,
|
||||
MemRegion mr,
|
||||
OopIterateClosure* cl,
|
||||
OldGenScanClosure* cl,
|
||||
CardTableRS* ct);
|
||||
|
||||
bool is_in_young(const void* p) const override;
|
||||
|
||||
@ -61,91 +61,6 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/stack.inline.hpp"
|
||||
|
||||
class ScavengeHelper {
|
||||
DefNewGeneration* _young_gen;
|
||||
HeapWord* _young_gen_end;
|
||||
public:
|
||||
ScavengeHelper(DefNewGeneration* young_gen) :
|
||||
_young_gen(young_gen),
|
||||
_young_gen_end(young_gen->reserved().end()) {}
|
||||
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return p < _young_gen_end;
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
T heap_oop = RawAccess<>::oop_load(p);
|
||||
// Should we copy the obj?
|
||||
if (!CompressedOops::is_null(heap_oop)) {
|
||||
oop obj = CompressedOops::decode_not_null(heap_oop);
|
||||
if (is_in_young_gen(obj)) {
|
||||
assert(!_young_gen->to()->is_in_reserved(obj), "Scanning field twice?");
|
||||
oop new_obj = obj->is_forwarded() ? obj->forwardee()
|
||||
: _young_gen->copy_to_survivor_space(obj);
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
|
||||
|
||||
// callback
|
||||
f(new_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class InHeapScanClosure : public BasicOopIterateClosure {
|
||||
ScavengeHelper _helper;
|
||||
protected:
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return _helper.is_in_young_gen(p);
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
_helper.try_scavenge(p, f);
|
||||
}
|
||||
|
||||
InHeapScanClosure(DefNewGeneration* young_gen) :
|
||||
BasicOopIterateClosure(young_gen->ref_processor()),
|
||||
_helper(young_gen) {}
|
||||
};
|
||||
|
||||
class OffHeapScanClosure : public OopClosure {
|
||||
ScavengeHelper _helper;
|
||||
protected:
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return _helper.is_in_young_gen(p);
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
_helper.try_scavenge(p, f);
|
||||
}
|
||||
|
||||
OffHeapScanClosure(DefNewGeneration* young_gen) : _helper(young_gen) {}
|
||||
};
|
||||
|
||||
class OldGenScanClosure : public InHeapScanClosure {
|
||||
CardTableRS* _rs;
|
||||
|
||||
template <typename T>
|
||||
void do_oop_work(T* p) {
|
||||
assert(!is_in_young_gen(p), "precondition");
|
||||
|
||||
try_scavenge(p, [&] (oop new_obj) {
|
||||
// If p points to a younger generation, mark the card.
|
||||
if (is_in_young_gen(new_obj)) {
|
||||
_rs->inline_write_ref_field_gc(p);
|
||||
}
|
||||
});
|
||||
}
|
||||
public:
|
||||
OldGenScanClosure(DefNewGeneration* g) : InHeapScanClosure(g),
|
||||
_rs(SerialHeap::heap()->rem_set()) {}
|
||||
|
||||
void do_oop(oop* p) { do_oop_work(p); }
|
||||
void do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
};
|
||||
|
||||
class PromoteFailureClosure : public InHeapScanClosure {
|
||||
template <typename T>
|
||||
void do_oop_work(T* p) {
|
||||
@ -785,11 +700,19 @@ void DefNewGeneration::collect(bool full,
|
||||
{
|
||||
StrongRootsScope srs(0);
|
||||
RootScanClosure root_cl{this};
|
||||
CLDScanClosure cld_scan_closure{this};
|
||||
CLDScanClosure cld_cl{this};
|
||||
|
||||
heap->young_process_roots(&root_cl,
|
||||
&old_gen_cl,
|
||||
&cld_scan_closure);
|
||||
MarkingCodeBlobClosure code_cl(&root_cl,
|
||||
CodeBlobToOopClosure::FixRelocations,
|
||||
false /* keepalive_nmethods */);
|
||||
|
||||
heap->process_roots(SerialHeap::SO_ScavengeCodeCache,
|
||||
&root_cl,
|
||||
&cld_cl,
|
||||
&cld_cl,
|
||||
&code_cl);
|
||||
|
||||
_old_gen->scan_old_to_young_refs();
|
||||
}
|
||||
|
||||
// "evacuate followers".
|
||||
|
||||
@ -146,17 +146,6 @@ GrowableArray<MemoryPool*> SerialHeap::memory_pools() {
|
||||
return memory_pools;
|
||||
}
|
||||
|
||||
void SerialHeap::young_process_roots(OopClosure* root_closure,
|
||||
OopIterateClosure* old_gen_closure,
|
||||
CLDClosure* cld_closure) {
|
||||
MarkingCodeBlobClosure mark_code_closure(root_closure, CodeBlobToOopClosure::FixRelocations, false /* keepalive nmethods */);
|
||||
|
||||
process_roots(SO_ScavengeCodeCache, root_closure,
|
||||
cld_closure, cld_closure, &mark_code_closure);
|
||||
|
||||
old_gen()->younger_refs_iterate(old_gen_closure);
|
||||
}
|
||||
|
||||
void SerialHeap::safepoint_synchronize_begin() {
|
||||
if (UseStringDeduplication) {
|
||||
SuspendibleThreadSet::synchronize();
|
||||
|
||||
@ -372,10 +372,6 @@ public:
|
||||
void oop_since_save_marks_iterate(OopClosureType1* cur,
|
||||
OopClosureType2* older);
|
||||
|
||||
void young_process_roots(OopClosure* root_closure,
|
||||
OopIterateClosure* old_gen_closure,
|
||||
CLDClosure* cld_closure);
|
||||
|
||||
void safepoint_synchronize_begin() override;
|
||||
void safepoint_synchronize_end() override;
|
||||
|
||||
|
||||
@ -37,4 +37,89 @@ void SerialHeap::oop_since_save_marks_iterate(OopClosureType1* cur,
|
||||
old_gen()->oop_since_save_marks_iterate(older);
|
||||
}
|
||||
|
||||
class ScavengeHelper {
|
||||
DefNewGeneration* _young_gen;
|
||||
HeapWord* _young_gen_end;
|
||||
public:
|
||||
ScavengeHelper(DefNewGeneration* young_gen) :
|
||||
_young_gen(young_gen),
|
||||
_young_gen_end(young_gen->reserved().end()) {}
|
||||
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return p < _young_gen_end;
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
T heap_oop = RawAccess<>::oop_load(p);
|
||||
// Should we copy the obj?
|
||||
if (!CompressedOops::is_null(heap_oop)) {
|
||||
oop obj = CompressedOops::decode_not_null(heap_oop);
|
||||
if (is_in_young_gen(obj)) {
|
||||
assert(!_young_gen->to()->is_in_reserved(obj), "Scanning field twice?");
|
||||
oop new_obj = obj->is_forwarded() ? obj->forwardee()
|
||||
: _young_gen->copy_to_survivor_space(obj);
|
||||
RawAccess<IS_NOT_NULL>::oop_store(p, new_obj);
|
||||
|
||||
// callback
|
||||
f(new_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class InHeapScanClosure : public BasicOopIterateClosure {
|
||||
ScavengeHelper _helper;
|
||||
protected:
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return _helper.is_in_young_gen(p);
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
_helper.try_scavenge(p, f);
|
||||
}
|
||||
|
||||
InHeapScanClosure(DefNewGeneration* young_gen) :
|
||||
BasicOopIterateClosure(young_gen->ref_processor()),
|
||||
_helper(young_gen) {}
|
||||
};
|
||||
|
||||
class OffHeapScanClosure : public OopClosure {
|
||||
ScavengeHelper _helper;
|
||||
protected:
|
||||
bool is_in_young_gen(void* p) const {
|
||||
return _helper.is_in_young_gen(p);
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void try_scavenge(T* p, Func&& f) {
|
||||
_helper.try_scavenge(p, f);
|
||||
}
|
||||
|
||||
OffHeapScanClosure(DefNewGeneration* young_gen) : _helper(young_gen) {}
|
||||
};
|
||||
|
||||
class OldGenScanClosure : public InHeapScanClosure {
|
||||
CardTableRS* _rs;
|
||||
|
||||
template <typename T>
|
||||
void do_oop_work(T* p) {
|
||||
assert(!is_in_young_gen(p), "precondition");
|
||||
|
||||
try_scavenge(p, [&] (oop new_obj) {
|
||||
// If p points to a younger generation, mark the card.
|
||||
if (is_in_young_gen(new_obj)) {
|
||||
_rs->inline_write_ref_field_gc(p);
|
||||
}
|
||||
});
|
||||
}
|
||||
public:
|
||||
OldGenScanClosure(DefNewGeneration* g) : InHeapScanClosure(g),
|
||||
_rs(SerialHeap::heap()->rem_set()) {}
|
||||
|
||||
void do_oop(oop* p) { do_oop_work(p); }
|
||||
void do_oop(narrowOop* p) { do_oop_work(p); }
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SERIAL_SERIALHEAP_INLINE_HPP
|
||||
|
||||
@ -267,14 +267,8 @@ HeapWord* TenuredGeneration::block_start(const void* p) const {
|
||||
return space()->block_start_const(p);
|
||||
}
|
||||
|
||||
void TenuredGeneration::younger_refs_iterate(OopIterateClosure* blk) {
|
||||
// Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in
|
||||
// "sp" that point into the young generation.
|
||||
// The iteration is only over objects allocated at the start of the
|
||||
// iterations; objects allocated as a result of applying the closure are
|
||||
// not included.
|
||||
|
||||
_rs->younger_refs_in_space_iterate(space(), blk);
|
||||
void TenuredGeneration::scan_old_to_young_refs() {
|
||||
_rs->scan_old_to_young_refs(space());
|
||||
}
|
||||
|
||||
TenuredGeneration::TenuredGeneration(ReservedSpace rs,
|
||||
|
||||
@ -100,7 +100,7 @@ class TenuredGeneration: public Generation {
|
||||
|
||||
HeapWord* block_start(const void* p) const;
|
||||
|
||||
void younger_refs_iterate(OopIterateClosure* blk);
|
||||
void scan_old_to_young_refs();
|
||||
|
||||
bool is_in(const void* p) const;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user