Skip to content

Commit 6756fef

Browse files
committed
Add support for jitDispatchJ9Method for MH on P
Enables transformation of invokeBasic, linkToStatic, and linkToSpecial calls into jitDispatchJ9Method acall nodes. Codegen recognizes this node in private linakge and produces code to directly call the MethodHandle target at runtime - using a new PPCJ9HelperCall snippet when the target is interpreted - otherwise branch and link to jit start pc of target Signed-off-by: Matthew Hall <matthew.hall3@outlook.com>
1 parent 64c5c8c commit 6756fef

File tree

7 files changed

+153
-19
lines changed

7 files changed

+153
-19
lines changed

runtime/compiler/p/codegen/CallSnippet.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#include "ras/Logger.hpp"
4040
#include "runtime/CodeCacheManager.hpp"
4141

42-
uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
42+
uint8_t *TR::PPCCallSnippet::flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
4343
{
4444
int32_t intArgNum=0, floatArgNum=0, offset;
4545
TR::Compilation *comp = cg->comp();
@@ -48,8 +48,13 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
4848
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
4949
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
5050
int32_t argStart = callNode->getFirstArgumentIndex();
51+
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp);
52+
if (isJitDispatchJ9Method) {
53+
argStart += 1;
54+
}
5155

52-
if (linkageProperties.getRightToLeft())
56+
bool rightToLeft = linkageProperties.getRightToLeft() && !isJitDispatchJ9Method;
57+
if (rightToLeft)
5358
offset = linkage->getOffsetToFirstParm();
5459
else
5560
offset = argSize+linkage->getOffsetToFirstParm();
@@ -62,29 +67,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
6267
case TR::Int8:
6368
case TR::Int16:
6469
case TR::Int32:
65-
if (!linkageProperties.getRightToLeft())
70+
if (!rightToLeft)
6671
offset -= TR::Compiler->om.sizeofReferenceAddress();
6772
if (intArgNum < linkageProperties.getNumIntArgRegs())
6873
{
6974
buffer = storeArgumentItem(TR::InstOpCode::stw, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
7075
}
7176
intArgNum++;
72-
if (linkageProperties.getRightToLeft())
77+
if (rightToLeft)
7378
offset += TR::Compiler->om.sizeofReferenceAddress();
7479
break;
7580
case TR::Address:
76-
if (!linkageProperties.getRightToLeft())
81+
if (!rightToLeft)
7782
offset -= TR::Compiler->om.sizeofReferenceAddress();
7883
if (intArgNum < linkageProperties.getNumIntArgRegs())
7984
{
8085
buffer = storeArgumentItem(storeGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
8186
}
8287
intArgNum++;
83-
if (linkageProperties.getRightToLeft())
88+
if (rightToLeft)
8489
offset += TR::Compiler->om.sizeofReferenceAddress();
8590
break;
8691
case TR::Int64:
87-
if (!linkageProperties.getRightToLeft())
92+
if (!rightToLeft)
8893
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
8994
if (intArgNum < linkageProperties.getNumIntArgRegs())
9095
{
@@ -98,29 +103,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
98103
}
99104
}
100105
intArgNum += comp->target().is64Bit() ? 1 : 2;
101-
if (linkageProperties.getRightToLeft())
106+
if (rightToLeft)
102107
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
103108
break;
104109
case TR::Float:
105-
if (!linkageProperties.getRightToLeft())
110+
if (!rightToLeft)
106111
offset -= TR::Compiler->om.sizeofReferenceAddress();
107112
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
108113
{
109114
buffer = storeArgumentItem(TR::InstOpCode::stfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
110115
}
111116
floatArgNum++;
112-
if (linkageProperties.getRightToLeft())
117+
if (rightToLeft)
113118
offset += TR::Compiler->om.sizeofReferenceAddress();
114119
break;
115120
case TR::Double:
116-
if (!linkageProperties.getRightToLeft())
121+
if (!rightToLeft)
117122
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
118123
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
119124
{
120125
buffer = storeArgumentItem(TR::InstOpCode::stfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
121126
}
122127
floatArgNum++;
123-
if (linkageProperties.getRightToLeft())
128+
if (rightToLeft)
124129
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
125130
break;
126131
}
@@ -1644,4 +1649,3 @@ TR_Debug::print(OMR::Logger *log, TR::PPCInterfaceCallSnippet * snippet)
16441649
printPrefix(log, NULL, cursor, sizeof(intptr_t));
16451650
log->printf(".long \t" POINTER_PRINTF_FORMAT "\t\t; J2I thunk address for private", *(intptr_t *)cursor);
16461651
}
1647-

runtime/compiler/p/codegen/CallSnippet.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class PPCCallSnippet : public TR::Snippet
5757
TR::SymbolReference * _realMethodSymbolReference;
5858

5959
public:
60+
static uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg);
6061

