mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-07 22:50:24 +02:00
* 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 -
This commit is contained in:
parent
83caedf4d2
commit
b50841bfce
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user