* support marking defs created via the getreusable*() class methods as

"don't free even if not registered"; use for defs that may not be written
    to a ppu file, but that must nevertheless survive the compilation of the
    current module
  * mark all defs created for para locations as "don't free even if not
    registered", because we don't discard and recalculate all para locations
    after a module has been compiled (since that's not needed)
   o solves issues if the paralocations for a routine in the interface of
     unit A are calculated while the implementation of unit B gets
     compiled, and a new reusable type is allocated at that point which
     is not used anywhere else (after r32160)

git-svn-id: trunk@32235 -
This commit is contained in:
Jonas Maebe 2015-11-04 20:46:18 +00:00
parent d5aa498cf5
commit fa3b0ca312
18 changed files with 87 additions and 39 deletions

View File

@ -318,7 +318,7 @@ unit cpupara;
hp.paraloc[side].size:=OS_ADDR;
hp.paraloc[side].alignment:=voidpointertype.alignment;
hp.paraloc[side].intsize:=voidpointertype.size;
hp.paraloc[side].def:=cpointerdef.getreusable(hp.vardef);
hp.paraloc[side].def:=cpointerdef.getreusable_no_free(hp.vardef);
with hp.paraloc[side].add_location^ do
begin
size:=OS_ADDR;
@ -397,7 +397,7 @@ unit cpupara;
if push_addr_param(varspez,paradef,p.proccalloption) then
begin
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
loc:=LOC_REGISTER;
paracgsize:=OS_ADDR;
paralen:=tcgsize2size[OS_ADDR];

View File

@ -92,7 +92,7 @@ unit cpupara;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=cpointerdef.getreusable(pdef);
pdef:=cpointerdef.getreusable_no_free(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
@ -378,7 +378,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@ -472,7 +472,7 @@ unit cpupara;
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -546,7 +546,7 @@ unit cpupara;
{ LOC_REFERENCE always contains everything that's left }
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=int_cgsize(paralen);
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
if (side=callerside) then
paraloc^.reference.index:=NR_STACK_POINTER_REG;
paraloc^.reference.offset:=stack_offset;
@ -559,7 +559,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
paraloc^.def:=cpointerdef.getreusable(paradef);
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
assignintreg
end
else

View File

@ -255,7 +255,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
loc:=LOC_REGISTER;
paracgsize:=OS_ADDR;
paralen:=tcgsize2size[OS_ADDR];
@ -353,7 +353,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paraloc^.size:=OS_ADDR;
paraloc^.def:=cpointerdef.getreusable(paradef);
paraloc^.def:=cpointerdef.getreusable_no_free(paradef);
assignintreg
end
else

View File

@ -422,7 +422,7 @@ unit cpupara;
begin
paralen:=sizeof(aint);
paracgsize:=OS_ADDR;
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
end
else
begin
@ -574,7 +574,7 @@ unit cpupara;
begin
paralen:=sizeof(aint);
paracgsize:=OS_ADDR;
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
end
else
begin

View File

@ -236,7 +236,7 @@ unit cpupara;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=cpointerdef.getreusable(pdef);
pdef:=cpointerdef.getreusable_no_free(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
@ -442,7 +442,7 @@ unit cpupara;
begin
paralen:=voidpointertype.size;
paracgsize:=int_cgsize(voidpointertype.size);
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
end
else
begin
@ -602,7 +602,7 @@ unit cpupara;
begin
paralen:=voidpointertype.size;
paracgsize:=int_cgsize(voidpointertype.size);
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
end
else
begin

View File

@ -160,7 +160,7 @@ implementation
else if jvmimplicitpointertype(result.def) then
begin
retcgsize:=OS_ADDR;
result.def:=cpointerdef.getreusable(result.def);
result.def:=cpointerdef.getreusable_no_free(result.def);
end
else
begin
@ -237,7 +237,7 @@ implementation
else if jvmimplicitpointertype(hp.vardef) then
begin
paracgsize:=OS_ADDR;
paradef:=cpointerdef.getreusable(hp.vardef);
paradef:=cpointerdef.getreusable_no_free(hp.vardef);
end
else
begin

View File

@ -140,7 +140,7 @@ unit llvmpara;
a pointer to the value that it should place on the stack (or
passed in registers, in some cases) }
paraloc^.llvmvalueloc:=false;
paraloc^.def:=cpointerdef.getreusable(paraloc^.def);
paraloc^.def:=cpointerdef.getreusable_no_free(paraloc^.def);
paraloc^.size:=def_cgsize(paraloc^.def);
paraloc^.loc:=LOC_REGISTER;
paraloc^.register:=hlcg.getaddressregister(list,paraloc^.def);

View File

@ -275,7 +275,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
end

View File

@ -273,7 +273,7 @@ implementation
begin
paracgsize := OS_ADDR;
paralen := tcgsize2size[paracgsize];
paradef := cpointerdef.getreusable(paradef);
paradef := cpointerdef.getreusable_no_free(paradef);
end
else
begin

View File

@ -560,7 +560,7 @@ implementation
retloc.def:=tdef(p.owner.defowner);
if not (is_implicit_pointer_object_type(retloc.def) or
(retloc.def.typ<>objectdef)) then
retloc.def:=cpointerdef.getreusable(retloc.def);
retloc.def:=cpointerdef.getreusable_no_free(retloc.def);
end;
retcgsize:=def_cgsize(retloc.def);
retloc.intsize:=retloc.def.size;
@ -568,7 +568,7 @@ implementation
{ Return is passed as var parameter }
if ret_in_param(retloc.def,p) then
begin
retloc.def:=cpointerdef.getreusable(retloc.def);
retloc.def:=cpointerdef.getreusable_no_free(retloc.def);
paraloc:=retloc.add_location;
paraloc^.loc:=LOC_REFERENCE;
paraloc^.size:=retcgsize;
@ -621,7 +621,7 @@ implementation
else if restlen in [1,2,4,8] then
result:=cgsize_orddef(int_cgsize(restlen))
else
result:=carraydef.getreusable(u8inttype,restlen);
result:=carraydef.getreusable_no_free(u8inttype,restlen);
end;

View File

@ -568,7 +568,8 @@ implementation
begin
def:=tdef(current_module.localsymtable.deflist[i]);
{ this also frees def, as the defs are owned by the symtable }
if not def.is_registered then
if not def.is_registered and
not(df_not_registered_no_free in def.defoptions) then
current_module.localsymtable.deletedef(def);
end;
end;

View File

@ -87,7 +87,7 @@ unit cpupara;
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=cpointerdef.getreusable(pdef);
pdef:=cpointerdef.getreusable_no_free(pdef);
cgpara.reset;
cgpara.size:=def_cgsize(pdef);
cgpara.intsize:=tcgsize2size[cgpara.size];
@ -389,7 +389,7 @@ unit cpupara;
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
loc:=LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];
@ -570,7 +570,7 @@ unit cpupara;
if paraloc^.size<>OS_NO then
paraloc^.def:=cgsize_orddef(paraloc^.size)
else
paraloc^.def:=carraydef.getreusable(u8inttype,paralen);
paraloc^.def:=carraydef.getreusable_no_free(u8inttype,paralen);
end;
else
internalerror(2006011101);

View File

@ -88,7 +88,7 @@ begin
psym:=tparavarsym(pd.paras[nr-1]);
pdef:=psym.vardef;
if push_addr_param(psym.varspez,pdef,pd.proccalloption) then
pdef:=cpointerdef.getreusable(pdef);
pdef:=cpointerdef.getreusable_no_free(pdef);
cgpara.reset;
cgpara.size := def_cgsize(pdef);
cgpara.intsize := tcgsize2size[cgpara.size];
@ -418,7 +418,7 @@ begin
next 8 byte boundary? }
paraaligned:=false;
if push_addr_param(varspez, paradef, p.proccalloption) then begin
paradef := cpointerdef.getreusable(paradef);
paradef := cpointerdef.getreusable_no_free(paradef);
loc := LOC_REGISTER;
paracgsize := OS_ADDR;
paralen := tcgsize2size[OS_ADDR];

View File

@ -196,7 +196,7 @@ implementation
if push_addr_param(hp.varspez,paradef,p.proccalloption) then
begin
paracgsize:=OS_ADDR;
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
end
else
begin

View File

@ -212,7 +212,13 @@ type
{ def has been copied from another def so symtable is not owned }
df_copied_def,
{ def was created as a generic constraint and thus is only "shallow" }
df_genconstraint
df_genconstraint,
{ don't free def after finishing the implementation section even if it
wasn't written to the ppu, as this def may still be referred (e.g. because
it was used to set the type of a paraloc, since paralocs are reused
across units) -- never stored to ppu, because in that case the def would
be registered }
df_not_registered_no_free
);
tdefoptions=set of tdefoption;

