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

NULL initialize dataAddr field for 0 size arrays #20892

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
152 changes: 77 additions & 75 deletions runtime/compiler/x/codegen/J9TreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1499,7 +1499,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
TR::LabelSymbol *nonZeroFirstDimLabel = generateLabelSymbol(cg);
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
TR::LabelSymbol *populateFirstDimDataAddrSlot = isOffHeapAllocationEnabled? generateLabelSymbol(cg) : NULL;
#endif /* defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) */

startLabel->setStartInternalControlFlow();
Expand Down Expand Up @@ -1554,37 +1553,18 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
// Init size and mustBeZero ('0') fields to 0
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfContiguousArraySizeField(), cg), 0, cg);
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg), 0, cg);
if (TR::Compiler->om.compressObjectReferences())
{ // Clear padding in contiguous array header layout. +4 because size field is 4 bytes wide.
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousArraySizeField() + 4, cg), 0, cg);
}

#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
if (isOffHeapAllocationEnabled)
{
// Load dataAddr slot offset difference since 0 size arrays are treated as discontiguous.
TR_ASSERT_FATAL_WITH_NODE(node,
IS_32BIT_SIGNED(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()),
"dataAddrFieldOffset is too big for the instruction.");

TR_ASSERT_FATAL_WITH_NODE(node,
(TR::Compiler->om.compressObjectReferences()
&& (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8)
|| (!TR::Compiler->om.compressObjectReferences()
&& fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField()),
"Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array if using compressed refs, "
"or same if using full refs. But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());

generateRegImmInstruction(TR::InstOpCode::MOV8RegImm4,
node,
temp3Reg,
static_cast<int32_t>(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()),
cg);

generateLabelInstruction(TR::InstOpCode::JMP4, node, populateFirstDimDataAddrSlot, cg);
{ // Init 1st dim dataAddr slot to 0
generateMemRegInstruction(TR::InstOpCode::S8MemImm4, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg), 0, cg);
}
else
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
{
generateLabelInstruction(TR::InstOpCode::JMP4, node, doneLabel, cg);
}
generateLabelInstruction(TR::InstOpCode::JMP4, node, doneLabel, cg);

//First dim length not 0
generateLabelInstruction(TR::InstOpCode::label, node, nonZeroFirstDimLabel, cg);
Expand Down Expand Up @@ -1633,6 +1613,28 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
generateMemRegInstruction(TR::InstOpCode::SMemReg(use64BitClasses), node, generateX86MemoryReference(targetReg, TR::Compiler->om.offsetOfObjectVftField(), cg), classReg, cg);
// Init 1st dim array size field
generateMemRegInstruction(TR::InstOpCode::S4MemReg, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfContiguousArraySizeField(), cg), firstDimLenReg, cg);
if (!TR::Compiler->om.compressObjectReferences())
{ // Clear padding in contiguous array header layout. +4 because size field is 4 bytes wide.
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(targetReg, fej9->getOffsetOfContiguousArraySizeField() + 4, cg), 0, cg);
}
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
if (isOffHeapAllocationEnabled)
{
/* Populate dataAddr slot of 1st dimension array. Arrays of non-zero size
* use contiguous header layout while zero size arrays use discontiguous header layout.
*/
generateRegMemInstruction(TR::InstOpCode::LEARegMem(),
node,
temp3Reg,
generateX86MemoryReference(targetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg),
cg);
generateMemRegInstruction(TR::InstOpCode::SMemReg(),
node,
generateX86MemoryReference(targetReg, fej9->getOffsetOfContiguousDataAddrField(), cg),
temp3Reg,
cg);
}
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */

// temp2 point to end of 1st dim array i.e. start of 2nd dim
generateRegRegInstruction(TR::InstOpCode::MOVRegReg(), node, temp2Reg, targetReg, cg);
Expand All @@ -1647,21 +1649,16 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
// Init 2nd dim element's size and mustBeZero ('0') fields to 0
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(temp2Reg, fej9->getOffsetOfContiguousArraySizeField(), cg), 0, cg);
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg), 0, cg);
if (TR::Compiler->om.compressObjectReferences())
{ // Clear padding in contiguous array header layout. +4 because size field is 4 bytes wide.
generateMemImmInstruction(TR::InstOpCode::S4MemImm4, node, generateX86MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousArraySizeField() + 4, cg), 0, cg);
}

#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
if (isOffHeapAllocationEnabled)
{
// Populate dataAddr slot for 2nd dimension zero size array.
generateRegMemInstruction(TR::InstOpCode::LEARegMem(),
node,
temp3Reg,
generateX86MemoryReference(temp2Reg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg),
cg);
generateMemRegInstruction(TR::InstOpCode::SMemReg(),
node,
generateX86MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg),
temp3Reg,
cg);
generateMemRegInstruction(TR::InstOpCode::S8MemImm4, node, generateX86MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg), 0, cg);
}
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */

Expand All @@ -1688,18 +1685,7 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
generateRegInstruction(TR::InstOpCode::DEC4Reg, node, firstDimLenReg, cg);
generateLabelInstruction(TR::InstOpCode::JA4, node, loopLabel, cg);

#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
if (isOffHeapAllocationEnabled)
{
// No offset is needed since 1st dimension array is contiguous.
generateRegRegInstruction(TR::InstOpCode::XOR4RegReg, node, temp3Reg, temp3Reg, cg);
generateLabelInstruction(TR::InstOpCode::JMP4, node, populateFirstDimDataAddrSlot, cg);
}
else
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
{
generateLabelInstruction(TR::InstOpCode::JMP4, node, doneLabel, cg);
}
generateLabelInstruction(TR::InstOpCode::JMP4, node, doneLabel, cg);

