RFR: 8286876: NMT.test_unaliged_block_address_vm_assert fails if using clang toolchain [v6]

Thomas Stuefe stuefe at openjdk.org
Tue Jan 17 06:30:11 UTC 2023


On Mon, 16 Jan 2023 23:15:19 GMT, Albert Mingkun Yang <ayang at openjdk.org> wrote:

> The input arg should be `const void*`, which accepts both `void*` and `const void*`, because that's a promise to the caller that the current method will not mutate the mem pointed by the input arg. 

Yes,

(Ofc, one could throw away `const` and mutate the mem anyway inside the method, but that's just bad code.)

Yes.

> 
> > but that should yield a const pointer too, not a non-const one.
> 
> I believe your reasoning is that in&out pointers are essentially the same (off by 1), so they should have the same const-ness.
> 
> However, the in&out args are two semantically different entities, `void*` vs `MallocHeader*`. For instance, a caller may construct a `MallocHeader*` out of a `const void*` -- the mem is immutable via `void*` but mutable via `MallocHeader*` due to the extra info offered by the more concrete type. IOW, whether the mem indicated by `MallocHeader*` is mutable or not is up to the caller.

Not sure if we talk at cross purposes, but:

- const variant is for safe *querying* while preventing accidental write access. You don't need write access for querying.
- non-const variant is for modifying the header. The header is mostly immutable, the only thing we change are the canaries. Without that, we could dispose of the non-const variant altogether.

The whole thing follows the same logic as a class where you differentiate between read-only and write-access for the same accessor, e.g.


class X {
   Y y;
   const Y& get_y() const;
   Y& get_y();
}


see e.g. Effective C++, Item 3. Regrettably, C++ forces us to duplicate the method.

> 
> Looking at the `const`-variant caller (I can just find this single one), it's more or less the same as a caller of the non-`const` variant.
> 
> ```c++
> static void check_expected_malloc_header(const void* payload, MEMFLAGS type, size_t size) {
>   const MallocHeader* hdr = MallocHeader::resolve_checked(payload);
>   EXPECT_EQ(hdr->size(), size);
>   EXPECT_EQ(hdr->flags(), type);
> }
> ```
> 
> vs
> 
> ```c++
>     void* const memblock = ...
> 
>     MallocHeader* header2 = MallocHeader::resolve_checked(memblock);
>     assert(header2->size() == size, "Wrong size");
>     assert(header2->flags() == flags, "Wrong flags");
> ```
> 
> (Seems to me, `header2` should be `const` as well -- here we promise not to mutate the obj via `header2`.)

Agreed.

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

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


More information about the hotspot-runtime-dev mailing list