@@ -4916,21 +4916,10 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
49164916      }
49174917
49184918   TR::LabelSymbol *zeroSecondDimLabel = generateLabelSymbol(cg);
4919- #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
4920-    bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
4921-    if (isOffHeapAllocationEnabled)
4922-       {
4923-       // Call helper if dim2 length is negative, zero, or larger that INT32_MAX (overflow).
4924-       cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRNP, node, inlineAllocFailLabel, cursor);
4925-       }
4926-    else
4927- #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
4928-       {
4929-       // Bypass dim2 size calculation if the size is zero.
4930-       cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor);
4931-       // Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow).
4932-       cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK5, node, inlineAllocFailLabel, cursor);
4933-       }
4919+    // Bypass dim2 size calculation if the size is zero.
4920+    cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor);
4921+    // Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow).
4922+    cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_MASK5, node, inlineAllocFailLabel, cursor);
49344923
49354924   int32_t headerSize= TR::Compiler->om.contiguousArrayHeaderSizeInBytes();
49364925   // size = (size + alignmentConstant - 1) & -alignmentConstant equation round up the size to a factor of alignmentConstant.
@@ -5038,12 +5027,17 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50385027      generateS390MemoryReference(resultReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor);
50395028
50405029#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5030+    bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
50415031   if (isOffHeapAllocationEnabled)
50425032      {
50435033      // Store first element's address in data address field.
50445034      cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, sizeReg, generateS390MemoryReference(resultReg, fej9->getOffsetOfContiguousDataAddrField(), cg), cursor);
50455035      // 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.
50465036      cursor = generateRILInstruction(cg, TR::InstOpCode::SLFI, node, dim2SizeReg, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cursor);
5037+       // The length of the second dimension is stored in the upper 32 bits of the scratch register.
5038+       // 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.
5039+       cursor = generateRREInstruction(cg, TR::InstOpCode::CGFR, node, scratchReg, scratchReg, cursor);
5040+       // The condition code has already been set and must remain unchanged during the second dimension allocation loop in this code path.
50475041      }
50485042#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
50495043
@@ -5057,34 +5051,54 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
50575051   cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, scratchReg, generateS390MemoryReference(dim1SizeReg,
50585052      static_cast<int32_t>(TR::Compiler->om.offsetOfContiguousArraySizeField()), cg), cursor);
50595053   int32_t shiftAmount = TR::Compiler->om.compressedReferenceShift();
5060-    if (shiftAmount > 0)
5061-       {
5062-       // Calculate the compressed reference of leaf array in the higher 32bits of dim2SizeReg.
5063-       cursor = generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount, cursor);
5064-       // Store the compressed 32 bit leaf address in the relevant element of the first dim array.
5065-       cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5066-       }
5067-    else
5054+ 
5055+    if (shiftAmount == 0)
50685056      {
5069-       // Store the 32 bit  leaf address in the relevant element of the first dim array.
5057+       // Store the leaf address in the relevant element of the first dim array.
50705058      cursor = generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, dim1SizeReg,
50715059         generateS390MemoryReference(sizeReg, 0, cg), cursor);
50725060      }
50735061
50745062#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
50755063   if (isOffHeapAllocationEnabled)
50765064      {
5065+       if (shiftAmount > 0)
5066+          {
5067+          // Compress the leaf array reference and store it in the first element of the dimension array.
5068+          // Avoid using any instructions that could affect the branch condition in this code path.
5069+          cursor = generateRSInstruction(cg, TR::InstOpCode::SRLG, node, dim1SizeReg, dim1SizeReg, shiftAmount, cursor);
5070+          cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, dim1SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5071+          // Decompress the leaf array reference.
5072+          cursor = generateRSInstruction(cg, TR::InstOpCode::SLLG, node, dim1SizeReg, dim1SizeReg, shiftAmount, cursor);
5073+          }
50775074      // Load the first element address.
50785075      cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg,
50795076         generateS390MemoryReference(dim1SizeReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor);
5080-       // Store the first element address in data address field.
5081-       cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg,
5082-          (fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor);
5077+       // Store the address of the first element in the data address field only if the second dimension length is non-zero.
5078+       cursor = generateRSInstruction(cg, TR::InstOpCode::STOCG, node, dim1SizeReg, getMaskForBranchCondition(TR::InstOpCode::COND_BNE),
5079+          generateS390MemoryReference(dim1SizeReg, (fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor);
5080+       // Load the next leaf address in dim1SizeReg.
5081+       cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, dim2SizeReg, 0, cg), cursor);
50835082      }
5083+    else
50845084#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5085+       {
5086+       if (shiftAmount > 0)
5087+          {
5088+          // Calculate the compressed reference of leaf array in the higher 32bits of dim2SizeReg.
5089+          cursor = generateRIEInstruction(cg, TR::InstOpCode::RISBG, node, dim2SizeReg, dim1SizeReg, 0, 31, 32-shiftAmount, cursor);
5090+          // Store the compressed 32 bit leaf address in the relevant element of the first dim array.
5091+          cursor = generateRXInstruction(cg, TR::InstOpCode::STFH, node, dim2SizeReg, generateS390MemoryReference(sizeReg, 0, cg), cursor);
5092+          // Load the next leaf address in dim1SizeReg.
5093+          cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor);
5094+          }
5095+       else
5096+          {
5097+          // Load the next leaf address in dim1SizeReg.
5098+          cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, dim2SizeReg, 0, cg), cursor);
5099+          }
5100+       }
50855101
5086-    // Load the next leaf address in dim1SizeReg.
5087-    cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor);
50885102   // Load the next element address of the first dim array in sizeReg.
50895103   cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg), cursor);
50905104   cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, secondDimLabel, cursor);
0 commit comments