RFR: 8269537: memset() is called after operator new

Ioi Lam iklam at openjdk.java.net
Tue Sep 7 23:32:06 UTC 2021


On Tue, 7 Sep 2021 12:25:54 GMT, Leo Korinth <lkorinth at openjdk.org> wrote:

> The basic problem is that we are relying on undefined behaviour, as documented in the code:
> 
> // This whole business of passing information from ResourceObj::operator new
> // to the ResourceObj constructor via fields in the "object" is technically UB.
> // But it seems to work within the limitations of HotSpot usage (such as no
> // multiple inheritance) with the compilers and compiler options we're using.
> // And it gives some possibly useful checking for misuse of ResourceObj.
> 
> 
> I am removing the undefined behaviour by passing the type of allocation through a thread local variable.
> 
> This solution has some advantages:
> 1) it is not UB
> 2) it is simpler and easier to understand
> 3) it uses less memory (I could make it use even less if I made the enum `allocation_type` a u8)
> 4) in the *very* unlikely situation that stack memory (or embedded) already equals the data calculated from the address of the object, the code will also work. 
> 
> When doing the change, I also updated  `allocated_on_stack()` to the new name `allocated_on_stack_or_embedded()` which is much harder to misinterpret.
> 
> I also disallow to "fake" the memory type by explicitly calling `ResourceObj::set_allocation_type`.
> 
> This forced me to change two places that is faking the allocation type of an embedded `GrowableArray` from  `STACK_OR_EMBEDDED` to `C_HEAP`. The faking of the type is hard to understand as a `STACK_OR_EMBEDDED` `GrowableArray` can allocate any type of object. My guess is that `GrowableArray` has changed behaviour, or maybe that it was hard to understand because the old naming of `allocated_on_stack()`. 
> 
> I have also tried to update the comments. In doing that I not only changed the comments for this change, but also for the *incorrect* advice to always delete object you allocate with new.
> 
> Testing on debug build tier1-3
> Testing on release build tier1

Changes requested by iklam (Reviewer).

src/hotspot/share/memory/allocation.hpp line 439:

> 437:   void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
> 438:       address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL);
> 439:       DEBUG_ONLY(if (res != NULL) _thread_last_allocated = RESOURCE_AREA;)

Maybe we should also guard against the possibility of nested allocations, which may trash `_thread_last_allocated`?


#define PUSH_RESOURCE_OBJ_ALLOC_TYPE(t) \
  assert(_thread_last_allocated == STACK_OR_EMBEDDED, "must not be nested"); \
  DEBUG_ONLY(_thread_last_allocated = t); \

...
  if (res != NULL) {
    PUSH_RESOURCE_OBJ_ALLOC_TYPE(RESOURCE_AREA);
  }


Similarly, the `ResourceObj` constructor should use a corresponding `POP_RESOURCE_OBJ_ALLOC_TYPE` macro.

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

PR: https://git.openjdk.java.net/jdk/pull/5387


More information about the serviceability-dev mailing list