2
0
Эх сурвалжийг харах

* moved JVM-specific code of tloadvmtaddrnode.pass_1 to njvmmem
* create separate nodes for Objective-C in tloadvmtaddrnode.pass_1
instead of implicitly relying on the fact that the Objective-C
ISA field is at the same offset as the VMT of Object-Pascal
classes
o translate the resulting loads of ISA field into direct pointer
accesses, so that even on non-fragile ABI platforms we don't
go via an indirection (like clang/gcc)

git-svn-id: trunk@30947 -

Jonas Maebe 10 жил өмнө
parent
commit
703e31512d

+ 23 - 0
compiler/jvm/njvmmem.pas

@@ -52,6 +52,7 @@ interface
        end;
 
        tjvmloadvmtaddrnode = class(tcgloadvmtaddrnode)
+         function pass_1: tnode; override;
          procedure pass_generate_code; override;
        end;
 
@@ -317,6 +318,28 @@ implementation
                          TJVMLOADVMTADDRNODE
 *****************************************************************************}
 
+    function tjvmloadvmtaddrnode.pass_1: tnode;
+      var
+        vs: tsym;
+      begin
+        result:=nil;
+        if is_javaclass(left.resultdef) and
+           (left.nodetype<>typen) and
+           (left.resultdef.typ<>classrefdef) then
+          begin
+            { call java.lang.Object.getClass() }
+            vs:=search_struct_member(tobjectdef(left.resultdef),'GETCLASS');
+            if not assigned(vs) or
+               (tsym(vs).typ<>procsym) then
+              internalerror(2011041901);
+            result:=ccallnode.create(nil,tprocsym(vs),vs.owner,left,[]);
+            inserttypeconv_explicit(result,resultdef);
+            { reused }
+            left:=nil;
+          end;
+      end;
+
+
     procedure tjvmloadvmtaddrnode.pass_generate_code;
       begin
         current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(

+ 13 - 26
compiler/nmem.pas

@@ -153,7 +153,7 @@ implementation
       globtype,systems,constexp,
       cutils,verbose,globals,
       symconst,symbase,defutil,defcmp,
-      nbas,ninl,nutils,
+      nbas,ninl,nutils,objcutil,
       wpobase,
 {$ifdef i8086}
       cpuinfo,
@@ -248,39 +248,26 @@ implementation
            include(current_procinfo.flags,pi_needs_got);
          if left.nodetype<>typen then
            begin
-             if (target_info.system=system_aarch64_darwin) and
-                (is_objc_class_or_protocol(left.resultdef) or
+             if (is_objc_class_or_protocol(left.resultdef) or
                  is_objcclassref(left.resultdef)) then
                begin
-                 { on Darwin/AArch64, the isa field is opaque and we must
-                   call Object_getClass to obtain the actual ISA pointer }
-                 result:=ccallnode.createinternfromunit('OBJC','OBJECT_GETCLASS',ccallparanode.create(left,nil));
-                 inserttypeconv_explicit(result,resultdef);
-                 { reused }
-                 left:=nil;
-               end
-             else if is_javaclass(left.resultdef) and
-                (left.nodetype<>typen) and
-                (left.resultdef.typ<>classrefdef) then
-               begin
-                 { call java.lang.Object.getClass() }
-                 vs:=search_struct_member(tobjectdef(left.resultdef),'GETCLASS');
-                 if not assigned(vs) or
-                    (tsym(vs).typ<>procsym) then
-                   internalerror(2011041901);
-                 result:=ccallnode.create(nil,tprocsym(vs),vs.owner,left,[]);
-                 inserttypeconv_explicit(result,resultdef);
+                 if target_info.system=system_aarch64_darwin then
+                   begin
+                     { on Darwin/AArch64, the isa field is opaque and we must
+                       call Object_getClass to obtain the actual ISA pointer }
+                     result:=ccallnode.createinternfromunit('OBJC','OBJECT_GETCLASS',ccallparanode.create(left,nil));
+                     inserttypeconv_explicit(result,resultdef);
+                   end
+                 else
+                   result:=objcloadbasefield(left,'ISA');
                  { reused }
                  left:=nil;
                end
              else
-               firstpass(left)
+               firstpass(left);
            end
          else if not is_objcclass(left.resultdef) and
-                 not is_objcclassref(left.resultdef) and
-                 not is_javaclass(left.resultdef) and
-                 not is_javaclassref(left.resultdef) and
-                 not is_javainterface(left.resultdef) then
+                 not is_objcclassref(left.resultdef) then
            begin
              if not(nf_ignore_for_wpo in flags) and
                 (not assigned(current_procinfo) or

+ 18 - 6
compiler/objcutil.pas

@@ -45,6 +45,10 @@ interface
     { Exports all assembler symbols related to the obj-c class }
     procedure exportobjcclass(def: tobjectdef);
 
+    { loads a field of an Objective-C root class (such as ISA) }
+    function objcloadbasefield(n: tnode; const fieldname: string): tnode;
+
+
 implementation
 
     uses
@@ -112,12 +116,23 @@ end;
       var
         vs         : tsym;
       begin
-        result:=cderefnode.create(ctypeconvnode.create_internal(n,objc_idtype));
         vs:=tsym(tabstractrecorddef(objc_objecttype).symtable.Find(fieldname));
         if not assigned(vs) or
            (vs.typ<>fieldvarsym) then
           internalerror(200911301);
-        result:=csubscriptnode.create(vs,result);
+        if fieldname='ISA' then
+          result:=ctypeconvnode.create_internal(
+            cderefnode.create(
+              ctypeconvnode.create_internal(n,
+                getpointerdef(getpointerdef(voidpointertype))
+              )
+            ),tfieldvarsym(vs).vardef
+          )
+        else
+          begin
+            result:=cderefnode.create(ctypeconvnode.create_internal(n,objc_idtype));
+            result:=csubscriptnode.create(vs,result);
+          end;
       end;
 
 
@@ -147,10 +162,7 @@ end;
 {$endif onlymacosx10_6 or arm aarch64}
                   result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof.childof));
                 tloadvmtaddrnode(result).forcall:=true;
-                if target_info.system<>system_aarch64_darwin then
-                  result:=objcloadbasefield(result,'ISA')
-                else
-                  result:=cloadvmtaddrnode.create(result);
+                result:=cloadvmtaddrnode.create(result);
                 typecheckpass(result);
                 { we're done }
                 exit;