Skip to content

Conversation

@adinn
Copy link
Contributor

@adinn adinn commented Nov 20, 2025

This PR adds save and restore of all generated stubs to the AOT code cache on x86 and aarch64. Other arches are modified to deal with the related generic PAI changes.

Small changes were required to the aarch64 and x86_64 generator code in order to meet two key constraints:

  1. the first declared entry of every stub starts at the first instruction in the stub code range
  2. all data/code cross-references from one stub to another target a declared stub entry

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issue

  • JDK-8372617: Save and restore stubgen stubs when using an AOT code cache (Enhancement - P4)

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/28433/head:pull/28433
$ git checkout pull/28433

Update a local copy of the PR:
$ git checkout pull/28433
$ git pull https://git.openjdk.org/jdk.git pull/28433/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 28433

View PR using the GUI difftool:
$ git pr show -t 28433

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/28433.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Nov 20, 2025

👋 Welcome back adinn! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Nov 20, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label Nov 20, 2025
@openjdk
Copy link

openjdk bot commented Nov 20, 2025

@adinn The following label will be automatically applied to this pull request:

  • hotspot

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@adinn
Copy link
Contributor Author

adinn commented Nov 20, 2025

This PR still needs to ensure that pre-universe stub entries are registered in the AOT address table. These stubs cannot be saved and restored because the AOT cache does not exist before universe init. As a consequence their addresses cannot be registered using the normal generate time mechanism. The required fix will be to add them via special case handling as soon as the AOT cache and address table have been initialised (preferably at the point where the majority of external addresses are registered).

This omission is not a problem for this patch i.e. as far as reference from existing stubs is concerned since none of the saved stubs targets to a pre-universe stub entry. However, they ought to be registered in case that situation changes or in case an nmethod that gets saved to and reloaded from the AOT cache needs at some point to target a pre-universe stub.

