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
8301007: [lworld] Handle mismatches of the preload attribute in the calling convention #834
Conversation
…eter returns for now
👋 Welcome back thartmann! A progress list of the required criteria for merging this PR into |
@TobiHartmann 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:
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 no new commits pushed to the ➡️ To integrate this PR with the above commit message to the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Runtime bits look good, thanks for the cleanups along the way
Thanks for the review, @MrSimms! |
/integrate |
@TobiHartmann Pushed as commit 6b0631c. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
[Don't be afraid by the ~4,700 LOC, it's mostly tests 😁]
C2 passes value class arguments in scalarized form if the calling convention if the resolved method supports this. This requires that the calling conventions of all overriding methods need to agree on which arguments are passed in scalarized form. Since the preload attribute added with JDK-8281116 does not guarantee any consistency between the overridden and overriding method, we need to handle mismatches at runtime. The same applies to returning value classes in scalarized form.
JDK-8301007 discusses several options for handling mismatches. Unfortunately, they are either very complex to implement (mismatch detection in the callee leading to deoptimization and re-execution in the caller) and/or have a significant impact on performance/footprint (global dictionary), sometimes even affecting methods not participating in the mismatch.
After several iterations of thinking and prototyping, I came up with the following solution.
Scalarized calls:
The calling convention is determined per method at link time. Mismatches can always be detected at that point by walking up the chain of overridden methods and checking if their calling conventions match for each argument with what we would like to set up for the to-be-linked method. In most of the cases, we can handle a mismatch by simply sticking to the calling convention that the super method uses. I.e., if the super method uses a non-scalarized calling convention because the argument was not yet loaded at link time due to a missing preload attribute, we don't scalarize that argument of the overriding method(s) either. In fact, a fallback to the non-scalarized calling convention is always sufficient because it can't happen that the argument type was loaded when the super method was linked and is not loaded now that an overriding method is linked.
However, this does not work in the following case of multiple inheritance where
MyValue
was not yet loaded whenI1::m
was linked but was loaded whenI2::m
was linked. Since the interfaces are completely independent, we scalarize the argument forI2::m
but not forI1::m
:Now once
C::m
is linked, we can't simply fall back to the non-scalarized calling convention because the method can still be called with a scalarized calling convention throughI2::m
. We mark such "offending" methods, in this case onlyI2::m
, in the overriding chain as mismatched, deoptimize all C2 compiled methods that include a scalarized call via that method and re-compile them by using the non-scalarized calling convention. To do that, we register an evol dependency when compiling a scalarized call site (viaC->dependencies()->assert_evol_method(call->method())
) and deoptimize all dependent nmethods viaCodeCache::flush_dependents_on_method
after mismatch detection.Scalarized returns:
Due to the lack of adapters on returns, value objects are always (from interpreter, C1 and C2) returned in scalarized form if the return type is a value class. Similar to scalarized calls, an issue occurs when overridden and overriding methods do not agree if the return value should be passed in scalarized form. For example, we might compile a call to a method with an unloaded return type. Later, the return type is loaded and the method (or an overriding method) returns a value in scalarized form that the previously compiled caller can't handle.
Since the interpreter always checks if a to-be-returned value or a value returned from a call is in scalarized form, we only need additional handling in C1 and C2. For C2, we replace the null assert, that is added after a call site with an unloaded return type, by a full-blown trap. This should have minimal impact and will be further improved (see remaining work section below). For C1, we need additional checks when returning an unloaded type and after invoking a method with an unloaded type. In both cases, the overhead is negligible because it boils down to a bit-check on a register to determine if we need to go to the slow path to handle a scalarized return.
Other changes:
StressCallingConvention
flag to stress test new code paths.Since this change became quite large, I'm postponing the following remaining work to JDK-8284443:
PhaseMacroExpand::expand_mh_intrinsic_return
logic.StressCallingConvention
inInterpreterMacroAssembler::remove_activation
, this still triggers some issues.Thanks,
Tobias
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/834/head:pull/834
$ git checkout pull/834
Update a local copy of the PR:
$ git checkout pull/834
$ git pull https://git.openjdk.org/valhalla.git pull/834/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 834
View PR using the GUI difftool:
$ git pr show -t 834
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/834.diff
Webrev
Link to Webrev Comment