-
Notifications
You must be signed in to change notification settings - Fork 778
Add support for offheap allocation in multianewarray evaluator on IBM Z platform #22797
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
81cbba3
9229e51
03e3d37
e9a7d49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4885,10 +4885,6 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node, | |
|
|
||
| TR::Register *dim2SizeReg = cg->allocateRegister(); | ||
| dependencies->addPostCondition(dim2SizeReg, TR::RealRegister::AssignAny); | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::LTGF, node, dim2SizeReg, generateS390MemoryReference(dimsPtrReg, 0, cg), cursor); | ||
ehsankianifar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| iComment("Load 2st dim length."); | ||
| // The size of zero length array is already loaded in size register. Jump over the array size calculation instructions if length is 0. | ||
| TR::LabelSymbol *zeroSecondDimLabel = generateLabelSymbol(cg); | ||
|
|
||
| if (componentSize == 1) | ||
| { | ||
|
|
@@ -4907,6 +4903,9 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node, | |
| // allocate inline is not frequent. | ||
| cursor = generateRSInstruction(cg, TR::InstOpCode::SLA, node, dim2SizeReg, trailingZeroes(componentSize), cursor); | ||
| } | ||
|
|
||
| TR::LabelSymbol *zeroSecondDimLabel = generateLabelSymbol(cg); | ||
|
|
||
| // Bypass dim2 size calculation if the size is zero. | ||
| cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BZ, node, zeroSecondDimLabel, cursor); | ||
| // Call helper if the length is negative or length * componentSize is larger that INT32_MAX (overflow). | ||
|
|
@@ -5016,6 +5015,25 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node, | |
| // Load the address of the first element of the first dimension array in sizeReg. | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, | ||
| generateS390MemoryReference(resultReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor); | ||
|
|
||
| #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) | ||
| bool isOffHeapAllocationEnabled = TR::Compiler->om.isOffHeapAllocationEnabled(); | ||
| TR::LabelSymbol *zeroLengthSecondDimLabel = NULL; | ||
| if (isOffHeapAllocationEnabled) | ||
| { | ||
| // Store first element's address in data address field. | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, sizeReg, generateS390MemoryReference(resultReg, fej9->getOffsetOfContiguousDataAddrField(), cg), cursor); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If leaf array size is 0, won't we completely miss initializing dataAddr slot for 1st dimension array?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No this code will be executed if the first dimension length is not zero.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah ok, I got confused by the comments. All clear now |
||
| // If the second dimension length is zero, allocate the leaf array OOL. | ||
| zeroLengthSecondDimLabel = generateLabelSymbol(cg); | ||
| // The length of the second dimension is stored in the upper 32 bits of the scratch register. | ||
| // 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. | ||
| cursor = generateRREInstruction(cg, TR::InstOpCode::CGFR, node, scratchReg, scratchReg, cursor); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, this was one of the reason originally I asked / recommended not to have values fused together before storing it. Can you explain the check here ? Lower half is zero and comparison would upperhalf with lowerhalf and upperhalf and CC is set ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is the most efficient way to check if the second dim is zero without extra loading or using extra registers.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be, not questioning that. I want to confirm my understanding of the logic here, so that I can continue review.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry I misunderstood the question earlier. |
||
| cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BE, node, zeroLengthSecondDimLabel, cursor); | ||
| // 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. | ||
| cursor = generateRILInstruction(cg, TR::InstOpCode::SLFI, node, dim2SizeReg, (int32_t)TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cursor); | ||
| } | ||
| #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */ | ||
|
|
||
| // Start setting second dim: | ||
| TR::LabelSymbol *secondDimLabel = generateLabelSymbol(cg); | ||
| cursor = generateS390LabelInstruction(cg, TR::InstOpCode::label, node, secondDimLabel, cursor); | ||
|
|
@@ -5035,18 +5053,63 @@ static TR::Register * generateMultianewArrayWithInlineAllocators(TR::Node *node, | |
| } | ||
| else | ||
| { | ||
| // Store the 32 bit leaf address in the relevant element of the first dim array. | ||
| // Store the leaf address in the relevant element of the first dim array. | ||
| cursor = generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, dim1SizeReg, | ||
| generateS390MemoryReference(sizeReg, 0, cg), cursor); | ||
| } | ||
|
|
||
| #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) | ||
| if (isOffHeapAllocationEnabled) | ||
| { | ||
| // Load the first element address. | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, | ||
| generateS390MemoryReference(dim1SizeReg, TR::Compiler->om.contiguousArrayHeaderSizeInBytes(), cg), cursor); | ||
| // Store the first element address in data address field. | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::STG, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, | ||
| (fej9->getOffsetOfContiguousDataAddrField() - TR::Compiler->om.contiguousArrayHeaderSizeInBytes()), cg), cursor); | ||
| } | ||
| #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */ | ||
|
|
||
| // Load the next leaf address in dim1SizeReg. | ||
| cursor = generateRREInstruction(cg, TR::InstOpCode::ALGFR, node, dim1SizeReg, dim2SizeReg, cursor); | ||
| // Load the next element address of the first dim array in sizeReg. | ||
| cursor = generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg), cursor); | ||
| cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, secondDimLabel, cursor); | ||
| cursor = generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_B, node, controlFlowEndLabel, cursor); | ||
| iComment("Allocation done!"); | ||
|
|
||
| /********************************************* OOL zero length offheap leaf allocator *********************************************/ | ||
| #if defined(J9VM_GC_SPARSE_HEAP_ALLOCATION) | ||
| if (isOffHeapAllocationEnabled) | ||
| { | ||
| TR_S390OutOfLineCodeSection *zeroLengthSecondDimAlloc = new (cg->trHeapMemory()) TR_S390OutOfLineCodeSection(zeroLengthSecondDimLabel, controlFlowEndLabel, cg); | ||
| cg->getS390OutOfLineCodeSectionList().push_front(zeroLengthSecondDimAlloc); | ||
| zeroLengthSecondDimAlloc->swapInstructionListsWithCompilation(); | ||
| generateS390LabelInstruction(cg, TR::InstOpCode::label, node, zeroLengthSecondDimLabel); | ||
|
|
||
| // Store the class field. | ||
| generateRXInstruction(cg, (compressedObjectHeaders ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, classReg, | ||
| generateS390MemoryReference(dim1SizeReg, static_cast<int32_t>(TR::Compiler->om.offsetOfObjectVftField()), cg)); | ||
| TR::Register *leafArrayRefReg = dim1SizeReg; | ||
| if (shiftAmount > 0) | ||
| { | ||
| leafArrayRefReg = dim2SizeReg; | ||
| // Calculate the compressed reference of leaf array in leafArrayRefReg. | ||
| generateRSInstruction(cg, TR::InstOpCode::SRLG, node, leafArrayRefReg, dim1SizeReg, shiftAmount); | ||
| } | ||
| // Store the leaf address in the relevant element of the first dim array. | ||
| generateRXInstruction(cg, (TR::Compiler->om.compressObjectReferences() ? TR::InstOpCode::ST : TR::InstOpCode::STG), node, leafArrayRefReg, | ||
| generateS390MemoryReference(sizeReg, 0, cg)); | ||
| // Load the next leaf address in dim1SizeReg. | ||
| size_t leafArraySize = OMR::align(TR::Compiler->om.discontiguousArrayHeaderSizeInBytes(), alignmentConstant); | ||
| generateRXInstruction(cg, TR::InstOpCode::LA, node, dim1SizeReg, generateS390MemoryReference(dim1SizeReg, leafArraySize, cg)); | ||
| // Load the next element address of the first dim array in sizeReg. | ||
| generateRXInstruction(cg, TR::InstOpCode::LA, node, sizeReg, generateS390MemoryReference(sizeReg, elementSize, cg)); | ||
| generateS390BranchInstruction(cg, TR::InstOpCode::BRCT, node, scratchReg, zeroLengthSecondDimLabel); | ||
|
|
||
| generateS390BranchInstruction(cg, TR::InstOpCode::BRC, TR::InstOpCode::COND_BRC, node, controlFlowEndLabel); | ||
| zeroLengthSecondDimAlloc->swapInstructionListsWithCompilation(); | ||
| } | ||
| #endif /* J9VM_GC_SPARSE_HEAP_ALLOCATION */ | ||
|
|
||
| TR::LabelSymbol *slowPathLabel = generateLabelSymbol(cg); | ||
| cursor = generateS390LabelInstruction(cg, TR::InstOpCode::label, node, inlineAllocFailLabel, cursor); | ||
|
|
@@ -5107,9 +5170,7 @@ J9::Z::TreeEvaluator::multianewArrayEvaluator(TR::Node * node, TR::CodeGenerator | |
|
|
||
| if ((nDims == 2) && (componentSize > 0) | ||
| && comp->target().cpu.isAtLeast(OMR_PROCESSOR_S390_Z196) | ||
| && !comp->suppressAllocationInlining() | ||
| // Temporarily disable inline allocation for offHeap. | ||
| && !TR::Compiler->om.isOffHeapAllocationEnabled()) | ||
| && !comp->suppressAllocationInlining()) | ||
| { | ||
| return generateMultianewArrayWithInlineAllocators(node, cg, componentSize); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a FYI, these changes are in https://github.com/eclipse-openj9/openj9/pull/22562/files as well so there might be a conflict if that PR goes in first.