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
378379const 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