Commit ee10850a authored by FPK's avatar FPK
Browse files

* patch by Sergey Larin: Reducing and aligning the size of TAnsiRec,...

  * 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
parent ea6529ff
Pipeline #389748609 passed with stages
in 16 minutes and 52 seconds
......@@ -1196,12 +1196,12 @@ if ((def.typ=recorddef) and
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 @@ if ((def.typ=recorddef) and
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 @@ (curagginfo.def.typ=recorddef) then
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
......
......@@ -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 @@
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;
......
......@@ -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 @@
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;
......
......@@ -50,7 +50,7 @@ procedure testproc(out str);
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);
......
......@@ -52,22 +52,15 @@ function Test(cmd: integer): integer;
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
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment