@@ -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