src/share/vm/memory/metaspace.cpp
Print this page
rev 7105 : 8049599: MetaspaceGC::_capacity_until_GC can overflow
rev 7106 : 8049599: MetaspaceGC::_capacity_until_GC can overflow (01)
*** 1413,1426 ****
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());
! return (size_t)Atomic::add_ptr(v, &_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());
*** 1516,1526 ****
// 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:"
*** 3319,3341 ****
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 {