6162
PPCCallSnippet(TR::CodeGenerator *cg, TR::Node *c, TR::LabelSymbol *lab, int32_t s)
6263
: TR::Snippet(cg, c, lab, needsGCMap(cg, c->getSymbolReference())), sizeOfArguments(s), callRA(0)

runtime/compiler/p/codegen/J9CodeGenerator.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,3 +832,13 @@ J9::Power::CodeGenerator::deriveCallingLinkage(TR::Node *node, bool isIndirect)
832832

833833
return self()->getLinkage(callee->getLinkageConvention());
834834
}
835+
836+
bool
837+
J9::Power::CodeGenerator::supportsNonHelper(TR::SymbolReferenceTable::CommonNonhelperSymbol symbol)
838+
{
839+
if (symbol == TR::SymbolReferenceTable::jitDispatchJ9MethodSymbol)
840+
{
841+
return true;
842+
}
843+
return J9::CodeGenerator::supportsNonHelper(symbol);
844+
}

runtime/compiler/p/codegen/J9CodeGenerator.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class OMR_EXTENSIBLE CodeGenerator : public J9::CodeGenerator
102102

103103
bool canEmitDataForExternallyRelocatableInstructions();
104104

105+
bool supportsNonHelper(TR::SymbolReferenceTable::CommonNonhelperSymbol symbol);
106+
105107
#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
106108
bool suppressInliningOfCryptoMethod(TR::RecognizedMethod method);
107109
bool inlineCryptoMethod(TR::Node *node, TR::Register *&resultReg);

runtime/compiler/p/codegen/J9PPCSnippet.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "p/codegen/PPCEvaluator.hpp"
4343
#include "p/codegen/PPCInstruction.hpp"
4444
#include "p/codegen/GenerateInstructions.hpp"
45+
#include "p/codegen/CallSnippet.hpp"
4546
#include "ras/Logger.hpp"
4647
#include "runtime/CodeCache.hpp"
4748
#include "runtime/CodeCacheManager.hpp"
@@ -293,6 +294,25 @@ int32_t TR::PPCReadMonitorSnippet::setEstimatedCodeLocation(int32_t estimatedSni
293294
return(estimatedSnippetStart);
294295
}
295296

