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