Skip to content

Commit ff0ba22

Browse files
committed
Intialize dataAddr field only for non-zero length array
Update array inline allocation sequence to initialize dataAddr field only for non-zero length arrays. Field should be left blank for zero length arrays. Signed-off-by: Shubham Verma <[email protected]>
1 parent 73af0c7 commit ff0ba22

File tree

1 file changed

+56
-145
lines changed

1 file changed

+56
-145
lines changed

runtime/compiler/z/codegen/J9TreeEvaluator.cpp

Lines changed: 56 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -4871,7 +4871,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
48714871

48724872
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
48734873
bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
4874-
TR::LabelSymbol *populateFirstDimDataAddrSlot = isOffHeapAllocationEnabled ? generateLabelSymbol(cg) : NULL;
48754874
#endif /* defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) */
48764875

48774876
// oolJumpLabel is a common point that all branches will jump to. From this label, we branch to OOL code.
@@ -4889,12 +4888,13 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
48894888
TR::Register *classReg = cg->evaluate(thirdChild);
48904889

48914890
// In the mainline, first load the first and second dimensions' lengths into registers.
4891+
TR::InstOpCode::Mnemonic loadDimLenOpCode = TR::InstOpCode::LGF;
48924892
TR::Register *firstDimLenReg = cg->allocateRegister();
4893-
cursor = generateRXInstruction(cg, TR::InstOpCode::LGF, node, firstDimLenReg, generateS390MemoryReference(dimsPtrReg, 4, cg));
4893+
cursor = generateRXInstruction(cg, loadDimLenOpCode, node, firstDimLenReg, generateS390MemoryReference(dimsPtrReg, 4, cg));
48944894
iComment("Load 1st dim length.");
48954895

48964896
TR::Register *secondDimLenReg = cg->allocateRegister();
4897-
cursor = generateRXInstruction(cg, TR::InstOpCode::L, node, secondDimLenReg, generateS390MemoryReference(dimsPtrReg, 0, cg));
4897+
cursor = generateRXInstruction(cg, loadDimLenOpCode, node, secondDimLenReg, generateS390MemoryReference(dimsPtrReg, 0, cg));
48984898
iComment("Load 2nd dim length.");
48994899

49004900
// Check to see if second dimension is indeed 0. If yes, then proceed to handle the case here. Otherwise jump to OOL code.
@@ -4948,33 +4948,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
49484948
iComment("Init 1st dim mustBeZero field.");
49494949
cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, firstDimLenReg, generateS390MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg));
49504950
iComment("Init 1st dim size field.");
4951-
}
4952-
49534951
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
4954-
if (isOffHeapAllocationEnabled)
4955-
{
4956-
TR_ASSERT_FATAL_WITH_NODE(node,
4957-
(TR::Compiler->om.compressObjectReferences()
4958-
&& (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8)
4959-
|| (!TR::Compiler->om.compressObjectReferences()
4960-
&& fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField()),
4961-
"Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array if using compressed refs, "
4962-
"or same if using full refs. But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
4963-
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
4964-
4965-
// Load dataAddr slot offset difference since 0 size arrays are treated as discontiguous.
4966-
generateRIInstruction(cg,
4967-
TR::InstOpCode::LGHI,
4968-
node,
4969-
temp1Reg,
4970-
static_cast<int32_t>(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()));
4971-
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, populateFirstDimDataAddrSlot);
4972-
}
4973-
else
4952+
if (isOffHeapAllocationEnabled)
4953+
{
4954+
TR_ASSERT_FATAL_WITH_NODE(node,
4955+
TR::InstOpCode::LGF == loadDimLenOpCode,
4956+
"LGF must be used to load 1st dimension length into firstDimLenReg. "
4957+
"Array size field is 32 bits in size but dataAddr slot is 64 bits so "
4958+
"to use the same register to intialize dataAddr slot we must clean "
4959+
"out top 32 bits of firstDimLenReg. LGF sign extends 32 bit 1st dim "
4960+
"size to 64 bits enabling us to use firstDimLenReg to write NULL in "
4961+
"the dataAddr field for 0 length arrays.\n");
4962+
cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, firstDimLenReg, generateS390MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
4963+
iComment("Clear 1st dim dataAddr field.");
4964+
}
49744965
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
4975-
{
4976-
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
49774966
}
4967+
4968+
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
49784969
iComment("Init class field and jump.");
49794970

49804971
// We end up in this region of the ICF if the first dimension is non-zero and the second dimension is zero.
@@ -5056,27 +5047,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50565047
iComment("Init 2st dim mustBeZero field.");
50575048
cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, secondDimLenReg, generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg));
50585049
iComment("Init 2st dim size field.");
5059-
}
5060-
5061-
TR::Register *temp3Reg = cg->allocateRegister();
5062-
50635050
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5064-
if (isOffHeapAllocationEnabled)
5065-
{
5066-
// Populate dataAddr slot for 2nd dimension zero size array.
5067-
generateRXInstruction(cg,
5068-
TR::InstOpCode::LA,
5069-
node,
5070-
temp3Reg,
5071-
generateS390MemoryReference(temp2Reg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg));
5072-
generateRXInstruction(cg,
5073-
TR::InstOpCode::STG,
5074-
node,
5075-
temp3Reg,
5076-
generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
5077-
}
5051+
if (isOffHeapAllocationEnabled)
5052+
{
5053+
TR_ASSERT_FATAL_WITH_NODE(node,
5054+
TR::InstOpCode::LGF == loadDimLenOpCode,
5055+
"LGF must be used to load 2nd dimension length into secondDimLenReg. "
5056+
"Array size field is 32 bits in size but dataAddr slot is 64 bits so "
5057+
"to use the same register to intialize dataAddr slot we must clean "
5058+
"out top 32 bits of secondDimLenReg. LGF sign extends 32 bit 2nd dim "
5059+
"size to 64 bits enabling us to use secondDimLenReg to write NULL in "
5060+
"the dataAddr field for 0 length arrays.\n");
5061+
cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, secondDimLenReg, generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
5062+
iComment("Clear 2nd dim dataAddr field.");
5063+
}
50785064
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5065+
}
50795066

