Explorar o código

+ heap manager: reduce overhead on fixed size chunks from 8 to 4

git-svn-id: trunk@4904 -
micha %!s(int64=19) %!d(string=hai) anos
pai
achega
dc3b37ff73
Modificáronse 1 ficheiros con 154 adicións e 163 borrados
  1. 154 163
      rtl/inc/heap.inc

+ 154 - 163
rtl/inc/heap.inc

@@ -53,7 +53,8 @@ const
   lastblockflag  = 4;   { flag if the block is the last in os chunk }
   lastblockflag  = 4;   { flag if the block is the last in os chunk }
   firstblockflag = 8;   { flag if the block is the first in os chunk }
   firstblockflag = 8;   { flag if the block is the first in os chunk }
   sizemask = not(blocksize-1);
   sizemask = not(blocksize-1);
-  fixedsizemask = sizemask and $ffff;
+  fixedoffsetshift = 16;
+  fixedsizemask = sizemask and ((1 shl fixedoffsetshift) - 1);
 
 
 {****************************************************************************}
 {****************************************************************************}
 
 
@@ -95,32 +96,26 @@ const
 {$ifndef HAS_MEMORYMANAGER}
 {$ifndef HAS_MEMORYMANAGER}
 type
 type
   poschunk = ^toschunk;
   poschunk = ^toschunk;
-  { keep size of this record dividable by 16 }
   toschunk = record
   toschunk = record
-    size,
-    used,
-    chunkindex : ptrint;
+    size : ptrint;
     next,
     next,
-    prev  : poschunk;
-{$ifdef CPU64}
-    pad1 : array[0..0] of pointer;
-{$else CPU64}
-    pad1 : array[0..2] of pointer;
-{$endif CPU64}
+    prev : poschunk;
+    used : ptrint;
+    { padding inserted automatically by alloc_oschunk }
   end;
   end;
 
 
   pmemchunk_fixed  = ^tmemchunk_fixed;
   pmemchunk_fixed  = ^tmemchunk_fixed;
   tmemchunk_fixed = record
   tmemchunk_fixed = record
-    size   : ptrint;
-    poc    : poschunk;
+    { aligning is done automatically in alloc_oschunk }
+    size  : ptrint;
     next_fixed,
     next_fixed,
     prev_fixed : pmemchunk_fixed;
     prev_fixed : pmemchunk_fixed;
   end;
   end;
 
 
   pmemchunk_var  = ^tmemchunk_var;
   pmemchunk_var  = ^tmemchunk_var;
   tmemchunk_var = record
   tmemchunk_var = record
-    size     : ptrint;
     prevsize : ptrint;
     prevsize : ptrint;
+    size  : ptrint;
     next_var,
     next_var,
     prev_var  : pmemchunk_var;
     prev_var  : pmemchunk_var;
   end;
   end;
@@ -128,21 +123,25 @@ type
   { ``header'', ie. size of structure valid when chunk is in use }
   { ``header'', ie. size of structure valid when chunk is in use }
   { should correspond to tmemchunk_var_hdr structure starting with the
   { should correspond to tmemchunk_var_hdr structure starting with the
     last field. Reason is that the overlap is starting from the end of the
     last field. Reason is that the overlap is starting from the end of the
-    record.
-    Alignment is 8 bytes for 32bit machines. This required
-    for x86 MMX/SSE and for sparc Double values }
+    record. }
   tmemchunk_fixed_hdr = record
   tmemchunk_fixed_hdr = record
-    size     : ptrint;
-    poschunk : pointer;
+    { aligning is done automatically in alloc_oschunk }
+    size : ptrint;
   end;
   end;
   tmemchunk_var_hdr = record
   tmemchunk_var_hdr = record
-    prevsize,
-    size     : ptrint;
+    prevsize : ptrint;
+    size : ptrint;
   end;
   end;
 
 
   tfreelists   = array[1..maxblockindex] of pmemchunk_fixed;
   tfreelists   = array[1..maxblockindex] of pmemchunk_fixed;
   pfreelists   = ^tfreelists;
   pfreelists   = ^tfreelists;
 
 
