Shortcut declocked on refcount = 1.

This commit is contained in:
Rika Ichinose 2025-01-30 05:11:44 +03:00 committed by FPK
parent d06dd9532c
commit 6ccad3dc4e
4 changed files with 19 additions and 32 deletions

View File

@ -2906,8 +2906,9 @@ asm
testl %edx,%edx testl %edx,%edx
jz .Lquit jz .Lquit
movl $0,(%eax) // s:=nil movl $0,(%eax) // s:=nil
cmpl $0,-8(%edx) // exit if refcount<0 cmpl $1,-8(%edx) // exit if refcount<1
jl .Lquit jl .Lquit
je .Lfree // skip the decrement if refcount=1.
{$ifdef FPC_PIC} {$ifdef FPC_PIC}
call fpc_geteipasecx call fpc_geteipasecx
addl $_GLOBAL_OFFSET_TABLE_,%ecx addl $_GLOBAL_OFFSET_TABLE_,%ecx
@ -2925,15 +2926,7 @@ asm
ret ret
.Lfree: .Lfree:
leal -12(%edx),%eax // points to start of allocation leal -12(%edx),%eax // points to start of allocation
{ freemem is not an assembler leaf function like fpc_geteipasecx, so it jmp FPC_FREEMEM // nostackframe + jmp allows to ignore stack alignment.
needs to be called with proper stack alignment }
{$ifdef FPC_SYSTEM_STACKALIGNMENT16}
leal -12(%esp),%esp
call FPC_FREEMEM
leal 12(%esp),%esp
{$else FPC_SYSTEM_STACKALIGNMENT16}
jmp FPC_FREEMEM // can perform a tail call
{$endif FPC_SYSTEM_STACKALIGNMENT16}
end; end;
function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward; function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;

View File

@ -139,18 +139,16 @@ Procedure fpc_ansistr_decr_ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DEC
If the reference count is zero, deallocate the string; If the reference count is zero, deallocate the string;
} }
Var Var
p: PAnsiRec; p: pointer;
Begin Begin
{ Zero string } p:=S;
If S=Nil then If p=Nil then
exit; exit;
{ check for constant strings ...}
p:=PAnsiRec(S-AnsiFirstOff);
s:=nil; s:=nil;
If p^.ref<0 then exit; If (PAnsiRec(p-AnsiFirstOff)^.ref>0) and { ref = -1 is constant string. }
{ declocked does a MT safe dec and returns true, if the counter is 0 } ((PAnsiRec(p-AnsiFirstOff)^.ref=1) { Shortcut declocked on ref = 1. }
If declocked(p^.ref) then or declocked(PAnsiRec(p-AnsiFirstOff)^.ref)) then
FreeMem(p); FreeMem(p-AnsiFirstOff);
end; end;
{$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF} {$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF}

View File

@ -86,7 +86,7 @@ procedure fpc_dynarray_clear(var p : pointer;ti : pointer); [Public,Alias:'FPC_D
if not assigned(pv) then if not assigned(pv) then
exit; exit;
p:=nil; p:=nil;
if (pv[-1].refcount>0) and declocked(pv[-1].refcount) then if (pv[-1].refcount>0) and ((pv[-1].refcount=1) or declocked(pv[-1].refcount)) then
begin begin
ti:=pdynarraytypedata(aligntoqword(ti+2+PByte(ti)[1]))^.elType; ti:=pdynarraytypedata(aligntoqword(ti+2+PByte(ti)[1]))^.elType;
if assigned(ti) then if assigned(ti) then

View File

@ -216,20 +216,16 @@ Procedure fpc_UnicodeStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_UNICODEST
If the reference count is zero, deallocate the string; If the reference count is zero, deallocate the string;
} }
Var Var
p: PUnicodeRec; p: pointer;
Begin Begin
{ Zero string } p:=S;
if S=Nil then If p=Nil then
exit; exit;
{ check for constant strings ...} s:=nil;
p:=PUnicodeRec(S-UnicodeFirstOff); If (PUnicodeRec(p-UnicodeFirstOff)^.ref>0) and { ref = -1 is constant string. }
S:=nil; ((PUnicodeRec(p-UnicodeFirstOff)^.ref=1) { Shortcut declocked on ref = 1. }
if p^.Ref<0 then or declocked(PUnicodeRec(p-UnicodeFirstOff)^.ref)) then
exit; FreeMem(p-UnicodeFirstOff);
{ declocked does a MT safe dec and returns true, if the counter is 0 }
if declocked(p^.Ref) then
FreeMem(p);
end; end;
{ alias for internal use } { alias for internal use }