@@ -4905,6 +4905,7 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
49054905 }
49064906
49074907 TR::LabelSymbol *zeroSecondDimLabel = generateLabelSymbol(cg);
4908+
49084909 // Bypass dim2 size calculation if the size is zero.
49094910 cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor);
49104911 // Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow).
@@ -5017,16 +5018,19 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50175018
50185019#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
50195020 bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
5021+ TR::LabelSymbol *zeroLengthSecondDimLabel = NULL;
50205022 if (isOffHeapAllocationEnabled)
50215023 {
50225024 // Store first element's address in data address field.
50235025 cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, sizeReg, generateS390MemoryReference(resultReg, fej9->getOffsetOfContiguousDataAddrField(), cg), cursor);
5024- // 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 .
5025- cursor = generateRILInstruction (cg, TR::InstOpCode::SLFI, node, dim2SizeReg, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cursor );
5026+ // If the second dimension length is zero, allocate the leaf array OOL .
5027+ zeroLengthSecondDimLabel = generateLabelSymbol (cg);
50265028 // 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.
5029+ // Comparing the full 64-bit scratch register with its lower 32 bits sets the condition code to COND_BE if the second dimension is zero.
50285030 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.
5031+ cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BE, node, zeroLengthSecondDimLabel, cursor);
5032+ // 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.
5033+ cursor = generateRILInstruction(cg, TR::InstOpCode::SLFI, node, dim2SizeReg, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cursor);
50305034 }
50315035#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
50325036
@@ -5040,59 +5044,75 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50405044 cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, scratchReg, generateS390MemoryReference(dim1SizeReg,
50415045 static_cast<int32_t>(TR::Compiler->om.offsetOfContiguousArraySizeField()), cg), cursor);
50425046 int32_t shiftAmount = TR::Compiler->om.compressedReferenceShift();
5043-
5044- if (shiftAmount == 0)
5047+ if (shiftAmount > 0)
5048+ {
5049+ // Calculate the compressed reference of leaf array in the higher 32bits of dim2SizeReg.
5050+ cursor = generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount, cursor);
5051+ // Store the compressed 32 bit leaf address in the relevant element of the first dim array.
5052+ cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5053+ }
5054+ else
50455055 {
5046- // Store the leaf address in the relevant element of the first dim array.
5056+ // Store the 32 bit leaf address in the relevant element of the first dim array.
50475057 cursor = generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, dim1SizeReg,
50485058 generateS390MemoryReference(sizeReg, 0, cg), cursor);
50495059 }
50505060
50515061#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
50525062 if (isOffHeapAllocationEnabled)
50535063 {
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- }
50635064 // Load the first element address.
50645065 cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg,
50655066 generateS390MemoryReference(dim1SizeReg, 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);
5067+ // Store the first element address in data address field.
5068+ cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg,
5069+ (fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor);
50715070 }
5072- else
50735071#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5072+
5073+ // Load the next leaf address in dim1SizeReg.
5074+ cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor);
5075+ // Load the next element address of the first dim array in sizeReg.
5076+ cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg), cursor);
5077+ cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, secondDimLabel, cursor);
5078+ cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_B, node, controlFlowEndLabel, cursor);
5079+
5080+ /********************************************* OOL zero length offheap leaf allocator *********************************************/
5081+ #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5082+ if (isOffHeapAllocationEnabled)
50745083 {
5084+ TR_S390OutOfLineCodeSection *zeroLengthSecondDimAlloc = new (cg->trHeapMemory()) TR_S390OutOfLineCodeSection(zeroLengthSecondDimLabel, controlFlowEndLabel, cg);
5085+ cg->getS390OutOfLineCodeSectionList().push_front(zeroLengthSecondDimAlloc);
5086+ zeroLengthSecondDimAlloc->swapInstructionListsWithCompilation();
5087+ generateS390LabelInstruction(cg, TR::InstOpCode::label, node, zeroLengthSecondDimLabel);
5088+
5089+ // Store the class field.
5090+ generateRXInstruction(cg, (compressedObjectHeaders ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, classReg,
5091+ generateS390MemoryReference(dim1SizeReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), cg));
5092+ // Store the array length.
50755093 if (shiftAmount > 0)
50765094 {
50775095 // 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 );
5096+ generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount);
50795097 // 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);
5098+ generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg));
50835099 }
50845100 else
50855101 {
5086- // Load the next leaf address in dim1SizeReg.
5087- cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, dim2SizeReg, 0, cg), cursor);
5102+ // Store the 32 bit leaf address in the relevant element of the first dim array.
5103+ generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, dim1SizeReg,
5104+ generateS390MemoryReference(sizeReg, 0, cg));
50885105 }
5089- }
5106+ // Load the next leaf address in dim1SizeReg.
5107+ generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg);
5108+ // Load the next element address of the first dim array in sizeReg.
5109+ generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg));
5110+ generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, zeroLengthSecondDimLabel);
50905111
5091- // Load the next element address of the first dim array in sizeReg.
5092- cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg), cursor);
5093- cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, secondDimLabel, cursor);
5094- cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_B, node, controlFlowEndLabel, cursor);
5095- iComment("Allocation done!");
5112+ generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, controlFlowEndLabel);
5113+ zeroLengthSecondDimAlloc->swapInstructionListsWithCompilation();
5114+ }
5115+ #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
50965116
50975117 TR::LabelSymbol *slowPathLabel = generateLabelSymbol(cg);
50985118 cursor = generateS390LabelInstruction(cg, TR::InstOpCode::label, node, inlineAllocFailLabel, cursor);
0 commit comments