+const
+  fixedfirstoffset = ((sizeof(toschunk) + sizeof(tmemchunk_fixed_hdr) + $f) 
+      and not $f) - sizeof(tmemchunk_fixed_hdr);
+  varfirstoffset = ((sizeof(toschunk) + sizeof(tmemchunk_var_hdr) + $f) 
+      and not $f) - sizeof(tmemchunk_var_hdr);
+
 var
 var
   internal_status : TFPCHeapStatus;
   internal_status : TFPCHeapStatus;
 
 
@@ -522,7 +521,7 @@ end;
                                 List adding/removal
                                 List adding/removal
 *****************************************************************************}
 *****************************************************************************}
 
 
-procedure append_to_list_var(pmc: pmemchunk_var);inline;
+procedure append_to_list_var(pmc: pmemchunk_var); inline;
 begin
 begin
   pmc^.prev_var := nil;
   pmc^.prev_var := nil;
   pmc^.next_var := freelist_var;
   pmc^.next_var := freelist_var;
@@ -531,7 +530,17 @@ begin
   freelist_var := pmc;
   freelist_var := pmc;
 end;
 end;
 
 
-procedure remove_from_list_var(pmc: pmemchunk_var);inline;
+procedure remove_from_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed); inline;
+begin
+  if assigned(pmc^.next_fixed) then
+    pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
+  if assigned(pmc^.prev_fixed) then
+    pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
+  else
+    freelists_fixed[blockindex] := pmc^.next_fixed;
+end;
+
+procedure remove_from_list_var(pmc: pmemchunk_var); inline;
 begin
 begin
   if assigned(pmc^.next_var) then
   if assigned(pmc^.next_var) then
     pmc^.next_var^.prev_var := pmc^.prev_var;
     pmc^.next_var^.prev_var := pmc^.prev_var;
@@ -581,32 +590,23 @@ var
   poc: poschunk;
   poc: poschunk;
 begin
 begin
   // block eligable for freeing
   // block eligable for freeing
-  poc := pointer(pmc)-sizeof(toschunk);
+  poc := pointer(pmc)-varfirstoffset;
   remove_from_list_var(pmc);
   remove_from_list_var(pmc);
   append_to_oslist(poc);
   append_to_oslist(poc);
 end;
 end;
 
 
-procedure append_to_oslist_fixed(poc: poschunk);
+procedure append_to_oslist_fixed(chunkindex, chunksize: ptrint; poc: poschunk);
 var
 var
   pmc: pmemchunk_fixed;
   pmc: pmemchunk_fixed;
-  chunksize,
-  chunkindex,
-  i, count: ptrint;
+  i, size: ptrint;
 begin
 begin
-  chunkindex:=poc^.chunkindex;
-  chunksize:=chunkindex shl blockshift;
-  pmc := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
-  count := (poc^.size - sizeof(toschunk)) div chunksize;
-  for i := 0 to count - 1 do
-    begin
-      if assigned(pmc^.next_fixed) then
-        pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
-      if assigned(pmc^.prev_fixed) then
-        pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
-      else
-        freelists_fixed[chunkindex] := pmc^.next_fixed;
-      pmc := pointer(pmc)+chunksize;
-    end;
+  size := poc^.size;
+  i := fixedfirstoffset;
+  repeat
+    pmc := pmemchunk_fixed(pointer(poc)+i);
+    remove_from_list_fixed(chunkindex, pmc);
+    inc(i, chunksize);
+  until i > size - chunksize;
   append_to_oslist(poc);
   append_to_oslist(poc);
 end;
 end;
 
 
@@ -734,24 +734,23 @@ end;
                                 Grow Heap
                                 Grow Heap
 *****************************************************************************}
 *****************************************************************************}
 
 
-function alloc_oschunk(chunkindex, size: ptrint):pointer;
+function alloc_oschunk(chunkindex, size: ptrint): pointer;
 var
 var
