浏览代码

+ optimizations in SysTinyReAllocMem for the case when growing the heap block
and there is enough free space after the block

git-svn-id: trunk@28723 -

nickysn 10 年之前
父节点
当前提交
1e0a69fa7f
共有 1 个文件被更改,包括 70 次插入7 次删除
  1. 70 7
      rtl/inc/tinyheap.inc

+ 70 - 7
rtl/inc/tinyheap.inc

@@ -260,6 +260,9 @@
     function SysTinyReAllocMem(var p: pointer; size: ptruint):pointer;
       var
         oldsize, OldAllocSize, NewAllocSize: ptruint;
+        after_block, before_block: PTinyHeapBlock;
+        after_block_size: PtrUInt;
+        new_after_block: PTinyHeapBlock;
       begin
 {$ifdef DEBUG_TINY_HEAP}
         Write('SysTinyReAllocMem(', HexStr(p), ',', size, ')=');
@@ -299,15 +302,75 @@
               end
             else
               begin
-                result := AllocMem(size);
-                if result <> nil then
+                { we're increasing the memory block size. First, find if there are free memory blocks immediately
+                  before and after our memory block. }
+                after_block := FreeList;
+                before_block := nil;
+                while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do
                   begin
-                    if oldsize > size then
-                      oldsize := size;
-                    move(pbyte(p)^, pbyte(result)^, oldsize);
+                    before_block := after_block;
+                    after_block := after_block^.Next;
+                  end;
+                { is after_block immediately after our block? }
+                if after_block=Pointer(TTinyHeapPointerArithmeticType(p)+(OldAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))) then
+                  begin
+                    if after_block = HeapPtr then
+                      after_block_size := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))
+                    else
+                      after_block_size := DecodeTinyHeapFreeBlockSize(after_block^.size);
+                  end
+                else
+                  after_block_size := 0;
+                { is there enough room after the block? }
+                if (OldAllocSize+after_block_size)>=NewAllocSize then
+                  begin
+                    if after_block = HeapPtr then
+                      begin
+                        HeapPtr:=Pointer(TTinyHeapPointerArithmeticType(HeapPtr)+(NewAllocSize-OldAllocSize));
+                        if assigned(before_block) then
+                          before_block^.Next := HeapPtr
+                        else
+                          FreeList := HeapPtr;
+                      end
+                    else
+                      begin
+                        if (NewAllocSize-OldAllocSize)=after_block_size then
+                          begin
+                            if assigned(before_block) then
+                              before_block^.Next := after_block^.Next
+                            else
+                              FreeList := after_block^.Next;
+                          end
+                        else
+                          begin
+                            new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(after_block)+(NewAllocSize-OldAllocSize));
+                            new_after_block^.Next:=after_block^.Next;
+                            new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(after_block_size-(NewAllocSize-OldAllocSize));
+                            if assigned(before_block) then
+                              before_block^.Next := new_after_block
+                            else
+                              FreeList := new_after_block;
+                          end;
+                      end;
+                    PTinyHeapMemBlockSize(p)[-1] := size;
+                    FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
+                  end
+                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
+                    //  ;
+
+                    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;
 {$ifdef DEBUG_TINY_HEAP}