5067+
TR::Register *temp3Reg = cg->allocateRegister();
50805068
// Store 2nd dim element into 1st dim array slot, compress temp2 if needed
50815069
if (comp->target().is64Bit() && comp->useCompressedPointers())
50825070
{
@@ -5103,15 +5091,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
51035091
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
51045092
if (isOffHeapAllocationEnabled)
51055093
{
5106-
// No offset is needed since 1st dimension array is contiguous.
5107-
generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, temp1Reg, temp1Reg);
5108-
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, populateFirstDimDataAddrSlot);
5094+
/* Populate dataAddr slot of 1st dimension array. We don't need to worry
5095+
* about zero length array since it has already been taken care of.
5096+
*/
5097+
generateRXInstruction(cg,
5098+
TR::InstOpCode::LA,
5099+
node,
5100+
temp3Reg,
5101+
generateS390MemoryReference(targetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg));
5102+
cursor = generateRXInstruction(cg,
5103+
TR::InstOpCode::STG,
5104+
node,
5105+
temp3Reg,
5106+
generateS390MemoryReference(targetReg, fej9->getOffsetOfContiguousDataAddrField(), cg));
5107+
iComment("populateFirstDimDataAddrSlot.");
51095108
}
5110-
else
51115109
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5112-
{
5113-
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
5114-
}
5110+
5111+
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
51155112

51165113
TR::RegisterDependencyConditions *dependencies = generateRegisterDependencyConditions(0,10,cg);
51175114
dependencies->addPostCondition(dimReg, TR::RealRegister::AssignAny);
@@ -5128,28 +5125,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
51285125
generateS390LabelInstruction(cg, TR::InstOpCode::label, node, oolJumpLabel);
51295126
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, oolFailLabel);
51305127

5131-
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5132-
if (isOffHeapAllocationEnabled)
5133-
{
5134-
/* Populate dataAddr slot of 1st dimension array. Arrays of non-zero size
5135-
* use contiguous header layout while zero size arrays use discontiguous header layout.
5136-
*/
5137-
cursor = generateS390LabelInstruction(cg, TR::InstOpCode::label, node, populateFirstDimDataAddrSlot);
5138-
iComment("populateFirstDimDataAddrSlot.");
5139-
5140-
generateRXInstruction(cg,
5141-
TR::InstOpCode::LA,
5142-
node,
5143-
temp3Reg,
5144-
generateS390MemoryReference(targetReg, temp1Reg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg));
5145-
generateRXInstruction(cg,
5146-
TR::InstOpCode::STG,
5147-
node,
5148-
temp3Reg,
5149-
generateS390MemoryReference(targetReg, temp1Reg, fej9->getOffsetOfContiguousDataAddrField(), cg));
5150-
}
5151-
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5152-
51535128
generateS390LabelInstruction(cg, TR::InstOpCode::label, node, cFlowRegionDone, dependencies);
51545129

