Ver código fonte

* no longer encode all pointers to other pointer types (such as
classes, interfaces, dynamic arrays, ...) as "array of JLObject",
but instead as an array of the actual pointed-to type. The reason
for the previous behaviour was mainly that the JVM threadvar
implementation internally stores all threadvars that are
such double pointer types into an "array of JLObject". Type casting
this array to e.g. an "array of array of byte" causes an exception
even if it only contains "array of byte" instances (since the outer
array type is different). This is now solved by first taking the
element of the array and then typecasting it to the destination
type (so dynarrbyte(arr[0]) instead of pdynarrbyte(arr)^[0]).

The reason for the new (more accurate) behaviour is because the
old one caused type errors in case a double pointer field was
internally created for the nestedfpstruct support (see added
test)

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

Jonas Maebe 13 anos atrás
pai
commit
21e6401921

+ 1 - 0
.gitattributes

@@ -9794,6 +9794,7 @@ tests/test/jvm/testshort.pp svneol=native#text/plain
 tests/test/jvm/tformalpara.pp svneol=native#text/plain
 tests/test/jvm/tint.pp svneol=native#text/plain
 tests/test/jvm/tintstr.pp svneol=native#text/plain
+tests/test/jvm/tnestdynarr.pp svneol=native#text/plain
 tests/test/jvm/tnestedset.pp svneol=native#text/plain
 tests/test/jvm/tnestproc.pp svneol=native#text/plain
 tests/test/jvm/tprop.pp svneol=native#text/plain

+ 3 - 12
compiler/jvm/jvmdef.pas

@@ -265,23 +265,14 @@ implementation
             begin
               if is_voidpointer(def) then
                 result:=jvmaddencodedtype(java_jlobject,false,encodedstr,forcesignature,founderror)
-              else if tpointerdef(def).pointeddef.typ in [orddef,floatdef] then
-                begin
-                  encodedstr:=encodedstr+'[';
-                  result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror);
-                end
               else if jvmimplicitpointertype(tpointerdef(def).pointeddef) then
                 result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror)
               else
                 begin
-                  { Semantically, these are pointers to types that are
-                    pointer-based themselves (or typecastable to pointer).
-                    Internally, we represent them all as array of JLObject so that
-                    they are assignment-compatible. We will perform the type
-                    checks when actually loading a value from them }
+                  { all pointer types are emulated via arrays }
                   encodedstr:=encodedstr+'[';
-                  result:=jvmaddencodedtype(java_jlobject,false,encodedstr,forcesignature,founderror)
-                end;
+                  result:=jvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr,forcesignature,founderror);
+                end
             end;
           floatdef :
             begin

+ 24 - 2
compiler/jvm/njvmld.pas

@@ -197,8 +197,30 @@ function tjvmloadnode.handle_threadvar_access: tnode;
     result:=cloadnode.create(vs,vs.owner);
     typecheckpass(result);
     result:=ccallnode.createinternmethod(result,'GETREADWRITEREFERENCE',nil);
-    result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
-    result:=cderefnode.create(result);
+    if not(tparavarsym(symtableentry).vardef.typ in [orddef,floatdef]) and
+       not jvmimplicitpointertype(tparavarsym(symtableentry).vardef) then
+      begin
+        { in these cases, the threadvar was internally constructed as an
+          "array of jlobject", while the variable itself is a different kind of
+          pointer (dynarmic array, class, interface, pointer type). We cannot
+          typecast an "array of jlobject" to e.g. an "array of array of byte",
+          even if all elements inside the array are "array of byte" (since the
+          outer array type is simply different) -> first dereference (= select
+          the array element) and then typecast to the result type. This works
+          even on the left-hand side because then we get e.g.
+            jlobject(threavarinstance.getreadwritereference^):=value;
+
+          threavarinstance.getreadwritereference returns a ppointer in these
+          cases.
+        }
+        result:=cderefnode.create(result);
+        result:=ctypeconvnode.create_explicit(result,resultdef);
+      end
+    else
+      begin
+        result:=ctypeconvnode.create_explicit(result,getpointerdef(resultdef));
+        result:=cderefnode.create(result);
+      end;
   end;
 
 

+ 4 - 0
tests/test/jvm/testall.bat

@@ -220,4 +220,8 @@ ppcjvm -O2 -g -B tdynarrnil
 if %errorlevel% neq 0 exit /b %errorlevel%
 java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tdynarrnil
 if %errorlevel% neq 0 exit /b %errorlevel%
+ppcjvm -O2 -g -B tnestdynarr
+if %errorlevel% neq 0 exit /b %errorlevel%
+java -Dfile.encoding=UTF-8 -cp ..\..\..\rtl\units\jvm-java;. tnestdynarr
+if %errorlevel% neq 0 exit /b %errorlevel%
 

+ 2 - 0
tests/test/jvm/testall.sh

@@ -120,3 +120,5 @@ $PPC -O2 -g -B tw20212
 java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/jvm-java:. tw20212
 $PPC -O2 -g -B tdynarrnil
 java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/jvm-java:. tdynarrnil
+$PPC -O2 -g -B tnestdynarr
+java -Dfile.encoding=UTF-8 -cp ../../../rtl/units/jvm-java:. tnestdynarr

+ 24 - 0
tests/test/jvm/tnestdynarr.pp

@@ -0,0 +1,24 @@
+program tnestdynarr;
+
+type
+  tbytearray = array of byte;
+
+procedure test(var a: tbytearray);
+
+  procedure nest;
+    begin
+      a[0]:=2;
+    end;
+
+begin
+  nest;
+end;
+
+var
+  a: tbytearray;
+begin
+  setlength(a,1);
+  test(a);
+  if a[0]<>2 then
+    halt(1);
+end.