From 4dfc731bdccafc8f290f59e209dbcdc8ea9c473d Mon Sep 17 00:00:00 2001 From: Jonas Maebe <jonas@freepascal.org> Date: Sun, 16 Mar 2014 19:46:17 +0000 Subject: [PATCH] + support for nested classes in the WPO devirtualisation and VMT optimization infrastructure (mantis #25869) git-svn-id: trunk@27167 - --- .gitattributes | 1 + compiler/optvirt.pas | 24 ++++++++++++++++-------- tests/webtbs/tw25869.pp | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 tests/webtbs/tw25869.pp diff --git a/.gitattributes b/.gitattributes index ccc6efdb89..9da9f98e01 100644 --- a/.gitattributes +++ b/.gitattributes @@ -13851,6 +13851,7 @@ tests/webtbs/tw25603.pp svneol=native#text/pascal tests/webtbs/tw2561.pp svneol=native#text/plain tests/webtbs/tw25685.pp svneol=native#text/pascal 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/tw2589.pp svneol=native#text/plain tests/webtbs/tw2594.pp svneol=native#text/plain diff --git a/compiler/optvirt.pas b/compiler/optvirt.pas index 15fa7fc197..60922abb5f 100644 --- a/compiler/optvirt.pas +++ b/compiler/optvirt.pas @@ -579,10 +579,10 @@ unit optvirt; { 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 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 mainprogname: string[2] = 'P$'; var @@ -591,6 +591,12 @@ unit optvirt; begin objparentsymtab:=objdef.symtable; 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 } if not(mainsymtab.symtabletype in [staticsymtable,globalsymtable]) then internalerror(200204177); @@ -604,9 +610,9 @@ unit optvirt; 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 - defunitclassname(objdef,unitname,classname); + defunitclassname(objdef,unitname,classname,classprefix); vmtentry:=procdef.extnumber; { if it's $ffff, this is not a valid virtual method } if (vmtentry=$ffff) then @@ -687,6 +693,7 @@ unit optvirt; procedure tprogdevirtinfo.converttreenode(node: tinheritancetreenode; arg: pointer); var i: longint; + classprefix: shortstring; unitid, classid: pshortstring; unitdevirtinfo: tunitdevirtinfo; classdevirtinfo: tclassdevirtinfo; @@ -698,9 +705,9 @@ unit optvirt; fill the vmt's of non-instantiated classes with calls to FPC_ABSTRACTERROR during the optimisation phase } - defunitclassname(node.def,unitid,classid); + defunitclassname(node.def,unitid,classid,classprefix); unitdevirtinfo:=addunitifnew(unitid^); - classdevirtinfo:=unitdevirtinfo.addclass(classid^,node.instantiated); + classdevirtinfo:=unitdevirtinfo.addclass(classprefix+classid^,node.instantiated); if (node.def.vmtentries.count=0) then exit; for i:=0 to node.def.vmtentries.count-1 do @@ -1088,6 +1095,7 @@ unit optvirt; classdevirtinfo: tclassdevirtinfo; vmtentry: longint; realobjdef: tobjectdef; + classprefix: shortstring; begin { if we don't have any devirtualisation info, exit } if not assigned(funits) then @@ -1124,7 +1132,7 @@ unit optvirt; end; { 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, it means that such class cannot be instantiated. So if we are @@ -1143,7 +1151,7 @@ unit optvirt; if not assigned(unitdevirtinfo) then exit; { and for this class? } - classdevirtinfo:=unitdevirtinfo.findclass(classid^); + classdevirtinfo:=unitdevirtinfo.findclass(classprefix+classid^); if not assigned(classdevirtinfo) then exit; if forvmtentry and diff --git a/tests/webtbs/tw25869.pp b/tests/webtbs/tw25869.pp new file mode 100644 index 0000000000..ba0d218b8f --- /dev/null +++ b/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. +