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

8251462: Simplify compilation policy #1985

Closed
wants to merge 6 commits into from

Conversation

veresov
Copy link
Contributor

@veresov veresov commented Jan 7, 2021

This change removes the legacy compilation policy and an emulation mode to the tiered policy to simulate the old behavior with -XX:-TieredCompilation. The change removed a bunch of interpreter code, devirtualizes the compilation policy API, adds a consistent way to query compiler configuration with the new CompilerConfig API.

I've tested this with hs-tier{1,2,3,4,5}. And also made sure it builds and works with C1/C2-Graal/AOT being enabled/disabled.

Since there are platform-specific changes I would greatly appreciate some help from the maintainers of the specific ports to verify the build and run basic smoke tests. I've already tested x64 and aarch64. Thanks!


Progress

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

Issue

Reviewers

Download

$ git fetch https://git.openjdk.java.net/jdk pull/1985/head:pull/1985
$ git checkout pull/1985

@veresov veresov changed the title [8251462 Remove legacy compilation policy. 8251462: Remove legacy compilation policy. Jan 7, 2021
@veresov veresov marked this pull request as draft January 7, 2021 18:44
@bridgekeeper
Copy link

bridgekeeper bot commented Jan 7, 2021

👋 Welcome back iveresov! 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 7, 2021

@veresov The following labels will be automatically applied to this pull request:

  • hotspot
  • serviceability
  • shenandoah

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

@openjdk openjdk bot added serviceability serviceability-dev@openjdk.org hotspot hotspot-dev@openjdk.org shenandoah shenandoah-dev@openjdk.org labels Jan 7, 2021
@veresov veresov changed the title 8251462: Remove legacy compilation policy. 8251462: Remove legacy compilation policy Jan 7, 2021
@veresov
Copy link
Contributor Author

veresov commented Jan 7, 2021

/label hotspot-compiler

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.org label Jan 7, 2021
@openjdk
Copy link

openjdk bot commented Jan 7, 2021

@veresov
The hotspot-compiler label was successfully added.

@veresov veresov marked this pull request as ready for review January 7, 2021 20:32
@openjdk openjdk bot added the rfr Pull request is ready for review label Jan 7, 2021
@mlbridge
Copy link

mlbridge bot commented Jan 7, 2021

Webrevs

Comment on lines +33 to 35
* While running the thread, it calls a method (doTask2() ) for number of times (10000).
* That would cause this method to be compiled, which causes a jvmti callback for compiled method load.
* (Hint : to force method compilation -XX:CompileThreshold=900 is used).
Copy link
Contributor

Choose a reason for hiding this comment

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

The test still uses (and the comments state it uses) -XX:CompileThreshold=900 to force compilation, yet it looks like you needed to bump the number of times the method is called from 1000 to 10000 to keep this test working. Why doesn't 1000 still work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tiered policy (which the -TieredCompilation emulation mode piggybacks on now) functions by doing periodic callbacks into the runtime to make policy decisions. The callback intervals are a power-of-2. So, because of the resulting rounding I cannot guarantee that the compilation will be triggered exactly at the specified threshold. Plus there are various adaptive mechanisms that I kept on even in the emulation mode that may also result in a method being compiled later than expected. To summarize, in the new world, the advisable way of triggering a compilation is to use the WB API. If that's too much effort, make sure that the method that you'd like to compile is invoked more than 2^(log2(CompileThreshold) + 1) times, plus a bit more. Very few tests actually depend on the legacy behavior, this just happens to be one of those.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok.

Copy link
Contributor

@plummercj plummercj left a comment

Choose a reason for hiding this comment

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

Marking as reviewed, but only for the jvmti tests. I don't believe there are any other svc changes in this PR.

@openjdk
Copy link

openjdk bot commented Jan 7, 2021

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

8251462: Simplify compilation policy

Reviewed-by: cjplummer, kvn

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

  • 71128cf: 8260586: Shenandoah: simplify "Concurrent Weak References" logging
  • 81e9e6a: 8260461: Modernize jsr166 tck tests
  • 2b166d8: 8260596: Comment cleanup in BigInteger
  • 1de3c55: 8260584: Shenandoah: simplify "Concurrent Thread Roots" logging
  • bbbfaa5: 8249262: Initialize InstanceKlass::_package_entry during CDS dump time
  • 3aabbd7: 8260432: allocateSpaceForGP in freetypeScaler.c might leak memory
  • abc4300: 8257746: Regression introduced with JDK-8250984 - memory might be null in some machines
  • 13ca433: 8259628: jdk/net/ExtendedSocketOption/AsynchronousSocketChannelNAPITest.java fails intermittently
  • baf46ba: 8259801: Enable XML Signature secure validation mode by default
  • 20e7df5: 8260466: Test TestHeapDumpOnOutOfMemoryError.java needs multiple @test sections
  • ... and 21 more: https://git.openjdk.java.net/jdk/compare/311a0a91ba520fcd0e163548e2d051d873aef51a...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 Jan 7, 2021
@mlbridge
Copy link

mlbridge bot commented Jan 8, 2021

Mailing list message from David Holmes on shenandoah-dev:

Hi Igor,

On 8/01/2021 6:36 am, Igor Veresov wrote:

This change removes the legacy compilation policy and an emulation mode to the tiered policy to simulate the old behavior with ```-XX:-TieredCompilation```. The change removed a bunch of interpreter code, devirtualizes the compilation policy API, adds a consistent way to query compiler configuration with the new ```CompilerConfig``` API.

Can you clarify, for non-compiler folk, what all the alternative configs
actually mean now. I'm a bit confused by this definition:

define_pd_global(bool, TieredCompilation,
COMPILER1_PRESENT(true) NOT_COMPILER1(false));

as I expected tiered compilation to require COMPILER1 and COMPILER2.

Also I see interpreter code that used to be guarded by TieredCompilation
now being executed unconditionally, which seems to assume C1 or C2 must
be present?

Overall it is a big change to digest, but after skimming it looks like a
few of the refactorings could have been applied in a layered fashion
using multiple commits to make it easier to review.

Thanks,
David
-----

@veresov
Copy link
Contributor Author

veresov commented Jan 8, 2021

Please find the answers in-line.

Mailing list message from David Holmes on shenandoah-dev:

Hi Igor,

On 8/01/2021 6:36 am, Igor Veresov wrote:

This change removes the legacy compilation policy and an emulation mode to the tiered policy to simulate the old behavior with -XX:-TieredCompilation. The change removed a bunch of interpreter code, devirtualizes the compilation policy API, adds a consistent way to query compiler configuration with the new CompilerConfig API.

Can you clarify, for non-compiler folk, what all the alternative configs
actually mean now. I'm a bit confused by this definition:

define_pd_global(bool, TieredCompilation,
COMPILER1_PRESENT(true) NOT_COMPILER1(false));

That's in a c2_globals_*.hpp, which is only included if C2 is present. Given that, if C1 is present as well the flag is set to true.

as I expected tiered compilation to require COMPILER1 and COMPILER2.

Right. That's exactly what's happening.

Also I see interpreter code that used to be guarded by TieredCompilation
now being executed unconditionally, which seems to assume C1 or C2 must
be present?

Counters and compilation policy callbacks are historically guarded by UseCompiler and UseLoopCounter flags, which are set to false if there are no compilers present. I haven't changed the semantics.

Overall it is a big change to digest, but after skimming it looks like a
few of the refactorings could have been applied in a layered fashion
using multiple commits to make it easier to review.

Frankly, I don't know how to split it into smaller pieces. There are surprisingly lots of interdependencies. However, the best way to think about it is that there are three major parts: 1. CompilerConfig API that is an abstraction over compiler configuration (what's compiled in, what flags are present that restrict compiler usage, etc); 2. The legacy policy removal. 3. Emulation of the old JVM behavior.