-  pmcfirst,
-  pmclast,
-  pmc       : pmemchunk_fixed;
+  pmc,
+  pmc_next  : pmemchunk_fixed;
   pmcv      : pmemchunk_var;
   pmcv      : pmemchunk_var;
   poc       : poschunk;
   poc       : poschunk;
-  chunksize,
   minsize,
   minsize,
   maxsize,
   maxsize,
-  i, count  : ptrint;
+  i         : ptrint;
+  chunksize : ptrint;
 begin
 begin
-  result:=nil;
-  chunksize:=chunkindex shl blockshift;
   { increase size by size needed for os block header }
   { increase size by size needed for os block header }
-  minsize := size + sizeof(toschunk);
+  minsize := size + varfirstoffset;
+  { for fixed size chunks we keep offset from os chunk to mem chunk in
+    upper bits, so maximum os chunk size is 64K on 32bit for fixed size }
   if chunkindex<>0 then
   if chunkindex<>0 then
-    maxsize := (chunksize * $ffff) + sizeof(toschunk)
+    maxsize := 1 shl (32-fixedoffsetshift)
   else
   else
     maxsize := high(ptrint);
     maxsize := high(ptrint);
   { blocks available in freelist? }
   { blocks available in freelist? }
@@ -770,47 +769,47 @@ begin
   if poc = nil then
   if poc = nil then
     begin
     begin
 {$ifdef DUMPGROW}
 {$ifdef DUMPGROW}
-      writeln('growheap(',size,')  allocating ',(size+sizeof(toschunk)+$ffff) and $ffff0000);
+      writeln('growheap(',size,')  allocating ',(size+sizeof(toschunk)+$ffff) and not $ffff);
       DumpBlocks;
       DumpBlocks;
 {$endif}
 {$endif}
       { allocate by 64K size }
       { allocate by 64K size }
-      size := (size+sizeof(toschunk)+$ffff) and not $ffff;
+      size := (size+varfirstoffset+$ffff) and not $ffff;
       { allocate smaller blocks for fixed-size chunks }
       { allocate smaller blocks for fixed-size chunks }
-      if chunksize<>0 then
+      if chunkindex<>0 then
         begin
         begin
           poc := SysOSAlloc(GrowHeapSizeSmall);
           poc := SysOSAlloc(GrowHeapSizeSmall);
           if poc<>nil then
           if poc<>nil then
             size := GrowHeapSizeSmall;
             size := GrowHeapSizeSmall;
         end
         end
-      { first try 256K (default) }
+    { first try 256K (default) }
       else if size<=GrowHeapSize1 then
       else if size<=GrowHeapSize1 then
         begin
         begin
           poc := SysOSAlloc(GrowHeapSize1);
           poc := SysOSAlloc(GrowHeapSize1);
           if poc<>nil then
           if poc<>nil then
             size := GrowHeapSize1;
             size := GrowHeapSize1;
         end
         end
-      { second try 1024K (default) }
+    { second try 1024K (default) }
       else if size<=GrowHeapSize2 then
       else if size<=GrowHeapSize2 then
         begin
         begin
           poc := SysOSAlloc(GrowHeapSize2);
           poc := SysOSAlloc(GrowHeapSize2);
           if poc<>nil then
           if poc<>nil then
             size := GrowHeapSize2;
             size := GrowHeapSize2;
         end
         end
-      { else allocate the needed bytes }
+    { else allocate the needed bytes }
       else
       else
         poc := SysOSAlloc(size);
         poc := SysOSAlloc(size);
-      { try again }
+    { try again }
       if poc=nil then
       if poc=nil then
