Skip to content

Commit d6662b9

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 1f1eb8a commit d6662b9

File tree

5 files changed

+200
-18
lines changed

5 files changed

+200
-18
lines changed

runtime/compiler/p/codegen/CallSnippet.cpp

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "il/Node_inlines.hpp"
3737
#include "p/codegen/PPCAOTRelocation.hpp"
3838
#include "p/codegen/PPCTableOfConstants.hpp"
39+
#include "p/codegen/PPCJ9HelperCallSnippet.hpp"
3940
#include "runtime/CodeCacheManager.hpp"
4041

4142
uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argSize, TR::CodeGenerator *cg)
@@ -47,8 +48,13 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
4748
TR::Linkage* linkage = cg->getLinkage(callNode->getSymbol()->castToMethodSymbol()->getLinkageConvention());
4849
const TR::PPCLinkageProperties &linkageProperties = linkage->getProperties();
4950
int32_t argStart = callNode->getFirstArgumentIndex();
51+
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp);
52+
if (isJitDispatchJ9Method) {
53+
argStart += 1;
54+
}
5055

51-
if (linkageProperties.getRightToLeft())
56+
bool rightToLeft = linkageProperties.getRightToLeft() && !isJitDispatchJ9Method;
57+
if (rightToLeft)
5258
offset = linkage->getOffsetToFirstParm();
5359
else
5460
offset = argSize+linkage->getOffsetToFirstParm();
@@ -61,29 +67,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
6167
case TR::Int8:
6268
case TR::Int16:
6369
case TR::Int32:
64-
if (!linkageProperties.getRightToLeft())
70+
if (!rightToLeft)
6571
offset -= TR::Compiler->om.sizeofReferenceAddress();
6672
if (intArgNum < linkageProperties.getNumIntArgRegs())
6773
{
6874
buffer = storeArgumentItem(TR::InstOpCode::stw, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
6975
}
7076
intArgNum++;
71-
if (linkageProperties.getRightToLeft())
77+
if (rightToLeft)
7278
offset += TR::Compiler->om.sizeofReferenceAddress();
7379
break;
7480
case TR::Address:
75-
if (!linkageProperties.getRightToLeft())
81+
if (!rightToLeft)
7682
offset -= TR::Compiler->om.sizeofReferenceAddress();
7783
if (intArgNum < linkageProperties.getNumIntArgRegs())
7884
{
7985
buffer = storeArgumentItem(storeGPROp, buffer, machine->getRealRegister(linkageProperties.getIntegerArgumentRegister(intArgNum)), offset, cg);
8086
}
8187
intArgNum++;
82-
if (linkageProperties.getRightToLeft())
88+
if (rightToLeft)
8389
offset += TR::Compiler->om.sizeofReferenceAddress();
8490
break;
8591
case TR::Int64:
86-
if (!linkageProperties.getRightToLeft())
92+
if (!rightToLeft)
8793
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
8894
if (intArgNum < linkageProperties.getNumIntArgRegs())
8995
{
@@ -97,29 +103,29 @@ uint8_t *flushArgumentsToStack(uint8_t *buffer, TR::Node *callNode, int32_t argS
97103
}
98104
}
99105
intArgNum += comp->target().is64Bit() ? 1 : 2;
100-
if (linkageProperties.getRightToLeft())
106+
if (rightToLeft)
101107
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
102108
break;
103109
case TR::Float:
104-
if (!linkageProperties.getRightToLeft())
110+
if (!rightToLeft)
105111
offset -= TR::Compiler->om.sizeofReferenceAddress();
106112
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
107113
{
108114
buffer = storeArgumentItem(TR::InstOpCode::stfs, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
109115
}
110116
floatArgNum++;
111-
if (linkageProperties.getRightToLeft())
117+
if (rightToLeft)
112118
offset += TR::Compiler->om.sizeofReferenceAddress();
113119
break;
114120
case TR::Double:
115-
if (!linkageProperties.getRightToLeft())
121+
if (!rightToLeft)
116122
offset -= 2*TR::Compiler->om.sizeofReferenceAddress();
117123
if (floatArgNum < linkageProperties.getNumFloatArgRegs())
118124
{
119125
buffer = storeArgumentItem(TR::InstOpCode::stfd, buffer, machine->getRealRegister(linkageProperties.getFloatArgumentRegister(floatArgNum)), offset, cg);
120126
}
121127
floatArgNum++;
122-
if (linkageProperties.getRightToLeft())
128+
if (rightToLeft)
123129
offset += 2*TR::Compiler->om.sizeofReferenceAddress();
124130
break;
125131
}
@@ -328,6 +334,25 @@ TR_RuntimeHelper TR::PPCCallSnippet::getInterpretedDispatchHelper(
328334
}
329335
}
330336

