@@ -55,22 +55,9 @@ public enum ExprNodeKind : byte
5555[ StructLayout ( LayoutKind . Explicit , Size = 24 ) ]
5656public struct ExprNode
5757{
58- // Packed layout of `_data` (MSB -> LSB):
59- // [ 8 bits NodeType ][ 8 bits Tag(flags+kind) ][ 16 bits NextIdx ][ 16 bits ChildCount ][ 16 bits ChildIdx ]
60- private const int NodeTypeShift = 56 ;
61- private const int TagShift = 48 ;
62- private const int NextShift = 32 ;
63- private const int CountShift = 16 ;
64- private const ulong IndexMask = 0xFFFF ;
65- private const ulong KindMask = 0x0F ;
58+ private const byte KindMask = 0x0F ;
6659 private const byte NextReservedFlag = 0x4 ;
6760 private const byte NextPointsParentFlag = 0x8 ;
68- private const ulong TagMask = 0xFFUL << TagShift ;
69- private const ulong NextMask = IndexMask << NextShift ;
70- private const ulong ChildCountMask = IndexMask << CountShift ;
71- private const ulong ChildInfoMask = ChildCountMask | IndexMask ;
72- private const ulong KeepWithoutNextMask = ~ NextMask ;
73- private const ulong KeepWithoutChildInfoMask = ~ ChildInfoMask ;
7461 private const int FlagsShift = 4 ;
7562
7663 /// <summary>Gets or sets the runtime type of the represented node.</summary>
@@ -81,66 +68,68 @@ public struct ExprNode
8168 [ FieldOffset ( 8 ) ]
8269 public object Obj ;
8370 [ FieldOffset ( 16 ) ]
84- private ulong _data ;
71+ private ushort _childIdx ;
72+ [ FieldOffset ( 18 ) ]
73+ private ushort _childCount ;
74+ [ FieldOffset ( 20 ) ]
75+ private ushort _nextIdx ;
76+ [ FieldOffset ( 22 ) ]
77+ private byte _tag ;
78+ [ FieldOffset ( 23 ) ]
79+ private byte _nodeType ;
8580
8681 /// <summary>Gets the expression kind encoded for this node.</summary>
87- // Extracts bits [63..56].
88- public ExpressionType NodeType => ( ExpressionType ) ( ( _data >> NodeTypeShift ) & 0xFF ) ;
82+ public ExpressionType NodeType => ( ExpressionType ) _nodeType ;
8983
9084 /// <summary>Gets the payload classification for this node.</summary>
91- // Extracts low 4 bits from Tag [51..48].
92- public ExprNodeKind Kind => ( ExprNodeKind ) ( ( _data >> TagShift ) & KindMask ) ;
85+ public ExprNodeKind Kind => ( ExprNodeKind ) ( _tag & KindMask ) ;
9386
94- // Extracts high 4 bits from Tag [55..52].
95- internal byte Flags => ( byte ) ( ( ( byte ) ( _data >> TagShift ) ) >> FlagsShift ) ;
87+ internal byte Flags => ( byte ) ( _tag >> FlagsShift ) ;
9688
9789 /// <summary>Gets the next sibling node index in the intrusive child chain.</summary>
98- public int NextIdx => ( int ) ( ( _data >> NextShift ) & IndexMask ) ;
90+ public int NextIdx => _nextIdx ;
9991
10092 internal bool IsParentLink => ( Flags & NextPointsParentFlag ) != 0 ;
10193
102- internal bool HasNextLink => ( _data & NextMask ) != 0 || ( Flags & ( NextPointsParentFlag | NextReservedFlag ) ) != 0 ;
94+ internal bool HasNextLink => _nextIdx != 0 || ( Flags & ( NextPointsParentFlag | NextReservedFlag ) ) != 0 ;
10395
10496 /// <summary>Gets the number of direct children linked from this node.</summary>
105- public int ChildCount => ( int ) ( ( _data >> CountShift ) & IndexMask ) ;
97+ public int ChildCount => _childCount ;
10698
10799 /// <summary>Gets the first child index or an auxiliary payload index.</summary>
108- public int ChildIdx => ( int ) ( _data & IndexMask ) ;
100+ public int ChildIdx => _childIdx ;
109101
110102 internal ExprNode ( Type type , object obj , ExpressionType nodeType , ExprNodeKind kind , byte flags = 0 , int childIdx = 0 , int childCount = 0 , int nextIdx = 0 )
111103 {
112104 Type = type ;
113105 Obj = obj ;
114- var tag = ( byte ) ( ( flags << FlagsShift ) | ( byte ) kind ) ;
115- _data = ( ( ulong ) ( byte ) nodeType << NodeTypeShift )
116- | ( ( ulong ) tag << TagShift )
117- | ( ( ulong ) ( ushort ) nextIdx << NextShift )
118- | ( ( ulong ) ( ushort ) childCount << CountShift )
119- | ( ushort ) childIdx ;
106+ _childIdx = ( ushort ) childIdx ;
107+ _childCount = ( ushort ) childCount ;
108+ _nextIdx = ( ushort ) nextIdx ;
109+ _tag = ( byte ) ( ( flags << FlagsShift ) | ( byte ) kind ) ;
110+ _nodeType = ( byte ) nodeType ;
120111 }
121112
122113 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
123114 internal void SetNextSiblingIdx ( int nextIdx )
124115 {
125- // Replace NextIdx [47..32] and clear link-state flags to "regular sibling link".
126- _data = ( _data & KeepWithoutNextMask ) | ( ( ulong ) ( ushort ) nextIdx << NextShift ) ;
116+ _nextIdx = ( ushort ) nextIdx ;
127117 SetFlags ( ( byte ) ( Flags & ~ ( NextPointsParentFlag | NextReservedFlag ) ) ) ;
128118 }
129119
130120 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
131121 internal void SetParentIdx ( int parentIdx )
132122 {
133- // Replace NextIdx [47..32] and mark it as "points to parent" (not sibling).
134- _data = ( _data & KeepWithoutNextMask ) | ( ( ulong ) ( ushort ) parentIdx << NextShift ) ;
123+ _nextIdx = ( ushort ) parentIdx ;
135124 SetFlags ( ( byte ) ( ( Flags | NextPointsParentFlag ) & ~ NextReservedFlag ) ) ;
136125 }
137126
138127 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
139- internal void SetChildInfo ( int childIdx , int childCount ) =>
140- // Replace ChildCount [31..16] and ChildIdx [15..0] together as one logical payload.
141- _data = ( _data & KeepWithoutChildInfoMask )
142- | ( ( ulong ) ( ushort ) childCount << CountShift )
143- | ( ushort ) childIdx ;
128+ internal void SetChildInfo ( int childIdx , int childCount )
129+ {
130+ _childIdx = ( ushort ) childIdx ;
131+ _childCount = ( ushort ) childCount ;
132+ }
144133
145134 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
146135 internal bool Is ( ExprNodeKind kind ) => Kind == kind ;
@@ -160,9 +149,7 @@ internal bool IsExpression() =>
160149 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
161150 private void SetFlags ( byte flags )
162151 {
163- // Rebuild Tag [55..48] as [flags(4 bits) | kind(4 bits)] and replace in place.
164- var tag = ( byte ) ( ( flags << FlagsShift ) | ( byte ) Kind ) ;
165- _data = ( _data & ~ TagMask ) | ( ( ulong ) tag << TagShift ) ;
152+ _tag = ( byte ) ( ( flags << FlagsShift ) | ( byte ) Kind ) ;
166153 }
167154}
168155
0 commit comments