Skip to content

8354887: Preserve runtime blobs in AOT code cache #25019

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

ashu-mehra
Copy link
Contributor

@ashu-mehra ashu-mehra commented May 3, 2025

8350209 introduced the framework for storing code in aot code cache and used it for caching i2c/c2i adapters.
This PR extends the AOTCodeCache infrastructure and stores various runtime blobs (shared blobs, C1 and C2 runtime blobs) in the AOT code cache. It adds a new diagnostic flag AOTStubCaching to enable/disable the caching of these blobs.
AOTCodeFlags.java test is extended to cover AOTStubCaching.


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-8354887: Preserve runtime blobs in AOT code cache (Enhancement - P4)

Contributors

  • Andrew Dinn <adinn@openjdk.org>

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 25019

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

Using diff file

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

Using Webrev

Link to Webrev Comment

ashu-mehra added 9 commits May 3, 2025 00:08
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Ensure CompressedOops::base and CompressedKlssPointers::base does not
change in production run

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@bridgekeeper
Copy link

bridgekeeper bot commented May 3, 2025

👋 Welcome back asmehra! 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 May 3, 2025

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

@openjdk
Copy link

openjdk bot commented May 3, 2025

@ashu-mehra 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.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label May 3, 2025
@ashu-mehra ashu-mehra changed the title Preserve runtime blobs master 8354887: Preserve runtime blobs in AOT code cache May 3, 2025
@openjdk openjdk bot added the rfr Pull request is ready for review label May 3, 2025
@ashu-mehra
Copy link
Contributor Author

/cc hotspot-runtime
/cc hotspot-compiler

/label remove hotspot

@openjdk openjdk bot added the hotspot-runtime hotspot-runtime-dev@openjdk.org label May 3, 2025
@openjdk
Copy link

openjdk bot commented May 3, 2025

@ashu-mehra
The hotspot-runtime label was successfully added.

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.org label May 3, 2025
@openjdk
Copy link

openjdk bot commented May 3, 2025

@ashu-mehra
The hotspot-compiler label was successfully added.

@openjdk openjdk bot removed the hotspot hotspot-dev@openjdk.org label May 3, 2025
@openjdk
Copy link

openjdk bot commented May 3, 2025

@ashu-mehra
The hotspot label was successfully removed.

@mlbridge
Copy link

mlbridge bot commented May 3, 2025

Webrevs

Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

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

Few comments.

