Skip to content
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

8293972: runtime/NMT/NMTInitializationTest.java#default_long-off failed with "Suspiciously long bucket chains in lookup table." #14607

Closed
wants to merge 10 commits into from

Conversation

gerard-ziemski
Copy link

@gerard-ziemski gerard-ziemski commented Jun 21, 2023

We improve the hash function, by using Mersenne prime (2^x - 1) i.e. 8191 , as the table size, which when combined with "modulo" operation, provides a uniform bit distribution.

To help with testing this change to make sure we improve the hash function, I collected NMTPreInitAllocation data on 3 platforms: macOS, Linux and Windows, using 100 runs of test/hotspot/jtreg/runtime/NMT/NMTInitializationTest.java and computed stdev as well as average max chain:

mac OS data:
 BEFORE total: max chain: 676, empties: 210892, ranges: 676, std_devs: 112.771
  AFTER total: max chain: 622, empties: 230762, ranges: 622, std_devs: 111.094
 BEFORE avg: max chain: 5.061, empties: 18.695, ranges: 5.061, std_devs: 0.010
  AFTER avg: max chain: 4.181, empties: 16.970, ranges: 4.161, std_devs: 0.009
	
Linux data:
 BEFORE total: max chain: 523, empties: 193174, ranges: 523, std_devs: 103.243
  AFTER total: max chain: 432, empties: 175347, ranges: 430, std_devs: 90.670
 BEFORE avg: max chain: 6.540, empties: 20.402, ranges: 6.540, std_devs: 0.011
  AFTER avg: max chain: 6.017, empties: 22.324, ranges: 6.017, std_devs: 0.011

Windows data:
 BEFORE total: max chain: 578, empties: 201224, ranges: 578, std_devs: 108.988
  AFTER total: max chain: 491, empties: 218653, ranges: 491, std_devs: 104.879
 BEFORE avg: max chain: 5.602, empties: 19.504, ranges: 5.602, std_devs: 0.011
  AFTER avg: max chain: 4.759, empties: 21.193, ranges: 4.759, std_devs: 0.010

Note: the lower the number, the better.
Note: the stdedev and max chain are the most important numbers here.

Tested manually with jtreg -nr -va -jdk:./build/macosx-x86_64-server-fastdebug/images/jdk test/hotspot/jtreg/runtime/NMT and gtestLauncher -jdk ./build/macosx-x86_64-server-fastdebug/images/jdk --gtest_output=xml:test_result.xml --gtest_catch_exceptions=0 --gtest_filter="NMT*:os*" -XX:NativeMemoryTracking=summary and Mach5 hs-tier1,2,3,4,5


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-8293972: runtime/NMT/NMTInitializationTest.java#default_long-off failed with "Suspiciously long bucket chains in lookup table." (Bug - P4)

Reviewers

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 14607

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

Using diff file

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

Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Jun 21, 2023

👋 Welcome back gziemski! 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 Jun 21, 2023

@gerard-ziemski The following label will be automatically applied to this pull request:

  • hotspot-runtime

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-runtime hotspot-runtime-dev@openjdk.org label Jun 21, 2023
@gerard-ziemski gerard-ziemski marked this pull request as ready for review June 21, 2023 22:54
@openjdk openjdk bot added the rfr Pull request is ready for review label Jun 21, 2023
@mlbridge
Copy link

mlbridge bot commented Jun 21, 2023

@dholmes-ora
Copy link
Member

We also, mark output with PID to help identify which test process it is coming from as the attached log was very confusing to read.

Isn't there only a single process created per test?

@dholmes-ora
Copy link
Member

This is failing in GHA:

 assert(false) failed: NMT preinit lookup table degenerated (7/14 chains longer than 30)

@gerard-ziemski
Copy link
Author

This is failing in GHA:

 assert(false) failed: NMT preinit lookup table degenerated (7/14 chains longer than 30)

Investigating...

@gerard-ziemski
Copy link
Author

This is failing in GHA:

 assert(false) failed: NMT preinit lookup table degenerated (7/14 chains longer than 30)

