RFR: 8247755: Leaner and more versatile GrowableArray classes

Stefan Karlsson stefan.karlsson at oracle.com
Tue Jun 23 10:23:38 UTC 2020


Latest patches:
  https://cr.openjdk.java.net/~stefank/8247755/webrev.02.delta/
  https://cr.openjdk.java.net/~stefank/8247755/webrev.02/

I haven't changed:
- GrowableArrayView to something else
- S to ALLOC or Derived. I'm leaning towards Derived.

Some comments inlined:

On 2020-06-23 11:35, Kim Barrett wrote:
>> On Jun 22, 2020, at 5:01 AM, Stefan Karlsson <stefan.karlsson at oracle.com> wrote:
>>
>> On 2020-06-22 09:25, Kim Barrett wrote:
>>> src/hotspot/share/utilities/globalDefinitions.hpp
>>>   435 // Need the correct linkage to call qsort without warnings
>>>   436 extern "C" {
>>>   437   typedef int (*_sort_Fn)(const void *, const void *);
>>>   438 }
>>> Rather than messing with function pointer types, why not use
>>> Quicksort::sort from utilities/quickSort.hpp?
>>
>> I didn't change this code, only moved it. This was done to reduce the clutter in growableArray.hpp. You don't suggest that I change this in this RFR, right?
> 
> I missed that this was moved from growableArray.hpp, having been in
> one of the largish deleted chunks there.
> 
> So there's a bit of a mess here, none of it related to your change.
> For example,
> 
> ./share/oops/instanceKlass.cpp:    // _sort_Fn is defined in growableArray.hpp.
> 
> And worse, the semantics of extern "C" includes things like possibly
> using different calling conventions. So casting a C++ function to
> _sort_Fn seems technically broken, though apparently happens to work
> on supported platforms.  (In which case it would seem to effectively
> be a nop.)
> 
> All of that could be eliminated by using Quicksort::sort (or
> std::sort, but I don't want to get into that here).
> 
> I've filed a bug:
> https://bugs.openjdk.java.net/browse/JDK-8248137

Thanks.

> 
>>> src/hotspot/share/memory/metaspaceShared.cpp
>>>   459 static GrowableArrayCHeap<Handle, mtClassShared>* _extra_interned_strings = NULL;
>>> ...
>>>   462   _extra_interned_strings = new GrowableArrayCHeap<Handle, mtClassShared>(10000);
>>> [pre-existing]
>>> I think this vector is only needed during the preload_and_dump
>>> operation that calls read_extra_data, and can then be discarded. […]
>>
>> Yes. I mainly wanted to use this as an example of a CHeap/CHeap-allocated GrowableArray. I also think it would make sense to change this to n on-stack CHeap array.
> 
> OK.  (Did I see a bug for cleaning this up go by?)

I created this:
https://bugs.openjdk.java.net/browse/JDK-8248007

> 
>>> src/hotspot/share/utilities/growableArray.hpp
>>>   115 class GrowableArrayView : public GrowableArrayBase {
>>> I don't like the name "View" for this concept. Common practice
>>> elsewhere (including the Standard) is for "view" types to be an
>>> adaptor over some other type, providing a limited range or otherwise
>>> adjusted access.  (Our BitMapView does that.)
>>> GrowableArrayData?
>>> I'm not sure how often this class name gets used by clients, so it
>>> might not matter that it's a little bit long or clumsy / clunky >
>>
>> My thinking was the just like the with the BitMapView, the backing storage is managed externally:
>>
>> // The BitMapView is used when the backing storage is managed externally.
>> class BitMapView : public BitMap {
>> public:
>>   BitMapView() : BitMap(NULL, 0) {}
>>   BitMapView(bm_word_t* map, idx_t size_in_bits) : BitMap(map, size_in_bits) {}
>> };
>>
>> I don't think GrowableArrayData is a better name, so if I need to change this, I'm going to need some decent suggestions. I talked briefly with Kim, but we couldn't immediately find a name that both liked. Suggestions?
> 
> I haven’t come up with anything better than we discussed.
> 

Then the current proposal is to keep this as GrowableArrayView. It's 
also an easy fix to deal with as a follow-up RFE.

>>> src/hotspot/share/utilities/growableArray.hpp
>>> Destructors for all but the most-derived classes should be non-public.
>>> Probably also the constructors.  That is, all of GrowableArrayBase,
>>> GrowableArrayView, and GrowableArrayWithAllocator should have
>>> protected constructors and destructors.
>>
>> OK. For GrowableArrayivew, I had an idea that someone *might* want to do:
>>
>> int _array[10];
>> ...
>> GrowableArrayView view(array, 10, 10);
>> do_something(view);
>>
>> but I'll change this to protected.
> 
> Classes that are used as both a base class and a concrete class can cause problems.
> For example, allowing accidental slicing, which leads to UB (which may or may not
> be detected in some way).

Noted.

> 
>>> src/hotspot/share/utilities/growableArray.hpp
>>> [pre-existing]
>>> GrowableArray's use of mtNone to indicate resource allocation seems
>>> like an abuse of that memory type. That memory type has a description
>>> string of "Unknown", nothing to do with resources. But it's considered
>>> an invalid type by MamTracker/MemReporter/MallocSite, and it seems to
>>> mean something else in the VirtualMemoryTracker, like "uninitialized".
>>
>> I thinks we view this differently. My view is that memflags belong to the CHeap allocations, but is only valid if != mtNone. Setting it to mtNone doesn't imply that resource allocations are marked with mtNone. It just means that we shouldn't care about the memflags value when allocating resource memory.
> 
> I’m OK with an interpretation that mtNone is considered an invalid memflags everywhere.
> There may be some places that ought to be treating it that way but aren’t.  The aarch64 pf
> function is one; you filed a bug and have a fix for that one - thanks.

For the record:
https://bugs.openjdk.java.net/browse/JDK-8248130

I haven't created a cleanup task for VirtualMemoryTracker oddity. I 
might get to it later.

> 
>>> But why have constructors with optional MEMFLAGS at all?  And why use
>>> mtNone that way?  Constructors without MEMFLAGS parameter are resource
>>> allocating, constructors with required MEMFLAGS parameter are CHeap
>>> allocating.  (Though the random status of mtNone noted above will make
>>> that one probably not actually usable.)  (That would require some small
>>> adjustments to GrowableArrayMetadata.)
>>
>> I think you've lost me here. Are you proposing that I split this up into more constructors. Are you suggesting that I change this:
>>
>> […]
>> and adjust allocate(...) and GrowableArrayMetadata(...) accordingly?
> 
> Not relevant is mtNone signals “invalid”.

OK.

> 
>>> src/hotspot/share/utilities/growableArray.hpp
>>>   586 public:
>>>   587   // Where are we going to allocate memory?
>>>   588   bool on_C_heap() { return _metadata.on_C_heap(); }
>>>   589   bool on_stack () { return _metadata.on_stack(); }
>>>   590   bool on_arena () { return _metadata.on_arena(); }
>>> These were previously protected; why make them public?
>>
>> Mainly to be usable by the tests. I can add a friend test class and revert this.
> 
> OK.  I think I’d prefer these not be in the public API; I wouldn’t want someone
> writing code that was conditional on any of them… Your call.

I changed them to be private.

StefanK

> 
> 


More information about the hotspot-dev mailing list