Przeglądaj źródła

* patch by Sergey Larin: Reducing and aligning the size of TAnsiRec, TUnicodeRec for CPU64, resolves #38018:
For CPU64, the size of record TAnsiRec and TUnicodeRec is 16 bytes instead of 24.
Which is very good also because of the alignment. when allocating memory, the address
of the first character of the string will be aligned on the 16-byte boundary.
At the same time, the useless Dummy field, which is needed in CPU64 for exactly alignment, has been removed.
For CPU32 (and CPU16), the record size has not changed, so procedures such as
fpc_AnsiStr_Decr_Ref, implemented in assembler (see i386, arm), remained working correctly.
* tests adapted

florian 3 lat temu
rodzic
commit
ee10850a57
5 zmienionych plików z 45 dodań i 36 usunięć
  1. 12 12
      compiler/aasmcnst.pas
  2. 14 6
      rtl/inc/astrings.inc
  3. 12 4
      rtl/inc/ustrings.inc
  4. 1 1
      tests/webtbs/tw20962.pp
  5. 6 13
      tests/webtbs/tw7100.pp

+ 12 - 12
compiler/aasmcnst.pas

@@ -1196,12 +1196,12 @@ implementation
          2 +
          { elesize }
          2 +
-{$ifdef cpu64bitaddr}
-         { alignment }
-         4 +
-{$endif cpu64bitaddr}
          { reference count }
+{$ifdef cpu64bitaddr}
+         s32inttype.size +
+{$else !cpu64bitaddr}
          sizesinttype.size +
+{$endif !cpu64bitaddr}
          { length }
          sizesinttype.size;
        unicodestring_header_size:=ansistring_header_size;
@@ -1442,12 +1442,12 @@ implementation
        emit_tai(tai_const.create_16bit(elesize),u16inttype);
        inc(result.ofs,2);
 {$ifdef cpu64bitaddr}
-       { dummy for alignment }
-       emit_tai(tai_const.create_32bit(0),u32inttype);
-       inc(result.ofs,4);
-{$endif cpu64bitaddr}
+       emit_tai(tai_const.Create_32bit(-1),s32inttype);
+       inc(result.ofs,s32inttype.size);
+{$else !cpu64bitaddr}
        emit_tai(tai_const.create_sizeint(-1),sizesinttype);
        inc(result.ofs,sizesinttype.size);
+{$endif !cpu64bitaddr}
        emit_tai(tai_const.create_sizeint(len),sizesinttype);
        inc(result.ofs,sizesinttype.size);
        if string_symofs=0 then
@@ -1653,12 +1653,12 @@ implementation
              else
                internalerror(2016082301);
            end;
-{$ifdef cpu64bitaddr}
-           { dummy for alignment }
-           result.add_field_by_def('',u32inttype);
-{$endif cpu64bitaddr}
            { reference count }
+{$ifdef cpu64bitaddr}
+           result.add_field_by_def('',s32inttype);
+{$else !cpu64bitaddr}
            result.add_field_by_def('',sizesinttype);
+{$endif !cpu64bitaddr}
            { length in elements }
            result.add_field_by_def('',sizesinttype);
          end

+ 14 - 6
rtl/inc/astrings.inc

@@ -24,11 +24,11 @@
   This file contains the implementation of the AnsiString type,
   and all things that are needed for it.
   AnsiString is defined as a 'silent' pchar :
-  a pchar that points to (S= SizeOf(SizeInt)):
+  a pchar that points to (S= SizeOf(SizeInt), R= (if CPU64 then SizeOf(Longint) else SizeOf(SizeInt))):
 
-  @-3*S   : Code page indicator.
-  @-3*S+2 : Character size (2 bytes)
-  @-2*S   : SizeInt for reference count;
+  @-S-R-4 : Code page indicator.
+  @-S-R-2 : Character size (2 bytes)
+  @-S-R   : Reference count (R bytes)
   @-S  : SizeInt for size;
   @    : String + Terminating #0;
   Pchar(Ansistring) is a valid typecast.
@@ -43,11 +43,19 @@ Type
   TAnsiRec = Record
     CodePage    : TSystemCodePage;
     ElementSize : Word;
-{$ifdef CPU64}	
+{$if not defined(VER3_0) and not defined(VER3_2)}
+  {$ifdef CPU64}	
+    Ref         : Longint;
+  {$else}
+    Ref         : SizeInt;
+  {$endif}
+{$else}
+  {$ifdef CPU64}	
     { align fields  }
 	Dummy       : DWord;
-{$endif CPU64}
+  {$endif CPU64}
     Ref         : SizeInt;
+{$endif}
     Len         : SizeInt;
   end;
 

+ 12 - 4
rtl/inc/ustrings.inc

@@ -21,9 +21,9 @@
   This file contains the implementation of the UnicodeString type,
   and all things that are needed for it.
   UnicodeString is defined as a 'silent' punicodechar :
-  a punicodechar that points to (S = SizeOf(SizeInt)) :
+  a punicodechar that points to (S= SizeOf(SizeInt), R= (if CPU64 then SizeOf(Longint) else SizeOf(SizeInt))):
 
-  @-2*S : SizeInt for reference count;
+  @-S-R : Reference count (R bytes)
   @-S   : SizeInt for size; size=number of chars. Multiply with
           sizeof(UnicodeChar) to get the number of bytes. This is compatible with Delphi.
   @      : String + Terminating #0;
@@ -39,11 +39,19 @@ Type
   TUnicodeRec = Record
     CodePage    : TSystemCodePage;
     ElementSize : Word;
-{$ifdef CPU64}	
+{$if not defined(VER3_0) and not defined(VER3_2)}
+  {$ifdef CPU64}	
+    Ref         : Longint;
+  {$else}
+    Ref         : SizeInt;
+  {$endif}
+{$else}
+  {$ifdef CPU64}	
     { align fields  }
 	Dummy       : DWord;
-{$endif CPU64}
+  {$endif CPU64}
     Ref         : SizeInt;
+{$endif}
     Len         : SizeInt;
   end;
 

+ 1 - 1
tests/webtbs/tw20962.pp

@@ -50,7 +50,7 @@ begin
  move('abcde',str1[1],5);
  str2:= str1;
  testproc(str2);
- if psizeint(pchar(pointer(str1))-2*sizeof(sizeint))^ <> 1 then
+ if StringRefCount(str1) <> 1 then
    Halt(1);
  if str1<>'abcde' then
    Halt(2);  

+ 6 - 13
tests/webtbs/tw7100.pp

@@ -52,22 +52,15 @@ end;
 procedure DumpString(const s: string);
 var
   i: sizeint;
-  pi: psizeint;
   pb: pbyte;
 begin
-  pi := psizeint(s);
-  pb := pbyte(pi);
+  pb := pbyte(s);
 
-  // Printing reference counter and string length
-  dec(pi, 2);
-  for i:=1 to 2 do
-  begin
-    { refcount has to be 1, length 2 -> happens to be the same as i }
-    if (pi^ <> i) then
-      halt(1);
-    write(IntToHex(pi^, sizeof(sizeint)*2),' ');
-    inc(pi);
-  end;
+  write(IntToHex(StringRefCount(s), sizeof(sizeint)*2),' ',IntToHex(Length(s), sizeof(sizeint)*2),' ');
+  if StringRefCount(s)<>1 then
+    halt(1);
+  if Length(s)<>2 then
+    halt(1);
 
   // Printing string bytes
   for i:=1 to length(s) do