mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
6952853: SIGSEGV with UseAdaptiveGCBoundary on 64b linux running jvm2008
Shrinking of a generation and the corresponding card table was causing part of the card table to be uncommitted. Reviewed-by: jcoomes
This commit is contained in:
parent
428d02d5d7
commit
c443776640
3 changed files with 54 additions and 17 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -566,14 +566,14 @@ void CardTableExtension::resize_covered_region_by_end(int changed_region,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Commit new or uncommit old pages, if necessary.
|
// Commit new or uncommit old pages, if necessary.
|
||||||
resize_commit_uncommit(changed_region, new_region);
|
if (resize_commit_uncommit(changed_region, new_region)) {
|
||||||
|
// Set the new start of the committed region
|
||||||
|
resize_update_committed_table(changed_region, new_region);
|
||||||
|
}
|
||||||
|
|
||||||
// Update card table entries
|
// Update card table entries
|
||||||
resize_update_card_table_entries(changed_region, new_region);
|
resize_update_card_table_entries(changed_region, new_region);
|
||||||
|
|
||||||
// Set the new start of the committed region
|
|
||||||
resize_update_committed_table(changed_region, new_region);
|
|
||||||
|
|
||||||
// Update the covered region
|
// Update the covered region
|
||||||
resize_update_covered_table(changed_region, new_region);
|
resize_update_covered_table(changed_region, new_region);
|
||||||
|
|
||||||
|
@ -604,8 +604,9 @@ void CardTableExtension::resize_covered_region_by_end(int changed_region,
|
||||||
debug_only(verify_guard();)
|
debug_only(verify_guard();)
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardTableExtension::resize_commit_uncommit(int changed_region,
|
bool CardTableExtension::resize_commit_uncommit(int changed_region,
|
||||||
MemRegion new_region) {
|
MemRegion new_region) {
|
||||||
|
bool result = false;
|
||||||
// Commit new or uncommit old pages, if necessary.
|
// Commit new or uncommit old pages, if necessary.
|
||||||
MemRegion cur_committed = _committed[changed_region];
|
MemRegion cur_committed = _committed[changed_region];
|
||||||
assert(_covered[changed_region].end() == new_region.end(),
|
assert(_covered[changed_region].end() == new_region.end(),
|
||||||
|
@ -675,20 +676,31 @@ void CardTableExtension::resize_commit_uncommit(int changed_region,
|
||||||
"card table expansion");
|
"card table expansion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
result = true;
|
||||||
} else if (new_start_aligned > cur_committed.start()) {
|
} else if (new_start_aligned > cur_committed.start()) {
|
||||||
// Shrink the committed region
|
// Shrink the committed region
|
||||||
|
#if 0 // uncommitting space is currently unsafe because of the interactions
|
||||||
|
// of growing and shrinking regions. One region A can uncommit space
|
||||||
|
// that it owns but which is being used by another region B (maybe).
|
||||||
|
// Region B has not committed the space because it was already
|
||||||
|
// committed by region A.
|
||||||
MemRegion uncommit_region = committed_unique_to_self(changed_region,
|
MemRegion uncommit_region = committed_unique_to_self(changed_region,
|
||||||
MemRegion(cur_committed.start(), new_start_aligned));
|
MemRegion(cur_committed.start(), new_start_aligned));
|
||||||
if (!uncommit_region.is_empty()) {
|
if (!uncommit_region.is_empty()) {
|
||||||
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
||||||
uncommit_region.byte_size())) {
|
uncommit_region.byte_size())) {
|
||||||
vm_exit_out_of_memory(uncommit_region.byte_size(),
|
// If the uncommit fails, ignore it. Let the
|
||||||
"card table contraction");
|
// committed table resizing go even though the committed
|
||||||
|
// table will over state the committed space.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
assert(!result, "Should be false with current workaround");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
assert(_committed[changed_region].end() == cur_committed.end(),
|
assert(_committed[changed_region].end() == cur_committed.end(),
|
||||||
"end should not change");
|
"end should not change");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardTableExtension::resize_update_committed_table(int changed_region,
|
void CardTableExtension::resize_update_committed_table(int changed_region,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -30,7 +30,9 @@ class GCTaskQueue;
|
||||||
class CardTableExtension : public CardTableModRefBS {
|
class CardTableExtension : public CardTableModRefBS {
|
||||||
private:
|
private:
|
||||||
// Support methods for resizing the card table.
|
// Support methods for resizing the card table.
|
||||||
void resize_commit_uncommit(int changed_region, MemRegion new_region);
|
// resize_commit_uncommit() returns true if the pages were committed or
|
||||||
|
// uncommitted
|
||||||
|
bool resize_commit_uncommit(int changed_region, MemRegion new_region);
|
||||||
void resize_update_card_table_entries(int changed_region,
|
void resize_update_card_table_entries(int changed_region,
|
||||||
MemRegion new_region);
|
MemRegion new_region);
|
||||||
void resize_update_committed_table(int changed_region, MemRegion new_region);
|
void resize_update_committed_table(int changed_region, MemRegion new_region);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -284,12 +284,19 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
||||||
committed_unique_to_self(ind, MemRegion(new_end_aligned,
|
committed_unique_to_self(ind, MemRegion(new_end_aligned,
|
||||||
cur_committed.end()));
|
cur_committed.end()));
|
||||||
if (!uncommit_region.is_empty()) {
|
if (!uncommit_region.is_empty()) {
|
||||||
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
// It is not safe to uncommit cards if the boundary between
|
||||||
uncommit_region.byte_size())) {
|
// the generations is moving. A shrink can uncommit cards
|
||||||
assert(false, "Card table contraction failed");
|
// owned by generation A but being used by generation B.
|
||||||
// The call failed so don't change the end of the
|
if (!UseAdaptiveGCBoundary) {
|
||||||
// committed region. This is better than taking the
|
if (!os::uncommit_memory((char*)uncommit_region.start(),
|
||||||
// VM down.
|
uncommit_region.byte_size())) {
|
||||||
|
assert(false, "Card table contraction failed");
|
||||||
|
// The call failed so don't change the end of the
|
||||||
|
// committed region. This is better than taking the
|
||||||
|
// VM down.
|
||||||
|
new_end_aligned = _committed[ind].end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
new_end_aligned = _committed[ind].end();
|
new_end_aligned = _committed[ind].end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,6 +304,19 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
||||||
// In any case, we can reset the end of the current committed entry.
|
// In any case, we can reset the end of the current committed entry.
|
||||||
_committed[ind].set_end(new_end_aligned);
|
_committed[ind].set_end(new_end_aligned);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
// Check that the last card in the new region is committed according
|
||||||
|
// to the tables.
|
||||||
|
bool covered = false;
|
||||||
|
for (int cr = 0; cr < _cur_covered_regions; cr++) {
|
||||||
|
if (_committed[cr].contains(new_end - 1)) {
|
||||||
|
covered = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(covered, "Card for end of new region not committed");
|
||||||
|
#endif
|
||||||
|
|
||||||
// The default of 0 is not necessarily clean cards.
|
// The default of 0 is not necessarily clean cards.
|
||||||
jbyte* entry;
|
jbyte* entry;
|
||||||
if (old_region.last() < _whole_heap.start()) {
|
if (old_region.last() < _whole_heap.start()) {
|
||||||
|
@ -354,6 +374,9 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) {
|
||||||
addr_for((jbyte*) _committed[ind].start()),
|
addr_for((jbyte*) _committed[ind].start()),
|
||||||
addr_for((jbyte*) _committed[ind].last()));
|
addr_for((jbyte*) _committed[ind].last()));
|
||||||
}
|
}
|
||||||
|
// Touch the last card of the covered region to show that it
|
||||||
|
// is committed (or SEGV).
|
||||||
|
debug_only(*byte_for(_covered[ind].last());)
|
||||||
debug_only(verify_guard();)
|
debug_only(verify_guard();)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue