Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add helper functions for off heap technology changes #18303

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
vmInfo._helperAddresses[i] = runtimeHelperValue((TR_RuntimeHelper) i);
#endif
vmInfo._isHotReferenceFieldRequired = TR::Compiler->om.isHotReferenceFieldRequired();
vmInfo._isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
vmInfo._osrGlobalBufferSize = javaVM->osrGlobalBufferSize;
vmInfo._needsMethodTrampolines = TR::CodeCacheManager::instance()->codeCacheConfig().needsMethodTrampolines();
vmInfo._objectAlignmentInBytes = TR::Compiler->om.objectAlignmentInBytes();
Expand Down
12 changes: 12 additions & 0 deletions runtime/compiler/env/J9ObjectModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,18 @@ J9::ObjectModel::isHotReferenceFieldRequired()
return TR::Compiler->javaVM->memoryManagerFunctions->j9gc_hot_reference_field_required(TR::Compiler->javaVM);
}

bool
J9::ObjectModel::isOffHeapAllocationEnabled()
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = TR::CompilationInfo::getStream())
{
auto *vmInfo = TR::compInfoPT->getClientData()->getOrCacheVMInfo(stream);
return vmInfo->_isOffHeapAllocationEnabled;
}
#endif /* defined(J9VM_OPT_JITSERVER) */
return TR::Compiler->javaVM->memoryManagerFunctions->j9gc_off_heap_allocation_enabled(TR::Compiler->javaVM);
}

UDATA
J9::ObjectModel::elementSizeOfBooleanArray()
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/env/J9ObjectModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class ObjectModel : public OMR::ObjectModelConnector

int32_t sizeofReferenceField();
bool isHotReferenceFieldRequired();
bool isOffHeapAllocationEnabled();
uintptr_t elementSizeOfBooleanArray();
uint32_t getSizeOfArrayElement(TR::Node *node);
int64_t maxArraySizeInElementsForAllocation(TR::Node *newArray, TR::Compilation *comp);
Expand Down
93 changes: 93 additions & 0 deletions runtime/compiler/optimizer/J9TransformUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this node also need to be tagged as an internal pointer ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Offset node doesn't contain an address; just an offset value relative to the array object pointer. So we should be ok not marking it as an internal pointer.

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
Expand Down
86 changes: 85 additions & 1 deletion runtime/compiler/optimizer/J9TransformUtil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Copy link
Contributor

@vijaysun-omr vijaysun-omr Nov 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we clarify what the strideNode means here ? It seems clearer how to use elementSize with indexNode to come up with an "offset tree" but what role a strideNode plays is less clear because it is not as clearly defined. Maybe an example/pseudocode would help.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the comment and variable name. Does it help or should I add more?

* \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
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/runtime/JITClientSession.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ class ClientSessionData
void *_helperAddresses[TR_numRuntimeHelpers];
#endif
bool _isHotReferenceFieldRequired;
bool _isOffHeapAllocationEnabled;
UDATA _osrGlobalBufferSize;
bool _needsMethodTrampolines;
int32_t _objectAlignmentInBytes;
Expand Down
1 change: 1 addition & 0 deletions runtime/gc/gctable.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ J9MemoryManagerFunctions MemoryManagerFunctions = {
j9gc_concurrent_scavenger_enabled,
j9gc_software_read_barrier_enabled,
j9gc_hot_reference_field_required,
j9gc_off_heap_allocation_enabled,
j9gc_max_hot_field_list_length,
#if defined(J9VM_GC_HEAP_CARD_TABLE)
j9gc_concurrent_getCardSize,
Expand Down
1 change: 1 addition & 0 deletions runtime/gc_base/gc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ extern J9_CFUNC UDATA j9gc_scavenger_enabled(J9JavaVM *javaVM);
extern J9_CFUNC UDATA j9gc_concurrent_scavenger_enabled(J9JavaVM *javaVM);
extern J9_CFUNC UDATA j9gc_software_read_barrier_enabled(J9JavaVM *javaVM);
extern J9_CFUNC BOOLEAN j9gc_hot_reference_field_required(J9JavaVM *javaVM);
extern J9_CFUNC BOOLEAN j9gc_off_heap_allocation_enabled(J9JavaVM *javaVM);
extern J9_CFUNC uint32_t j9gc_max_hot_field_list_length(J9JavaVM *javaVM);
extern J9_CFUNC void j9gc_objaccess_indexableStoreAddress(J9VMThread *vmThread, J9IndexableObject *destObject, I_32 index, void *value, UDATA isVolatile);
extern J9_CFUNC void j9gc_objaccess_mixedObjectStoreAddress(J9VMThread *vmThread, j9object_t destObject, UDATA offset, void *value, UDATA isVolatile);
Expand Down
16 changes: 16 additions & 0 deletions runtime/gc_modron_startup/mmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,22 @@ j9gc_hot_reference_field_required(J9JavaVM *javaVM)
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) || defined(OMR_GC_VLHGC) */
}

/**
* Query if off heap allocation for large objects is enabled.
*
* @param javaVM pointer to J9JavaVM
* @return true if extensions flag isVirtualLargeObjectHeapEnabled is set, 0 otherwise
*/
BOOLEAN
j9gc_off_heap_allocation_enabled(J9JavaVM *javaVM)
{
#if defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION)
return MM_GCExtensions::getExtensions(javaVM)->isVirtualLargeObjectHeapEnabled;
#else /* defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION) */
return FALSE;
#endif /* defined(J9VM_GC_ENABLE_SPARSE_HEAP_ALLOCATION) */
}

/**
* Query for the max hot field list length that a class is allowed to have.
* Valid if dynamicBreadthFirstScanOrdering is enabled.
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4471,6 +4471,7 @@ typedef struct J9MemoryManagerFunctions {
UDATA ( *j9gc_concurrent_scavenger_enabled)(struct J9JavaVM *javaVM) ;
UDATA ( *j9gc_software_read_barrier_enabled)(struct J9JavaVM *javaVM) ;
BOOLEAN ( *j9gc_hot_reference_field_required)(struct J9JavaVM *javaVM) ;
BOOLEAN ( *j9gc_off_heap_allocation_enabled)(struct J9JavaVM *javaVM) ;
uint32_t ( *j9gc_max_hot_field_list_length)(struct J9JavaVM *javaVM) ;
#if defined(J9VM_GC_HEAP_CARD_TABLE)
UDATA ( *j9gc_concurrent_getCardSize)(struct J9JavaVM *javaVM) ;
Expand Down