Skip to content

Commit

Permalink
DetectPinnedRegions: Inline the stack-slot involved in CustomRefPinPa…
Browse files Browse the repository at this point in the history
…ttern so that the following ProcessPinnedRegion call can reuse existing unmanaged pointer variables instead of being forced to create a new variable.

(cherry picked from commit 3c2e528)
  • Loading branch information
siegfriedpammer authored and dgrunwald committed Apr 3, 2022
1 parent b2fba46 commit 732d82b
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
14 changes: 7 additions & 7 deletions ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,13 +422,13 @@ public unsafe void FixedSpan(Span<int> span)
#endif

#if CS73
//public unsafe void FixedCustomReferenceType(CustomPinnable mem)
//{
// fixed (int* ptr = mem)
// {
// UsePointer(ptr);
// }
//}
public unsafe void FixedCustomReferenceType(CustomPinnable mem)
{
fixed (int* ptr = mem)
{
UsePointer(ptr);
}
}

public unsafe void FixedCustomReferenceTypeNoPointerUse(CustomPinnable mem)
{
Expand Down
28 changes: 24 additions & 4 deletions ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ void DetectNullSafeArrayToPointerOrCustomRefPin(BlockContainer container)
((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
modified = true;
}
else if (IsCustomRefPinPattern(block, out ILInstruction ldlocMem, out var callGPR, out v, out var stlocPtr, out targetBlock))
else if (IsCustomRefPinPattern(block, out ILInstruction ldlocMem, out var callGPR, out v, out var stlocPtr,
out targetBlock, out var nullBlock, out var notNullBlock))
{
context.Step("CustomRefPinPattern", block);
ILInstruction gpr;
Expand All @@ -197,6 +198,20 @@ void DetectNullSafeArrayToPointerOrCustomRefPin(BlockContainer container)
block.Instructions.Insert(block.Instructions.Count - 1, stlocPtr);
}
((Branch)block.Instructions.Last()).TargetBlock = targetBlock;
// clear out internal blocks that are now unreachable, so that
// targetBlock.IncomingEdgeCount is accurate at this point.
nullBlock?.Instructions.Clear();
notNullBlock.Instructions.Clear();
if (targetBlock.IncomingEdgeCount == 1 && targetBlock.Parent == block.Parent)
{
block.Instructions.RemoveLast();
block.Instructions.AddRange(targetBlock.Instructions);
targetBlock.Instructions.Clear();
if (stlocPtr != null)
{
ILInlining.InlineOneIfPossible(block, stlocPtr.ChildIndex, InliningOptions.None, context);
}
}
modified = true;
}
}
Expand Down Expand Up @@ -226,13 +241,15 @@ void DetectNullSafeArrayToPointerOrCustomRefPin(BlockContainer container)
// stloc ptr(conv ref->u (ldloc V_1))
// br targetBlock
private bool IsCustomRefPinPattern(Block block, out ILInstruction ldlocMem, out CallInstruction callGPR,
out ILVariable v, out StLoc ptrAssign, out Block targetBlock)
out ILVariable v, out StLoc ptrAssign, out Block targetBlock, out Block nullBlock, out Block notNullBlock)
{
ldlocMem = null;
callGPR = null;
v = null;
ptrAssign = null;
targetBlock = null;
nullBlock = null;
notNullBlock = null;
// if (comp.o(ldloc mem != ldnull)) br on_not_null
// br on_null
if (!block.MatchIfAtEndOfBlock(out var ifCondition, out var trueInst, out var falseInst))
Expand All @@ -250,9 +267,9 @@ private bool IsCustomRefPinPattern(Block block, out ILInstruction ldlocMem, out
}
if (!SemanticHelper.IsPure(ldlocMem.Flags))
return false;
if (!trueInst.MatchBranch(out Block notNullBlock) || notNullBlock.Parent != block.Parent)
if (!trueInst.MatchBranch(out notNullBlock) || notNullBlock.Parent != block.Parent)
return false;
if (!falseInst.MatchBranch(out Block nullBlock) || nullBlock.Parent != block.Parent)
if (!falseInst.MatchBranch(out nullBlock) || nullBlock.Parent != block.Parent)
return false;

// Block notNullBlock (incoming: 1) {
Expand Down Expand Up @@ -309,6 +326,9 @@ private bool IsCustomRefPinPattern(Block block, out ILInstruction ldlocMem, out

if (targetBlock != nullBlock)
return false;
// nullBlock must be set to null, so that
// we do not clear out targetBlock in the caller.
nullBlock = null;
}
return true;
}
Expand Down

0 comments on commit 732d82b

Please sign in to comment.