Skip to content

Commit

Permalink
Merge pull request #3 from hzongaro/inline-getcomponentclass
Browse files Browse the repository at this point in the history
Inline java.lang.Class.getComponentType() in Value Propagation
  • Loading branch information
nbhuiyan authored May 1, 2024
2 parents 383bb66 + 4385039 commit a988445
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 5 deletions.
37 changes: 34 additions & 3 deletions runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,28 @@ TR_J9VMBase::testAreSomeClassFlagsSet(TR::Node *j9ClassRefNode, uint32_t flagsTo
return maskedFlags;
}

TR::Node *
TR_J9VMBase::testAreSomeClassAndDepthFlagsSet(TR::Node *j9ClassRefNode, uint32_t flagsToTest)
{
TR::SymbolReference *classAndDepthFlagsSymRef = TR::comp()->getSymRefTab()->findOrCreateClassAndDepthFlagsSymbolRef();
TR::Node *classFlags = NULL;

if (TR::comp()->target().is32Bit())
{
classFlags = TR::Node::createWithSymRef(TR::iloadi, 1, 1, j9ClassRefNode, classAndDepthFlagsSymRef);
}
else
{
classFlags = TR::Node::createWithSymRef(TR::lloadi, 1, 1, j9ClassRefNode, classAndDepthFlagsSymRef);
classFlags = TR::Node::create(TR::l2i, 1, classFlags);
}

TR::Node *maskedFlags = TR::Node::create(TR::iand, 2, classFlags, TR::Node::iconst(j9ClassRefNode, flagsToTest));

return maskedFlags;
}


TR::Node *
TR_J9VMBase::testIsClassValueType(TR::Node *j9ClassRefNode)
{
Expand All @@ -2902,13 +2924,21 @@ TR_J9VMBase::testIsClassIdentityType(TR::Node *j9ClassRefNode)
}

TR::Node *
TR_J9VMBase::checkSomeArrayCompClassFlags(TR::Node *arrayBaseAddressNode, TR::ILOpCodes ifCmpOp, uint32_t flagsToTest)
TR_J9VMBase::loadArrayClassComponentType(TR::Node *j9ClassRefNode)
{
TR::SymbolReference *vftSymRef = TR::comp()->getSymRefTab()->findOrCreateVftSymbolRef();
TR::SymbolReference *arrayCompSymRef = TR::comp()->getSymRefTab()->findOrCreateArrayComponentTypeSymbolRef();
TR::Node *arrayCompClass = TR::Node::createWithSymRef(TR::aloadi, 1, 1, j9ClassRefNode, arrayCompSymRef);

return arrayCompClass;
}

