* instead of a flags field generate a table with all Initialize operators of all fields (nested or not, parent class or not) for class types; objects and records don't use this (yet)

git-svn-id: trunk@39690 -
This commit is contained in:
svenbarth 2018-08-29 19:21:35 +00:00
parent 21e7ddaac7
commit a076677336
6 changed files with 137 additions and 74 deletions

View File

@ -65,7 +65,7 @@ interface
procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef); procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
procedure write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara); procedure write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara);
procedure write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym); procedure write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
procedure write_record_init_flag(tcb:ttai_typedconstbuilder;value:longword); procedure write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
public public
constructor create; constructor create;
procedure write_rtti(def:tdef;rt:trttitype); procedure write_rtti(def:tdef;rt:trttitype);
@ -175,7 +175,6 @@ implementation
TRTTIWriter TRTTIWriter
***************************************************************************} ***************************************************************************}
procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities); procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
var var
rtticount, rtticount,
@ -454,13 +453,79 @@ implementation
end; end;
procedure TRTTIWriter.write_record_init_flag(tcb:ttai_typedconstbuilder;value:longword); function compare_mop_offset_entry(item1,item2:pointer):longint;
var
entry1: pmanagementoperator_offset_entry absolute item1;
entry2: pmanagementoperator_offset_entry absolute item2;
begin begin
{ keep this in sync with the type declaration of TRecordInfoInitFlag(s) if entry1^.offset<entry2^.offset then
in both rttidecl.inc and typinfo.pp } result:=-1
if target_info.endian=endian_big then else if entry1^.offset>entry2^.offset then
value:=reverse_longword(value); result:=1
tcb.emit_ord_const(value,u32inttype); else
result:=0;
end;
procedure TRTTIWriter.write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
var
list : tfplist;
datatcb : ttai_typedconstbuilder;
tbllbl : TAsmLabel;
entry : pmanagementoperator_offset_entry;
datadef,entrydef : tdef;
i : longint;
pdef : tobjectdef;
begin
list:=tfplist.create;
tabstractrecordsymtable(def.symtable).get_managementoperator_offset_list(mop,list);
if (def.typ=objectdef) then
begin
pdef:=tobjectdef(def).childof;
while assigned(pdef) do
begin
tabstractrecordsymtable(pdef.symtable).get_managementoperator_offset_list(mop,list);
pdef:=pdef.childof;
end;
list.sort(@compare_mop_offset_entry);
end;
if list.count=0 then
tcb.emit_tai(tai_const.create_nil_dataptr,voidpointertype)
else
begin
tcb.start_internal_data_builder(current_asmdata.AsmLists[al_rtti],sec_rodata,'',datatcb,tbllbl);
datatcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
targetinfos[target_info.system]^.alignment.recordalignmin,
targetinfos[target_info.system]^.alignment.maxCrecordalign);
datatcb.emit_ord_const(list.count,u32inttype);
entrydef:=get_recorddef(itp_init_mop_offset_entry,[voidcodepointertype,sizeuinttype],defaultpacking);
for i:=0 to list.count-1 do
begin
entry:=pmanagementoperator_offset_entry(list[i]);
datatcb.maybe_begin_aggregate(entrydef);
datatcb.queue_init(voidcodepointertype);
datatcb.queue_emit_proc(entry^.pd);
datatcb.queue_init(sizeuinttype);
datatcb.queue_emit_ordconst(entry^.offset,sizeuinttype);
datatcb.maybe_end_aggregate(entrydef);
dispose(entry);
end;
datadef:=datatcb.end_anonymous_record;
tcb.finish_internal_data_builder(datatcb,tbllbl,datadef,sizeof(pint));
tcb.emit_tai(tai_const.Create_sym(tbllbl),voidpointertype);
end;
list.free;
end; end;
@ -1251,10 +1316,8 @@ implementation
{ store rtti management operators only for init table } { store rtti management operators only for init table }
if (rt=initrtti) then if (rt=initrtti) then
begin begin
riif:=0; { for now records don't have the initializer table }
if def.has_non_trivial_init_child(false) then tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
riif:=riif or riifNonTrivialChild;
write_record_init_flag(tcb,riif);
if (trecordsymtable(def.symtable).managementoperators=[]) then if (trecordsymtable(def.symtable).managementoperators=[]) then
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype) tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
else else
@ -1407,12 +1470,11 @@ implementation
{ pointer to management operators available only for initrtti } { pointer to management operators available only for initrtti }
if (rt=initrtti) then if (rt=initrtti) then
begin begin
riif:=0; { initializer table only available for classes currently }
if def.has_non_trivial_init_child(false) then if def.objecttype=odt_class then
riif:=riif or riifNonTrivialChild; write_mop_offset_table(tcb,def,mop_initialize)
if assigned(def.childof) and def.childof.has_non_trivial_init_child(true) then else
riif:=riif or riifParentHasNonTrivialChild; tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
write_record_init_flag(tcb,riif);
tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype); tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
end; end;
{ enclosing record takes care of alignment } { enclosing record takes care of alignment }

