RFR: 8247470: Fix CHeap GrowableArray NMT accounting

Stefan Karlsson stefan.karlsson at oracle.com
Mon Jun 15 20:37:14 UTC 2020


On 2020-06-15 20:16, coleen.phillimore at oracle.com wrote:
>
> Looks good.  Now there are no ambiguous constructors?

Maybe this one could have been problematic:
GrowableArray(Arena* arena, int initial_size, int initial_len, const E& 
filler)

If some code previously did, say:
GrowableArray(0, 0, 0, false)

and tried to match the old:
GrowableArray(int initial_size, int initial_len, const E& filler, bool 
C_heap = false, MEMFLAGS memflags = mtNone)

it could have called the arena version.

I temporarily added a dummy parameter like this:
GrowableArray(Arena* arena, GADummy dummy, int initial_size, int 
initial_len, const E& filler)

and fixed all call-sites where arena GrowableArrays are used. It 
compiles on Linux x64. I'll verify that it builds on the other platforms 
as well.

>
> I was looking to see if the GrowableArray code in os_linux.cpp was in 
> windows/bsd, but it's not but os_windows includes growableArray.hpp.  
> I wonder if you could try taking it out?  It seems related to this 
> change.  If not, it's not important.

I'll take it out and let the full test of this run overnight.

Thanks,
StefanK
>
> thanks,
> Coleen
>
> On 6/15/20 2:05 PM, Stefan Karlsson wrote:
>> Hi all,
>>
>> Updated webrevs:
>>
>> https://cr.openjdk.java.net/~stefank/8247470/webrev.02.delta/
>> https://cr.openjdk.java.net/~stefank/8247470/webrev.02/
>>
>> Testing showed that the previous patch was incomplete. I changed the 
>> signature and expected the compiler to show all places I needed to 
>> update. The intention was that the compiler should see that 
>> true/false wasn't a MEMFLAGS and complain. Unfortunately, there was a 
>> problem with the following pattern:
>>
>>   new (ResourceObj::C_HEAP, mtCode)GrowableArray<const char*>(0, true);
>>
>> which matches the following constructor:
>>
>> // Resource allocation
>> GrowableArray(Thread* thread, int initial_size) : 
>> GenericGrowableArray(initial_size, 0, mtNone) {
>>
>> and yields thread == NULL (0) and initial_size == 1 (true).
>>
>> There were only two places that used the Thread* parameter. This 
>> special constructor seems to have been a performance optimization at 
>> some point. But we've made Thread::current() much cheaper, and 
>> neither of the affected call sites seems to be performance sensitive. 
>> I opted to simplify the code and removed that constructor.
>>
>> The systemDictionaryShared.cpp was needed after I rebased the patch.
>>
>> Thanks,
>> StefanK
>>
>>
>> On 2020-06-12 11:33, Stefan Karlsson wrote:
>>> Hi all,
>>>
>>> Please review this patch to fix the NMT accounting of CHeap 
>>> GrowableArray allocations.
>>>
>>> https://cr.openjdk.java.net/~stefank/8247470/webrev.01/
>>> https://bugs.openjdk.java.net/browse/JDK-8247470
>>>
>>> The initial reason why I started fixing this was that I found code 
>>> like this:
>>>
>>> src/hotspot/share/classfile/javaClasses.cpp:
>>>     new (ResourceObj::C_HEAP, mtModule) GrowableArray<Klass*>(500, 
>>> true);
>>>
>>> Before this patch, the GrowableArray constructor looked like this:
>>>
>>> GrowableArray(int initial_size, bool C_heap = false, MEMFLAGS F = 
>>> mtInternal)
>>> : GenericGrowableArray(initial_size, 0, C_heap, F) {
>>> _data = (E*)raw_allocate(sizeof(E));
>>>
>>> and:
>>>
>>> GenericGrowableArray(int initial_size, int initial_len, bool c_heap, 
>>> MEMFLAGS flags = mtNone) { _len = initial_len; _max = initial_size; 
>>> _memflags = flags;
>>>
>>> and:
>>> void* GenericGrowableArray::raw_allocate(int elementSize) {
>>> ...
>>> return (void*)AllocateHeap(byte_size, _memflags);
>>>
>>> This means that the GrowableArray instance was accounted to 
>>> mtModule, but the backing memory for the array was accounted to 
>>> mtInternal.
>>>
>>> My proposal for fixing this is to fuse the (c_heap, flags) duality 
>>> into one parameter (flags). The call sites are then changed like this:
>>>
>>> For resource allocations:
>>> GrowableArray(...) -> GrowableArray(...)
>>> GrowableArray(... /* c_heap */ false) -> GrowableArray(...)
>>> GrowableArray(... /* c_heap */ false, /* flags */ mtXX) -> 
>>> GrowableArray(...)
>>>
>>> For CHeap allocations:
>>> GrowableArray(... /* c_heap */ true, /* flags */ mtXX) -> 
>>> GrowableArray(..., mtXX)
>>> GrowableArray(... /* c_heap */ true) -> GrowableArray(..., mtInternal)
>>>
>>> That is, if you specify a "valid" mtXX tag it invokes the CHeap 
>>> allocation path. If you don't specify a mtXX tag, then 'flags' get 
>>> the mtNone default value. This is a marker for the code that no 
>>> CHeap allocation should be done.
>>>
>>> While properly tagging all GrowableArray allocations, I went ahead 
>>> and changed most GrowableArray mtInternal tags to the appropriate 
>>> values. I also introduced a new mtServiceability tag, since a lot of 
>>> the mtInternal tags were in areas dealing with serviceability code. 
>>> I could split this out into a separate patch, if necessary.
>>>
>>> This hasn't been fully tested yet, because I'd like to get some 
>>> early feedback.
>>>
>>> Thanks,
>>> StefanK
>>
>



More information about the hotspot-dev mailing list