RFR: 8296139: Make GrowableBitMap the base class of all implementations

Axel Boldt-Christmas aboldtch at openjdk.org
Thu Nov 3 11:16:44 UTC 2022


On Wed, 2 Nov 2022 19:08:15 GMT, Xin Liu <xliu at openjdk.org> wrote:

>> This is how I treat them using the base pointer 'ArenaBitMap*'
>> https://github.com/navyxliu/jdk/commit/cdbc0e1c97f747fd53ad408d59e65ec8adf0fc16#diff-17a9d48a5570e5bcde557c8d1efcbe78d69a5657bc865bed37b22c3c8b5d447d
>> 
>>> The places where VectorSet() is used today, can we not just use ArenaBitMap(Thread::current()->resource_area(), [...]) instead. And have the replacement be VectorSet -> ArenaBitMap
>> 
>> `Thread::current()->resource_area()` returns ResourceArena*. ResourceArena is a subclass of Arena. In this sense, we can use the same ArenaAllocator to handle both ResourceBitMap and ArenaBitMap. That's why I remove 'ResourceAllocator' in this patch. 
>> 
>> I think it is possible to do what you said. Let's say we use ArenaBitMap as 'ResourceBitMap'. Shall we keep ArenaBitMap and ResourceBitMap separated then? In classic object-oriented design, ResourceBitMap 'is-a' ArenaBitMap, isn't it? If we keep 2 classes in parallel, we may end up 2 'ResourceBitMap' with different behaviors. 
>> 
>> In current patch, ResourceBitMap is just an adapter. It supports copy constructor and copy assignment because 'resource arena' is unique.
>
> Correction: s/resource arena/resource area
> 
> This is my understanding. 'Resource area' in HotSpot is a special 'area' whose lifecycle is bound to stacktrace. By default, we still use 'arena' allocation algorithm. That's why I think we can treat ResourceBitMap as a subclass of ArenaBitMap.

I like the type hierarchy but for one thing. Today we have two ways of creating a resource arena
* `ResourceBitmap([...])`
  * Which checks `verify_has_resource_mark` in debug builds
* `ArenaBitmap(some_resource_area, [...])`
  * Which does not check `verify_has_resource_mark`

This would add a third way where `ArenaBitmap(nullptr, [...])` has the same behaviour as `ResourceBitmap`. This can be solved with a new `ArenaBitMap` constructor.
```c++
 protected:
  ArenaBitMap(std::nullptr_t, idx_t size_in_bits, bool clean);

And add a debug assert in the normal ArenaBitMap constructor `precond(arena != nullptr);`

Which would give a behaviour like this
```c++
#ifdef ASSERT
TEST_VM(BitMap, resource_work) {
  ResourceBitMap rbm(0);
  ArenaBitMap abm(Thread::current()->resource_area(),0);
  static_cast<void>(rbm);
  static_cast<void>(abm);
}
TEST_VM_ASSERT(BitMap, nullptr_arena) {
  Arena* ptr = nullptr;
  ArenaBitMap crash(ptr,0);
  // ArenaBitMap does_not_compile(nullptr,0);
  // ArenaBitMap does_not_compile(NULL,0);
  static_cast<void>(crash);
}
#endif


I do not know if the extra branch in the arena allocator ever matters, but if it did you can just store the resource area arena in `_arena` on release and not branch. The only semantical difference then would be that if the [re]allocating functions gets called from different threads. But I would think that a resource allocated bitmap crossing thread boundaries is never an appropriate use. 

But I did preface this discussion with that I do not know how we treat resource allocated objects that just look like arena allocated objects and thus circumvent the `verify_has_resource_mark` check. It happens all over the place in the compiler code, and I am not sure why.

-------------

PR: https://git.openjdk.org/jdk/pull/10941


More information about the hotspot-runtime-dev mailing list