Investigating...

I used (2^13 - 1) notation in the code to be more explicit on how the value is constructed, but ^ is XOR operator, not pow. I will fix this:

static const int table_size = 8191; // i.e. 8191==(2^13 - 1);

Copy link
Member

@tstuefe tstuefe left a comment

Choose a reason for hiding this comment

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

Looking back at this, I wonder whether we should reduce the table size. 64k for this lookup table is pretty big. The MallocSizeTable itself, that arguably holds a lot more allocations, is just have as wide.

src/hotspot/share/services/nmtPreInit.hpp Outdated Show resolved Hide resolved
@gerard-ziemski
Copy link
Author

gerard-ziemski commented Jun 22, 2023

Here are the results with Thomas proposed hash function (tmp >> 3) ^ (tmp >> 35):

Mac OS data:

original total: max chain: 523, empties: 193174, ranges: 523, std_devs: 103.243
           avg: max chain: 5.061, empties: 18.695, ranges: 5.061, std_devs: 0.010

  gerard total: max chain: 432, empties: 175347, ranges: 430, std_devs: 90.670
           avg: max chain: 4.181, empties: 16.970, ranges: 4.161, std_devs: 0.009

 Thomas1 total: max chain: 485, empties: 207085, ranges: 484, std_devs: 99.429
           avg: max chain: 4.694, empties: 20.041, ranges: 4.684, std_devs: 0.010

 Thomas2 total: max chain: 520, empties: 192194, ranges: 520, std_devs: 102.801
           avg: max chain: 5.032, empties: 18.600, ranges: 5.032, std_devs: 0.010


Linux OS data:

original total: max chain: 676, empties: 210892, ranges: 676, std_devs: 112.771
           avg: max chain: 6.540, empties: 20.402, ranges: 6.540, std_devs: 0.011

  gerard total: max chain: 622, empties: 230762, ranges: 622, std_devs: 111.094
           avg: max chain: 6.017, empties: 22.324, ranges: 6.017, std_devs: 0.011

 Thomas1 total: max chain: 656, empties: 225850, ranges: 656, std_devs: 110.384
           avg: max chain: 6.346, empties: 21.849, ranges: 6.346, std_devs: 0.011

 Thomas2 total: max chain: 680, empties: 210918, ranges: 680, std_devs: 112.780
           avg: max chain: 6.578, empties: 20.404, ranges: 6.578, std_devs: 0.011


Windows OS data:

original total: max chain: 578, empties: 201224, ranges: 578, std_devs: 108.988
           avg: max chain: 5.602, empties: 19.504, ranges: 5.602, std_devs: 0.011

  gerard total: max chain: 491, empties: 218653, ranges: 491, std_devs: 104.879
           avg: max chain: 4.759, empties: 21.193, ranges: 4.759, std_devs: 0.010

 Thomas1 total: max chain: 565, empties: 218421, ranges: 565, std_devs: 107.261
           avg: max chain: 5.476, empties: 21.171, ranges: 5.476, std_devs: 0.010

 Thomas2 total: max chain: 578, empties: 201224, ranges: 578, std_devs: 108.987
           avg: max chain: 5.602, empties: 19.504, ranges: 5.602, std_devs: 0.011

Note:
 original table_size 7919
 gerard table_size 8191
 Thomas1 table_size 8191
 Thomas2 table_size 7919

Summary:

  • at the table size of 8191 which is Mersenne Prime (Thomas1), it is less than 1% better in stddev for Linux pointers, but quite a bit worse everywhere else than my proposed one (including max chain length for Linux)
  • at the table size of 7919 (Thomas2), it is virtually the same as the original and worse than my proposed one

So we don't gain anything by using clever bit shifts and xors (I know I tried many myself) compared to the "naked" pointer - the opposite in fact.

I will post the code to the sandbox I used for these experiments after I clean it up a bit...

@gerard-ziemski
Copy link
Author

gerard-ziemski commented Jun 23, 2023

