ソースを参照

* more efficient temp allocation, in particular in case many small temps
are allocated at irregular intervals in between larger allocations
(reduces stack usage of taddnode.det_resulttype on darwin/i386 from
11+kb to 868 bytes; no effect on Darwin/ppc, and a few small
improvements on linux/i386)

git-svn-id: trunk@4640 -

Jonas Maebe 19 年 前
コミット
b50841bfce
2 ファイル変更74 行追加9 行削除
  1. 24 0
      compiler/cutils.pas
  2. 50 9
      compiler/tgobj.pas

+ 24 - 0
compiler/cutils.pas

@@ -56,6 +56,7 @@ interface
     function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
 
     function used_align(varalign,minalign,maxalign:shortint):shortint;
+    function isbetteralignedthan(new, org, limit: cardinal): boolean;
     function size_2_align(len : longint) : shortint;
     function packedbitsloadsize(bitlen: int64) : int64;
     procedure Replace(var s:string;s1:string;const s2:string);
@@ -292,6 +293,29 @@ uses
       end;
 
 
+    function isbetteralignedthan(new, org, limit: cardinal): boolean;
+      var
+        cnt: cardinal;
+      begin
+        cnt:=2;
+        while (cnt <= limit) do
+          begin
+            if (org and (cnt-1)) > (new and (cnt-1)) then
+              begin
+                result:=true;
+                exit;
+              end
+            else if (org and (cnt-1)) < (new and (cnt-1)) then
+              begin
+                result:=false;
+                exit;
+              end;
+            cnt:=cnt*2;
+          end;
+        result:=false;
+      end;
+
+
     function used_align(varalign,minalign,maxalign:shortint):shortint;
       begin
         { varalign  : minimum alignment required for the variable

+ 50 - 9
compiler/tgobj.pas

@@ -218,14 +218,16 @@ implementation
          tl,htl,
          bestslot,bestprev,
          hprev,hp : ptemprecord;
-         bestsize : longint;
          freetype : ttemptype;
+         bestatend,
+         fitatbegin,
+         fitatend : boolean;
       begin
          AllocTemp:=0;
          bestprev:=nil;
          bestslot:=nil;
          tl:=nil;
-         bestsize:=0;
+         bestatend:=false;
 
          if size=0 then
           begin
@@ -260,23 +262,56 @@ implementation
                if (hp^.temptype=freetype) and
                   (hp^.def=def) and
                   (hp^.size>=size) and
-                  (hp^.pos=align(hp^.pos,alignment)) then
+                  ((hp^.pos=align(hp^.pos,alignment)) or
+                   (hp^.pos+hp^.size-size = align(hp^.pos+hp^.size-size,alignment))) then
                 begin
                   { Slot is the same size then leave immediatly }
                   if (hp^.size=size) then
                    begin
                      bestprev:=hprev;
                      bestslot:=hp;
-                     bestsize:=size;
                      break;
                    end
                   else
                    begin
-                     if (bestsize=0) or (hp^.size<bestsize) then
+                     { we can fit a smaller block either at the begin or at }
+                     { the end of a block. For direction=-1 we prefer the   }
+                     { end, for direction=1 we prefer the begin (i.e.,      }
+                     { always closest to the source). We also try to use    }
+                     { the block with the worst possible alignment that     }
+                     { still suffices. And we pick the block which will     }
+                     { have the best alignmenment after this new block is   }
+                     { substracted from it.                                 }
+                     fitatend:=(hp^.pos+hp^.size-size)=align(hp^.pos+hp^.size-size,alignment);
+                     fitatbegin:=hp^.pos=align(hp^.pos,alignment);
+                     if assigned(bestslot) then
+                       begin
+                         fitatend:=fitatend and
+                           ((not bestatend and
+                             (direction=-1)) or
+                            (bestatend and
+                             isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(hp^.pos+hp^.size-size),aktalignment.localalignmax)));
+                         fitatbegin:=fitatbegin and
+                           (not bestatend or
+                            (direction=1)) and
+                           isbetteralignedthan(abs(hp^.pos+size),abs(bestslot^.pos+size),aktalignment.localalignmax);
+                       end;
+                     if fitatend and
+                        fitatbegin then
+                       if isbetteralignedthan(abs(hp^.pos+hp^.size-size),abs(hp^.pos+size),aktalignment.localalignmax) then
+                         fitatbegin:=false
+                       else if isbetteralignedthan(abs(hp^.pos+size),abs(hp^.pos+hp^.size-size),aktalignment.localalignmax) then
+                         fitatend:=false
+                       else if (direction=1) then
+                         fitatend:=false
+                       else
+                         fitatbegin:=false;
+                     if fitatend or
+                        fitatbegin then
                       begin
                         bestprev:=hprev;
                         bestslot:=hp;
-                        bestsize:=hp^.size;
+                        bestatend:=fitatend;
                       end;
                    end;
                 end;
@@ -287,7 +322,7 @@ implementation
          { Reuse an old temp ? }
          if assigned(bestslot) then
           begin
-            if bestsize=size then
+            if bestslot^.size=size then
              begin
                tl:=bestslot;
                { Remove from the tempfreelist }
@@ -308,7 +343,8 @@ implementation
                  For direction=1 we can use tl for the new block. For direction=-1 we
                  will be reusing bestslot and resize the new block, that means we need
                  to swap the pointers }
-               if direction=-1 then
+               if (direction=-1) xor
+                  bestatend then
                  begin
                    htl:=tl;
                    tl:=bestslot;
@@ -319,12 +355,17 @@ implementation
                    else
                      tempfreelist:=bestslot;
                  end;
+
+               if not bestatend then
+                 inc(bestslot^.pos,size)
+               else
+                 inc(tl^.pos,tl^.size-size);
+
                { Create new block and resize the old block }
                tl^.size:=size;
                tl^.nextfree:=nil;
                { Resize the old block }
                dec(bestslot^.size,size);
-               inc(bestslot^.pos,size);
              end;
             tl^.temptype:=temptype;
             tl^.def:=def;