瀏覽代碼

Shortcut declocked on refcount = 1.

Rika Ichinose 6 月之前
父節點
當前提交
6ccad3dc4e
共有 4 個文件被更改,包括 19 次插入32 次删除
  1. 3 10
      rtl/i386/i386.inc
  2. 7 9
      rtl/inc/astrings.inc
  3. 1 1
      rtl/inc/dynarr.inc
  4. 8 12
      rtl/inc/ustrings.inc

+ 3 - 10
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;

+ 7 - 9
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}
 

+ 1 - 1
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

+ 8 - 12
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 }