Skip to content

Commit

Permalink
p: NULL initialize dataAddr field for 0 size arrays
Browse files Browse the repository at this point in the history
Update array inline allocation sequence to initialize dataAddr field
only for non-zero size arrays. Field should be left blank for zero
size arrays.

Signed-off-by: Shubham Verma <[email protected]>
  • Loading branch information
VermaSh committed Jan 8, 2025
1 parent 3f2f1b0 commit 2d3567e
Showing 1 changed file with 72 additions and 32 deletions.
104 changes: 72 additions & 32 deletions runtime/compiler/p/codegen/J9TreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6163,6 +6163,26 @@ static void genInitArrayHeader(TR::Node *node, TR::Instruction *&iCursor, bool i
TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousArraySizeField(), 4),
instanceSizeReg, iCursor);
}

// Clear padding after size field
if (needZeroInit)
{
TR_ASSERT_FATAL_WITH_NODE(node, zeroReg, "zeroReg is expected to be intialized but wasn't.\n");
if (TR::Compiler->om.compressObjectReferences())
{
// padding field starts at fej9->getOffsetOfDiscontiguousArraySizeField() + 4
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node,
TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousArraySizeField() + 4, 4),
zeroReg, iCursor);
}
else
{
// padding field starts at fej9->getOffsetOfDiscontiguousArraySizeField()
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node,
TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousArraySizeField(), 4),
zeroReg, iCursor);
}
}
}

static void genZeroInit(TR::CodeGenerator *cg, TR::Node *node, TR::Register *objectReg, int32_t headerSize, int32_t totalSize, bool useInitInfo)
Expand Down Expand Up @@ -6492,67 +6512,87 @@ TR::Register *J9::Power::TreeEvaluator::VMnewEvaluator(TR::Node *node, TR::CodeG
* runtime size checks are needed to determine whether to use contiguous or discontiguous header layout.
*
* In both scenarios, arrays of non-zero size use contiguous header layout while zero size arrays use
* discontiguous header layout.
* discontiguous header layout. DataAddr field of zero size arrays is intialized to NULL because they
* don't have any data elements.
*/
TR::Register *offsetReg = tmp5Reg;
TR::Register *firstDataElementReg = tmp4Reg;
TR::MemoryReference *dataAddrSlotMR = NULL;

if (TR::Compiler->om.compressObjectReferences())
{
TR_ASSERT_FATAL_WITH_NODE(node,
(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8,
"Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. "
"But was %d bytes for discontigous and %d bytes for contiguous array.\n",
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
}
else
{
TR_ASSERT_FATAL_WITH_NODE(node,
fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(),
"dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. "
"But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
}

if (isVariableLen && TR::Compiler->om.compressObjectReferences())
{
/* We need to check enumReg at runtime to determine correct offset of dataAddr field.
* Here we deal only with compressed refs because dataAddr offset for discontiguous
* and contiguous arrays is the same in full refs.
*/
if (comp->getOption(TR_TraceCG))
traceMsg(comp, "Node (%p): Dealing with compressed refs variable length array.\n", node);
traceMsg(comp, "Node (%p): Dealing with full/compressed refs variable length array.\n", node);

TR_ASSERT_FATAL_WITH_NODE(node,
(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8,
"Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. "
"But was %d bytes for discontigous and %d bytes for contiguous array.\n",
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
TR::LabelSymbol *dataAddrInitDoneLabel = generateLabelSymbol(cg);
TR::LabelSymbol *nonZeroArrayLabel = generateLabelSymbol(cg);

iCursor = generateTrg1Src1Instruction(cg, TR::InstOpCode::cntlzd, node, offsetReg, enumReg, iCursor);
iCursor = generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rlwinm, node, offsetReg, offsetReg, 29, 8, iCursor);
// offsetReg should either be 0 (if enumReg > 0) or 8 (if enumReg == 0)
iCursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, offsetReg, resReg, offsetReg, iCursor);
iCursor = generateTrg1Src1ImmInstruction(cg,TR::InstOpCode::cmpi8, node, condReg, enumReg, 0, iCursor);
iCursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bgt, node, nonZeroArrayLabel, condReg, iCursor);
// Clear dataAddr field of 0 size array
if (needZeroInit)
{
// Use zeroReg to clear the field
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std,
node,
TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), 8),
zeroReg, iCursor);
}
iCursor = generateLabelInstruction(cg, TR::InstOpCode::b, node, dataAddrInitDoneLabel);

iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, offsetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor);
dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, offsetReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());
// Init dataAddr field for non-zero size array
iCursor = generateLabelInstruction(cg, TR::InstOpCode::label, node, nonZeroArrayLabel, iCursor);
// Load first data element address
iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor);
dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());
// Store the first data element address to dataAddr slot
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor);

iCursor = generateLabelInstruction(cg, TR::InstOpCode::label, node, dataAddrInitDoneLabel, iCursor);
}
else if (!isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0)
else if (needZeroInit && !isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0)
{
if (comp->getOption(TR_TraceCG))
traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length zero size array.\n", node);

iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), iCursor);
dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());

// Use zeroReg to NULL dataAddr slot
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, zeroReg, iCursor);
}
else
{
if (comp->getOption(TR_TraceCG))
{
traceMsg(comp,
"Node (%p): Dealing with either full/compressed refs fixed length non-zero size array or full refs variable length array.\n",
node);
}

if (!TR::Compiler->om.compressObjectReferences())
{
TR_ASSERT_FATAL_WITH_NODE(node,
fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(),
"dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. "
"But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
}
traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length non-zero size array.\n", node);

// Load first element address into firstDataElementReg
iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor);
dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress());
}

// store the first data element address to dataAddr slot
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor);
// Store the first data element address to dataAddr slot
iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor);
}
}
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
if (generateArraylets)
Expand Down

0 comments on commit 2d3567e

Please sign in to comment.