As far as the runtime part of the change is concerted, it's pretty much only the legacy policy removal. In particular, the parts of the interpreter that dealt with the old policy (basically everything in the interpreter that was under !TieredCompilation has gotten removed).

Igor

Thanks,
David

@veresov
Copy link
Contributor Author

veresov commented Jan 8, 2021

To clarify the possible configs.

  1. There is only one policy now. Functions with both compilers or a single compiler.
  2. The best way to control the operation mode is with the -XX:CompilationMode= flag. Possible values so far are: normal (aka default), high-only (c2 or graal only), quick-only(c1 only), high-only-quick-internal (a special mode for jar graal where only graal itself is compiled by c1, but the user code is compiled with graal).
  3. There is a mode that emulates the behavior when the user specifies -TieredCompilation. That's basically the high-only mode.
  4. There is also support for legacy policy flags such as CompileThreshold, which would properly setup the policy parameters to match the old behavior.

@mlbridge
Copy link

mlbridge bot commented Jan 11, 2021

Mailing list message from David Holmes on shenandoah-dev:

On 8/01/2021 4:09 pm, Igor Veresov wrote:

On Thu, 7 Jan 2021 21:49:56 GMT, Chris Plummer <cjplummer at openjdk.org> wrote:

Igor Veresov has updated the pull request incrementally with one additional commit since the last revision:

Fix s390 build

Marking as reviewed, but only for the jvmti tests. I don't believe there are any other svc changes in this PR.

Please find the answers in-line.

_Mailing list message from [David Holmes](mailto:david.holmes at oracle.com) on [shenandoah-dev](mailto:shenandoah-dev at openjdk.java.net):_

Hi Igor,

On 8/01/2021 6:36 am, Igor Veresov wrote:

This change removes the legacy compilation policy and an emulation mode to the tiered policy to simulate the old behavior with ```-XX:-TieredCompilation```. The change removed a bunch of interpreter code, devirtualizes the compilation policy API, adds a consistent way to query compiler configuration with the new ```CompilerConfig``` API.

Can you clarify, for non-compiler folk, what all the alternative configs
actually mean now. I'm a bit confused by this definition:

define_pd_global(bool, TieredCompilation,
COMPILER1_PRESENT(true) NOT_COMPILER1(false));

That's in a c2_globals_*.hpp, which is only included if C2 is present. Given that, if C1 is present as well the flag is set to true.

Sorry I overlooked the exact placement.

as I expected tiered compilation to require COMPILER1 and COMPILER2.

Right. That's exactly what's happening.

Also I see interpreter code that used to be guarded by TieredCompilation
now being executed unconditionally, which seems to assume C1 or C2 must
be present?

Counters and compilation policy callbacks are historically guarded by UseCompiler and UseLoopCounter flags, which are set to false if there are no compilers present. I haven't changed the semantics.

That is not at all obvious. For example in
templateInterpreterGenerator_aarch64.cpp this code used to guarded by
TieredCompilation:

608: __ bind(no_mdo);
// Increment counter in MethodCounters
const Address invocation_counter(rscratch2,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rmethod, rscratch2, done);
const Address mask(rscratch2,
in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rscratch1, r1, false, Assembler::EQ, overflow);
__ bind(done);

but now it seems to be executed unconditionally with no reference to
either flag you mentioned.

Overall it is a big change to digest, but after skimming it looks like a
few of the refactorings could have been applied in a layered fashion
using multiple commits to make it easier to review.

Frankly, I don't know how to split it into smaller pieces. There are surprisingly lots of interdependencies. However, the best way to think about it is that there are three major parts: 1. CompilerConfig API that is an abstraction over compiler configuration (what's compiled in, what flags are present that restrict compiler usage, etc); 2. The legacy policy removal. 3. Emulation of the old JVM behavior.

I was thinking the ifdef related changes as one commit; then the
TieredCompilation removals; then the addition of CompilerConfig API ...

These aren't separate changes just different commits within the PR so
that it can be reviewed in stages.

Cheers,
David
-----

@veresov
Copy link
Contributor Author

veresov commented Jan 11, 2021

Dave, I'm answering inline.

Mailing list message from David Holmes on shenandoah-dev:

On 8/01/2021 4:09 pm, Igor Veresov wrote:

On Thu, 7 Jan 2021 21:49:56 GMT, Chris Plummer wrote:

Igor Veresov has updated the pull request incrementally with one additional commit since the last revision:
Fix s390 build

Marking as reviewed, but only for the jvmti tests. I don't believe there are any other svc changes in this PR.

Please find the answers in-line.

