* changed initialization of records from constructing a new instance and

copying that over the old one into calling a dedicated fpcInitializeRec()
    method that initializes the required fields. The reason is that this
    initialization is performed for out-parameters, and the fpcDeepCopy()
    method (used to copy one instance over another) has an out-parameter
    -> infinite loop

git-svn-id: branches/jvmbackend@18674 -
This commit is contained in:
Jonas Maebe 2011-08-20 08:23:27 +00:00
parent b52dcd4a56
commit 5bf16214cd
4 changed files with 59 additions and 7 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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)