View File

@ -734,6 +734,7 @@ type
itp_rtti_set_outer, itp_rtti_set_outer,
itp_rtti_set_inner, itp_rtti_set_inner,
itp_init_record_operators, itp_init_record_operators,
itp_init_mop_offset_entry,
itp_threadvar_record, itp_threadvar_record,
itp_objc_method_list, itp_objc_method_list,
itp_objc_proto_list, itp_objc_proto_list,
@ -873,6 +874,7 @@ inherited_objectoptions : tobjectoptions = [oo_has_virtual,oo_has_private,oo_has
'$rtti_set_outer$', '$rtti_set_outer$',
'$rtti_set_inner$', '$rtti_set_inner$',
'$init_record_operators$', '$init_record_operators$',
'$init_mop_offset_entry$',
'$threadvar_record$', '$threadvar_record$',
'$objc_method_list$', '$objc_method_list$',
'$objc_proto_list$', '$objc_proto_list$',

View File

@ -382,8 +382,9 @@
{$ifndef VER3_0} {$ifndef VER3_0}
var var
vmt : PVmt; vmt : PVmt;
temp : pointer; inittable : pointer;
flags : TRecordInfoInitFlags; mopinittable : PRTTIRecordOpOffsetTable;
i : longint;
{$endif VER3_0} {$endif VER3_0}
begin begin
{ the size is saved at offset 0 } { the size is saved at offset 0 }
@ -397,23 +398,22 @@
{$ifndef VER3_0} {$ifndef VER3_0}
{ for management operators like initialize call int_initialize } { for management operators like initialize call int_initialize }
vmt := PVmt(self); vmt := PVmt(self);
while vmt<>nil do if assigned(vmt) then
begin begin
Temp:= vmt^.vInitTable; inittable:=vmt^.vInitTable;
if assigned(Temp) then if assigned(inittable) then
begin begin
flags:=RecordRTTIInitFlags(Temp); mopinittable:=RTTIRecordMopInitTable(inittable);
if riifNonTrivialChild in flags then if assigned(mopinittable) then
{ The RTTI format matches one for records, except the type begin
is tkClass. Since RecordRTTI does not check the type, {$push}
calling it yields the desired result. } { ensure that no range check errors pop up with the [0..0] array }
RecordRTTI(Instance,Temp,@int_initialize); {$R-}
{ no need to continue complex initializing up the inheritance for i:=0 to mopinittable^.Count-1 do
tree if none of the parents require it anyway } TRTTIRecVarOp(mopinittable^.Entries[i].ManagmentOperator)(PByte(Instance)+mopinittable^.Entries[i].FieldOffset);
if not (riifParentHasNonTrivialChild in flags) then {$pop}
break; end;
end; end;
vmt:= vmt^.vParent;
end; end;
{$endif VER3_0} {$endif VER3_0}

View File

@ -138,10 +138,10 @@ end;
{$ifndef VER3_0} {$ifndef VER3_0}
function RecordRTTIInitFlags(ti: Pointer): TRecordInfoInitFlags; function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable;
begin begin
ti:=aligntoqword(ti+2+PByte(ti)[1]); ti:=aligntoqword(ti+2+PByte(ti)[1]);
Result:=PRecordInfoInit(ti)^.Flags; Result:=PRecordInfoInit(ti)^.InitRecordOpTable;
end; end;
{$endif VER3_0} {$endif VER3_0}

View File

@ -92,24 +92,24 @@ type
Copy: TRTTIRecCopyOp; Copy: TRTTIRecCopyOp;
end; end;
{$ifndef VER3_0} TRTTIRecordOpOffsetEntry =
{$push} {$ifdef USE_PACKED}
packed
{$endif USE_PACKED}
record
ManagmentOperator: CodePointer;
FieldOffset: SizeUInt;
end;
{ better alignment for TRecordInfoInit } TRTTIRecordOpOffsetTable =
{ keep in sync with ncgrtti.TRTTIWriter.write_record_init_flag() and typinfo.pp } {$ifdef USE_PACKED}
{ ToDo: different values for 8/16-bit platforms? } packed
{$minenumsize 4} {$endif USE_PACKED}
{$packset 4} record
Count: LongWord;
TRecordInfoInitFlag = ( Entries: array[0..0] of TRTTIRecordOpOffsetEntry;
riifNonTrivialChild, end;
{ only relevant for classes } PRTTIRecordOpOffsetTable = ^TRTTIRecordOpOffsetTable;
riifParentHasNonTrivialChild
);
TRecordInfoInitFlags = set of TRecordInfoInitFlag;
{$pop}
{$endif}
TRecordInfoInit= TRecordInfoInit=
{$ifdef USE_PACKED} {$ifdef USE_PACKED}
@ -119,7 +119,7 @@ type
Terminator: Pointer; Terminator: Pointer;
Size: Longint; Size: Longint;
{$ifndef VER3_0} {$ifndef VER3_0}
Flags: TRecordInfoInitFlags; InitRecordOpTable: PRTTIRecordOpOffsetTable;
RecordOp: PRTTIRecordOpVMT; RecordOp: PRTTIRecordOpVMT;
{$endif VER3_0} {$endif VER3_0}
Count: Longint; Count: Longint;
@ -148,7 +148,7 @@ type
{$ifndef VER3_0} {$ifndef VER3_0}
function RecordRTTIInitFlags(ti: Pointer): TRecordInfoInitFlags; forward; function RTTIRecordMopInitTable(ti: Pointer): PRTTIRecordOpOffsetTable; forward;
{$endif VER3_0} {$endif VER3_0}
{$ifdef VER3_0} {$ifdef VER3_0}

View File

@ -410,25 +410,24 @@ unit TypInfo;
Entries: array[0..0] of TVmtMethodEntry; Entries: array[0..0] of TVmtMethodEntry;
end; end;
TRecOpOffsetEntry =
{$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{$endif FPC_REQUIRES_PROPER_ALIGNMENT}
record
ManagementOperator: CodePointer;
FieldOffset: SizeUInt;
end;
{$ifndef VER3_0} TRecOpOffsetTable =
{$push} {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
packed
{ better alignment for TRecordInfoInit } {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
{ keep in sync with ncgrtti.TRTTIWriter.write_record_init_flag() and rttidecl.inc } record
{ ToDo: different values for 8/16-bit platforms? } Count: LongWord;
{$minenumsize 4} Entries: array[0..0] of TRecOpOffsetEntry;
{$packset 4} end;
PRecOpOffsetTable = ^TRecOpOffsetTable;
TRecordInfoInitFlag = (
riifNonTrivialChild,
{ only relevant for classes }
riifParentHasNonTrivialChild
);
TRecordInfoInitFlags = set of TRecordInfoInitFlag;
{$pop}
{$endif}
PRecInitData = ^TRecInitData; PRecInitData = ^TRecInitData;
TRecInitData = TRecInitData =
@ -439,7 +438,7 @@ unit TypInfo;
Terminator: Pointer; Terminator: Pointer;
Size: Integer; Size: Integer;
{$ifndef VER3_0} {$ifndef VER3_0}
Flags: TRecordInfoInitFlags; InitOffsetOp: PRecOpOffsetTable;
ManagementOp: Pointer; ManagementOp: Pointer;
{$endif} {$endif}
ManagedFieldCount: Integer; ManagedFieldCount: Integer;