mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
6730514: assertion failure in mangling code when expanding by 0 bytes
An expansion by 0 bytes was not anticipated when the assertion was composed. Reviewed-by: jjh, jcoomes, apetrusenko
This commit is contained in:
parent
b8633a3b01
commit
74b3de5c3b
9 changed files with 87 additions and 53 deletions
|
@ -107,7 +107,7 @@ ifeq ($(USING_CYGWIN), true)
|
||||||
ABS_OUTPUTDIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(OUTPUTDIR)"))
|
ABS_OUTPUTDIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(OUTPUTDIR)"))
|
||||||
ABS_BOOTDIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(BOOTDIR)"))
|
ABS_BOOTDIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(BOOTDIR)"))
|
||||||
ABS_GAMMADIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(GAMMADIR)"))
|
ABS_GAMMADIR := $(subst /,\\,$(shell /bin/cygpath -m -a "$(GAMMADIR)"))
|
||||||
ABS_OS_MAKEFILE := $(shell /bin/cygpath -m -a "$(HS_BUILD_DIR)/$(OSNAME)")/build.make
|
ABS_OS_MAKEFILE := $(shell /bin/cygpath -m -a "$(HS_MAKE_DIR)/$(OSNAME)")/build.make
|
||||||
else
|
else
|
||||||
ABS_OUTPUTDIR := $(subst /,\\,$(shell $(CD) $(OUTPUTDIR);$(PWD)))
|
ABS_OUTPUTDIR := $(subst /,\\,$(shell $(CD) $(OUTPUTDIR);$(PWD)))
|
||||||
ABS_BOOTDIR := $(subst /,\\,$(shell $(CD) $(BOOTDIR);$(PWD)))
|
ABS_BOOTDIR := $(subst /,\\,$(shell $(CD) $(BOOTDIR);$(PWD)))
|
||||||
|
|
|
@ -3195,31 +3195,16 @@ ConcurrentMarkSweepGeneration::expand_and_allocate(size_t word_size,
|
||||||
// YSR: All of this generation expansion/shrinking stuff is an exact copy of
|
// YSR: All of this generation expansion/shrinking stuff is an exact copy of
|
||||||
// OneContigSpaceCardGeneration, which makes me wonder if we should move this
|
// OneContigSpaceCardGeneration, which makes me wonder if we should move this
|
||||||
// to CardGeneration and share it...
|
// to CardGeneration and share it...
|
||||||
|
bool ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||||
|
return CardGeneration::expand(bytes, expand_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes,
|
void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes,
|
||||||
CMSExpansionCause::Cause cause)
|
CMSExpansionCause::Cause cause)
|
||||||
{
|
{
|
||||||
assert_locked_or_safepoint(Heap_lock);
|
|
||||||
|
|
||||||
size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes);
|
bool success = expand(bytes, expand_bytes);
|
||||||
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
|
||||||
bool success = false;
|
|
||||||
if (aligned_expand_bytes > aligned_bytes) {
|
|
||||||
success = grow_by(aligned_expand_bytes);
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
success = grow_by(aligned_bytes);
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
size_t remaining_bytes = _virtual_space.uncommitted_size();
|
|
||||||
if (remaining_bytes > 0) {
|
|
||||||
success = grow_by(remaining_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GC_locker::is_active()) {
|
|
||||||
if (PrintGC && Verbose) {
|
|
||||||
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// remember why we expanded; this information is used
|
// remember why we expanded; this information is used
|
||||||
// by shouldConcurrentCollect() when making decisions on whether to start
|
// by shouldConcurrentCollect() when making decisions on whether to start
|
||||||
// a new CMS cycle.
|
// a new CMS cycle.
|
||||||
|
|
|
@ -1048,10 +1048,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||||
double _initiating_occupancy;
|
double _initiating_occupancy;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Grow generation by specified size (returns false if unable to grow)
|
|
||||||
bool grow_by(size_t bytes);
|
|
||||||
// Grow generation to reserved size.
|
|
||||||
bool grow_to_reserved();
|
|
||||||
// Shrink generation by specified size (returns false if unable to shrink)
|
// Shrink generation by specified size (returns false if unable to shrink)
|
||||||
virtual void shrink_by(size_t bytes);
|
virtual void shrink_by(size_t bytes);
|
||||||
|
|
||||||
|
@ -1103,6 +1099,11 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||||
// Override
|
// Override
|
||||||
virtual void ref_processor_init();
|
virtual void ref_processor_init();
|
||||||
|
|
||||||
|
// Grow generation by specified size (returns false if unable to grow)
|
||||||
|
bool grow_by(size_t bytes);
|
||||||
|
// Grow generation to reserved size.
|
||||||
|
bool grow_to_reserved();
|
||||||
|
|
||||||
void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; }
|
void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; }
|
||||||
|
|
||||||
// Space enquiries
|
// Space enquiries
|
||||||
|
@ -1193,6 +1194,7 @@ class ConcurrentMarkSweepGeneration: public CardGeneration {
|
||||||
// Allocation failure
|
// Allocation failure
|
||||||
void expand(size_t bytes, size_t expand_bytes,
|
void expand(size_t bytes, size_t expand_bytes,
|
||||||
CMSExpansionCause::Cause cause);
|
CMSExpansionCause::Cause cause);
|
||||||
|
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||||
void shrink(size_t bytes);
|
void shrink(size_t bytes);
|
||||||
HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
|
HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz);
|
||||||
bool expand_and_ensure_spooling_space(PromotionInfo* promo);
|
bool expand_and_ensure_spooling_space(PromotionInfo* promo);
|
||||||
|
|
|
@ -215,10 +215,22 @@ HeapWord* PSOldGen::expand_and_cas_allocate(size_t word_size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PSOldGen::expand(size_t bytes) {
|
void PSOldGen::expand(size_t bytes) {
|
||||||
|
if (bytes == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
MutexLocker x(ExpandHeap_lock);
|
MutexLocker x(ExpandHeap_lock);
|
||||||
const size_t alignment = virtual_space()->alignment();
|
const size_t alignment = virtual_space()->alignment();
|
||||||
size_t aligned_bytes = align_size_up(bytes, alignment);
|
size_t aligned_bytes = align_size_up(bytes, alignment);
|
||||||
size_t aligned_expand_bytes = align_size_up(MinHeapDeltaBytes, alignment);
|
size_t aligned_expand_bytes = align_size_up(MinHeapDeltaBytes, alignment);
|
||||||
|
if (aligned_bytes == 0){
|
||||||
|
// The alignment caused the number of bytes to wrap. An expand_by(0) will
|
||||||
|
// return true with the implication that and expansion was done when it
|
||||||
|
// was not. A call to expand implies a best effort to expand by "bytes"
|
||||||
|
// but not a guarantee. Align down to give a best effort. This is likely
|
||||||
|
// the most that the generation can expand since it has some capacity to
|
||||||
|
// start with.
|
||||||
|
aligned_bytes = align_size_down(bytes, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (aligned_expand_bytes > aligned_bytes) {
|
if (aligned_expand_bytes > aligned_bytes) {
|
||||||
|
@ -231,8 +243,8 @@ void PSOldGen::expand(size_t bytes) {
|
||||||
success = expand_to_reserved();
|
success = expand_to_reserved();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GC_locker::is_active()) {
|
if (PrintGC && Verbose) {
|
||||||
if (PrintGC && Verbose) {
|
if (success && GC_locker::is_active()) {
|
||||||
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,6 +253,9 @@ void PSOldGen::expand(size_t bytes) {
|
||||||
bool PSOldGen::expand_by(size_t bytes) {
|
bool PSOldGen::expand_by(size_t bytes) {
|
||||||
assert_lock_strong(ExpandHeap_lock);
|
assert_lock_strong(ExpandHeap_lock);
|
||||||
assert_locked_or_safepoint(Heap_lock);
|
assert_locked_or_safepoint(Heap_lock);
|
||||||
|
if (bytes == 0) {
|
||||||
|
return true; // That's what virtual_space()->expand_by(0) would return
|
||||||
|
}
|
||||||
bool result = virtual_space()->expand_by(bytes);
|
bool result = virtual_space()->expand_by(bytes);
|
||||||
if (result) {
|
if (result) {
|
||||||
if (ZapUnusedHeapArea) {
|
if (ZapUnusedHeapArea) {
|
||||||
|
|
|
@ -39,7 +39,8 @@ bool SpaceMangler::is_mangled(HeapWord* q) {
|
||||||
|
|
||||||
void SpaceMangler::set_top_for_allocations(HeapWord* v) {
|
void SpaceMangler::set_top_for_allocations(HeapWord* v) {
|
||||||
if (v < end()) {
|
if (v < end()) {
|
||||||
assert(is_mangled(v), "The high water mark is not mangled");
|
assert(!CheckZapUnusedHeapArea || is_mangled(v),
|
||||||
|
"The high water mark is not mangled");
|
||||||
}
|
}
|
||||||
_top_for_allocations = v;
|
_top_for_allocations = v;
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,14 +432,16 @@ bool CompactingPermGenGen::grow_by(size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CompactingPermGenGen::grow_to_reserved() {
|
bool CompactingPermGenGen::grow_to_reserved() {
|
||||||
// Don't allow _virtual_size to expand into shared spaces.
|
// Don't allow _virtual_size to expand into shared spaces.
|
||||||
|
bool success = false;
|
||||||
if (_virtual_space.uncommitted_size() > _shared_space_size) {
|
if (_virtual_space.uncommitted_size() > _shared_space_size) {
|
||||||
size_t remaining_bytes =
|
size_t remaining_bytes =
|
||||||
_virtual_space.uncommitted_size() - _shared_space_size;
|
_virtual_space.uncommitted_size() - _shared_space_size;
|
||||||
bool success = OneContigSpaceCardGeneration::grow_by(remaining_bytes);
|
success = OneContigSpaceCardGeneration::grow_by(remaining_bytes);
|
||||||
DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
|
DEBUG_ONLY(if (!success) warning("grow to reserved failed");)
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ public:
|
||||||
void post_compact();
|
void post_compact();
|
||||||
size_t contiguous_available() const;
|
size_t contiguous_available() const;
|
||||||
bool grow_by(size_t bytes);
|
bool grow_by(size_t bytes);
|
||||||
void grow_to_reserved();
|
virtual bool grow_to_reserved();
|
||||||
|
|
||||||
void clear_remembered_set();
|
void clear_remembered_set();
|
||||||
void invalidate_remembered_set();
|
void invalidate_remembered_set();
|
||||||
|
|
|
@ -379,6 +379,41 @@ CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CardGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||||
|
assert_locked_or_safepoint(Heap_lock);
|
||||||
|
if (bytes == 0) {
|
||||||
|
return true; // That's what grow_by(0) would return
|
||||||
|
}
|
||||||
|
size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes);
|
||||||
|
if (aligned_bytes == 0){
|
||||||
|
// The alignment caused the number of bytes to wrap. An expand_by(0) will
|
||||||
|
// return true with the implication that an expansion was done when it
|
||||||
|
// was not. A call to expand implies a best effort to expand by "bytes"
|
||||||
|
// but not a guarantee. Align down to give a best effort. This is likely
|
||||||
|
// the most that the generation can expand since it has some capacity to
|
||||||
|
// start with.
|
||||||
|
aligned_bytes = ReservedSpace::page_align_size_down(bytes);
|
||||||
|
}
|
||||||
|
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
||||||
|
bool success = false;
|
||||||
|
if (aligned_expand_bytes > aligned_bytes) {
|
||||||
|
success = grow_by(aligned_expand_bytes);
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
success = grow_by(aligned_bytes);
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
success = grow_to_reserved();
|
||||||
|
}
|
||||||
|
if (PrintGC && Verbose) {
|
||||||
|
if (success && GC_locker::is_active()) {
|
||||||
|
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// No young generation references, clear this generation's cards.
|
// No young generation references, clear this generation's cards.
|
||||||
void CardGeneration::clear_remembered_set() {
|
void CardGeneration::clear_remembered_set() {
|
||||||
|
@ -441,25 +476,9 @@ OneContigSpaceCardGeneration::expand_and_allocate(size_t word_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OneContigSpaceCardGeneration::expand(size_t bytes, size_t expand_bytes) {
|
bool OneContigSpaceCardGeneration::expand(size_t bytes, size_t expand_bytes) {
|
||||||
GCMutexLocker x(ExpandHeap_lock);
|
GCMutexLocker x(ExpandHeap_lock);
|
||||||
size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes);
|
return CardGeneration::expand(bytes, expand_bytes);
|
||||||
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
|
||||||
bool success = false;
|
|
||||||
if (aligned_expand_bytes > aligned_bytes) {
|
|
||||||
success = grow_by(aligned_expand_bytes);
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
success = grow_by(aligned_bytes);
|
|
||||||
}
|
|
||||||
if (!success) {
|
|
||||||
grow_to_reserved();
|
|
||||||
}
|
|
||||||
if (GC_locker::is_active()) {
|
|
||||||
if (PrintGC && Verbose) {
|
|
||||||
gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -606,11 +606,21 @@ class CardGeneration: public Generation {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Attempt to expand the generation by "bytes". Expand by at a
|
||||||
|
// minimum "expand_bytes". Return true if some amount (not
|
||||||
|
// necessarily the full "bytes") was done.
|
||||||
|
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||||
|
|
||||||
virtual void clear_remembered_set();
|
virtual void clear_remembered_set();
|
||||||
|
|
||||||
virtual void invalidate_remembered_set();
|
virtual void invalidate_remembered_set();
|
||||||
|
|
||||||
virtual void prepare_for_verify();
|
virtual void prepare_for_verify();
|
||||||
|
|
||||||
|
// Grow generation with specified size (returns false if unable to grow)
|
||||||
|
virtual bool grow_by(size_t bytes) = 0;
|
||||||
|
// Grow generation to reserved size.
|
||||||
|
virtual bool grow_to_reserved() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// OneContigSpaceCardGeneration models a heap of old objects contained in a single
|
// OneContigSpaceCardGeneration models a heap of old objects contained in a single
|
||||||
|
@ -631,14 +641,14 @@ class OneContigSpaceCardGeneration: public CardGeneration {
|
||||||
// and after last GC.
|
// and after last GC.
|
||||||
|
|
||||||
// Grow generation with specified size (returns false if unable to grow)
|
// Grow generation with specified size (returns false if unable to grow)
|
||||||
bool grow_by(size_t bytes);
|
virtual bool grow_by(size_t bytes);
|
||||||
// Grow generation to reserved size.
|
// Grow generation to reserved size.
|
||||||
bool grow_to_reserved();
|
virtual bool grow_to_reserved();
|
||||||
// Shrink generation with specified size (returns false if unable to shrink)
|
// Shrink generation with specified size (returns false if unable to shrink)
|
||||||
void shrink_by(size_t bytes);
|
void shrink_by(size_t bytes);
|
||||||
|
|
||||||
// Allocation failure
|
// Allocation failure
|
||||||
void expand(size_t bytes, size_t expand_bytes);
|
virtual bool expand(size_t bytes, size_t expand_bytes);
|
||||||
void shrink(size_t bytes);
|
void shrink(size_t bytes);
|
||||||
|
|
||||||
// Accessing spaces
|
// Accessing spaces
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue