Browse Source

+ support for nested classes in the WPO devirtualisation and VMT
optimization infrastructure (mantis #25869)

git-svn-id: trunk@27167 -

Jonas Maebe 11 years ago
parent
commit
4dfc731bdc
3 changed files with 34 additions and 8 deletions
  1. 1 0
      .gitattributes
  2. 16 8
      compiler/optvirt.pas
  3. 17 0
      tests/webtbs/tw25869.pp

+ 1 - 0
.gitattributes

@@ -13851,6 +13851,7 @@ tests/webtbs/tw25603.pp svneol=native#text/pascal
 tests/webtbs/tw2561.pp svneol=native#text/plain
 tests/webtbs/tw2561.pp svneol=native#text/plain
 tests/webtbs/tw25685.pp svneol=native#text/pascal
 tests/webtbs/tw25685.pp svneol=native#text/pascal
 tests/webtbs/tw25814.pp svneol=native#text/plain
 tests/webtbs/tw25814.pp svneol=native#text/plain
+tests/webtbs/tw25869.pp svneol=native#text/plain
 tests/webtbs/tw2588.pp svneol=native#text/plain
 tests/webtbs/tw2588.pp svneol=native#text/plain
 tests/webtbs/tw2589.pp svneol=native#text/plain
 tests/webtbs/tw2589.pp svneol=native#text/plain
 tests/webtbs/tw2594.pp svneol=native#text/plain
 tests/webtbs/tw2594.pp svneol=native#text/plain

+ 16 - 8
compiler/optvirt.pas

@@ -579,10 +579,10 @@ unit optvirt;
     { helper routines: decompose an object & procdef combo into a unitname, class name and vmtentry number
     { helper routines: decompose an object & procdef combo into a unitname, class name and vmtentry number
       (unit name where the objectdef is declared, class name of the objectdef, vmtentry number of the
       (unit name where the objectdef is declared, class name of the objectdef, vmtentry number of the
        procdef -- procdef does not necessarily belong to objectdef, it may also belong to a descendant
        procdef -- procdef does not necessarily belong to objectdef, it may also belong to a descendant
-       or parent)
+       or parent). classprefix is set in case of nested classes.
     }
     }
 
 
-    procedure defunitclassname(objdef: tobjectdef; out unitname, classname: pshortstring);
+    procedure defunitclassname(objdef: tobjectdef; out unitname, classname: pshortstring; out classprefix: shortstring);
       const
       const
         mainprogname: string[2] = 'P$';
         mainprogname: string[2] = 'P$';
       var
       var
@@ -591,6 +591,12 @@ unit optvirt;
       begin
       begin
         objparentsymtab:=objdef.symtable;
         objparentsymtab:=objdef.symtable;
         mainsymtab:=objparentsymtab.defowner.owner;
         mainsymtab:=objparentsymtab.defowner.owner;
+        classprefix:='';
+        while mainsymtab.symtabletype in [recordsymtable,objectsymtable] do
+          begin
+            classprefix:=mainsymtab.name^+'.'+classprefix;
+            mainsymtab:=mainsymtab.defowner.owner;
+          end;
         { main symtable must be static or global }
         { main symtable must be static or global }
         if not(mainsymtab.symtabletype in [staticsymtable,globalsymtable]) then
         if not(mainsymtab.symtabletype in [staticsymtable,globalsymtable]) then
          internalerror(200204177);
          internalerror(200204177);
@@ -604,9 +610,9 @@ unit optvirt;
       end;
       end;
 
 
 
 
-    procedure defsdecompose(objdef: tobjectdef; procdef: tprocdef; out unitname, classname: pshortstring; out vmtentry: longint);
+    procedure defsdecompose(objdef: tobjectdef; procdef: tprocdef; out unitname, classname: pshortstring; out classprefix: shortstring; out vmtentry: longint);
       begin
       begin
-        defunitclassname(objdef,unitname,classname);
+        defunitclassname(objdef,unitname,classname,classprefix);
         vmtentry:=procdef.extnumber;
         vmtentry:=procdef.extnumber;
         { if it's $ffff, this is not a valid virtual method }
         { if it's $ffff, this is not a valid virtual method }
         if (vmtentry=$ffff) then
         if (vmtentry=$ffff) then
@@ -687,6 +693,7 @@ unit optvirt;
     procedure tprogdevirtinfo.converttreenode(node: tinheritancetreenode; arg: pointer);
     procedure tprogdevirtinfo.converttreenode(node: tinheritancetreenode; arg: pointer);
       var
       var
         i: longint;
         i: longint;
+        classprefix: shortstring;
         unitid, classid: pshortstring;
         unitid, classid: pshortstring;
         unitdevirtinfo: tunitdevirtinfo;
         unitdevirtinfo: tunitdevirtinfo;
         classdevirtinfo: tclassdevirtinfo;
         classdevirtinfo: tclassdevirtinfo;
@@ -698,9 +705,9 @@ unit optvirt;
           fill the vmt's of non-instantiated classes with calls to
           fill the vmt's of non-instantiated classes with calls to
           FPC_ABSTRACTERROR during the optimisation phase
           FPC_ABSTRACTERROR during the optimisation phase
         }
         }
-        defunitclassname(node.def,unitid,classid);
+        defunitclassname(node.def,unitid,classid,classprefix);
         unitdevirtinfo:=addunitifnew(unitid^);
         unitdevirtinfo:=addunitifnew(unitid^);
-        classdevirtinfo:=unitdevirtinfo.addclass(classid^,node.instantiated);
+        classdevirtinfo:=unitdevirtinfo.addclass(classprefix+classid^,node.instantiated);
         if (node.def.vmtentries.count=0) then
         if (node.def.vmtentries.count=0) then
           exit;
           exit;
         for i:=0 to node.def.vmtentries.count-1 do
         for i:=0 to node.def.vmtentries.count-1 do
@@ -1088,6 +1095,7 @@ unit optvirt;
         classdevirtinfo: tclassdevirtinfo;
         classdevirtinfo: tclassdevirtinfo;
         vmtentry: longint;
         vmtentry: longint;
         realobjdef: tobjectdef;
         realobjdef: tobjectdef;
+        classprefix: shortstring;
       begin
       begin
          { if we don't have any devirtualisation info, exit }
          { if we don't have any devirtualisation info, exit }
          if not assigned(funits) then
          if not assigned(funits) then
@@ -1124,7 +1132,7 @@ unit optvirt;
            end;
            end;
 
 
          { get the component names for the class/procdef combo }
          { get the component names for the class/procdef combo }
-         defsdecompose(realobjdef,tprocdef(procdef),unitid,classid,vmtentry);
+         defsdecompose(realobjdef,tprocdef(procdef),unitid,classid,classprefix,vmtentry);
 
 
          { If we don't have information about a particular unit/class/method,
          { If we don't have information about a particular unit/class/method,
            it means that such class cannot be instantiated. So if we are
            it means that such class cannot be instantiated. So if we are
@@ -1143,7 +1151,7 @@ unit optvirt;
          if not assigned(unitdevirtinfo) then
          if not assigned(unitdevirtinfo) then
            exit;
            exit;
          { and for this class? }
          { and for this class? }
-         classdevirtinfo:=unitdevirtinfo.findclass(classid^);
+         classdevirtinfo:=unitdevirtinfo.findclass(classprefix+classid^);
          if not assigned(classdevirtinfo) then
          if not assigned(classdevirtinfo) then
            exit;
            exit;
          if forvmtentry and
          if forvmtentry and

+ 17 - 0
tests/webtbs/tw25869.pp

@@ -0,0 +1,17 @@
+{ %wpoparas=optvmts }
+{ %wpopasses=1 }
+
+{$MODE OBJFPC}
+program test;
+
+type
+   TFoo = class
+    type
+      TSubFoo = class
+      end;
+   end;
+
+begin
+   TFoo.TSubFoo.Create();
+end.
+