-        begin
-          poc := SysOSAlloc(size);
-          if (poc=nil) then
-            begin
-              if ReturnNilIfGrowHeapFails then
-                exit
-              else
-                HandleError(203);
-            end;
-        end;
+      begin
+        poc := SysOSAlloc(size);
+        if poc=nil then
+          begin
+            if ReturnNilIfGrowHeapFails then
+              exit
+            else
+              HandleError(203);
+          end;
+      end;
       { set the total new heap size }
       { set the total new heap size }
       inc(internal_status.currheapsize,size);
       inc(internal_status.currheapsize,size);
       if internal_status.currheapsize>internal_status.maxheapsize then
       if internal_status.currheapsize>internal_status.maxheapsize then
@@ -819,46 +818,47 @@ begin
   { initialize os-block }
   { initialize os-block }
   poc^.used := 0;
   poc^.used := 0;
   poc^.size := size;
   poc^.size := size;
-  poc^.chunkindex := chunkindex;
-  { initialized oschunck for fixed chunks }
   if chunkindex<>0 then
   if chunkindex<>0 then
     begin
     begin
       { chop os chunk in fixedsize parts,
       { chop os chunk in fixedsize parts,
         maximum of $ffff elements are allowed, otherwise
         maximum of $ffff elements are allowed, otherwise
         there will be an overflow }
         there will be an overflow }
-      count := (size-sizeof(toschunk)) div chunksize;
-      if count>$ffff then
+      chunksize := chunkindex shl blockshift;
+      if size-chunksize>maxsize then
         HandleError(204);
         HandleError(204);
-      { Initialize linkedlist of chunks, the first chunk
-        is pmemchunk_fixed(poc) and the last chunk will be in pmc at
-        the end of the loop }
-      pmcfirst := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
-      pmc:=pmcfirst;
-      for i:=1 to count do
-        begin
-          pmc^.poc:=poc;
-          pmc^.size:=chunksize or fixedsizeflag;
-          pmc^.prev_fixed := pointer(pmc)-chunksize;
-          pmc^.next_fixed := pointer(pmc)+chunksize;
-          pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
-        end;
-      { undo last increase to get last chunk }
-      pmclast := pmemchunk_fixed(pointer(pmc)-chunksize);
-      { Add to freelist and fixup first and last chunk }
-      pmclast^.next_fixed := freelists_fixed[chunkindex];
-      if freelists_fixed[chunkindex]<>nil then
-        freelists_fixed[chunkindex]^.prev_fixed := pmclast;
-      freelists_fixed[chunkindex] := pmcfirst;
-      pmemchunk_fixed(poc)^.prev_fixed:=nil;
-      result:=pmcfirst;
+      { we need to align the user pointers to 8 byte at least for
+        mmx/sse and doubles on sparc, align to 16 bytes }
+      i := fixedfirstoffset;
+      result := pointer(poc) + i;
+      pmc := pmemchunk_fixed(result);
+      pmc^.prev_fixed := nil;
+      repeat
+        pmc^.size := fixedsizeflag or chunksize or (i shl fixedoffsetshift);
+        pmc^.next_fixed := pointer(pmc)+chunksize;
+        inc(i, chunksize);
+        if i <= size - chunksize then
+          begin
+            pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
+            pmc^.prev_fixed := pointer(pmc)-chunksize;
+          end
+        else
+          break;
+      until false;
+      pmc_next := freelists_fixed[chunkindex];
+      pmc^.next_fixed := pmc_next;
+      if pmc_next<>nil then
+        pmc_next^.prev_fixed := pmc;
+      freelists_fixed[chunkindex] := pmemchunk_fixed(result);
     end
     end
   else
   else
     begin
     begin
-      pmcv := pmemchunk_var(pointer(poc)+sizeof(toschunk));
+      { we need to align the user pointers to 8 byte at least for
+        mmx/sse and doubles on sparc, align to 16 bytes }
+      result := pointer(poc)+varfirstoffset;
+      pmcv := pmemchunk_var(result);
       append_to_list_var(pmcv);
       append_to_list_var(pmcv);
-      pmcv^.size := ((size-sizeof(toschunk)) and sizemask) or (firstblockflag or lastblockflag);
+      pmcv^.size := ((size-varfirstoffset) and sizemask) or (firstblockflag or lastblockflag);
       pmcv^.prevsize := 0;
       pmcv^.prevsize := 0;