Mailing list message from [David Holmes](mailto:david.holmes at oracle.com) on [shenandoah-dev](mailto:shenandoah-dev at openjdk.java.net):
Hi Igor,
On 8/01/2021 6:36 am, Igor Veresov wrote:

This change removes the legacy compilation policy and an emulation mode to the tiered policy to simulate the old behavior with -XX:-TieredCompilation. The change removed a bunch of interpreter code, devirtualizes the compilation policy API, adds a consistent way to query compiler configuration with the new CompilerConfig API.

Can you clarify, for non-compiler folk, what all the alternative configs
actually mean now. I'm a bit confused by this definition:
define_pd_global(bool, TieredCompilation,
COMPILER1_PRESENT(true) NOT_COMPILER1(false));

That's in a c2_globals_*.hpp, which is only included if C2 is present. Given that, if C1 is present as well the flag is set to true.

Sorry I overlooked the exact placement.

as I expected tiered compilation to require COMPILER1 and COMPILER2.

Right. That's exactly what's happening.

Also I see interpreter code that used to be guarded by TieredCompilation
now being executed unconditionally, which seems to assume C1 or C2 must
be present?

Counters and compilation policy callbacks are historically guarded by UseCompiler and UseLoopCounter flags, which are set to false if there are no compilers present. I haven't changed the semantics.

That is not at all obvious. For example in
templateInterpreterGenerator_aarch64.cpp this code used to guarded by
TieredCompilation:

608: __ bind(no_mdo);
// Increment counter in MethodCounters
const Address invocation_counter(rscratch2,
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rmethod, rscratch2, done);
const Address mask(rscratch2,
in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rscratch1, r1, false, Assembler::EQ, overflow);
__ bind(done);

This code is in generate_counter_incr() each call to which is guarded by if (inc_counter), and inc_counter is defined as bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;. Again, I haven't changed that at all, that how it always worked. We may try to tidy this up but I feel like this change is big enough already.

but now it seems to be executed unconditionally with no reference to
either flag you mentioned.

Overall it is a big change to digest, but after skimming it looks like a
few of the refactorings could have been applied in a layered fashion
using multiple commits to make it easier to review.

Frankly, I don't know how to split it into smaller pieces. There are surprisingly lots of interdependencies. However, the best way to think about it is that there are three major parts: 1. CompilerConfig API that is an abstraction over compiler configuration (what's compiled in, what flags are present that restrict compiler usage, etc); 2. The legacy policy removal. 3. Emulation of the old JVM behavior.

I was thinking the ifdef related changes as one commit; then the
TieredCompilation removals; then the addition of CompilerConfig API ...

These aren't separate changes just different commits within the PR so
that it can be reviewed in stages.

I could've done that, I guess, but I usually like to make my checkpoints compilable. Sorry.

Cheers,
David

__ cmp_32(Ricnt, R1_tmp);
__ b(*overflow, hs);
__ bind(done);
int increment = InvocationCounter::count_increment;
Copy link
Contributor

Choose a reason for hiding this comment

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

The small code below seems not to be equivalent replacement for the above code. I would appreciate some explanation on why we change the things. Thanks.

Copy link
Contributor Author

@veresov veresov Jan 11, 2021

Choose a reason for hiding this comment

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

