Skip to content

Commit 2e8cf57

Browse files
authored
Merge pull request #21720 from matthewhall2/resolveInvokeDynamic_stackOverflowFix
Pop extra args on BootstrapMethodError for invokedynamic
2 parents f30ea2e + 743a0ce commit 2e8cf57

File tree

2 files changed

+81
-8
lines changed

2 files changed

+81
-8
lines changed

runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,15 @@ class TR_J9ByteCodeIlGenerator : public TR_IlGenerator, public TR_J9ByteCodeIter
149149

150150
bool runMacro(TR::SymbolReference *);
151151
bool runFEMacro(TR::SymbolReference *);
152-
TR::Node * genInvoke(TR::SymbolReference *, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver = NULL);
152+
TR::Node * genInvoke(TR::SymbolReference *, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver = NULL, int32_t numExpectedArgs = -1);
153153
TR::Node * genInvokeInner(
154154
TR::SymbolReference *,
155155
TR::Node *indirectCallFirstChild,
156156
TR::Node *invokedynamicReceiver,
157-
TR::KnownObjectTable::Index *requiredKoi);
157+
TR::KnownObjectTable::Index *requiredKoi,
158+
int32_t numExpectedArgs = -1);
158159

159-
TR::Node * genInvokeDirect(TR::SymbolReference *symRef){ return genInvoke(symRef, NULL); }
160+
TR::Node * genInvokeDirect(TR::SymbolReference *symRef, int32_t numExpectedArgs = -1){ return genInvoke(symRef, NULL, NULL, numExpectedArgs); }
160161
TR::Node * genInvokeWithVFTChild(TR::SymbolReference *);
161162
TR::Node * getReceiverFor(TR::SymbolReference *);
162163
void stashArgumentsForOSR(TR_J9ByteCode byteCode);

runtime/compiler/ilgen/Walker.cpp

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,29 @@ static char *suffixedName(char *baseName, char typeSuffix, char *buf, int32_t bu
32003200
return methodName;
32013201
}
32023202

3203+
static int32_t countParams(unsigned char *sig)
3204+
{
3205+
sig++; // skip opening brace
3206+
int32_t count = 0;
3207+
while (*sig != ')')
3208+
{
3209+
while (*sig == '[')
3210+
{
3211+
sig++;
3212+
}
3213+
if (*sig == 'L')
3214+
{
3215+
while (*sig != ';')
3216+
{
3217+
sig++;
3218+
}
3219+
}
3220+
count++;
3221+
sig++;
3222+
}
3223+
return count;
3224+
}
3225+
32033226
void
32043227
TR_J9ByteCodeIlGenerator::genInvokeDynamic(int32_t callSiteIndex)
32053228
{
@@ -3210,7 +3233,7 @@ TR_J9ByteCodeIlGenerator::genInvokeDynamic(int32_t callSiteIndex)
32103233
{
32113234
comp()->failCompilation<J9::AOTHasInvokeHandle>("COMPILATION_AOT_HAS_INVOKEHANDLE 0");
32123235
}
3213-
// Call generated when call site table entry is resolved:
3236+
// Call generated when call site table entry is resolved and appendix object is non-null:
32143237
// -----------------------------------------------------
32153238
// call <target method obtained from memberName object>
32163239
// arg0
@@ -3261,7 +3284,33 @@ TR_J9ByteCodeIlGenerator::genInvokeDynamic(int32_t callSiteIndex)
32613284
if (comp()->getOption(TR_TraceILGen))
32623285
printStack(comp(), _stack, "(Stack after load from callsite table)");
32633286

3264-
TR::Node* callNode = genInvokeDirect(targetMethodSymRef);
3287+
/* We need to get the expected number of parameters from the signature. There is a case where findOrCreateDynamicMethodSymbol()
3288+
* returns an error-throwing MethodHandle that takes 0 arguments (occurs when an error is caught during resolveInvokeDynamic()). We cannot use
3289+
* TR::Method::numberOfExplicitParameters() since that fetches the number of parameters of targetMethodSymRefs (the MH actually returned)
3290+
* 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
3291+
* properly popped.
3292+
*/
3293+
int32_t paramCount = 0;
3294+
if (isUnresolved)
3295+
{
3296+
// we need both appendix and membername objects ==> we have at least 2 args
3297+
paramCount = 2;
3298+
}
3299+
else
3300+
{
3301+
// we only need to account for the appendix object if it is non-null
3302+
paramCount = (isInvokeCacheAppendixNull ? 0 : 1);
3303+
}
3304+
3305+
TR_ResolvedJ9Method* ownerMethod = static_cast<TR_ResolvedJ9Method *>(_methodSymbol->getResolvedMethod());
3306+
J9ROMClass *ownerROMMethod = ownerMethod->romClassPtr();
3307+
J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(ownerROMMethod);
3308+
J9ROMNameAndSignature *nameAndSig = SRP_PTR_GET(callSiteData + callSiteIndex, J9ROMNameAndSignature*);
3309+
J9UTF8* sig = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig);
3310+
// count params gets the number of explicit parameters and does not include the appendix and/or membername objects
3311+
paramCount += countParams(J9UTF8_DATA(sig));
3312+
3313+
TR::Node* callNode = genInvokeDirect(targetMethodSymRef, paramCount);
32653314

