On Thu, 16 Apr 2026 23:09:52 GMT, Vladimir Kozlov <[email protected]> wrote:

> Improve startup and warmup time by making optimized native code for an 
> application instantly available when the HotSpot Java Virtual Machine starts. 
> Achieve this by compiling application code to native code in a training run, 
> storing the native code in the [AOT 
> cache](https://openjdk.org/jeps/483#Description) for use in subsequent 
> production runs.
> 
> More details in the [JEP](https://openjdk.org/jeps/544).
> 
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK 
> Interim AI Policy](https://openjdk.org/legal/ai).

src/hotspot/share/code/aotCodeCache.cpp line 3567:

> 3565:     return false;
> 3566:   } else if (java_lang_Module::is_instance(obj)) {
> 3567:     fatal("Module object unimplemented");

This is oddly harsh; the other rejected objects just return false with a soft 
bailout.

Perhaps add a comment explaining the choice to go fatal?

Or maybe just do the `set_lookup_failed` dance here as well?

src/hotspot/share/code/aotCodeCache.cpp line 4080:

> 4078:     // Required by initial stubs
> 4079:     
> ADD_EXTERNAL_ADDRESS(SharedRuntime::exception_handler_for_return_address); // 
> used by forward_exception
> 4080:     ADD_EXTERNAL_ADDRESS(CompressedKlassPointers::base_addr());

Here’s an overall question/comment about the sequencing of 
`ADD_EXTERNAL_ADDRESS`:  It looks like the index assigned to each added addr 
depend senstively on configuration information, both static build options and 
even command line options.  What prevents the AP and PR (assembly phase and 
production run) from disagreeing on which addr is at which index?  (Or would 
any such disagreement be benign – which I doubt.)  Suppose we had a bug where 
there was an undetected config drift in the PR which affected the sequencing of 
the addrs; how would such a bug be detected?  Crashes?

If we could use some more "belt and suspenders" redundancy here, I have a 
suggestion:  Make the length (`_extrs_length`) be part of the AOT cache config, 
to be matched between AP and PR.  Sample the length at the end of startup, and 
maybe a few other places (since startup has predictable phases).  Make sure the 
expected length, observed in the AP, shows up in the PR.

src/hotspot/share/code/aotCodeCache.hpp line 360:

> 358:   do_var(uint,  GCCardSizeInBytes) \
> 359:   do_var(bool,  PreserveFramePointer) \
> 360:   do_var(bool,  UseTLAB) \

Consider `ZeroTLAB` which may also affect compilation.

Also look at `StackReservedPages`, `StackOverflow::stack_shadow_zone_size()` 
which affect the stack banging code on method entry.  Even `os::vm_page_size()` 
affects stack banging; it should be in the config if it was hard-coded in the 
AOT code.  Or, if those values are too volatile (cannot be assumed stable), 
load them from a global variable.

Also, a quick look at Shenandoah code suggests that, at some point, variables 
like `ShenandoahSATBBarrier` and `ShenandoahLoadRefBarrier` and 
`ShenandoahCardBarrier` and `ShenandoahCloneBarrier` may need checking; that 
would need its own gating on the GC as well.

More vars to consider: `UseAdler32Intrinsics`, `InlineTypePassFieldsAsArgs` 
(when Valhalla is supported), `ReduceInitialCardMarks`, 
`VM_Version::use_rop_protection()`, `VM_Version::zva_length()`, 
`VM_Version::dcache_line_size()`.  In case it’s not obvious, these random names 
came from a mechanical scan of JIT-related code!

JVMTI affects codegen, so maybe a `do_fun` for things like 
`JvmtiExport::can_hotswap_or_post_breakpoint()`, 
`JvmtiExport::can_walk_any_space()`, etc.

src/hotspot/share/compiler/compilationPolicy.cpp line 163:

> 161:       MethodTrainingData* mtd = MethodTrainingData::find_fast(m);
> 162:       if (mtd != nullptr) {
> 163:         CompileTrainingData* ctd = mtd->last_toplevel_compile(level);

Other parallel code in this file uses `compile_data_for_aot_code` but this one 
uses `last_toplevel_compile`; maybe comment why?

src/hotspot/share/compiler/compileBroker.cpp line 2665:

> 2663:     uint  total_cnt = 0;
> 2664:     uint active_cnt = 0;
> 2665:     for (JavaThread* jt : *ThreadsSMRSupport::get_java_thread_list()) {

Why not a `ThreadsListHandle` here as well?

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

PR Review Comment: https://git.openjdk.org/jdk/pull/30778#discussion_r3986831588
PR Review Comment: https://git.openjdk.org/jdk/pull/30778#discussion_r3986743368
PR Review Comment: https://git.openjdk.org/jdk/pull/30778#discussion_r3986776483
PR Review Comment: https://git.openjdk.org/jdk/pull/30778#discussion_r3986854927
PR Review Comment: https://git.openjdk.org/jdk/pull/30778#discussion_r3986867852

Reply via email to