Browse Source

Faster RTTIManagementAndSize -_-.

Rika Ichinose 11 months ago
parent
commit
cd2c8a6539
3 changed files with 56 additions and 57 deletions
  1. 3 3
      rtl/inc/dynarr.inc
  2. 52 53
      rtl/inc/rtti.inc
  3. 1 1
      rtl/inc/rttidecl.inc

+ 3 - 3
rtl/inc/dynarr.inc

@@ -182,7 +182,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
        begin
        begin
           newp:=AllocMem(size);
           newp:=AllocMem(size);
           { call int_InitializeArray for management operators; not required if no operators as memory is already zeroed }
           { call int_InitializeArray for management operators; not required if no operators as memory is already zeroed }
-          if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size)=manCustom) then
+          if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, manCustom)=manCustom) then
             int_InitializeArray(pointer(newp)+sizeof(tdynarray), eletype, dims[0]);
             int_InitializeArray(pointer(newp)+sizeof(tdynarray), eletype, dims[0]);
        end
        end
      else
      else
@@ -204,7 +204,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
                if size-sizeof(tdynarray)>movsize then
                if size-sizeof(tdynarray)>movsize then
                  begin
                  begin
                    fillchar((pointer(newp)+sizeof(tdynarray)+movsize)^,size-sizeof(tdynarray)-movsize,0);
                    fillchar((pointer(newp)+sizeof(tdynarray)+movsize)^,size-sizeof(tdynarray)-movsize,0);
-                   if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size)=manCustom) then
+                   if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, manCustom)=manCustom) then
                      int_InitializeArray(pointer(newp)+sizeof(tdynarray)+movsize, eletype, dims[0]-movelen);
                      int_InitializeArray(pointer(newp)+sizeof(tdynarray)+movsize, eletype, dims[0]-movelen);
                  end;
                  end;
 
 
@@ -238,7 +238,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
                newp := realp;
                newp := realp;
                fillchar((pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1))^,
                fillchar((pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1))^,
                  (dims[0]-newp^.high-1)*elesize,0);
                  (dims[0]-newp^.high-1)*elesize,0);
-               if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size)=manCustom) then
+               if assigned(eletypemngd) and (PTypeKind(eletype)^ in [tkRecord, tkObject, tkArray]) and (RTTIManagementAndSize(eletype, rotInitialize, _size, manCustom)=manCustom) then
                  int_InitializeArray(pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1),
                  int_InitializeArray(pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1),
                    eletype, dims[0]-newp^.high-1);
                    eletype, dims[0]-newp^.high-1);
             end;
             end;

+ 52 - 53
rtl/inc/rtti.inc

@@ -44,60 +44,59 @@ begin
 end;
 end;
 
 
 { result = manBuiltin means e.g. that initialization is simply zeroing and can be omitted if the memory is already zeroed, as in dynarr.inc. }
 { result = manBuiltin means e.g. that initialization is simply zeroing and can be omitted if the memory is already zeroed, as in dynarr.inc. }
-function RTTIManagementAndSize(typeInfo: Pointer; op: TRTTIRecOpType; out size: SizeInt): TRTTIManagement;
+function RTTIManagementAndSize(typeInfo: Pointer; op: TRTTIRecOpType; out size: SizeInt; maxInteresting: TRTTIManagement): TRTTIManagement;
+const
+  Special = 49;
+  ManagedSizes: array[TTypeKind] of uint8 = { 0 — unmanaged, Special — special, otherwise manBuiltin of that size. }
+  (
+    {tkUnknown} 0, {tkInteger} 0, {tkChar} 0, {tkEnumeration} 0, {tkFloat} 0,
+    {tkSet} 0, {tkMethod} 0, {tkSString} 0, {tkLString} 0, {tkAString} sizeof(pointer),
+    {tkWString} sizeof(pointer), {tkVariant} {$ifdef FPC_HAS_FEATURE_VARIANTS} sizeof(TVarData) {$else} 0 {$endif}, {tkArray} Special, {tkRecord} Special, {tkInterface} sizeof(pointer),
+    {tkClass} 0, {tkObject} Special, {tkWChar} 0, {tkBool} 0, {tkInt64} 0, {tkQWord} 0,
+    {tkDynArray} sizeof(pointer), {tkInterfaceRaw} 0, {tkProcVar} 0, {tkUString} sizeof(pointer), {tkUChar} 0,
+    {tkHelper} 0, {tkFile} 0, {tkClassRef} 0, {tkPointer} 0
+  );
 var
 var
   ri: PRecordInfoInit;
   ri: PRecordInfoInit;
-  elem, eElem: PRecordElement;
+  elem: PRecordElement;
   newMan: TRTTIManagement;
   newMan: TRTTIManagement;
   _initrtti: pointer;
   _initrtti: pointer;
-  _size: SizeInt;
+  elemCount,sample,_size: SizeInt;
 begin
 begin