297+
uint8_t *TR::PPCJ9HelperCallSnippet::emitSnippetBody() {
298+
uint8_t *buffer = cg()->getBinaryBufferCursor();
299+
uint8_t *gtrmpln, *trmpln;
300+
301+
getSnippetLabel()->setCodeLocation(buffer);
302+
buffer = TR::PPCCallSnippet::flushArgumentsToStack(buffer, this->getNode(), this->getSizeOfArguments(), cg());
303+
304+
if (this->getNode()->isJitDispatchJ9MethodCall(cg()->comp()))
305+
{
306+
// move value in r11 to r3 for the interpreter
307+
// or r11 r3 r11 444 0
308+
// 011111 01011 00011 01011 0110111100 0
309+
*(int32_t *)buffer = 0x7D635B78;
310+
buffer += 4;
311+
}
312+
313+
return this->genHelperCall(buffer);
314+
}
315+
296316
TR::PPCAllocPrefetchSnippet::PPCAllocPrefetchSnippet(
297317
TR::CodeGenerator *codeGen,
298318
TR::Node *node,
@@ -1270,4 +1290,3 @@ uint32_t TR::PPCNonZeroAllocPrefetchSnippet::getLength(int32_t estimatedCodeStar
12701290

12711291
return PPC_INSTRUCTION_LENGTH;
12721292
}
1273-

runtime/compiler/p/codegen/J9PPCSnippet.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ class PPCReadMonitorSnippet : public TR::PPCHelperCallSnippet
7474
int32_t getLoadOffset() { return _loadOffset; }
7575
};
7676

77+
class PPCJ9HelperCallSnippet : public TR::PPCHelperCallSnippet {
78+
int32_t _argSize;
79+
80+
public:
81+
PPCJ9HelperCallSnippet(TR::CodeGenerator *cg, TR::Node *node, TR::LabelSymbol *snippetlab,
82+
TR::SymbolReference *helper, TR::LabelSymbol *restartLabel = NULL, int32_t argSize = -1)
83+
: TR::PPCHelperCallSnippet(cg, node, snippetlab, helper, restartLabel)
84+
, _argSize(argSize)
85+
{}
86+
87+
int32_t getSizeOfArguments() { return _argSize; }
88+
virtual uint8_t *emitSnippetBody();
89+
};
90+
7791
class PPCAllocPrefetchSnippet : public TR::Snippet
7892
{
7993

runtime/compiler/p/codegen/PPCPrivateLinkage.cpp

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
#include "il/TreeTop_inlines.hpp"
5050
#include "p/codegen/CallSnippet.hpp"
5151
#include "p/codegen/GenerateInstructions.hpp"
52+
#include "p/codegen/J9PPCSnippet.hpp"
5253
#include "p/codegen/PPCEvaluator.hpp"
5354
#include "p/codegen/PPCHelperCallSnippet.hpp"
5455
#include "p/codegen/PPCInstruction.hpp"
@@ -373,7 +374,7 @@ J9::Power::PrivateLinkage::PrivateLinkage(TR::CodeGenerator *cg)
373374
}
374375
_properties._computedCallTargetRegister = TR::RealRegister::gr0; // gr11 = interface, gr12 = virtual, so we need something else for computed
375376
_properties._vtableIndexArgumentRegister = TR::RealRegister::gr12;
376-
_properties._j9methodArgumentRegister = TR::RealRegister::gr3; // TODO:JSR292: Confirm
377+
_properties._j9methodArgumentRegister = TR::RealRegister::gr11; // TODO:JSR292: Confirm
377378
}
378379

379380
const TR::PPCLinkageProperties& J9::Power::PrivateLinkage::getProperties()
@@ -1470,10 +1471,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
14701471
TR_Array<TR::Register *>& tempLongRegisters = cg()->getTransientLongRegisters();
14711472
TR::MethodSymbol *callSymbol = callNode->getSymbol()->castToMethodSymbol();
14721473

1474+
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp);
14731475
bool isHelperCall = linkage == TR_Helper || linkage == TR_CHelper;
14741476
bool rightToLeft = isHelperCall &&
14751477
//we want the arguments for induceOSR to be passed from left to right as in any other non-helper call
1476-
!callNode->getSymbolReference()->isOSRInductionHelper();
1478+
!callNode->getSymbolReference()->isOSRInductionHelper() && !isJitDispatchJ9Method;
14771479

