From e76675526bac40b6962133701dabbbfebaf82321 Mon Sep 17 00:00:00 2001 From: Shubham Verma Date: Sat, 5 Aug 2023 12:13:39 -0400 Subject: [PATCH] Add APIs to help with array access New APIs are: `generateDataAddrLoadTrees` `generateArrayAddressNode` `generateArrayStartTrees` `generateOffsetNode` Signed-off-by: Shubham Verma --- .../compiler/optimizer/J9TransformUtil.cpp | 93 +++++++++++++++++++ .../compiler/optimizer/J9TransformUtil.hpp | 86 ++++++++++++++++- 2 files changed, 178 insertions(+), 1 deletion(-) diff --git a/runtime/compiler/optimizer/J9TransformUtil.cpp b/runtime/compiler/optimizer/J9TransformUtil.cpp index a7c6abc1f2d..2a64a82f67d 100644 --- a/runtime/compiler/optimizer/J9TransformUtil.cpp +++ b/runtime/compiler/optimizer/J9TransformUtil.cpp @@ -90,6 +90,99 @@ J9::TransformUtil::generateArrayElementShiftAmountTrees( return shiftAmount; } +#if defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION) +TR::Node * +J9::TransformUtil::generateDataAddrLoadTrees(TR::Compilation *comp, TR::Node *arrayObject) + { + TR_ASSERT_FATAL_WITH_NODE(arrayObject, + TR::Compiler->om.isOffHeapAllocationEnabled(), + "This helper shouldn't be called if off heap allocation is disabled.\n"); + + TR::SymbolReference *dataAddrFieldOffset = comp->getSymRefTab()->findOrCreateContiguousArrayDataAddrFieldShadowSymRef(); + TR::Node *dataAddrField = TR::Node::createWithSymRef(TR::aloadi, 1, arrayObject, 0, dataAddrFieldOffset); + dataAddrField->setIsInternalPointer(true); + + return dataAddrField; + } +#endif /* J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION */ + +TR::Node * +J9::TransformUtil::generateArrayAddressTrees(TR::Compilation *comp, TR::Node *arrayNode, TR::Node *offsetNode) + { + TR::Node *arrayAddressNode = NULL; + TR::Node *totalOffsetNode = NULL; + + TR_ASSERT_FATAL_WITH_NODE(arrayNode, + !TR::Compiler->om.canGenerateArraylets(), + "This helper shouldn't be called if arraylets are enabled.\n"); + +#if defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION) + if (TR::Compiler->om.isOffHeapAllocationEnabled()) + { + arrayAddressNode = generateDataAddrLoadTrees(comp, arrayNode); + if (offsetNode) + arrayAddressNode = TR::Node::create(TR::aladd, 2, arrayAddressNode, offsetNode); + } + else if (comp->target().is64Bit()) +#else + if (comp->target().is64Bit()) +#endif /* J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION */ + { + totalOffsetNode = TR::Node::lconst(TR::Compiler->om.contiguousArrayHeaderSizeInBytes()); + if (offsetNode) + totalOffsetNode = TR::Node::create(TR::ladd, 2, offsetNode, totalOffsetNode); + arrayAddressNode = TR::Node::create(TR::aladd, 2, arrayNode, totalOffsetNode); + } + else + { + totalOffsetNode = TR::Node::iconst(TR::Compiler->om.contiguousArrayHeaderSizeInBytes()); + if (offsetNode) + totalOffsetNode = TR::Node::create(TR::iadd, 2, offsetNode, totalOffsetNode); + arrayAddressNode = TR::Node::create(TR::aiadd, 2, arrayNode, totalOffsetNode); + } + + return arrayAddressNode; + } + +TR::Node * +J9::TransformUtil::generateArrayStartTrees(TR::Compilation *comp, TR::Node *arrayObject) + { + TR::Node *firstArrayElementNode = generateArrayAddressTrees(comp, arrayObject); + return firstArrayElementNode; + } + +TR::Node * +J9::TransformUtil::generateArrayOffsetTrees(TR::Compilation *comp, TR::Node *indexNode, TR::Node *elementSizeNode, int32_t elementSize, bool useShiftOpCode) + { + TR::Node *offsetNode = indexNode->createLongIfNeeded(); + TR::Node *strideNode = elementSizeNode; + if (strideNode) + strideNode = strideNode->createLongIfNeeded(); + + if (strideNode != NULL || elementSize > 1) + { + TR::ILOpCodes offsetOpCode = TR::BadILOp; + if (comp->target().is64Bit()) + { + if (strideNode == NULL && elementSize > 1) + strideNode = TR::Node::lconst(indexNode, elementSize); + + offsetOpCode = useShiftOpCode ? TR::lshl : TR::lmul; + } + else + { + if (strideNode == NULL && elementSize > 1) + strideNode = TR::Node::iconst(indexNode, elementSize); + + offsetOpCode = useShiftOpCode ? TR::ishl : TR::imul; + } + + offsetNode = TR::Node::create(offsetOpCode, 2, offsetNode, strideNode); + } + + return offsetNode; + } + // // A few predicates describing shadow symbols that we can reason about at // compile time. Note that "final field" here doesn't rule out a pointer to a diff --git a/runtime/compiler/optimizer/J9TransformUtil.hpp b/runtime/compiler/optimizer/J9TransformUtil.hpp index b7a8e2a5d30..395c3875159 100644 --- a/runtime/compiler/optimizer/J9TransformUtil.hpp +++ b/runtime/compiler/optimizer/J9TransformUtil.hpp @@ -106,7 +106,91 @@ class OMR_EXTENSIBLE TransformUtil : public OMR::TransformUtilConnector TR::Compilation *comp, TR::Node *object); - static bool transformDirectLoad(TR::Compilation *, TR::Node *node); +#if defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION) + /** + * \brief + * Generate IL to load dataAddr pointer from the array header + * + * \param comp + * The compilation object + * + * \param arrayObject + * The array object node + * + * \return + * IL for loading dataAddr pointer + */ + static TR::Node *generateDataAddrLoadTrees(TR::Compilation *comp, TR::Node *arrayObject); +#endif /* J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION */ + + /** + * \brief + * Generate array element access IL for on and off heap contiguous arrays + * + * \param comp + * The compilation object + * + * \param arrayNode + * The array object node + * + * \param offsetNode + * The offset node (in bytes) + * + * \return + * IL to access array element at offset provided by offsetNode or + * first array element if no offset node is provided + */ + static TR::Node *generateArrayAddressTrees( + TR::Compilation *comp, + TR::Node *arrayNode, + TR::Node *offsetNode = NULL); + + /** + * \brief + * Generate IL to access first array element + * + * \param comp + * The compilation object + * + * \param arrayObject + * The array object node + * + * \return + * IL for accessing first array element + */ + static TR::Node *generateArrayStartTrees(TR::Compilation *comp, TR::Node *arrayObject); + + /** + * \brief + * Generates IL to convert element index to offset in bytes using element + * size (node or integer) + * + * \param comp + * The compilation object + * + * \param indexNode + * Array element index node + * + * \param elementSizeNode + * Array element size tree (ex: const node containing element size) + * + * \param elementSize + * Array element size + * + * \param useShiftOpCode + * Use left shift instead of multiplication + * + * \return + * IL to convert array element index to offset in bytes + */ + static TR::Node *generateArrayOffsetTrees( + TR::Compilation *comp, + TR::Node *indexNode, + TR::Node *elementSizeNode = NULL, + int32_t elementSize = 0, + bool useShiftOpCode = false); + + static bool transformDirectLoad(TR::Compilation *comp, TR::Node *node); /** * \brief