Faster RTTIManagementAndSize -_-.

This commit is contained in:
Rika Ichinose 2024-08-31 11:34:49 +03:00
parent 8a38755dab
commit cd2c8a6539
3 changed files with 56 additions and 57 deletions

View File

@ -182,7 +182,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
begin
newp:=AllocMem(size);
{ 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]);
end
else
@ -204,7 +204,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
if size-sizeof(tdynarray)>movsize then
begin
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);
end;
@ -238,7 +238,7 @@ procedure fpc_dynarray_setlength(var p : pointer;pti : pointer;
newp := realp;
fillchar((pointer(newp)+sizeof(tdynarray)+elesize*(newp^.high+1))^,
(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),
eletype, dims[0]-newp^.high-1);
end;

View File

@ -44,60 +44,59 @@ begin
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. }
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
ri: PRecordInfoInit;
elem, eElem: PRecordElement;
elem: PRecordElement;
newMan: TRTTIManagement;
_initrtti: pointer;
_size: SizeInt;
elemCount,sample,_size: SizeInt;
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;
{ 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
i, size : SizeInt;
begin
if RTTIManagementAndSize(typeinfo, rotInitialize, size)<>manNone then
if RTTIManagementAndSize(typeinfo, rotInitialize, size, manBuiltin)<>manNone then
for i:=0 to count-1 do
int_initialize(data+size*i,typeinfo);
end;
@ -386,7 +385,7 @@ procedure fpc_finalize_array(data,typeinfo : pointer;count : SizeInt); [Public,A
var
i, size : SizeInt;
begin
if RTTIManagementAndSize(typeinfo, rotFinalize, size)<>manNone then
if RTTIManagementAndSize(typeinfo, rotFinalize, size, manBuiltin)<>manNone then
for i:=0 to count-1 do
int_finalize(data+size*i,typeinfo);
end;
@ -396,7 +395,7 @@ procedure fpc_addref_array(data,typeinfo: pointer; count: SizeInt); [public,alia
var
i, size : SizeInt;
begin
if RTTIManagementAndSize(typeinfo, rotAddRef, size)<>manNone then
if RTTIManagementAndSize(typeinfo, rotAddRef, size, manBuiltin)<>manNone then
for i:=0 to count-1 do
int_addref(data+size*i,typeinfo);
end;
@ -422,7 +421,7 @@ procedure CopyArray(dest, source, typeInfo: Pointer; count: SizeInt);
var
i, size: SizeInt;
begin
if RTTIManagementAndSize(typeinfo, rotCopy, size)<>manNone then
if RTTIManagementAndSize(typeinfo, rotCopy, size, manBuiltin)<>manNone then
for i:=0 to count-1 do
fpc_Copy_internal(source+size*i, dest+size*i, typeInfo);
end;

View File

@ -157,7 +157,7 @@ type
);
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;
{$pop}