32663315
#else
32673316
if (comp()->compileRelocatableCode())
@@ -3659,11 +3708,11 @@ static TR::SymbolReference * getPrimitiveValueFieldSymbolReference(TR_J9ByteCode
36593708
}
36603709

36613710
TR::Node*
3662-
TR_J9ByteCodeIlGenerator::genInvoke(TR::SymbolReference * symRef, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver)
3711+
TR_J9ByteCodeIlGenerator::genInvoke(TR::SymbolReference * symRef, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver, int32_t numExpectedArgs)
36633712
{
36643713
TR::KnownObjectTable::Index requiredKoi;
36653714
TR::Node *callNode = genInvokeInner(
3666-
symRef, indirectCallFirstChild, invokedynamicReceiver, &requiredKoi);
3715+
symRef, indirectCallFirstChild, invokedynamicReceiver, &requiredKoi, numExpectedArgs);
36673716

36683717
if (requiredKoi == TR::KnownObjectTable::UNKNOWN)
36693718
return callNode;
@@ -3682,7 +3731,8 @@ TR_J9ByteCodeIlGenerator::genInvokeInner(
36823731
TR::SymbolReference * symRef,
36833732
TR::Node *indirectCallFirstChild,
36843733
TR::Node *invokedynamicReceiver,
3685-
TR::KnownObjectTable::Index *requiredKoi)
3734+
TR::KnownObjectTable::Index *requiredKoi,
3735+
int32_t numExpectedArgs)
36863736
{
36873737
TR::MethodSymbol * symbol = symRef->getSymbol()->castToMethodSymbol();
36883738
bool isStatic = symbol->isStatic();
@@ -3691,6 +3741,12 @@ TR_J9ByteCodeIlGenerator::genInvokeInner(
36913741
TR::Method * calledMethod = symbol->getMethod();
36923742
int32_t numArgs = calledMethod->numberOfExplicitParameters() + (isStatic ? 0 : 1);
36933743

3744+
// need to track stack size at beginning and end of ILGeneration for invokeDynamic for the case
3745+
// where we get the special error throwing MethodHandle
3746+
int32_t startingStackSize = _stack->size();
3747+
if (numExpectedArgs == -1)
3748+
numExpectedArgs = numArgs;
3749+
36943750
if (pushRequiredConst(requiredKoi))
36953751
{
36963752
TR::Node *result = pop();
@@ -4601,6 +4657,22 @@ break
46014657
else
46024658
resultNode = callNode;
46034659

4660+
/* There is a case where findOrCreateDynamicMethodSymbol() returns an error-throwing MethodHandle that
4661+
* takes 0 arguments (occurs when an error is thrown during resolveInvokeDynamic()). In that case, we will not have
4662+
* popped all the arguments off the stack, so we need to pop the expected number.
4663+
*/
4664+
int32_t numPopped = startingStackSize - _stack->size();
4665+
if (numPopped < numExpectedArgs)
4666+
{
4667+
if (comp()->getOption(TR_TraceILGen))
4668+
traceMsg(comp(), "InvokeDynamic recieved error throwing MethodHandle. Popping extra args.\n");
4669+
while (numPopped < numExpectedArgs)
4670+
{
4671+
pop();
4672+
numPopped++;
4673+
}
4674+
}
4675+
46044676
TR::DataType returnType = calledMethod->returnType();
46054677
if (returnType != TR::NoType)
46064678
{

0 commit comments

Comments
 (0)