mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-04 20:30:40 +02:00
* cache and reuse procvardefs internally created to get the address of a
procdef (halves the amount of memory needed to compile the googlapi package using a build unit, as done by fpmake) git-svn-id: trunk@30856 -
This commit is contained in:
parent
801fc50e86
commit
bd8079f896
@ -1268,7 +1268,7 @@ implementation
|
||||
|
||||
procedure ttai_typedconstbuilder.emit_procdef_const(pd: tprocdef);
|
||||
begin
|
||||
emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),pd.getcopyas(procvardef,pc_address_only));
|
||||
emit_tai(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0),getprocaddressprocvar(pd));
|
||||
end;
|
||||
|
||||
|
||||
|
@ -144,6 +144,7 @@ interface
|
||||
symlist : TFPObjectList;
|
||||
ptrdefs : tPtrDefHashSet; { list of pointerdefs created in this module so we can reuse them (not saved/restored) }
|
||||
arraydefs : THashSet; { list of single-element-arraydefs created in this module so we can reuse them (not saved/restored) }
|
||||
procaddrdefs : THashSet; { list of procvardefs created when getting the address of a procdef (not saved/restored) }
|
||||
{$ifdef llvm}
|
||||
llvmdefs : THashSet; { defs added for llvm-specific reasons (not saved/restored) }
|
||||
{$endif llvm}
|
||||
@ -572,6 +573,7 @@ implementation
|
||||
symlist:=TFPObjectList.Create(false);
|
||||
ptrdefs:=cPtrDefHashSet.Create;
|
||||
arraydefs:=THashSet.Create(64,true,false);
|
||||
procaddrdefs:=THashSet.Create(64,true,false);
|
||||
{$ifdef llvm}
|
||||
llvmdefs:=THashSet.Create(64,true,false);
|
||||
{$endif llvm}
|
||||
@ -689,6 +691,7 @@ implementation
|
||||
symlist.free;
|
||||
ptrdefs.free;
|
||||
arraydefs.free;
|
||||
procaddrdefs.free;
|
||||
{$ifdef llvm}
|
||||
llvmdefs.free;
|
||||
{$endif llvm}
|
||||
@ -756,6 +759,8 @@ implementation
|
||||
ptrdefs:=cPtrDefHashSet.Create;
|
||||
arraydefs.free;
|
||||
arraydefs:=THashSet.Create(64,true,false);
|
||||
procaddrdefs.free;
|
||||
procaddrdefs:=THashSet.Create(64,true,false);
|
||||
{$ifdef llvm}
|
||||
llvmdefs.free;
|
||||
llvmdefs:=THashSet.Create(64,true,false);
|
||||
|
@ -318,7 +318,7 @@ implementation
|
||||
begin
|
||||
if (pd.typ=procdef) or
|
||||
not pd.is_addressonly then
|
||||
result:=pd.getcopyas(procvardef,pc_address_only)
|
||||
result:=getprocaddressprocvar(pd)
|
||||
else
|
||||
result:=pd
|
||||
end;
|
||||
@ -419,7 +419,7 @@ implementation
|
||||
{ if this is a complex procvar, get the non-tmethod-like equivalent }
|
||||
if (pd.typ=procvardef) and
|
||||
not pd.is_addressonly then
|
||||
pd:=tprocvardef(pd.getcopyas(procvardef,pc_address_only));
|
||||
pd:=tprocvardef(getprocaddressprocvar(pd));
|
||||
{ if the function returns a function pointer type or is varargs, we
|
||||
must specify the full function signature, otherwise we can only
|
||||
specify the return type }
|
||||
|
@ -236,7 +236,7 @@ implementation
|
||||
procedure tllvmtai_typedconstbuilder.emit_tai_procvar2procdef(p: tai; pvdef: tprocvardef);
|
||||
begin
|
||||
if not pvdef.is_addressonly then
|
||||
pvdef:=tprocvardef(pvdef.getcopyas(procvardef,pc_address_only));
|
||||
pvdef:=getprocaddressprocvar(pvdef);
|
||||
emit_tai(p,pvdef);
|
||||
end;
|
||||
|
||||
@ -444,7 +444,7 @@ implementation
|
||||
the procdef }
|
||||
if (fromdef.typ=procdef) and
|
||||
(todef.typ<>procdef) then
|
||||
fromdef:=tprocdef(fromdef).getcopyas(procvardef,pc_address_only);
|
||||
fromdef:=getprocaddressprocvar(tprocdef(fromdef));
|
||||
op:=llvmconvop(fromdef,todef);
|
||||
case op of
|
||||
la_ptrtoint_to_x,
|
||||
|
@ -820,7 +820,7 @@ implementation
|
||||
of far calls where the procvardef was defined does not matter,
|
||||
even though the procvardef constructor called by getcopyas looks at
|
||||
it) }
|
||||
codeprocdef:=tabstractprocdef(procdefinition.getcopyas(procvardef,pc_address_only));
|
||||
codeprocdef:=getprocaddressprocvar(procdefinition);
|
||||
result:=hlcg.getaddressregister(current_asmdata.CurrAsmList,codeprocdef);
|
||||
{ in case we have a method pointer on a big endian target in registers,
|
||||
the method address is stored in registerhi (it's the first field
|
||||
|
@ -722,7 +722,7 @@ implementation
|
||||
hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
|
||||
tostr(i)+'_$_'+pd.mangledname);
|
||||
{ create reference }
|
||||
datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),pd.getcopyas(procvardef,pc_address_only));
|
||||
datatcb.emit_tai(Tai_const.Createname(hs,AT_FUNCTION,0),getprocaddressprocvar(pd));
|
||||
end;
|
||||
end
|
||||
else
|
||||
@ -1011,7 +1011,7 @@ implementation
|
||||
procname:='FPC_EMPTYMETHOD'
|
||||
else if not wpoinfomanager.optimized_name_for_vmt(_class,vmtpd,procname) then
|
||||
procname:=vmtpd.mangledname;
|
||||
tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),vmtpd.getcopyas(procvardef,pc_address_only));
|
||||
tcb.emit_tai(Tai_const.Createname(procname,AT_FUNCTION,0),getprocaddressprocvar(vmtpd));
|
||||
{$ifdef vtentry}
|
||||
hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(pint));
|
||||
current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
|
||||
|
@ -1128,6 +1128,8 @@ interface
|
||||
an existing one in case it exists in the current module }
|
||||
function getsingletonarraydef(def: tdef): tarraydef;
|
||||
function getarraydef(def: tdef; elecount: asizeint): tarraydef;
|
||||
{ returns a procvardef that represents the address of a procdef }
|
||||
function getprocaddressprocvar(def: tabstractprocdef): tprocvardef;
|
||||
|
||||
function getansistringcodepage:tstringencoding; inline;
|
||||
function getansistringdef:tstringdef;
|
||||
@ -7651,4 +7653,30 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function getprocaddressprocvar(def: tabstractprocdef): tprocvardef;
|
||||
var
|
||||
res: PHashSetItem;
|
||||
oldsymtablestack: tsymtablestack;
|
||||
begin
|
||||
if not assigned(current_module) then
|
||||
internalerror(2011081301);
|
||||
res:=current_module.procaddrdefs.FindOrAdd(@def,sizeof(def));
|
||||
if not assigned(res^.Data) then
|
||||
begin
|
||||
{ since these pointerdefs can be reused anywhere in the current
|
||||
unit, add them to the global/staticsymtable }
|
||||
oldsymtablestack:=symtablestack;
|
||||
{ do not simply push/pop current_module.localsymtable, because
|
||||
that can have side-effects (e.g., it removes helpers) }
|
||||
symtablestack:=nil;
|
||||
res^.Data:=def.getcopyas(procvardef,pc_address_only);
|
||||
if assigned(current_module.localsymtable) then
|
||||
current_module.localsymtable.insertdef(tdef(res^.Data))
|
||||
else
|
||||
current_module.globalsymtable.insertdef(tdef(res^.Data));
|
||||
symtablestack:=oldsymtablestack;
|
||||
end;
|
||||
result:=tprocvardef(res^.Data);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user