Skip to content

Commit 023bb11

Browse files
Copilotdadhi
andauthored
refactor: simplify expr node equality precheck
Agent-Logs-Url: https://github.com/dadhi/FastExpressionCompiler/sessions/5b87e13e-991a-4ea4-aab8-266df9dda7fd Co-authored-by: dadhi <39516+dadhi@users.noreply.github.com>
1 parent a1f952f commit 023bb11

1 file changed

Lines changed: 121 additions & 102 deletions

File tree

src/FastExpressionCompiler.LightExpression/FlatExpression.cs

Lines changed: 121 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public struct ExprNode
6161
private const uint MetaKeepWithoutNext = 0xFFFF0000u;
6262
// _data layout: bits [31:16]=ChildCount | [15:0]=ChildIdx (or full uint for inline constants)
6363
private const int DataCountShift = 16;
64+
private const uint DataKeepWithoutChildIdx = 0xFFFF0000u;
6465
private const uint DataIdxMask = 0xFFFFu;
6566
private const int FlagsShift = 4;
6667
private const uint KindMask = 0x0Fu;
@@ -139,6 +140,19 @@ internal void SetChildInfo(int childIdx, int childCount) =>
139140
[MethodImpl(MethodImplOptions.AggressiveInlining)]
140141
internal bool HasFlag(byte flag) => (Flags & flag) != 0;
141142

