Skip to content

Commit

Permalink
Update System.arraycopy to support null restricted value type arrays
Browse files Browse the repository at this point in the history
Required by JEP 401: If null restricted value type is enabled,
we need to preform null check on the value being stored in order to
throw a `NullPointerException` if the array is null-restricted
and the value to write is null. If it is this case,
`System.arraycopy` cannot be transformed into arraycopy instructions.

Based on whether or not the source array and the destination array
are null restricted value type, and whether or not they are flattened,
VP decides whether or not transform `System.arraycopy`.

Fixes: eclipse-openj9/openj9#17196,eclipse-openj9/openj9#17586

Signed-off-by: Annabelle Huo <[email protected]>
  • Loading branch information
a7ehuo committed Aug 22, 2023
1 parent 43a2b1d commit 71ddb70
Show file tree
Hide file tree
Showing 5 changed files with 656 additions and 10 deletions.
24 changes: 24 additions & 0 deletions compiler/env/OMRClassEnv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ class OMR_EXTENSIBLE ClassEnv
bool isAnonymousClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz) { return false; }
bool isValueTypeClass(TR_OpaqueClassBlock *) { return false; }

/** \brief
* Returns the size of the flattened array element
*
* When array elements are flattened, the array element is inlined into the array. For example,
* Class Point {
* int x;
* int y;
* }
* Point pointArray[];
*
* If pointArray is not flattened, the size of pointArray[i] is the size of the reference pointer size.
* If pointArray is flattened, the size of pointArray[i] is the total size of x and y and plus padding if there is any.
*
* \param comp
* The compilation object
*
* \param arrayClass
* The array class that is to be checked
*
* \return
* Size of the flattened array element
*/
int32_t flattenedArrayElementSize(TR::Compilation *comp, TR_OpaqueClassBlock *arrayClass) { return 0; }

/**
* \brief
* Checks whether instances of the specified class can be trivially initialized by
Expand Down
8 changes: 8 additions & 0 deletions compiler/env/OMRObjectModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ class ObjectModel
bool mayRequireSpineChecks() { return false; }

bool areValueTypesEnabled() { return false; }
/**
* @brief: Returns true if flattenable value type is enabled
*/
bool areFlattenableValueTypesEnabled() { return false; }
/**
* @brief: Returns true if value type array element flattening is enabled
*/
bool isValueTypeArrayFlatteningEnabled() { return false; }

bool generateCompressedObjectHeaders() { return false; }

Expand Down
36 changes: 33 additions & 3 deletions compiler/optimizer/OMRValuePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1690,11 +1690,15 @@ TR_YesNoMaybe OMR::ValuePropagation::isCastClassObject(TR::VPClassType *type)
}


TR_YesNoMaybe OMR::ValuePropagation::isArrayCompTypeValueType(TR::VPConstraint *arrayConstraint)
TR_YesNoMaybe OMR::ValuePropagation::isArrayCompTypePrimitiveValueType(TR::VPConstraint *arrayConstraint)
{
return TR::Compiler->om.areValueTypesEnabled() ? TR_maybe : TR_no;
return TR::Compiler->om.areFlattenableValueTypesEnabled() ? TR_maybe : TR_no;
}

TR_YesNoMaybe OMR::ValuePropagation::isArrayElementFlattened(TR::VPConstraint *arrayConstraint)
{
return (TR::Compiler->om.areFlattenableValueTypesEnabled() && TR::Compiler->om.isValueTypeArrayFlatteningEnabled()) ? TR_maybe : TR_no;
}

bool OMR::ValuePropagation::isArrayStoreCheckNeeded(TR::Node *arrayRef, TR::Node *objectRef, bool &mustFail,
TR_OpaqueClassBlock* &storeClassForCheck, TR_OpaqueClassBlock* &componentClassForCheck)
Expand Down Expand Up @@ -7283,7 +7287,6 @@ void OMR::ValuePropagation::doDelayedTransformations()
for (converterCallTree = convIt.getFirst();
converterCallTree; converterCallTree = convIt.getNext())
{

transformConverterCall(converterCallTree);
}
_converterCalls.deleteAll();
Expand Down Expand Up @@ -7355,6 +7358,33 @@ void OMR::ValuePropagation::doDelayedTransformations()
}
_needMultiLeafArrayCopy.deleteAll();
}

if (TR::Compiler->om.areFlattenableValueTypesEnabled())
{
ListIterator<TR_NeedRuntimeTestNullRestrictedArrayCopy> tt(&_needRuntimeTestNullRestrictedArrayCopy);
TR_NeedRuntimeTestNullRestrictedArrayCopy *nullRestrictedArrayCopyTree;

for (nullRestrictedArrayCopyTree = tt.getFirst();
nullRestrictedArrayCopyTree; nullRestrictedArrayCopyTree = tt.getNext())
{
if (trace())
{
TR::CFG *cfg = comp()->getFlowGraph();
comp()->dumpMethodTrees("Trees before transformNullRestrictedArrayCopy");
comp()->getDebug()->print(comp()->getOutFile(), cfg);
}

transformNullRestrictedArrayCopy(nullRestrictedArrayCopyTree);

if (trace())
{
TR::CFG *cfg = comp()->getFlowGraph();
comp()->dumpMethodTrees("Trees after transformNullRestrictedArrayCopy");
comp()->getDebug()->print(comp()->getOutFile(), cfg);
}
}
_needRuntimeTestNullRestrictedArrayCopy.deleteAll();
}
#endif

int32_t i;
Expand Down
49 changes: 44 additions & 5 deletions compiler/optimizer/OMRValuePropagation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,14 +367,27 @@ class ValuePropagation : public TR::Optimization
TR_YesNoMaybe isCastClassObject(TR::VPClassType *type);

/**
* Determine whether the component type of an array is, or might be, a value
* Determine whether the component type of an array is, or might be, a primitive value
* type.
* \param arrayConstraint The \ref TR::VPConstraint type constraint for the array reference
* \return \c TR_yes if the array's component type is definitely a value type;\n
* \c TR_no if it is definitely not a value type; or\n
* \c TR_maybe otherwise.
* \returns \c TR_yes if the array's component type is definitely a primitive value type;\n
* \c TR_no if it is definitely not a primitive value type; or\n
* \c TR_maybe otherwise.
*/
virtual TR_YesNoMaybe isArrayCompTypeValueType(TR::VPConstraint *arrayConstraint);
virtual TR_YesNoMaybe isArrayCompTypePrimitiveValueType(TR::VPConstraint *arrayConstraint);

/**
* \brief
* Determines whether the array element is, or might be, flattened.
*
* \param arrayConstraint
* The \ref TR::VPConstraint type constraint for the array reference.
*
* \returns \c TR_yes if the array element is flattened;\n
* \c TR_no if it is definitely not flattened; or\n
* \c TR_maybe otherwise.
*/
virtual TR_YesNoMaybe isArrayElementFlattened(TR::VPConstraint *arrayConstraint);

/**
* Determine whether assignment of the supplied object reference to an element of the
Expand Down Expand Up @@ -599,6 +612,29 @@ class ValuePropagation : public TR::Optimization
TR::SymbolReference *_arraycopySymRef;
};

struct TR_NeedRuntimeTestNullRestrictedArrayCopy
{
TR_ALLOC(TR_Memory::ValuePropagation)

TR_NeedRuntimeTestNullRestrictedArrayCopy(TR::Node *dstArrRef, TR::Node *srcArrRef,
TR::TreeTop *ptt, TR::TreeTop *ntt,
TR::Block *originBlock, TR::Block *slowBlock,
bool testDstArray)
: _dstArrayRefNode(dstArrRef), _srcArrayRefNode(srcArrRef), _prevTT(ptt), _nextTT(ntt), _originBlock(originBlock), _slowBlock(slowBlock), _needRuntimeTestDstArray(testDstArray)
{}

TR::Node *_dstArrayRefNode;
TR::Node *_srcArrayRefNode;

TR::TreeTop *_prevTT;
TR::TreeTop *_nextTT;

TR::Block *_originBlock;
TR::Block *_slowBlock;

bool _needRuntimeTestDstArray;
};

TR::TreeTop *createPrimitiveOrReferenceCompareNode(TR::Node *);
TR::TreeTop *createArrayStoreCompareNode(TR::Node *, TR::Node *);

Expand Down Expand Up @@ -662,6 +698,8 @@ class ValuePropagation : public TR::Optimization

#ifdef J9_PROJECT_SPECIFIC
void transformRTMultiLeafArrayCopy(TR_RealTimeArrayCopy *rtArrayCopyTree);

void transformNullRestrictedArrayCopy(TR_NeedRuntimeTestNullRestrictedArrayCopy *nullRestrictedArrayCopyTree);
#endif

TR::TreeTop *buildSameLeafTest(TR::Node *offset,TR::Node *len,TR::Node *spineShiftNode);
Expand Down Expand Up @@ -952,6 +990,7 @@ class ValuePropagation : public TR::Optimization
List<TR_TreeTopWrtBarFlag> _referenceArrayCopyTrees;
List<TR_RealTimeArrayCopy> _needRunTimeCheckArrayCopy;
List<TR_RealTimeArrayCopy> _needMultiLeafArrayCopy;
List<TR_NeedRuntimeTestNullRestrictedArrayCopy> _needRuntimeTestNullRestrictedArrayCopy;
List<TR_ArrayCopySpineCheck> _arrayCopySpineCheck;
List<TR::TreeTop> _multiLeafCallsToInline;
List<TR_TreeTopNodePair> _scalarizedArrayCopies;
Expand Down
Loading

0 comments on commit 71ddb70

Please sign in to comment.