Skip to content

Pop extra args on BootstrapMethodError for invokedynamic #21720

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

Conversation

matthewhall2
Copy link
Contributor

@matthewhall2 matthewhall2 commented Apr 24, 2025

When an error is caught during resolveInvokeDynamic (MethodHandleResolver.java), a MethodHandle that throws a BootstrapMethodError is returned, which has no arguments. This can cause an issue for OSR where we run out of pending push temp slots during OSR BookKeeping since we are not popping all the args off the operand stack.

This change recognizes when we have not popped all the arguments and pops them accordingly

Fixes: #21419

@matthewhall2 matthewhall2 force-pushed the resolveInvokeDynamic_stackOverflowFix branch from 390d85c to 2cd5462 Compare May 2, 2025 19:38
@matthewhall2 matthewhall2 marked this pull request as draft May 2, 2025 20:03
@matthewhall2 matthewhall2 force-pushed the resolveInvokeDynamic_stackOverflowFix branch from 2cd5462 to 3ecd2b3 Compare May 2, 2025 20:13
@matthewhall2 matthewhall2 marked this pull request as ready for review May 2, 2025 20:18
@jdmpapin jdmpapin self-requested a review May 2, 2025 20:19
@matthewhall2 matthewhall2 changed the title Add StackOverflow check in resolveInvokeDynamic Pop extra args on BootstrapMethodError for invokedynamic May 2, 2025
Copy link
Contributor

@jdmpapin jdmpapin left a comment

Choose a reason for hiding this comment

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

There are some typos at end of the commit message:

all the arguemnts → arguments and pops then → them accordinly → accordingly.

I see that you've already corrected them in the PR description

@matthewhall2 matthewhall2 marked this pull request as draft May 8, 2025 14:33
@matthewhall2 matthewhall2 force-pushed the resolveInvokeDynamic_stackOverflowFix branch 5 times, most recently from dda7f01 to da57af0 Compare May 12, 2025 14:41
@matthewhall2 matthewhall2 marked this pull request as ready for review May 12, 2025 14:42
@matthewhall2 matthewhall2 requested a review from jdmpapin May 12, 2025 14:42
@matthewhall2
Copy link
Contributor Author

Thanks @jdmpapin , I've made the requested changes. Can I get another review please?

Copy link
Contributor

@jdmpapin jdmpapin left a comment

Choose a reason for hiding this comment

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

This looks like it works properly now. Just a couple of formatting comments, and the "arguemnts" typo is still there in the commit message

@matthewhall2 matthewhall2 force-pushed the resolveInvokeDynamic_stackOverflowFix branch from da57af0 to e8af1a6 Compare May 12, 2025 18:50
@matthewhall2 matthewhall2 requested a review from jdmpapin May 12, 2025 18:52
When an error is caught during resolveInvokeDynamic
(MethodHandleResolver.java), a MethodHandle that throws a
BootstrapMethodError is returned, which has no arguments.
This can cause an issue for OSR where we run out of pending push temp
slots since we are not popping all the args off the operand stack.

This commit recognizes when we have not popped all the arguments and
pops them accordingly.

Fixes: eclipse-openj9#21419

Signed-off-by: Matthew Hall <[email protected]>
@matthewhall2 matthewhall2 force-pushed the resolveInvokeDynamic_stackOverflowFix branch from e8af1a6 to 743a0ce Compare May 12, 2025 18:57
@jdmpapin
Copy link
Contributor

@hzongaro, could you please review as well?

@jdmpapin jdmpapin requested a review from hzongaro May 12, 2025 19:29
Copy link
Member

@hzongaro hzongaro left a comment

Choose a reason for hiding this comment

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

I think the changes look good. I had some cosmetic comments, but I don't want them to hold up the fix; I will approve this change and ask you to address them when you have the opportunity.

@@ -149,14 +149,15 @@ class TR_J9ByteCodeIlGenerator : public TR_IlGenerator, public TR_J9ByteCodeIter

bool runMacro(TR::SymbolReference *);
bool runFEMacro(TR::SymbolReference *);
TR::Node * genInvoke(TR::SymbolReference *, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver = NULL);
TR::Node * genInvoke(TR::SymbolReference *, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver = NULL, int32_t numExpectedArgs = -1);
Copy link
Member

Choose a reason for hiding this comment

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

May I ask you to add Doxygen comments for this method? I know it's not a new method, but hopefully over time we can get broader coverage.


TR::Node * genInvokeDirect(TR::SymbolReference *symRef){ return genInvoke(symRef, NULL); }
TR::Node * genInvokeDirect(TR::SymbolReference *symRef, int32_t numExpectedArgs = -1){ return genInvoke(symRef, NULL, NULL, numExpectedArgs); }
Copy link
Member

Choose a reason for hiding this comment

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

Again, may I ask you to add Doxygen comments for this method?

@@ -3200,6 +3200,29 @@ static char *suffixedName(char *baseName, char typeSuffix, char *buf, int32_t bu
return methodName;
}

static int32_t countParams(unsigned char *sig)
Copy link
Member

Choose a reason for hiding this comment

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

May I ask you to add Doxygen comments for this method?

/* We need to get the expected number of parameters from the signature. There is a case where findOrCreateDynamicMethodSymbol()
* returns an error-throwing MethodHandle that takes 0 arguments (occurs when an error is caught during resolveInvokeDynamic()). We cannot use
* TR::Method::numberOfExplicitParameters() since that fetches the number of parameters of targetMethodSymRefs (the MH actually returned)
* instead of whats expected the invokedynamic call. This can be a problem since the expcected of args are already on the stack and won't be
Copy link
Member

Choose a reason for hiding this comment

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

Typos:

  • "whats expected the invokedynamic" -> "what's expected for the invokedynamic"
  • "expcected" -> "expected"

if (numPopped < numExpectedArgs)
{
if (comp()->getOption(TR_TraceILGen))
traceMsg(comp(), "InvokeDynamic recieved error throwing MethodHandle. Popping extra args.\n");
Copy link
Member

Choose a reason for hiding this comment

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

Typo: "recieved" -> "received"

@hzongaro
Copy link
Member

Jenkins test sanity.functional,sanity.openjdk all jdk17,jdk21

@hzongaro hzongaro self-assigned this May 15, 2025
@hzongaro
Copy link
Member

Testing completed successful and reviews approved. Merging.

@pshipton
Copy link
Member

pshipton commented May 16, 2025

This seems to be causing crashes on jdk8, reverting it via #21902

@jdmpapin
Copy link
Contributor

@matthewhall2, I'm guessing the extra popping was kicking in when it shouldn't. If that's the case, it should be possible to fix it by only doing extra pops when numExpectedArgs was explicitly specified, i.e. skip this part

if (numExpectedArgs == -1)
      numExpectedArgs = numArgs;

and then later on we can restrict the condition for popping:

if (numExpectedArgs > 0 && numPopped < numExpectedArgs)
   {
   ...
   }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

System.Logger Triggers J9 Crash on OpenJDK 17 and 21
4 participants