Просмотр исходного кода

+ support for regular arrays and open arrays
o support for copying value parameters at the callee side if they were
passed by reference in hlcg
o JVM g_concatcopy() implementation for arrays
o moved code to get length of an array from njvminl to hlcgcpu so it can
be reused elsewhere as well
o export array copy helpers from system unit for use when assigning one
array to another
o some generic support for types that are normally not implicit pointers,
but which are for the JVM target (such as normal arrays)
* handle assigning nil to a dynamic array by generating a setlength(x,0)
node instead of by hardcoding a call to fpc_dynarray_clear, so
target-specific code can handle it if required
* hook up gethltemp() for JVM ttgjvm so array temps are properly
allocated

git-svn-id: branches/jvmbackend@18388 -

Jonas Maebe 14 лет назад
Родитель
Сommit
2c313e397e

+ 1 - 0
.gitattributes

@@ -225,6 +225,7 @@ compiler/jvm/njvmcnv.pas svneol=native#text/plain
 compiler/jvm/njvmcon.pas svneol=native#text/plain
 compiler/jvm/njvmcon.pas svneol=native#text/plain
 compiler/jvm/njvmflw.pas svneol=native#text/plain
 compiler/jvm/njvmflw.pas svneol=native#text/plain
 compiler/jvm/njvminl.pas svneol=native#text/plain
 compiler/jvm/njvminl.pas svneol=native#text/plain
+compiler/jvm/njvmld.pas svneol=native#text/plain
 compiler/jvm/njvmmat.pas svneol=native#text/plain
 compiler/jvm/njvmmat.pas svneol=native#text/plain
 compiler/jvm/njvmmem.pas svneol=native#text/plain
 compiler/jvm/njvmmem.pas svneol=native#text/plain
 compiler/jvm/njvmutil.pas svneol=native#text/plain
 compiler/jvm/njvmutil.pas svneol=native#text/plain

+ 24 - 4
compiler/hlcg2ll.pas

@@ -328,8 +328,8 @@ unit hlcg2ll;
              @param(dest Destination reference of copy)
              @param(dest Destination reference of copy)
 
 
           }
           }
-//          procedure g_copyshortstring(list : TAsmList;const source,dest : treference;len:byte);
-//          procedure g_copyvariant(list : TAsmList;const source,dest : treference);
+          procedure g_copyshortstring(list : TAsmList;const source,dest : treference;strdef:tstringdef);override;
+          procedure g_copyvariant(list : TAsmList;const source,dest : treference;vardef:tvariantdef);override;
 
 
           procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
           procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
           procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
           procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
@@ -349,8 +349,8 @@ unit hlcg2ll;
           procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); override;
           procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); override;
           procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation);override;
           procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation);override;
 
 
-//          procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);override;
-//          procedure g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);override;
+          procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;arrdef: tarraydef;destreg:tregister);override;
+          procedure g_releasevaluepara_openarray(list : TAsmList;arrdef: tarraydef;const l:tlocation);override;
 
 
           {# Emits instructions when compilation is done in profile
           {# Emits instructions when compilation is done in profile
              mode (this is set as a command line option). The default
              mode (this is set as a command line option). The default
@@ -1063,6 +1063,16 @@ procedure thlcg2ll.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; co
       cg.g_concatcopy_unaligned(list,source,dest,size.size);
       cg.g_concatcopy_unaligned(list,source,dest,size.size);
     end;
     end;
 
 
+  procedure thlcg2ll.g_copyshortstring(list: TAsmList; const source, dest: treference; strdef: tstringdef);
+    begin
+      cg.g_copyshortstring(list,source,dest,strdef.len);
+    end;
+
+  procedure thlcg2ll.g_copyvariant(list: TAsmList; const source, dest: treference; vardef: tvariantdef);
+    begin
+      cg.g_copyvariant(list,source,dest);
+    end;
+
   procedure thlcg2ll.g_incrrefcount(list: TAsmList; t: tdef; const ref: treference);
   procedure thlcg2ll.g_incrrefcount(list: TAsmList; t: tdef; const ref: treference);
     begin
     begin
       cg.g_incrrefcount(list,t,ref);
       cg.g_incrrefcount(list,t,ref);
@@ -1098,6 +1108,16 @@ procedure thlcg2ll.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; co
       cg.g_overflowCheck_loc(list,loc,def,ovloc);
       cg.g_overflowCheck_loc(list,loc,def,ovloc);
     end;
     end;
 
 
+  procedure thlcg2ll.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
+    begin
+      cg.g_copyvaluepara_openarray(list,ref,lenloc,arrdef.elesize,destreg);
+    end;
+
+  procedure thlcg2ll.g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation);
+    begin
+      cg.g_releasevaluepara_openarray(list,l);
+    end;
+
   procedure thlcg2ll.g_profilecode(list: TAsmList);
   procedure thlcg2ll.g_profilecode(list: TAsmList);
     begin
     begin
       cg.g_profilecode(list);
       cg.g_profilecode(list);

+ 122 - 9
compiler/hlcgobj.pas

@@ -354,8 +354,8 @@ unit hlcgobj;
              @param(dest Destination reference of copy)
              @param(dest Destination reference of copy)
 
 
           }
           }
-//          procedure g_copyshortstring(list : TAsmList;const source,dest : treference;len:byte);
-//          procedure g_copyvariant(list : TAsmList;const source,dest : treference);
+          procedure g_copyshortstring(list : TAsmList;const source,dest : treference;strdef:tstringdef);virtual;abstract;
+          procedure g_copyvariant(list : TAsmList;const source,dest : treference;vardef:tvariantdef);virtual;abstract;
 
 
           procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;abstract;
           procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;abstract;
           procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;abstract;
           procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);virtual;abstract;
@@ -375,8 +375,8 @@ unit hlcgobj;
           procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); virtual; abstract;
           procedure g_overflowcheck(list: TAsmList; const Loc:tlocation; def:tdef); virtual; abstract;
           procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation);virtual; abstract;
           procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation);virtual; abstract;
 
 
-//          procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);virtual;
-//          procedure g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);virtual;
+          procedure g_copyvaluepara_openarray(list : TAsmList;const ref:treference;const lenloc:tlocation;arrdef: tarraydef;destreg:tregister);virtual;abstract;
+          procedure g_releasevaluepara_openarray(list : TAsmList;arrdef: tarraydef;const l:tlocation);virtual;abstract;
 
 
           {# Emits instructions when compilation is done in profile
           {# Emits instructions when compilation is done in profile
              mode (this is set as a command line option). The default
              mode (this is set as a command line option). The default
@@ -430,15 +430,21 @@ unit hlcgobj;
 //          procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmreg(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 //          procedure location_force_mmreg(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract;
 
 
+          { Retrieve the location of the data pointed to in location l, when the location is
+            a register it is expected to contain the address of the data }
+          procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);virtual;
+
           procedure maketojumpbool(list:TAsmList; p : tnode);virtual;
           procedure maketojumpbool(list:TAsmList; p : tnode);virtual;
 
 
           procedure gen_proc_symbol(list:TAsmList);virtual;
           procedure gen_proc_symbol(list:TAsmList);virtual;
           procedure gen_proc_symbol_end(list:TAsmList);virtual;
           procedure gen_proc_symbol_end(list:TAsmList);virtual;
 
 
           procedure gen_load_para_value(list:TAsmList);virtual;
           procedure gen_load_para_value(list:TAsmList);virtual;
-
-         private
+         protected
+          { helpers called by gen_load_para_value }
+          procedure g_copyvalueparas(p:TObject;arg:pointer);virtual;
           procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
           procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
+          procedure init_paras(p:TObject;arg:pointer);
          protected
          protected
           { Some targets have to put "something" in the function result
           { Some targets have to put "something" in the function result
             location if it's not initialised by the Pascal code, e.g.
             location if it's not initialised by the Pascal code, e.g.
@@ -1727,6 +1733,33 @@ implementation
       end;
       end;
     end;
     end;
 
 
+    procedure thlcgobj.location_get_data_ref(list: TAsmList; def: tdef; const l: tlocation; var ref: treference; loadref: boolean; alignment: longint);
+      begin
+        case l.loc of
+          LOC_REGISTER,
+          LOC_CREGISTER :
+            begin
+              if not loadref then
+                internalerror(200410231);
+              reference_reset_base(ref,l.register,0,alignment);
+            end;
+          LOC_REFERENCE,
+          LOC_CREFERENCE :
+            begin
+              if loadref then
+                begin
+                  reference_reset_base(ref,cg.getaddressregister(list),0,alignment);
+                  { it's a pointer to def }
+                  hlcg.a_load_ref_reg(list,voidpointertype,voidpointertype,l.reference,ref.base);
+                end
+              else
+                ref:=l.reference;
+            end;
+          else
+            internalerror(200309181);
+        end;
+      end;
+
   procedure thlcgobj.maketojumpbool(list: TAsmList; p: tnode);
   procedure thlcgobj.maketojumpbool(list: TAsmList; p: tnode);
   {
   {
     produces jumps to true respectively false labels using boolean expressions
     produces jumps to true respectively false labels using boolean expressions
@@ -1856,7 +1889,7 @@ implementation
 
 
   { generates the code for incrementing the reference count of parameters and
   { generates the code for incrementing the reference count of parameters and
     initialize out parameters }
     initialize out parameters }
-  procedure init_paras(p:TObject;arg:pointer);
+  procedure thlcgobj.init_paras(p:TObject;arg:pointer);
     var
     var
       href : treference;
       href : treference;
       tmpreg : tregister;
       tmpreg : tregister;
@@ -1883,7 +1916,7 @@ implementation
                  if not((tparavarsym(p).vardef.typ=variantdef) and
                  if not((tparavarsym(p).vardef.typ=variantdef) and
                    paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                    paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                    begin
                    begin
-                     location_get_data_ref(list,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+                     location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
                      hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
                      hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
                    end;
                    end;
                end;
                end;
@@ -1958,7 +1991,7 @@ implementation
       { generate copies of call by value parameters, must be done before
       { generate copies of call by value parameters, must be done before
         the initialization and body is parsed because the refcounts are
         the initialization and body is parsed because the refcounts are
         incremented using the local copies }
         incremented using the local copies }
-//      current_procinfo.procdef.parast.SymList.ForEachCall(@copyvalueparas,list);
+      current_procinfo.procdef.parast.SymList.ForEachCall(@g_copyvalueparas,list);
 
 
       if not(po_assembler in current_procinfo.procdef.procoptions) then
       if not(po_assembler in current_procinfo.procdef.procoptions) then
         begin
         begin
@@ -1979,6 +2012,86 @@ implementation
         end;
         end;
     end;
     end;
 
 
+  procedure thlcgobj.g_copyvalueparas(p: TObject; arg: pointer);
+    var
+      href : treference;
+      hreg : tregister;
+      list : TAsmList;
+      hsym : tparavarsym;
+      l    : longint;
+      highloc,
+      localcopyloc : tlocation;
+    begin
+      list:=TAsmList(arg);
+      if (tsym(p).typ=paravarsym) and
+         (tparavarsym(p).varspez=vs_value) and
+        (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
+        begin
+          { we have no idea about the alignment at the caller side }
+          location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,true,1);
+          if is_open_array(tparavarsym(p).vardef) or
+             is_array_of_const(tparavarsym(p).vardef) then
+            begin
+              { cdecl functions don't have a high pointer so it is not possible to generate
+                a local copy }
+              if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
+                begin
+                  if paramanager.push_high_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption) then
+                    begin
+                      hsym:=tparavarsym(tsym(p).owner.Find('high'+tsym(p).name));
+                      if not assigned(hsym) then
+                        internalerror(2011020506);
+                      highloc:=hsym.initialloc
+                    end
+                  else
+                    highloc.loc:=LOC_INVALID;
+                  hreg:=cg.getaddressregister(list);
+                  if not is_packed_array(tparavarsym(p).vardef) then
+                    g_copyvaluepara_openarray(list,href,highloc,tarraydef(tparavarsym(p).vardef),hreg)
+                  else
+                    internalerror(2011020507);
+//                      cg.g_copyvaluepara_packedopenarray(list,href,hsym.intialloc,tarraydef(tparavarsym(p).vardef).elepackedbitsize,hreg);
+                  a_load_reg_loc(list,tparavarsym(p).vardef,tparavarsym(p).vardef,hreg,tparavarsym(p).initialloc);
+                end;
+            end
+          else
+            begin
+              { Allocate space for the local copy }
+              l:=tparavarsym(p).getsize;
+              localcopyloc.loc:=LOC_REFERENCE;
+              localcopyloc.size:=int_cgsize(l);
+              tg.GetLocal(list,l,tparavarsym(p).vardef,localcopyloc.reference);
+              { Copy data }
+              if is_shortstring(tparavarsym(p).vardef) then
+                begin
+                  { this code is only executed before the code for the body and the entry/exit code is generated
+                    so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
+                  }
+                  include(current_procinfo.flags,pi_do_call);
+                  g_copyshortstring(list,href,localcopyloc.reference,tstringdef(tparavarsym(p).vardef))
+                end
+              else if tparavarsym(p).vardef.typ=variantdef then
+                begin
+                  { this code is only executed before the code for the body and the entry/exit code is generated
+                    so we're allowed to include pi_do_call here; after pass1 is run, this isn't allowed anymore
+                  }
+                  include(current_procinfo.flags,pi_do_call);
+                  g_copyvariant(list,href,localcopyloc.reference,tvariantdef(tparavarsym(p).vardef))
+                end
+              else
+                begin
+                  { pass proper alignment info }
+                  localcopyloc.reference.alignment:=tparavarsym(p).vardef.alignment;
+                  g_concatcopy(list,tparavarsym(p).vardef,href,localcopyloc.reference);
+                end;
+              { update localloc of varsym }
+              tg.Ungetlocal(list,tparavarsym(p).localloc.reference);
+              tparavarsym(p).localloc:=localcopyloc;
+              tparavarsym(p).initialloc:=localcopyloc;
+            end;
+        end;
+    end;
+
   procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
   procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
     begin
     begin
       case l.loc of
       case l.loc of

+ 3 - 4
compiler/jvm/cpunode.pas

@@ -32,9 +32,8 @@ implementation
   uses
   uses
     ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
     ncgbas,ncgflw,ncgcnv,ncgld,ncgmem,ncgcon,ncgset,
     ncgadd, ncgcal,ncgmat,ncginl,
     ncgadd, ncgcal,ncgmat,ncginl,
-    njvmadd,njvmcal,njvmmat,njvmcnv,njvmcon,njvminl,njvmmem,njvmflw
-{    ncpuadd,ncpucall,ncpumat,ncpuinln,ncpucnv,ncpuset, }
-    { this not really a node }
-{    rgcpu},tgcpu,njvmutil;
+    njvmadd,njvmcal,njvmmat,njvmcnv,njvmcon,njvminl,njvmmem,njvmflw,njvmld
+    { these are not really nodes }
+    ,rgcpu,tgcpu,njvmutil;
 
 
 end.
 end.

+ 24 - 3
compiler/jvm/cpupara.pas

@@ -35,7 +35,9 @@ interface
       { TJVMParaManager }
       { TJVMParaManager }
 
 
       TJVMParaManager=class(TParaManager)
       TJVMParaManager=class(TParaManager)
+        function  push_high_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
         function  push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
+        function  push_size(varspez: tvarspez; def: tdef; calloption: tproccalloption): longint;override;
         {Returns a structure giving the information on the storage of the parameter
         {Returns a structure giving the information on the storage of the parameter
         (which must be an integer parameter)
         (which must be an integer parameter)
         @param(nr Parameter number of routine, starting from 1)}
         @param(nr Parameter number of routine, starting from 1)}
@@ -55,7 +57,7 @@ implementation
 
 
     uses
     uses
       cutils,verbose,systems,
       cutils,verbose,systems,
-      defutil,
+      defutil,jvmdef,
       cgobj;
       cgobj;
 
 
 
 
@@ -65,12 +67,31 @@ implementation
         internalerror(2010121001);
         internalerror(2010121001);
       end;
       end;
 
 
+    function TJVMParaManager.push_high_param(varspez: tvarspez; def: tdef; calloption: tproccalloption): boolean;
+      begin
+        { we don't need a separate high parameter, since all arrays in Java
+          have an implicit associated length }
+        if not is_open_array(def) then
+          result:=inherited
+        else
+          result:=false;
+      end;
+
 
 
     { true if a parameter is too large to copy and only the address is pushed }
     { true if a parameter is too large to copy and only the address is pushed }
     function TJVMParaManager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
     function TJVMParaManager.push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;
       begin
       begin
-        { call by reference does not exist in Java bytecode }
-        result:=false;
+        result:=jvmimplicitpointertype(def);
+      end;
+
+
+    function TJVMParaManager.push_size(varspez: tvarspez; def: tdef; calloption: tproccalloption): longint;
+      begin
+        { all aggregate types are emulated using indirect pointer types }
+        if def.typ in [arraydef,recorddef,setdef,stringdef] then
+          result:=4
+        else
+          result:=inherited;
       end;
       end;
 
 
 
 

+ 266 - 3
compiler/jvm/hlcgcpu.pas

@@ -73,6 +73,8 @@ uses
 
 
       procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
       procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
 
 
+      procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
+
       procedure a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference); override;
       procedure a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference); override;
       procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
       procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
       procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
       procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
@@ -89,6 +91,10 @@ uses
       procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);override;
       procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);override;
       procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);override;
       procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);override;
 
 
+      procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);override;
+      procedure g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister); override;
+      procedure g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation); override;
+
       { JVM-specific routines }
       { JVM-specific routines }
 
 
       procedure a_load_stack_reg(list : TAsmList;size: tdef;reg: tregister);
       procedure a_load_stack_reg(list : TAsmList;size: tdef;reg: tregister);
@@ -118,6 +124,9 @@ uses
         evaluation stack, and creates a new array of type arrdef with these
         evaluation stack, and creates a new array of type arrdef with these
         dimensions }
         dimensions }
       procedure g_newarray(list : TAsmList; arrdef: tdef; initdim: longint);
       procedure g_newarray(list : TAsmList; arrdef: tdef; initdim: longint);
+      { gets the length of the array whose reference is stored in arrloc,
+        and puts it on the evaluation stack }
+      procedure g_getarraylen(list : TAsmList; const arrloc: tlocation);
 
 
       { this routine expects that all values are already massaged into the
       { this routine expects that all values are already massaged into the
         required form (sign bits xor'ed for gt/lt comparisons for OS_32/OS_64,
         required form (sign bits xor'ed for gt/lt comparisons for OS_32/OS_64,
@@ -159,6 +168,10 @@ uses
       procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
       procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
       { common implementation of a_call_* }
       { common implementation of a_call_* }
       procedure a_call_name_intern(list : TAsmList;pd : tprocdef;const s : string; inheritedcall: boolean);
       procedure a_call_name_intern(list : TAsmList;pd : tprocdef;const s : string; inheritedcall: boolean);
+
+      { concatcopy helpers }
+      procedure concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference);
+
     end;
     end;
 
 
   procedure create_hlcodegen;
   procedure create_hlcodegen;
@@ -175,8 +188,8 @@ implementation
     verbose,cutils,globals,
     verbose,cutils,globals,
     defutil,
     defutil,
     aasmtai,aasmcpu,
     aasmtai,aasmcpu,
-    symconst,jvmdef,
-    procinfo,cgcpu;
+    symconst,symtable,symsym,jvmdef,
+    procinfo,cgcpu,tgobj;
 
 
   const
   const
     TOpCG2IAsmOp : array[topcg] of TAsmOp=(                       { not = xor -1 }
     TOpCG2IAsmOp : array[topcg] of TAsmOp=(                       { not = xor -1 }
@@ -595,6 +608,46 @@ implementation
         end;
         end;
     end;
     end;
 
 
+  procedure thlcgjvm.g_getarraylen(list: TAsmList; const arrloc: tlocation);
+    var
+      nillab,endlab: tasmlabel;
+    begin
+      { inline because we have to use the arraylength opcode, which
+        cannot be represented directly in Pascal. Even though the JVM
+        supports allocated arrays with length=0, we still also have to
+        check for nil pointers because even if FPC always generates
+        allocated empty arrays under all circumstances, external Java
+        code could pass in nil pointers.
+
+        Note that this means that assigned(arr) can be different from
+        length(arr)<>0 for dynamic arrays when targeting the JVM.
+      }
+      current_asmdata.getjumplabel(nillab);
+      current_asmdata.getjumplabel(endlab);
+
+      { if assigned(arr) ... }
+      a_load_loc_stack(list,java_jlobject,arrloc);
+      list.concat(taicpu.op_none(a_dup));
+      incstack(list,1);
+      list.concat(taicpu.op_none(a_aconst_null));
+      incstack(list,1);
+      list.concat(taicpu.op_sym(a_if_acmpeq,nillab));
+      decstack(list,2);
+
+      { ... then result:=arraylength(arr) ... }
+      list.concat(taicpu.op_none(a_arraylength));
+      a_jmp_always(list,endlab);
+
+      { ... else result:=0 }
+      a_label(list,nillab);
+      list.concat(taicpu.op_none(a_pop));
+      decstack(list,1);
+      list.concat(taicpu.op_none(a_iconst_0));
+      incstack(list,1);
+
+      a_label(list,endlab);
+    end;
+
     procedure thlcgjvm.a_cmp_stack_label(list: TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
     procedure thlcgjvm.a_cmp_stack_label(list: TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
       const
       const
         opcmp2icmp: array[topcmp] of tasmop = (A_None,
         opcmp2icmp: array[topcmp] of tasmop = (A_None,
@@ -859,7 +912,12 @@ implementation
 
 
   procedure thlcgjvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
   procedure thlcgjvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
     begin
     begin
-      internalerror(2010120534);
+      { only allowed for types that are not implicit pointers in Pascal (in
+        that case, ref contains a pointer to the actual data and we simply
+        return that pointer) }
+      if not jvmimplicitpointertype(fromsize) then
+        internalerror(2010120534);
+      a_load_ref_reg(list,java_jlobject,java_jlobject,ref,r);
     end;
     end;
 
 
   procedure thlcgjvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister);
   procedure thlcgjvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister);
@@ -957,6 +1015,115 @@ implementation
       list.concat(taicpu.op_sym(a_goto,current_asmdata.RefAsmSymbol(l.name)));
       list.concat(taicpu.op_sym(a_goto,current_asmdata.RefAsmSymbol(l.name)));
     end;
     end;
 
 
+  procedure thlcgjvm.concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference);
+    var
+      procname: string;
+      eledef: tdef;
+      pd: tprocdef;
+      srsym: tsym;
+      ndim: longint;
+    begin
+      { load copy helper parameters on the stack }
+      a_load_ref_stack(list,java_jlobject,source,prepare_stack_for_ref(list,source,false));
+      a_load_ref_stack(list,java_jlobject,dest,prepare_stack_for_ref(list,dest,false));
+      { call copy helper }
+      eledef:=tarraydef(size).elementdef;
+      ndim:=1;
+      case eledef.typ of
+        orddef:
+          begin
+            case torddef(eledef).ordtype of
+              pasbool8,s8bit,u8bit,bool8bit,uchar:
+                procname:='FPC_COPY_JBYTE_ARRAY';
+              s16bit,u16bit,bool16bit,pasbool16:
+                procname:='FPC_COPY_JSHORT_ARRAY';
+              uwidechar:
+                procname:='FPC_COPY_JCHAR_ARRAY';
+              s32bit,u32bit,bool32bit,pasbool32:
+                procname:='FPC_COPY_JINT_ARRAY';
+              s64bit,u64bit,bool64bit,pasbool64,scurrency:
+                procname:='FPC_COPY_JLONG_ARRAY';
+              else
+                internalerror(2011020504);
+            end;
+          end;
+        floatdef:
+          case tfloatdef(eledef).floattype of
+            s32real:
+              procname:='FPC_COPY_JFLOAT_ARRAY';
+            s64real:
+              procname:='FPC_COPY_JDOUBLE_ARRAY';
+          end;
+        arraydef:
+          begin
+            { call fpc_setlength_dynarr_multidim with deepcopy=true, and extra
+              parameters }
+            while (eledef.typ=arraydef) and
+                  not is_dynamic_array(eledef) do
+              begin
+                eledef:=tarraydef(eledef).elementdef;
+                inc(ndim)
+              end;
+            if (ndim=1) then
+              procname:='FPC_COPY_JOBJECT_ARRAY'
+            else
+              begin
+                { deepcopy=true }
+                a_load_const_stack(list,pasbool8type,1,R_INTREGISTER);
+                { ndim }
+                a_load_const_stack(list,s32inttype,ndim,R_INTREGISTER);
+                { eletype }
+                a_load_const_stack(list,cwidechartype,ord(jvmarrtype_setlength(eledef)),R_INTREGISTER);
+                procname:='FPC_SETLENGTH_DYNARR_MULTIDIM';
+              end;
+          end;
+        setdef,
+        recorddef,
+        stringdef,
+        variantdef:
+          begin
+            { todo: make a (recursive for records) deep copy, not sure yet how... }
+            internalerror(2011020505);
+          end;
+        else
+          procname:='FPC_COPY_JOBJECT_ARRAY';
+      end;
+     srsym:=tsym(systemunit.find(procname));
+     if not assigned(srsym) or
+        (srsym.typ<>procsym) then
+       Message1(cg_f_unknown_compilerproc,procname);
+     pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
+     a_call_name(list,pd,pd.mangledname,false);
+     if ndim=1 then
+       decstack(list,2)
+     else
+       begin
+         decstack(list,4);
+         { pop return value, must be the same as dest }
+         list.concat(taicpu.op_none(a_pop));
+         decstack(list,1);
+       end;
+    end;
+
+  procedure thlcgjvm.g_concatcopy(list: TAsmList; size: tdef; const source, dest: treference);
+    var
+      handled: boolean;
+    begin
+      handled:=false;
+      case size.typ of
+        arraydef:
+          begin
+            if not is_dynamic_array(size) then
+              begin
+                concatcopy_normal_array(list,size,source,dest);
+                handled:=true;
+              end;
+          end;
+      end;
+      if not handled then
+        inherited;
+    end;
+
   procedure thlcgjvm.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference);
   procedure thlcgjvm.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference);
     var
     var
       dstack_slots: longint;
       dstack_slots: longint;
@@ -1077,6 +1244,90 @@ implementation
       // do nothing
       // do nothing
     end;
     end;
 
 
+  procedure thlcgjvm.location_get_data_ref(list: TAsmList; def: tdef; const l: tlocation; var ref: treference; loadref: boolean; alignment: longint);
+    var
+      tmploc: tlocation;
+    begin
+      { This routine is a combination of a generalised a_loadaddr_ref_reg()
+        that also works for addresses in registers (in case loadref is false)
+        and of a_load_ref_reg (in case loadref is true). It is used for
+        a) getting the address of managed types
+        b) getting to the actual data of value types that are passed by
+           reference by the compiler (and then get a local copy at the caller
+           side). Normally, depending on whether this reference is passed in a
+           register or reference, we either need a reference with that register
+           as base or load the address in that reference and use that as a new
+           base.
+
+        Since the JVM cannot take the address of anything, all
+        "pass-by-reference" value parameters (which are always aggregate types)
+        are already simply the implicit pointer to the data (since arrays,
+        records, etc are already internally implicit pointers). This means
+        that if "loadref" is true, we must simply return this implicit pointer.
+        If it is false, we are supposed the take the address of this implicit
+        pointer, which is not possible.
+
+        However, managed types are also implicit pointers in Pascal, so in that
+        case "taking the address" again consists of simply returning the
+        implicit pointer/current value.
+      }
+      if not loadref then
+        begin
+          if not is_managed_type(def) then
+            internalerror(2011020601);
+        end
+      else
+        begin
+          if not jvmimplicitpointertype(def) then
+            internalerror(2011020602);
+        end;
+      case l.loc of
+        LOC_REGISTER,
+        LOC_CREGISTER :
+          begin
+            { the implicit pointer is in a register and has to be in a
+              reference -> create a reference and put it there }
+            tmploc:=l;
+            location_force_mem(list,tmploc,java_jlobject);
+            ref:=tmploc.reference;
+          end;
+        LOC_REFERENCE,
+        LOC_CREFERENCE :
+          begin
+            ref:=l.reference;
+          end;
+        else
+          internalerror(2011020603);
+      end;
+    end;
+
+  procedure thlcgjvm.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
+    var
+      localref: treference;
+      arrloc: tlocation;
+      stackslots: longint;
+    begin
+      { temporary reference for passing to concatcopy }
+      tg.gethltemp(list,java_jlobject,java_jlobject.size,tt_persistent,localref);
+      stackslots:=prepare_stack_for_ref(list,localref,false);
+      { create the local copy of the array (lenloc is invalid, get length
+        directly from the array) }
+      location_reset_ref(arrloc,LOC_REFERENCE,OS_ADDR,sizeof(pint));
+      arrloc.reference:=ref;
+      g_getarraylen(list,arrloc);
+      g_newarray(list,arrdef,1);
+      a_load_stack_ref(list,java_jlobject,localref,stackslots);
+      { copy the source array to the destination }
+      g_concatcopy(list,arrdef,ref,localref);
+      { and put the array pointer in the register as expected by the caller }
+      a_load_ref_reg(list,java_jlobject,java_jlobject,localref,destreg);
+    end;
+
+  procedure thlcgjvm.g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation);
+    begin
+      // do nothing, long live garbage collection!
+    end;
+
   procedure thlcgjvm.a_load_stack_reg(list: TAsmList; size: tdef; reg: tregister);
   procedure thlcgjvm.a_load_stack_reg(list: TAsmList; size: tdef; reg: tregister);
     var
     var
       opc: tasmop;
       opc: tasmop;
@@ -1084,6 +1335,9 @@ implementation
     begin
     begin
       opc:=loadstoreopc(size,false,false,finishandval);
       opc:=loadstoreopc(size,false,false,finishandval);
       list.concat(taicpu.op_reg(opc,reg));
       list.concat(taicpu.op_reg(opc,reg));
+      { avoid problems with getting the size of an open array etc }
+      if jvmimplicitpointertype(size) then
+        size:=java_jlobject;
       decstack(list,1+ord(size.size>4));
       decstack(list,1+ord(size.size>4));
     end;
     end;
 
 
@@ -1100,6 +1354,9 @@ implementation
         list.concat(taicpu.op_ref(opc,ref))
         list.concat(taicpu.op_ref(opc,ref))
       else
       else
         list.concat(taicpu.op_none(opc));
         list.concat(taicpu.op_none(opc));
+      { avoid problems with getting the size of an open array etc }
+      if jvmimplicitpointertype(size) then
+        size:=java_jlobject;
       decstack(list,1+ord(size.size>4)+extra_slots);
       decstack(list,1+ord(size.size>4)+extra_slots);
     end;
     end;
 
 
@@ -1112,6 +1369,9 @@ implementation
       list.concat(taicpu.op_reg(opc,reg));
       list.concat(taicpu.op_reg(opc,reg));
       if finishandval<>-1 then
       if finishandval<>-1 then
         a_op_const_stack(list,OP_AND,size,finishandval);
         a_op_const_stack(list,OP_AND,size,finishandval);
+      { avoid problems with getting the size of an open array etc }
+      if jvmimplicitpointertype(size) then
+        size:=java_jlobject;
       incstack(list,1+ord(size.size>4));
       incstack(list,1+ord(size.size>4));
     end;
     end;
 
 
@@ -1130,6 +1390,9 @@ implementation
         list.concat(taicpu.op_none(opc));
         list.concat(taicpu.op_none(opc));
       if finishandval<>-1 then
       if finishandval<>-1 then
         a_op_const_stack(list,OP_AND,size,finishandval);
         a_op_const_stack(list,OP_AND,size,finishandval);
+      { avoid problems with getting the size of an open array etc }
+      if jvmimplicitpointertype(size) then
+        size:=java_jlobject;
       incstack(list,1+ord(size.size>4)-extra_slots);
       incstack(list,1+ord(size.size>4)-extra_slots);
     end;
     end;
 
 

+ 24 - 37
compiler/jvm/njvminl.pas

@@ -89,7 +89,8 @@ implementation
     function tjvminlinenode.typecheck_length(var handled: boolean): tnode;
     function tjvminlinenode.typecheck_length(var handled: boolean): tnode;
       begin
       begin
         typecheckpass(left);
         typecheckpass(left);
-        if is_dynamic_array(left.resultdef) then
+        if is_dynamic_array(left.resultdef) or
+           is_open_array(left.resultdef) then
           begin
           begin
             resultdef:=s32inttype;
             resultdef:=s32inttype;
             result:=nil;
             result:=nil;
@@ -101,7 +102,8 @@ implementation
     function tjvminlinenode.typecheck_high(var handled: boolean): tnode;
     function tjvminlinenode.typecheck_high(var handled: boolean): tnode;
       begin
       begin
         typecheckpass(left);
         typecheckpass(left);
-        if is_dynamic_array(left.resultdef) then
+        if is_dynamic_array(left.resultdef) or
+           is_open_array(left.resultdef) then
           begin
           begin
             { replace with pred(length(arr)) }
             { replace with pred(length(arr)) }
             result:=cinlinenode.create(in_pred_x,false,
             result:=cinlinenode.create(in_pred_x,false,
@@ -247,6 +249,18 @@ implementation
             eledef:=tarraydef(eledef).elementdef;
             eledef:=tarraydef(eledef).elementdef;
             ppn:=tcallparanode(ppn).right;
             ppn:=tcallparanode(ppn).right;
           end;
           end;
+        { in case it's a dynamic array of static arrays, we must also allocate
+          the static arrays! }
+        while (eledef.typ=arraydef) and
+              not is_dynamic_array(eledef) do
+          begin
+            inc(ndims);
+            tcallparanode(ppn).right:=
+              ccallparanode.create(
+                genintconstnode(tarraydef(eledef).elecount),nil);
+            ppn:=tcallparanode(ppn).right;
+            eledef:=tarraydef(eledef).elementdef;
+          end;
         { prepend type parameter for the array }
         { prepend type parameter for the array }
         newparas:=ccallparanode.create(ctypenode.create(left.resultdef),newparas);
         newparas:=ccallparanode.create(ctypenode.create(left.resultdef),newparas);
         ttypenode(tcallparanode(newparas).left).allowed:=true;
         ttypenode(tcallparanode(newparas).left).allowed:=true;
@@ -268,8 +282,11 @@ implementation
           assignmenttarget:=tcallparanode(left).left.getcopy;
           assignmenttarget:=tcallparanode(left).left.getcopy;
         newparas:=left;
         newparas:=left;
         left:=nil;
         left:=nil;
-        { if more than 1 dimension, typecast to generic array of tobject }
-        if ndims>1 then
+        { if more than 1 dimension, or if 1 dimention of a non-primitive type,
+          typecast to generic array of tobject }
+        setlenroutine:=jvmarrtype(eledef,primitive);
+        if (ndims>1) or
+           not primitive then
           begin
           begin
             objarraydef:=search_system_type('TJOBJECTARRAY').typedef;
             objarraydef:=search_system_type('TJOBJECTARRAY').typedef;
             tcallparanode(newparas).left:=ctypeconvnode.create_explicit(tcallparanode(newparas).left,objarraydef);
             tcallparanode(newparas).left:=ctypeconvnode.create_explicit(tcallparanode(newparas).left,objarraydef);
@@ -294,7 +311,6 @@ implementation
           end
           end
         else
         else
           begin
           begin
-            setlenroutine:=jvmarrtype(eledef,primitive);
             if not primitive then
             if not primitive then
               setlenroutine:='OBJECT'
               setlenroutine:='OBJECT'
             else
             else
@@ -318,43 +334,14 @@ implementation
 
 
 
 
     procedure tjvminlinenode.second_length;
     procedure tjvminlinenode.second_length;
-      var
-        nillab,endlab: tasmlabel;
       begin
       begin
-        if is_dynamic_array(left.resultdef) then
+        if is_dynamic_array(left.resultdef) or
+           is_open_array(left.resultdef) then
           begin
           begin
-            { inline because we have to use the arraylength opcode, which
-              cannot be represented directly in Pascal. Even though the JVM
-              supports allocated arrays with length=0, we still also have to
-              check for nil pointers because even if FPC always generates
-              allocated empty arrays under all circumstances, external Java
-              code could pass in nil pointers.
-
-              Note that this means that assigned(arr) can be different from
-              length(arr)<>0 when targeting the JVM.
-            }
-
-            { if assigned(arr) then result:=arraylength(arr) else result:=0 }
             location_reset(location,LOC_REGISTER,OS_S32);
             location_reset(location,LOC_REGISTER,OS_S32);
             location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s32inttype);
             location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,s32inttype);
             secondpass(left);
             secondpass(left);
-            current_asmdata.getjumplabel(nillab);
-            current_asmdata.getjumplabel(endlab);
-            thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);
-            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_dup));
-            thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
-            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_aconst_null));
-            thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
-            current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_if_acmpeq,nillab));
-            thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,2);
-            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_arraylength));
-            hlcg.a_jmp_always(current_asmdata.CurrAsmList,endlab);
-            hlcg.a_label(current_asmdata.CurrAsmList,nillab);
-            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_pop));
-            thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,1);
-            current_asmdata.CurrAsmList.concat(taicpu.op_none(a_iconst_0));
-            thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
-            hlcg.a_label(current_asmdata.CurrAsmList,endlab);
+            thlcgjvm(hlcg).g_getarraylen(current_asmdata.CurrAsmList,left.location);
             thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
             thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
           end
           end
         else
         else

