RFR: 8319117: GrowableArray: Allow for custom initializer instead of copy constructor

Johan Sjölen jsjolen at openjdk.org
Tue Oct 31 11:56:29 UTC 2023


On Tue, 31 Oct 2023 10:11:59 GMT, Quan Anh Mai <qamai at openjdk.org> wrote:

>>> I think a more preferable approach is to do emplace-like filling
>>> 
>>> ```
>>> template <class... Args>
>>> E& at_grow(int i, Args... args) {
>>>     assert(0 <= i, "negative index %d", i);
>>>     if (i >= this->_len) {
>>>         if (i >= this->_capacity) {
>>>             grow(i);
>>>         }
>>>         for (int j = this->_len; j <= i; j++) {
>>>             _data[j].~E();
>>>             new (&_data[j]) E(args...);
>>>         }
>>>         this->_len = i + 1;
>>>     }
>>>     return _data[i];
>>> }
>>> ```
>> 
>> I think you might be right. If I understand this correctly we can pick between copy construction (having `Args` be equal to `E`) and "regular" construction depending on the arguments provided?
>> 
>> @stefank, @dean-long. Re: tests, yes, I should add tests. The goal here is to avoid copy construction, and I chose to provide a function so that you can yourself pick how to initialize the memory. I think @merykitty's solution might be preferable to mine.
>
> @jdksjolen Yes you are right, note that the idiom for standard C++ looks like this
> 
>     template <class... Args>
>     void emplace(Args&&... args) {
>         call(std::forward<Args>(args)...);
>     }
> 
> And I'm not really sure what this would become without move semantics.

Trying out @merykitty's idea reminded me of why this solution turned out like this: There's no 'generic' placement new-operator in `AnyObj`. This can be fixed by adding in 

```c++
class AnyObj {
  //...
  operator new (size_t, void* ptr) {
    return ptr;
  }
}

 
tier1 and tier2 passes with the addition of this operator.

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

PR Comment: https://git.openjdk.org/jdk/pull/16409#issuecomment-1787070329


More information about the hotspot-dev mailing list