浏览代码

* generate a loadvmtaddrnode wrapper around Java objectdef typenode arguments
to tasnode (like for regular Object Pascal classes)
* don't collect WPO information for Java classes in tloadvmtaddrnode.pass_1()
(devirtualization can't work for Java, since classes can always be loaded
at run time, except for final/sealed classes -- but that's not yet
implemented)
+ JVM is-node support, unified JVM type checking codegen for is- and as-nodes

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

Jonas Maebe 14 年之前
父节点
当前提交
fde622e050
共有 3 个文件被更改,包括 103 次插入27 次删除
  1. 99 25
      compiler/jvm/njvmcnv.pas
  2. 2 1
      compiler/ncnv.pas
  3. 2 1
      compiler/nmem.pas

+ 99 - 25
compiler/jvm/njvmcnv.pas

@@ -62,6 +62,14 @@ interface
          procedure pass_generate_code; override;
        end;
 
+       tjvmisnode = class(tisnode)
+        protected
+         function target_specific_typecheck: boolean;override;
+        public
+         function pass_1 : tnode;override;
+         procedure pass_generate_code; override;
+       end;
+
 implementation
 
    uses
@@ -420,7 +428,10 @@ implementation
                 not is_dynamic_array(fromdef)) or
                (todef<>java_jlobject) then
               begin
-                result:=casnode.create(left,ctypenode.create(resultdef));
+                result:=ctypenode.create(resultdef);
+                if resultdef.typ=objectdef then
+                  result:=cloadvmtaddrnode.create(result);
+                result:=casnode.create(left,result);
                 left:=nil;
               end;
             exit;
@@ -462,30 +473,31 @@ implementation
         CGMessage2(type_e_illegal_type_conversion,left.resultdef.typename,resultdef.typename);
       end;
 
+
     {*****************************************************************************
-                                 TJVMAsNode
+                         AsNode and IsNode common helpers
     *****************************************************************************}
 
-  function tjvmasnode.target_specific_typecheck: boolean;
+  function asis_target_specific_typecheck(node: tasisnode): boolean;
     var
       fromelt, toelt: tdef;
     begin
       { dynamic arrays can be converted to java.lang.Object and vice versa }
-      if right.resultdef=java_jlobject then
+      if node.right.resultdef=java_jlobject then
         { dynamic array to java.lang.Object }
-        result:=is_dynamic_array(left.resultdef)
-      else if is_dynamic_array(right.resultdef) then
+        result:=is_dynamic_array(node.left.resultdef)
+      else if is_dynamic_array(node.right.resultdef) then
         begin
           { <x> to dynamic array: only if possibly valid }
-          fromelt:=left.resultdef;
-          toelt:=right.resultdef;
+          fromelt:=node.left.resultdef;
+          toelt:=node.right.resultdef;
           get_most_nested_types(fromelt,toelt);
           { final levels must be convertable:
               a) from dynarray to java.lang.Object or vice versa, or
               b) the same primitive/class type
           }
           result:=
-           (compare_defs(fromelt,toelt,left.nodetype) in [te_exact,te_equal]) or
+           (compare_defs(fromelt,toelt,node.left.nodetype) in [te_exact,te_equal]) or
            (((fromelt.typ=objectdef) or
              is_dynamic_array(fromelt)) and
             ((toelt.typ=objectdef) or
@@ -495,12 +507,58 @@ implementation
         begin
           { full class reference support requires using the Java reflection API,
             not yet implemented }
-          if (right.nodetype<>typen) then
+          if (node.right.nodetype<>loadvmtaddrn) or
+             (tloadvmtaddrnode(node.right).left.nodetype<>typen) then
             internalerror(2011012601);
           result:=false;
         end;
       if result then
-        resultdef:=right.resultdef;
+        if node.nodetype=asn then
+          begin
+            if node.right.resultdef.typ<>classrefdef then
+              node.resultdef:=node.right.resultdef
+            else
+              node.resultdef:=tclassrefdef(node.right.resultdef).pointeddef
+          end
+        else
+          node.resultdef:=pasbool8type;
+    end;
+
+
+  procedure asis_generate_code(node: tasisnode; opcode: tasmop);
+    var
+      checkdef: tdef;
+    begin
+      secondpass(node.left);
+      thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,node.left.resultdef,node.left.location);
+      location_freetemp(current_asmdata.CurrAsmList,node.left.location);
+      { Perform a checkcast instruction, which will raise an exception in case
+        the actual type does not match/inherit from the expected type.
+
+        Object types need the full type name (package+class name), arrays only
+        the array definition }
+      if node.nodetype=asn then
+        checkdef:=node.resultdef
+      else if node.right.resultdef.typ=classrefdef then
+        checkdef:=tclassrefdef(node.right.resultdef).pointeddef
+      else
+        checkdef:=node.right.resultdef;
+      if checkdef.typ=objectdef then
+        current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(tobjectdef(checkdef).jvm_full_typename(true))))
+      else
+        current_asmdata.CurrAsmList.concat(taicpu.op_sym(opcode,current_asmdata.RefAsmSymbol(jvmencodetype(checkdef))));
+      location_reset(node.location,LOC_REGISTER,OS_ADDR);
+      node.location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,node.resultdef);
+      thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,node.resultdef,node.location.register);
+    end;
+
+    {*****************************************************************************
+                                 TJVMAsNode
+    *****************************************************************************}
+
+  function tjvmasnode.target_specific_typecheck: boolean;
+    begin
+      result:=asis_target_specific_typecheck(self);
     end;
 
 
