提交 57e0ee46 编写于 作者: J jmasa

6952853: SIGSEGV with UseAdaptiveGCBoundary on 64b linux running jvm2008

Summary: Shrinking of a generation and the corresponding card table was causing part of the card table to be uncommitted.
Reviewed-by: jcoomes
上级 9aa6edd7
/* /*
* 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, ...@@ -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, ...@@ -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, ...@@ -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,
......
/* /*
* 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; ...@@ -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);
......
/* /*
* 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) { ...@@ -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) { ...@@ -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) { ...@@ -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();)
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册