337+
uint8_t *TR::PPCJ9HelperCallSnippet::emitSnippetBody() {
338+
uint8_t *buffer = cg()->getBinaryBufferCursor();
339+
uint8_t *gtrmpln, *trmpln;
340+
341+
getSnippetLabel()->setCodeLocation(buffer);
342+
buffer = flushArgumentsToStack(buffer, this->getNode(), this->getSizeOfArguments(), cg());
343+
344+
if (this->getNode()->isJitDispatchJ9MethodCall(cg()->comp()))
345+
{
346+
// move value in r11 to r3 for the interpreter
347+
// or r11 r3 r11 444 0
348+
// 011111 01011 00011 01011 0110111100 0
349+
*(int32_t *)buffer = 0x7D635B78;
350+
buffer += 4;
351+
}
352+
353+
return this->genHelperCall(buffer);
354+
}
355+
331356
uint8_t *TR::PPCCallSnippet::emitSnippetBody()
332357
{
333358

@@ -1642,4 +1667,3 @@ TR_Debug::print(TR::FILE *pOutFile, TR::PPCInterfaceCallSnippet * snippet)
16421667
printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));
16431668
trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; J2I thunk address for private", *(intptr_t *)cursor);
16441669
}
1645-

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);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*******************************************************************************
2+
* Copyright IBM Corp. and others 2000
3+
*
4+
* This program and the accompanying materials are made available under
5+
* the terms of the Eclipse Public License 2.0 which accompanies this
6+
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7+
* or the Apache License, Version 2.0 which accompanies this distribution and
8+
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9+
*
10+
* This Source Code may also be made available under the following
11+
* Secondary Licenses when the conditions for such availability set
12+
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13+
* General Public License, version 2 with the GNU Classpath
14+
* Exception [1] and GNU General Public License, version 2 with the
15+
* OpenJDK Assembly Exception [2].
16+
*
17+
* [1] https://www.gnu.org/software/classpath/license.html
18+
* [2] https://openjdk.org/legal/assembly-exception.html
19+
*
20+
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
21+
*******************************************************************************/
22+
23+
#ifndef PPCJ9HELPERCALLSNIPPET_INCL
24+
#define PPCJ9HELPERCALLSNIPPET_INCL
25+
26+
#include "codegen/Snippet.hpp"
27+
#include "codegen/PPCHelperCallSnippet.hpp"
28+
#include "env/VMJ9.h"
29+
#include "infra/Annotations.hpp"
30+
#include "p/codegen/PPCInstruction.hpp"
31+
32+
namespace TR { class CodeGenerator; }
33+
34+
namespace TR {
35+
36+
class PPCJ9HelperCallSnippet : public TR::PPCHelperCallSnippet {
37+
int32_t _argSize;
38+
39+
public:
40+
PPCJ9HelperCallSnippet(TR::CodeGenerator *cg, TR::Node *node, TR::LabelSymbol *snippetlab,
41+
TR::SymbolReference *helper, TR::LabelSymbol *restartLabel = NULL, int32_t argSize = -1)
42+
: TR::PPCHelperCallSnippet(cg, node, snippetlab, helper, restartLabel)
43+
, _argSize(argSize)
44+
{}
45+
46+
int32_t getSizeOfArguments() { return _argSize; }
47+
virtual uint8_t *emitSnippetBody();
48+
};
49+
}
50+
51+
#endif

runtime/compiler/p/codegen/PPCPrivateLinkage.cpp

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "il/TreeTop.hpp"
4949
#include "il/TreeTop_inlines.hpp"
5050
#include "p/codegen/CallSnippet.hpp"
51+
#include "p/codegen/PPCJ9HelperCallSnippet.hpp"
5152
#include "p/codegen/GenerateInstructions.hpp"
5253
#include "p/codegen/PPCEvaluator.hpp"
5354
#include "p/codegen/PPCHelperCallSnippet.hpp"
@@ -372,7 +373,7 @@ J9::Power::PrivateLinkage::PrivateLinkage(TR::CodeGenerator *cg)
372373
}
373374
_properties._computedCallTargetRegister = TR::RealRegister::gr0; // gr11 = interface, gr12 = virtual, so we need something else for computed
374375
_properties._vtableIndexArgumentRegister = TR::RealRegister::gr12;
375-
_properties._j9methodArgumentRegister = TR::RealRegister::gr3; // TODO:JSR292: Confirm
376+
_properties._j9methodArgumentRegister = TR::RealRegister::gr11; // TODO:JSR292: Confirm
376377
}
377378

378379
const TR::PPCLinkageProperties& J9::Power::PrivateLinkage::getProperties()
@@ -1466,10 +1467,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
14661467
TR_Array<TR::Register *>& tempLongRegisters = cg()->getTransientLongRegisters();
14671468
TR::MethodSymbol *callSymbol = callNode->getSymbol()->castToMethodSymbol();
14681469

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