Uploaded the src code of the sandbox + data sets, which I used for comparing hash functions, to the bug issue https://bugs.openjdk.org/browse/JDK-8293972

@gerard-ziemski
Copy link
Author

gerard-ziemski commented Jun 23, 2023

Looking back at this, I wonder whether we should reduce the table size. 64k for this lookup table is pretty big. The MallocSizeTable itself, that arguably holds a lot more allocations, is just have as wide.

Tested with a smaller table size 4093, about half of 8191:

Using original table size and Marsenne prime:

macOS data set:
  avg1 - max chain: 5.129, empties: 1897.891, ranges: 4.139, std_devs: 0.813
  avg2 - max chain: 4.228, empties: 1712.020, ranges: 3.238, std_devs: 0.686
  avg3 - max chain: 4.743, empties: 2030.426, ranges: 3.752, std_devs: 0.762

Linux data set:
  avg1 - max chain: 6.624, empties: 2067.396, ranges: 5.634, std_devs: 0.921
  avg2 - max chain: 6.109, empties: 2263.485, ranges: 5.119, std_devs: 0.899
  avg3 - max chain: 6.436, empties: 2213.792, ranges: 5.446, std_devs: 0.897

Windows data set:
  avg1 - max chain: 5.653, empties: 1970.208, ranges: 4.663, std_devs: 0.883
  avg2 - max chain: 4.802, empties: 2143.931, ranges: 3.812, std_devs: 0.822
  avg3 - max chain: 5.525, empties: 2136.158, ranges: 4.535, std_devs: 0.862

Note1: avg1 - the original code, table size of 7919
Note2: avg2 - gerard's proposed hash function, table size of 8191
Note3: avg3 - Thomas'es proposed hash function, table size of 8191
Note4: elapsed time: 46.5 sec
Note5: the smaller the numbers the better


Using smaller table size of 4093 for all cases:

macOS data set:
  avg1 - max chain: 6.871, empties: 318.000, ranges: 5.871, std_devs: 1.207
  avg2 - max chain: 5.881, empties: 219.634, ranges: 4.851, std_devs: 1.002
  avg3 - max chain: 6.891, empties: 308.396, ranges: 5.891, std_devs: 1.194

Linux data set:
  avg1 - max chain: 8.980, empties: 310.990, ranges: 7.990, std_devs: 1.420
  avg2 - max chain: 8.545, empties: 326.772, ranges: 7.554, std_devs: 1.401
  avg3 - max chain: 8.970, empties: 311.000, ranges: 7.980, std_devs: 1.420

Windows data set:
  avg1 - max chain: 7.703, empties: 277.386, ranges: 6.713, std_devs: 1.339
  avg2 - max chain: 6.901, empties: 314.089, ranges: 5.911, std_devs: 1.353
  avg3 - max chain: 7.703, empties: 277.366, ranges: 6.713, std_devs: 1.340

Note1: table_size == 4093 (about half of the Marsenne prime of 8191)
Note2: avg1 - the original code
Note3: avg2 - gerard's proposed hash function
Note4: avg3 - Thomas'es proposed hash function
Note5: elapsed time: 25.4 sec
Note6: the smaller the numbers the better

I think we could go smaller as you asked. My proposed hash function still is the best 2 out of 3 for stddev and best for all max chain and ranges.

@gerard-ziemski
Copy link
Author

I'm going on vacation till July 5th. Thank you David and Thomas for feedback!

@gerard-ziemski
Copy link
Author

Once I started thinking of making the NMTPreInit table smaller I kept thinking and decided to try moving NMT initialization earlier, before processing of VM arguments. This allows us to keep the table smaller, code simpler (no need to worry about realloc) and delete bunch of testing code, which used some hardcoded limits whose values seemed to be based on lots of heuristic analysis.

Please take another look and tell me what you think.

After this fix goes in, I would like to continue work alongside the idea of less reliance on NMTPreInit and try to eliminate it completely, by turning "summary" NMT ON by default in a follow-up issue.

@tstuefe
Copy link
Member

tstuefe commented Jul 20, 2023

Sorry, I appreciate your work, but I'm not a big fan. I had similar thoughts when building NMTPreinit, but decided to implement realloc fully because it is just a lot safer and flexible.

You bank on no reallocs ever happening in early initialization code. The amount of code that could run may surprise you. I know it surprised me. And those can be code paths very rarely taken. Realloc is such a basic function. Automatic C++ objects may realloc, for instance. I think UL has a ton of those, as has the Compiler. Or, you may crash and execute the crash handler - are we sure no realloc ever runs then?

Your patch introduces a new dependency: now we will never be able to run code beforehand that uses realloc. And we will not be able to precede NMT argument parsing with another argument. That makes the code brittle.

To be sure this works, we'd need at least add a guarantee - not an assert - at os::realloc(). Because the code paths taken can vary wildly, and you can never be sure we test everything.

Bottomline, you trade in potential crashes (guarantees) and more inflexibility for a complexity reduction in code that makes no real problem. I'd rather just dumb down the test.

Copy link
Member

@dholmes-ora dholmes-ora left a comment

Choose a reason for hiding this comment

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

Can someone remind me what the realloc issue is please. On the surface this looks like a big simplification.

Thanks.

src/hotspot/share/runtime/arguments.cpp Outdated Show resolved Hide resolved
src/hotspot/share/runtime/threads.cpp Outdated Show resolved Hide resolved
src/hotspot/share/services/memTracker.cpp Outdated Show resolved Hide resolved
@tstuefe
Copy link
Member

tstuefe commented Jul 20, 2023

Can someone remind me what the realloc issue is please. On the surface this looks like a big simplification.

Thanks.

In brief, NMTPreInit is a mechanism that allows us to initialize NMT together with all other VM subsystems after normal argument processing.

Before NMTPreInit, NMT was controlled by the launcher. That was complex and brittle and prevented us from using NMT when hotspot was embedded into a different launcher. E.g. IntelliJ, Eclipse, our gtestlauncher... the latter prevented us from having NMT-related gtests.

NMTPreInit needs to track early-state mallocs and reallocs to handle them correctly in case these blocks are handed into os::realloc or os::free after NMT initialization. Not doing so corrupts the C-heap because of malloc header mismatch.

This PR wants to remove the capability to handle early state reallocs. It tries to achieve that by moving NMT argument processing to the start of CJVM. The assumption is that no C-heap reallocs happen before that. The problem with that assumption is that we cannot be sure. We have a lot of code that runs right from the point of loading the libjvm.so on, long before CJVM is invoked. In the case of static linking (gtestlauncher or whatever Google tries to do), right from the point of initial program load.

This PR bets on no reallocs happening before CJVM. Should our bet go wrong, the C-heap will be corrupted if:

  • NMT is enabled
  • we realloc before NMT initialization and free or realloc after NMT initialization.

We had a similar discussion for https://bugs.openjdk.org/browse/JDK-8301811 and https://bugs.openjdk.org/browse/JDK-8299196 - see my comment there. For some reason, NMTPreInit seems to attract a lot of cleanup efforts.

Dealing with malloc and free seems deceptively simple. So NMTPreInit seems unnecessarily complex. But the issue itself is complex. NMTPreInit is the simplest possible answer to that complex problem. Dumbing it down more incurs a much greater risk and/or a larger deal of inflexibility.

We could get rid of it if we agree that no code must run, under any circumstances, before NMT initialization. No code because otherwise, the use of C-heap allocation is very difficult to police. And getting it wrong is very costly.

That would mean forbidding global C++ objects and platform-dependent DLL initialization. That, in turn, should be first agreed upon by the hotspot community and then has to actually happen. And I'm not sure it would be the right decision since global C++ objects are a powerful tool, especially for testing and prototyping.

My gut feeling is that I don't want to depend on this assumption and that even if we get this right now, an inability to run any form of complex code before CJVM ties us down in ways I don't yet foresee.

@tstuefe
Copy link
Member

tstuefe commented Jul 20, 2023

One more note of why I hesitate to remove "realloc"-support:

realloc is often used for buffers that grow on demand. These growth points are difficult to predict since they depend on dynamic buffer content. Therefore this code is very difficult to fully cover with tests.

We have seen these problems with stringStream back when it was still using RA as backing store. All would go well in tests, but when the customer turned on logging in a particular way, and we logged a particular sequence of log strings, the reallocation would hit just right at the wrong spot - in this case, we would reallocate in a leaf function under a temporary ResourceMark - and then later crash in the caller when the RM was removed.

For our case, it means if someone creates a global C++ object that uses e.g. a stringStream (now uses C-Heap) or a GrowableHeapArray, and uses that before CJVM, it may trigger reallocs before CJVM at a customer, but not in our tests.

@gerard-ziemski
Copy link
Author

I really do not like the complexity of NMTPreInit, and removing realloc from it looked promising, but that is actually an optional simplification, that we do not strictly need for this fix.

So I can add realloc back to NMTPreInit if required, after I consider this issue more and am unable to accommodate your use cases.

What about the other change, where we move NMT initialization before we process the arguments, which makes the NMTPreInit table much smaller? Is that part OK?

@gerard-ziemski
Copy link
Author

Thank you David and Thomas for your feedback.

I will do David's suggestions shortly, but Thomas realloc will require bit more time of thinking it through. And I may need to add realloc back...

@gerard-ziemski
Copy link
Author

I'm leaning towards adding back the realloc to NMTPreInit for now.

I will tackle replacing NMTPreInit with NMT in summary mode in a different issue.

@tstuefe
Copy link
Member

tstuefe commented Jul 21, 2023

I really do not like the complexity of NMTPreInit

Yeah, I noticed.

IMHO There are tons of better targets for cleanups and reviewer cycles. Just from the top of my head the NMT backend, the virtual memory abstraction layer, UL, ReservedSpace, Hotspot arena handling... all these are areas are quite complex and often very messy and would benefit a lot from cleanup attention.

NMTPreinit was a large improvement over the way things were. It has made little problems over the years, barring over-strict tests like this one (my own darn fault for writing them, ironically - untested code does not draw attention).

So I can add realloc back to NMTPreInit if required, after I consider this issue more and am unable to accommodate your useå cases.

What about the other change, where we move NMT initialization before we process the arguments, which makes the NMTPreInit table much smaller? Is that part OK?

I like the change to a Mersenne prime, that's a good idea.

But the initialization change not so much. It adds a lot of complexity and brittleness to NMT initialization, for not much benefit.

Right now, NMT initialization is simple. Because it is time-independent. All VM subsystems are already started, and we are in normal VM land. We can log, we can use Thread::current, we can use ostream, we can crash and have useful hs_err files... That was a big simplification that NMTPreInit brought.

With your patch, we are back at having two NMT initialization phases. And the early phase happens before UL or Thread::current() or ostream or reasonable hs_err file printing are available.

And we don't get that much for it. NMTInitializationTest.java is a very artificial test, not sure we should optimize for that. A normal debug VM started without arguments has 331 pre-init malloc calls. That drops to 47 with your patch. So, with arguments, I convert maybe 300..400 preinit mallocs to normal os::malloc calls.

I think instead our time would be well spent on tracking down those mallocs and removing them. IIRC A lot of that stuff comes from UL. And UL would benefit so much from simplification. It is so darn complex for a simple logging framework. I don't see why it needs to dynamically allocate at all before argument parsing, since it has no way of knowing yet what's what. I suspect whatever is generated there could just as well live as automatic variable, or inlined, or hard-coded as constants.

For this test, I think you could make the failure threshold much higher. When I originally wrote the test, I intended to weed out stupid problems like "oh, hashcode is constant", or "oh, we only use every 16th table bucket because of ptr alignment". But in this case, the hash distribution is not that bad.

@gerard-ziemski
Copy link
Author

OK, I will keep the hash table changes and revert anything else.

I'm not giving up on tackling NMTPreInit yet though, but instead of simplifying it, I will see if I can drop all of it, by turning NMT in summary mode ON instead (if I can figure out how to color memory pointers)