-      result:=pmcv;
     end;
     end;
 end;
 end;
 
 
@@ -866,41 +866,40 @@ end;
                                  SysGetMem
                                  SysGetMem
 *****************************************************************************}
 *****************************************************************************}
 
 
-function SysGetMem_Fixed(size: ptrint): pointer;
+function SysGetMem_Fixed(chunksize: ptrint): pointer;
 var
 var
-  pmc,hp : pmemchunk_fixed;
-  poc : poschunk;
-  chunkindex : ptrint;
+  pmc, pmc_next: pmemchunk_fixed;
+  poc: poschunk;
+  chunkindex: ptrint;
 begin
 begin
   { try to find a block in one of the freelists per size }
   { try to find a block in one of the freelists per size }
-  chunkindex := size shr blockshift;
+  chunkindex := chunksize shr blockshift;
   pmc := freelists_fixed[chunkindex];
   pmc := freelists_fixed[chunkindex];
   result:=nil;
   result:=nil;
   { no free blocks ? }
   { no free blocks ? }
   if not assigned(pmc) then
   if not assigned(pmc) then
     begin
     begin
-      pmc:=alloc_oschunk(chunkindex, size);
+      pmc := alloc_oschunk(chunkindex, chunksize);
       if not assigned(pmc) then
       if not assigned(pmc) then
         exit;
         exit;
     end;
     end;
   { get a pointer to the block we should return }
   { get a pointer to the block we should return }
   result := pointer(pmc)+sizeof(tmemchunk_fixed_hdr);
   result := pointer(pmc)+sizeof(tmemchunk_fixed_hdr);
   { update freelist }
   { update freelist }
-  hp:=pmc^.next_fixed;
-  poc := pmc^.poc;
-  freelists_fixed[chunkindex] := hp;
-  if assigned(hp) then
-    hp^.prev_fixed := nil;
+  pmc_next := pmc^.next_fixed;
+  freelists_fixed[chunkindex] := pmc_next;
+  if assigned(pmc_next) then
+    pmc_next^.prev_fixed := nil;
+  poc := poschunk(pointer(pmc) - (pmc^.size shr fixedoffsetshift));
   if (poc^.used = 0) then
   if (poc^.used = 0) then
     freelists_free_chunk[chunkindex] := false;
     freelists_free_chunk[chunkindex] := false;
   inc(poc^.used);
   inc(poc^.used);
   { statistics }
   { statistics }
-  inc(internal_status.currheapused,size);
+  inc(internal_status.currheapused,chunksize);
   if internal_status.currheapused>internal_status.maxheapused then
   if internal_status.currheapused>internal_status.maxheapused then
     internal_status.maxheapused:=internal_status.currheapused;
     internal_status.maxheapused:=internal_status.currheapused;
 end;
 end;
 
 
-
 function SysGetMem_Var(size: ptrint): pointer;
 function SysGetMem_Var(size: ptrint): pointer;
 var
 var
   pcurr : pmemchunk_var;
   pcurr : pmemchunk_var;
@@ -994,23 +993,23 @@ end;
 
 
 function SysFreeMem_Fixed(pmc: pmemchunk_fixed): ptrint;
 function SysFreeMem_Fixed(pmc: pmemchunk_fixed): ptrint;
 var
 var
-  hp : pmemchunk_fixed;
-  chunksize,
-  chunkindex : ptrint;
-  poc : poschunk;
+  chunkindex,
+  chunksize: ptrint;
+  poc: poschunk;
+  pmc_next: pmemchunk_fixed;
 begin
 begin
