Lock-based vs lock-free MethodCounters initialization

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Mon May 12 15:09:28 UTC 2014


On 5/12/14 5:09 PM, Mikael Gerdin wrote:
>> I'm in favor of lock-free solution, but not sure about how serious
>> fragmentation issue is in NPG world. What do you think?
>
> 1. Are MethodCounters objects large enough to fit on the per-metaspace block
> free list? See:
> MetaWord* BlockFreelist::get_block(size_t word_size) {
>    (...)
>    if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
>      // Dark matter.  Too small for dictionary.
>      return NULL;
>    }
MethodCounters have fixed size, but it's too small - 
MethodCounters::size() reports 4 words for Tiered in 64-bit VM and 
TreeChunk::min_size() is 12 words.

> 2. If the above is true, are all MethodCounters the same size? I know how you
> guys love your variable-sized objects :)
>
>
> If this is not true then we could encounter some severe fragmentation in
> Metaspace. There are already several issues with fragmentation and waste and I
> would prefer if we could avoid adding to the problem.
I'll choose lock-based solution then. Thanks for the info.

Best regards,
Vladimir Ivanov

>
> /Mikael
>
>
>>
>> Thanks!
>>
>> Best regards,
>> Vladimir Ivanov
>>
>> [1]
>> http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/tip/src/share/vm/oops/m
>> ethod.cpp#l384
>>
>> MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
>>     methodHandle mh(m);
>>     ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
>>     MethodCounters* counters = MethodCounters::allocate(loader_data,
>> CHECK_NULL);
>>     if (mh->method_counters() == NULL) {
>>       mh->set_method_counters(counters);
>>     } else {
>>       MetadataFactory::free_metadata(loader_data, counters);
>>     }
>>     return mh->method_counters();
>> }
>>
>> [2]
>> http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/tip/src/share/vm/oops/m
>> ethod.cpp#l360
>>
>> void Method::build_interpreter_method_data(methodHandle method, TRAPS) {
>>     // Do not profile method if current thread holds the pending list lock,
>>     // which avoids deadlock for acquiring the MethodData_lock.
>>     if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
>>       return;
>>     }
>>
>>     // Grab a lock here to prevent multiple
>>     // MethodData*s from being created.
>>     MutexLocker ml(MethodData_lock, THREAD);
>>     if (method->method_data() == NULL) {
>>       ClassLoaderData* loader_data =
>> method->method_holder()->class_loader_data();
>>       MethodData* method_data = MethodData::allocate(loader_data, method,
>> CHECK);
>>       method->set_method_data(method_data);
>>       if (PrintMethodData && (Verbose || WizardMode)) {
>>         ResourceMark rm(THREAD);
>>         tty->print("build_interpreter_method_data for ");
>>         method->print_name(tty);
>>         tty->cr();
>>         // At the end of the run, the MDO, full of data, will be dumped.
>>       }
>>     }
>> }
>>
>> [3] Possible lock-free solution:
>> MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
>>     methodHandle mh(m);
>>     if (mh->method_counters() != NULL)  return mh->method_counters();
>>     ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
>>     MethodCounters* counters = MethodCounters::allocate(loader_data,
>> CHECK_NULL);
>>     MethodCounters* old = (MethodCounters*)Atomic::cmpxchg_ptr(counters,
>> &_method_counters, NULL);
>>     if (old != NULL) {
>>       MetadataFactory::free_metadata(loader_data, counters);
>>     }
>>     return mh->method_counters();
>> }
>>
>> [4] https://bugs.openjdk.java.net/browse/JDK-6988439
>


More information about the hotspot-dev mailing list