@@ -312,75 +312,77 @@ private readonly int CountPropertyGroupOutlined(ushort groupId)
312312
313313 public void ClearPropertyGroup ( ushort groupId )
314314 {
315- switch ( state )
315+ if ( state == TableState . Empty )
316+ return ;
317+ else if ( state == TableState . Dictinary )
316318 {
317- case TableState . Empty :
318- return ;
319- case TableState . Array8 :
320- case TableState . Array16 :
321- {
322- var bitmap = Impl . FindGroupBitmap ( this . keys ! , groupId ) ;
323- int index = 0 ;
324- if ( bitmap == 0 )
325- return ;
326- OwnKeys ( ) ;
327- OwnValues ( ) ;
328- do
329- {
330- int bit = BitOperations . TrailingZeroCount ( bitmap ) ;
331- bitmap >>= ( bit + 1 ) ;
332- index += bit ;
333- Debug . Assert ( keys ! [ index ] . IsInPropertyGroup ( groupId ) , $ "Key { keys [ index ] } at index { index } is not in property group { groupId } ") ;
334- keys ! [ index ] = default ;
335- valuesAsArray [ index ] = null ;
336- index ++ ;
337- } while ( bitmap != 0 ) ;
338- CheckInvariant ( ) ;
339- return ;
340- }
341- case TableState . Dictinary :
342- {
343- var dict = this . valuesAsDictionary ;
344- // we want to avoid allocating the list if there is only one property
345- DotvvmPropertyId toRemove = default ;
346- List < DotvvmPropertyId > ? toRemoveRest = null ;
319+ ClearPropertyGroupOutlined ( groupId ) ;
320+ return ;
321+ }
322+
323+ Debug . Assert ( state is TableState . Array16 or TableState . Array8 ) ;
324+ var bitmap = Impl . FindGroupBitmap ( this . keys ! , groupId ) ;
325+ if ( bitmap == 0 )
326+ return ;
347327
348- foreach ( var ( p , _) in dict )
349- {
350- if ( p . IsInPropertyGroup ( groupId ) )
351- {
352- if ( toRemove . Id == 0 )
353- toRemove = p ;
354- else
355- {
356- toRemoveRest ??= new List < DotvvmPropertyId > ( ) ;
357- toRemoveRest . Add ( p ) ;
358- }
359- }
360- }
328+ OwnKeys ( ) ;
329+ OwnValues ( ) ;
361330
362- if ( toRemove . Id != 0 )
363- {
364- if ( ! ownsValues )
365- {
366- CloneValues ( ) ;
367- dict = this . valuesAsDictionary ;
368- }
331+ int index = 0 ;
332+ var values = Impl . UnsafeArrayReference ( this . valuesAsArray ) ;
333+ var keys = Impl . UnsafeArrayReference ( this . keys ! ) ;
334+ do
335+ {
336+ int bit = BitOperations . TrailingZeroCount ( bitmap ) ;
337+ bitmap >>= ( bit + 1 ) ;
338+ index += bit ;
339+ Debug . Assert ( this . keys ! [ index ] . IsInPropertyGroup ( groupId ) , $ "Key { this . keys [ index ] } at index { index } is not in property group { groupId } ") ;
340+ Unsafe . Add ( ref keys , index ) = default ;
341+ Unsafe . Add ( ref values , index ) = null ;
342+ index ++ ;
343+ } while ( bitmap != 0 ) ;
344+ CheckInvariant ( ) ;
345+ }
369346
370- dict . Remove ( toRemove ) ;
371- }
347+ private void ClearPropertyGroupOutlined ( ushort groupId )
348+ {
349+ var dict = this . valuesAsDictionary ;
350+ // we want to avoid allocating the list if there is only one property
351+ DotvvmPropertyId toRemove = default ;
352+ List < DotvvmPropertyId > ? toRemoveRest = null ;
372353
373- if ( toRemoveRest is { } )
354+ foreach ( var ( p , _) in dict )
355+ {
356+ if ( p . IsInPropertyGroup ( groupId ) )
357+ {
358+ if ( toRemove . Id == 0 )
359+ toRemove = p ;
360+ else
374361 {
375- Debug . Assert ( ownsValues ) ;
376- foreach ( var p in toRemoveRest )
377- dict . Remove ( p ) ;
362+ toRemoveRest ??= new List < DotvvmPropertyId > ( ) ;
363+ toRemoveRest . Add ( p ) ;
378364 }
379- CheckInvariant ( ) ;
380- return ;
381365 }
382366 }
383- Impl . Fail ( ) ;
367+
368+ if ( toRemove . Id != 0 )
369+ {
370+ if ( ! ownsValues )
371+ {
372+ CloneValues ( ) ;
373+ dict = this . valuesAsDictionary ;
374+ }
375+
376+ dict . Remove ( toRemove ) ;
377+ }
378+
379+ if ( toRemoveRest is { } )
380+ {
381+ Debug . Assert ( ownsValues ) ;
382+ foreach ( var p in toRemoveRest )
383+ dict . Remove ( p ) ;
384+ }
385+ CheckInvariant ( ) ;
384386 }
385387
386388 [ MethodImpl ( Inline ) ]
@@ -396,9 +398,9 @@ public readonly bool TryGet(DotvvmPropertyId p, out object? value)
396398 if ( index >= 0 )
397399 {
398400#if NET6_0_OR_GREATER
399- value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArray ) , index ) ;
401+ value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ) , index ) ;
400402#else
401- value = valuesAsArray [ index ] ;
403+ value = valuesAsArrayUnsafe ! [ index ] ;
402404#endif
403405 return true ;
404406 }
@@ -422,7 +424,12 @@ private readonly bool TryGetOutlined(DotvvmPropertyId p, out object? value)
422424 var index = Impl . FindSlot16 ( this . keys ! , p ) ;
423425 if ( index >= 0 )
424426 {
425- value = valuesAsArray [ index ] ;
427+
428+ #if NET6_0_OR_GREATER
429+ value = Unsafe . Add ( ref MemoryMarshal . GetArrayDataReference ( valuesAsArrayUnsafe ) , index ) ;
430+ #else
431+ value = valuesAsArrayUnsafe ! [ index ] ;
432+ #endif
426433 return true ;
427434 }
428435 else
@@ -463,7 +470,7 @@ private readonly bool TryGetOutlined(DotvvmPropertyId p, out object? value)
463470 public void Set ( DotvvmPropertyId p , object ? value )
464471 {
465472 CheckInvariant ( ) ;
466- if ( p . MemberId == 0 ) ThrowZeroPropertyId ( ) ;
473+ if ( p . MemberId == 0 ) { ThrowZeroPropertyId ( ) ; return ; }
467474
468475 if ( state == TableState . Array8 )
469476 {
0 commit comments