On Fri, 17 Apr 2026 10:43:42 GMT, Tobias Hartmann <[email protected]> wrote:

> The test `compiler/print/CompileCommandMemLimit.java` fails because we 
> suddenly don't hit the expected memory limit anymore when compiling empty 
> method `TestMain::method2` with `--enable-preview`. In fact, the VM is 
> reporting that no memory is used for compilation at all:
> 
> c1 (27) (ok) Arena usage 
> compiler/print/CompileCommandMemLimit$TestMain::method2(()V): Total Usage: 0
> 
> 
> I added some logging to the 
> `CompilationMemoryStatistic::on_arena_chunk_allocation` path in 
> `ChunkPool::allocate_chunk` and noticed that the only difference is that with 
> `--enable-preview` we don't have this allocation in 
> `Thread::current()->resource_area()`:
> 
> V  [libjvm.so+0x4bb99c]  ChunkPool::allocate_chunk(Arena*, unsigned long, 
> AllocFailStrategy::AllocFailEnum)+0x16c
> V  [libjvm.so+0x4bc28d]  Arena::grow(unsigned long, 
> AllocFailStrategy::AllocFailEnum)+0x5d
> V  [libjvm.so+0x7a4d83]  
> DebugInformationRecorder::DebugInformationRecorder(OopRecorder*)+0x43
> V  [libjvm.so+0x58e3d1]  Compilation::initialize()+0xb1
> V  [libjvm.so+0x58fe1c]  Compilation::compile_method()+0x6c
> V  [libjvm.so+0x590190]  Compilation::Compilation(AbstractCompiler*, ciEnv*, 
> ciMethod*, int, BufferBlob*, bool, DirectiveSet*)+0x1f0
> V  [libjvm.so+0x590866]  Compiler::compile_method(ciEnv*, ciMethod*, int, 
> bool, DirectiveSet*)+0xb6
> 
> 
> The reason is that with `--enable-preview` -> `-XX:+UseFieldFlattening` we 
> have a new code path `ciInstanceKlass::compute_nonstatic_fields_impl` that 
> processes flat fields and creates `ciField` objects for those. We hit that 
> code path very early during `ciObjectFactory::init_shared_objects` for some 
> core-libs klass:
> 
> 
> V  [libjvm.so+0x4bb99c]  ChunkPool::allocate_chunk(Arena*, unsigned long, 
> AllocFailStrategy::AllocFailEnum)+0x16c
> V  [libjvm.so+0x4bc28d]  Arena::grow(unsigned long, 
> AllocFailStrategy::AllocFailEnum)+0x5d
> V  [libjvm.so+0x10bfdce]  Symbol::as_C_string() const+0x1e
> V  [libjvm.so+0x69da5c]  ciField::ciField(ciField*, ciField*)+0x7c
> V  [libjvm.so+0x6a6ab8]  
> ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray<ciField*> 
> const*, GrowableArray<ciField*> const*)+0x1168
> V  [libjvm.so+0x6bb22c]  ciObjectFactory::init_shared_objects()+0xc8c
> V  [libjvm.so+0x6bcc56]  ciObjectFactory::initialize()+0x96
> V  [libjvm.so+0x759535]  CompileBroker::compiler_thread_loop()+0x1a5
> ``` 
> 
> As a result, the `Thread::current()->resource_area()` is growing already 
> before the allocation and there is no need to grow it anymore during the 
> compilation. As a result, no chunk allocations are detected by th...

While adding missing ResourceMarks is good, this problem feels a little like 
"whack-a-mole".  Also, there seems to be opposing tension between memory stat 
accuracy and arena efficiency.  For efficiency, it seems better if a 
compilation rarely needs to allocate a new chunk.  On the other hand, for 
chunk-based memory stats to work, it would be better if every compilation needs 
to allocate a new chunk.  For a long-term solution, I think we need some sort 
of "reset" after init_shared_objects() if MemLimit is enabled.  My first 
thought was to split the current chunk, but that complicates freeing.  My 
second thought was some kind of high water mark.  Or maybe it is enough to use 
smaller chunk sizes for compiler threads when MemLimit is enabled?

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

PR Comment: https://git.openjdk.org/valhalla/pull/2330#issuecomment-4271099929

Reply via email to