Ver código fonte

* 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 -

Jonas Maebe 14 anos atrás
pai
commit
5bf16214cd
4 arquivos alterados com 59 adições e 7 exclusões
  1. 15 7
      compiler/jvm/hlcgcpu.pas
  2. 9 0
      compiler/pjvm.pas
  3. 34 0
      compiler/symcreat.pas
  4. 1 0
      compiler/symdef.pas

+ 15 - 7
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);

+ 9 - 0
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;
 

+ 34 - 0
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:

+ 1 - 0
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)