ソースを参照

Skip nil tails when finalizing pointer arrays.

Rika Ichinose 1 週間 前
コミット
5a0f69f452
1 ファイル変更25 行追加6 行削除
  1. 25 6
      rtl/inc/rtti.inc

+ 25 - 6
rtl/inc/rtti.inc

@@ -104,9 +104,9 @@ end;
 
 procedure InitializeRecord(Data : pointer;Ri : PRecordInfoInit); forward;
 
-procedure InlinedInitialize(Data,TypeInfo : pointer); inline; { Should come before InitializeRecord for inlining. }
 const
-  Flatten: array[TTypeKind] of uint8 =
+  RTTIFlattenInitializePointer = 0;
+  RTTIFlattenInitialize: array[TTypeKind] of uint8 =
   ( { 0: pointer, 1: record, 2: array, 3: variant, 255: unmanaged. }
     {tkUnknown} 255, {tkInteger} 255, {tkChar} 255, {tkEnumeration} 255, {tkFloat} 255,
     {tkSet} 255, {tkMethod} 255, {tkSString} 255, {tkLString} 255, {tkAString} 0,
@@ -115,11 +115,13 @@ const
     {tkDynArray} 0, {tkInterfaceRaw} 255, {tkProcVar} 255, {tkUString} 0, {tkUChar} 255,
     {tkHelper} 255, {tkFile} 255, {tkClassRef} 255, {tkPointer} 255
   );
+
+procedure InlinedInitialize(Data,TypeInfo : pointer); inline; { Should come before InitializeRecord for inlining. }
 var
   ri: PRecordInfoInit;
 begin
-  case cardinal(Flatten[PTypeKind(TypeInfo)^]) of
-    0: { pointer }
+  case cardinal(RTTIFlattenInitialize[PTypeKind(TypeInfo)^]) of
+    RTTIFlattenInitializePointer: { pointer }
       PPointer(Data)^:=Nil;
     1: { record }
       InitializeRecord(Data,RTTIRecordInfoInit(TypeInfo));
@@ -389,11 +391,25 @@ procedure fpc_initialize_array(data,typeinfo : pointer;count : SizeInt); [public
   end;
 
 
+function SkipTrailingNils(data : PPointer;count : SizeInt) : SizeInt;
+  var
+    pd: PPointer;
+  begin
+    pd:=data+count;
+    while (pd<>data) and not Assigned(pd[-1]) do
+      dec(pd);
+    result:=SizeUint(pointer(pd)-pointer(data)) div sizeof(pointer);
+  end;
+
+
 procedure fpc_finalize_array(data,typeinfo : pointer;count : SizeInt); [Public,Alias:'FPC_FINALIZE_ARRAY'];  compilerproc;
   var
     size,i : SizeInt;
   begin
-    if RTTIManagementAndSize(typeinfo, rotFinalize, size, false) then
+    if RTTIFlattenInitialize[PTypeKind(typeinfo)^]=RTTIFlattenInitializePointer then
+      for i:=0 to SkipTrailingNils(data,count)-1 do
+        int_finalize(PPointer(data)+i,typeinfo)
+    else if RTTIManagementAndSize(typeinfo, rotFinalize, size, false) then
       for i:=0 to count-1 do
         int_finalize(data+size*i,typeinfo);
   end;
@@ -403,7 +419,10 @@ procedure fpc_addref_array(data,typeinfo: pointer; count: SizeInt); [public,alia
   var
     size,i : SizeInt;
   begin
-    if RTTIManagementAndSize(typeinfo, rotAddRef, size, false) then
+    if RTTIFlattenInitialize[PTypeKind(typeinfo)^]=RTTIFlattenInitializePointer then
+      for i:=0 to SkipTrailingNils(data,count)-1 do
+        int_addref(PPointer(data)+i,typeinfo)
+    else if RTTIManagementAndSize(typeinfo, rotAddRef, size, false) then
       for i:=0 to count-1 do
         int_addref(data+size*i,typeinfo);
   end;