From d8a9860e920a473bc6d3a563b2a47d8c41904b74 Mon Sep 17 00:00:00 2001 From: nickysn <nickysn@gmail.com> Date: Tue, 7 Oct 2014 14:36:23 +0000 Subject: [PATCH] + optimization in tinyheap's reallocmem for the case when there's not enough space after the block, but it becomes enough when the space before the block is also reclaimed git-svn-id: trunk@28786 - --- rtl/inc/tinyheap.inc | 66 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/rtl/inc/tinyheap.inc b/rtl/inc/tinyheap.inc index e4c1d6991e..155417b67c 100644 --- a/rtl/inc/tinyheap.inc +++ b/rtl/inc/tinyheap.inc @@ -260,8 +260,8 @@ function SysTinyReAllocMem(var p: pointer; size: ptruint):pointer; var oldsize, OldAllocSize, NewAllocSize: ptruint; - after_block, before_block: PTinyHeapBlock; - after_block_size: PtrUInt; + after_block, before_block, before_before_block: PTinyHeapBlock; + after_block_size, before_block_size: PtrUInt; new_after_block: PTinyHeapBlock; begin {$ifdef DEBUG_TINY_HEAP} @@ -306,8 +306,10 @@ before and after our memory block. } after_block := FreeList; before_block := nil; + before_before_block := nil; while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do begin + before_before_block := before_block; before_block := after_block; after_block := after_block^.Next; end; @@ -358,18 +360,60 @@ else begin { is before_block immediately before our block? } - //if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then - // ; + if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then + before_block_size := DecodeTinyHeapFreeBlockSize(before_block^.Size) + else + before_block_size := 0; - result := AllocMem(size); - if result <> nil then + { if there's enough space, we can slide our current block back and reclaim before_block } + if (before_block_size<NewAllocSize) and ((before_block_size+OldAllocSize+after_block_size)>=NewAllocSize) and + { todo: implement this also for after_block_size>0 } + (after_block_size>0) then begin - if oldsize > size then - oldsize := size; - move(pbyte(p)^, pbyte(result)^, oldsize); + if (before_block_size+OldAllocSize+after_block_size)=NewAllocSize then + begin + if after_block=HeapPtr then + begin + HeapPtr := HeapEnd; + if assigned(before_before_block) then + before_before_block^.Next := HeapPtr + else + FreeList := HeapPtr; + end + else + if assigned(before_before_block) then + before_before_block^.Next := after_block^.Next + else + FreeList := after_block^.Next; + end; + Result := Pointer(TTinyHeapPointerArithmeticType(before_block)+SizeOf(TTinyHeapMemBlockSize)); + Move(p^, Result^, oldsize); + PTinyHeapMemBlockSize(before_block)^ := size; + if (before_block_size+OldAllocSize+after_block_size)>NewAllocSize then + begin + new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(before_block)+NewAllocSize); + new_after_block^.Next:=after_block^.Next; + new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(before_block_size+after_block_size-(NewAllocSize-OldAllocSize)); + if assigned(before_before_block) then + before_before_block^.Next := new_after_block + else + FreeList := new_after_block; + end; + FillChar((TTinyHeapPointerArithmeticType(Result)+oldsize)^, size-oldsize, 0); + p := Result; + end + else + begin + result := AllocMem(size); + if result <> nil then + begin + if oldsize > size then + oldsize := size; + move(pbyte(p)^, pbyte(result)^, oldsize); + end; + SysTinyFreeMem(p); + p := result; end; - SysTinyFreeMem(p); - p := result; end; end; end;