8015486: PSScavenge::is_obj_in_young is unnecessarily slow with UseCompressedOops

Compare compressed oops to a compressed young gen boundary instead of uncompressing the oops before doing the young gen boundary check.

Reviewed-by: brutisso, jmasa
This commit is contained in:
Stefan Karlsson 2013-05-30 10:58:16 +02:00
parent de314e391b
commit c39235c377
4 changed files with 35 additions and 22 deletions

View File

@ -42,7 +42,7 @@ inline void PSPromotionManager::claim_or_forward_internal_depth(T* p) {
if (o->is_forwarded()) { if (o->is_forwarded()) {
o = o->forwardee(); o = o->forwardee();
// Card mark // Card mark
if (PSScavenge::is_obj_in_young((HeapWord*) o)) { if (PSScavenge::is_obj_in_young(o)) {
PSScavenge::card_table()->inline_write_ref_field_gc(p, o); PSScavenge::card_table()->inline_write_ref_field_gc(p, o);
} }
oopDesc::encode_store_heap_oop_not_null(p, o); oopDesc::encode_store_heap_oop_not_null(p, o);

View File

@ -61,6 +61,7 @@ CardTableExtension* PSScavenge::_card_table = NULL;
bool PSScavenge::_survivor_overflow = false; bool PSScavenge::_survivor_overflow = false;
uint PSScavenge::_tenuring_threshold = 0; uint PSScavenge::_tenuring_threshold = 0;
HeapWord* PSScavenge::_young_generation_boundary = NULL; HeapWord* PSScavenge::_young_generation_boundary = NULL;
uintptr_t PSScavenge::_young_generation_boundary_compressed = 0;
elapsedTimer PSScavenge::_accumulated_time; elapsedTimer PSScavenge::_accumulated_time;
Stack<markOop, mtGC> PSScavenge::_preserved_mark_stack; Stack<markOop, mtGC> PSScavenge::_preserved_mark_stack;
Stack<oop, mtGC> PSScavenge::_preserved_oop_stack; Stack<oop, mtGC> PSScavenge::_preserved_oop_stack;
@ -71,7 +72,7 @@ bool PSScavenge::_promotion_failed = false;
class PSIsAliveClosure: public BoolObjectClosure { class PSIsAliveClosure: public BoolObjectClosure {
public: public:
bool do_object_b(oop p) { bool do_object_b(oop p) {
return (!PSScavenge::is_obj_in_young((HeapWord*) p)) || p->is_forwarded(); return (!PSScavenge::is_obj_in_young(p)) || p->is_forwarded();
} }
}; };
@ -815,7 +816,7 @@ void PSScavenge::initialize() {
// Set boundary between young_gen and old_gen // Set boundary between young_gen and old_gen
assert(old_gen->reserved().end() <= young_gen->eden_space()->bottom(), assert(old_gen->reserved().end() <= young_gen->eden_space()->bottom(),
"old above young"); "old above young");
_young_generation_boundary = young_gen->eden_space()->bottom(); set_young_generation_boundary(young_gen->eden_space()->bottom());
// Initialize ref handling object for scavenging. // Initialize ref handling object for scavenging.
MemRegion mr = young_gen->reserved(); MemRegion mr = young_gen->reserved();

View File

@ -62,19 +62,22 @@ class PSScavenge: AllStatic {
protected: protected:
// Flags/counters // Flags/counters
static ReferenceProcessor* _ref_processor; // Reference processor for scavenging. static ReferenceProcessor* _ref_processor; // Reference processor for scavenging.
static PSIsAliveClosure _is_alive_closure; // Closure used for reference processing static PSIsAliveClosure _is_alive_closure; // Closure used for reference processing
static CardTableExtension* _card_table; // We cache the card table for fast access. static CardTableExtension* _card_table; // We cache the card table for fast access.
static bool _survivor_overflow; // Overflow this collection static bool _survivor_overflow; // Overflow this collection
static uint _tenuring_threshold; // tenuring threshold for next scavenge static uint _tenuring_threshold; // tenuring threshold for next scavenge
static elapsedTimer _accumulated_time; // total time spent on scavenge static elapsedTimer _accumulated_time; // total time spent on scavenge
static HeapWord* _young_generation_boundary; // The lowest address possible for the young_gen. // The lowest address possible for the young_gen.
// This is used to decide if an oop should be scavenged, // This is used to decide if an oop should be scavenged,
// cards should be marked, etc. // cards should be marked, etc.
static HeapWord* _young_generation_boundary;
// Used to optimize compressed oops young gen boundary checking.
static uintptr_t _young_generation_boundary_compressed;
static Stack<markOop, mtGC> _preserved_mark_stack; // List of marks to be restored after failed promotion static Stack<markOop, mtGC> _preserved_mark_stack; // List of marks to be restored after failed promotion
static Stack<oop, mtGC> _preserved_oop_stack; // List of oops that need their mark restored. static Stack<oop, mtGC> _preserved_oop_stack; // List of oops that need their mark restored.
static CollectorCounters* _counters; // collector performance counters static CollectorCounters* _counters; // collector performance counters
static bool _promotion_failed; static bool _promotion_failed;
static void clean_up_failed_promotion(); static void clean_up_failed_promotion();
@ -112,6 +115,9 @@ class PSScavenge: AllStatic {
// boundary moves, _young_generation_boundary must be reset // boundary moves, _young_generation_boundary must be reset
static void set_young_generation_boundary(HeapWord* v) { static void set_young_generation_boundary(HeapWord* v) {
_young_generation_boundary = v; _young_generation_boundary = v;
if (UseCompressedOops) {
_young_generation_boundary_compressed = (uintptr_t)oopDesc::encode_heap_oop((oop)v);
}
} }
// Called by parallelScavengeHeap to init the tenuring threshold // Called by parallelScavengeHeap to init the tenuring threshold
@ -140,11 +146,19 @@ class PSScavenge: AllStatic {
static void copy_and_push_safe_barrier_from_klass(PSPromotionManager* pm, oop* p); static void copy_and_push_safe_barrier_from_klass(PSPromotionManager* pm, oop* p);
// Is an object in the young generation // Is an object in the young generation
// This assumes that the HeapWord argument is in the heap, // This assumes that the 'o' is in the heap,
// so it only checks one side of the complete predicate. // so it only checks one side of the complete predicate.
inline static bool is_obj_in_young(oop o) {
return (HeapWord*)o >= _young_generation_boundary;
}
inline static bool is_obj_in_young(narrowOop o) {
return (uintptr_t)o >= _young_generation_boundary_compressed;
}
inline static bool is_obj_in_young(HeapWord* o) { inline static bool is_obj_in_young(HeapWord* o) {
const bool result = (o >= _young_generation_boundary); return o >= _young_generation_boundary;
return result;
} }
}; };

View File

@ -39,9 +39,7 @@ inline void PSScavenge::save_to_space_top_before_gc() {
template <class T> inline bool PSScavenge::should_scavenge(T* p) { template <class T> inline bool PSScavenge::should_scavenge(T* p) {
T heap_oop = oopDesc::load_heap_oop(p); T heap_oop = oopDesc::load_heap_oop(p);
if (oopDesc::is_null(heap_oop)) return false; return PSScavenge::is_obj_in_young(heap_oop);
oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
return PSScavenge::is_obj_in_young((HeapWord*)obj);
} }
template <class T> template <class T>
@ -94,7 +92,7 @@ inline void PSScavenge::copy_and_push_safe_barrier(PSPromotionManager* pm,
// or from metadata. // or from metadata.
if ((!PSScavenge::is_obj_in_young((HeapWord*)p)) && if ((!PSScavenge::is_obj_in_young((HeapWord*)p)) &&
Universe::heap()->is_in_reserved(p)) { Universe::heap()->is_in_reserved(p)) {
if (PSScavenge::is_obj_in_young((HeapWord*)new_obj)) { if (PSScavenge::is_obj_in_young(new_obj)) {
card_table()->inline_write_ref_field_gc(p, new_obj); card_table()->inline_write_ref_field_gc(p, new_obj);
} }
} }
@ -147,7 +145,7 @@ class PSScavengeFromKlassClosure: public OopClosure {
} }
oopDesc::encode_store_heap_oop_not_null(p, new_obj); oopDesc::encode_store_heap_oop_not_null(p, new_obj);
if (PSScavenge::is_obj_in_young((HeapWord*)new_obj)) { if (PSScavenge::is_obj_in_young(new_obj)) {
do_klass_barrier(); do_klass_barrier();
} }
} }