TR::RegisterDependencyConditions *deps = generateRegisterDependencyConditions((uint8_t)0, 13, cg);

Expand Down Expand Up @@ -1746,26 +1732,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
generateLabelInstruction(TR::InstOpCode::label, node, oolJumpPoint, cg);
generateLabelInstruction(TR::InstOpCode::JMP4, node, oolFailLabel, cg);

#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
if (isOffHeapAllocationEnabled)
{
/* Populate dataAddr slot of 1st dimension array. Arrays of non-zero size
* use contiguous header layout while zero size arrays use discontiguous header layout.
*/
generateLabelInstruction(TR::InstOpCode::label, node, populateFirstDimDataAddrSlot, cg);
generateRegMemInstruction(TR::InstOpCode::LEARegMem(),
node,
temp2Reg,
generateX86MemoryReference(targetReg, temp3Reg, 0, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg),
cg);
generateMemRegInstruction(TR::InstOpCode::SMemReg(),
node,
generateX86MemoryReference(targetReg, temp3Reg, 0, fej9->getOffsetOfContiguousDataAddrField(), cg),
temp2Reg,
cg);
}
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */

generateLabelInstruction(TR::InstOpCode::label, node, doneLabel, deps, cg);

// Copy the newly allocated object into a collected reference register now that it is a valid object.
Expand Down Expand Up @@ -6827,6 +6793,24 @@ static void genInitArrayHeader(
}
}

// Clear padding after size field in array header
if (TR::Compiler->om.compressObjectReferences())
{ // Clear padding after size field in discontiguous header layout (for 0 length arrays)
generateMemImmInstruction(TR::InstOpCode::S4MemImm4,
node,
generateX86MemoryReference(objectReg, fej9->getOffsetOfDiscontiguousArraySizeField() + 4, cg),
0,
cg);
}
else
{ // Clear padding after size field in contiguous header layout
generateMemImmInstruction(TR::InstOpCode::S4MemImm4,
node,
generateX86MemoryReference(objectReg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg),
0,
cg);
}

bool generateArraylets = comp->generateArraylets();

if (generateArraylets)
Expand Down Expand Up @@ -7481,7 +7465,8 @@ static void handleOffHeapDataForArrays(
* 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::MemoryReference *dataAddrSlotMR = NULL;
TR::MemoryReference *dataAddrMR = NULL;
Expand All @@ -7504,16 +7489,26 @@ static void handleOffHeapDataForArrays(
generateRegRegInstruction(TR::InstOpCode::XOR4RegReg, node, discontiguousDataAddrOffsetReg, discontiguousDataAddrOffsetReg, cg);
generateRegImmInstruction(TR::InstOpCode::CMPRegImm4(), node, sizeReg, 1, cg);
generateRegImmInstruction(TR::InstOpCode::ADCRegImm4(), node, discontiguousDataAddrOffsetReg, 0, cg);

dataAddrMR = generateX86MemoryReference(targetReg, discontiguousDataAddrOffsetReg, 3, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
dataAddrSlotMR = generateX86MemoryReference(targetReg, discontiguousDataAddrOffsetReg, 3, fej9->getOffsetOfContiguousDataAddrField(), cg);
// Load first data element address
generateRegMemInstruction(TR::InstOpCode::LEARegMem(), node, tempReg, dataAddrMR, cg);

// Clear out tempReg if dealing with 0 length array
generateRegImmInstruction(TR::InstOpCode::CMPRegImm4(), node, sizeReg, 0, cg);
generateRegMemInstruction(TR::InstOpCode::CMOVE8RegMem, node, tempReg, generateX86MemoryReference(cg->findOrCreate8ByteConstant(node, 0), cg), cg);

// Write first data element address to dataAddr slot
generateMemRegInstruction(TR::InstOpCode::SMemReg(), node, dataAddrSlotMR, tempReg, cg);
}
else if (NULL == sizeReg && 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);

dataAddrMR = generateX86MemoryReference(targetReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg);
dataAddrSlotMR = generateX86MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg);
generateMemImmInstruction(TR::InstOpCode::S8MemImm4, node, dataAddrSlotMR, 0, cg);
}
else
{
Expand All @@ -7535,11 +7530,18 @@ static void handleOffHeapDataForArrays(

dataAddrMR = generateX86MemoryReference(targetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
dataAddrSlotMR = generateX86MemoryReference(targetReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
}
// Load first data element address
generateRegMemInstruction(TR::InstOpCode::LEARegMem(), node, tempReg, dataAddrMR, cg);

// write first data element address to dataAddr slot
generateRegMemInstruction(TR::InstOpCode::LEARegMem(), node, tempReg, dataAddrMR, cg);
generateMemRegInstruction(TR::InstOpCode::SMemReg(), node, dataAddrSlotMR, tempReg, cg);
if (!TR::Compiler->om.compressObjectReferences() && NULL != sizeReg)
{
// Clear out tempReg if dealing with 0 length array
generateRegImmInstruction(TR::InstOpCode::CMPRegImm4(), node, sizeReg, 0, cg);
generateRegMemInstruction(TR::InstOpCode::CMOVE8RegMem, node, tempReg, generateX86MemoryReference(cg->findOrCreate8ByteConstant(node, 0), cg), cg);
}
// Write first data element address to dataAddr slot
generateMemRegInstruction(TR::InstOpCode::SMemReg(), node, dataAddrSlotMR, tempReg, cg);
}
}
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */

Expand Down