14781480
if (rightToLeft)
14791481
{
@@ -1501,7 +1503,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15011503
switch (callSymbol->getMandatoryRecognizedMethod())
15021504
{
15031505
// Node: special long args are still only passed in one GPR
1504-
case TR::java_lang_invoke_ComputedCalls_dispatchJ9Method:
1506+
case TR::java_lang_invoke_ComputedCalls_dispatchJ9Method: // old MH implementation
15051507
specialArgReg = getProperties().getJ9MethodArgumentRegister();
15061508
// Other args go in memory
15071509
numIntArgRegs = 0;
@@ -1515,6 +1517,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15151517
break;
15161518
}
15171519

1520+
if (isJitDispatchJ9Method)
1521+
{
1522+
specialArgReg = getProperties().getJ9MethodArgumentRegister();
1523+
}
1524+
15181525
if (specialArgReg != TR::RealRegister::NoReg)
15191526
{
15201527
logprintf(trace, log, "Special arg %s in %s\n",
@@ -1533,6 +1540,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15331540
totalSize += TR::Compiler->om.sizeofReferenceAddress();
15341541
}
15351542

1543+
// will not process special args
15361544
for (int32_t i = from; (rightToLeft && i >= to) || (!rightToLeft && i <= to); i += step)
15371545
{
15381546
child = callNode->getChild(i);
@@ -1588,7 +1596,9 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15881596
}
15891597

15901598
if (specialArgReg)
1599+
{
15911600
from -= step; // we do want to process special args in the following loop
1601+
}
15921602

15931603
numIntegerArgs = 0;
15941604
numFloatArgs = 0;
@@ -2870,20 +2880,94 @@ void J9::Power::PrivateLinkage::buildDirectCall(TR::Node *callNode,
28702880
TR::ResolvedMethodSymbol *sym = callSymbol->getResolvedMethodSymbol();
28712881
TR_ResolvedMethod *vmm = (sym==NULL)?NULL:sym->getResolvedMethod();
28722882
bool myself = comp()->isRecursiveMethodTarget(vmm);
2883+
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp());
28732884

28742885
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp()->fe());
28752886

2876-
if (callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers)
2887+
if ((callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers) && !isJitDispatchJ9Method)
28772888
fej9->reserveTrampolineIfNecessary(comp(), callSymRef, false);
28782889

28792890
bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp());
2880-
if ((callSymbol->isJITInternalNative() ||
2891+
if (!isJitDispatchJ9Method && (callSymbol->isJITInternalNative() ||
28812892
(!callSymRef->isUnresolved() && !callSymbol->isInterpreted() && ((forceUnresolvedDispatch && callSymbol->isHelper()) || !forceUnresolvedDispatch))))
28822893
{
28832894
gcPoint = generateDepImmSymInstruction(cg(), TR::InstOpCode::bl, callNode,
28842895
myself?0:(uintptr_t)callSymbol->getMethodAddress(),
28852896
dependencies, callSymRef?callSymRef:callNode->getSymbolReference());
28862897
}
2898+
else if (isJitDispatchJ9Method)
2899+
{
2900+
auto regMapMask = pp.getPreservedRegisterMapForGC();
2901+
2902+
TR::Register *scratchReg = dependencies->searchPostConditionRegister(pp.getVTableIndexArgumentRegister());
2903+
TR::Register *scratchReg2 = dependencies->searchPreConditionRegister(TR::RealRegister::gr0);
2904+
TR::Register *cndReg = dependencies->searchPreConditionRegister(TR::RealRegister::cr0);
2905+
TR::Register *j9MethodReg = callNode->getChild(0)->getRegister();
2906+
2907+
TR::LabelSymbol *startICFLabel = generateLabelSymbol(cg());
2908+
TR::LabelSymbol *doneLabel = generateLabelSymbol(cg());
2909+
TR::LabelSymbol *oolLabel = generateLabelSymbol(cg());
2910+
startICFLabel->setStartInternalControlFlow();
2911+
doneLabel->setEndInternalControlFlow();
2912+
2913+
TR::RegisterDependencyConditions *preDeps = dependencies->clone(cg());
2914+
preDeps->setNumPostConditions(0, trMemory());
2915+
preDeps->setAddCursorForPost(0);
2916+
2917+
TR::RegisterDependencyConditions *postDeps = dependencies->clone(cg());
2918+
postDeps->setNumPreConditions(0, trMemory());
2919+
postDeps->setAddCursorForPre(0);
2920+
2921+
TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg());
2922+
TR::SymbolReference *helperRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_j2iTransition, true, true, false);
2923+
TR::Snippet *interpCallSnippet = new (cg()->trHeapMemory()) TR::PPCJ9HelperCallSnippet(cg(), callNode, snippetLabel, helperRef, doneLabel, argSize);
2924+
interpCallSnippet->gcMap().setGCRegisterMask(regMapMask);
2925+
cg()->addSnippet(interpCallSnippet);
2926+
TR::SymbolReference *snippetSymRef = new (trHeapMemory()) TR::SymbolReference(comp()->getSymRefTab(), snippetLabel);
2927+
2928+
TR_PPCOutOfLineCodeSection *snippetCall = new (cg()->trHeapMemory()) TR_PPCOutOfLineCodeSection(oolLabel, doneLabel, cg());
2929+
cg()->getPPCOutOfLineCodeSectionList().push_front(snippetCall);
2930+
snippetCall->swapInstructionListsWithCompilation();
2931+
TR::Instruction *OOLLabelInstr = generateLabelInstruction(cg(), TR::InstOpCode::label, callNode, oolLabel);
2932+
gcPoint = generateDepLabelInstruction(cg(), TR::InstOpCode::bl, callNode, snippetLabel, dependencies);
2933+
gcPoint->PPCNeedsGCMap(regMapMask);
2934+
generateLabelInstruction(cg(), TR::InstOpCode::b, callNode, doneLabel);
2935+
snippetCall->swapInstructionListsWithCompilation();
2936+
2937+
generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, startICFLabel, preDeps);
2938+
2939+
// test if compiled
2940+
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, scratchReg,
2941+
TR::MemoryReference::createWithDisplacement(cg(), j9MethodReg, offsetof(J9Method, extra), TR::Compiler->om.sizeofReferenceAddress()));
2942+
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::andi_r, callNode, scratchReg2, scratchReg, 1);
2943+
cg()->stopUsingRegister(scratchReg2);
2944+
2945+
if (cg()->stressJitDispatchJ9MethodJ2I())
2946+
{
2947+
gcPoint = generateLabelInstruction(cg(), TR::InstOpCode::b, callNode, oolLabel);
2948+
}
2949+
else
2950+
{
2951+
generateConditionalBranchInstruction(cg(), TR::InstOpCode::bne, callNode, oolLabel, cndReg);
2952+
}
2953+
gcPoint->PPCNeedsGCMap(regMapMask);
2954+
2955+
// compiled - jump to jit entry point
2956+
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, j9MethodReg,
2957+
TR::MemoryReference::createWithDisplacement(cg(), scratchReg, -4, TR::Compiler->om.sizeofReferenceAddress()));
2958+
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::srawi, callNode, j9MethodReg, j9MethodReg, 16);
2959+
if (comp()->target().is64Bit())
2960+
{
2961+
generateTrg1Src1Instruction(cg(), TR::InstOpCode::extsw, callNode, j9MethodReg, j9MethodReg);
2962+
}
2963+
generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, callNode, scratchReg, j9MethodReg, scratchReg);
2964+
generateSrc1Instruction(cg(), TR::InstOpCode::mtctr, callNode, scratchReg);
2965+
gcPoint = generateInstruction(cg(), TR::InstOpCode::bctrl, callNode);
2966+
gcPoint->PPCNeedsGCMap(regMapMask);
2967+
2968+
generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, doneLabel, postDeps);
2969+
return;
2970+
}
28872971
else
28882972
{
28892973
TR::LabelSymbol *label = generateLabelSymbol(cg());

0 commit comments

Comments
 (0)