Comment on lines 1863 to 1868
if (AOTCodeCache::is_on_for_dump()) {
// Created runtime_call_type relocation when caching code
__ lea(r10, RuntimeAddress((address)$meth$$method));
} else {
__ mov64(r10, (int64_t) $meth$$method);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should do it always, not conditionally. On AArch64 it is unconditional - relocation processing know how to do that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I will update premain code too later.

Comment on lines 300 to 303
~CHeapString() {
os::free((void*)_string);
_string = nullptr;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Move it into .cpp so you don't need to include os.hpp here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Constructor too.

@@ -157,6 +158,7 @@ static bool check_compiled_frame(JavaThread* thread) {
C2_STUB_TYPEFUNC(name), \
C2_STUB_C_FUNC(name), \
C2_STUB_NAME(name), \
(int)C2_STUB_ID(name), \
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, align \

@@ -170,6 +172,7 @@ static bool check_compiled_frame(JavaThread* thread) {
notify_jvmti_vthread_Type, \
C2_JVMTI_STUB_C_FUNC(name), \
C2_STUB_NAME(name), \
(int)C2_STUB_ID(name), \
Copy link
Contributor

Choose a reason for hiding this comment

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

Here too.

Comment on lines 25 to 27
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Conditional includes are placed at the end of includes.

Comment on lines 419 to 422
if (_compressedKlassBase != CompressedKlassPointers::base()) {
log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CompressedKlassPointers::base() = %p vs current %p", _compressedKlassBase, CompressedKlassPointers::base());
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.

I would suggest to use relocation for klass's base too but not in these changes. I think bailout is fine here.

return false;
}
log_debug(aot, codecache, stubs)("Writing blob '%s' to AOT Code Cache", name);
log_info(aot, codecache, stubs)("Writing blob '%s' (id=%u, kind=%s) to AOT Code Cache", name, id, AOTCodeEntry::kind_string(entry_kind));
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, use log_debug() in final changes.

return reader.compile_code_blob(name, entry_offset_count, entry_offsets);
CodeBlob* blob = reader.compile_code_blob(name, entry_offset_count, entry_offsets);

log_info(aot, codecache, stubs)("Read blob '%s' (id=%u, kind=%s) from AOT Code Cache", name, id, AOTCodeEntry::kind_string(entry_kind));
Copy link
Contributor

Choose a reason for hiding this comment

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

Use log_debug()

Comment on lines +1116 to +1119
log_trace(aot, codecache, stubs)("asm remark offset=%d, str='%s'", offset, str);
uint n = write_bytes(&offset, sizeof(uint));
if (n != sizeof(uint)) {
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.

Consider using id_for_C_string() and record ID instead of coping string. These strings should be recorded in C strings table already.
If id_for_C_string() does not find - assert. We should add add_C_string() in missing place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The asm remarks and dbg strings are not currently recorded in C string table.
I tried to add these strings by calling AOTCodeCache::add_C_string() in AsmRemarkCollection::insert() but this results in adding LOTS of strings. So I add the strings to the string table only when writing the asm remarks. This keeps the string count in check.

Comment on lines 1156 to 1158
log_trace(aot, codecache, stubs)("dbg string=%s", str);
uint len = (uint)strlen(str) + 1; // including '\0' char
uint n = write_bytes(str, len);
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

@vnkozlov
Copy link
Contributor

vnkozlov commented May 3, 2025

We need to do something about Compressed Klass base:

java -XX:AOTCache=app.aotcache -XX:+UnlockDiagnosticVMOptions -XX:+AOTAdapterCaching -XX:+AOTStubCaching -Xlog:aot+codecache+init=debug -cp hello.jar HelloWorld
[0.009s][debug][aot,codecache,init] Mapped 548864 bytes at address 0x00007f17b1611000 at AOT Code Cache
[0.009s][info ][aot,codecache,init] Loaded 384 AOT code entries from AOT Code Cache
[0.009s][debug][aot,codecache,init]   Adapters:  total=316
[0.009s][debug][aot,codecache,init]   Shared Blobs: total=14
[0.009s][debug][aot,codecache,init]   C1 Blobs: total=34
[0.009s][debug][aot,codecache,init]   C2 Blobs: total=20
[0.009s][debug][aot,codecache,init]   AOT code cache size: 543392 bytes
[0.009s][debug][aot,codecache,init]   Loaded 1 C strings of total length 28 at offset 521860 from AOT Code Cache
[0.010s][debug][aot,codecache,init] AOT Code Cache disabled: it was created with CompressedKlassPointers::base() = 0x7f56c6000000 vs current 0x7f1762000000
[0.010s][info ][aot,codecache,init] Unable to use AOT Code Cache.
Hellow World!

@vnkozlov
Copy link
Contributor

vnkozlov commented May 3, 2025

Which blob/stubs decompress/compress klass using the base?

@vnkozlov
Copy link
Contributor

vnkozlov commented May 3, 2025

May be we should use Relocation for it.

@ashu-mehra
Copy link
Contributor Author

We need to do something about Compressed Klass base:

I too feel bailing out is too restrictive. In my tests I have seen this happening too frequently to ignore.

Which blob/stubs decompress/compress klass using the base?

CompressedKlassPointers::base() is called by C1 blob for is_instance_of [0].

[0]

__ load_klass(temp2, obj, /*tmp*/temp1);

mov64(tmp, (int64_t)CompressedKlassPointers::base());

@ashu-mehra
Copy link
Contributor Author

@vnkozlov How about updating decode_klass_not_null like this?

  if (CompressedKlassPointers::base() != nullptr) {
    if (AOTCodeCache::is_on_for_dump()) {
      movptr(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
    } else {
      mov64(tmp, (int64_t)CompressedKlassPointers::base());
    }
    addq(r, tmp);
  }

and adding CompressedKlassPointers::base_addr() to the AOTAddressTable.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 5, 2025

Yes, please do that in decode_klass_not_null().
We update other methods for nmethod caching in JDK 26.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 5, 2025

Test crashes on linux-x64 with debug VM:

% make test JTREG=AOT_JDK=true CONF=fastdebug TEST=compiler/c2/cr6865031/Test.java

CompileCommand: inline compiler/c2/cr6865031/AbstractMemoryEfficientList.equals bool inline = true
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (/jdk_git/open/src/hotspot/cpu/x86/macroAssembler_x86.cpp:442), pid=843441, tid=843472
#  fatal error: DEBUG MESSAGE: StubRoutines::forward exception: no pending exception (1)
#
# JRE version: Java(TM) SE Runtime Environment (25.0) (fastdebug build 25-internal-LTS-2025-05-03-2344395.vkozlov...)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-internal-LTS-2025-05-03-2344395.vkozlov..., mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0x153a125]  MacroAssembler::debug64(char*, long, long*)+0x45

@vnkozlov
Copy link
Contributor

vnkozlov commented May 5, 2025

Test runtime/cds/appcds/aotClassLinking/MethodHandleTest.java crashed on linux-aarch64:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000ffffb4df1f84, pid=3645763, tid=3645766
#
# JRE version: Java(TM) SE Runtime Environment (25.0) (fastdebug build 25-internal-LTS-2025-05-05-2218263.vladimir.kozlov.jdkgit2)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-internal-LTS-2025-05-05-2218263.vladimir.kozlov.jdkgit2, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-aarch64)
# Problematic frame:
# v  ~RuntimeStub::Shared Runtime throw_NullPointerException_at_call_blob 0x0000ffff73dd2db0

@vnkozlov
Copy link
Contributor

vnkozlov commented May 5, 2025

I attached hs_err file to RFE in JBS.

@ashu-mehra
Copy link
Contributor Author

@vnkozlov thanks for testing the patch.

% make test JTREG=AOT_JDK=true CONF=fastdebug TEST=compiler/c2/cr6865031/Test.java

I can recreate this test locally. Looking into it.

@ashu-mehra
Copy link
Contributor Author

I can recreate this test locally. Looking into it.

Looks like the code for C2 blobs generated in assembly phase is not correct.
For example, code for new_instance blob is:

[0.141s][550409][aot,codecache,stubs] Decoding CodeBlob, name: C2 Runtime new_instance, at  [0x00007fed0f904260, 0x00007fed0f9042b8]  88 bytes
[0.141s][550409][aot,codecache,stubs]  ;; N1: # out( B1 ) <- in( B3 B2 )  Freq: 1
[0.141s][550409][aot,codecache,stubs]  ;; B1: # out( B3 B2 ) <- BLOCK HEAD IS JUNK  Freq: 1
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904260:   sub    $0x8,%rsp
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904267:   mov    %rbp,(%rsp)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f90426b:   mov    %rsp,0x3e8(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904272:   mov    %rsi,%rdi
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904275:   mov    %r15,%rsi
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904278:   movabs $0x7fed28908982,%r10
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904282:   call   *%r10
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904285:   nopl   0x0(%rax,%rax,1)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f90428d:   mov    %r12,0x3e8(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904294:   mov    %r12,0x3f0(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f90429b:   mov    0x440(%r15),%rax
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042a2:   mov    %r12,0x440(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042a9:   cmp    0x8(%r15),%r12
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042ad:   jne    0x00007fed0f9042b1
[0.141s][550409][aot,codecache,stubs]  ;; B2: # out( N1 ) <- in( B1 )  Freq: 0.999999
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042af:   pop    %rbp
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042b0:   ret    
[0.141s][550409][aot,codecache,stubs]  ;; B3: # out( N1 ) <- in( B1 )  Freq: 1e-06
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042b1:   pop    %rbp
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042b2:   jmp    Stub::forward_exception
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042b7:   hlt    

Look at the instructions generated after the call to runtime method:

[0.141s][550409][aot,codecache,stubs]   0x00007fed0f90428d:   mov    %r12,0x3e8(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f904294:   mov    %r12,0x3f0(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f90429b:   mov    0x440(%r15),%rax
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042a2:   mov    %r12,0x440(%r15)
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042a9:   cmp    0x8(%r15),%r12
[0.141s][550409][aot,codecache,stubs]   0x00007fed0f9042ad:   jne    0x00007fed0f9042b1

Comparing it with the case when AOT code cache is not used:

   0x7fffdef07c8d:	movq   $0x0,0x3e8(%r15)
   0x7fffdef07c98:	movq   $0x0,0x3f0(%r15)
   0x7fffdef07ca3:	mov    0x440(%r15),%rax
   0x7fffdef07caa:	movq   $0x0,0x440(%r15)
   0x7fffdef07cb5:	mov    0x8(%r15),%r10
   0x7fffdef07cb9:	test   %r10,%r10
   0x7fffdef07cbc:	jne    0x7fffdef07cc0

For some reason r12 is used instead of null (0x0). r12 is the CompressedOop::base address.
C2 code that generates this is

// Clear last_Java_sp

I suspect I missed porting a change from premain. @adinn @vnkozlov any idea what that could be?

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

Easy to fix. Look for checks UseCompressedOops && (CompressedOops::base() == nullptr) in predicates in x86_64.ad and add additional check !AOTCodeCache::is_on_for dump(). May be create new function r12_is_null() or something.

@adinn
Copy link
Contributor

adinn commented May 7, 2025

I suspect I missed porting a change from premain. @adinn @vnkozlov any idea what that could be?

@ashu-mehra Just to explain what is going on here:

This is a performance trick. When compressed oops base is null r12 (aka rheapbase) will have been initialized to zero so it can be used as a zero register. This allows, for example, a move instruction to employ a register operand immediate rather than include a 64 bit zero value in the instruction stream, which results in reduced code size. In this case the two moves are zeroing the current Java thread's frame anchor fields, last Java frame pc and sp, which are only set while the thread is in native.

This trick is fine when generated code is run in the same JVM but no use if the code is generated in a VM with zero compressed oops base then reloaded into a JVM where it is no longer null.

So, Vladimir's advice is to disable this trick when generating AOT code.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

In premain branch we don't have null in R12 because we set shift together with base when we generate AOT code: compressedOops.cpp#L51

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

@adinn Do you remember why we commented UseCompatibleCompressedOops setting?:
openjdk/leyden@478f86f

It is still not enabled - how we are not crashing in premain?

@ashu-mehra
Copy link
Contributor Author

It is still not enabled - how we are not crashing in premain?

That's a news to me. I thought we were setting UseCompatibleCompressedOops to true which is why we are avoiding this issue in premain. But ..

@adinn
Copy link
Contributor

adinn commented May 7, 2025

@vnkozlov Ergonomics comes into play. It is set to true in cdsConfig.cpp if CacheDataStore != nullptr.

@ashu-mehra
Copy link
Contributor Author

@adinn in premain it is commented out -
https://github.com/openjdk/leyden/blob/f09d2f7724c628c90df51eacb16b33fee710ed1a/src/hotspot/share/cds/cdsConfig.cpp#L790

#ifdef _LP64
  // FLAG_SET_ERGO_IF_DEFAULT(UseCompatibleCompressedOops, true); // FIXME @iklam - merge with mainline - UseCompatibleCompressedOops
#endif

I don't see any other place it is set.

@adinn
Copy link
Contributor

adinn commented May 7, 2025

I don't see any other place it is set.

I do ;-)

Look at cdsConfig.cpp:468 in method CDSConfig::check_vm_args_consistency()

  if (CacheDataStore != nullptr) {
    // Leyden temp work-around:
    //
    // By default, when using CacheDataStore, use the HeapBasedNarrowOop mode so that
    // AOT code can be always work regardless of runtime heap range.
    //
    // If you are *absolutely sure* that the CompressedOops::mode() will be the same
    // between training and production runs (e.g., if you specify -Xmx128m
    // for both training and production runs, and you know the OS will always reserve
    // the heap under 4GB), you can explicitly disable this with:
    //     java -XX:-UseCompatibleCompressedOops -XX:CacheDataStore=...
    // However, this is risky and there's a chance that the production run will be slower
    // because it is unable to load the AOT code cache.
#ifdef _LP64
    FLAG_SET_ERGO_IF_DEFAULT(UseCompatibleCompressedOops, true);  // <== here
#endif

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

@adinn I think you are looking on old version of premain branch. The latest changeset is Igor's "Address review comments".

@adinn
Copy link
Contributor

adinn commented May 7, 2025

Ah yes, I was looking at an old version. Apologies for that.

@adinn
Copy link
Contributor

adinn commented May 7, 2025

I looked back at the history and found that this line got commented out as part of a merge from mainline (date: 2025-01-15 shaid 4cd4c7c).

I'm not at all sure why Ioi did this and have no idea why he added my name to the original FIXME. The very next change he made in the premain branch was to update the FIXME comment, resetting it to his name.

I also don't understand why this is not biting us in premain.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

There could be testing failures which expect some state of compressed oops. I will test enabling this flag.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

We were lucky. I reproduced issue in premain with HelloWord by running AOTMode=create -Xmx4G and product run with Xmx31g. It has the same shift = 3 but different base (0 for 4Gb).

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

Unfortunately we can't enable the flag (that is why Ioi commented it, I think):

#  Internal Error (/leyden/open/src/hotspot/share/oops/compressedOops.cpp:87), pid=1169225, tid=1169229
#  assert((intptr_t)base() <= ((intptr_t)_heap_address_range.start() - (intptr_t)os::vm_page_size()) || base() == nullptr) failed: invalid value
#
# JRE version:  (25.0) (fastdebug build )
# Java VM: Java HotSpot(TM) 64-Bit Server VM (fastdebug 25-internal-LTS-2025-05-07-1649004.vkozlov..., mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xba81e9]  CompressedOops::initialize(ReservedHeapSpace const&)+0x3c9

@ashu-mehra please restore verification check for COOP base you had. instead of patching x86_64.ad file

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

I think it is fine not use AOT code when the heap base does not match. Based on my test it will happen only with big heap's size difference between assembly and production runs.

@ashu-mehra
Copy link
Contributor Author

@vnkozlov I wonder if that assert needs modification as well.

This assert assumes that if CompressedOops::_base is not null, then it will be set to a page size before the heap range start. This is fine because _base is not null only when heap range goes beyond OopEncodingHeapMax, and in such cases ReservedHeapSpace::noaccess_prefix is equal to os::vm_page_size().
But with UseCompatibleCompressedOops the _base is set to non-null value even when heap range is within OopEncodingHeapMax and in such cases ReservedHeapSpace::noaccess_prefix is 0.

I think the assert should be using noaccess_prefix instead of hard-coding os::vm_page_size:

-  assert((intptr_t)base() <= ((intptr_t)_heap_address_range.start() - (intptr_t)os::vm_page_size()) ||
+  assert((intptr_t)base() <= ((intptr_t)_heap_address_range.start() - (intptr_t)heap_space.noaccess_prefix()) ||

With this change I can run the helloworld program with UseCompatibleCompressedOops enabled.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

I also hit failure in premain testing in runtime/cds/appcds/leyden/LeydenHello.java#aot test on Windows-x64 due to wrong Compress Class encoding due to different base:

[0.031s][info][cds] The current max heap size = 1024M, G1HeapRegion::GrainBytes = 1048576
[0.031s][info][cds]     narrow_klass_base = 0x0000015298000000, arrow_klass_pointer_bits = 32, narrow_klass_shift = 0

AOT code uses 0x800000000 instead :

88: 8b 78 08                mov    edi,DWORD PTR [rax+0x8]
8b: 49 ba 00 00 00 00 08    movabs r10,0x800000000
92: 00 00 00
95: 49 03 fa                add    rdi,r10
98: 48 3b 5f 38             cmp    rbx,QWORD PTR [rdi+0x38]

So we need the relocation fix from current changes in premain branch too.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

With this change I can run the helloworld program with UseCompatibleCompressedOops enabled.

I will try your assert fix.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

Several AOT tests failed on linux-x64 with flag enabled:

$ make test CONF=fast TEST=test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking TEST_OPTS_JAVA_OPTIONS="-Xmixed -XX:+UseCompatibleCompressedOops"
...
   TEST                                              TOTAL  PASS  FAIL ERROR  SKIP   
   jtreg:open/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking
>>                                                      15     5     8     0     2

@vnkozlov
Copy link
Contributor

vnkozlov commented May 7, 2025

I moved UseCompatibleCompressedOops flag setting to check_vm_args_consistency() to affect current workflow.
And I used if (AOTCodeCache::is_caching_enabled()) { for its setting.

@vnkozlov
Copy link
Contributor

vnkozlov commented May 8, 2025

I think for these changes we should not use AOT code when the heap base does not match.
Something changed in compressed oops code which prevents enforcing encoding.
We can investigate and fix it later.

@mlbridge
Copy link

mlbridge bot commented May 8, 2025

Mailing list message from John Rose on hotspot-compiler-dev:

On 7 May 2025, at 12:37, Vladimir Kozlov wrote:

I think it is fine not use AOT code when the heap base does not match. Based on my test it will happen only with big heap's size difference between assembly and production runs.

Won?t ASLR spoil matches on some platforms?

The match must depend on how the VM negotiates memory
segments with the OS. If the OS is committed to random
segment assignment, then routine mismatch is something
we should be prepared to address, as the issue comes up.

(I?m not saying we need to address it now, if tests
seem to behave properly. But I suspect even now there
are some platforms that will throw a monkey wrench at us.)

ASLR: https://en.wikipedia.org/wiki/Address_space_layout_randomization

@vnkozlov
Copy link
Contributor

vnkozlov commented May 8, 2025

@rose00 We have solution for that: we enforce encoding instructions (UseCompatibleCompressedOops flag) and use relocation info to patch correct COOP base address when loading AOT code.
The current issue is something changed in COOP code in runtime which cause next assert hit when we enforce encoding and use AOT code: instanceKlass.cpp#L794

@ashu-mehra
Copy link
Contributor Author

I think for these changes we should not use AOT code when the heap base does not match.
Something changed in compressed oops code which prevents enforcing encoding.
We can investigate and fix it later.

@vnkozlov for this PR we are relying on having relocation for COOP base, not on enforcing encoding. And that should be able to handle cases where heap base is different in assembly vs prod. Why do you suggest to not use AOT code when the heap base does not match?

@vnkozlov
Copy link
Contributor

vnkozlov commented May 8, 2025

To support that you would need to modify x86_64.ad to exclude r12 from usage as 0 as we discussed.
I think that using your original changes to not use AOT code with mismatched coop base is simpler for these changes and more robust for mainline. I concern that we may missing some places which will cause issues later. And we near JDK 25 fork. We can do more changes/improvements later in JDK 26.

One suggestion I have is to skip using only new runtime blobs you are adding when bases do not match because adapters don't have this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot-compiler hotspot-compiler-dev@openjdk.org hotspot-runtime hotspot-runtime-dev@openjdk.org rfr Pull request is ready for review
Development

Successfully merging this pull request may close these issues.

3 participants