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

8259609: C2: optimize long range checks in long counted loops #2045

Closed
wants to merge 24 commits into from

Conversation

rwestrel
Copy link
Contributor

@rwestrel rwestrel commented Jan 12, 2021

JDK-8255150 makes it possible for java code to explicitly perform a
range check on long values. JDK-8223051 provides a transformation of
long counted loops into loop nests with an inner int counted
loop. With this change I propose transforming long range checks that
operate on the iv of a long counted loop into range checks that
operate on the iv of the int inner loop once it has been
created. Existing range check eliminations can then kick in.

Transformation of range checks is piggy backed on the loop nest
creation for 2 reasons:

  • pattern matching range checks is easier right before the loop nest
    is created

  • the number of iterations of the inner loop is adjusted so scale *
    inner_iv doesn't overflow

C2 has logic to delay some split if transformations so they don't
break the scale * iv + offset pattern. I reused that logic for long
range checks and had to relax what's considered a range check because
initially a range check from Object.checkIndex() may include a test
for range > 0 that needs a round of loop opts to be hoisted. I realize
there's some code duplication but I didn't see a way to share logic
between IdealLoopTree::may_have_range_check()
IdealLoopTree::policy_range_check() that would feel right.

I realize the comment in PhaseIdealLoop::transform_long_range_checks()
is scary. FWIW, it's not as complicated as it looks. I found drawing
the range covered by the entire long loop and the range covered by the
inner loop help see how range checks can be transformed. Then the
comment helps make sure all cases are covered and verify the generated
code actually covers all of them.

One issue is overflow. I think the fact that inner_iv * scale doesn't
overflow helps simplify thing. One possible overflow is that of scale

  • upper + offset which is handled by forcing all range checks in that
    case to deoptimize. I don't think other case of overflow needs special
    handling.

This was tested with a Memory Segment micro benchmark (and patched
Memory Segment support to take advantage of the new checkIndex
intrinsic, both provided by Maurizio). Range checks in the micro
benchmark are properly optimized (and performance increases
significantly).


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8259609: C2: optimize long range checks in long counted loops

Reviewers

Contributors

  • John R Rose <jrose@openjdk.org>

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/2045/head:pull/2045
$ git checkout pull/2045

Update a local copy of the PR:
$ git checkout pull/2045
$ git pull https://git.openjdk.java.net/jdk pull/2045/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 2045

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

Using diff file

Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/2045.diff

@bridgekeeper
Copy link

bridgekeeper bot commented Jan 12, 2021

👋 Welcome back roland! 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 Jan 12, 2021

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

  • hotspot-compiler

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-compiler hotspot-compiler-dev@openjdk.org label Jan 12, 2021
@openjdk openjdk bot added the rfr Pull request is ready for review label Jan 12, 2021
@mlbridge
Copy link

mlbridge bot commented Jan 12, 2021

@TobiHartmann
Copy link
Member

Hi Roland,

I haven't looked at the code in detail yet but submitted some quick testing. Unfortunately, there are failures with an internal test that I'm unable to share. Some details:

#  Internal Error (src/hotspot/share/utilities/globalDefinitions.hpp:460), pid=27250, tid=27265
#  assert(static_cast<T1>(result) == thing) failed: must be
Stack: [0x00007fca9cdfa000,0x00007fca9cefb000],  sp=0x00007fca9cef5360,  free space=1004k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x12f5a3e]  IdealLoopTree::policy_range_check(PhaseIdealLoop*) const [clone .part.0]+0x33e
V  [libjvm.so+0x1301e4f]  IdealLoopTree::iteration_split_impl(PhaseIdealLoop*, Node_List&) [clone .part.0]+0x6ef
V  [libjvm.so+0x13021bb]  IdealLoopTree::iteration_split(PhaseIdealLoop*, Node_List&)+0x13b
V  [libjvm.so+0x13020b5]  IdealLoopTree::iteration_split(PhaseIdealLoop*, Node_List&)+0x35
V  [libjvm.so+0x1330633]  PhaseIdealLoop::build_and_optimize(LoopOptsMode)+0xc83
V  [libjvm.so+0xa1cbdb]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x32b
V  [libjvm.so+0xa18636]  Compile::Optimize()+0x586
V  [libjvm.so+0xa1b370]  Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, bool, DirectiveSet*)+0x1840
V  [libjvm.so+0x84b1bc]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x1dc
V  [libjvm.so+0xa2b3a8]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xe88
V  [libjvm.so+0xa2bff8]  CompileBroker::compiler_thread_loop()+0x5a8
V  [libjvm.so+0x18b06c6]  JavaThread::thread_main_inner()+0x256
V  [libjvm.so+0x18b70d0]  Thread::call_run()+0x100
V  [libjvm.so+0x1599dd6]  thread_native_entry(Thread*)+0x116

