diff --git a/compiler/jvm/hlcgcpu.pas b/compiler/jvm/hlcgcpu.pas index 31daffb484..65247f6b2c 100644 --- a/compiler/jvm/hlcgcpu.pas +++ b/compiler/jvm/hlcgcpu.pas @@ -1449,7 +1449,8 @@ implementation procedure thlcgjvm.g_initialize(list: TAsmList; t: tdef; const ref: treference); var dummyloc: tlocation; - recref: treference; + sym: tsym; + pd: tprocdef; begin if (t.typ=arraydef) and not is_dynamic_array(t) then @@ -1459,12 +1460,19 @@ implementation end else if is_record(t) then begin - { create a new, empty record and replace the contents of the old one - with those of the new one (in the future we can generate a dedicate - initialization helper) } - tg.gethltemp(list,t,t.size,tt_persistent,recref); - g_concatcopy(list,t,recref,ref); - tg.ungettemp(list,recref); + { call the fpcInitializeRec method } + sym:=tsym(trecorddef(t).symtable.find('FPCINITIALIZEREC')); + if assigned(sym) and + (sym.typ=procsym) then + begin + if tprocsym(sym).procdeflist.Count<>1 then + internalerror(2011071713); + pd:=tprocdef(tprocsym(sym).procdeflist[0]); + end; + a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false)); + a_call_name(list,pd,pd.mangledname,false); + { parameter removed, no result } + decstack(list,1); end else a_load_const_ref(list,t,0,ref); diff --git a/compiler/pjvm.pas b/compiler/pjvm.pas index 2a06ce53ab..f28560c3a8 100644 --- a/compiler/pjvm.pas +++ b/compiler/pjvm.pas @@ -195,6 +195,15 @@ implementation pd.synthetickind:=tsk_record_deepcopy else internalerror(2011032807); + if def.needs_inittable then + begin + { 'var' instead of 'out' parameter, because 'out' would trigger + calling the initialize method recursively } + if str_parse_method_dec('procedure fpcInitializeRec;',potype_procedure,false,def,pd) then + pd.synthetickind:=tsk_record_initialize + else + internalerror(2011071711); + end; restore_scanner(sstate); end; diff --git a/compiler/symcreat.pas b/compiler/symcreat.pas index b0ef0876e1..10f4acf50f 100644 --- a/compiler/symcreat.pas +++ b/compiler/symcreat.pas @@ -375,6 +375,38 @@ implementation end; + procedure implement_record_initialize(pd: tprocdef); + var + struct: tabstractrecorddef; + str: ansistring; + i: longint; + sym: tsym; + fsym: tfieldvarsym; + begin + if not(pd.struct.typ in [recorddef,objectdef]) then + internalerror(2011071710); + struct:=pd.struct; + { anonymous record types must get an artificial name, so we can generate + a typecast at the scanner level } + if (struct.typ=recorddef) and + not assigned(struct.typesym) then + internalerror(2011032811); + { walk over all fields that need initialization } + str:='begin '; + for i:=0 to struct.symtable.symlist.count-1 do + begin + sym:=tsym(struct.symtable.symlist[i]); + if (sym.typ=fieldvarsym) then + begin + fsym:=tfieldvarsym(sym); + if fsym.vardef.needs_inittable then + str:=str+'system.initialize(&'+fsym.realname+');'; + end; + end; + str:=str+'end;'; + str_parse_method_impl(str,pd,false); + end; + procedure implement_empty(pd: tprocdef); var str: ansistring; @@ -618,6 +650,8 @@ implementation implement_jvm_clone(pd); tsk_record_deepcopy: implement_record_deepcopy(pd); + tsk_record_initialize: + implement_record_initialize(pd); tsk_empty, { special handling for this one is done in tnodeutils.wrap_proc_body } tsk_tcinit: diff --git a/compiler/symdef.pas b/compiler/symdef.pas index e6c9058e27..859da89234 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -499,6 +499,7 @@ interface tsk_anon_inherited, // anonymous inherited call tsk_jvm_clone, // Java-style clone method tsk_record_deepcopy, // deepcopy for records field by field + tsk_record_initialize, // initialize for records field by field (explicit rather than via rtti) tsk_empty, // an empty routine tsk_tcinit, // initialisation of typed constants tsk_callthrough, // call through to another routine with the same parameters/return type (its def is stored in the skpara field)