mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-16 09:59:17 +02:00
* keep track of the number of abstract methods per class via a counter
* use this counter to mark classes containing abstract methods as "abstract" in the bytecode per the JVM spec * also use the counter to short-circuit printing of all abstract methods in a class when creating a new instance (we build the list of abstract methods every time a new instance is created, which is a waste of time if there are none in the first place) git-svn-id: branches/jvmbackend@18635 -
This commit is contained in:
parent
92fbbcff88
commit
6154f1b0d9
@ -570,7 +570,8 @@ implementation
|
|||||||
AsmWrite('.class ');
|
AsmWrite('.class ');
|
||||||
if oo_is_sealed in tobjectdef(obj).objectoptions then
|
if oo_is_sealed in tobjectdef(obj).objectoptions then
|
||||||
AsmWrite('final ');
|
AsmWrite('final ');
|
||||||
if oo_is_abstract in tobjectdef(obj).objectoptions then
|
if (oo_is_abstract in tobjectdef(obj).objectoptions) or
|
||||||
|
(tobjectdef(obj).abstractcnt<>0) then
|
||||||
AsmWrite('abstract ');
|
AsmWrite('abstract ');
|
||||||
if toplevelowner.symtabletype=globalsymtable then
|
if toplevelowner.symtabletype=globalsymtable then
|
||||||
AsmWrite('public ');
|
AsmWrite('public ');
|
||||||
|
@ -2456,6 +2456,9 @@ implementation
|
|||||||
end;
|
end;
|
||||||
if not assigned(objectdf) then
|
if not assigned(objectdf) then
|
||||||
exit;
|
exit;
|
||||||
|
{ quick exit if nothing to check }
|
||||||
|
if objectdf.abstractcnt = 0 then
|
||||||
|
exit;
|
||||||
|
|
||||||
parents := tlinkedlist.create;
|
parents := tlinkedlist.create;
|
||||||
AbstractMethodsList := TFPHashList.create;
|
AbstractMethodsList := TFPHashList.create;
|
||||||
|
@ -384,6 +384,12 @@ implementation
|
|||||||
vmtentryvis:=pd.visibility;
|
vmtentryvis:=pd.visibility;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ in case we are overriding an abstract method,
|
||||||
|
decrease the number of abstract methods in this class }
|
||||||
|
if (po_overridingmethod in pd.procoptions) and
|
||||||
|
(po_abstractmethod in vmtpd.procoptions) then
|
||||||
|
dec(tobjectdef(pd.owner.defowner).abstractcnt);
|
||||||
|
|
||||||
{ override old virtual method in VMT }
|
{ override old virtual method in VMT }
|
||||||
if updatevalues then
|
if updatevalues then
|
||||||
begin
|
begin
|
||||||
|
@ -1667,7 +1667,11 @@ begin
|
|||||||
(oo_is_sealed in tprocdef(pd).struct.objectoptions) then
|
(oo_is_sealed in tprocdef(pd).struct.objectoptions) then
|
||||||
Message(parser_e_sealed_class_cannot_have_abstract_methods)
|
Message(parser_e_sealed_class_cannot_have_abstract_methods)
|
||||||
else if (po_virtualmethod in pd.procoptions) then
|
else if (po_virtualmethod in pd.procoptions) then
|
||||||
include(pd.procoptions,po_abstractmethod)
|
begin
|
||||||
|
include(pd.procoptions,po_abstractmethod);
|
||||||
|
{ one more abstract method }
|
||||||
|
inc(tobjectdef(pd.owner.defowner).abstractcnt);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
Message(parser_e_only_virtual_methods_abstract);
|
Message(parser_e_only_virtual_methods_abstract);
|
||||||
{ the method is defined }
|
{ the method is defined }
|
||||||
|
@ -43,7 +43,7 @@ type
|
|||||||
{$endif Test_Double_checksum}
|
{$endif Test_Double_checksum}
|
||||||
|
|
||||||
const
|
const
|
||||||
CurrentPPUVersion = 136;
|
CurrentPPUVersion = 137;
|
||||||
|
|
||||||
{ buffer sizes }
|
{ buffer sizes }
|
||||||
maxentrysize = 1024;
|
maxentrysize = 1024;
|
||||||
|
@ -284,6 +284,10 @@ interface
|
|||||||
iidstr : pshortstring;
|
iidstr : pshortstring;
|
||||||
{ store implemented interfaces defs and name mappings }
|
{ store implemented interfaces defs and name mappings }
|
||||||
ImplementedInterfaces : TFPObjectList;
|
ImplementedInterfaces : TFPObjectList;
|
||||||
|
{ number of abstract methods (used by JVM target to determine whether
|
||||||
|
or not the class should be marked as abstract: must be done if 1 or
|
||||||
|
more abstract methods) }
|
||||||
|
abstractcnt : longint;
|
||||||
writing_class_record_dbginfo,
|
writing_class_record_dbginfo,
|
||||||
{ a class of this type has been created in this module }
|
{ a class of this type has been created in this module }
|
||||||
created_in_current_module,
|
created_in_current_module,
|
||||||
@ -4902,6 +4906,7 @@ implementation
|
|||||||
ppufile.getguid(iidguid^);
|
ppufile.getguid(iidguid^);
|
||||||
iidstr:=stringdup(ppufile.getstring);
|
iidstr:=stringdup(ppufile.getstring);
|
||||||
end;
|
end;
|
||||||
|
abstractcnt:=ppufile.getlongint;
|
||||||
|
|
||||||
if objecttype=odt_helper then
|
if objecttype=odt_helper then
|
||||||
ppufile.getderef(extendeddefderef);
|
ppufile.getderef(extendeddefderef);
|
||||||
@ -5038,6 +5043,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
if assigned(iidstr) then
|
if assigned(iidstr) then
|
||||||
tobjectdef(result).iidstr:=stringdup(iidstr^);
|
tobjectdef(result).iidstr:=stringdup(iidstr^);
|
||||||
|
tobjectdef(result).abstractcnt:=abstractcnt;
|
||||||
if assigned(ImplementedInterfaces) then
|
if assigned(ImplementedInterfaces) then
|
||||||
begin
|
begin
|
||||||
for i:=0 to ImplementedInterfaces.count-1 do
|
for i:=0 to ImplementedInterfaces.count-1 do
|
||||||
@ -5084,6 +5090,7 @@ implementation
|
|||||||
ppufile.putguid(iidguid^);
|
ppufile.putguid(iidguid^);
|
||||||
ppufile.putstring(iidstr^);
|
ppufile.putstring(iidstr^);
|
||||||
end;
|
end;
|
||||||
|
ppufile.putlongint(abstractcnt);
|
||||||
if objecttype=odt_helper then
|
if objecttype=odt_helper then
|
||||||
ppufile.putderef(extendeddefderef);
|
ppufile.putderef(extendeddefderef);
|
||||||
|
|
||||||
@ -5313,6 +5320,8 @@ implementation
|
|||||||
exit;
|
exit;
|
||||||
{ inherit options and status }
|
{ inherit options and status }
|
||||||
objectoptions:=objectoptions+(c.objectoptions*inherited_objectoptions);
|
objectoptions:=objectoptions+(c.objectoptions*inherited_objectoptions);
|
||||||
|
{ initially has the same number of abstract methods as the parent }
|
||||||
|
abstractcnt:=c.abstractcnt;
|
||||||
{ add the data of the anchestor class/object }
|
{ add the data of the anchestor class/object }
|
||||||
if (objecttype in [odt_class,odt_object,odt_objcclass,odt_javaclass]) then
|
if (objecttype in [odt_class,odt_object,odt_objcclass,odt_javaclass]) then
|
||||||
begin
|
begin
|
||||||
|
@ -2055,6 +2055,8 @@ begin
|
|||||||
writeln(space,' IID String : ',getstring);
|
writeln(space,' IID String : ',getstring);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
writeln(space,' Abstract methods : ',getlongint);
|
||||||
|
|
||||||
if (tobjecttyp(b)=odt_helper) or
|
if (tobjecttyp(b)=odt_helper) or
|
||||||
(oo_is_classhelper in current_objectoptions) then
|
(oo_is_classhelper in current_objectoptions) then
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user