14741476
if (rightToLeft)
14751477
{
@@ -1511,6 +1513,11 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15111513
break;
15121514
}
15131515

1516+
if (isJitDispatchJ9Method)
1517+
{
1518+
specialArgReg = getProperties().getJ9MethodArgumentRegister();
1519+
}
1520+
15141521
if (specialArgReg != TR::RealRegister::NoReg)
15151522
{
15161523
if (comp()->getOption(TR_TraceCG))
@@ -1531,6 +1538,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15311538
totalSize += TR::Compiler->om.sizeofReferenceAddress();
15321539
}
15331540

1541+
// will not process special args
15341542
for (int32_t i = from; (rightToLeft && i >= to) || (!rightToLeft && i <= to); i += step)
15351543
{
15361544
child = callNode->getChild(i);
@@ -1585,8 +1593,20 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
15851593
pushToMemory = new (trStackMemory()) TR::PPCMemoryArgument[memArgs];
15861594
}
15871595

1588-
if (specialArgReg)
1596+
if (specialArgReg && !isJitDispatchJ9Method)
1597+
{
15891598
from -= step; // we do want to process special args in the following loop
1599+
}
1600+
else if (specialArgReg && isJitDispatchJ9Method)
1601+
{
1602+
TR::Register *targetReg = cg()->evaluate(callNode->getChild(0));
1603+
dependencies->addPreCondition(targetReg, specialArgReg);
1604+
}
1605+
1606+
if (isJitDispatchJ9Method)
1607+
{
1608+
TR_ASSERT_FATAL(from == step, "should skip first child for jitDispatchJ9Method\n");
1609+
}
15901610