Hope that helps.

@rwestrel
Copy link
Contributor Author

I haven't looked at the code in detail yet but submitted some quick testing. Unfortunately, there are failures with an internal test that I'm unable to share. Some details:

Thanks. I pushed a fix.

@TobiHartmann
Copy link
Member

I think you forgot to push the fix.

@rwestrel
Copy link
Contributor Author

I think you forgot to push the fix.

Indeed. Pushed now.

@TobiHartmann
Copy link
Member

I'm now seeing this with the same test at a higher tier (and therefore different flags):

#  Internal Error (workspace/open/src/hotspot/share/opto/loopPredicate.cpp:1154), pid=8709, tid=8726
#  assert(ok) failed: must be index expression

Stack: [0x00007f2f3bdfe000,0x00007f2f3beff000],  sp=0x00007f2f3bef8fd0,  free space=1003k
Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x129032b]  PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree*, ProjNode*, ProjNode*, CountedLoopNode*, ConNode*, Invariance&, Deoptimization::DeoptReason)+0x74b
V  [libjvm.so+0x1291e0b]  PhaseIdealLoop::loop_predication_impl(IdealLoopTree*) [clone .part.0]+0x81b
V  [libjvm.so+0x1292d09]  IdealLoopTree::loop_predication(PhaseIdealLoop*)+0x109
V  [libjvm.so+0x1292c28]  IdealLoopTree::loop_predication(PhaseIdealLoop*)+0x28
V  [libjvm.so+0x12dd182]  PhaseIdealLoop::build_and_optimize(LoopOptsMode)+0x1282
V  [libjvm.so+0xa1bfbb]  PhaseIdealLoop::optimize(PhaseIterGVN&, LoopOptsMode)+0x32b
V  [libjvm.so+0xa182a6]  Compile::Optimize()+0x586
V  [libjvm.so+0xa1af60]  Compile::Compile(ciEnv*, ciMethod*, int, bool, bool, bool, bool, DirectiveSet*)+0x1840
V  [libjvm.so+0x84a6bc]  C2Compiler::compile_method(ciEnv*, ciMethod*, int, bool, DirectiveSet*)+0x1dc
V  [libjvm.so+0xa2afd8]  CompileBroker::invoke_compiler_on_method(CompileTask*)+0xe88
V  [libjvm.so+0xa2bc28]  CompileBroker::compiler_thread_loop()+0x5a8
V  [libjvm.so+0x1856b66]  JavaThread::thread_main_inner()+0x256
V  [libjvm.so+0x185d570]  Thread::call_run()+0x100
V  [libjvm.so+0x1543f46]  thread_native_entry(Thread*)+0x116

@rwestrel
Copy link
Contributor Author

I'm now seeing this with the same test at a higher tier (and therefore different flags):

Fixed and added a test case that covers this issue

Copy link
Member

@TobiHartmann TobiHartmann left a comment

Choose a reason for hiding this comment

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

I did a first pass over the changes and added some comments but I need more time to review.

bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const {
bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, BasicType bt, Node *iv, Node *&range,
Node *&offset,
jlong &scale) const {
Copy link
Member

Choose a reason for hiding this comment

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

Newline should be removed.

return false;
}
if (offset && !invar.is_invariant(offset)) { // offset must be invariant
return false;
}
return true;
}
return false;
}
Copy link
Member

Choose a reason for hiding this comment

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

Code is hard to read because the indentation of above lines is broken. Some * could also be moved to the type.

