From 2d3567e36c65e6684204b142f1edc2caf76bc596 Mon Sep 17 00:00:00 2001 From: Shubham Verma Date: Tue, 31 Dec 2024 14:46:13 -0500 Subject: [PATCH] p: NULL initialize dataAddr field for 0 size arrays Update array inline allocation sequence to initialize dataAddr field only for non-zero size arrays. Field should be left blank for zero size arrays. Signed-off-by: Shubham Verma --- .../compiler/p/codegen/J9TreeEvaluator.cpp | 104 ++++++++++++------ 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp index b0e8c1d91a3..2f890ffb583 100644 --- a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp +++ b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp @@ -6163,6 +6163,26 @@ static void genInitArrayHeader(TR::Node *node, TR::Instruction *&iCursor, bool i TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousArraySizeField(), 4), instanceSizeReg, iCursor); } + + // Clear padding after size field + if (needZeroInit) + { + TR_ASSERT_FATAL_WITH_NODE(node, zeroReg, "zeroReg is expected to be intialized but wasn't.\n"); + if (TR::Compiler->om.compressObjectReferences()) + { + // padding field starts at fej9->getOffsetOfDiscontiguousArraySizeField() + 4 + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node, + TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousArraySizeField() + 4, 4), + zeroReg, iCursor); + } + else + { + // padding field starts at fej9->getOffsetOfDiscontiguousArraySizeField() + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::stw, node, + TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousArraySizeField(), 4), + zeroReg, iCursor); + } + } } static void genZeroInit(TR::CodeGenerator *cg, TR::Node *node, TR::Register *objectReg, int32_t headerSize, int32_t totalSize, bool useInitInfo) @@ -6492,12 +6512,30 @@ TR::Register *J9::Power::TreeEvaluator::VMnewEvaluator(TR::Node *node, TR::CodeG * runtime size checks are needed to determine whether to use contiguous or discontiguous header layout. * * In both scenarios, arrays of non-zero size use contiguous header layout while zero size arrays use - * discontiguous header layout. + * discontiguous header layout. DataAddr field of zero size arrays is intialized to NULL because they + * don't have any data elements. */ TR::Register *offsetReg = tmp5Reg; TR::Register *firstDataElementReg = tmp4Reg; TR::MemoryReference *dataAddrSlotMR = NULL; + if (TR::Compiler->om.compressObjectReferences()) + { + TR_ASSERT_FATAL_WITH_NODE(node, + (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8, + "Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. " + "But was %d bytes for discontigous and %d bytes for contiguous array.\n", + fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField()); + } + else + { + TR_ASSERT_FATAL_WITH_NODE(node, + fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(), + "dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. " + "But was %d bytes for discontiguous and %d bytes for contiguous array.\n", + fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField()); + } + if (isVariableLen && TR::Compiler->om.compressObjectReferences()) { /* We need to check enumReg at runtime to determine correct offset of dataAddr field. @@ -6505,54 +6543,56 @@ TR::Register *J9::Power::TreeEvaluator::VMnewEvaluator(TR::Node *node, TR::CodeG * and contiguous arrays is the same in full refs. */ if (comp->getOption(TR_TraceCG)) - traceMsg(comp, "Node (%p): Dealing with compressed refs variable length array.\n", node); + traceMsg(comp, "Node (%p): Dealing with full/compressed refs variable length array.\n", node); - TR_ASSERT_FATAL_WITH_NODE(node, - (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8, - "Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. " - "But was %d bytes for discontigous and %d bytes for contiguous array.\n", - fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField()); + TR::LabelSymbol *dataAddrInitDoneLabel = generateLabelSymbol(cg); + TR::LabelSymbol *nonZeroArrayLabel = generateLabelSymbol(cg); - iCursor = generateTrg1Src1Instruction(cg, TR::InstOpCode::cntlzd, node, offsetReg, enumReg, iCursor); - iCursor = generateTrg1Src1Imm2Instruction(cg, TR::InstOpCode::rlwinm, node, offsetReg, offsetReg, 29, 8, iCursor); - // offsetReg should either be 0 (if enumReg > 0) or 8 (if enumReg == 0) - iCursor = generateTrg1Src2Instruction(cg, TR::InstOpCode::add, node, offsetReg, resReg, offsetReg, iCursor); + iCursor = generateTrg1Src1ImmInstruction(cg,TR::InstOpCode::cmpi8, node, condReg, enumReg, 0, iCursor); + iCursor = generateConditionalBranchInstruction(cg, TR::InstOpCode::bgt, node, nonZeroArrayLabel, condReg, iCursor); + // Clear dataAddr field of 0 size array + if (needZeroInit) + { + // Use zeroReg to clear the field + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, + node, + TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), 8), + zeroReg, iCursor); + } + iCursor = generateLabelInstruction(cg, TR::InstOpCode::b, node, dataAddrInitDoneLabel); - iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, offsetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor); - dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, offsetReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress()); + // Init dataAddr field for non-zero size array + iCursor = generateLabelInstruction(cg, TR::InstOpCode::label, node, nonZeroArrayLabel, iCursor); + // Load first data element address + iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor); + dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress()); + // Store the first data element address to dataAddr slot + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor); + + iCursor = generateLabelInstruction(cg, TR::InstOpCode::label, node, dataAddrInitDoneLabel, iCursor); } - else if (!isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0) + else if (needZeroInit && !isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0) { if (comp->getOption(TR_TraceCG)) traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length zero size array.\n", node); - iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), iCursor); dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress()); + + // Use zeroReg to NULL dataAddr slot + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, zeroReg, iCursor); } else { if (comp->getOption(TR_TraceCG)) - { - traceMsg(comp, - "Node (%p): Dealing with either full/compressed refs fixed length non-zero size array or full refs variable length array.\n", - node); - } - - if (!TR::Compiler->om.compressObjectReferences()) - { - TR_ASSERT_FATAL_WITH_NODE(node, - fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(), - "dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. " - "But was %d bytes for discontiguous and %d bytes for contiguous array.\n", - fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField()); - } + traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length non-zero size array.\n", node); + // Load first element address into firstDataElementReg iCursor = generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::addi, node, firstDataElementReg, resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), iCursor); dataAddrSlotMR = TR::MemoryReference::createWithDisplacement(cg, resReg, fej9->getOffsetOfContiguousDataAddrField(), TR::Compiler->om.sizeofReferenceAddress()); - } - // store the first data element address to dataAddr slot - iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor); + // Store the first data element address to dataAddr slot + iCursor = generateMemSrc1Instruction(cg, TR::InstOpCode::std, node, dataAddrSlotMR, firstDataElementReg, iCursor); + } } #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */ if (generateArraylets)