From 6ccad3dc4e7ad93c39eeeeb2cd0f99775feb340a Mon Sep 17 00:00:00 2001 From: Rika Ichinose Date: Thu, 30 Jan 2025 05:11:44 +0300 Subject: [PATCH] Shortcut declocked on refcount = 1. --- rtl/i386/i386.inc | 13 +++---------- rtl/inc/astrings.inc | 16 +++++++--------- rtl/inc/dynarr.inc | 2 +- rtl/inc/ustrings.inc | 20 ++++++++------------ 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 07187c74e9..1fcc402207 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -2906,8 +2906,9 @@ asm testl %edx,%edx jz .Lquit movl $0,(%eax) // s:=nil - cmpl $0,-8(%edx) // exit if refcount<0 + cmpl $1,-8(%edx) // exit if refcount<1 jl .Lquit + je .Lfree // skip the decrement if refcount=1. {$ifdef FPC_PIC} call fpc_geteipasecx addl $_GLOBAL_OFFSET_TABLE_,%ecx @@ -2925,15 +2926,7 @@ asm ret .Lfree: leal -12(%edx),%eax // points to start of allocation - { freemem is not an assembler leaf function like fpc_geteipasecx, so it - 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} + jmp FPC_FREEMEM // nostackframe + jmp allows to ignore stack alignment. end; function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward; diff --git a/rtl/inc/astrings.inc b/rtl/inc/astrings.inc index 4014910934..9ec5a7bfe9 100644 --- a/rtl/inc/astrings.inc +++ b/rtl/inc/astrings.inc @@ -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; } Var - p: PAnsiRec; + p: pointer; Begin - { Zero string } - If S=Nil then + p:=S; + If p=Nil then exit; - { check for constant strings ...} - p:=PAnsiRec(S-AnsiFirstOff); s:=nil; - If p^.ref<0 then exit; - { declocked does a MT safe dec and returns true, if the counter is 0 } - If declocked(p^.ref) then - FreeMem(p); + If (PAnsiRec(p-AnsiFirstOff)^.ref>0) and { ref = -1 is constant string. } + ((PAnsiRec(p-AnsiFirstOff)^.ref=1) { Shortcut declocked on ref = 1. } + or declocked(PAnsiRec(p-AnsiFirstOff)^.ref)) then + FreeMem(p-AnsiFirstOff); end; {$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF} diff --git a/rtl/inc/dynarr.inc b/rtl/inc/dynarr.inc index acf0c1885f..697e73f4cd 100644 --- a/rtl/inc/dynarr.inc +++ b/rtl/inc/dynarr.inc @@ -86,7 +86,7 @@ procedure fpc_dynarray_clear(var p : pointer;ti : pointer); [Public,Alias:'FPC_D if not assigned(pv) then exit; 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 ti:=pdynarraytypedata(aligntoqword(ti+2+PByte(ti)[1]))^.elType; if assigned(ti) then diff --git a/rtl/inc/ustrings.inc b/rtl/inc/ustrings.inc index ddd3ad14d6..6d8843c399 100644 --- a/rtl/inc/ustrings.inc +++ b/rtl/inc/ustrings.inc @@ -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; } Var - p: PUnicodeRec; + p: pointer; Begin - { Zero string } - if S=Nil then + p:=S; + If p=Nil then exit; - { check for constant strings ...} - p:=PUnicodeRec(S-UnicodeFirstOff); - S:=nil; - if p^.Ref<0 then - exit; - - { declocked does a MT safe dec and returns true, if the counter is 0 } - if declocked(p^.Ref) then - FreeMem(p); + s:=nil; + If (PUnicodeRec(p-UnicodeFirstOff)^.ref>0) and { ref = -1 is constant string. } + ((PUnicodeRec(p-UnicodeFirstOff)^.ref=1) { Shortcut declocked on ref = 1. } + or declocked(PUnicodeRec(p-UnicodeFirstOff)^.ref)) then + FreeMem(p-UnicodeFirstOff); end; { alias for internal use }