8276229: Stop allowing implicit updates in G1BlockOffsetTable
Reviewed-by: tschatzl, ayang
This commit is contained in:
parent
7719a74cec
commit
1d79cfd3a1
@ -213,42 +213,6 @@ void G1BlockOffsetTablePart::check_all_cards(size_t start_card, size_t end_card)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_slow(HeapWord* q,
|
|
||||||
HeapWord* n,
|
|
||||||
const void* addr) {
|
|
||||||
// We're not in the normal case. We need to handle an important subcase
|
|
||||||
// here: LAB allocation. An allocation previously recorded in the
|
|
||||||
// offset table was actually a lab allocation, and was divided into
|
|
||||||
// several objects subsequently. Fix this situation as we answer the
|
|
||||||
// query, by updating entries as we cross them.
|
|
||||||
|
|
||||||
// If the fist object's end q is at the card boundary. Start refining
|
|
||||||
// with the corresponding card (the value of the entry will be basically
|
|
||||||
// set to 0). If the object crosses the boundary -- start from the next card.
|
|
||||||
size_t n_index = _bot->index_for(n);
|
|
||||||
size_t next_index = _bot->index_for(n) + !_bot->is_card_boundary(n);
|
|
||||||
// Calculate a consistent next boundary. If "n" is not at the boundary
|
|
||||||
// already, step to the boundary.
|
|
||||||
HeapWord* next_boundary = _bot->address_for_index(n_index) +
|
|
||||||
(n_index == next_index ? 0 : BOTConstants::N_words);
|
|
||||||
assert(next_boundary <= _bot->_reserved.end(),
|
|
||||||
"next_boundary is beyond the end of the covered region "
|
|
||||||
" next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT,
|
|
||||||
p2i(next_boundary), p2i(_bot->_reserved.end()));
|
|
||||||
while (next_boundary < addr) {
|
|
||||||
while (n <= next_boundary) {
|
|
||||||
q = n;
|
|
||||||
oop obj = cast_to_oop(q);
|
|
||||||
if (obj->klass_or_null_acquire() == NULL) return q;
|
|
||||||
n += block_size(q);
|
|
||||||
}
|
|
||||||
assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
|
|
||||||
// [q, n) is the block that crosses the boundary.
|
|
||||||
alloc_block_work(&next_boundary, q, n);
|
|
||||||
}
|
|
||||||
return forward_to_block_containing_addr_const(q, n, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// threshold_
|
// threshold_
|
||||||
// | _index_
|
// | _index_
|
||||||
|
@ -141,26 +141,11 @@ private:
|
|||||||
// Returns the address of a block whose start is at most "addr".
|
// Returns the address of a block whose start is at most "addr".
|
||||||
inline HeapWord* block_at_or_preceding(const void* addr) const;
|
inline HeapWord* block_at_or_preceding(const void* addr) const;
|
||||||
|
|
||||||
|
// Return the address of the beginning of the block that contains "addr".
|
||||||
// "q" is a block boundary that is <= "addr"; "n" is the address of the
|
// "q" is a block boundary that is <= "addr"; "n" is the address of the
|
||||||
// next block (or the end of the space.) Return the address of the
|
// next block (or the end of the space.)
|
||||||
// beginning of the block that contains "addr". Does so without side
|
inline HeapWord* forward_to_block_containing_addr(HeapWord* q, HeapWord* n,
|
||||||
// effects (see, e.g., spec of block_start.)
|
const void* addr) const;
|
||||||
inline HeapWord* forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n,
|
|
||||||
const void* addr) const;
|
|
||||||
|
|
||||||
// "q" is a block boundary that is <= "addr"; return the address of the
|
|
||||||
// beginning of the block that contains "addr". May have side effects
|
|
||||||
// on "this", by updating imprecise entries.
|
|
||||||
inline HeapWord* forward_to_block_containing_addr(HeapWord* q,
|
|
||||||
const void* addr);
|
|
||||||
|
|
||||||
// "q" is a block boundary that is <= "addr"; "n" is the address of the
|
|
||||||
// next block (or the end of the space.) Return the address of the
|
|
||||||
// beginning of the block that contains "addr". May have side effects
|
|
||||||
// on "this", by updating imprecise entries.
|
|
||||||
HeapWord* forward_to_block_containing_addr_slow(HeapWord* q,
|
|
||||||
HeapWord* n,
|
|
||||||
const void* addr);
|
|
||||||
|
|
||||||
// Requires that "*threshold_" be the first array entry boundary at or
|
// Requires that "*threshold_" be the first array entry boundary at or
|
||||||
// above "blk_start". If the block starts at or crosses "*threshold_", records
|
// above "blk_start". If the block starts at or crosses "*threshold_", records
|
||||||
|
@ -46,16 +46,10 @@ inline HeapWord* G1BlockOffsetTablePart::threshold_for_addr(const void* addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* G1BlockOffsetTablePart::block_start(const void* addr) {
|
inline HeapWord* G1BlockOffsetTablePart::block_start(const void* addr) {
|
||||||
assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address");
|
|
||||||
HeapWord* q = block_at_or_preceding(addr);
|
|
||||||
return forward_to_block_containing_addr(q, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline HeapWord* G1BlockOffsetTablePart::block_start_const(const void* addr) const {
|
|
||||||
assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address");
|
assert(addr >= _hr->bottom() && addr < _hr->top(), "invalid address");
|
||||||
HeapWord* q = block_at_or_preceding(addr);
|
HeapWord* q = block_at_or_preceding(addr);
|
||||||
HeapWord* n = q + block_size(q);
|
HeapWord* n = q + block_size(q);
|
||||||
return forward_to_block_containing_addr_const(q, n, addr);
|
return forward_to_block_containing_addr(q, n, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
u_char G1BlockOffsetTable::offset_array(size_t index) const {
|
u_char G1BlockOffsetTable::offset_array(size_t index) const {
|
||||||
@ -141,9 +135,16 @@ inline HeapWord* G1BlockOffsetTablePart::block_at_or_preceding(const void* addr)
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n,
|
inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWord* q, HeapWord* n,
|
||||||
const void* addr) const {
|
const void* addr) const {
|
||||||
while (n <= addr) {
|
while (n <= addr) {
|
||||||
|
// When addr is not covered by the block starting at q we need to
|
||||||
|
// step forward until we find the correct block. With the BOT
|
||||||
|
// being precise, we should never have to step through more than
|
||||||
|
// a single card.
|
||||||
|
assert(_bot->index_for(n) == _bot->index_for(addr),
|
||||||
|
"BOT not precise. Index for n: " SIZE_FORMAT " must be equal to the index for addr: " SIZE_FORMAT,
|
||||||
|
_bot->index_for(n), _bot->index_for(addr));
|
||||||
q = n;
|
q = n;
|
||||||
oop obj = cast_to_oop(q);
|
oop obj = cast_to_oop(q);
|
||||||
if (obj->klass_or_null_acquire() == NULL) {
|
if (obj->klass_or_null_acquire() == NULL) {
|
||||||
@ -156,21 +157,4 @@ inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr_const(
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* G1BlockOffsetTablePart::forward_to_block_containing_addr(HeapWord* q,
|
|
||||||
const void* addr) {
|
|
||||||
if (cast_to_oop(q)->klass_or_null_acquire() == NULL) {
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
HeapWord* n = q + block_size(q);
|
|
||||||
// In the normal case, where the query "addr" is a card boundary, and the
|
|
||||||
// offset table chunks are the same size as cards, the block starting at
|
|
||||||
// "q" will contain addr, so the test below will fail, and we'll fall
|
|
||||||
// through quickly.
|
|
||||||
if (n <= addr) {
|
|
||||||
q = forward_to_block_containing_addr_slow(q, n, addr);
|
|
||||||
}
|
|
||||||
assert(q <= addr, "wrong order for current and arg");
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SHARE_GC_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
|
#endif // SHARE_GC_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
|
||||||
|
@ -84,10 +84,6 @@ inline HeapWord* HeapRegion::block_start(const void* p) {
|
|||||||
return _bot_part.block_start(p);
|
return _bot_part.block_start(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline HeapWord* HeapRegion::block_start_const(const void* p) const {
|
|
||||||
return _bot_part.block_start_const(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool HeapRegion::is_obj_dead_with_size(const oop obj, const G1CMBitMap* const prev_bitmap, size_t* size) const {
|
inline bool HeapRegion::is_obj_dead_with_size(const oop obj, const G1CMBitMap* const prev_bitmap, size_t* size) const {
|
||||||
HeapWord* addr = cast_from_oop<HeapWord*>(obj);
|
HeapWord* addr = cast_from_oop<HeapWord*>(obj);
|
||||||
|
|
||||||
@ -356,8 +352,6 @@ HeapWord* HeapRegion::oops_on_memregion_seq_iterate_careful(MemRegion mr,
|
|||||||
HeapWord* const end = mr.end();
|
HeapWord* const end = mr.end();
|
||||||
|
|
||||||
// Find the obj that extends onto mr.start().
|
// Find the obj that extends onto mr.start().
|
||||||
// Update BOT as needed while finding start of (possibly dead)
|
|
||||||
// object containing the start of the region.
|
|
||||||
HeapWord* cur = block_start(start);
|
HeapWord* cur = block_start(start);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user