+ support for nested classes in the WPO devirtualisation and VMT

optimization infrastructure (mantis #25869)

git-svn-id: trunk@27167 -
This commit is contained in:
Jonas Maebe 2014-03-16 19:46:17 +00:00
parent 80863a8361
commit 4dfc731bdc
3 changed files with 34 additions and 8 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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
tests/webtbs/tw25869.pp Normal file
View File

@ -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.