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

8251047: GC stackwalking doesn't work when intrinsics are enabled #279

Closed
wants to merge 4 commits into from

Conversation

JornVernee
Copy link
Member

@JornVernee JornVernee commented Aug 5, 2020

Hi,

This patch fixes GC stack walking for optimized native calls.

For calls in compiled frames, the callee argument oops are processed using special case code in CompiledMethod::preserve_callee_argument_oops. This code relies on the original bytecode to find the signature of the callee, but for optimized native calls this doesn't make sense, since the original call is replaced, and some of the arguments (notably some that are oops) are discarded. In the case of an optimized native call, we can skip all callee argument oop processing, since we can't pass any oops to native calls any ways.

Since the current code was already looking at debug info to find the signature of the callee, I piggy-backed on that to add a flag for optimized native calls. If the flag is set, we return early, skipping any processing.

(I left in the assert I used to debug this, since it gives the failure a better error message, should we run into this again in the future)

Thanks,
Jorn


Progress

  • Change must not contain extraneous whitespace
  • Change must be properly reviewed

Issue

  • JDK-8251047: GC stackwalking doesn't work when intrinsics are enabled

Reviewers

Download

$ git fetch https://git.openjdk.java.net/panama-foreign pull/279/head:pull/279
$ git checkout pull/279

Sorry, something went wrong.

@bridgekeeper
Copy link

bridgekeeper bot commented Aug 5, 2020

👋 Welcome back jvernee! A progress list of the required criteria for merging this PR into foreign-abi will be added to the body of your pull request.

@openjdk openjdk bot added the rfr Ready for review label Aug 5, 2020
@mlbridge
Copy link

mlbridge bot commented Aug 5, 2020

Webrevs

Copy link
Collaborator

@mcimadamore mcimadamore left a comment

Choose a reason for hiding this comment

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

Makes sense to me - probably better if somebody from the VM team takes a look :-)

@openjdk
Copy link

openjdk bot commented Aug 5, 2020

@JornVernee This change now passes all automated pre-integration checks, type /integrate in a new comment to proceed. After integration, the commit message will be:

8251047: GC stackwalking doesn't work when intrinsics are enabled

Reviewed-by: mcimadamore
  • If you would like to add a summary, use the /summary command.
  • To credit additional contributors, use the /contributor command.
  • To add additional solved issues, use the /issue command.

There are currently no new commits on the foreign-abi branch since the last update of the source branch of this PR. If another commit should be pushed before you perform the /integrate command, your PR will be automatically rebased. If you would like to avoid potential automatic rebasing, specify the current head hash when integrating, like this: /integrate 0546e792759ef97579d690462a26d66f48efb324.

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

@openjdk openjdk bot added the ready Ready to be integrated label Aug 5, 2020
@iwanowww
Copy link
Collaborator

iwanowww commented Aug 5, 2020

Not sure it's the best way to fix the problem (need to look into the code more closely), but the fix looks good for now.

@JornVernee
Copy link
Member Author

Thanks for the reviews.

When running the Upcalls benchmark I ran into another crash that looks related, so I'm looking into that before integrating.

@iwanowww
Copy link
Collaborator

iwanowww commented Aug 21, 2020

Explicitly save RBP location in thread anchor, so we can add it to the RegisterMap when jumping from the entry frame to

The fix looks good.

Still, IMO the best solution would be to adjust CallNative so it always kills RBP in case state transition is present.

@JornVernee
Copy link
Member Author

JornVernee commented Aug 24, 2020

@iwanowww Thanks for the review.

Still, IMO the best solution would be to adjust CallNative so it always kills RBP in case state transition is present.

I'm already doing this, see the changes in lcm.cpp. RBP seems to need special handling beyond killing it in the IR. Looking at some of the runtime stub code, these are also explicitly saving RBP and creating an oop map for it.