15911611
numIntegerArgs = 0;
15921612
numFloatArgs = 0;
@@ -1611,7 +1631,7 @@ int32_t J9::Power::PrivateLinkage::buildPrivateLinkageArgs(TR::Node
16111631
TR::MemoryReference *mref = NULL;
16121632
TR::Register *argRegister;
16131633
child = callNode->getChild(i);
1614-
bool isSpecialArg = (i == from && specialArgReg != TR::RealRegister::NoReg);
1634+
bool isSpecialArg = (i == from && specialArgReg != TR::RealRegister::NoReg) && !isJitDispatchJ9Method;
16151635
switch (child->getDataType())
16161636
{
16171637
case TR::Int8:
@@ -2868,20 +2888,95 @@ void J9::Power::PrivateLinkage::buildDirectCall(TR::Node *callNode,
28682888
TR::ResolvedMethodSymbol *sym = callSymbol->getResolvedMethodSymbol();
28692889
TR_ResolvedMethod *vmm = (sym==NULL)?NULL:sym->getResolvedMethod();
28702890
bool myself = comp()->isRecursiveMethodTarget(vmm);
2891+
bool isJitDispatchJ9Method = callNode->isJitDispatchJ9MethodCall(comp());
28712892

28722893
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp()->fe());
28732894

2874-
if (callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers)
2895+
if ((callSymRef->getReferenceNumber() >= TR_PPCnumRuntimeHelpers) && !isJitDispatchJ9Method)
28752896
fej9->reserveTrampolineIfNecessary(comp(), callSymRef, false);
28762897

28772898
bool forceUnresolvedDispatch = !fej9->isResolvedDirectDispatchGuaranteed(comp());
2878-
if ((callSymbol->isJITInternalNative() ||
2899+
if (!isJitDispatchJ9Method && (callSymbol->isJITInternalNative() ||
28792900
(!callSymRef->isUnresolved() && !callSymbol->isInterpreted() && ((forceUnresolvedDispatch && callSymbol->isHelper()) || !forceUnresolvedDispatch))))
28802901
{
28812902
gcPoint = generateDepImmSymInstruction(cg(), TR::InstOpCode::bl, callNode,
28822903
myself?0:(uintptr_t)callSymbol->getMethodAddress(),
28832904
dependencies, callSymRef?callSymRef:callNode->getSymbolReference());
28842905
}
2906+
else if (isJitDispatchJ9Method)
2907+
{
2908+
auto flags = pp.getPreservedRegisterMapForGC();
2909+
// we do not want gr11 in the gc map since this will not contain any object reference
2910+
flags ^= 1 << pp.getJ9MethodArgumentRegister();
2911+
2912+
TR::Register *scratchReg = dependencies->searchPostConditionRegister(pp.getVTableIndexArgumentRegister());
2913+
TR::Register *scratchReg2 = cg()->allocateRegister();
2914+
TR::Register *cndReg = dependencies->searchPreConditionRegister(TR::RealRegister::cr0);
2915+
TR::Register *j9MethodReg = callNode->getChild(0)->getRegister();
2916+
2917+
TR::LabelSymbol *startICFLabel = generateLabelSymbol(cg());
2918+
TR::LabelSymbol *doneLabel = generateLabelSymbol(cg());
2919+
TR::LabelSymbol *oolLabel = generateLabelSymbol(cg());
2920+
startICFLabel->setStartInternalControlFlow();
2921+
doneLabel->setEndInternalControlFlow();
2922+
2923+
TR::RegisterDependencyConditions *preDeps = dependencies->clone(cg());
2924+
preDeps->setNumPostConditions(0, trMemory());
2925+
preDeps->setAddCursorForPost(0);
2926+
2927+
TR::RegisterDependencyConditions *newPostDeps = new (trHeapMemory()) TR::RegisterDependencyConditions(0, 2, trMemory());
2928+
newPostDeps->addPostCondition(j9MethodReg, TR::RealRegister::NoReg);
2929+
newPostDeps->addPostCondition(scratchReg2,TR::RealRegister::NoReg);
2930+
2931+
TR::RegisterDependencyConditions *postDeps = dependencies->clone(cg(), newPostDeps);
2932+
postDeps->setNumPreConditions(0, trMemory());
2933+
postDeps->setAddCursorForPre(0);
2934+
2935+
TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg());
2936+
TR::SymbolReference *helperRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_j2iTransition);
2937+
TR::Snippet *interpCallSnippet = new (cg()->trHeapMemory()) TR::PPCJ9HelperCallSnippet(cg(), callNode, snippetLabel, helperRef, doneLabel, argSize);
2938+
interpCallSnippet->gcMap().setGCRegisterMask(flags);
2939+
cg()->addSnippet(interpCallSnippet);
2940+
2941+
TR_PPCOutOfLineCodeSection *snippetCall = new (cg()->trHeapMemory()) TR_PPCOutOfLineCodeSection(oolLabel, doneLabel, cg());
2942+
cg()->getPPCOutOfLineCodeSectionList().push_front(snippetCall);
2943+
snippetCall->swapInstructionListsWithCompilation();
2944+
TR::Instruction *OOLLabelInstr = generateLabelInstruction(cg(), TR::InstOpCode::label, callNode, oolLabel);
2945+
gcPoint = generateDepLabelInstruction(cg(), TR::InstOpCode::bl, callNode, snippetLabel, dependencies);
2946+
gcPoint->PPCNeedsGCMap(flags);
2947+
generateLabelInstruction(cg(), TR::InstOpCode::b, callNode, doneLabel);
2948+
// helper snippet sets up jump back to doneLabel
2949+
snippetCall->swapInstructionListsWithCompilation();
2950+
2951+
generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, startICFLabel, preDeps);
2952+
2953+
// test if compiled
2954+
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, scratchReg,
2955+
TR::MemoryReference::createWithDisplacement(cg(), j9MethodReg, offsetof(J9Method, extra), TR::Compiler->om.sizeofReferenceAddress()));
2956+
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::andi_r, callNode, scratchReg2, scratchReg, 1);
2957+
// branch to ool if J9_STARTPC_NOT_TRANSLATED is set
2958+
gcPoint = generateConditionalBranchInstruction(cg(), TR::InstOpCode::bne, callNode, oolLabel, cndReg);
2959+
gcPoint->PPCNeedsGCMap(flags);
2960+
2961+
// compiled - jump to jit entry point
2962+
generateTrg1MemInstruction(cg(), TR::InstOpCode::Op_load, callNode, j9MethodReg,
2963+
TR::MemoryReference::createWithDisplacement(cg(), scratchReg, -4, TR::Compiler->om.sizeofReferenceAddress()));
2964+
generateTrg1Src1ImmInstruction(cg(), TR::InstOpCode::srawi, callNode, j9MethodReg, j9MethodReg, 16);
2965+
if (comp()->target().is64Bit())
2966+
{
2967+
generateTrg1Src1Instruction(cg(), TR::InstOpCode::extsw, callNode, j9MethodReg, j9MethodReg);
2968+
}
2969+
generateTrg1Src2Instruction(cg(), TR::InstOpCode::add, callNode, scratchReg, j9MethodReg, scratchReg);
2970+
generateSrc1Instruction(cg(), TR::InstOpCode::mtctr, callNode, scratchReg);
2971+
gcPoint = generateInstruction(cg(), TR::InstOpCode::bctrl, callNode);
2972+
gcPoint->PPCNeedsGCMap(flags);
2973+
2974+
cg()->stopUsingRegister(scratchReg);
2975+
cg()->stopUsingRegister(scratchReg2);
2976+
cg()->stopUsingRegister(cndReg);
2977+
generateDepLabelInstruction(cg(), TR::InstOpCode::label, callNode, doneLabel, postDeps);
2978+
return;
2979+
}
28852980
else
28862981
{
28872982
TR::LabelSymbol *label = generateLabelSymbol(cg());

0 commit comments

Comments
 (0)