Skip to content

Commit 9229e51

Browse files
committed
Z: Add support for inline zero-length offheap 2D array allocation
Enhances the multianewarray evaluator to support zero-length offheap allocation on IBM Z platform. signed-off-by: Ehsan Kiani Far <ehsan.kianifar@gmail.com>
1 parent 81cbba3 commit 9229e51

File tree

1 file changed

+43
-29
lines changed

1 file changed

+43
-29
lines changed

runtime/compiler/z/codegen/J9TreeEvaluator.cpp

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4905,21 +4905,10 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
49054905
}
49064906

49074907
TR::LabelSymbol *zeroSecondDimLabel = generateLabelSymbol(cg);
4908-
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
4909-
bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
4910-
if (isOffHeapAllocationEnabled)
4911-
{
4912-
// Call helper if dim2 length is negative, zero, or larger that INT32_MAX (overflow).
4913-
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRNP, node, inlineAllocFailLabel, cursor);
4914-
}
4915-
else
4916-
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
4917-
{
4918-
// Bypass dim2 size calculation if the size is zero.
4919-
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor);
4920-
// Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow).
4921-
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK5, node, inlineAllocFailLabel, cursor);
4922-
}
4908+
// Bypass dim2 size calculation if the size is zero.
4909+
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor);
4910+
// Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow).
4911+
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK5, node, inlineAllocFailLabel, cursor);
49234912

49244913
int32_t headerSize= TR::Compiler->om.contiguousArrayHeaderSizeInBytes();
49254914
// size = (size + alignmentConstant - 1) & -alignmentConstant equation round up the size to a factor of alignmentConstant.
@@ -5027,12 +5016,17 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50275016
generateS390MemoryReference(resultReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor);
50285017

50295018
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5019+
bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
50305020
if (isOffHeapAllocationEnabled)
50315021
{
50325022
// Store first element's address in data address field.
50335023
cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, sizeReg, generateS390MemoryReference(resultReg, fej9->getOffsetOfContiguousDataAddrField(), cg), cursor);
50345024
// Subtract the header size from the dim2 size, so we can move to the next leaf by adding this value to the address of the leaf's first element.
50355025
cursor = generateRILInstruction(cg, TR::InstOpCode::SLFI, node, dim2SizeReg, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cursor);
5026+
// The length of the second dimension is stored in the upper 32 bits of the scratch register.
5027+
// Comparing the full 64-bit scratch register with its lower 32 bits sets the condition code to COND_BNE if the second dimension is non-zero.
5028+
cursor = generateRREInstruction(cg, TR::InstOpCode::CGFR, node, scratchReg, scratchReg, cursor);
5029+
// The condition code has already been set and must remain unchanged during the second dimension allocation loop in this code path.
50365030
}
50375031
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
50385032

@@ -5046,34 +5040,54 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50465040
cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, scratchReg, generateS390MemoryReference(dim1SizeReg,
50475041
static_cast<int32_t>(TR::Compiler->om.offsetOfContiguousArraySizeField()), cg), cursor);
50485042
int32_t shiftAmount = TR::Compiler->om.compressedReferenceShift();
5049-
if (shiftAmount > 0)
5050-
{
5051-
// Calculate the compressed reference of leaf array in the higher 32bits of dim2SizeReg.
5052-
cursor = generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount, cursor);
5053-
// Store the compressed 32 bit leaf address in the relevant element of the first dim array.
5054-
cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5055-
}
5056-
else
5043+
5044+
if (shiftAmount == 0)
50575045
{
5058-
// Store the 32 bit leaf address in the relevant element of the first dim array.
5046+
// Store the leaf address in the relevant element of the first dim array.
50595047
cursor = generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, dim1SizeReg,
50605048
generateS390MemoryReference(sizeReg, 0, cg), cursor);
50615049
}
50625050

50635051
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
50645052
if (isOffHeapAllocationEnabled)
50655053
{
5054+
if (shiftAmount > 0)
5055+
{
5056+
// Compress the leaf array reference and store it in the first element of the dimension array.
5057+
// Avoid using any instructions that could affect the branch condition in this code path.
5058+
cursor = generateRSInstruction(cg, TR::InstOpCode::SRLG, node, dim1SizeReg, dim1SizeReg, shiftAmount, cursor);
5059+
cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, dim1SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5060+
// Decompress the leaf array reference.
5061+
cursor = generateRSInstruction(cg, TR::InstOpCode::SLLG, node, dim1SizeReg, dim1SizeReg, shiftAmount, cursor);
5062+
}
50665063
// Load the first element address.
50675064
cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg,
50685065
generateS390MemoryReference(dim1SizeReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor);
5069-
// Store the first element address in data address field.
5070-
cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg,
5071-
(fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor);
5066+
// Store the address of the first element in the data address field only if the second dimension length is non-zero.
5067+
cursor = generateRSInstruction(cg, TR::InstOpCode::STOCG, node, dim1SizeReg, getMaskForBranchCondition(TR::InstOpCode::COND_BNE),
5068+
generateS390MemoryReference(dim1SizeReg, (fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor);
5069+
// Load the next leaf address in dim1SizeReg.
5070+
cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, dim2SizeReg, 0, cg), cursor);
50725071
}
5072+
else
50735073
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5074+
{
5075+
if (shiftAmount > 0)
5076+
{
5077+
// Calculate the compressed reference of leaf array in the higher 32bits of dim2SizeReg.
5078+
cursor = generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount, cursor);
5079+
// Store the compressed 32 bit leaf address in the relevant element of the first dim array.
5080+
cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5081+
// Load the next leaf address in dim1SizeReg.
5082+
cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor);
5083+
}
5084+
else
5085+
{
5086+
// Load the next leaf address in dim1SizeReg.
5087+
cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, dim2SizeReg, 0, cg), cursor);
5088+
}
5089+
}
50745090

5075-
// Load the next leaf address in dim1SizeReg.
5076-
cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor);
50775091
// Load the next element address of the first dim array in sizeReg.
50785092
cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg), cursor);
50795093
cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, secondDimLabel, cursor);

0 commit comments

Comments
 (0)