src/share/vm/memory/metaspace.cpp
Print this page
rev 7106 : 8049599: MetaspaceGC::_capacity_until_GC can overflow (01)
*** 1413,1448 ****
size_t value = (size_t)OrderAccess::load_ptr_acquire(&_capacity_until_GC);
assert(value >= MetaspaceSize, "Not initialied properly?");
return value;
}
! size_t MetaspaceGC::inc_capacity_until_GC(size_t v) {
assert_is_size_aligned(v, Metaspace::commit_alignment());
size_t capacity_until_GC = (size_t) _capacity_until_GC;
size_t new_value = capacity_until_GC + v;
if (new_value < capacity_until_GC) {
! // the addition wrapped around, set new_value to max value
! new_value = max_uintx;
}
! bool cas_succeeded = false;
! size_t num_retries = 5; // just to limit the number of CAS attempts
! for (size_t i = 0; i < num_retries; i++) {
! intptr_t cmp = (intptr_t) capacity_until_GC;
! intptr_t swap = (intptr_t) new_value;
! intptr_t prev = Atomic::cmpxchg_ptr(swap, &_capacity_until_GC, cmp);
! if (prev == cmp) {
! cas_succeeded = true;
! break;
! }
}
! // if the CAS did not succeed, just return the current value
! return cas_succeeded ? new_value : _capacity_until_GC;
}
size_t MetaspaceGC::dec_capacity_until_GC(size_t v) {
assert_is_size_aligned(v, Metaspace::commit_alignment());
--- 1413,1447 ----
size_t value = (size_t)OrderAccess::load_ptr_acquire(&_capacity_until_GC);
assert(value >= MetaspaceSize, "Not initialied properly?");
return value;
}
! bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) {
assert_is_size_aligned(v, Metaspace::commit_alignment());
size_t capacity_until_GC = (size_t) _capacity_until_GC;
size_t new_value = capacity_until_GC + v;
if (new_value < capacity_until_GC) {
! // the addition wrapped around, set new_value to aligned max value
! new_value = align_size_down(max_uintx, Metaspace::commit_alignment());
}
! intptr_t expected = (intptr_t) capacity_until_GC;
! intptr_t actual = Atomic::cmpxchg((intptr_t) new_value, &_capacity_until_GC, expected);
! if (expected != actual) {
! return false;
}
! if (new_cap_until_GC != NULL) {
! *new_cap_until_GC = new_value;
! }
! if (old_cap_until_GC != NULL) {
! *old_cap_until_GC = capacity_until_GC;
! }
! return true;
}
size_t MetaspaceGC::dec_capacity_until_GC(size_t v) {
assert_is_size_aligned(v, Metaspace::commit_alignment());
*** 1538,1548 ****
// increment the HWM.
size_t expand_bytes = minimum_desired_capacity - capacity_until_GC;
expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment());
// Don't expand unless it's significant
if (expand_bytes >= MinMetaspaceExpansion) {
! size_t new_capacity_until_GC = MetaspaceGC::inc_capacity_until_GC(expand_bytes);
Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
new_capacity_until_GC,
MetaspaceGCThresholdUpdater::ComputeNewSize);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr(" expanding:"
--- 1537,1550 ----
// increment the HWM.
size_t expand_bytes = minimum_desired_capacity - capacity_until_GC;
expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment());
// Don't expand unless it's significant
if (expand_bytes >= MinMetaspaceExpansion) {
! size_t new_capacity_until_GC = 0;
! bool succeeded = MetaspaceGC::inc_capacity_until_GC(expand_bytes, &new_capacity_until_GC);
! assert(succeeded, "Should always succesfully increment HWM when at safepoint");
!
Metaspace::tracer()->report_gc_threshold(capacity_until_GC,
new_capacity_until_GC,
MetaspaceGCThresholdUpdater::ComputeNewSize);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr(" expanding:"
*** 3341,3363 ****
MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) {
size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord);
assert(delta_bytes > 0, "Must be");
! size_t after_inc = MetaspaceGC::inc_capacity_until_GC(delta_bytes);
!
! // capacity_until_GC might be updated concurrently, must calculate previous value.
! size_t before_inc = after_inc - delta_bytes;
tracer()->report_gc_threshold(before_inc, after_inc,
MetaspaceGCThresholdUpdater::ExpandAndAllocate);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
" to " SIZE_FORMAT, before_inc, after_inc);
}
! return allocate(word_size, mdtype);
}
// Space allocated in the Metaspace. This may
// be across several metadata virtual spaces.
char* Metaspace::bottom() const {
--- 3343,3374 ----
MetaWord* Metaspace::expand_and_allocate(size_t word_size, MetadataType mdtype) {
size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord);
assert(delta_bytes > 0, "Must be");
! size_t before_inc = 0;
! size_t after_inc = 0;
! MetaWord* res = NULL;
! bool inc_succeeded = false;
!
! while (!inc_succeeded && res == NULL) {
! inc_succeeded = MetaspaceGC::inc_capacity_until_GC(delta_bytes,
! &after_inc,
! &before_inc);
! res = allocate(word_size, mdtype);
! }
+ if (inc_succeeded) {
tracer()->report_gc_threshold(before_inc, after_inc,
MetaspaceGCThresholdUpdater::ExpandAndAllocate);
if (PrintGCDetails && Verbose) {
gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT
" to " SIZE_FORMAT, before_inc, after_inc);
}
+ }
! return res;
}
// Space allocated in the Metaspace. This may
// be across several metadata virtual spaces.
char* Metaspace::bottom() const {