TR::Node *
TR_J9VMBase::checkSomeArrayCompClassFlags(TR::Node *arrayBaseAddressNode, TR::ILOpCodes ifCmpOp, uint32_t flagsToTest)
{
TR::SymbolReference *vftSymRef = TR::comp()->getSymRefTab()->findOrCreateVftSymbolRef();
TR::Node *vft = TR::Node::createWithSymRef(TR::aloadi, 1, 1, arrayBaseAddressNode, vftSymRef);
TR::Node *arrayCompClass = TR::Node::createWithSymRef(TR::aloadi, 1, 1, vft, arrayCompSymRef);

TR::Node *arrayCompClass = loadArrayClassComponentType(vft);
TR::Node *maskedFlagsNode = testAreSomeClassFlagsSet(arrayCompClass, flagsToTest);
TR::Node *ifNode = TR::Node::createif(ifCmpOp, maskedFlagsNode, TR::Node::iconst(arrayBaseAddressNode, 0));

Expand Down Expand Up @@ -7642,6 +7672,7 @@ TR_J9VM::inlineNativeCall(TR::Compilation * comp, TR::TreeTop * callNodeTreeTop,
TR::Node::recreate(callNode, TR::aloadi);
callNode->setSymbolReference(comp->getSymRefTab()->findOrCreateVftSymbolRef());
callNode = TR::Node::createWithSymRef(TR::aloadi, 1, 1, callNode, comp->getSymRefTab()->findOrCreateJavaLangClassFromClassSymbolRef());
callNode->setIsNonNull(true);
return callNode;

// Note: these cases are not tested and thus are commented out:
Expand Down
4 changes: 4 additions & 0 deletions runtime/compiler/env/VMJ9.h
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,8 @@ class TR_J9VMBase : public TR_FrontEnd
*/
TR::Node * testAreSomeClassFlagsSet(TR::Node *j9ClassRefNode, uint32_t flagsToTest);

TR::Node * testAreSomeClassAndDepthFlagsSet(TR::Node *j9ClassRefNode, uint32_t flagsToTest);

/**
* \brief Load class flags field of the specified class and test whether the value type
* flag is set.
Expand Down Expand Up @@ -1290,6 +1292,8 @@ class TR_J9VMBase : public TR_FrontEnd
*/
TR::Node * testIsClassIdentityType(TR::Node *j9ClassRefNode);

TR::Node * loadArrayClassComponentType(TR::Node *j9ClassRefNode);

/**
* \brief Test whether any of the specified flags is set on the array's component class
* \param arrayBaseAddressNode A node representing a reference to the array base address
Expand Down
66 changes: 64 additions & 2 deletions runtime/compiler/optimizer/J9ValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1691,8 +1691,11 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node)
TR::Node *classChild = node->getLastChild();
bool classChildGlobal;
TR::VPConstraint *classChildConstraint = getConstraint(classChild, classChildGlobal);
if (classChildConstraint && classChildConstraint->isJavaLangClassObject() == TR_yes
&& classChildConstraint->isNonNullObject()
bool isNonNullJavaLangClass = classChildConstraint
&& classChildConstraint->isJavaLangClassObject() == TR_yes
&& classChildConstraint->isNonNullObject();

if (isNonNullJavaLangClass
&& classChildConstraint->getClassType()
&& classChildConstraint->getClassType()->asFixedClass())
{
Expand Down Expand Up @@ -1748,6 +1751,65 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node)
return;
}
}
else if (isNonNullJavaLangClass)
{
if (!performTransformation(comp(), "%sTransforming %s on node %p to load component type inline\n", OPT_DETAILS, signature, node))
break;

// Consider two cases:
//
// (i) The operand is an instance of java.lang.Class indirectly loaded through a vft. In that case,
// we can work with the vft directly
// (ii) The operand is definitely a non-null instance of java.lang.Class. In that case, load the
// J9Class from the java.lang.Class by way of <classFromJavaLangClass>
//

TR::SymbolReference *symRef = classChild->getOpCode().hasSymbolReference() ? classChild->getSymbolReference() : NULL;
TR::SymbolReference *jlcFromClassSymRef = comp()->getSymRefTab()->findOrCreateJavaLangClassFromClassSymbolRef();
TR::Node *classOperand = NULL;

if ((symRef != NULL) && (symRef == jlcFromClassSymRef))
{
classOperand = classChild->getFirstChild();
}
else
{
classOperand = TR::Node::createWithSymRef(TR::aloadi, 1, 1, classChild,
comp()->getSymRefTab()->findOrCreateClassFromJavaLangClassSymbolRef());
}

TR::Node *loadComponentTypeNode = comp()->fej9()->loadArrayClassComponentType(classOperand);
TR::Node *jlcOfComponentTypeNode = NULL;

if ((classChildConstraint == NULL)
|| (classChildConstraint->getClassType() == NULL)
|| !comp()->fej9()->isClassArray(classChildConstraint->getClass()))
{
TR::Node *testIsArrayClassNode =
TR::Node::create(node, TR::icmpne, 2,
comp()->fej9()->testAreSomeClassAndDepthFlagsSet(classOperand, comp()->fej9()->getFlagValueForArrayCheck()),
TR::Node::iconst(node, 0));
loadComponentTypeNode =
TR::Node::create(TR::aselect, 3,
testIsArrayClassNode,
loadComponentTypeNode,
classOperand);
loadComponentTypeNode =
TR::Node::createWithSymRef(node, TR::aloadi, 1, loadComponentTypeNode, jlcFromClassSymRef);
jlcOfComponentTypeNode =
TR::Node::create(TR::aselect, 3,
testIsArrayClassNode,
loadComponentTypeNode,
TR::Node::aconst(node, 0));
}
else
{
jlcOfComponentTypeNode =
TR::Node::createWithSymRef(node, TR::aloadi, 1, loadComponentTypeNode, jlcFromClassSymRef);
}

transformCallToNodeDelayedTransformations(_curTree, jlcOfComponentTypeNode, false);
}
break;
}
case TR::java_lang_J9VMInternals_getSuperclass:
Expand Down

0 comments on commit a988445

Please sign in to comment.