@@ -9807,6 +9807,195 @@ static TR::Register *inlineAtomicOperation(TR::Node *node, TR::CodeGenerator *cg
9807
9807
return resultReg;
9808
9808
}
9809
9809
9810
+ // duplicate from the static method in Z
9811
+ static TR::SymbolReference *getClassSymRefAndDepth(TR::Node *classNode,
9812
+ TR::Compilation *comp, int32_t &classDepth)
9813
+ {
9814
+ classDepth = -1;
9815
+ TR::SymbolReference *classSymRef = NULL;
9816
+ const TR::ILOpCodes opcode = classNode->getOpCodeValue();
9817
+ bool isClassNodeLoadAddr = opcode == TR::loadaddr;
9818
+
9819
+ // getting the symbol ref
9820
+ if (isClassNodeLoadAddr)
9821
+ {
9822
+ classSymRef = classNode->getSymbolReference();
9823
+ }
9824
+ else if (opcode == TR::aloadi)
9825
+ {
9826
+ // recognizedCallTransformer adds another layer of aloadi
9827
+ while (classNode->getOpCodeValue() == TR::aloadi && classNode->getFirstChild()->getOpCodeValue() == TR::aloadi)
9828
+ {
9829
+ classNode = classNode->getFirstChild();
9830
+ }
9831
+
9832
+ if (classNode->getOpCodeValue() == TR::aloadi && classNode->getFirstChild()->getOpCodeValue() == TR::loadaddr)
9833
+ {
9834
+ classSymRef = classNode->getFirstChild()->getSymbolReference();
9835
+ }
9836
+ }
9837
+
9838
+ // the class node being <loadaddr> is an edge case - likely will not happen since we shouldn't see
9839
+ // Class.isAssignableFrom on classes known at compile (javac) time, but still possible.
9840
+ if (!isClassNodeLoadAddr && (classNode->getOpCodeValue() != TR::aloadi ||
9841
+ classNode->getSymbolReference() != comp->getSymRefTab()->findJavaLangClassFromClassSymbolRef() ||
9842
+ classNode->getFirstChild()->getOpCodeValue() != TR::loadaddr))
9843
+ {
9844
+ return classSymRef; // cannot find class depth
9845
+ }
9846
+
9847
+ TR::Node *classRef = isClassNodeLoadAddr ? classNode : classNode->getFirstChild();
9848
+ TR::SymbolReference *symRef = classRef->getOpCode().hasSymbolReference() ? classRef->getSymbolReference() : NULL;
9849
+
9850
+ if (symRef != NULL && !symRef->isUnresolved())
9851
+ {
9852
+ TR::StaticSymbol *classSym = symRef->getSymbol()->getStaticSymbol();
9853
+ TR_OpaqueClassBlock *clazz = (classSym != NULL) ? (TR_OpaqueClassBlock *) classSym->getStaticAddress() : NULL;
9854
+ if (clazz != NULL)
9855
+ classDepth = static_cast<int32_t>(TR::Compiler->cls.classDepthOf(clazz));
9856
+ }
9857
+
9858
+ return classSymRef;
9859
+ }
9860
+
9861
+ static TR::Register *inlineCheckAssignableFromEvaluator(TR::Node *node, TR::CodeGenerator *cg)
9862
+ {
9863
+ TR::Compilation *comp = cg->comp();
9864
+
9865
+ // original form: toClass.isAssignableFrom(fromClass)
9866
+ TR::Node *fromClass = node->getFirstChild();
9867
+ TR::Node *toClass = node->getSecondChild();
9868
+
9869
+ TR::Register *fromClassReg = cg->evaluate(fromClass);
9870
+ TR::Register *toClassReg = cg->evaluate(toClass);
9871
+
9872
+ TR::Register *cacheReg = cg->allocateRegister();
9873
+
9874
+ TR::Register *condReg = cg->allocateRegister(TR_CCR);
9875
+
9876
+ TR::Register *resultReg = cg->allocateRegister();
9877
+
9878
+ TR::LabelSymbol *startLabel = generateLabelSymbol(cg);
9879
+ TR::LabelSymbol *oolJumpLabel = generateLabelSymbol(cg);
9880
+ TR::LabelSymbol *endLabel = generateLabelSymbol(cg);
9881
+
9882
+ TR::LabelSymbol *failLabel = generateLabelSymbol(cg);
9883
+ TR::LabelSymbol *successLabel = endLabel;
9884
+
9885
+ TR_PPCScratchRegisterManager *srm = cg->generateScratchRegisterManager();
9886
+
9887
+ // jump to the out of line code if inlined code cannot handle it
9888
+ TR_PPCOutOfLineCodeSection *outlinedHelperCall = new (cg->trHeapMemory())
9889
+ TR_PPCOutOfLineCodeSection(node, TR::icall, resultReg, oolJumpLabel, endLabel, cg);
9890
+ cg->getPPCOutOfLineCodeSectionList().push_front(outlinedHelperCall);
9891
+
9892
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, startLabel);
9893
+ startLabel->setStartInternalControlFlow();
9894
+
9895
+ // Checking at compile time if possible.
9896
+ int32_t toClassDepth = -1;
9897
+ TR::SymbolReference *toClassSymRef = getClassSymRefAndDepth(toClass, comp, toClassDepth);
9898
+ bool fastFail = false;
9899
+ if (comp->getOption(TR_TraceCG))
9900
+ {
9901
+ traceMsg(comp, "%s: toClassSymRef is %s\n", node->getOpCode().getName(),
9902
+ NULL == toClassSymRef ? "null" : "non-null");
9903
+ if (toClassSymRef)
9904
+ {
9905
+ traceMsg(comp, "%s: toClass is %s, %s, %s\n", node->getOpCode().getName(),
9906
+ toClassSymRef->isClassInterface(comp) ? "an interface" : "not an interface",
9907
+ toClassSymRef->isClassAbstract(comp) ? "abstract" : "non-abstract");
9908
+ }
9909
+ }
9910
+ if ((NULL != toClassSymRef) && !toClassSymRef->isClassInterface(comp))
9911
+ {
9912
+ int32_t fromClassDepth = -1;
9913
+ TR::SymbolReference *fromClassSymRef = getClassSymRefAndDepth(fromClass, comp, fromClassDepth);
9914
+ if (comp->getOption(TR_TraceCG))
9915
+ {
9916
+ traceMsg(comp, "%s: fromClassSymRef is %s\n", node->getOpCode().getName(),
9917
+ NULL == fromClassSymRef ? "null" : "non-null");
9918
+ if (fromClassSymRef)
9919
+ {
9920
+ traceMsg(comp, "%s: fromClass is %s, %s, %s\n", node->getOpCode().getName(),
9921
+ fromClassSymRef->isClassInterface(comp) ? "an interface" : "not an interface",
9922
+ fromClassSymRef->isClassAbstract(comp) ? "abstract" : "non-abstract");
9923
+ }
9924
+ }
9925
+ if ((NULL != fromClassSymRef) && !fromClassSymRef->isClassInterface(comp))
9926
+ {
9927
+ if (comp->getOption(TR_TraceCG))
9928
+ traceMsg(comp, "depths %d %d\n", toClassDepth, fromClassDepth);
9929
+ if (toClassDepth > -1 && fromClassDepth > -1 && toClassDepth > fromClassDepth)
9930
+ {
9931
+ // fall into the failLabel
9932
+ fastFail = true;
9933
+ }
9934
+ }
9935
+ }
9936
+
9937
+ if (!fastFail) // generate the inline tests if we cannot figure it out on compile time
9938
+ {
9939
+ generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, resultReg, 0x777); // eyecatcher
9940
+ // default to success
9941
+ generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, resultReg, 1);
9942
+
9943
+ // equality test
9944
+ generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, node, condReg, fromClassReg, toClassReg);
9945
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, successLabel, condReg);
9946
+
9947
+ // castClassCache test
9948
+ if ((NULL == toClassSymRef) || (!toClassSymRef->isClassAbstract(comp)))
9949
+ {
9950
+ generateTrg1MemInstruction(cg,TR::InstOpCode::Op_load, node, cacheReg,
9951
+ TR::MemoryReference::createWithDisplacement(cg, fromClassReg,
9952
+ offsetof(J9Class, castClassCache), TR::Compiler->om.sizeofReferenceAddress()));
9953
+ generateTrg1Src2Instruction(cg,TR::InstOpCode::Op_cmpl, node, condReg, cacheReg, toClassReg);
9954
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, successLabel, condReg);
9955
+ }
9956
+
9957
+ // superClass test
9958
+ if ((NULL == toClassSymRef) || (!toClassSymRef->isClassInterface(comp)))
9959
+ {
9960
+ genInstanceOfOrCheckCastSuperClassTest(node, condReg, fromClassReg, toClassReg,
9961
+ toClassDepth, oolJumpLabel, srm, cg);
9962
+ generateConditionalBranchInstruction(cg, TR::InstOpCode::beq, node, successLabel, condReg);
9963
+ }
9964
+ // fallback to the helper
9965
+ generateLabelInstruction(cg, TR::InstOpCode::b, node, oolJumpLabel);
9966
+ }
9967
+
9968
+ generateLabelInstruction(cg, TR::InstOpCode::label, node, failLabel);
9969
+ generateTrg1ImmInstruction(cg, TR::InstOpCode::li, node, resultReg, 0);
9970
+
9971
+ srm->stopUsingRegisters();
9972
+ cg->stopUsingRegister(fromClassReg);
9973
+ cg->stopUsingRegister(toClassReg);
9974
+ cg->stopUsingRegister(cacheReg);
9975
+
9976
+ const short numReg = 4 + srm->numAvailableRegisters();
9977
+ TR::RegisterDependencyConditions *dependencies =
9978
+ new (cg->trHeapMemory()) TR::RegisterDependencyConditions(0,
9979
+ numReg, cg->trMemory());
9980
+
9981
+ srm->addScratchRegistersToDependencyList(dependencies);
9982
+
9983
+ dependencies->addPostCondition(fromClassReg, TR::RealRegister::NoReg);
9984
+ dependencies->addPostCondition(toClassReg, TR::RealRegister::NoReg);
9985
+ dependencies->addPostCondition(cacheReg, TR::RealRegister::NoReg);
9986
+ dependencies->addPostCondition(resultReg, TR::RealRegister::NoReg);
9987
+
9988
+ for (int i = 0; i < numReg; i++) {
9989
+ dependencies->getPostConditions()->getRegisterDependency(i)->setExcludeGPR0();
9990
+ }
9991
+
9992
+ generateDepLabelInstruction(cg, TR::InstOpCode::label, node, endLabel, dependencies);
9993
+
9994
+ endLabel->setEndInternalControlFlow();
9995
+ node->setRegister(resultReg);
9996
+ return resultReg;
9997
+ }
9998
+
9810
9999
static TR::Register *inlineConcurrentLinkedQueueTMOffer(TR::Node *node, TR::CodeGenerator *cg)
9811
10000
{
9812
10001
TR::Compilation *comp = cg->comp();
@@ -12495,6 +12684,16 @@ J9::Power::CodeGenerator::inlineDirectCall(TR::Node *node, TR::Register *&result
12495
12684
{
12496
12685
return true;
12497
12686
}
12687
+ else if (node->getSymbolReference()->getReferenceNumber() == TR_checkAssignable)
12688
+ {
12689
+ if (comp->getOption(TR_TraceCG))
12690
+ {
12691
+ printf("LkL inlining\n");
12692
+ resultReg = inlineCheckAssignableFromEvaluator(node, cg);
12693
+ return true;
12694
+ }
12695
+ return false;
12696
+ }
12498
12697
else if (methodSymbol)
12499
12698
{
12500
12699
bool disableCASInlining = !cg->getSupportsInlineUnsafeCompareAndSet();
0 commit comments