JDK-8331087 : Move immutable nmethod data from CodeCache
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 23
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2024-04-24
  • Updated: 2024-08-30
  • Resolved: 2024-04-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 23
23 b21Fixed
Related Reports
Relates :  
Relates :  
Description
Investigate possibility to move read-only nmethod's data from CodeCache to C heap. It includes dependencies, nul_chk_table, handler_table, scopes_pcs, scopes_data, speculations, jvmci_data. It amounts for about 30% (optimized VM) of space in CodeCache.

Comments
Thank you for this change! We have applications that use super large code cache, and this change helps a lot.
30-08-2024

Changeset: bdcc2400 Author: Vladimir Kozlov <kvn@openjdk.org> Date: 2024-04-29 15:58:03 +0000 URL: https://git.openjdk.org/jdk/commit/bdcc2400db63e604d76f9b5bd3c876271743f69f
29-04-2024

Tom clarified for me that this is all about immutability in terms of writing code to read-only memory. In that case, the _failed_speculations field is indeed mutable in that it will always refer to runtime allocated memory.
28-04-2024

Sorry, Tom's right about _nmethod_mirror_index - I overlooked that. The write to _nmethod_mirror_index[1] was added by JDK-8258380. As far as I can tell, the write is still required for the sake of IsUnloadingBehaviour::is_unloading so it cannot be made immutable. Wrt _failed_speculations, I still think it is immutable as it is the address of a pointer to the failed speculations list. This pointer is allocated independently[2] and freed as part of nmethod unloading. I can't see the _failed_speculations field being written to after initialization. [1] https://github.com/openjdk/jdk/commit/1f556d22#diff-f6b79d39a54fc627561d67d22fb07d30eed6dac79520f44016d0019106fde58dR721 [2] https://github.com/openjdk/jdk/blob/16c7dcdb04a7c220684a20eb4a0da4505ae03813/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java#L88
28-04-2024

Thank you, Tom. I will move jvmci_data back to nmethod.
28-04-2024

The values in JVMCINMethodData aren’t immutable. _nmethod_mirror_index can be written to during unloading. _failed_speculations is obviously written to by deopt. The speculations are of course immutable.
27-04-2024

Thanks for the background information. Yes, JVMCI's speculations and jvmci_data are immutable.
27-04-2024

[~dnsimon] I assumed that JVMCI's speculations and jvmci_data are also immutable and I moved them too. Can you, please, confirm that they are immutable? Otherwise I will need to move them back to nmethod.
27-04-2024

Yes, we have long standing RFE JDK-7072317 to move nmethod's data from code cache to make code more compact (less CodeCache purges/flushes). There is also assumption that it should help Aarch64 - more short calls. And finally it is for Leyden project. As John Rose commented in JDK-8330181 PR: https://github.com/openjdk/jdk/pull/18895#pullrequestreview-2023615600 "As a top level goal, I hope some day soon we will get all the metadata out of code space, both mutable (as in this case) and immutable. By immutable metadata I mean all the oddly encoded non-code sections in the nmethod layout In a world with Leyden, it is best to put immutable metadata in a read-only memory-mapped part of the CDS archive, rather than in either the malloc heap or inside the nmethod itself."
27-04-2024

Is the motivation here to reduce CodeCache pressure?
27-04-2024

Updated PrintNMethodStatistics output for JavacBench: Statistics for 152 native nmethods: N. total size = 73208 N. relocation = 3232 N. main code = 32893 Statistics for 2817 bytecoded nmethods for C1: total size = 9168704 (100%) in CodeCache = 7336432 (80.016022%) header = 653544 (8.908199%) relocation = 560328 (7.637609%) constants = 352 (0.004798%) main code = 5634632 (76.803436%) stub code = 299736 (4.085583%) oops = 22256 (0.303363%) metadata = 132968 (1.812434%) immutable data = 1832272 (19.983980%) dependencies = 51992 (2.837570%) nul chk table = 116944 (6.382459%) handler table = 69408 (3.788084%) scopes pcs = 858304 (46.843700%) scopes data = 735624 (40.148186%) Statistics for 1303 bytecoded nmethods for C2: total size = 5769000 (100%) in CodeCache = 4145208 (71.853149%) header = 302296 (7.292662%) relocation = 444168 (10.715217%) constants = 800 (0.019299%) main code = 3123816 (75.359695%) stub code = 58888 (1.420628%) oops = 26560 (0.640740%) metadata = 171744 (4.143194%) immutable data = 1623792 (28.146854%) dependencies = 57072 (3.514736%) nul chk table = 65272 (4.019727%) handler table = 115368 (7.104851%) scopes pcs = 450400 (27.737543%) scopes data = 935680 (57.623142%) Debug Data Chunks: 421657, shared 241309, non-SP's elided 0 PcDesc Statistics: 10872 queries, 4.58 comparisons per query caches=4120 queries=10872/0, hits=2609+1354, tests=21063+28682, adds=6909 Dependency check (find_witness) calls=23726, steps=159478 (avg=6.7), singles=490
26-04-2024

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/18984 Date: 2024-04-26 21:16:03 +0000
26-04-2024

Here is PrintNMethodStatistics output for JavacBench test we use in Leyden: Statistics for 153 native nmethods: N. total size = 74472 N. relocation = 3288 N. main code = 33844 Statistics for 2832 bytecoded nmethods for C1: total in heap = 7357864 (100%) header = 657024 (8.929548%) relocation = 562608 (7.646349%) constants = 352 (0.004784%) main code = 5648296 (76.765427%) stub code = 300960 (4.090318%) oops = 22384 (0.304219%) metadata = 133296 (1.811613%) total in Cheap = 1838736 (100%) dependencies = 52080 (2.832381%) nul chk table = 117616 (6.396568%) handler table = 68712 (3.736915%) scopes pcs = 861776 (46.867847%) scopes data = 738552 (40.166286%) Statistics for 1318 bytecoded nmethods for C2: total in heap = 4161880 (100%) header = 305776 (7.347064%) relocation = 452744 (10.878353%) constants = 800 (0.019222%) main code = 3123408 (75.048004%) stub code = 59944 (1.440311%) oops = 27032 (0.649514%) metadata = 175256 (4.210981%) total in Cheap = 1654656 (100%) dependencies = 58240 (3.519765%) nul chk table = 66808 (4.037576%) handler table = 116232 (7.024542%) scopes pcs = 460032 (27.802275%) scopes data = 953344 (57.615841%) Debug Data Chunks: 428400, shared 244893, non-SP's elided 0 PcDesc Statistics: 10987 queries, 4.58 comparisons per query caches=4150 queries=10987/0, hits=2639+1381, tests=21244+29098, adds=6967 Dependency check (find_witness) calls=23907, steps=163569 (avg=6.8), singles=512
25-04-2024