@@ -152,6 +152,7 @@ internal bool ShouldCloneWhenLinked() =>
152152/// <summary>Stores an expression tree as a flat node array plus out-of-line closure constants.</summary>
153153public struct ExprTree
154154{
155+ private static readonly object ClosureConstantMarker = new ( ) ;
155156 internal const byte ParameterByRefFlag = 1 ;
156157 internal const byte ParameterDeclarationFlag = 2 ;
157158 private const byte ConstantInlineValue32Flag = 1 ;
@@ -201,6 +202,12 @@ public int Constant(object value, Type type)
201202 if ( TryGetInlineConstantValue32 ( value , type , out var value32 ) )
202203 return AddRawInlineConstantNode ( type , value32 ) ;
203204
205+ if ( ShouldStoreConstantInClosureConstants ( value , type ) )
206+ {
207+ var constantIndex = ClosureConstants . Add ( value ) ;
208+ return AddRawExpressionNodeWithChildIndex ( type , ClosureConstantMarker , ExpressionType . Constant , constantIndex ) ;
209+ }
210+
204211 return AddRawExpressionNode ( type , value , ExpressionType . Constant ) ;
205212 }
206213
@@ -997,6 +1004,12 @@ private int AddConstant(System.Linq.Expressions.ConstantExpression constant)
9971004 if ( TryGetInlineConstantValue32 ( constant . Value , constant . Type , out var value32 ) )
9981005 return _tree . AddRawInlineConstantNode ( constant . Type , value32 ) ;
9991006
1007+ if ( ShouldStoreConstantInClosureConstants ( constant . Value , constant . Type ) )
1008+ {
1009+ var constantIndex = _tree . ClosureConstants . Add ( constant . Value ) ;
1010+ return _tree . AddRawExpressionNodeWithChildIndex ( constant . Type , ClosureConstantMarker , constant . NodeType , constantIndex ) ;
1011+ }
1012+
10001013 return _tree . AddRawExpressionNode ( constant . Type , constant . Value , constant . NodeType ) ;
10011014 }
10021015
@@ -1307,6 +1320,10 @@ private static bool TryGetInlineConstantValue32(object value, Type type, out int
13071320 }
13081321 }
13091322
1323+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
1324+ private static bool ShouldStoreConstantInClosureConstants ( object value , Type type ) =>
1325+ value != null && value is not string && value is not Type && ! type . IsEnum && Type . GetTypeCode ( type ) == TypeCode . Object ;
1326+
13101327 private static object ReadInlineConstantValue32 ( Type type , int value32 )
13111328 {
13121329 if ( type . IsEnum )
@@ -1438,7 +1455,9 @@ public SysExpr ReadExpression(int index)
14381455 return SysExpr . Constant (
14391456 node . HasFlag ( ConstantInlineValue32Flag )
14401457 ? ReadInlineConstantValue32 ( node . Type , node . Value32 )
1441- : node . Obj ,
1458+ : ReferenceEquals ( node . Obj , ClosureConstantMarker )
1459+ ? _tree . ClosureConstants [ node . ChildIdx ]
1460+ : node . Obj ,
14421461 node . Type ) ;
14431462 case ExpressionType . Default :
14441463 return SysExpr . Default ( node . Type ) ;
@@ -1790,44 +1809,36 @@ private SysExpr[] ReadExpressions(in ChildList childIndexes)
17901809
17911810internal static class Throw
17921811{
1793- [ DoesNotReturn ]
17941812 public static void DuplicateParameterDeclaration ( string name ) =>
17951813 throw new ArgumentException ( $ "The parameter or variable `{ name ?? "?" } ` is declared more than once.") ;
17961814
1797- [ DoesNotReturn ]
17981815 public static void ParameterDeclarationExpected ( int index ) =>
17991816 throw new ArgumentException ( $ "Expected a parameter declaration node at index { index } .") ;
18001817
1801- [ DoesNotReturn ]
18021818 public static void UndeclaredParameterUsage ( string name ) =>
18031819 throw new InvalidOperationException ( $ "The parameter or variable `{ name ?? "?" } ` is used before it is declared.") ;
18041820
1805- [ DoesNotReturn ]
18061821 public static void UnsupportedInlineConstantType ( Type type ) =>
18071822 throw new NotSupportedException ( $ "Inline 32-bit constant storage does not support `{ type } `.") ;
18081823
1809- [ DoesNotReturn ]
18101824 public static T DuplicateParameterDeclaration < T > ( string name )
18111825 {
18121826 DuplicateParameterDeclaration ( name ) ;
18131827 return default ;
18141828 }
18151829
1816- [ DoesNotReturn ]
18171830 public static T ParameterDeclarationExpected < T > ( int index )
18181831 {
18191832 ParameterDeclarationExpected ( index ) ;
18201833 return default ;
18211834 }
18221835
1823- [ DoesNotReturn ]
18241836 public static T UndeclaredParameterUsage < T > ( string name )
18251837 {
18261838 UndeclaredParameterUsage ( name ) ;
18271839 return default ;
18281840 }
18291841
1830- [ DoesNotReturn ]
18311842 public static T UnsupportedInlineConstantType < T > ( Type type )
18321843 {
18331844 UnsupportedInlineConstantType ( type ) ;
0 commit comments