@@ -509,6 +567,8 @@ implementation
       { call-by-reference does not exist in Java, so it's no problem to
         change a memory location to a register }
       firstpass(left);
+      if right.nodetype<>typen then
+        firstpass(right);
       expectloc:=LOC_REGISTER;
       result:=nil;
     end;
@@ -516,21 +576,34 @@ implementation
 
   procedure tjvmasnode.pass_generate_code;
     begin
-      secondpass(left);
-      thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,resultdef,left.location);
-      location_freetemp(current_asmdata.CurrAsmList,left.location);
-      { Perform a checkcast instruction, which will raise an exception in case
-        the actual type does not match/inherit from the expected type.
+      asis_generate_code(self,a_checkcast);
+    end;
 
-        Object types need the full type name (package+class name), arrays only
-        the array definition }
-      if resultdef.typ=objectdef then
-        current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_checkcast,current_asmdata.RefAsmSymbol(tobjectdef(resultdef).jvm_full_typename)))
-      else
-        current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_checkcast,current_asmdata.RefAsmSymbol(jvmencodetype(resultdef))));
-      location_reset(location,LOC_REGISTER,OS_ADDR);
-      location.register:=hlcg.getaddressregister(current_asmdata.CurrAsmList,resultdef);
-      thlcgjvm(hlcg).a_load_stack_reg(current_asmdata.CurrAsmList,resultdef,location.register);
+
+  {*****************************************************************************
+                               TJVMIsNode
+  *****************************************************************************}
+
+
+  function tjvmisnode.target_specific_typecheck: boolean;
+    begin
+      result:=asis_target_specific_typecheck(self);
+    end;
+
+
+  function tjvmisnode.pass_1: tnode;
+    begin
+      firstpass(left);
+      if right.nodetype<>typen then
+        firstpass(right);
+      expectloc:=LOC_REGISTER;
+      result:=nil;
+    end;
+
+
+  procedure tjvmisnode.pass_generate_code;
+    begin
+      asis_generate_code(self,a_instanceof);
     end;
 
 
@@ -539,4 +612,5 @@ implementation
 begin
   ctypeconvnode:=tjvmtypeconvnode;
   casnode:=tjvmasnode;
+  cisnode:=tjvmisnode;
 end.

+ 2 - 1
compiler/ncnv.pas

@@ -3364,7 +3364,8 @@ implementation
                 { relation checks are not possible }
               end
             { or left must be a class }
-            else if is_class(left.resultdef) then
+            else if is_class(left.resultdef) or
+                    is_javaclass(left.resultdef) then
               begin
                 { the operands must be related }
                 if (not(tobjectdef(left.resultdef).is_related(

+ 2 - 1
compiler/nmem.pas

@@ -239,7 +239,8 @@ implementation
                firstpass(left)
            end
          else if not is_objcclass(left.resultdef) and
-                 not is_objcclassref(left.resultdef) then
+                 not is_objcclassref(left.resultdef) and
+                 not is_javaclass(left.resultdef) then
            begin
              if not(nf_ignore_for_wpo in flags) and
                 (not assigned(current_procinfo) or