Skip to content

Commit

Permalink
Inline java.lang.Class.getComponentType() in Value Propagation
Browse files Browse the repository at this point in the history
Also, mark result of inlined code for Object.getClass() as non-null.
  • Loading branch information
hzongaro committed Apr 25, 2024
1 parent 4998aab commit 4385039
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 4385039

Please sign in to comment.