I have to look at this in more detail to figure out if we can refactor the current native call support to work more like that of the runtime stubs. (though that adds a lot of indirection, so maybe it's worth it to try and remove the special handling of RBP in the compiler instead, but that probably also touches more code and implicit assumptions).

I added a comment in the last revision that clarifies this, as well as only killing callee saved regs in case we are actually doing a thread state transition.

@JornVernee
Copy link
Member Author

/integrate

@openjdk openjdk bot closed this Aug 24, 2020
@openjdk openjdk bot added integrated Pull request has been integrated and removed ready Ready to be integrated rfr Ready for review labels Aug 24, 2020
@openjdk
Copy link

openjdk bot commented Aug 24, 2020

@JornVernee
Pushed as commit f8cc3f4.

@JornVernee JornVernee deleted the RegisterMap_Assert branch August 24, 2020 15:09
nick-arm added a commit to nick-arm/jdk that referenced this pull request Dec 9, 2020
This is more-or-less a straight port of the x86 code to AArch64.
GraphKit::make_native_call() calls SharedRuntime::make_native_invoker()
to generate a blob that jumps to the native function entry point. This
simply switches the thread state from Java to native and handles the
safepoint poll on return from native code.

AArch64 suffers the same problem as x86 in JDK-8251047 where R29 (frame
pointer) may hold a live oop over the MachCallNative node. Normally this
would be saved by RegisterSaver::save_live_registers() but the native
invoker blob is not a "proper" stub routine so doesn't have an oop map.
I copied the x86 solution to this where the frame pointer register is
saved to the stack and a pointer to that is stored in the frame anchor.
This is then read back and added to the register map when walking the
stack. I saw in the PR comments [1] that this might be a temporary fix,
but I'm not sure if there's any plan to change that now?

Another potential fix might be to change the C2 register definition of
R29 and R29_H to be save-on-call as below. This works for the
TestStackWalk.java test case but I don't know whether it has other
unintended side-effects.

  reg_def R29     ( SOC,  NS, Op_RegI, 29, r29->as_VMReg()        ); // fp
  reg_def R29_H   ( SOC,  NS, Op_RegI, 29, r29->as_VMReg()->next());

JMH results from jdk/incubator/foreign/CallOverhead.java to show it's
working:

-Djdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS=false:

Benchmark                                    Mode  Cnt     Score     Error  Units
CallOverhead.jni_blank                       avgt   30    51.450 ?   0.363  ns/op
CallOverhead.jni_identity                    avgt   30    54.145 ?   0.627  ns/op
CallOverhead.panama_args10                   avgt   30  1914.431 ?  73.771  ns/op
CallOverhead.panama_args5                    avgt   30  1394.274 ?  49.369  ns/op
CallOverhead.panama_blank                    avgt   30   872.878 ?  20.716  ns/op
CallOverhead.panama_blank_trivial            avgt   30   873.852 ?  21.350  ns/op
CallOverhead.panama_identity                 avgt   30  1058.729 ?  20.229  ns/op
CallOverhead.panama_identity_memory_address  avgt   30  1041.648 ?  22.930  ns/op
CallOverhead.panama_identity_struct          avgt   30  3212.483 ? 151.627  ns/op
CallOverhead.panama_identity_trivial         avgt   30  1056.398 ?  18.779  ns/op

-Djdk.internal.foreign.ProgrammableInvoker.USE_INTRINSICS=true:

Benchmark                                    Mode  Cnt     Score     Error  Units
CallOverhead.jni_blank                       avgt   30    51.519 ?   0.345  ns/op
CallOverhead.jni_identity                    avgt   30    54.689 ?   0.687  ns/op
CallOverhead.panama_args10                   avgt   30    42.856 ?   0.760  ns/op
CallOverhead.panama_args5                    avgt   30    42.192 ?   0.712  ns/op
CallOverhead.panama_blank                    avgt   30    41.934 ?   0.349  ns/op
CallOverhead.panama_blank_trivial            avgt   30     2.806 ?   0.545  ns/op
CallOverhead.panama_identity                 avgt   30    44.043 ?   0.398  ns/op
CallOverhead.panama_identity_memory_address  avgt   30    45.021 ?   0.409  ns/op
CallOverhead.panama_identity_struct          avgt   30  3206.829 ? 175.750  ns/op
CallOverhead.panama_identity_trivial         avgt   30     7.849 ?   1.651  ns/op

[1] openjdk/panama-foreign#279 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

None yet

3 participants