+ 54 - 0
compiler/jvm/njvmld.pas

@@ -0,0 +1,54 @@
+{
+    Copyright (c) 2011 by Jonas Maebe
+
+    Generate JVM assembler for nodes that handle loads and assignments
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit njvmld;
+
+{$I fpcdefs.inc}
+
+interface
+
+uses
+  node, ncgld;
+
+type
+  tjvmloadnode = class(tcgloadnode)
+    function is_addr_param_load: boolean; override;
+  end;
+
+implementation
+
+uses
+  nld,
+  symsym,
+  jvmdef;
+
+function tjvmloadnode.is_addr_param_load: boolean;
+  begin
+    result:=
+      inherited and
+      not jvmimplicitpointertype(tparavarsym(symtableentry).vardef);
+  end;
+
+
+begin
+  cloadnode:=tjvmloadnode;
+end.
+

+ 21 - 3
compiler/jvm/njvmmem.pas

@@ -42,7 +42,7 @@ implementation
       cutils,verbose,
       cutils,verbose,
       symdef,defutil,
       symdef,defutil,
       aasmdata,pass_2,
       aasmdata,pass_2,
-      cgutils,hlcgobj;
+      cgutils,hlcgobj,hlcgcpu;
 
 
 {*****************************************************************************
 {*****************************************************************************
                              TJVMVECNODE
                              TJVMVECNODE
@@ -65,7 +65,9 @@ implementation
           location_reset_ref(location,LOC_CREFERENCE,newsize,left.location.reference.alignment)
           location_reset_ref(location,LOC_CREFERENCE,newsize,left.location.reference.alignment)
         else
         else
           location_reset_ref(location,LOC_REFERENCE,newsize,left.location.reference.alignment);
           location_reset_ref(location,LOC_REFERENCE,newsize,left.location.reference.alignment);
-        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
+        { don't use left.resultdef, because it may be an open or regular array,
+          and then asking for the size doesn't make any sense }
+        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,java_jlobject,java_jlobject,true);
         location.reference.base:=left.location.register;
         location.reference.base:=left.location.register;
         secondpass(right);
         secondpass(right);
         { simplify index location if necessary, since array references support
         { simplify index location if necessary, since array references support
@@ -74,6 +76,22 @@ implementation
            (right.location.reference.arrayreftype<>art_none) then
            (right.location.reference.arrayreftype<>art_none) then
           hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
           hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,true);
 
 
+        { adjust index if necessary }
+        if not is_special_array(left.resultdef) and
+           (tarraydef(left.resultdef).lowrange<>0) and
+           (right.location.loc<>LOC_CONSTANT) then
+          begin
+            thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
+            thlcgjvm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_SUB,right.resultdef,tarraydef(left.resultdef).lowrange);
+            if right.location.loc<>LOC_REGISTER then
+              begin
+                location_reset(right.location,LOC_REGISTER,def_cgsize(right.resultdef));
+                right.location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,right.resultdef);
+              end;
+            thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,right.resultdef,right.location.register);
+          end;
+
+        { create array reference }
         case right.location.loc of
         case right.location.loc of
           LOC_REGISTER,LOC_CREGISTER:
           LOC_REGISTER,LOC_CREGISTER:
             begin
             begin
@@ -90,7 +108,7 @@ implementation
           LOC_CONSTANT:
           LOC_CONSTANT:
             begin
             begin
               location.reference.arrayreftype:=art_indexconst;
               location.reference.arrayreftype:=art_indexconst;
-              location.reference.indexoffset:=right.location.value;
+              location.reference.indexoffset:=right.location.value-tarraydef(left.resultdef).lowrange;
             end
             end
           else
           else
             internalerror(2011012002);
             internalerror(2011012002);

+ 56 - 1
compiler/jvm/tgcpu.pas

@@ -31,6 +31,7 @@ unit tgcpu;
     uses
     uses
        globtype,
        globtype,
        aasmdata,
        aasmdata,
+       cgutils,
        symtype,tgobj;
        symtype,tgobj;
 
 
     type
     type
@@ -39,19 +40,57 @@ unit tgcpu;
 
 
        ttgjvm = class(ttgobj)
        ttgjvm = class(ttgobj)
         protected
         protected
+         function getifspecialtemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference): boolean;
          function alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint; override;
          function alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint; override;
         public
         public
          procedure setfirsttemp(l : longint); override;
          procedure setfirsttemp(l : longint); override;
