瀏覽代碼

* fixed calling non-static class methods via procvars: since we can't known
on the caller side whether it's a normal or class method that we are
calling, add the self-class parameter inside the invoke method if
necessary (by simply counting the number of parameters and inserting
it if we're one short)

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

Jonas Maebe 14 年之前
父節點
當前提交
249b56d742
共有 3 個文件被更改,包括 65 次插入15 次删除
  1. 3 2
      compiler/jvm/njvmcnv.pas
  2. 57 10
      rtl/java/jpvar.inc
  3. 5 3
      rtl/java/jpvarh.inc

+ 3 - 2
compiler/jvm/njvmcnv.pas

@@ -394,8 +394,9 @@ implementation
         for i:=procdef.paras.count-1 downto 0 do
         for i:=procdef.paras.count-1 downto 0 do
           begin
           begin
             pvs:=tparavarsym(procdef.paras[i]);
             pvs:=tparavarsym(procdef.paras[i]);
-            { self is deal with via the "inst" parameter }
-            if vo_is_self in pvs.varoptions then
+            { self is is an implicit parameter for normal methods }
+            if (vo_is_self in pvs.varoptions) and
+               not(po_classmethod in procdef.procoptions) then
               continue;
               continue;
             { in case of an arraydef, pass by jlclass.forName() to get the classdef
             { in case of an arraydef, pass by jlclass.forName() to get the classdef
               (could be optimized by adding support to loadvmtaddrnode to also deal
               (could be optimized by adding support to loadvmtaddrnode to also deal

+ 57 - 10
rtl/java/jpvar.inc

@@ -46,6 +46,19 @@
     end;
     end;
 
 
 
 
+  function FpcBaseProcVarType.getClassProcArgs(const args: array of jlobject): TJLObjectDynArray;
+    var
+      arglen: longint;
+    begin
+      { add the self pointer as first argument (Java class methods don't take an
+        implicit self parameters, Pascal ones do) }
+      arglen:=length(args);
+      setlength(result,arglen+1);
+      JLSystem.ArrayCopy(JLObject(@args),0,JLObject(result),1,arglen);
+      result[0]:=method.data;
+    end;
+
+
   procedure FpcBaseProcVarType.fpcDeepCopy(result: FpcBaseProcVarType);
   procedure FpcBaseProcVarType.fpcDeepCopy(result: FpcBaseProcVarType);
     begin
     begin
       result.method:=method;
       result.method:=method;
@@ -61,61 +74,95 @@
 
 
   procedure FpcBaseProcVarType.invokeProc(const args: array of jlobject);
   procedure FpcBaseProcVarType.invokeProc(const args: array of jlobject);
     begin
     begin
-      method.code.invoke(method.data,args);
+      { caching the length would be faster, but that would have to be done
+        in a synchronised way. Doing it at construction time and in fpcDeepCopy/
+        clone is not enough, because the method field can be manipulated
+        directly }
+      if length(method.code.getParameterTypes)=length(args) then
+        method.code.invoke(method.data,args)
+      else
+        method.code.invoke(method.data,getClassProcArgs(args));
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeBooleanFunc(const args: array of jlobject): jboolean;
   function FpcBaseProcVarType.invokeBooleanFunc(const args: array of jlobject): jboolean;
     begin
     begin
-      result:=JLBoolean(method.code.invoke(method.data,args)).booleanValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLBoolean(method.code.invoke(method.data,args)).booleanValue
+      else
+        result:=JLBoolean(method.code.invoke(method.data,getClassProcArgs(args))).booleanValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeCharFunc(const args: array of jlobject): jchar;
   function FpcBaseProcVarType.invokeCharFunc(const args: array of jlobject): jchar;
     begin
     begin
-      result:=JLCharacter(method.code.invoke(method.data,args)).charValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLCharacter(method.code.invoke(method.data,args)).charValue
+      else
+        result:=JLCharacter(method.code.invoke(method.data,getClassProcArgs(args))).charValue;
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeByteFunc(const args: array of jlobject): jbyte;
   function FpcBaseProcVarType.invokeByteFunc(const args: array of jlobject): jbyte;
     begin
     begin
-      result:=JLByte(method.code.invoke(method.data,args)).byteValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLByte(method.code.invoke(method.data,args)).byteValue
+      else
+        result:=JLByte(method.code.invoke(method.data,getClassProcArgs(args))).byteValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeShortFunc(const args: array of jlobject): jshort;
   function FpcBaseProcVarType.invokeShortFunc(const args: array of jlobject): jshort;
     begin
     begin
-      result:=JLShort(method.code.invoke(method.data,args)).shortValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLShort(method.code.invoke(method.data,args)).shortValue
+      else
+        result:=JLShort(method.code.invoke(method.data,getClassProcArgs(args))).shortValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeIntFunc(const args: array of jlobject): jint;
   function FpcBaseProcVarType.invokeIntFunc(const args: array of jlobject): jint;
     begin
     begin
-      result:=JLInteger(method.code.invoke(method.data,args)).intValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLInteger(method.code.invoke(method.data,args)).intValue
+      else
+        result:=JLInteger(method.code.invoke(method.data,getClassProcArgs(args))).intValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeLongFunc(const args: array of jlobject): jlong;
   function FpcBaseProcVarType.invokeLongFunc(const args: array of jlobject): jlong;
     begin
     begin
-      result:=JLLong(method.code.invoke(method.data,args)).longValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLLong(method.code.invoke(method.data,args)).longValue
+      else
+        result:=JLLong(method.code.invoke(method.data,getClassProcArgs(args))).longValue;
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeSingleFunc(const args: array of jlobject): jfloat;
   function FpcBaseProcVarType.invokeSingleFunc(const args: array of jlobject): jfloat;
     begin
     begin
-      result:=JLFloat(method.code.invoke(method.data,args)).floatValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLFloat(method.code.invoke(method.data,args)).floatValue
+      else
+        result:=JLFloat(method.code.invoke(method.data,getClassProcArgs(args))).floatValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeDoubleFunc(const args: array of jlobject): jdouble;
   function FpcBaseProcVarType.invokeDoubleFunc(const args: array of jlobject): jdouble;
     begin
     begin
-      result:=JLDouble(method.code.invoke(method.data,args)).doubleValue;
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=JLDouble(method.code.invoke(method.data,args)).doubleValue
+      else
+        result:=JLDouble(method.code.invoke(method.data,getClassProcArgs(args))).doubleValue
     end;
     end;
 
 
 
 
   function FpcBaseProcVarType.invokeObjectFunc(const args: array of jlobject): jlobject;
   function FpcBaseProcVarType.invokeObjectFunc(const args: array of jlobject): jlobject;
     begin
     begin
-      result:=method.code.invoke(method.data,args);
+      if length(method.code.getParameterTypes)=length(args) then
+        result:=method.code.invoke(method.data,args)
+      else
+        result:=method.code.invoke(method.data,getClassProcArgs(args))
     end;
     end;
 
 
 
 

+ 5 - 3
rtl/java/jpvarh.inc

@@ -34,6 +34,11 @@ type
     function clone: JLObject; override;
     function clone: JLObject; override;
 
 
    strict protected
    strict protected
+    type
+      { TJObjectArray isn't declared here yet }
+      TJLObjectDynArray = array of JLObject;
+
+    function getClassProcArgs(const args: array of jlobject): TJLObjectDynArray;
     procedure invokeProc(const args: array of jlobject); virtual;
     procedure invokeProc(const args: array of jlobject); virtual;
     function invokeBooleanFunc(const args: array of jlobject): jboolean; virtual;
     function invokeBooleanFunc(const args: array of jlobject): jboolean; virtual;
     function invokeCharFunc(const args: array of jlobject): jchar; virtual;
     function invokeCharFunc(const args: array of jlobject): jchar; virtual;
@@ -48,9 +53,6 @@ type
 
 
   FpcBaseNestedProcVarType = class(FpcBaseProcVarType)
   FpcBaseNestedProcVarType = class(FpcBaseProcVarType)
    strict protected
    strict protected
-    type
-      { TJObjectArray isn't declared here yet }
-      TJLObjectDynArray = array of JLObject;
     { add the nestedfpstruct to the list of parameters }
     { add the nestedfpstruct to the list of parameters }
     function getNestedArgs(const args: array of jlobject): TJLObjectDynArray; virtual;
     function getNestedArgs(const args: array of jlobject): TJLObjectDynArray; virtual;
    public
    public