-  case PTypeKind(typeinfo)^ of
-    tkAString,tkWString,tkUString,
-    tkInterface,tkDynarray:
-      begin
-        size:=sizeof(Pointer);
-        result:=manBuiltin;
-      end;
-{$ifdef FPC_HAS_FEATURE_VARIANTS}
-    tkVariant:
-      begin
-        size:=sizeof(TVarData);
-        result:=manBuiltin;
-      end;
-{$endif FPC_HAS_FEATURE_VARIANTS}
-    tkArray:
-      begin
-        typeInfo:=aligntoqword(typeInfo+2+PByte(typeInfo)[1]);
-        size:=PArrayInfo(typeInfo)^.Size;
-        result:=RTTIManagementAndSize(PArrayInfo(typeInfo)^.ElInfo^, op, _size);
-      end;
-    tkObject,
-    tkRecord:
-      begin
-        ri:=RTTIRecordOp(typeInfo, _initrtti);
-        size:=ri^.Size;
-        if Assigned(ri^.RecordOp) and Assigned(ri^.RecordOp^.Ops[op]) then
-          result:=manCustom
-        else
-          begin
-            result:=manNone;
-            elem:=AlignTypeData(Pointer(@ri^.Count)+SizeOf(ri^.Count));
-            eElem:=elem+ri^.Count;
-            while elem<>eElem do
-              begin
-                newMan:=RTTIManagementAndSize(elem^.TypeInfo^, op, _size);
-                if newMan<>manNone then
-                  result:=newMan;
-                if newMan=manCustom then
-                  break;
-                inc(elem);
-              end;
-          end;
-      end;
-  else
-    result:=manNone; { Size undefined, ultimately can be always correct to support unmanaged scenarios. }
-  end;
+  sample:=ManagedSizes[PTypeKind(typeinfo)^];
+  size:=sample;
+  if sample<>Special then
+    result:=TRTTIManagement(ord(sample<>0)) { manNone(0) if sample = 0, manBuiltin(1) otherwise. }
+  else if PTypeKind(typeinfo)^=tkArray then
+    begin
+      typeInfo:=aligntoqword(typeInfo+2+PByte(typeInfo)[1]);
+      size:=PArrayInfo(typeInfo)^.Size;
+      result:=RTTIManagementAndSize(PArrayInfo(typeInfo)^.ElInfo^, op, _size, maxInteresting);
+    end
+  else {tkObject, tkRecord}
+    begin
+      ri:=RTTIRecordOp(typeInfo, _initrtti);
+      size:=ri^.Size;
+      if Assigned(ri^.RecordOp) and Assigned(ri^.RecordOp^.Ops[op]) then
+        exit(manCustom);
+      result:=manNone;
+      elem:=AlignTypeData(Pointer(@ri^.Count)+SizeOf(ri^.Count));
+      for elemCount:=ri^.Count downto 1 do
+        begin
+          sample:=ManagedSizes[PTypeKind(elem^.TypeInfo^)^];
+          if sample<>Special then
+            newMan:=TRTTIManagement(ord(sample<>0)) { Avoid recursive call for simple fields. }
+          else
+            newMan:=RTTIManagementAndSize(elem^.TypeInfo^, op, _size, maxInteresting);
+          if newMan>result then
+            begin
+              result:=newMan;
+              if newMan>=maxInteresting then
+                break;
+            end;
+          inc(elem);
+        end;
+    end;
 end;
 end;
 
 
 { if you modify this procedure, fpc_copy must be probably modified as well }
 { if you modify this procedure, fpc_copy must be probably modified as well }
@@ -376,7 +375,7 @@ procedure fpc_initialize_array(data,typeinfo : pointer;count : SizeInt); [public
   var
   var
     i, size : SizeInt;
     i, size : SizeInt;
   begin
   begin
-    if RTTIManagementAndSize(typeinfo, rotInitialize, size)<>manNone then
+    if RTTIManagementAndSize(typeinfo, rotInitialize, size, manBuiltin)<>manNone then
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         int_initialize(data+size*i,typeinfo);
         int_initialize(data+size*i,typeinfo);
   end;
   end;
@@ -386,7 +385,7 @@ procedure fpc_finalize_array(data,typeinfo : pointer;count : SizeInt); [Public,A
   var
   var
     i, size : SizeInt;
     i, size : SizeInt;
   begin
   begin
-    if RTTIManagementAndSize(typeinfo, rotFinalize, size)<>manNone then
+    if RTTIManagementAndSize(typeinfo, rotFinalize, size, manBuiltin)<>manNone then
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         int_finalize(data+size*i,typeinfo);
         int_finalize(data+size*i,typeinfo);
   end;
   end;
@@ -396,7 +395,7 @@ procedure fpc_addref_array(data,typeinfo: pointer; count: SizeInt); [public,alia
   var
   var
     i, size : SizeInt;
     i, size : SizeInt;
   begin
   begin
-    if RTTIManagementAndSize(typeinfo, rotAddRef, size)<>manNone then
+    if RTTIManagementAndSize(typeinfo, rotAddRef, size, manBuiltin)<>manNone then
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         int_addref(data+size*i,typeinfo);
         int_addref(data+size*i,typeinfo);
   end;
   end;
@@ -422,7 +421,7 @@ procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt);
   var
   var
     i, size: SizeInt;
     i, size: SizeInt;
   begin
   begin
-    if RTTIManagementAndSize(typeinfo, rotCopy, size)<>manNone then
+    if RTTIManagementAndSize(typeinfo, rotCopy, size, manBuiltin)<>manNone then
       for i:=0 to count-1 do
       for i:=0 to count-1 do
         fpc_Copy_internal(source+size*i, dest+size*i, typeInfo);
         fpc_Copy_internal(source+size*i, dest+size*i, typeInfo);
   end;
   end;

+ 1 - 1
rtl/inc/rttidecl.inc

@@ -157,7 +157,7 @@ type
       );
       );
   end;
   end;
 
 
-function RTTIManagementAndSize(typeInfo: Pointer; op: TRTTIRecOpType; out size: SizeInt): TRTTIManagement; forward;
+function RTTIManagementAndSize(typeInfo: Pointer; op: TRTTIRecOpType; out size: SizeInt; maxInteresting: TRTTIManagement): TRTTIManagement; forward;
 function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable; forward;
 function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable; forward;
 
 
 {$pop}
 {$pop}