mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-12 20:29:23 +02:00
+ support for nested classes in the WPO devirtualisation and VMT
optimization infrastructure (mantis #25869) git-svn-id: trunk@27167 -
This commit is contained in:
parent
80863a8361
commit
4dfc731bdc
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||||
|
@ -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
17
tests/webtbs/tw25869.pp
Normal 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.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user