Comment on lines 603 to 611
int entry_count = StubInfo::entry_count(stub_id);
assert(entry_count == 1, "sanity check");
if (find_archive_data(stub_id)) {
address start = nullptr;
address end = nullptr;
load_archive_data(stub_id, start, end);
return start;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code pattern repeats a lot. Can we move it into load_archive_data()?

address start = load_archive_data(stub_id);
if (start != nullptr) {
  return start;
}

And have an other specialized load_archive_data if you need end value.

Copy link
Contributor Author

@adinn adinn Nov 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think I can probably refactor this to make it simpler and avoid returning end. I'll push a revised version soon. Return of end is mostly a hangover from an older version but it does still serve a purpose (see below). Originally, it was not clear what all the other specialized cases were going to be but I thinkit is now fairly clear that we only need to cater for:

  • multiple entries other than the start address
  • multiple extra addresses
  • both the above.

n.b. entries and extras are distinguished by one simple criterion: the former can be accessed from AOT code while the latter cannot. So, entries need to be registered with the AOT address table beneath load_entry while extras can be omitted (although they almost certainly need to be registered with the current runtime by the caller). That distinction ought to be written down in a comment somewhere, also the acceptable values for both:

start clearly must be non-null. Additional entries may be nullptr or in the range [start, end). Extra addresses may be nullptr or in the range [start, end] i.e. extras can address the first byte after the end of the stub.

This is needed so that an extra can be used to mark the (exclusive) end address of a range that covers the tail of a stub. So far, it has always been the case that extra addresses occur in triples identifying UnsafeMemoryAccess handler regions, (open, close, handler). I'm leaving it open as to whether any other uses might turn up which is why processing of extras happens in the caller rather than under load_entry.

load_entry now knows and verifies how many entries it ought to be retrieving and accepts an extras array if and only if there are extra addresses in the archive. It also range checks the entry/extra addresses. So, all a caller needs to do is assign extra entries to the outputs passed by the caller then validate the extras count and process them appropriate to whatever the stub understands them to mean.

end was originally being returned by load_entry to allow the caller to range check both entry and extra addresses but that check is now redundant. It is still needed because of an unnecessary complication in the current code. Addresses are converted to offsets before saving in the archive and translated back to addresses when loading. store_entry does ensure that all entry or extra offsets addresses lie within the range [start, end) and [start, end] respectively. However, nullptr and end both get saved to the archive as start - end. That means both of them get restored as nullptr. Clients are expected to know whether a restored nullptr at some offset in the extras array is really an end address and substitute end in its place (e.g. in the case where close == nullptr really means close == end). Because of that load_entry has to make end visible to the caller. If I change things so that nullptr is saved as UINT_MAX in that will avoid the ambiguity, allowing the client to use the value without an extra check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 13107 to 13115
void StubGenerator_AOTAddressTable_init() {
ResourceMark rm;
GrowableArray<address> external_addresses;
// publish static addresses referred to by aarch64 generator
StubGenerator::init_AOTAddressTable(external_addresses);
// publish external data addresses defined in nested aarch64 class
StubRoutines::aarch64::init_AOTAddressTable(external_addresses);
AOTCodeCache::publish_external_addresses(external_addresses);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and *init_AOTAddressTable() methods should be under #if INCLUDE_CDS

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


// Non-generated init method

void StubRoutines::init_AOTAddressTable() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this body be in platform specific file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll add an implementation to file stubRoutines_xxx.cpp for each platform.

@vnkozlov
Copy link
Contributor

I noticed that we have to add a lot of local data tables addresses for stubs (math intrinsics).
May be we should consider to have platform specific AOT address tables for such address (and platform specific stubs). To avoid search in one big table.

@openjdk
Copy link

openjdk bot commented Nov 26, 2025

@adinn this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout save-stubgen-stubs
git fetch https://git.openjdk.org/jdk.git master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label Nov 26, 2025
@openjdk openjdk bot removed the merge-conflict Pull request has merge conflict with target branch label Nov 26, 2025
@adinn adinn changed the title Save stubgen stubs 8372617: Save and restore stubgen stubs when using an AOT code cache Nov 26, 2025
@adinn adinn marked this pull request as ready for review November 28, 2025 10:35
@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 28, 2025
@mlbridge
Copy link

mlbridge bot commented Nov 28, 2025

Webrevs

Copy link
Contributor

@ashu-mehra ashu-mehra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I only have minor comments, some typos and unused code.

// handler pc may be null in which case it defaults to the
// default_handler.

void StubCodeGenerator::register_unsafe_access_handlers(GrowableArray<address> &entries, int begin, int count) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a case or is it possible that begin is non -zero? I think it is same to assume we need to register all the values in entries in the UnsafeMemoryAccess::_table, right?

static void init_early_stubs_table() NOT_CDS_RETURN;
static void init_shared_blobs_table() NOT_CDS_RETURN;
static void init_early_c1_table() NOT_CDS_RETURN;
static void set_shared_stubs_complete() NOT_CDS_RETURN;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see set_shared_stubs_complete, set_c1_stubs_complete and set_c2_stubs_complete called from anywhere.


~AOTStubData() CDS_ONLY({FREE_C_HEAP_ARRAY(StubAddrRange, _ranges);}) NOT_CDS({})

bool is_open() CDS_ONLY({ return (_flags & OPEN) != 0; }) NOT_CDS_RETURN_(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra indentation

_complete = true;
void AOTCodeAddressTable::set_c1_stubs_complete() {
assert(!_c1_stubs_complete, "repeated close for c1 stubs!");
_c2_stubs_complete = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be setting _c1_stubs_complete

for (int i = 0; i < addresses.length(); i++) {
SET_ADDRESS(_extrs, addresses.at(i));
}
log_debug(aot, codecache, init)("External addresses recorded");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log message is not very helpful. Following the code I now know it refers to the step where arch specific external address are added. So it does seem relevant, however the current message does not convey the context. But I don't know how to improve it either :).

@@ -2383,6 +2736,9 @@ class StubGenerator: public StubCodeGenerator {
__ leave(); // required for proper stackwalking of RuntimeStub frame
__ ret(lr);

// record the stub entry and end plus any no_push entry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before, comments refers to "no_push entry".

vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); // PSHUFFLE_BYTE_FLIP_MASK wrt rip
assert(pshuffle_byte_flip_mask_addr + 32 == StubRoutines::x86::pshuffle_byte_flip_mask_ymm_lo_addr_sha512(), "sanity");

vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); // PSHUFFLE_BYTE_FLIP_MASK wrt rip
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation is off

assert(pshuffle_byte_flip_mask_addr + 64 == StubRoutines::x86::pshuffle_byte_flip_mask_dc00_addr(), "sanity");

vmovdqu(BYTE_FLIP_MASK, ExternalAddress(pshuffle_byte_flip_mask_addr + 0)); // [PSHUFFLE_BYTE_FLIP_MASK wrt rip]
vmovdqu(SHUF_00BA, ExternalAddress(pshuffle_byte_flip_mask_addr + 32)); // [_SHUF_00BA wrt rip]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we have StubRoutines::x86::pshuffle_byte_flip_mask_00ba_addr(), I think it should replace pshuffle_byte_flip_mask_addr + 32. Makes the usage of these addresses explicit.

address StubRoutines::crc32c_table_addr() { ShouldNotCallThis(); return nullptr; }

#if INCLUDE_CDS
// nothing to do for xero
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xero->zero


// Disable stubs caching until JDK-8357398 is fixed.
FLAG_SET_ERGO(AOTStubCaching, false);
// FLAG_SET_ERGO(AOTStubCaching, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't seem to access JDK-8357398. I am not sure if that bug is fixed or not. But if it is not fixed yet, I think we should keep this un-commented. I guess this was commented out for testing purpose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hotspot hotspot-dev@openjdk.org rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

3 participants