-  poc := pmc^.poc;
-  chunkindex:=poc^.chunkindex;
-  chunksize:=chunkindex shl blockshift;
-  { statistics }
-  dec(internal_status.currheapused,chunksize);
-  hp:=freelists_fixed[chunkindex];
+  chunksize := pmc^.size and fixedsizemask;
+  dec(internal_status.currheapused, chunksize);
   { insert the block in it's freelist }
   { insert the block in it's freelist }
+  chunkindex := chunksize shr blockshift;
+  pmc_next := freelists_fixed[chunkindex];
   pmc^.prev_fixed := nil;
   pmc^.prev_fixed := nil;
-  pmc^.next_fixed := hp;
-  if assigned(hp) then
-    hp^.prev_fixed := pmc;
+  pmc^.next_fixed := pmc_next;
+  if assigned(pmc_next) then
+    pmc_next^.prev_fixed := pmc;
   freelists_fixed[chunkindex] := pmc;
   freelists_fixed[chunkindex] := pmc;
+  { decrease used blocks count }
+  poc := poschunk(pointer(pmc)-(pmc^.size shr fixedoffsetshift));
   dec(poc^.used);
   dec(poc^.used);
   if poc^.used <= 0 then
   if poc^.used <= 0 then
     begin
     begin
@@ -1019,47 +1018,44 @@ begin
         HandleError(204);
         HandleError(204);
       { osblock can be freed? }
       { osblock can be freed? }
       if freelists_free_chunk[chunkindex] then
       if freelists_free_chunk[chunkindex] then
-        append_to_oslist_fixed(poc)
+        append_to_oslist_fixed(chunkindex, chunksize, poc)
       else
       else
         freelists_free_chunk[chunkindex] := true;
         freelists_free_chunk[chunkindex] := true;
     end;
     end;
   result := chunksize;
   result := chunksize;
 end;
 end;
 
 
-
-function SysFreeMem_Var(pcurr: pmemchunk_var): ptrint;
+function SysFreeMem_Var(pmcv: pmemchunk_var): ptrint;
 var
 var
   chunksize: ptrint;
   chunksize: ptrint;
 begin
 begin
-  chunksize := pcurr^.size and sizemask;
+  chunksize := pmcv^.size and sizemask;
   dec(internal_status.currheapused,chunksize);
   dec(internal_status.currheapused,chunksize);
   { insert the block in it's freelist }
   { insert the block in it's freelist }
-  pcurr^.size := pcurr^.size and (not usedflag);
-  append_to_list_var(pcurr);
+  pmcv^.size := pmcv^.size and (not usedflag);
+  append_to_list_var(pmcv);
+  pmcv := try_concat_free_chunk(pmcv);
+  if (pmcv^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
+    append_to_oslist_var(pmcv);
   result := chunksize;
   result := chunksize;
-  pcurr := try_concat_free_chunk(pcurr);
-  if (pcurr^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
-    append_to_oslist_var(pcurr);
 end;
 end;
 
 
 
 
 function SysFreeMem(p: pointer): ptrint;
 function SysFreeMem(p: pointer): ptrint;
 var
 var
-  hp : pmemchunk_fixed;
+  pmc: pmemchunk_fixed;
 begin
 begin
   if p=nil then
   if p=nil then
     begin
     begin
       result:=0;
       result:=0;
       exit;
       exit;
     end;
     end;
-
-  hp:=pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr));
-
+  pmc := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr));
   { check if this is a fixed- or var-sized chunk }
   { check if this is a fixed- or var-sized chunk }
-  if (hp^.size and fixedsizeflag) = 0 then
+  if (pmc^.size and fixedsizeflag) = 0 then
     result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)))
     result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)))
   else
   else
-    result := sysfreemem_fixed(hp);
+    result := sysfreemem_fixed(pmc);
 end;
 end;
 
 
 {*****************************************************************************
 {*****************************************************************************
@@ -1067,27 +1063,15 @@ end;
 *****************************************************************************}
 *****************************************************************************}
 
 
 Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
 Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
-var
-  hp : pmemchunk_fixed;
 begin
 begin
-  SysFreeMemSize := 0;
-  if p=nil then
-    exit;
   if size<=0 then
   if size<=0 then
