@@ -4871,7 +4871,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
4871
4871
4872
4872
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
4873
4873
bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled();
4874
- TR::LabelSymbol *populateFirstDimDataAddrSlot = isOffHeapAllocationEnabled ? generateLabelSymbol(cg) : NULL;
4875
4874
#endif /* defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) */
4876
4875
4877
4876
// oolJumpLabel is a common point that all branches will jump to. From this label, we branch to OOL code.
@@ -4889,12 +4888,13 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
4889
4888
TR::Register *classReg = cg->evaluate(thirdChild);
4890
4889
4891
4890
// In the mainline, first load the first and second dimensions' lengths into registers.
4891
+ TR::InstOpCode::Mnemonic loadDimLenOpCode = TR::InstOpCode::LGF;
4892
4892
TR::Register *firstDimLenReg = cg->allocateRegister();
4893
- cursor = generateRXInstruction(cg, TR::InstOpCode::LGF , node, firstDimLenReg, generateS390MemoryReference(dimsPtrReg, 4, cg));
4893
+ cursor = generateRXInstruction(cg, loadDimLenOpCode , node, firstDimLenReg, generateS390MemoryReference(dimsPtrReg, 4, cg));
4894
4894
iComment("Load 1st dim length.");
4895
4895
4896
4896
TR::Register *secondDimLenReg = cg->allocateRegister();
4897
- cursor = generateRXInstruction(cg, TR::InstOpCode::L , node, secondDimLenReg, generateS390MemoryReference(dimsPtrReg, 0, cg));
4897
+ cursor = generateRXInstruction(cg, loadDimLenOpCode , node, secondDimLenReg, generateS390MemoryReference(dimsPtrReg, 0, cg));
4898
4898
iComment("Load 2nd dim length.");
4899
4899
4900
4900
// Check to see if second dimension is indeed 0. If yes, then proceed to handle the case here. Otherwise jump to OOL code.
@@ -4948,33 +4948,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
4948
4948
iComment("Init 1st dim mustBeZero field.");
4949
4949
cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, firstDimLenReg, generateS390MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg));
4950
4950
iComment("Init 1st dim size field.");
4951
- }
4952
-
4953
4951
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
4954
- if (isOffHeapAllocationEnabled)
4955
- {
4956
- TR_ASSERT_FATAL_WITH_NODE(node,
4957
- (TR::Compiler->om.compressObjectReferences()
4958
- && (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8)
4959
- || (!TR::Compiler->om.compressObjectReferences()
4960
- && fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField()),
4961
- "Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array if using compressed refs, "
4962
- "or same if using full refs. But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
4963
- fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
4964
-
4965
- // Load dataAddr slot offset difference since 0 size arrays are treated as discontiguous.
4966
- generateRIInstruction(cg,
4967
- TR::InstOpCode::LGHI,
4968
- node,
4969
- temp1Reg,
4970
- static_cast<int32_t>(fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()));
4971
- cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, populateFirstDimDataAddrSlot);
4972
- }
4973
- else
4952
+ if (isOffHeapAllocationEnabled)
4953
+ {
4954
+ TR_ASSERT_FATAL_WITH_NODE(node,
4955
+ TR::InstOpCode::LGF == loadDimLenOpCode,
4956
+ "LGF must be used to load 1st dimension length into firstDimLenReg. "
4957
+ "Array size field is 32 bits in size but dataAddr slot is 64 bits so "
4958
+ "to use the same register to intialize dataAddr slot we must clean "
4959
+ "out top 32 bits of firstDimLenReg. LGF sign extends 32 bit 1st dim "
4960
+ "size to 64 bits enabling us to use firstDimLenReg to write NULL in "
4961
+ "the dataAddr field for 0 length arrays.\n");
4962
+ cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, firstDimLenReg, generateS390MemoryReference(targetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
4963
+ iComment("Clear 1st dim dataAddr field.");
4964
+ }
4974
4965
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
4975
- {
4976
- cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
4977
4966
}
4967
+
4968
+ cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
4978
4969
iComment("Init class field and jump.");
4979
4970
4980
4971
// We end up in this region of the ICF if the first dimension is non-zero and the second dimension is zero.
@@ -5056,27 +5047,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
5056
5047
iComment("Init 2st dim mustBeZero field.");
5057
5048
cursor = generateRXInstruction(cg, TR::InstOpCode::ST, node, secondDimLenReg, generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousArraySizeField(), cg));
5058
5049
iComment("Init 2st dim size field.");
5059
- }
5060
-
5061
- TR::Register *temp3Reg = cg->allocateRegister();
5062
-
5063
5050
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5064
- if (isOffHeapAllocationEnabled)
5065
- {
5066
- // Populate dataAddr slot for 2nd dimension zero size array.
5067
- generateRXInstruction(cg,
5068
- TR::InstOpCode::LA,
5069
- node,
5070
- temp3Reg,
5071
- generateS390MemoryReference(temp2Reg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg));
5072
- generateRXInstruction(cg,
5073
- TR::InstOpCode::STG,
5074
- node,
5075
- temp3Reg,
5076
- generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
5077
- }
5051
+ if (isOffHeapAllocationEnabled)
5052
+ {
5053
+ TR_ASSERT_FATAL_WITH_NODE(node,
5054
+ TR::InstOpCode::LGF == loadDimLenOpCode,
5055
+ "LGF must be used to load 2nd dimension length into secondDimLenReg. "
5056
+ "Array size field is 32 bits in size but dataAddr slot is 64 bits so "
5057
+ "to use the same register to intialize dataAddr slot we must clean "
5058
+ "out top 32 bits of secondDimLenReg. LGF sign extends 32 bit 2nd dim "
5059
+ "size to 64 bits enabling us to use secondDimLenReg to write NULL in "
5060
+ "the dataAddr field for 0 length arrays.\n");
5061
+ cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, secondDimLenReg, generateS390MemoryReference(temp2Reg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg));
5062
+ iComment("Clear 2nd dim dataAddr field.");
5063
+ }
5078
5064
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5065
+ }
5079
5066
5067
+ TR::Register *temp3Reg = cg->allocateRegister();
5080
5068
// Store 2nd dim element into 1st dim array slot, compress temp2 if needed
5081
5069
if (comp->target().is64Bit() && comp->useCompressedPointers())
5082
5070
{
@@ -5103,15 +5091,24 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
5103
5091
#if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5104
5092
if (isOffHeapAllocationEnabled)
5105
5093
{
5106
- // No offset is needed since 1st dimension array is contiguous.
5107
- generateRRInstruction(cg, TR::InstOpCode::getXORRegOpCode(), node, temp1Reg, temp1Reg);
5108
- generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, populateFirstDimDataAddrSlot);
5094
+ /* Populate dataAddr slot of 1st dimension array. We don't need to worry
5095
+ * about zero length array since it has already been taken care of.
5096
+ */
5097
+ generateRXInstruction(cg,
5098
+ TR::InstOpCode::LA,
5099
+ node,
5100
+ temp3Reg,
5101
+ generateS390MemoryReference(targetReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg));
5102
+ cursor = generateRXInstruction(cg,
5103
+ TR::InstOpCode::STG,
5104
+ node,
5105
+ temp3Reg,
5106
+ generateS390MemoryReference(targetReg, fej9->getOffsetOfContiguousDataAddrField(), cg));
5107
+ iComment("populateFirstDimDataAddrSlot.");
5109
5108
}
5110
- else
5111
5109
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5112
- {
5113
- generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
5114
- }
5110
+
5111
+ generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, cFlowRegionDone);
5115
5112
5116
5113
TR::RegisterDependencyConditions *dependencies = generateRegisterDependencyConditions(0,10,cg);
5117
5114
dependencies->addPostCondition(dimReg, TR::RealRegister::AssignAny);
@@ -5128,28 +5125,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node,
5128
5125
generateS390LabelInstruction(cg, TR::InstOpCode::label, node, oolJumpLabel);
5129
5126
generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, oolFailLabel);
5130
5127
5131
- #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION)
5132
- if (isOffHeapAllocationEnabled)
5133
- {
5134
- /* Populate dataAddr slot of 1st dimension array. Arrays of non-zero size
5135
- * use contiguous header layout while zero size arrays use discontiguous header layout.
5136
- */
5137
- cursor = generateS390LabelInstruction(cg, TR::InstOpCode::label, node, populateFirstDimDataAddrSlot);
5138
- iComment("populateFirstDimDataAddrSlot.");
5139
-
5140
- generateRXInstruction(cg,
5141
- TR::InstOpCode::LA,
5142
- node,
5143
- temp3Reg,
5144
- generateS390MemoryReference(targetReg, temp1Reg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg));
5145
- generateRXInstruction(cg,
5146
- TR::InstOpCode::STG,
5147
- node,
5148
- temp3Reg,
5149
- generateS390MemoryReference(targetReg, temp1Reg, fej9->getOffsetOfContiguousDataAddrField(), cg));
5150
- }
5151
- #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
5152
-
5153
5128
generateS390LabelInstruction(cg, TR::InstOpCode::label, node, cFlowRegionDone, dependencies);
5154
5129
5155
5130
TR::Register *targetRegisterFinal = cg->allocateCollectedReferenceRegister();
@@ -11119,81 +11094,17 @@ J9::Z::TreeEvaluator::VMnewEvaluator(TR::Node * node, TR::CodeGenerator * cg)
11119
11094
#ifdef J9VM_GC_SPARSE_HEAP_ALLOCATION
11120
11095
if (TR::Compiler->om.isOffHeapAllocationEnabled())
11121
11096
{
11122
- /* Here we'll update dataAddr slot for both fixed and variable length arrays. Fixed length arrays are
11123
- * simple as we just need to check first child of the node for array size. For variable length arrays
11124
- * runtime size checks are needed to determine whether to use contiguous or discontiguous header layout.
11125
- *
11126
- * In both scenarios, arrays of non-zero size use contiguous header layout while zero size arrays use
11127
- * discontiguous header layout.
11097
+ /* Here we'll update dataAddr slot for fixed and variable non-zero length arrays. DataAddr field
11098
+ * should be left blank for zero length arrays.
11128
11099
*/
11129
- TR::Register *offsetReg = NULL;
11130
- TR::MemoryReference *dataAddrMR = NULL;
11131
- TR::MemoryReference *dataAddrSlotMR = NULL;
11132
-
11133
- if (isVariableLen && TR::Compiler->om.compressObjectReferences())
11134
- {
11135
- /* We need to check enumReg (array size) at runtime to determine correct offset of dataAddr field.
11136
- * Here we deal only with compressed refs because dataAddr offset for discontiguous
11137
- * and contiguous arrays is the same in full refs.
11138
- */
11139
- if (comp->getOption(TR_TraceCG))
11140
- traceMsg(comp, "Node (%p): Dealing with compressed refs variable length array.\n", node);
11141
-
11142
- TR_ASSERT_FATAL_WITH_NODE(node,
11143
- (fej9->getOffsetOfDiscontiguousDataAddrField() - fej9->getOffsetOfContiguousDataAddrField()) == 8,
11144
- "Offset of dataAddr field in discontiguous array is expected to be 8 bytes more than contiguous array. "
11145
- "But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
11146
- fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
11147
-
11148
- offsetReg = cg->allocateRegister();
11149
- // Invert enumReg sign. 0 and negative numbers remain unchanged.
11150
- iCursor = generateRREInstruction(cg, TR::InstOpCode::LNGFR, node, offsetReg, enumReg, iCursor);
11151
- iCursor = generateRSInstruction(cg, TR::InstOpCode::SRLG, node, dataSizeReg, offsetReg, 63, iCursor);
11152
- iCursor = generateRSInstruction(cg, TR::InstOpCode::SLLG, node, offsetReg, dataSizeReg, 3, iCursor);
11153
- // Inverting the sign bit will leave us with either -8 (if enumCopyReg > 0) or 0 (if enumCopyReg == 0).
11154
- iCursor = generateRREInstruction(cg, TR::InstOpCode::LNGR, node, offsetReg, offsetReg, iCursor);
11155
-
11156
- dataAddrMR = generateS390MemoryReference(resReg, offsetReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg);
11157
- dataAddrSlotMR = generateS390MemoryReference(resReg, offsetReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg);
11158
- }
11159
- else if (!isVariableLen && node->getFirstChild()->getOpCode().isLoadConst() && node->getFirstChild()->getInt() == 0)
11160
- {
11161
- if (comp->getOption(TR_TraceCG))
11162
- traceMsg(comp, "Node (%p): Dealing with full/compressed refs fixed length zero size array.\n", node);
11163
-
11164
- dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), cg);
11165
- dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfDiscontiguousDataAddrField(), cg);
11166
- }
11167
- else
11168
- {
11169
- if (comp->getOption(TR_TraceCG))
11170
- {
11171
- traceMsg(comp,
11172
- "Node (%p): Dealing with either full/compressed refs fixed length non-zero size array or full refs variable length array.\n",
11173
- node);
11174
- }
11175
-
11176
- if (!TR::Compiler->om.compressObjectReferences())
11177
- {
11178
- TR_ASSERT_FATAL_WITH_NODE(node,
11179
- fej9->getOffsetOfDiscontiguousDataAddrField() == fej9->getOffsetOfContiguousDataAddrField(),
11180
- "dataAddr field offset is expected to be same for both contiguous and discontiguous arrays in full refs. "
11181
- "But was %d bytes for discontiguous and %d bytes for contiguous array.\n",
11182
- fej9->getOffsetOfDiscontiguousDataAddrField(), fej9->getOffsetOfContiguousDataAddrField());
11183
- }
11184
-
11185
- dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
11186
- dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
11187
- }
11100
+ TR::MemoryReference *dataAddrMR = generateS390MemoryReference(resReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg);
11101
+ TR::MemoryReference *dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
11188
11102
11103
+ dataAddrSlotMR = generateS390MemoryReference(resReg, fej9->getOffsetOfContiguousDataAddrField(), cg);
11189
11104
iCursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dataSizeReg, dataAddrMR, iCursor);
11190
- iCursor = generateRXInstruction (cg, TR::InstOpCode::STG , node, dataSizeReg, dataAddrSlotMR , iCursor);
11105
+ iCursor = generateRILInstruction (cg, TR::InstOpCode::CFI , node, enumReg, 0 , iCursor);
11191
11106
11192
- if (offsetReg)
11193
- {
11194
- conditions->addPostCondition(offsetReg, TR::RealRegister::AssignAny);
11195
- cg->stopUsingRegister(offsetReg);
11196
- }
11107
+ iCursor = generateRSInstruction(cg, TR::InstOpCode::STOCG, node, dataSizeReg, static_cast<uint32_t>(0x2), dataAddrSlotMR, iCursor);
11197
11108
}
11198
11109
#endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */
11199
11110
0 commit comments