143+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
144+
internal bool HasSameHeaderExceptNext(ref ExprNode other) =>
145+
Type == other.Type && (_meta & MetaKeepWithoutNext) == (other._meta & MetaKeepWithoutNext);
146+
147+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
148+
internal bool HasSameShapeExceptLinks(ref ExprNode other) =>
149+
HasSameHeaderExceptNext(ref other) &&
150+
(_data & DataKeepWithoutChildIdx) == (other._data & DataKeepWithoutChildIdx);
151+
152+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
153+
internal bool HasSameShapeExceptNext(ref ExprNode other) =>
154+
HasSameHeaderExceptNext(ref other) && _data == other._data;
155+
142156
[MethodImpl(MethodImplOptions.AggressiveInlining)]
143157
internal bool ShouldCloneWhenLinked() =>
144158
ReferenceEquals(Obj, InlineValueMarker) ||
@@ -1646,7 +1660,17 @@ public bool Eq(ref ExprTree xTree, ref ExprTree yTree)
16461660
{
16471661
ref var x = ref xTree.Nodes.GetSurePresentRef(xIdx);
16481662
ref var y = ref yTree.Nodes.GetSurePresentRef(yIdx);
1649-
if (x.Kind != y.Kind || x.NodeType != y.NodeType || x.Type != y.Type || x.Flags != y.Flags)
1663+
if (x.Kind == ExprNodeKind.UInt16Pair)
1664+
{
1665+
if (!x.HasSameShapeExceptNext(ref y))
1666+
return false;
1667+
}
1668+
else if (x.NodeType == ExpressionType.Constant)
1669+
{
1670+
if (!x.HasSameHeaderExceptNext(ref y))
1671+
return false;
1672+
}
1673+
else if (!x.HasSameShapeExceptLinks(ref y))
16501674
return false;
16511675

16521676
var descendX = 0;
@@ -1655,122 +1679,117 @@ public bool Eq(ref ExprTree xTree, ref ExprTree yTree)
16551679
var restoreXParameterCount = -1;
16561680
var restoreYParameterCount = -1;
16571681

1658-
if (x.Kind == ExprNodeKind.LabelTarget)
1682+
if (x.Kind != ExprNodeKind.UInt16Pair)
16591683
{
1660-
if (!EqLabelTarget(ref x, ref y))
1661-
return false;
1662-
}
1663-
else if (x.Kind == ExprNodeKind.UInt16Pair)
1664-
{
1665-
if (x.ChildIdx != y.ChildIdx || x.ChildCount != y.ChildCount)
1666-
return false;
1667-
}
1668-
else if (x.Kind == ExprNodeKind.CatchBlock)
1669-
{
1670-
if (x.ChildCount != y.ChildCount)
1671-
return false;
1672-
1673-
restoreXParameterCount = _xParameterIds.Count;
1674-
restoreYParameterCount = _yParameterIds.Count;
1675-
descendX = x.ChildIdx;
1676-
descendY = y.ChildIdx;
1677-
descendChildCount = x.ChildCount - (x.HasFlag(CatchHasVariableFlag) ? 1 : 0);
1678-
if (x.HasFlag(CatchHasVariableFlag))
1684+
if (x.Kind == ExprNodeKind.LabelTarget)
16791685
{
1680-
ref var xv = ref xTree.Nodes.GetSurePresentRef(descendX);
1681-
ref var yv = ref yTree.Nodes.GetSurePresentRef(descendY);
1682-
if (!AreEquivalentParameterDeclarations(ref xv, ref yv))
1686+
if (!EqLabelTarget(ref x, ref y))
16831687
return false;
1684-
_xParameterIds.Add(ToStoredUShortIdx(xv.ChildIdx));
1685-
_yParameterIds.Add(ToStoredUShortIdx(yv.ChildIdx));
1686-
descendX = xv.NextIdx;
1687-
descendY = yv.NextIdx;
16881688
}
1689-
}
1690-
else
1691-
{
1692-
switch (x.NodeType)
1689+
else if (x.Kind == ExprNodeKind.CatchBlock)
16931690
{
1694-
case ExpressionType.Parameter:
1695-
if (!EqParameter(ref x, ref y))
1696-
return false;
1697-
break;
1698-
1699-
case ExpressionType.Constant:
1700-
if (!AreConstantsEqual(ref xTree, ref x, ref yTree, ref y))
1701-
return false;
1702-
break;
1703-
1704-
case ExpressionType.Lambda:
1705-
if (x.ChildCount != y.ChildCount || x.ChildCount == 0)
1691+
restoreXParameterCount = _xParameterIds.Count;
1692+
restoreYParameterCount = _yParameterIds.Count;
1693+
descendX = x.ChildIdx;
1694+
descendY = y.ChildIdx;
1695+
descendChildCount = x.ChildCount - (x.HasFlag(CatchHasVariableFlag) ? 1 : 0);
1696+
if (x.HasFlag(CatchHasVariableFlag))
1697+
{
1698+
ref var xv = ref xTree.Nodes.GetSurePresentRef(descendX);
1699+
ref var yv = ref yTree.Nodes.GetSurePresentRef(descendY);
1700+
if (!AreEquivalentParameterDeclarations(ref xv, ref yv))
17061701
return false;
1707-
1708-
restoreXParameterCount = _xParameterIds.Count;
1709-
restoreYParameterCount = _yParameterIds.Count;
1710-
descendX = x.ChildIdx;
1711-
descendY = y.ChildIdx;
1712-
descendChildCount = 1;
1713-
var xParameterIdx = xTree.Nodes.GetSurePresentRef(descendX).NextIdx;
1714-
var yParameterIdx = yTree.Nodes.GetSurePresentRef(descendY).NextIdx;
1715-
for (var i = 1; i < x.ChildCount; ++i)
1716-
{
1717-
ref var xp = ref xTree.Nodes.GetSurePresentRef(xParameterIdx);
1718-
ref var yp = ref yTree.Nodes.GetSurePresentRef(yParameterIdx);
1719-
if (!AreEquivalentParameterDeclarations(ref xp, ref yp))
1702+
_xParameterIds.Add(ToStoredUShortIdx(xv.ChildIdx));
1703+
_yParameterIds.Add(ToStoredUShortIdx(yv.ChildIdx));
1704+
descendX = xv.NextIdx;
1705+
descendY = yv.NextIdx;
1706+
}
1707+
}
1708+
else
1709+
{
1710+
switch (x.NodeType)
1711+
{
1712+
case ExpressionType.Parameter:
1713+
if (!EqParameter(ref x, ref y))
17201714
return false;
1721-
_xParameterIds.Add(ToStoredUShortIdx(xp.ChildIdx));
1722-
_yParameterIds.Add(ToStoredUShortIdx(yp.ChildIdx));
1723-
xParameterIdx = xp.NextIdx;
1724-
yParameterIdx = yp.NextIdx;
1725-
}
1726-
break;
1715+
break;
17271716

1728-
case ExpressionType.Block:
1729-
if (x.ChildCount != y.ChildCount || x.ChildCount == 0)
1730-
return false;
1717+
case ExpressionType.Constant:
1718+
if (!AreConstantsEqual(ref xTree, ref x, ref yTree, ref y))
1719+
return false;
1720+
break;
17311721

1732-
restoreXParameterCount = _xParameterIds.Count;
1733-
restoreYParameterCount = _yParameterIds.Count;
1734-
descendX = x.ChildIdx;
1735-
descendY = y.ChildIdx;
1736-
descendChildCount = 1;
1737-
if (x.ChildCount == 2)
1738-
{
1739-
ref var xVariables = ref xTree.Nodes.GetSurePresentRef(descendX);
1740-
ref var yVariables = ref yTree.Nodes.GetSurePresentRef(descendY);
1741-
if (xVariables.Kind != ExprNodeKind.ChildList || yVariables.Kind != ExprNodeKind.ChildList ||
1742-
xVariables.ChildCount != yVariables.ChildCount)
1722+
case ExpressionType.Lambda:
1723+
if (x.ChildCount == 0)
17431724
return false;
17441725

1745-
var xVariableIdx = xVariables.ChildIdx;
1746-
var yVariableIdx = yVariables.ChildIdx;
1747-
for (var i = 0; i < xVariables.ChildCount; ++i)
1726+
restoreXParameterCount = _xParameterIds.Count;
1727+
restoreYParameterCount = _yParameterIds.Count;
1728+
descendX = x.ChildIdx;
1729+
descendY = y.ChildIdx;
1730+
descendChildCount = 1;
1731+
var xParameterIdx = xTree.Nodes.GetSurePresentRef(descendX).NextIdx;
1732+
var yParameterIdx = yTree.Nodes.GetSurePresentRef(descendY).NextIdx;
1733+
for (var i = 1; i < x.ChildCount; ++i)
17481734
{
1749-
ref var xv = ref xTree.Nodes.GetSurePresentRef(xVariableIdx);
1750-
ref var yv = ref yTree.Nodes.GetSurePresentRef(yVariableIdx);
1751-
if (!AreEquivalentParameterDeclarations(ref xv, ref yv))
1735+
ref var xp = ref xTree.Nodes.GetSurePresentRef(xParameterIdx);
1736+
ref var yp = ref yTree.Nodes.GetSurePresentRef(yParameterIdx);
1737+
if (!AreEquivalentParameterDeclarations(ref xp, ref yp))
17521738
return false;
1753-
_xParameterIds.Add(ToStoredUShortIdx(xv.ChildIdx));
1754-
_yParameterIds.Add(ToStoredUShortIdx(yv.ChildIdx));
1755-
xVariableIdx = xv.NextIdx;
1756-
yVariableIdx = yv.NextIdx;
1739+
_xParameterIds.Add(ToStoredUShortIdx(xp.ChildIdx));
1740+
_yParameterIds.Add(ToStoredUShortIdx(yp.ChildIdx));
1741+
xParameterIdx = xp.NextIdx;
1742+
yParameterIdx = yp.NextIdx;
17571743
}
1744+
break;
17581745

1759-
descendX = xVariables.NextIdx;
1760-
descendY = yVariables.NextIdx;
1761-
}
1762-
break;
1746+
case ExpressionType.Block:
1747+
if (x.ChildCount == 0)
1748+
return false;
17631749

1764-
default:
1765-
if (x.ChildCount != y.ChildCount || !EqObj(ref x, ref y))
1766-
return false;
1767-
if (x.ChildCount != 0)
1768-
{
1750+
restoreXParameterCount = _xParameterIds.Count;
1751+
restoreYParameterCount = _yParameterIds.Count;
17691752
descendX = x.ChildIdx;
17701753
descendY = y.ChildIdx;
1771-
descendChildCount = x.ChildCount;
1772-
}
1773-
break;
1754+
descendChildCount = 1;
1755+
if (x.ChildCount == 2)
1756+
{
1757+
ref var xVariables = ref xTree.Nodes.GetSurePresentRef(descendX);
1758+
ref var yVariables = ref yTree.Nodes.GetSurePresentRef(descendY);
1759+
if (xVariables.Kind != ExprNodeKind.ChildList || yVariables.Kind != ExprNodeKind.ChildList ||
1760+
xVariables.ChildCount != yVariables.ChildCount)
1761+
return false;
1762+
1763+
var xVariableIdx = xVariables.ChildIdx;
1764+
var yVariableIdx = yVariables.ChildIdx;
1765+
for (var i = 0; i < xVariables.ChildCount; ++i)
1766+
{
1767+
ref var xv = ref xTree.Nodes.GetSurePresentRef(xVariableIdx);
1768+
ref var yv = ref yTree.Nodes.GetSurePresentRef(yVariableIdx);
1769+
if (!AreEquivalentParameterDeclarations(ref xv, ref yv))
1770+
return false;
1771+
_xParameterIds.Add(ToStoredUShortIdx(xv.ChildIdx));
1772+
_yParameterIds.Add(ToStoredUShortIdx(yv.ChildIdx));
1773+
xVariableIdx = xv.NextIdx;
1774+
yVariableIdx = yv.NextIdx;
1775+
}
1776+
1777+
descendX = xVariables.NextIdx;
1778+
descendY = yVariables.NextIdx;
1779+
}
1780+
break;
1781+
1782+
default:
1783+
if (!EqObj(ref x, ref y))
1784+
return false;
1785+
if (x.ChildCount != 0)
1786+
{
1787+
descendX = x.ChildIdx;
1788+
descendY = y.ChildIdx;
1789+
descendChildCount = x.ChildCount;
1790+
}
1791+
break;
1792+
}
17741793
}
17751794
}
17761795

@@ -1848,9 +1867,9 @@ private bool EqLabelTarget(ref ExprNode x, ref ExprNode y)
18481867

18491868
[MethodImpl(MethodImplOptions.AggressiveInlining)]
18501869
private static bool AreEquivalentParameterDeclarations(ref ExprNode x, ref ExprNode y) =>
1851-
x.NodeType == ExpressionType.Parameter && y.NodeType == ExpressionType.Parameter &&
1852-
x.Kind == ExprNodeKind.Expression && y.Kind == ExprNodeKind.Expression &&
1853-
x.Type == y.Type && x.HasFlag(ParameterByRefFlag) == y.HasFlag(ParameterByRefFlag);
1870+
x.NodeType == ExpressionType.Parameter &&
1871+
y.NodeType == ExpressionType.Parameter &&
1872+
x.HasSameShapeExceptLinks(ref y);
18541873

18551874
private static bool EqObj(ref ExprNode x, ref ExprNode y)
18561875
{

0 commit comments

Comments
 (0)