mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-05-30 23:02:35 +02:00
Values of managed variables are never ever used after decrementing reference on the variable, so there is no point of having a 'decrement reference' as a separate operation. We can always do 'finalize', i.e. clear the contents after decref.
* Modified fpc_ansistr_decr_ref and fpc_widestr_decr_ref so they always zero the pointer passed by reference. Other _decr_ref helpers already do it. - Removed tcg.g_decrrefcount, calling cg.g_finalize instead. - finalize_data_node and tcg.g_finalize: removed code generation for zeroing locations, because it is now done by RTL helpers. This further reduces code size. As a total result of this change and r20118, the size of Lazarus executable is reduced by about 12%. git-svn-id: trunk@20119 -
This commit is contained in:
parent
afb4992113
commit
06192a8137
@ -446,7 +446,6 @@ unit cgobj;
|
||||
procedure g_copyvariant(list : TAsmList;const source,dest : treference);
|
||||
|
||||
procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);
|
||||
procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);
|
||||
procedure g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation;
|
||||
const name: string);
|
||||
procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);
|
||||
@ -3514,72 +3513,6 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure tcg.g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);
|
||||
var
|
||||
href : treference;
|
||||
decrfunc : string;
|
||||
needrtti : boolean;
|
||||
cgpara1,cgpara2 : TCGPara;
|
||||
tempreg1,tempreg2 : TRegister;
|
||||
begin
|
||||
cgpara1.init;
|
||||
cgpara2.init;
|
||||
paramanager.getintparaloc(pocall_default,1,cgpara1);
|
||||
paramanager.getintparaloc(pocall_default,2,cgpara2);
|
||||
needrtti:=false;
|
||||
if is_interfacecom_or_dispinterface(t) then
|
||||
decrfunc:='FPC_INTF_DECR_REF'
|
||||
else if is_ansistring(t) then
|
||||
decrfunc:='FPC_ANSISTR_DECR_REF'
|
||||
else if is_widestring(t) then
|
||||
decrfunc:='FPC_WIDESTR_DECR_REF'
|
||||
else if is_unicodestring(t) then
|
||||
decrfunc:='FPC_UNICODESTR_DECR_REF'
|
||||
else if is_dynamic_array(t) then
|
||||
begin
|
||||
decrfunc:='FPC_DYNARRAY_DECR_REF';
|
||||
needrtti:=true;
|
||||
end
|
||||
else
|
||||
decrfunc:='';
|
||||
{ call the special decr function or the generic decref }
|
||||
if decrfunc<>'' then
|
||||
begin
|
||||
if needrtti then
|
||||
begin
|
||||
reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
|
||||
tempreg2:=getaddressregister(list);
|
||||
a_loadaddr_ref_reg(list,href,tempreg2);
|
||||
end;
|
||||
tempreg1:=getaddressregister(list);
|
||||
a_loadaddr_ref_reg(list,ref,tempreg1);
|
||||
if needrtti then
|
||||
a_load_reg_cgpara(list,OS_ADDR,tempreg2,cgpara2);
|
||||
a_load_reg_cgpara(list,OS_ADDR,tempreg1,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
if needrtti then
|
||||
paramanager.freecgpara(list,cgpara2);
|
||||
allocallcpuregisters(list);
|
||||
a_call_name(list,decrfunc,false);
|
||||
deallocallcpuregisters(list);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if is_open_array(t) then
|
||||
InternalError(201103053);
|
||||
reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
|
||||
a_loadaddr_ref_cgpara(list,href,cgpara2);
|
||||
a_loadaddr_ref_cgpara(list,ref,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara2);
|
||||
allocallcpuregisters(list);
|
||||
a_call_name(list,'FPC_DECREF',false);
|
||||
deallocallcpuregisters(list);
|
||||
end;
|
||||
cgpara2.done;
|
||||
cgpara1.done;
|
||||
end;
|
||||
|
||||
procedure tcg.g_array_rtti_helper(list: TAsmList; t: tdef; const ref: treference; const highloc: tlocation; const name: string);
|
||||
var
|
||||
cgpara1,cgpara2,cgpara3: TCGPara;
|
||||
@ -3671,43 +3604,45 @@ implementation
|
||||
var
|
||||
href : treference;
|
||||
cgpara1,cgpara2 : TCGPara;
|
||||
decrfunc : string;
|
||||
begin
|
||||
if is_interfacecom_or_dispinterface(t) then
|
||||
decrfunc:='FPC_INTF_DECR_REF'
|
||||
else if is_ansistring(t) then
|
||||
decrfunc:='FPC_ANSISTR_DECR_REF'
|
||||
else if is_widestring(t) then
|
||||
decrfunc:='FPC_WIDESTR_DECR_REF'
|
||||
else if is_unicodestring(t) then
|
||||
decrfunc:='FPC_UNICODESTR_DECR_REF'
|
||||
else if t.typ=variantdef then
|
||||
decrfunc:='FPC_VARIANT_CLEAR'
|
||||
else
|
||||
begin
|
||||
cgpara1.init;
|
||||
cgpara2.init;
|
||||
if is_open_array(t) then
|
||||
InternalError(201103051);
|
||||
paramanager.getintparaloc(pocall_default,1,cgpara1);
|
||||
paramanager.getintparaloc(pocall_default,2,cgpara2);
|
||||
reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
|
||||
a_loadaddr_ref_cgpara(list,href,cgpara2);
|
||||
a_loadaddr_ref_cgpara(list,ref,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara2);
|
||||
if is_dynamic_array(t) then
|
||||
g_call(list,'FPC_DYNARRAY_CLEAR')
|
||||
else
|
||||
g_call(list,'FPC_FINALIZE');
|
||||
cgpara1.done;
|
||||
cgpara2.done;
|
||||
exit;
|
||||
end;
|
||||
cgpara1.init;
|
||||
cgpara2.init;
|
||||
if is_ansistring(t) or
|
||||
is_widestring(t) or
|
||||
is_unicodestring(t) or
|
||||
is_interfacecom_or_dispinterface(t) then
|
||||
begin
|
||||
g_decrrefcount(list,t,ref);
|
||||
a_load_const_ref(list,OS_ADDR,0,ref);
|
||||
end
|
||||
else if t.typ=variantdef then
|
||||
begin
|
||||
paramanager.getintparaloc(pocall_default,1,cgpara1);
|
||||
a_loadaddr_ref_cgpara(list,ref,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
allocallcpuregisters(list);
|
||||
a_call_name(list,'FPC_VARIANT_CLEAR',false);
|
||||
deallocallcpuregisters(list);
|
||||
end
|
||||
else
|
||||
begin
|
||||
if is_open_array(t) then
|
||||
InternalError(201103051);
|
||||
paramanager.getintparaloc(pocall_default,1,cgpara1);
|
||||
paramanager.getintparaloc(pocall_default,2,cgpara2);
|
||||
reference_reset_symbol(href,RTTIWriter.get_rtti_label(t,initrtti),0,sizeof(pint));
|
||||
a_loadaddr_ref_cgpara(list,href,cgpara2);
|
||||
a_loadaddr_ref_cgpara(list,ref,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara2);
|
||||
allocallcpuregisters(list);
|
||||
a_call_name(list,'FPC_FINALIZE',false);
|
||||
deallocallcpuregisters(list);
|
||||
end;
|
||||
paramanager.getintparaloc(pocall_default,1,cgpara1);
|
||||
a_loadaddr_ref_cgpara(list,ref,cgpara1);
|
||||
paramanager.freecgpara(list,cgpara1);
|
||||
g_call(list,decrfunc);
|
||||
cgpara1.done;
|
||||
cgpara2.done;
|
||||
end;
|
||||
|
||||
|
||||
|
@ -177,15 +177,11 @@ implementation
|
||||
InternalError(201103063);
|
||||
secondpass(third);
|
||||
cg.g_array_rtti_helper(current_asmdata.CurrAsmList,tarraydef(resultdef).elementdef,
|
||||
href,third.location,'FPC_DECREF_ARRAY');
|
||||
href,third.location,'FPC_FINALIZE_ARRAY');
|
||||
end;
|
||||
end
|
||||
else if (resultdef.typ=formaldef) then
|
||||
{ stuff being passed to formal parameter has to be completely cleaned,
|
||||
because it cannot be initialized at callee side (bug #20962) }
|
||||
cg.g_finalize(current_asmdata.CurrAsmList,left.resultdef,href)
|
||||
else
|
||||
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
||||
cg.g_finalize(current_asmdata.CurrAsmList,left.resultdef,href)
|
||||
end;
|
||||
|
||||
paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,not followed_by_stack_tainting_call_cached,tempcgpara);
|
||||
@ -397,7 +393,7 @@ implementation
|
||||
function since this is code is only executed after the function call has returned }
|
||||
if is_managed_type(funcretnode.resultdef) and
|
||||
(funcretnode.nodetype<>temprefn) then
|
||||
cg.g_decrrefcount(current_asmdata.CurrAsmList,funcretnode.resultdef,funcretnode.location.reference);
|
||||
cg.g_finalize(current_asmdata.CurrAsmList,funcretnode.resultdef,funcretnode.location.reference);
|
||||
|
||||
case location.loc of
|
||||
LOC_REGISTER :
|
||||
|
@ -1712,10 +1712,10 @@ implementation
|
||||
eldef:=tarraydef(tparavarsym(p).vardef).elementdef;
|
||||
if not assigned(hsym) then
|
||||
internalerror(201003032);
|
||||
cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_DECREF_ARRAY');
|
||||
cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_FINALIZE_ARRAY');
|
||||
end
|
||||
else
|
||||
cg.g_decrrefcount(list,tparavarsym(p).vardef,href);
|
||||
cg.g_finalize(list,tparavarsym(p).vardef,href);
|
||||
end;
|
||||
end;
|
||||
{ open arrays can contain elements requiring init/final code, so the else has been removed here }
|
||||
|
@ -626,57 +626,27 @@ implementation
|
||||
function finalize_data_node(p:tnode):tnode;
|
||||
var
|
||||
newstatement : tstatementnode;
|
||||
hs : string;
|
||||
begin
|
||||
if not assigned(p.resultdef) then
|
||||
typecheckpass(p);
|
||||
{ 'decr_ref' suffix is somewhat misleading, all these helpers
|
||||
set the passed pointer to nil now }
|
||||
if is_ansistring(p.resultdef) then
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_ansistr_decr_ref',
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(p,voidpointertype),
|
||||
nil)));
|
||||
addstatement(newstatement,cassignmentnode.create(
|
||||
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
|
||||
cnilnode.create
|
||||
));
|
||||
end
|
||||
hs:='fpc_ansistr_decr_ref'
|
||||
else if is_widestring(p.resultdef) then
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_widestr_decr_ref',
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(p,voidpointertype),
|
||||
nil)));
|
||||
addstatement(newstatement,cassignmentnode.create(
|
||||
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
|
||||
cnilnode.create
|
||||
));
|
||||
end
|
||||
hs:='fpc_widestr_decr_ref'
|
||||
else if is_unicodestring(p.resultdef) then
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_unicodestr_decr_ref',
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(p,voidpointertype),
|
||||
nil)));
|
||||
addstatement(newstatement,cassignmentnode.create(
|
||||
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
|
||||
cnilnode.create
|
||||
));
|
||||
end
|
||||
hs:='fpc_unicodestr_decr_ref'
|
||||
else if is_interfacecom_or_dispinterface(p.resultdef) then
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_intf_decr_ref',
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(p,voidpointertype),
|
||||
nil)));
|
||||
addstatement(newstatement,cassignmentnode.create(
|
||||
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
|
||||
cnilnode.create
|
||||
));
|
||||
end
|
||||
hs:='fpc_intf_decr_ref'
|
||||
else
|
||||
hs:='';
|
||||
if hs<>'' then
|
||||
result:=ccallnode.createintern(hs,
|
||||
ccallparanode.create(
|
||||
ctypeconvnode.create_internal(p,voidpointertype),
|
||||
nil))
|
||||
else if p.resultdef.typ=variantdef then
|
||||
begin
|
||||
result:=ccallnode.createintern('fpc_variant_clear',
|
||||
|
@ -1333,23 +1333,14 @@ function fpc_freemem_x(p:pointer):ptrint; [external name 'FPC_FREEMEM_X'];
|
||||
|
||||
Procedure fpc_AnsiStr_Decr_Ref (Var S : Pointer); [Public,Alias:'FPC_ANSISTR_DECR_REF']; compilerproc; nostackframe; assembler;
|
||||
asm
|
||||
cmpl $0,(%eax)
|
||||
jne .Ldecr_ref_continue
|
||||
ret
|
||||
.Ldecr_ref_continue:
|
||||
// Temps allocated between ebp-24 and ebp+0
|
||||
subl $4,%esp
|
||||
// Var S located in register
|
||||
// Var l located in register
|
||||
movl %eax,(%esp)
|
||||
// [101] l:=@PAnsiRec(S-FirstOff)^.Ref;
|
||||
movl (%eax),%edx
|
||||
subl $8,%edx
|
||||
// [102] If l^<0 then exit;
|
||||
cmpl $0,(%edx)
|
||||
cmpl $0,(%eax)
|
||||
je .Lquit
|
||||
pushl %esi
|
||||
movl (%eax),%esi
|
||||
subl $12,%esi // points to start of allocation
|
||||
movl $0,(%eax) // s:=nil
|
||||
cmpl $0,4(%esi) // exit if refcount<0
|
||||
jl .Lj3596
|
||||
.Lj3603:
|
||||
// [104] If declocked(l^) then
|
||||
{$ifdef FPC_PIC}
|
||||
pushl %ebx
|
||||
call fpc_geteipasebx
|
||||
@ -1362,27 +1353,20 @@ asm
|
||||
cmpl $0,ismultithread
|
||||
{$endif FPC_PIC}
|
||||
jne .Lj3610
|
||||
decl (%edx)
|
||||
decl 4(%esi)
|
||||
je .Lj3620
|
||||
addl $4,%esp
|
||||
ret
|
||||
jmp .Lj3596
|
||||
.Lj3610:
|
||||
movl %edx,%eax
|
||||
leal 4(%esi),%eax
|
||||
call cpudeclocked
|
||||
testb %al,%al
|
||||
je .Lj3605
|
||||
je .Lj3596
|
||||
.Lj3620:
|
||||
movl (%esp),%eax
|
||||
movl (%eax),%eax
|
||||
subl $12,%eax
|
||||
movl %esi,%eax
|
||||
call FPC_FREEMEM_X
|
||||
movl (%esp),%eax
|
||||
movl $0,(%eax)
|
||||
.Lj3618:
|
||||
.Lj3605:
|
||||
.Lj3596:
|
||||
// [107] end;
|
||||
addl $4,%esp
|
||||
popl %esi
|
||||
.Lquit:
|
||||
end;
|
||||
|
||||
function fpc_truely_ansistr_unique(Var S : Pointer): Pointer; forward;
|
||||
|
@ -92,13 +92,11 @@ Begin
|
||||
exit;
|
||||
{ check for constant strings ...}
|
||||
p:=PAnsiRec(S-AnsiFirstOff);
|
||||
s:=nil;
|
||||
If p^.ref<0 then exit;
|
||||
{ declocked does a MT safe dec and returns true, if the counter is 0 }
|
||||
If declocked(p^.ref) then
|
||||
begin
|
||||
FreeMem(p);
|
||||
s:=nil;
|
||||
end;
|
||||
FreeMem(p);
|
||||
end;
|
||||
|
||||
{$endif FPC_SYSTEM_HAS_ANSISTR_DECR_REF}
|
||||
|
@ -216,15 +216,13 @@ Begin
|
||||
exit;
|
||||
{ check for constant strings ...}
|
||||
p:=PUnicodeRec(S-UnicodeFirstOff);
|
||||
S:=nil;
|
||||
if p^.Ref<0 then
|
||||
exit;
|
||||
|
||||
{ declocked does a MT safe dec and returns true, if the counter is 0 }
|
||||
if declocked(p^.Ref) then
|
||||
begin
|
||||
FreeMem(p);
|
||||
S:=nil;
|
||||
end;
|
||||
FreeMem(p);
|
||||
end;
|
||||
|
||||
{ alias for internal use }
|
||||
|
Loading…
Reference in New Issue
Block a user