ntdll: Simplify the fallback case in heap_reallocate.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2022-05-18 09:34:18 +02:00 committed by Alexandre Julliard
parent 3728b2b7d2
commit 419e4730ba
1 changed files with 8 additions and 37 deletions

View File

@ -1663,9 +1663,11 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt
static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size, void **ret )
{
struct block *next;
ARENA_INUSE *pArena;
SUBHEAP *subheap;
SIZE_T oldBlockSize, oldActualSize, rounded_size;
NTSTATUS status;
rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags);
if (rounded_size < size) return STATUS_NO_MEMORY; /* overflow */
@ -1684,20 +1686,8 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size
oldActualSize = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes;
if (rounded_size > oldBlockSize)
{
struct block *next;
if (rounded_size >= HEAP_MIN_LARGE_BLOCK_SIZE)
{
if (flags & HEAP_REALLOC_IN_PLACE_ONLY) return STATUS_NO_MEMORY;
if (!(*ret = allocate_large_block( heap, flags, size ))) return STATUS_NO_MEMORY;
memcpy( *ret, pArena + 1, oldActualSize );
notify_free( pArena + 1 );
HEAP_MakeInUseBlockFree( subheap, pArena );
return STATUS_SUCCESS;
}
if ((next = next_block( subheap, pArena )) && (block_get_flags( next ) & ARENA_FLAG_FREE) &&
(oldBlockSize + block_get_size( next ) >= rounded_size))
rounded_size < HEAP_MIN_LARGE_BLOCK_SIZE && rounded_size <= oldBlockSize + block_get_size( next ))
{
/* The next block is free and large enough */
struct entry *entry = (struct entry *)next;
@ -1707,34 +1697,15 @@ static NTSTATUS heap_reallocate( HEAP *heap, ULONG flags, void *ptr, SIZE_T size
notify_realloc( pArena + 1, oldActualSize, size );
HEAP_ShrinkBlock( subheap, pArena, rounded_size );
}
else /* Do it the hard way */
else
{
ARENA_FREE *pNew;
ARENA_INUSE *pInUse;
SUBHEAP *newsubheap;
if (flags & HEAP_REALLOC_IN_PLACE_ONLY) return STATUS_NO_MEMORY;
if (!(pNew = HEAP_FindFreeBlock( heap, rounded_size, &newsubheap ))) return STATUS_NO_MEMORY;
/* Build the in-use arena */
list_remove( &pNew->entry );
pInUse = (ARENA_INUSE *)pNew;
pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE)
+ sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
pInUse->magic = ARENA_INUSE_MAGIC;
HEAP_ShrinkBlock( newsubheap, pInUse, rounded_size );
mark_block_initialized( pInUse + 1, oldActualSize );
notify_alloc( pInUse + 1, size, FALSE );
memcpy( pInUse + 1, pArena + 1, oldActualSize );
/* Free the previous block */
if ((status = heap_allocate( heap, flags & ~HEAP_ZERO_MEMORY, size, ret ))) return status;
memcpy( *ret, pArena + 1, oldActualSize );
if (flags & HEAP_ZERO_MEMORY) memset( (char *)*ret + oldActualSize, 0, size - oldActualSize );
notify_free( pArena + 1 );
HEAP_MakeInUseBlockFree( subheap, pArena );
subheap = newsubheap;
pArena = pInUse;
return STATUS_SUCCESS;
}
}
else