Skip to content

Commit

Permalink
Fix VP constraint for null-restricted array class
Browse files Browse the repository at this point in the history
If null-restricted array is enabled and the class is an array class,
the null-restricted array class and the nullable array class share
the same signature. The null-restricted array can be viewed
as a sub-type of the nullable array. Therefore, the constraint cannot
be fixed class.

Related: eclipse-openj9/openj9#20522
Signed-off-by: Annabelle Huo <[email protected]>
  • Loading branch information
a7ehuo committed Dec 11, 2024
1 parent 7fe2fcc commit 2cb7621
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
16 changes: 14 additions & 2 deletions compiler/optimizer/VPConstraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,15 @@ TR::VPClassType *TR::VPClassType::create(OMR::ValuePropagation *vp, const char *
return TR::VPUnresolvedClass::create(vp, sig, len, method);
}

static bool canBaseClassBeTrusted(TR_OpaqueClassBlock *baseClass)
{
#ifdef J9_PROJECT_SPECIFIC
if (TR::Compiler->om.areFlattenableValueTypesEnabled() && TR::Compiler->cls.isValueTypeClass(baseClass))
return false;
#endif
return true;
}

TR::VPResolvedClass *TR::VPResolvedClass::create(OMR::ValuePropagation *vp, TR_OpaqueClassBlock *klass)
{
// If the class is final, we really want to make this a fixed class
Expand All @@ -1284,9 +1293,12 @@ TR::VPResolvedClass *TR::VPResolvedClass::create(OMR::ValuePropagation *vp, TR_O
if (TR::Compiler->cls.isClassArray(vp->comp(), klass))
{
// An array class is fixed if the base class for the array is final
// But if null-restricted array is enabled and the class is an array class, the null-restricted array
// class and the nullable array class share the same signature. The null-restricted array can be viewed
// as a sub-type of the nullable array. Therefore, the constraint cannot be fixed class.
//
TR_OpaqueClassBlock * baseClass = vp->fe()->getLeafComponentClassFromArrayClass(klass);
if (baseClass && TR::Compiler->cls.isClassFinal(vp->comp(), baseClass))
if (baseClass && TR::Compiler->cls.isClassFinal(vp->comp(), baseClass) && canBaseClassBeTrusted(baseClass))
return TR::VPFixedClass::create(vp, klass);
}
else
Expand Down Expand Up @@ -6078,7 +6090,7 @@ void TR::VPResolvedClass::print(TR::Compilation *comp, TR::FILE *outFile)
len = static_cast<int32_t>(strlen(sig));
}

trfprintf(outFile, "class %.*s", len, sig);
trfprintf(outFile, "class 0x%p %.*s", _class, len, sig);
if (_typeHintClass)
{
trfprintf(outFile, " (hint 0x%p", _typeHintClass);
Expand Down
41 changes: 40 additions & 1 deletion compiler/optimizer/VPHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,42 @@
extern TR::Node *constrainChildren(OMR::ValuePropagation *vp, TR::Node *node);
extern TR::Node *constrainVcall(OMR::ValuePropagation *vp, TR::Node *node);

static bool canTrustAsFixedClass(OMR::ValuePropagation *vp, TR::SymbolReference *symRef, TR_OpaqueClassBlock *classObject)
{
#ifdef J9_PROJECT_SPECIFIC
if (!TR::Compiler->om.areFlattenableValueTypesEnabled())
return true;

if ((classObject == NULL) && symRef && symRef->getSymbol()->isClassObject())
{
if (!symRef->isUnresolved())
{
classObject = (TR_OpaqueClassBlock*)symRef->getSymbol()->getStaticSymbol()->getStaticAddress();
}
else
{
int32_t len;
const char *name = TR::Compiler->cls.classNameChars(vp->comp(), symRef, len);
char *sig = TR::Compiler->cls.classNameToSignature(name, len, vp->comp());
classObject = vp->fe()->getClassFromSignature(sig, len, symRef->getOwningMethod(vp->comp()));
}
}

if (classObject)
{
// If null-restricted array is enabled and the class is an array class, the null-restricted array
// class and the nullable array class share the same signature. The null-restricted array can be viewed
// as a sub-type of the nullable array. Therefore, the constraint cannot be fixed class.
int32_t numDims = 0;
TR_OpaqueClassBlock *klass = vp->comp()->fej9()->getBaseComponentClass(classObject, numDims);

if ((numDims > 0) && TR::Compiler->cls.isValueTypeClass(klass))
return false;
}
#endif
return true;
}

static void checkForNonNegativeAndOverflowProperties(OMR::ValuePropagation *vp, TR::Node *node, TR::VPConstraint *constraint = NULL)
{
if (!constraint)
Expand Down Expand Up @@ -1938,6 +1974,7 @@ TR::Node *constrainAload(OMR::ValuePropagation *vp, TR::Node *node)
{
if (classBlock != jlClass)
{
isFixed = isFixed ? canTrustAsFixedClass(vp, NULL, classBlock) : isFixed;
constraint = TR::VPClassType::create(vp, sig, len, owningMethod, isFixed, classBlock);
if (*sig == '[' || sig[0] == 'L')
{
Expand Down Expand Up @@ -11207,9 +11244,11 @@ static void constrainClassObjectLoadaddr(
"constrainClassObjectLoadaddr: n%un loadaddr is not for a class\n",
node->getGlobalIndex());

bool isFixed = canTrustAsFixedClass(vp, symRef, NULL);

TR::VPConstraint *constraint = TR::VPClass::create(
vp,
TR::VPClassType::create(vp, symRef, true),
TR::VPClassType::create(vp, symRef, isFixed),
TR::VPNonNullObject::create(vp),
NULL,
NULL,
Expand Down

0 comments on commit 2cb7621

Please sign in to comment.