View File

@ -225,6 +225,11 @@ interface
{ returns a pointerdef for def, reusing an existing one in case it
exists in the current module }
class function getreusable(def: tdef): tpointerdef; virtual;
{ same as above, but in case the def must never be freed after the
current module has been compiled -- even if the def was not written
to the ppu file (for defs in para locations, as we don't reset them
so we don't have to recalculate them all the time) }
class function getreusable_no_free(def: tdef): tpointerdef;
function size:asizeint;override;
function getcopy:tstoreddef;override;
constructor ppuload(ppufile:tcompilerppufile);
@ -496,6 +501,11 @@ interface
constructor create_from_pointer(def:tpointerdef);virtual;
constructor create(l,h:asizeint;def:tdef);virtual;
class function getreusable(def: tdef; elems: asizeint): tarraydef; virtual;
{ same as above, but in case the def must never be freed after the
current module has been compiled -- even if the def was not written
to the ppu file (for defs in para locations, as we don't reset them
so we don't have to recalculate them all the time) }
class function getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
constructor ppuload(ppufile:tcompilerppufile);
destructor destroy; override;
function getcopy : tstoreddef;override;
@ -616,6 +626,11 @@ interface
constructor create(level:byte);virtual;
{ returns a procvardef that represents the address of a proc(var)def }
class function getreusableprocaddr(def: tabstractprocdef): tprocvardef; virtual;
{ same as above, but in case the def must never be freed after the
current module has been compiled -- even if the def was not written
to the ppu file (for defs in para locations, as we don't reset them
so we don't have to recalculate them all the time) }
class function getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
constructor ppuload(ppufile:tcompilerppufile);
function getcopy : tstoreddef;override;
{ do not override this routine in platform-specific subclasses,
@ -2154,6 +2169,7 @@ implementation
{ Register in current_module }
if assigned(current_module) then
begin
exclude(defoptions,df_not_registered_no_free);
if defid<defid_not_registered then
defid:=deflist_index
else
@ -3224,6 +3240,14 @@ implementation
end;
class function tpointerdef.getreusable_no_free(def: tdef): tpointerdef;
begin
result:=getreusable(def);
if not result.is_registered then
include(result.defoptions,df_not_registered_no_free);
end;
function tpointerdef.size: asizeint;
begin
result:=sizeof(pint);
@ -3540,6 +3564,13 @@ implementation
result:=tarraydef(res^.Data);
end;
class function tarraydef.getreusable_no_free(def: tdef; elems: asizeint): tarraydef;
begin
result:=getreusable(def,elems);
if not result.is_registered then
include(result.defoptions,df_not_registered_no_free);
end;
destructor tarraydef.destroy;
begin
@ -6086,6 +6117,14 @@ implementation
end;
class function tprocvardef.getreusableprocaddr_no_free(def: tabstractprocdef): tprocvardef;
begin
result:=getreusableprocaddr(def);
if not result.is_registered then
include(result.defoptions,df_not_registered_no_free);
end;
constructor tprocvardef.ppuload(ppufile:tcompilerppufile);
begin
inherited ppuload(procvardef,ppufile);

View File

@ -1420,7 +1420,9 @@ const
(mask:df_generic; str:'Generic'),
(mask:df_specialization; str:'Specialization'),
(mask:df_copied_def; str:'Copied Typedef'),
(mask:df_genconstraint; str:'Generic Constraint')
(mask:df_genconstraint; str:'Generic Constraint'),
{ this should never happen for defs stored to a ppu file }
(mask:df_not_registered_no_free; str:'Unregistered/No free (invalid)')
);
defstate : array[1..ord(high(tdefstate))] of tdefstateinfo=(
(mask:ds_vmt_written; str:'VMT Written'),

View File

@ -288,7 +288,7 @@ unit cpupara;
else
result:=class2;
result.typ:=X86_64_SSE_CLASS;
result.def:=carraydef.getreusable(s32floattype,2)
result.def:=carraydef.getreusable_no_free(s32floattype,2)
end;
@ -401,7 +401,7 @@ unit cpupara;
(classes[i-1].typ<>X86_64_SSEUP_CLASS) then
begin
classes[i].typ:=X86_64_SSE_CLASS;
classes[i].def:=carraydef.getreusable(s32floattype,2);
classes[i].def:=carraydef.getreusable_no_free(s32floattype,2);
end;
(* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
@ -443,7 +443,7 @@ unit cpupara;
X86_64_SSESF_CLASS:
begin
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=carraydef.getreusable(s32floattype,2);
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
end;
end;
{ 2) the second part is 32 bit, but the total size is > 12 bytes }
@ -457,7 +457,7 @@ unit cpupara;
X86_64_SSESF_CLASS:
begin
classes[1].typ:=X86_64_SSE_CLASS;
classes[1].def:=carraydef.getreusable(s32floattype,2);
classes[1].def:=carraydef.getreusable_no_free(s32floattype,2);
end;
end;
@ -613,7 +613,7 @@ unit cpupara;
{ if we have e.g. a record with two successive "single"
fields, we need a 64 bit rather than a 32 bit load }
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=carraydef.getreusable(s32floattype,2);
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
end;
result:=1;
end;
@ -639,9 +639,9 @@ unit cpupara;
s128real:
begin
classes[0].typ:=X86_64_SSE_CLASS;
classes[0].def:=carraydef.getreusable(s32floattype,2);
classes[0].def:=carraydef.getreusable_no_free(s32floattype,2);
classes[1].typ:=X86_64_SSEUP_CLASS;
classes[1].def:=carraydef.getreusable(s32floattype,2);
classes[1].def:=carraydef.getreusable_no_free(s32floattype,2);
result:=2;
end;
else
@ -1102,7 +1102,7 @@ unit cpupara;
loc[2].typ:=X86_64_NO_CLASS;
paracgsize:=OS_ADDR;
paralen:=sizeof(pint);
paradef:=cpointerdef.getreusable(paradef);
paradef:=cpointerdef.getreusable_no_free(paradef);
loc[1].def:=paradef;
end
else