+         procedure getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference); override;
+         procedure gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference); override;
        end;
        end;
 
 
   implementation
   implementation
 
 
     uses
     uses
-       verbose;
+       verbose,
+       cgbase,
+       symconst,defutil,
+       hlcgobj,hlcgcpu,
+       symdef;
 
 
 
 
     { ttgjvm }
     { ttgjvm }
 
 
+    function ttgjvm.getifspecialtemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference): boolean;
+      var
+        eledef: tdef;
+        ndim: longint;
+      begin
+        result:=false;
+        case def.typ of
+          arraydef:
+            begin
+              if not is_dynamic_array(def) then
+                begin
+                  { allocate an array of the right size }
+                  gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
+                  ndim:=0;
+                  eledef:=def;
+                  repeat
+                    thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,tarraydef(eledef).elecount,R_INTREGISTER);
+                    eledef:=tarraydef(eledef).elementdef;
+                    inc(ndim);
+                  until (eledef.typ<>arraydef) or
+                        is_dynamic_array(eledef);
+                  eledef:=tarraydef(def).elementdef;
+                  thlcgjvm(hlcg).g_newarray(list,def,ndim);
+                  thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
+                  result:=true;
+                end;
+            end;
+        end;
+      end;
+
+
     function ttgjvm.alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint;
     function ttgjvm.alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint;
       begin
       begin
         { the JVM only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
         { the JVM only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
@@ -67,12 +106,28 @@ unit tgcpu;
         result:=inherited alloctemp(list, size shr 2, 1, temptype, nil);
         result:=inherited alloctemp(list, size shr 2, 1, temptype, nil);
       end;
       end;
 
 
+
     procedure ttgjvm.setfirsttemp(l: longint);
     procedure ttgjvm.setfirsttemp(l: longint);
       begin
       begin
         firsttemp:=l;
         firsttemp:=l;
         lasttemp:=l;
         lasttemp:=l;
       end;
       end;
 
 
+
+    procedure ttgjvm.getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference);
+      begin
+        if not getifspecialtemp(list,def,size,tt_persistent,ref) then
+          inherited;
+      end;
+
+
+    procedure ttgjvm.gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference);
+      begin
+        if not getifspecialtemp(list,def,forcesize,temptype,ref) then
+          inherited;
+      end;
+
+
 begin
 begin
   tgobjclass:=ttgjvm;
   tgobjclass:=ttgjvm;
 end.
 end.

+ 33 - 2
compiler/jvmdef.pas

@@ -57,6 +57,10 @@ interface
     function jvmarrtype(def: tdef; out primitivetype: boolean): string;
     function jvmarrtype(def: tdef; out primitivetype: boolean): string;
     function jvmarrtype_setlength(def: tdef): char;
     function jvmarrtype_setlength(def: tdef): char;
 
 
+    { returns whether a def is emulated using an implicit pointer type on the
+      JVM target (e.g., records, regular arrays, ...) }
+    function jvmimplicitpointertype(def: tdef): boolean;
+
 implementation
 implementation
 
 
   uses
   uses
@@ -171,7 +175,6 @@ implementation
           arraydef :
           arraydef :
             begin
             begin
               if is_array_of_const(def) or
               if is_array_of_const(def) or
-                 is_open_array(def) or
                  is_packed_array(def) then
                  is_packed_array(def) then
                 result:=false
                 result:=false
               else
               else
@@ -281,8 +284,15 @@ implementation
                 internalerror(2011012206);
                 internalerror(2011012206);
               end;
               end;
             primitivetype:=true;
             primitivetype:=true;
+          end
+        else if (result[1]='L') then
+          begin
+            { in case of a class reference, strip the leading 'L' and the
+              trailing ';' }
+            setlength(result,length(result)-1);
+            delete(result,1,1);
           end;
           end;
-        { in other cases, use the actual reference type }
+        { for arrays, use the actual reference type }
       end;
       end;
 
 
 
 
@@ -299,6 +309,27 @@ implementation
           result:='A';
           result:='A';
       end;
       end;
 
 
+    function jvmimplicitpointertype(def: tdef): boolean;
+      begin
+        case def.typ of
+          arraydef:
+            result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
+                is_open_array(def) or
+                is_array_of_const(def) or
+                is_array_constructor(def);
+          recorddef:
+            result:=true;
+          objectdef:
+            result:=is_object(def);
+          setdef:
+            result:=not is_smallset(def);
+          stringdef :
+            result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
+          else
+            result:=false;
+        end;
+      end;
+
 
 
 {******************************************************************
 {******************************************************************
                     jvm type validity checking
                     jvm type validity checking

+ 2 - 2
compiler/ncgcal.pas

@@ -130,7 +130,7 @@ implementation
       begin
       begin
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
         if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
           internalerror(200304235);
           internalerror(200304235);
-        cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.location.reference,tempcgpara);
+        hlcg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,left.resultdef,tempcgpara.def,left.location.reference,tempcgpara);
       end;
       end;
 
 
 
 
@@ -174,7 +174,7 @@ implementation
              if (parasym.varspez=vs_out) and
              if (parasym.varspez=vs_out) and
                 is_managed_type(left.resultdef) then
                 is_managed_type(left.resultdef) then
                begin
                begin
-                 location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
+                 hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,left.location,href,false,sizeof(pint));
                  if is_open_array(resultdef) then
                  if is_open_array(resultdef) then
                    begin
                    begin
                      if third=nil then
                      if third=nil then

+ 4 - 4
compiler/ncgld.pas

@@ -603,7 +603,7 @@ implementation
               not is_constnode(right) then
               not is_constnode(right) then
             begin
             begin
               hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
               hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
-              location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false,sizeof(pint));
+              hlcg.location_get_data_ref(current_asmdata.CurrAsmList,right.resultdef,right.location,href,false,sizeof(pint));
               hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
               hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
             end;
             end;
            if codegenerror then
            if codegenerror then
@@ -615,7 +615,7 @@ implementation
            { decrement destination reference counter }
            { decrement destination reference counter }
            if is_managed_type(left.resultdef) then
            if is_managed_type(left.resultdef) then
              begin
              begin
-               location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
+               hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,left.location,href,false,sizeof(pint));
                hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
                hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
              end;
              end;
            if codegenerror then
            if codegenerror then
@@ -628,7 +628,7 @@ implementation
            { decrement destination reference counter }
            { decrement destination reference counter }
            if is_managed_type(left.resultdef) then
            if is_managed_type(left.resultdef) then
              begin
              begin
-               location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
+               hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,left.location,href,false,sizeof(pint));
                hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
                hlcg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
              end;
              end;
            if codegenerror then
            if codegenerror then
@@ -650,7 +650,7 @@ implementation
               (right.nodetype<>stringconstn) then
               (right.nodetype<>stringconstn) then
              begin
              begin
                hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
                hlcg.location_force_mem(current_asmdata.CurrAsmList,right.location,right.resultdef);
-               location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false,sizeof(pint));
+               hlcg.location_get_data_ref(current_asmdata.CurrAsmList,left.resultdef,right.location,href,false,sizeof(pint));
                hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
                hlcg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
              end;
              end;
 
 

+ 5 - 35
compiler/ncgutil.pas

@@ -79,9 +79,6 @@ interface
 
 
     procedure register_maybe_adjust_setbase(list: TAsmList; var l: tlocation; setbase: aint);
     procedure register_maybe_adjust_setbase(list: TAsmList; var l: tlocation; setbase: aint);
 
 
-    { Retrieve the location of the data pointed to in location l, when the location is
-      a register it is expected to contain the address of the data }
-    procedure location_get_data_ref(list:TAsmList;const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);
 
 
     function  has_alias_name(pd:tprocdef;const s:string):boolean;
     function  has_alias_name(pd:tprocdef;const s:string):boolean;
     procedure alloc_proc_symbol(pd: tprocdef);
     procedure alloc_proc_symbol(pd: tprocdef);
@@ -1208,33 +1205,6 @@ implementation
       end;
       end;
 
 
 
 
-    procedure location_get_data_ref(list:TAsmList;const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);
-      begin
-        case l.loc of
-          LOC_REGISTER,
-          LOC_CREGISTER :
-            begin
-              if not loadref then
-                internalerror(200410231);
-              reference_reset_base(ref,l.register,0,alignment);
-            end;
-          LOC_REFERENCE,
-          LOC_CREFERENCE :
-            begin
-              if loadref then
-                begin
-                  reference_reset_base(ref,cg.getaddressregister(list),0,alignment);
-                  cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,l.reference,ref.base);
-                end
-              else
-                ref:=l.reference;
-            end;
-          else
-            internalerror(200309181);
-        end;
-      end;
-
-
 {****************************************************************************
 {****************************************************************************
                             Init/Finalize Code
                             Init/Finalize Code
 ****************************************************************************}
 ****************************************************************************}
