-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
8289925: Shared code shouldn't reference the platform specific method frame::interpreter_frame_last_sp() #9411
Conversation
👋 Welcome back rrich! A progress list of the required criteria for merging this PR into |
/label hotspot-compiler |
@reinrich |
Webrevs
|
Ping? The change is tiny. |
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.
Looks good.
@reinrich 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 |
That was prompt, thanks a lot! :) |
Are you sure unextended_sp() returns the same thing as interpreter_frame_last_sp() on all platforms? I didn't think that was true for aarch64. Maybe what we need is a new shared API that will return what the continuation code expects, or promote interpreter_frame_last_sp() to be shared. It seems that all platforms implement it. |
Hi Dean, thanks for looking at the PR.
I'm no sure. The question is difficult to answer because it is a platform detail. It is even hard to make assumptions about the unextended_sp that are true for This was a major issue in the loom port to ppc. Shared code expects to find call IMHO uses of unextended_sp in shared code should be replaced with abstractions
I'd think any address within the frame is good for calling Thanks, Richard. [1] On ppc unextended_sp < sp is possible. |
Indeed. AArch64 makes a strong distinction between the machine SP and the interpreter's expression SP, and much of the difficulty with that port was because it was difficult to tell which was which in shared and x86 code. I wouldn't be able to guarantee that using unextended_sp() was always safe. |
Given the fact that Continuation::is_frame_in_continuation() uses f.unextended_sp(), and it is called for interpreted frames, I would tentatively agree, but let's see what @pron says. |
Looking at this some more, if unextended_sp < sp is possible and unextended_sp can actually point outside the current frame and into the next frame (according to continuationFreezeThaw_ppc.inline.hpp), then using unextended_sp doesn't seem quite right if it's not in the current frame. Maybe using something like ContinuationHelper::InterpretedFrame::frame_bottom() would be better. |
I think you are right.
I'm currently out of office and not able to look into the code on a decent display. Will do as soon as I'm back. Ad hoc I think the frame's actual sp (frame::sp()) should be used. Using other pointers from the interpreter frame is problematic because the code is also called during deoptimization, where the interpreter frame is still skeletal, i.e. the expression stack pointer is not yet set as I learned when trying to use it. |
It looks like the interpreter trims the stack before a call: jdk/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp Lines 1147 to 1157 in 4594696
so it seems like using unextended_sp() is actually fine, and the drawing in continuationFreezeThaw_ppc.inline.hpp needs to be updated. |
The interpreter allocates a new frame reserving space for the maximum expression stack. For a call it is trimmed to the current size of the stack. Consequently unextended_sp < sp is possible if max. stack is large. |
OK, if I'm not mistaken, aarch64 is doing the same thing. So that could mean that code like Continuation::is_frame_in_continuation() that uses unextended_sp is already broken on some platforms. For example, if an interpreted frame in the carrier thread had a very large max_stack, then is_frame_in_continuation() could return true when it should return false. |
Just wanted to let you know that I'm stuck with just my phone for the next 2 weeks. I'll have a closer look when I'm back. |
Sure, no problem. |
I have had a look at aarch64 now. There the interpreter also pushes a new frame
It is likely not yet broken but for ppc64 it will not work. The usage of Looking at the callers of is_sp_in_continuation() we find the the following is passed as parameter
Where 3. is a special case for continuation entry frames (see I'd like to change the callers of is_sp_in_continuation() static inline bool is_sp_in_continuation(const ContinuationEntry* entry, intptr_t* const sp) {
return entry->entry_sp() > sp;
} to pass the actual sp. This is correct because the following is true on all a.sp() > E->entry_sp() > b.sp() > c.sp() where is_sp_in_continuation() will then return true for |
hotspot_loom and jdk_loom tests on x86_64 and aarch64 still pass with the last commit fdb1409. |
Actually, for interpreted --> interpreted, aarch64 and ppc64 seem to do the same trimming. The difference is ppc64 does it in the caller, while aarch64 does it in the callee:
So this would mean for interpreted --> compiled, ppc64 does trimming and aarch64 does not. I also noticed that on ppc64, the value of unextended_sp for interpreted frames in inconsistent. Whether or not it is the "max stack" value depends on who calls the frame constructor. Some Loom code and sender_for_compiled_frame() sets unextended_sp the same as sp, while only sender_for_interpreter_frame() uses the "max stack" value. Giving unextended_sp a consistent "canonical" value that is always inside the frame, no matter if the callee is interpreted or compiled, seems like it would make unextended_sp() valid for is_sp_in_continuation() as well. |
Hi Dean, I'll answer your questions below but actually I don't think it is necessary to Also if ppc64 would be changed (and maybe also aarch64 after A dedicated RFE would be needed to establish
I see, thanks.
On x64 sender_for_compiled_frame() also sets unextended_sp == sp even though For the ppc64 Loom port I was forced to construct frames with unextended_sps
For good reason because if the sender is compiled then the sender_sp has to be
Not really as it would still rely on an undefined property which, for instance, Thanks, Richard. |
Thinking about this some more, while sp() may work for all platforms, it seems like frame::id() is what the shared Loom code should really be using. Then we would have:
The Loom code shouldn't really be assuming that stacks grow in a particular direction. That is what frame:is_older() is for. Unfortunately, I found that aarch64 has a problem with this. Given a frame f, we can't assert on aarch64 that f.sender().is_older(f.id()) because aarch64 uses unextended_sp() for frame::id(). |
With that we would have s.th. like bool Continuation::is_frame_in_continuation(const ContinuationEntry* entry, const frame& f) {
return entry->to_frame().is_older(f.id());
} and replace all uses of is_sp_in_continuation() with it. Not sure if performance !f.is_older(entry->frame_id()); with a platform dependent definition of frame_id() could be faster then.
Yes indeed there seems to be an issue with is_older() on aarch64 because of the Actually I assumed hotspot does not abstract over stack growth direction because So there might be is_older() now but looking for instance at class StackOverflow Another example from Loom is the shared code related to JavaThread::_cont_fastpath We could duplicate is_sp_in_continuation() on the platforms or add a static |
Yes, there would be quite a bit of fan-out if we decided to go with frame::id(). There are a few places where we could call is_sp_in_continuation() with a frame instead of an id. Also, as you pointed out, there is still _cont_fastpath that uses an sp. That field as well as entry->_parent_cont_fastpath should probably be using frame::id(). A new JBS enhancement for that makes sense. |
Ok. I have created https://bugs.openjdk.org/browse/JDK-8294284. |
Thanks! |
I think it would be good to also have this looked at by someone from hotspot-runtime. @coleenp, could you take a look? |
Thanks for the review @dean-long |
I think this ready to be integrated. I'll do so tomorrow if there are no further comments until then. |
/integrate |
Going to push as commit ee6c391.
Your commit was automatically rebased without conflicts. |
The method
frame::interpreter_frame_last_sp()
is a platform method in the sense that it is not declared in a shared header file. It is declared and defined on some platforms though (x86 and aarch64 I think).frame::interpreter_frame_last_sp()
existed on these platforms before vm continuations (aka loom). Shared code that is part of the vm continuations implementation references it. This breaks the platform abstraction.Using unextended_sp is problematic too because there are no guarantees by the platform abstraction layer for it. In fact unextended_sp < sp is possible on ppc64 and aarch64.
This fix changes the callers of is_sp_in_continuation()
to pass the actual sp. This is correct because the following is true on all platforms:
a.sp() > E->entry_sp() > b.sp() > c.sp()
where
a
,b
,c
are stack frames in call order andE
is a ContinuationEntry.a
is the caller frame of the continuation entry frame that corresponds toE
.is_sp_in_continuation() will then return true for
b.sp()
andc.sp()
and false fora.sp()
Testing: hotspot_loom and jdk_loom on x86_64 and aarch64.
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/9411/head:pull/9411
$ git checkout pull/9411
Update a local copy of the PR:
$ git checkout pull/9411
$ git pull https://git.openjdk.org/jdk pull/9411/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 9411
View PR using the GUI difftool:
$ git pr show -t 9411
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/9411.diff