diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index e16562b909..7f78586aff 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -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; diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index c579208d5e..46cf0fb1ea 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -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 : diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 11cd27ac5c..093708bf55 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -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 } diff --git a/compiler/nutils.pas b/compiler/nutils.pas index 8432c0145d..b80bfff8ec 100644 --- a/compiler/nutils.pas +++ b/compiler/nutils.pas @@ -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', diff --git a/rtl/i386/i386.inc b/rtl/i386/i386.inc index 4017c3625c..e5a901cb57 100644 --- a/rtl/i386/i386.inc +++ b/rtl/i386/i386.inc @@ -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; diff --git a/rtl/inc/astrings.inc b/rtl/inc/astrings.inc index a210764ee0..7a60c56ea1 100644 --- a/rtl/inc/astrings.inc +++ b/rtl/inc/astrings.inc @@ -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} diff --git a/rtl/inc/ustrings.inc b/rtl/inc/ustrings.inc index 26be84a5e5..4bb6caf773 100644 --- a/rtl/inc/ustrings.inc +++ b/rtl/inc/ustrings.inc @@ -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 }