@@ -20,7 +20,7 @@ internal struct DotvvmControlProperties : IEnumerable<KeyValuePair<DotvvmPropert
2020 {
2121 // There are 3 possible states of this structure:
2222 // 1. Empty -> keys == values == null
23- // 2. Dictinary -> keys == null & values is Dictionary<DotvvmPropertyId, object> --> it falls back to traditional mutable property dictionary
23+ // 2. Dictionary -> keys == null & values is Dictionary<DotvvmPropertyId, object> --> it falls back to traditional mutable property dictionary
2424 // 3. Array8 or Array16 -> keys is DotvvmPropertyId[] & values is object[] -- small linear search array
2525
2626 // Note about unsafe code:
@@ -118,7 +118,7 @@ private readonly void CheckInvariant()
118118 }
119119 }
120120 break ;
121- case TableState . Dictinary :
121+ case TableState . Dictionary :
122122 Debug . Assert ( keys is null ) ;
123123 Debug . Assert ( values is Dictionary < DotvvmPropertyId , object > ) ;
124124 break ;
@@ -160,8 +160,8 @@ public void AssignBulk(DotvvmPropertyId[] keys, object?[] values, bool ownsKeys,
160160 [ DoesNotReturn , MethodImpl ( NoInlining ) ]
161161 void throwArgumentError ( DotvvmPropertyId [ ] ? keys , object ? [ ] ? values )
162162 {
163- ThrowHelpers . ArgumentNull ( nameof ( keys ) ) ;
164- ThrowHelpers . ArgumentNull ( nameof ( values ) ) ;
163+ ThrowHelpers . ArgumentNull ( keys ) ;
164+ ThrowHelpers . ArgumentNull ( values ) ;
165165 if ( keys . Length is not 8 and not 16 )
166166 throw new ArgumentException ( $ "The length of keys array must be 8 or 16.", nameof ( keys ) ) ;
167167 if ( keys . Length != values . Length )
@@ -183,15 +183,20 @@ public void AssignBulk(Dictionary<DotvvmPropertyId, object?> values, bool owns)
183183 this . keys = null ;
184184 this . valuesAsDictionary = values ;
185185 this . ownsValues = owns ;
186- this . state = TableState . Dictinary ;
186+ this . state = TableState . Dictionary ;
187187 }
188188 else
189189 {
190- if ( owns )
190+ if ( owns && values . Count >= 8 )
191191 {
192192 foreach ( var ( k , v ) in this )
193193 {
194+ #if DotNetCore
194195 values . TryAdd ( k , v ) ;
196+ #else
197+ if ( ! values . ContainsKey ( k ) )
198+ values [ k ] = v ;
199+ #endif
195200 }
196201 this . values = values ;
197202 this . keys = null ;
@@ -236,7 +241,7 @@ private readonly bool ContainsOutlined(DotvvmPropertyId p) // doesn't need to be
236241 {
237242 return Impl . ContainsKey16 ( this . keys ! , p ) ;
238243 }
239- if ( state == TableState . Dictinary )
244+ if ( state == TableState . Dictionary )
240245 {
241246 return valuesAsDictionary ! . ContainsKey ( p ) ;
242247 }
@@ -295,7 +300,7 @@ private readonly int CountPropertyGroupOutlined(ushort groupId)
295300 return 0 ;
296301 case TableState . Array16 :
297302 return Impl . CountPropertyGroup ( this . keys ! , groupId ) ;
298- case TableState . Dictinary :
303+ case TableState . Dictionary :
299304 {
300305 int count = 0 ;
301306 foreach ( var key in valuesAsDictionary . Keys )
@@ -314,23 +319,25 @@ public void ClearPropertyGroup(ushort groupId)
314319 {
315320 if ( state == TableState . Empty )
316321 return ;
317- else if ( state == TableState . Dictinary )
322+ else if ( state == TableState . Dictionary )
318323 {
319324 ClearPropertyGroupOutlined ( groupId ) ;
320325 return ;
321326 }
322-
327+
323328 Debug . Assert ( state is TableState . Array16 or TableState . Array8 ) ;
329+ #if Vectorize
324330 var bitmap = Impl . FindGroupBitmap ( this . keys ! , groupId ) ;
325331 if ( bitmap == 0 )
326332 return ;
327333
328334 OwnKeys ( ) ;
329335 OwnValues ( ) ;
336+ Impl . Assert ( this . keys ! . Length == this . valuesAsArray . Length ) ;
330337
331338 int index = 0 ;
332- var values = Impl . UnsafeArrayReference ( this . valuesAsArray ) ;
333- var keys = Impl . UnsafeArrayReference ( this . keys ! ) ;
339+ ref var values = ref Impl . UnsafeArrayReference ( this . valuesAsArray ) ;
340+ ref var keys = ref Impl . UnsafeArrayReference ( this . keys ) ;
334341 do
335342 {
336343 int bit = BitOperations . TrailingZeroCount ( bitmap ) ;
@@ -341,6 +348,21 @@ public void ClearPropertyGroup(ushort groupId)
341348 Unsafe . Add ( ref values , index ) = null ;
342349 index ++ ;
343350 } while ( bitmap != 0 ) ;
351+ #else
352+ var keys = this . keys ! ;
353+ for ( var i = 0 ; i < keys . Length ; i ++ )
354+ {
355+ if ( keys [ i ] . IsInPropertyGroup ( groupId ) )
356+ {
357+ if ( ! ownsKeys )
358+ keys = CloneKeys ( ) ;
359+ if ( ! ownsValues )
360+ CloneValues ( ) ;
361+ keys [ i ] = default ;
362+ this . valuesAsArray [ i ] = null ;
363+ }
364+ }
365+ #endif
344366 CheckInvariant ( ) ;
345367 }
346368
@@ -398,7 +420,7 @@ public readonly bool TryGet(DotvvmPropertyId p, out object? value)
398420 if ( index >= 0 )
399421 {
400422#if NET6_0_OR_GREATER
401- value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ) , index ) ;
423+ value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ! ) , index ) ;
402424#else
403425 value = valuesAsArrayUnsafe ! [ index ] ;
404426#endif
@@ -426,7 +448,7 @@ private readonly bool TryGetOutlined(DotvvmPropertyId p, out object? value)
426448 {
427449
428450#if NET6_0_OR_GREATER
429- value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ) , index ) ;
451+ value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ! ) , index ) ;
430452#else
431453 value = valuesAsArrayUnsafe ! [ index ] ;
432454#endif
@@ -438,7 +460,7 @@ private readonly bool TryGetOutlined(DotvvmPropertyId p, out object? value)
438460 return false ;
439461 }
440462 }
441- case TableState . Dictinary :
463+ case TableState . Dictionary :
442464 return valuesAsDictionary . TryGetValue ( p , out value ) ;
443465 default :
444466 value = null ;
@@ -740,9 +762,6 @@ public readonly int Count()
740762 return Impl . Count ( this . keys ) ;
741763 }
742764
743- [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
744- private static byte BoolToInt ( bool x ) => Unsafe . As < bool , byte > ( ref x ) ;
745-
746765 internal void CloneInto ( ref DotvvmControlProperties newDict , DotvvmBindableObject newParent )
747766 {
748767 CheckInvariant ( ) ;
@@ -886,7 +905,7 @@ void IncreaseSize()
886905 case TableState . Array16 :
887906 SwitchToDictionary ( ) ;
888907 break ;
889- case TableState . Dictinary :
908+ case TableState . Dictionary :
890909 break ;
891910 default :
892911 Impl . Fail ( ) ;
@@ -912,17 +931,17 @@ void SwitchToDictionary()
912931 if ( keysTmp [ i ] . Id != 0 )
913932 d [ keysTmp [ i ] ] = valuesTmp [ i ] ;
914933 }
915- this . state = TableState . Dictinary ;
934+ this . state = TableState . Dictionary ;
916935 this . valuesAsDictionary = d ;
917936 this . keys = null ;
918937 this . ownsValues = true ;
919938 break ;
920939 case TableState . Empty :
921- this . state = TableState . Dictinary ;
940+ this . state = TableState . Dictionary ;
922941 this . valuesAsDictionary = new Dictionary < DotvvmPropertyId , object ? > ( ) ;
923942 this . ownsValues = true ;
924943 break ;
925- case TableState . Dictinary :
944+ case TableState . Dictionary :
926945 break ;
927946 default :
928947 Impl . Fail ( ) ;
@@ -988,7 +1007,7 @@ public PropertyGroupEnumerable(in DotvvmControlProperties properties, ushort gro
9881007 public enum TableState : byte
9891008 {
9901009 Empty = 0 ,
991- Dictinary = 1 ,
1010+ Dictionary = 1 ,
9921011 Array8 = 2 ,
9931012 Array16 = 3 ,
9941013 }
0 commit comments