-    begin
-      if size<0 then
-        HandleError(204);
-      exit;
-    end;
-
-  hp:=pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr));
-  { check if this is a fixed- or var-sized chunk. We can't check the passed
-    size parameter since the block can be resized (by reallocmem) to an
-    optimized value that the user doesn't know }
-  if (hp^.size and fixedsizeflag) = 0 then
-    result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)))
-  else
-    result := sysfreemem_fixed(hp);
+  begin
+    if size<0 then
+      HandleError(204);
+    exit(0);
+  end;
+  { can't free partial blocks, ignore size }
+  result := SysFreeMem(p);
 end;
 end;
 
 
 
 
@@ -1100,12 +1084,12 @@ begin
   result := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
   result := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
   if (result and fixedsizeflag) = 0 then
   if (result and fixedsizeflag) = 0 then
     begin
     begin
-      result := SysMemSize and sizemask;
+      result := result and sizemask;
       dec(result, sizeof(tmemchunk_var_hdr));
       dec(result, sizeof(tmemchunk_var_hdr));
     end
     end
   else
   else
     begin
     begin
-      result := SysMemSize and fixedsizemask;
+      result := result and fixedsizemask;
       dec(result, sizeof(tmemchunk_fixed_hdr));
       dec(result, sizeof(tmemchunk_fixed_hdr));
     end;
     end;
 end;
 end;
@@ -1151,11 +1135,12 @@ begin
         2. For resizing to greater size first check if the size fits in the fixed block range to prevent
         2. For resizing to greater size first check if the size fits in the fixed block range to prevent
            "truncating" the size by the fixedsizemask }
            "truncating" the size by the fixedsizemask }
       if ((size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr))) and
       if ((size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr))) and
-          ((size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and sizemask<=currsize )) then
+          ((size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and sizemask <= currsize)) then
         begin
         begin
           systryresizemem:=true;
           systryresizemem:=true;
           exit;
           exit;
         end;
         end;
+
       { we need to allocate a new fixed or var memchunck }
       { we need to allocate a new fixed or var memchunck }
       exit;
       exit;
     end;
     end;
@@ -1169,7 +1154,7 @@ begin
     begin
     begin
       SysTryResizeMem := true;
       SysTryResizeMem := true;
       exit;
       exit;
-   end;
+    end;
 
 
   { get pointer to block }
   { get pointer to block }
   pcurr := pmemchunk_var(pointer(p)-sizeof(tmemchunk_var_hdr));
   pcurr := pmemchunk_var(pointer(p)-sizeof(tmemchunk_var_hdr));
@@ -1289,6 +1274,7 @@ end;
 {*****************************************************************************
 {*****************************************************************************
                                  InitHeap
                                  InitHeap
 *****************************************************************************}
 *****************************************************************************}
+
 {$ifndef gba}
 {$ifndef gba}
 { This function will initialize the Heap manager and need to be called from
 { This function will initialize the Heap manager and need to be called from
   the initialization of the system unit }
   the initialization of the system unit }
@@ -1306,12 +1292,17 @@ end;
 procedure FinalizeHeap;
 procedure FinalizeHeap;
 var
 var
   poc : poschunk;
   poc : poschunk;
+  pmc : pmemchunk_fixed;
   i : longint;
   i : longint;
 begin
 begin
 {$ifdef HAS_SYSOSFREE}
 {$ifdef HAS_SYSOSFREE}
   for i:=low(freelists_free_chunk) to high(freelists_free_chunk) do
   for i:=low(freelists_free_chunk) to high(freelists_free_chunk) do
     if freelists_free_chunk[i] then
     if freelists_free_chunk[i] then
-      SysOSFree(freelists_fixed[i]^.poc,freelists_fixed[i]^.poc^.size);
+    begin
+      pmc := freelists_fixed[i];
+      poc := poschunk(pointer(pmc)-(pmc^.size shr fixedoffsetshift));
+      SysOSFree(poc,poc^.size);
+    end;
   while assigned(freeoslist) do
   while assigned(freeoslist) do
     begin
     begin
       poc:=freeoslist^.next;
       poc:=freeoslist^.next;