51555130
TR::Register *targetRegisterFinal = cg->allocateCollectedReferenceRegister();
@@ -11119,81 +11094,17 @@ J9::Z::TreeEvaluator::VMnewEvaluator(TR::Node * node, TR::CodeGenerator * cg)
1111911094
#ifdef J9VM_GC_SPARSE_HEAP_ALLOCATION
1112011095
if (TR::Compiler->om.isOffHeapAllocationEnabled())
1112111096
{
11122-
/* Here we'll update dataAddr slot for both fixed and variable length arrays. Fixed length arrays are
11123-
* simple as we just need to check first child of the node for array size. For variable length arrays
11124-
* runtime size checks are needed to determine whether to use contiguous or discontiguous header layout.
11125-
*
11126-
* In both scenarios, arrays of non-zero size use contiguous header layout while zero size arrays use
11127-
* discontiguous header layout.
11097+
/* Here we'll update dataAddr slot for fixed and variable non-zero length arrays. DataAddr field
11098+
* should be left blank for zero length arrays.
1112811099
*/
11129-
TR::Register *offsetReg = NULL;
11130-
TR::MemoryReference *dataAddrMR = NULL;
11131-
TR::MemoryReference *dataAddrSlotMR = NULL;
11132-
11133-
if (isVariableLen && TR::Compiler->om.compressObjectReferences())
11134-
{
11135-
/* We need to check enumReg (array size) at runtime to determine correct offset of dataAddr field.
11136-
* Here we deal only with compressed refs because dataAddr offset for discontiguous
11137-
* and contiguous arrays is the same in full refs.
11138-
*/
11139-
if (comp->getOption(TR_TraceCG))
11140-
traceMsg(comp, "Node (%p): Dealing with compressed refs variable length array.\n", node);
11141-
11142-
TR_ASSERT_FATAL_WITH_NODE(node,
11143-
(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8,
11144-
"Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. "
11145-
"But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
11146-
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
11147-
11148-
offsetReg = cg->allocateRegister();
11149-
// Invert enumReg sign. 0 and negative numbers remain unchanged.
11150-
iCursor = generateRREInstruction(cg, TR::InstOpCode::LNGFR, node, offsetReg, enumReg, iCursor);
11151-
iCursor = generateRSInstruction(cg, TR::InstOpCode::SRLG, node, dataSizeReg, offsetReg, 63, iCursor);
11152-
iCursor = generateRSInstruction(cg, TR::InstOpCode::SLLG, node, offsetReg, dataSizeReg, 3, iCursor);
11153-
// Inverting the sign bit will leave us with either -8 (if enumCopyReg > 0) or 0 (if enumCopyReg == 0).
11154-
iCursor = generateRREInstruction(cg, TR::InstOpCode::LNGR, node, offsetReg, offsetReg, iCursor);
11155-
11156-
dataAddrMR = generateS390MemoryReference(resReg, offsetReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg);
11157-
dataAddrSlotMR = generateS390MemoryReference(resReg, offsetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg);
11158-
}
11159-
else if (!isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0)
11160-
{
11161-
if (comp->getOption(TR_TraceCG))
11162-
traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length zero size array.\n", node);
11163-
11164-
dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg);
11165-
dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg);
11166-
}
11167-
else
11168-
{
11169-
if (comp->getOption(TR_TraceCG))
11170-
{
11171-
traceMsg(comp,
11172-
"Node (%p): Dealing with either full/compressed refs fixed length non-zero size array or full refs variable length array.\n",
11173-
node);
11174-
}
11175-
11176-
if (!TR::Compiler->om.compressObjectReferences())
11177-
{
11178-
TR_ASSERT_FATAL_WITH_NODE(node,
11179-
fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(),
11180-
"dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. "
11181-
"But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
11182-
fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
11183-
}
11184-
11185-
dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
11186-
dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
11187-
}
11100+
TR::MemoryReference *dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
11101+
TR::MemoryReference *dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
1118811102

11103+
dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
1118911104
iCursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dataSizeReg, dataAddrMR, iCursor);
11190-
iCursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, dataSizeReg, dataAddrSlotMR, iCursor);
11105+
iCursor = generateRILInstruction(cg, TR::InstOpCode::CFI, node, enumReg, 0, iCursor);
1119111106

11192-
if (offsetReg)
11193-
{
11194-
conditions->addPostCondition(offsetReg, TR::RealRegister::AssignAny);
11195-
cg->stopUsingRegister(offsetReg);
11196-
}
11107+
iCursor = generateRSInstruction(cg, TR::InstOpCode::STOCG, node, dataSizeReg, static_cast<uint32_t>(0x2), dataAddrSlotMR, iCursor);
1119711108
}
1119811109
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
1119911110

0 commit comments

Comments
 (0)