SUGGESTED FIX
One liner!
@@ -1594,7 +1598,7 @@
assert(regions_accounted_for(), "Region leakage!");
return attempt_allocation_at_safepoint(word_size,
- true /* expect_null_cur_alloc_region */);
+ false /* expect_null_cur_alloc_region */);
|
EVALUATION
This is caused by an incorrect assumption. We do an allocation attempt at the end of expand_and_allocate() and we claim that the current alloc region should be NULL (expect_null_cur_alloc_region == true):
HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
...
return attempt_allocation_at_safepoint(word_size,
true /* expect_null_cur_alloc_region */);
}
However, this is incorrect. expand_and_allocate() is called from satisfy_failed_allocation():
HeapWord*
G1CollectedHeap::satisfy_failed_allocation(size_t word_size,
bool* succeeded) {
....
HeapWord* result = attempt_allocation_at_safepoint(word_size,
false /* expect_null_cur_alloc_region */);
if (result != NULL) {
assert(*succeeded, "sanity");
return result;
}
...
result = expand_and_allocate(word_size);
...
Note that in the first allocation attempt in satisfy_failed_allocation() we pass false for expect_null_cur_alloc_region. But, by the time we get into expand_and_allocate() we haven't done any attempt to retire the current alloc region. So, the assumption re: the current alloc region being NULL or not should be the same in both places and, specifically, expect_null_cur_alloc_region should be false in both places.
The failure is triggered by a humongous allocation attempt. The original allocation attempts in mem_allocate() failed so a safepoint was triggered which called the satisfy_failed_allocation() method. It's perfectly correct to have a non-NULL current alloc region at this point as the earlier allocation attempts did not use it as the request is for a humongous object.
|