Skip to content

Commit

Permalink
For Unsafe.get()/put(), reorder blocks to optimize fallthrough path
Browse files Browse the repository at this point in the history
When offheap is enabled and the type of the object being operated on
is unknown, there are three possible cases that need to be accounted
for regarding the type of the object being operated on for
Unsafe.get()/put():

1.) array object
2.) java/lang/Class object
3.) none of the above

Since case (3) is the most likely, we want the block corresponding to
this case (directAccessBlock) to be on the fallthrough path.

Signed-off-by: midronij <[email protected]>
  • Loading branch information
midronij committed Jul 9, 2024
1 parent df0fcb1 commit cf73c72
Showing 1 changed file with 23 additions and 32 deletions.
55 changes: 23 additions & 32 deletions runtime/compiler/optimizer/InlinerTempForJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -893,14 +893,13 @@ TR_J9InlinerPolicy::genCodeForUnsafeGetPut(TR::Node* unsafeAddress,
nullComparisonBlock = prevTreeTop->getEnclosingBlock();
}

// If low-order bit of offset is set, perform indirect access. The IL for the case
// that handles conversion places the indirect access code on the fall-through
// path, so it needs to branch if the bit is not set; otherise, the indirect
// access code is on the taken path of the branch, so it needs to branch if the
// bit is set.
//
// If low-order bit of offset is set, perform indirect access. In both cases where
// a runtime lowtag check is needed (CASES 1 and 2), the direct access code is placed
// on the fallthrough path, so it will ALWAYS need to take the branch to the indirect
// access block if the bit is set.

TR::TreeTop *lowTagCmpTree = checksNeeded ? // CASES (1) and (2)
genClassCheckForUnsafeGetPut(unsafeOffset, /* branchIfLowTagged */ !conversionNeeded) : NULL;
genClassCheckForUnsafeGetPut(unsafeOffset, true) : NULL;

TR::TreeTop *firstComparisonTree;
TR::TreeTop *branchTargetTree;
Expand All @@ -916,7 +915,7 @@ TR_J9InlinerPolicy::genCodeForUnsafeGetPut(TR::Node* unsafeAddress,
{
firstComparisonTree = nullComparisonTree;
branchTargetTree = arrayDirectAccessTreeTop;
fallThroughTree = indirectAccessTreeTop;
fallThroughTree = directAccessTreeTop;
}
else if (checksNeeded && !arrayBlockNeeded) // CASE (2)
{
Expand Down Expand Up @@ -962,27 +961,26 @@ TR_J9InlinerPolicy::genCodeForUnsafeGetPut(TR::Node* unsafeAddress,

if (arrayCheckNeeded && arrayBlockNeeded) // CASE (1)
{
indirectAccessBlock = beforeCallBlock->getNextBlock();
directAccessBlock = beforeCallBlock->getNextBlock();

//Generating block for direct access
directAccessBlock = TR::Block::createEmptyBlock(lowTagCmpTree->getNode(), comp(),
indirectAccessBlock->getFrequency());
directAccessBlock->append(directAccessTreeTop);
directAccessBlock->append(
//Generating block for indirect access
indirectAccessBlock = TR::Block::createEmptyBlock(lowTagCmpTree->getNode(), comp(),
directAccessBlock->getFrequency());
indirectAccessBlock->append(indirectAccessTreeTop);
indirectAccessBlock->append(
TR::TreeTop::create(comp(),
TR::Node::create(directAccessTreeTop->getNode(),
TR::Node::create(indirectAccessTreeTop->getNode(),
TR::Goto, 0, joinBlock->getEntry())));

arrayDirectAccessBlock = firstComparisonTree->getNode()->getBranchDestination()->getNode()->getBlock();
arrayDirectAccessBlock->getExit()->insertTreeTopsAfterMe(directAccessBlock->getEntry(),
directAccessBlock->getExit());
arrayDirectAccessBlock->getExit()->insertTreeTopsAfterMe(indirectAccessBlock->getEntry(),
indirectAccessBlock->getExit());

cfg->addNode(directAccessBlock);
cfg->addEdge(TR::CFGEdge::createEdge(directAccessBlock, joinBlock, trMemory()));
cfg->addNode(indirectAccessBlock);
cfg->addEdge(TR::CFGEdge::createEdge(indirectAccessBlock, joinBlock, trMemory()));

//fix NULLCHK so that directAccessBlock is executed if object is NULL
nullComparisonTree->getNode()->setBranchDestination(directAccessBlock->getEntry());
cfg->addEdge(TR::CFGEdge::createEdge(nullComparisonBlock, directAccessBlock, trMemory()));
}
else if (checksNeeded && !arrayBlockNeeded) // CASE (2)
{
Expand Down Expand Up @@ -1050,18 +1048,11 @@ TR_J9InlinerPolicy::genCodeForUnsafeGetPut(TR::Node* unsafeAddress,
isArrayBlock = TR::Block::createEmptyBlock(vftLoad, comp(), indirectAccessBlock->getFrequency());
isArrayBlock->append(isArrayTreeTop);
cfg->addNode(isArrayBlock);
isArrayNode->setBranchDestination(arrayBlockNeeded ? arrayDirectAccessBlock->getEntry() : directAccessBlock->getEntry());
if (arrayBlockNeeded)
{
indirectAccessBlock->getEntry()->insertTreeTopsBeforeMe(lowTagCmpBlock->getEntry(), lowTagCmpBlock->getExit());
lowTagCmpTree->getNode()->setBranchDestination(directAccessBlock->getEntry());
}
else
{
traceMsg(comp(),"\t\t Generating an isArray test as j9class of java/lang/Class is NULL");
directAccessBlock->getEntry()->insertTreeTopsBeforeMe(lowTagCmpBlock->getEntry(), lowTagCmpBlock->getExit());
lowTagCmpTree->getNode()->setBranchDestination(indirectAccessBlock->getEntry());
}
isArrayNode->setBranchDestination(arrayDirectAccessBlock->getEntry());

directAccessBlock->getEntry()->insertTreeTopsBeforeMe(lowTagCmpBlock->getEntry(), lowTagCmpBlock->getExit());
lowTagCmpTree->getNode()->setBranchDestination(indirectAccessBlock->getEntry());

lowTagCmpBlock->getEntry()->insertTreeTopsBeforeMe(isArrayBlock->getEntry(),
isArrayBlock->getExit());
cfg->addEdge(TR::CFGEdge::createEdge(isArrayBlock, lowTagCmpBlock, trMemory()));
Expand Down

0 comments on commit cf73c72

Please sign in to comment.