src/share/vm/memory/metaspace.cpp

Print this page
rev 6722 : 8049599: MetaspaceGC::_capacity_until_GC can overflow
Reviewed-by: jmasa, stefank

*** 1412,1425 **** 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()); --- 1412,1446 ---- 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_ptr((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());
*** 1515,1525 **** // 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:" --- 1536,1549 ---- // 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:"
*** 3317,3339 **** 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 { --- 3341,3373 ---- 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 = 0; ! size_t after = 0; ! MetaWord* res; ! bool incremented; ! ! // Each thread increments the HWM at most once. Even if the thread fails to increment ! // the HWM, an allocation is still attempted. This is because another thread must then ! // have incremented the HWM and therefore the allocation might still succeed. ! do { ! incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before); ! res = allocate(word_size, mdtype); ! } while (!incremented && res == NULL); ! if (incremented) { ! tracer()->report_gc_threshold(before, after, MetaspaceGCThresholdUpdater::ExpandAndAllocate); if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT ! " to " SIZE_FORMAT, before, after); ! } } ! return res; } // Space allocated in the Metaspace. This may // be across several metadata virtual spaces. char* Metaspace::bottom() const {