Skip to content

Commit

Permalink
Forbid creation of non-faulting null-check nodes. (#77078)
Browse files Browse the repository at this point in the history
* Forbid creation of non-faulting null-check nodes.

* Skip null check if op1 cannot be null.

* x86 bug fix for Skip gtChangeOperToNullCheck if it cannot be null.

* Fix Arm64 AVE: Do not lower indir when NOP.

* formatting fix.

* Arm64 regression bug fix that removes const bool for a variable.

* Preserve const and shorten expression.

* Fix format.

* Addressed code review feedback

* Forbid creation of non-faulting nullcheck node: Addressed feedback

* Forbid creation of non-faulting null-check nodes: Remove duplicate codes that was supposed to be deleted.
  • Loading branch information
JulieLeeMSFT authored Jan 28, 2023
1 parent ce66d01 commit 08f13dd
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 11 deletions.
6 changes: 4 additions & 2 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10013,8 +10013,8 @@ var_types Compiler::gtTypeForNullCheck(GenTree* tree)
// gtChangeOperToNullCheck: helper to change tree oper to a NULLCHECK.
//
// Arguments:
// tree - the node to change;
// basicBlock - basic block of the node.
// tree - the node to change;
// block - basic block of the node.
//
// Notes:
// the function should not be called after lowering for platforms that do not support
Expand All @@ -10026,6 +10026,8 @@ void Compiler::gtChangeOperToNullCheck(GenTree* tree, BasicBlock* block)
assert(tree->OperIs(GT_FIELD, GT_IND, GT_OBJ, GT_BLK));
tree->ChangeOper(GT_NULLCHECK);
tree->ChangeType(gtTypeForNullCheck(tree));
assert(fgAddrCouldBeNull(tree->gtGetOp1()));
tree->gtFlags |= GTF_EXCEPT;
block->bbFlags |= BBF_HAS_NULLCHECK;
optMethodFlags |= OMF_HAS_NULLCHECK;
}
Expand Down
19 changes: 16 additions & 3 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16191,11 +16191,24 @@ void Compiler::gtExtractSideEffList(GenTree* expr,
{
if (m_compiler->gtNodeHasSideEffects(node, m_flags))
{
Append(node);
if (node->OperIsBlk() && !node->OperIsStoreBlk())
{
JITDUMP("Replace an unused OBJ/BLK node [%06d] with a NULLCHECK\n", dspTreeID(node));
m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB);
// Check for a guaranteed non-faulting IND, and create a NOP node instead of a NULLCHECK in that
// case.
if (m_compiler->fgAddrCouldBeNull(node->AsBlk()->Addr()))
{
Append(node);
JITDUMP("Replace an unused OBJ/BLK node [%06d] with a NULLCHECK\n", dspTreeID(node));
m_compiler->gtChangeOperToNullCheck(node, m_compiler->compCurBB);
}
else
{
JITDUMP("Dropping non-faulting OBJ/BLK node [%06d]\n", dspTreeID(node));
}
}
else
{
Append(node);
}
return Compiler::WALK_SKIP_SUBTREES;
}
Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8215,7 +8215,15 @@ void Compiler::impImportBlockCode(BasicBlock* block)
// via an underlying address, just null check the address.
if (op1->OperIs(GT_FIELD, GT_IND, GT_OBJ))
{
gtChangeOperToNullCheck(op1, block);
GenTree* addr = op1->gtGetOp1();
if ((addr != nullptr) && fgAddrCouldBeNull(addr))
{
gtChangeOperToNullCheck(op1, block);
}
else
{
op1 = gtNewNothingNode();
}
}
else
{
Expand Down
22 changes: 17 additions & 5 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7283,13 +7283,16 @@ void Lowering::LowerIndir(GenTreeIndir* ind)
#if defined(TARGET_ARM64)
// Verify containment safety before creating an LEA that must be contained.
//
const bool isContainable = IsSafeToContainMem(ind, ind->Addr());
const bool isContainable = (ind->Addr() != nullptr) && IsSafeToContainMem(ind, ind->Addr());
#else
const bool isContainable = true;
#endif

TryCreateAddrMode(ind->Addr(), isContainable, ind);
ContainCheckIndir(ind);
if (!ind->OperIs(GT_NOP))
{
TryCreateAddrMode(ind->Addr(), isContainable, ind);
ContainCheckIndir(ind);
}

#ifdef TARGET_XARCH
if (ind->OperIs(GT_NULLCHECK) || ind->IsUnusedValue())
Expand Down Expand Up @@ -7337,14 +7340,23 @@ void Lowering::TransformUnusedIndirection(GenTreeIndir* ind, Compiler* comp, Bas
//
assert(ind->OperIs(GT_NULLCHECK, GT_IND, GT_BLK, GT_OBJ));

GenTree* const addr = ind->Addr();
if (!comp->fgAddrCouldBeNull(addr))
{
addr->SetUnusedValue();
ind->gtBashToNOP();
JITDUMP("bash an unused indir [%06u] to NOP.\n", comp->dspTreeID(ind));
return;
}

ind->ChangeType(comp->gtTypeForNullCheck(ind));

#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
bool useNullCheck = true;
#elif TARGET_ARM
#elif defined(TARGET_ARM)
bool useNullCheck = false;
#else // TARGET_XARCH
bool useNullCheck = !ind->Addr()->isContained();
bool useNullCheck = !addr->isContained();
ind->ClearDontExtend();
#endif // !TARGET_XARCH

Expand Down

0 comments on commit 08f13dd

Please sign in to comment.