@gerard-ziemski
Copy link
Author

Removed anything even remotely controversial. We only change the heuristic function and tweak the hash table size to be 8191, i.e. Mersenne prime.

Thank you David and Thomas for your patience!

@gerard-ziemski
Copy link
Author

I'm going on vacation for a week this Monday, so if I get your OKs I will integrate after I come back, just in case this will affect anything and I need to be available...

Copy link
Member

@tstuefe tstuefe left a comment

Choose a reason for hiding this comment

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

Good!

@openjdk
Copy link

openjdk bot commented Jul 22, 2023

@gerard-ziemski This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8293972: runtime/NMT/NMTInitializationTest.java#default_long-off failed with "Suspiciously long bucket chains in lookup table."

Reviewed-by: stuefe, dholmes

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 33 new commits pushed to the master branch:

  • 0487aa6: 8312530: Problemlist runtime/os/TestTrimNative.java
  • 8d1ab57: 8301341: LinkedTransferQueue does not respect timeout for poll()
  • bfa76df: 8311978: Shenandoah: Create abstraction over heap metrics for heuristics
  • 3c644dc: 8312044: Simplify toolkit Builder/Writer world
  • f4ba7b2: 8312414: Make java.util.ServiceLoader.LANG_ACCESS final
  • d55d7e8: 8136895: Writer not closed with disk full error, file resource leaked
  • 8042a50: 8309305: sun/security/ssl/SSLSocketImpl/BlockedAsyncClose.java fails with jtreg test timeout
  • 84b325b: 8312182: THPs cause huge RSS due to thread start timing issue
  • 842d632: 8227229: Deprecate the launcher -Xdebug/-debug flags that have not done anything since Java 6
  • 9e4fc56: 8293114: JVM should trim the native heap
  • ... and 23 more: https://git.openjdk.org/jdk/compare/b5b6f4e7a77db4d13e19e186d3cd402cd7c626ea...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 22, 2023
Copy link
Member

@dholmes-ora dholmes-ora left a comment

Choose a reason for hiding this comment

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

I'm also fine with this very simple fix.

Thanks.

@gerard-ziemski
Copy link
Author

Thank you David and Thomas for the reviews!

@gerard-ziemski
Copy link
Author

/integrate

@openjdk
Copy link

openjdk bot commented Jul 31, 2023

Going to push as commit 78f6799.
Since your change was applied there have been 110 commits pushed to the master branch:

  • 97b6883: 8295059: test/langtools/tools/javap 12 test classes use com.sun.tools.classfile library
  • 3671d83: 8313252: Java_sun_awt_windows_ThemeReader_paintBackground release resources in early returns
  • b60e0ad: 8313207: Remove MetaspaceShared::_has_error_classes
  • 408987e: 8313307: java/util/Formatter/Padding.java fails on some Locales
  • 6fca289: 8313023: Return value corrupted when using CCS + isTrivial (mainline)
  • f8c2b7f: 8313231: Redundant if statement in ZoneInfoFile
  • 807ca2d: 8313316: Disable runtime/ErrorHandling/MachCodeFramesInErrorFile.java on ppc64le
  • ad34be1: 8312525: New test runtime/os/TestTrimNative.java#trimNative is failing: did not see the expected RSS reduction
  • d6245b6: 8310268: RISC-V: misaligned memory access in String.Compare intrinsic
  • 402cb6a: 8312201: Clean up common behavior in "page writers" and "member writers"
  • ... and 100 more: https://git.openjdk.org/jdk/compare/b5b6f4e7a77db4d13e19e186d3cd402cd7c626ea...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jul 31, 2023
@openjdk openjdk bot closed this Jul 31, 2023
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Jul 31, 2023
@openjdk
Copy link

openjdk bot commented Jul 31, 2023

@gerard-ziemski Pushed as commit 78f6799.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot-runtime hotspot-runtime-dev@openjdk.org integrated Pull request has been integrated
3 participants