if (p_offset != NULL) {
if (*p_scale == min_signed_integer(bt)) {
return false;
Copy link
Member

Choose a reason for hiding this comment

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

I find it suspicious that this edge case needs to be handled here. Could you explain why and add a corresponding comment?

Copy link
Member

Choose a reason for hiding this comment

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

Looks like you forgot to address this comment?

}
// Because RCE opportunities can be masked by split_thru_phi,
// look for RCE candidates and inhibit split_thru_phi
// on just their loop-phi's for this pass of loop opts
if (SplitIfBlocks && do_split_ifs) {
AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
if (lpt->policy_range_check(this)) {
if (lpt->may_have_range_check(this)) {
Copy link
Member

Choose a reason for hiding this comment

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

Can be merged with above if.

RangeCheckNode* rc = c->in(0)->as_RangeCheck();
if (loop->is_range_check_if(rc, this, T_LONG, phi, range, offset, scale) &&
loop->is_invariant(range) && loop->is_invariant(offset)) {
if (iters_limit_as_long / ABS(scale * stride_con) > min_iters/* && UseNewCode*/) {
Copy link
Member

Choose a reason for hiding this comment

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

UseNewCode should be removed and if should be merged with if above.

@rwestrel
Copy link
Contributor Author

@TobiHartmann thanks for the comments. I pushed a change that should address them.

@rose00
Copy link
Contributor

rose00 commented Feb 1, 2021

Partial review:
Yes, good cleanups along with great new functionality for big data! I
like the refactorings which use the new generic factory methods from
JDK-8255150.

The comment in PhaseIdealLoop::transform_long_range_checks is very
good.

PhaseTransform::integercon has a bug left over from JDK-8256655,
the cast in assert(((long)int_con) == l, "not an int") is wrong.
Just use intcon(checked_cast<jint>(l)) as you already do elsewhere.

(I also noticed also that PhaseIdealLoop::exact_limit and
LoopLimitNode::value have similar asserts which could be replaced
with checked_cast. In fact, PhaseIdealLoop::exact_limit is a
duplicated from LoopLimitNode::value just to avoid creating a node,
yuck. That fiddly stuff should have been written as few times as
possible. I suggest putting it into a static inline in the class
LoopLimitNode, where it will also serve as documentation.)

typo: /had a change to be hoisted yet/s/change/chance/

Also there are unusually long comment lines there and inside
transform_long_range_checks. 130 columns plus is longer than my
widest laptop window holds unless I aggravate my presbyopia with
a smaller font size. Maybe, consider reflowing? I know some
of those lines are intrinsically long.

This variable is unused: Node* long_stride = head->stride();

The argument signed_int is unused in MulNode::operates_on.

Well done adapting is_scaled_iv and friends to T_LONG!

The logic for turning a shift amount into a scale factor looks
flawed, at least if shift_amount is ever out of range for the
corresponding basic type. I suggest being safe rather than
sorry: shift_amount &= (bt == T_INT ? 31 : 63); //clip
(There are about 3 possible bugs with out-of-range shifts.)
Even better: Use both overloadings of java_shift_left
from globalDefinitions.hpp; I think that would be the
best practice.

I realize
there's some code duplication but I didn't see a way to share logic
between IdealLoopTree::may_have_range_check()
IdealLoopTree::policy_range_check() that would feel right.

I did a direct diff -w of the two function bodies and they are
so similar that I think it is better to maintain them as one copy
of the code. I suggest adding a boolean flag provisional
that activates the changed bits of logic:

bool IdealLoopTree::policy_range_check(PhaseIdealLoop *phase, bool provisional = false) const {
+ if (_head->is_CountedLoop()) {
    CountedLoopNode *cl = _head->as_CountedLoop();
    ...existing stuff about unroll_only etc...
+ }
+ BaseCountedLoopNode *cl = _head->as_BaseCountedLoop();
  Node *trip_counter = cl->phi();
+ BasicType bt = cl->bt();
  for (...) {
      ...
      Node *cmp = bol->in(1);
      Node *rc_exp = cmp->in(1);
      Node *limit = cmp->in(2);
+     if (provisional) {
+       // Try to pattern match with either cmp inputs, do not check whether one of the
+       // inputs is loop independent as it may not have had a chance to be hoisted yet.
+       if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL, bt) &&
+           !phase->is_scaled_iv_plus_offset(limit,  trip_counter, NULL, NULL, bt)) {
        continue;
+     } else {  // check loop independence if non-provisional
         Node *limit_c = phase->get_ctrl(limit);
         ...existing checks & swap of rc_exp and limit...
         if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL)) {
           continue;
         }
+     }
      if (is_loop_exit(iff)) {
        // Found valid reason to split iterations (if there is room).
        // NOTE: Usually a gross overestimate.
        return provisional || phase->may_require_nodes(est_loop_clone_sz(2));
      }
  }
}

Now for the biggest part: You are replacing long range checks with
32-bit range checks which then can be RCE-ed. You dial back the
strip-mining count as needed to make sure the various scaled index
computations don't suffer overflow. Very clever!

I suggest placing extract_long_range_checks before
transform_long_range_checks because that's the order they are
executed. That way the two can be read more easily in sequence.

The variable jlong stride_con should be int. It is never used
for anything bigger, or else an assert would fire.

IMO the expression scale > 0 != stride_con > 0 needs parens around
each of the two comparisons. This is a case of relying on obscure
C language precedence rules. (I had to look it up myself!)

This group of definitions is loop-invariant, and should probably
be set up once outside of the for-loop:

// Compute lower and upper
Node* last = new LoopLimitNode(C, int_zero, inner_iters_actual_int, int_stride);
register_new_node(last, entry_control);
last = new SubINode(last, int_stride);
register_new_node(last, entry_control);

Node* lower = outer_phi;
Node* upper = new ConvI2LNode(last);
register_new_node(upper, entry_control);
upper = new AddLNode(lower, upper);
register_new_node(upper, entry_control);

In new AddLNode(upper, long_one), I think long_one should
have the same sign as the stride. But I'm not sure (yet).

You have an expression for accumulating the maximum scale:
max_scale = MAX2(max_scale, scale). I think that the
accumulated value should not be negative, so you probably
want max_scale = MAX2(max_scale, ABS(scale)).

But, I suggest getting rid of max_scale altogether.
The logic will be simpler if it works like this:

jlong original_iters_limit = iters_limit;
jlong reduced_iters_limit = iters_limit;
for (...) {
  ... jlong new_limit = original_iters_limit / ABS(scale * stride_con)
  if (new_limit >= min_iters) { // ??? or > ???
    reduced_iters_limit = MIN2(reduced_iters_limit, new_limit);
    range_checks.push(c);

  }
}
return checked_cast<int>(reduced_iters_limit);

If you do this you won't need that delicate assert at the end.

More later. I'm still working through the core logic in
transform_long_range_checks, and I will propose more changes
there.

@bridgekeeper
Copy link

bridgekeeper bot commented Mar 1, 2021

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@rwestrel
Copy link
Contributor Author

rwestrel commented Mar 4, 2021

comment to keep the PR open

@bridgekeeper
Copy link

bridgekeeper bot commented Apr 21, 2021

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@rwestrel
Copy link
Contributor Author

comment to keep the PR open

@bridgekeeper
Copy link

bridgekeeper bot commented May 25, 2021

@rwestrel This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration!

@rwestrel
Copy link
Contributor Author

rwestrel commented Jun 1, 2021

comment to keep the PR open

@rwestrel
Copy link
Contributor Author

I wonder if this would be a good direction, and if I can help somehow?

Do I understand right that you're suggesting modifying c2 so it handles long range checks with the existing range check optimizations (rc_predicate etc.)? The approach this PR has taken is to convert long range checks into int range checks so existing range check optimizations work as is. Ignoring the merit of either approach, what you're suggesting, if I understand right, is different so it can't help this particular PR.
If you get what you're suggesting working then I expect you'll hit the same roadblock that this PR hits: someone will have to validate the logic before it integrates. FWIW, John and I both spent quite a bit on time on this. John has validated most of the logic and I updated the PR according to his latest comments. It's unfortunate it's taking that much time, but I doubt going a different road makes a lot of sense at this point.

@rsmogura
Copy link
Contributor

More or less I thought with constrain dist(lower_bound , upper_bound) < Long.MAX it should not create a case that we will read pass the range and preconditions will be satisfied (if two bounds will overflow long and be in range, and because scale & offset are loop invariant it means it's by developer's design).

In any way I didn't want to interfere, and I hope it will be finished soon.

Copy link
Contributor

@rose00 rose00 left a comment

Choose a reason for hiding this comment

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

No more comments from me. Ship it!

@openjdk
Copy link

openjdk bot commented Oct 20, 2021

@rwestrel 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:

8259609: C2: optimize long range checks in long counted loops

Co-authored-by: John R Rose <jrose@openjdk.org>
Reviewed-by: thartmann, jrose

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 114 new commits pushed to the master branch:

  • 7ca053d: 8251904: vmTestbase/nsk/sysdict/vm/stress/btree/btree010/btree010.java fails with ClassNotFoundException: nsk.sysdict.share.BTree0LLRLRLRRLR
  • 4be88d5: 8275047: Optimize existing fill stubs for AVX-512 target
  • 63e0f34: 8275767: JDK source code contains redundant boolean operations in jdk.charsets
  • 4961373: 8275137: jdk.unsupported/sun.reflect.ReflectionFactory.readObjectNoDataForSerialization uses wrong signature
  • 174f553: 8275869: Problem list applications/jcstress/copy.java on Linux-aarch64
  • 3ff085e: 8275582: Don't purge metaspace mapping lists
  • 10e1610: 8251134: Unwrapping a key with a Private Key generated by Microsoft CNG fails
  • 4361945: 8185844: MSCAPI doesn't list aliases correctly
  • 337a9b7: 8269853: Prefetch::read should accept pointer to const
  • 97d3280: 8275536: Add test to check that File::lastModified returns same time stamp as Files.getLastModifiedTime
  • ... and 104 more: https://git.openjdk.java.net/jdk/compare/947d52c4c3deec1bdea43959c200201c614ae114...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 Oct 20, 2021
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Oct 20, 2021
@openjdk openjdk bot added ready Pull request is ready to be integrated rfr Pull request is ready for review labels Oct 21, 2021
Copy link
Member

@TobiHartmann TobiHartmann 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 to me overall but I did not verify the transform_long_range_checks logic in detail.

I gave this a good amount of testing in our infra (tier 1-6). All green.

if (p_offset != NULL) {
if (*p_scale == min_signed_integer(bt)) {
return false;
Copy link
Member

Choose a reason for hiding this comment

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

Looks like you forgot to address this comment?

@@ -1633,6 +1654,8 @@ class PhaseIdealLoop : public PhaseTransform {

void try_sink_out_of_loop(Node* n);

Node* clamp(Node* pNode, Node* pNode1, Node* pNode2);
Copy link
Member

Choose a reason for hiding this comment

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

Argument naming is not consistent with the implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll fix the argument names.
-min_jint is min_jint. So there's no way to handle a min_jint (or min_jlong) scale above. How else would you handle it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I pushed a commit that addresses both comments.

@rwestrel
Copy link
Contributor Author

/contributor add jrose

@openjdk
Copy link

openjdk bot commented Oct 26, 2021

@rwestrel
Contributor John R Rose <jrose@openjdk.org> successfully added.

Copy link
Member

@TobiHartmann TobiHartmann left a comment

Choose a reason for hiding this comment

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

Thanks, that looks good to me.

@rwestrel
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Oct 26, 2021

Going to push as commit 82f4aac.
Since your change was applied there have been 119 commits pushed to the master branch:

  • 574f890: 8275720: CommonComponentAccessibility.createWithParent isWrapped causes mem leak
  • 7c88a59: 8275809: crash in [CommonComponentAccessibility getCAccessible:withEnv:]
  • c9dec2f: 8273299: Unnecessary Vector usage in java.security.jgss
  • b98ed55: 8275819: [TableRowAccessibility accessibilityChildren] method is ineffective
  • 71d593e: 8275162: Use varargs in 'def' macros in mutexLocker.cpp
  • 7ca053d: 8251904: vmTestbase/nsk/sysdict/vm/stress/btree/btree010/btree010.java fails with ClassNotFoundException: nsk.sysdict.share.BTree0LLRLRLRRLR
  • 4be88d5: 8275047: Optimize existing fill stubs for AVX-512 target
  • 63e0f34: 8275767: JDK source code contains redundant boolean operations in jdk.charsets
  • 4961373: 8275137: jdk.unsupported/sun.reflect.ReflectionFactory.readObjectNoDataForSerialization uses wrong signature
  • 174f553: 8275869: Problem list applications/jcstress/copy.java on Linux-aarch64
  • ... and 109 more: https://git.openjdk.java.net/jdk/compare/947d52c4c3deec1bdea43959c200201c614ae114...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot closed this Oct 26, 2021
@openjdk openjdk bot added integrated Pull request has been integrated and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Oct 26, 2021
@openjdk
Copy link

openjdk bot commented Oct 26, 2021

@rwestrel Pushed as commit 82f4aac.

💡 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-compiler hotspot-compiler-dev@openjdk.org integrated Pull request has been integrated
4 participants