Skip to content

Commit 005b4bf

Browse files
authored
refactor: assert normalized flat constants
1 parent b1874d8 commit 005b4bf

1 file changed

Lines changed: 31 additions & 6 deletions

File tree

src/FastExpressionCompiler.LightExpression/FlatExpression.cs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ public struct ExprNode
107107

108108
internal ExprNode(Type type, object obj, ExpressionType nodeType, ExprNodeKind kind, byte flags = 0, int childIdx = 0, int childCount = 0, int nextIdx = 0)
109109
{
110+
Debug.Assert(!RequiresInlineConstantStorage(type, obj, nodeType));
110111
Type = type;
111112
Obj = obj;
112113
var tag = (byte)((flags << FlagsShift) | (byte)kind);
@@ -137,6 +138,23 @@ internal void SetChildInfo(int childIdx, int childCount) =>
137138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
138139
internal bool IsExpression() => Kind == ExprNodeKind.Expression;
139140

141+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
142+
internal static bool RequiresInlineConstantStorage(Type type, object obj, ExpressionType nodeType)
143+
{
144+
if (nodeType != ExpressionType.Constant || obj == null || ReferenceEquals(obj, InlineValueMarker))
145+
return false;
146+
147+
return type.IsEnum
148+
? IsSmallPrimitive(Type.GetTypeCode(Enum.GetUnderlyingType(type)))
149+
: type.IsPrimitive && IsSmallPrimitive(Type.GetTypeCode(type));
150+
}
151+
152+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
153+
private static bool IsSmallPrimitive(TypeCode tc) =>
154+
tc == TypeCode.Boolean || tc == TypeCode.Byte || tc == TypeCode.SByte ||
155+
tc == TypeCode.Char || tc == TypeCode.Int16 || tc == TypeCode.UInt16 ||
156+
tc == TypeCode.Int32 || tc == TypeCode.UInt32 || tc == TypeCode.Single;
157+
140158
[MethodImpl(MethodImplOptions.AggressiveInlining)]
141159
internal bool HasFlag(byte flag) => (Flags & flag) != 0;
142160

@@ -2005,22 +2023,29 @@ private static int GetConstantHashCode(ref ExprTree tree, ref ExprNode node)
20052023
{
20062024
if (ReferenceEquals(node.Obj, ExprNode.InlineValueMarker))
20072025
return GetInlineConstantHashCode(node.Type, node.InlineValue);
2026+
2027+
Debug.Assert(!ExprNode.RequiresInlineConstantStorage(node.Type, node.Obj, node.NodeType));
20082028
return GetStoredConstantValue(ref tree, ref node)?.GetHashCode() ?? 0;
20092029
}
20102030

20112031
private static bool AreConstantsEqual(ref ExprTree xTree, ref ExprNode x, ref ExprTree yTree, ref ExprNode y)
20122032
{
2013-
var xObj = GetStoredConstantValue(ref xTree, ref x);
2014-
var yObj = GetStoredConstantValue(ref yTree, ref y);
20152033
var xInline = ReferenceEquals(x.Obj, ExprNode.InlineValueMarker);
20162034
var yInline = ReferenceEquals(y.Obj, ExprNode.InlineValueMarker);
2017-
if (!(xInline && yInline))
2035+
Debug.Assert(xInline == yInline);
2036+
if (xInline != yInline)
2037+
return false;
2038+
2039+
if (!xInline)
2040+
{
2041+
Debug.Assert(!ExprNode.RequiresInlineConstantStorage(x.Type, x.Obj, x.NodeType));
2042+
var xObj = GetStoredConstantValue(ref xTree, ref x);
2043+
var yObj = GetStoredConstantValue(ref yTree, ref y);
20182044
return ReferenceEquals(xObj, yObj) || Equals(xObj, yObj);
2045+
}
20192046

20202047
if (x.Type.IsEnum)
2021-
{
20222048
return x.InlineValue == y.InlineValue;
2023-
}
20242049

20252050
return Type.GetTypeCode(x.Type) switch
20262051
{
@@ -2033,7 +2058,7 @@ private static bool AreConstantsEqual(ref ExprTree xTree, ref ExprNode x, ref Ex
20332058
TypeCode.Int32 => GetInlineInt32(ref x) == GetInlineInt32(ref y),
20342059
TypeCode.UInt32 => GetInlineUInt32(ref x) == GetInlineUInt32(ref y),
20352060
TypeCode.Single => GetInlineSingle(ref x).Equals(GetInlineSingle(ref y)),
2036-
_ => ReferenceEquals(xObj, yObj) || Equals(xObj, yObj)
2061+
_ => FlatExpressionThrow.UnsupportedInlineConstantType<bool>(x.Type)
20372062
};
20382063
}
20392064

0 commit comments

Comments
 (0)