[PATCH 6/6] ntdll: Use a more compact block layout.

Rémi Bernon wine at gitlab.winehq.org
Wed Jun 1 03:10:01 CDT 2022


From: Rémi Bernon <rbernon at codeweavers.com>

With a separate block_flags field.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/ntdll/heap.c | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 0d7feee189b..7f6108d6214 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -78,9 +78,10 @@ struct rtl_heap_entry
 
 struct block
 {
-    DWORD  size;                    /* Block size; must be the first field */
-    DWORD  magic : 24;              /* Magic number */
-    DWORD  unused_bytes : 8;        /* Number of bytes in the block not used by user data (max value is HEAP_MIN_DATA_SIZE+HEAP_MIN_SHRINK_SIZE) */
+    WORD block_size;   /* block size in multiple of ALIGNMENT */
+    BYTE block_flags;
+    BYTE tail_size;    /* unused size (used block) / high size bits (free block) */
+    DWORD magic;
 };
 
 C_ASSERT( sizeof(struct block) == 8 );
@@ -228,36 +229,39 @@ static inline BOOL contains( const void *a, SIZE_T a_size, const void *b, SIZE_T
 
 static inline UINT block_get_flags( const struct block *block )
 {
-    return block->size & ~ARENA_SIZE_MASK;
+    return block->block_flags;
 }
 
 static inline UINT block_get_type( const struct block *block )
 {
-    if (block_get_flags( block ) & BLOCK_FLAG_FREE) return (block->unused_bytes << 24)|block->magic;
     return block->magic;
 }
 
 static inline void block_set_type( struct block *block, UINT type )
 {
-    if (type >> 24) block->unused_bytes = type >> 24;
     block->magic = type;
 }
 
 static inline UINT block_get_overhead( const struct block *block )
 {
     if (block_get_flags( block ) & BLOCK_FLAG_FREE) return sizeof(*block) + sizeof(struct list);
-    return sizeof(*block) + block->unused_bytes;
+    return sizeof(*block) + block->tail_size;
 }
 
 /* return the size of a block, including its header */
 static inline UINT block_get_size( const struct block *block )
 {
-    return block->size & ARENA_SIZE_MASK;
+    UINT block_size = block->block_size;
+    if (block_get_flags( block ) & BLOCK_FLAG_FREE) block_size += (UINT)block->tail_size << 16;
+    return block_size * ALIGNMENT;
 }
 
-static inline void block_set_size( struct block *block, UINT flags, UINT block_size )
+static inline void block_set_size( struct block *block, UINT block_flags, UINT block_size )
 {
-    block->size = (block_size & ARENA_SIZE_MASK) | (flags & ~ARENA_SIZE_MASK);
+    block_size /= ALIGNMENT;
+    if (block_flags & BLOCK_FLAG_FREE) block->tail_size = block_size >> 16;
+    block->block_size = block_size;
+    block->block_flags = block_flags;
 }
 
 static inline void *subheap_base( const SUBHEAP *subheap )
@@ -350,7 +354,7 @@ static inline void mark_block_free( void *ptr, SIZE_T size, DWORD flags )
 /* mark a block of memory as a tail block */
 static inline void mark_block_tail( struct block *block, DWORD flags )
 {
-    char *tail = (char *)block + block_get_size( block ) - block->unused_bytes;
+    char *tail = (char *)block + block_get_size( block ) - block->tail_size;
     if (flags & HEAP_TAIL_CHECKING_ENABLED)
     {
         valgrind_make_writable( tail, ALIGNMENT );
@@ -518,7 +522,7 @@ static void heap_dump( const HEAP *heap )
             {
                 TRACE( "      %p: (used) type %#10x, size %#8x, flags %#4x, unused %#4x", block,
                        block_get_type( block ), block_get_size( block ), block_get_flags( block ),
-                       block->unused_bytes );
+                       block->tail_size );
                 if (!(block_get_flags( block ) & BLOCK_FLAG_PREV_FREE)) TRACE( "\n" );
                 else TRACE( ", back %p\n", *((struct block **)block - 1) );
 
@@ -548,7 +552,7 @@ static void heap_dump( const HEAP *heap )
             if (!(block = heap->pending_free[i])) break;
 
             TRACE( "   %c%p: (pend) type %#10x, size %#8x, flags %#4x, unused %#4x", i == heap->pending_pos ? '*' : ' ',
-                   block, block_get_type( block ), block_get_size( block ), block_get_flags( block ), block->unused_bytes );
+                   block, block_get_type( block ), block_get_size( block ), block_get_flags( block ), block->tail_size );
             if (!(block_get_flags( block ) & BLOCK_FLAG_PREV_FREE)) TRACE( "\n" );
             else TRACE( ", back %p\n", *((struct block **)block - 1) );
         }
@@ -763,15 +767,15 @@ static inline void shrink_used_block( SUBHEAP *subheap, struct block *block, UIN
     if (old_block_size >= block_size + HEAP_MIN_BLOCK_SIZE)
     {
         block_set_size( block, flags, block_size );
-        block->unused_bytes = block_size - sizeof(*block) - size;
+        block->tail_size = block_size - sizeof(*block) - size;
         create_free_block( subheap, next_block( subheap, block ), old_block_size - block_size );
     }
     else
     {
         struct block *next;
         block_set_size( block, flags, old_block_size );
-        block->unused_bytes = old_block_size - sizeof(*block) - size;
-        if ((next = next_block( subheap, block ))) next->size &= ~BLOCK_FLAG_PREV_FREE;
+        block->tail_size = old_block_size - sizeof(*block) - size;
+        if ((next = next_block( subheap, block ))) next->block_flags &= ~BLOCK_FLAG_PREV_FREE;
     }
 }
 
@@ -1136,7 +1140,7 @@ static BOOL validate_used_block( const SUBHEAP *subheap, const struct block *blo
         err = "invalid block flags";
     else if (!contains( base, commit_end - base, block, block_get_size( block ) ))
         err = "invalid block size";
-    else if (block->unused_bytes > block_get_size( block ) - sizeof(*block))
+    else if (block->tail_size > block_get_size( block ) - sizeof(*block))
         err = "invalid block unused size";
     else if ((next = next_block( subheap, block )) && (block_get_flags( next ) & BLOCK_FLAG_PREV_FREE))
         err = "invalid next block flags";
@@ -1162,7 +1166,7 @@ static BOOL validate_used_block( const SUBHEAP *subheap, const struct block *blo
     }
     else if (!err && (flags & HEAP_TAIL_CHECKING_ENABLED))
     {
-        const unsigned char *tail = (unsigned char *)block + block_get_size( block ) - block->unused_bytes;
+        const unsigned char *tail = (unsigned char *)block + block_get_size( block ) - block->tail_size;
         for (i = 0; !err && i < ALIGNMENT; i++) if (tail[i] != ARENA_TAIL_FILLER) err = "invalid block tail";
     }
 
-- 
GitLab

https://gitlab.winehq.org/wine/wine/-/merge_requests/165



More information about the wine-devel mailing list