@@ -1254,7 +1224,7 @@ implementation
           (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
           (paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
           begin
           begin
             { we have no idea about the alignment at the caller side }
             { we have no idea about the alignment at the caller side }
-            location_get_data_ref(list,tparavarsym(p).initialloc,href,true,1);
+            hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,true,1);
             if is_open_array(tparavarsym(p).vardef) or
             if is_open_array(tparavarsym(p).vardef) or
                is_array_of_const(tparavarsym(p).vardef) then
                is_array_of_const(tparavarsym(p).vardef) then
               begin
               begin
@@ -1605,7 +1575,7 @@ implementation
                    if not((tparavarsym(p).vardef.typ=variantdef) and
                    if not((tparavarsym(p).vardef.typ=variantdef) and
                      paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                      paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
                      begin
                      begin
-                       location_get_data_ref(list,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+                       hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
                        if is_open_array(tparavarsym(p).vardef) then
                        if is_open_array(tparavarsym(p).vardef) then
                          begin
                          begin
                            { open arrays do not contain correct element count in their rtti,
                            { open arrays do not contain correct element count in their rtti,
@@ -1617,7 +1587,7 @@ implementation
                            cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_ADDREF_ARRAY');
                            cg.g_array_rtti_helper(list,eldef,href,hsym.initialloc,'FPC_ADDREF_ARRAY');
                          end
                          end
                        else
                        else
-                         cg.g_incrrefcount(list,tparavarsym(p).vardef,href);
+                        cg.g_incrrefcount(list,tparavarsym(p).vardef,href);
                      end;
                      end;
                  end;
                  end;
              vs_out :
              vs_out :
@@ -1697,7 +1667,7 @@ implementation
            if (tparavarsym(p).varspez=vs_value) then
            if (tparavarsym(p).varspez=vs_value) then
             begin
             begin
               include(current_procinfo.flags,pi_needs_implicit_finally);
               include(current_procinfo.flags,pi_needs_implicit_finally);
-              location_get_data_ref(list,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+              hlcg.location_get_data_ref(list,tparavarsym(p).vardef,tparavarsym(p).localloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
               if is_open_array(tparavarsym(p).vardef) then
               if is_open_array(tparavarsym(p).vardef) then
                 begin
                 begin
                   hsym:=tparavarsym(tsym(p).owner.Find('high'+tsym(p).name));
                   hsym:=tparavarsym(tsym(p).owner.Find('high'+tsym(p).name));
@@ -1718,7 +1688,7 @@ implementation
             { cdecl functions don't have a high pointer so it is not possible to generate
             { cdecl functions don't have a high pointer so it is not possible to generate
               a local copy }
               a local copy }
             if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
             if not(current_procinfo.procdef.proccalloption in cdecl_pocalls) then
-              cg.g_releasevaluepara_openarray(list,tparavarsym(p).localloc);
+              hlcg.g_releasevaluepara_openarray(list,tarraydef(tparavarsym(p).vardef),tparavarsym(p).localloc);
           end;
           end;
       end;
       end;
 
 

+ 7 - 6
compiler/nld.pas

@@ -50,7 +50,7 @@ interface
           procedure buildderefimpl;override;
           procedure buildderefimpl;override;
           procedure derefimpl;override;
           procedure derefimpl;override;
           procedure set_mp(p:tnode);
           procedure set_mp(p:tnode);
-          function  is_addr_param_load:boolean;
+          function  is_addr_param_load:boolean;virtual;
           function  dogetcopy : tnode;override;
           function  dogetcopy : tnode;override;
           function  pass_1 : tnode;override;
           function  pass_1 : tnode;override;
           function  pass_typecheck:tnode;override;
           function  pass_typecheck:tnode;override;
@@ -149,7 +149,7 @@ interface
 implementation
 implementation
 
 
     uses
     uses
-      cutils,verbose,globtype,globals,systems,
+      cutils,verbose,globtype,globals,systems,constexp,
       symnot,
       symnot,
       defutil,defcmp,
       defutil,defcmp,
       htypechk,pass_1,procinfo,paramgr,
       htypechk,pass_1,procinfo,paramgr,
@@ -550,10 +550,11 @@ implementation
            { remove property flag to avoid errors, see comments for }
            { remove property flag to avoid errors, see comments for }
            { tf_winlikewidestring assignments below                 }
            { tf_winlikewidestring assignments below                 }
            exclude(left.flags,nf_isproperty);
            exclude(left.flags,nf_isproperty);
-           hp:=ccallparanode.create(caddrnode.create_internal
-                   (crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
-               ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
-           result := ccallnode.createintern('fpc_dynarray_clear',hp);
+           { generate a setlength node so it can be intercepted by
+             target-specific code }
+           result:=cinlinenode.create(in_setlength_x,false,
+             ccallparanode.create(genintconstnode(0),
+               ccallparanode.create(left,nil)));
            left:=nil;
            left:=nil;
            exit;
            exit;
          end;
          end;

+ 1 - 1
compiler/paramgr.pas

@@ -56,7 +56,7 @@ unit paramgr;
           }
           }
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;abstract;
           function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;virtual;abstract;
           { return the size of a push }
           { return the size of a push }
-          function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;
+          function push_size(varspez:tvarspez;def : tdef;calloption : tproccalloption) : longint;virtual;
           {# Returns a structure giving the information on
           {# Returns a structure giving the information on
             the storage of the parameter (which must be
             the storage of the parameter (which must be
             an integer parameter). This is only used when calling
             an integer parameter). This is only used when calling

+ 2 - 2
compiler/tgobj.pas

@@ -86,7 +86,7 @@ unit tgobj;
 
 
             the forcesize parameter is so that it can be used for defs that
             the forcesize parameter is so that it can be used for defs that
             don't have an inherent size (e.g., array of const) }
             don't have an inherent size (e.g., array of const) }
-          procedure gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference);
+          procedure gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference); virtual;
           procedure gettemp(list: TAsmList; size, alignment : longint;temptype:ttemptype;out ref : treference);
           procedure gettemp(list: TAsmList; size, alignment : longint;temptype:ttemptype;out ref : treference);
           procedure gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
           procedure gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
           procedure ungettemp(list: TAsmList; const ref : treference);
           procedure ungettemp(list: TAsmList; const ref : treference);
@@ -109,7 +109,7 @@ unit tgobj;
 
 
           { Allocate space for a local }
           { Allocate space for a local }
           procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
           procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
-          procedure getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference);
+          procedure getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference); virtual;
           procedure UnGetLocal(list: TAsmList; const ref : treference);
           procedure UnGetLocal(list: TAsmList; const ref : treference);
        end;
        end;
        ttgobjclass = class of ttgobj;
        ttgobjclass = class of ttgobj;

+ 11 - 0
rtl/java/jdynarrh.inc

@@ -50,6 +50,17 @@ function fpc_setlength_dynarr_jfloat(aorg, anew: TJFloatArray; deepcopy: boolean
 function fpc_setlength_dynarr_jdouble(aorg, anew: TJDoubleArray; deepcopy: boolean): TJDoubleArray;
 function fpc_setlength_dynarr_jdouble(aorg, anew: TJDoubleArray; deepcopy: boolean): TJDoubleArray;
 function fpc_setlength_dynarr_jobject(aorg, anew: TJObjectArray; deepcopy: boolean; docopy : boolean = true): TJObjectArray;
 function fpc_setlength_dynarr_jobject(aorg, anew: TJObjectArray; deepcopy: boolean; docopy : boolean = true): TJObjectArray;
 
 
+{ array copying helpers }
+
+procedure fpc_copy_jbyte_array(src, dst: TJByteArray);
+procedure fpc_copy_jshort_array(src, dst: TJShortArray);
+procedure fpc_copy_jint_array(src, dst: TJIntArray);
+procedure fpc_copy_jlong_array(src, dst: TJLongArray);
+procedure fpc_copy_jchar_array(src, dst: TJCharArray);
+procedure fpc_copy_jfloat_array(src, dst: TJFloatArray);
+procedure fpc_copy_jdouble_array(src, dst: TJDoubleArray);
+procedure fpc_copy_jobject_array(src, dst: TJObjectArray);
+
 { multi-dimendional setlength routine: all intermediate dimensions are arrays
 { multi-dimendional setlength routine: all intermediate dimensions are arrays
   of arrays, so that's the same for all array kinds. Only the type of the final
   of arrays, so that's the same for all array kinds. Only the type of the final
   dimension matters.
   dimension matters.

+ 16 - 16
rtl/java/system.pp

@@ -128,7 +128,7 @@ function min(a,b : longint) : longint;
 { copying helpers }
 { copying helpers }
 
 
 { also for booleans }
 { also for booleans }
-procedure copy_jbyte_array(src, dst: TJByteArray);
+procedure fpc_copy_jbyte_array(src, dst: TJByteArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -137,7 +137,7 @@ procedure copy_jbyte_array(src, dst: TJByteArray);
   end;
   end;
 
 
 
 
-procedure copy_jshort_array(src, dst: TJShortArray);
+procedure fpc_copy_jshort_array(src, dst: TJShortArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -146,7 +146,7 @@ procedure copy_jshort_array(src, dst: TJShortArray);
   end;
   end;
 
 
 
 
-procedure copy_jint_array(src, dst: TJIntArray);
+procedure fpc_copy_jint_array(src, dst: TJIntArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -155,7 +155,7 @@ procedure copy_jint_array(src, dst: TJIntArray);
   end;
   end;
 
 
 
 
-procedure copy_jlong_array(src, dst: TJLongArray);
+procedure fpc_copy_jlong_array(src, dst: TJLongArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -164,7 +164,7 @@ procedure copy_jlong_array(src, dst: TJLongArray);
   end;
   end;
 
 
 
 
-procedure copy_jchar_array(src, dst: TJCharArray);
+procedure fpc_copy_jchar_array(src, dst: TJCharArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -173,7 +173,7 @@ procedure copy_jchar_array(src, dst: TJCharArray);
   end;
   end;
 
 
 
 
-procedure copy_jfloat_array(src, dst: TJFloatArray);
+procedure fpc_copy_jfloat_array(src, dst: TJFloatArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -182,7 +182,7 @@ procedure copy_jfloat_array(src, dst: TJFloatArray);
   end;
   end;
 
 
 
 
-procedure copy_jdouble_array(src, dst: TJDoubleArray);
+procedure fpc_copy_jdouble_array(src, dst: TJDoubleArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -191,7 +191,7 @@ procedure copy_jdouble_array(src, dst: TJDoubleArray);
   end;
   end;
 
 
 
 
-procedure copy_jobject_array(src, dst: TJObjectArray);
+procedure fpc_copy_jobject_array(src, dst: TJObjectArray);
   var
   var
     i: longint;
     i: longint;
   begin
   begin
@@ -207,7 +207,7 @@ function fpc_setlength_dynarr_jbyte(aorg, anew: TJByteArray; deepcopy: boolean):
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jbyte_array(aorg,anew);
+        fpc_copy_jbyte_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -220,7 +220,7 @@ function fpc_setlength_dynarr_jshort(aorg, anew: TJShortArray; deepcopy: boolean
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jshort_array(aorg,anew);
+        fpc_copy_jshort_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -233,7 +233,7 @@ function fpc_setlength_dynarr_jint(aorg, anew: TJIntArray; deepcopy: boolean): T
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jint_array(aorg,anew);
+        fpc_copy_jint_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -246,7 +246,7 @@ function fpc_setlength_dynarr_jlong(aorg, anew: TJLongArray; deepcopy: boolean):
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jlong_array(aorg,anew);
+        fpc_copy_jlong_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -259,7 +259,7 @@ function fpc_setlength_dynarr_jchar(aorg, anew: TJCharArray; deepcopy: boolean):
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jchar_array(aorg,anew);
+        fpc_copy_jchar_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -272,7 +272,7 @@ function fpc_setlength_dynarr_jfloat(aorg, anew: TJFloatArray; deepcopy: boolean
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jfloat_array(aorg,anew);
+        fpc_copy_jfloat_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -285,7 +285,7 @@ function fpc_setlength_dynarr_jdouble(aorg, anew: TJDoubleArray; deepcopy: boole
     if deepcopy or
     if deepcopy or
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
-        copy_jdouble_array(aorg,anew);
+        fpc_copy_jdouble_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else
@@ -299,7 +299,7 @@ function fpc_setlength_dynarr_jobject(aorg, anew: TJObjectArray; deepcopy: boole
        (length(aorg)<>length(anew)) then
        (length(aorg)<>length(anew)) then
       begin
       begin
         if docopy then
         if docopy then
-          copy_jobject_array(aorg,anew);
+          fpc_copy_jobject_array(aorg,anew);
         result:=anew
         result:=anew
       end
       end
     else
     else