The code that is currently there should be exactly the code that was guarded by if (TieredCompilation) before. The else part (corresponding to !TieredCompilation is what's gotten removed. Since the new policy is based off of tiered we don't need the old style of callbacks. Is there something else that you've noticed?

@bulasevich
Copy link
Contributor

I see some regression on ARM32 with this change:
http://cr.openjdk.java.net/~bulasevich/tmp/8251462_jtreg_hotspot/

@veresov
Copy link
Contributor Author

veresov commented Jan 11, 2021

I see some regression on ARM32 with this change:
http://cr.openjdk.java.net/~bulasevich/tmp/8251462_jtreg_hotspot/

I don't think those are related to the changes. Those are probably some preexisting c1 and c2 problems respectively that for some reason weren't triggered before.

The TestOptionsWithRanges is my fault though. I'll fix that.

@veresov
Copy link
Contributor Author

veresov commented Jan 12, 2021

I've added the flag validity pre-checks, which should solve the issues with VM complaining about tiered flags being invalid as a result of CompileThreshold and friends being invalid. We'd have to solve the C1 SIGILL and the C2 loop opts crash separately. Those are not really related to the change.

@bulasevich
Copy link
Contributor

Ok. I will see what is wrong there.

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.

I would also suggest to do performance runs. Ask Eric for help. Changes are significant and may affect performance due to some typo.

src/hotspot/share/compiler/compilerDefinitions.hpp Outdated Show resolved Hide resolved
src/hotspot/share/compiler/compilerDefinitions.hpp Outdated Show resolved Hide resolved
src/hotspot/share/compiler/compilerDefinitions.hpp Outdated Show resolved Hide resolved
src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp Outdated Show resolved Hide resolved
src/hotspot/share/runtime/vmStructs.cpp Show resolved Hide resolved
src/hotspot/share/jvmci/vmStructs_jvmci.cpp Show resolved Hide resolved
test/hotspot/jtreg/TEST.quick-groups Show resolved Hide resolved
src/hotspot/share/compiler/compilerDefinitions.cpp Outdated Show resolved Hide resolved
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.

Looks better now. I would like to see result of performance testing before approving.

@veresov
Copy link
Contributor Author

veresov commented Jan 25, 2021

I asked Eric to run the benchmarks. The results should be ready on Wednesday.

@veresov
Copy link
Contributor Author

veresov commented Jan 27, 2021

The benchmarking is done. No regressions. There are mild improvements in startup benchmarks on the order of 1-5% (I suspect because of the compilation policy devirtualization).

@dholmes-ora, do still plan to look at this? It's been a few weeks, I'd like to push this.

@shipilev
Copy link
Member

Please update from current master to get x86_32 built and tested in GH Actions.

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.

I approve it based on performance results.

@mlbridge
Copy link

mlbridge bot commented Jan 28, 2021

Mailing list message from David Holmes on shenandoah-dev:

Hi Igor,

On 28/01/2021 2:46 am, Igor Veresov wrote:

On Mon, 25 Jan 2021 18:13:20 GMT, Igor Veresov <iveresov at openjdk.org> wrote:

Looks better now. I would like to see result of performance testing before approving.

I asked Eric to run the benchmarks. The results should be ready on Wednesday.

The benchmarking is done. No regressions. There are mild improvements in startup benchmarks on the order of 1-5% (I suspect because of the compilation policy devirtualization).

@dholmes-ora, do still plan to look at this? It's been a few weeks, I'd like to push this.

No I only perused this and made a couple of comments, now addressed.

I'll leave a full review to others.

Thanks,
David

@veresov veresov changed the title 8251462: Remove legacy compilation policy 8251462: Simplify compilation policy Jan 28, 2021
@veresov
Copy link
Contributor Author

veresov commented Jan 28, 2021

/integrate

@openjdk openjdk bot closed this Jan 28, 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 Jan 28, 2021
@openjdk
Copy link

openjdk bot commented Jan 28, 2021

@veresov Since your change was applied there have been 31 commits pushed to the master branch:

  • 71128cf: 8260586: Shenandoah: simplify "Concurrent Weak References" logging
  • 81e9e6a: 8260461: Modernize jsr166 tck tests
  • 2b166d8: 8260596: Comment cleanup in BigInteger
  • 1de3c55: 8260584: Shenandoah: simplify "Concurrent Thread Roots" logging
  • bbbfaa5: 8249262: Initialize InstanceKlass::_package_entry during CDS dump time
  • 3aabbd7: 8260432: allocateSpaceForGP in freetypeScaler.c might leak memory
  • abc4300: 8257746: Regression introduced with JDK-8250984 - memory might be null in some machines
  • 13ca433: 8259628: jdk/net/ExtendedSocketOption/AsynchronousSocketChannelNAPITest.java fails intermittently
  • baf46ba: 8259801: Enable XML Signature secure validation mode by default
  • 20e7df5: 8260466: Test TestHeapDumpOnOutOfMemoryError.java needs multiple @test sections
  • ... and 21 more: https://git.openjdk.java.net/jdk/compare/311a0a91ba520fcd0e163548e2d051d873aef51a...master

Your commit was automatically rebased without conflicts.

Pushed as commit 1519632.

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