* 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:
Jonas Maebe 2011-08-20 08:17:12 +00:00
parent 92fbbcff88
commit 6154f1b0d9
7 changed files with 28 additions and 3 deletions

View File

@ -570,7 +570,8 @@ implementation
AsmWrite('.class ');
if oo_is_sealed in tobjectdef(obj).objectoptions then
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 ');
if toplevelowner.symtabletype=globalsymtable then
AsmWrite('public ');

View File

@ -2456,6 +2456,9 @@ implementation
end;
if not assigned(objectdf) then
exit;
{ quick exit if nothing to check }
if objectdf.abstractcnt = 0 then
exit;
parents := tlinkedlist.create;
AbstractMethodsList := TFPHashList.create;

View File

@ -384,6 +384,12 @@ implementation
vmtentryvis:=pd.visibility;
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 }
if updatevalues then
begin

View File

@ -1667,7 +1667,11 @@ begin
(oo_is_sealed in tprocdef(pd).struct.objectoptions) then
Message(parser_e_sealed_class_cannot_have_abstract_methods)
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
Message(parser_e_only_virtual_methods_abstract);
{ the method is defined }

View File

@ -43,7 +43,7 @@ type
{$endif Test_Double_checksum}
const
CurrentPPUVersion = 136;
CurrentPPUVersion = 137;
{ buffer sizes }
maxentrysize = 1024;

View File

@ -284,6 +284,10 @@ interface
iidstr : pshortstring;
{ store implemented interfaces defs and name mappings }
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,
{ a class of this type has been created in this module }
created_in_current_module,
@ -4902,6 +4906,7 @@ implementation
ppufile.getguid(iidguid^);
iidstr:=stringdup(ppufile.getstring);
end;
abstractcnt:=ppufile.getlongint;
if objecttype=odt_helper then
ppufile.getderef(extendeddefderef);
@ -5038,6 +5043,7 @@ implementation
end;
if assigned(iidstr) then
tobjectdef(result).iidstr:=stringdup(iidstr^);
tobjectdef(result).abstractcnt:=abstractcnt;
if assigned(ImplementedInterfaces) then
begin
for i:=0 to ImplementedInterfaces.count-1 do
@ -5084,6 +5090,7 @@ implementation
ppufile.putguid(iidguid^);
ppufile.putstring(iidstr^);
end;
ppufile.putlongint(abstractcnt);
if objecttype=odt_helper then
ppufile.putderef(extendeddefderef);
@ -5313,6 +5320,8 @@ implementation
exit;
{ inherit options and status }
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 }
if (objecttype in [odt_class,odt_object,odt_objcclass,odt_javaclass]) then
begin

View File

@ -2055,6 +2055,8 @@ begin
writeln(space,' IID String : ',getstring);
end;
writeln(space,' Abstract methods : ',getlongint);
if (tobjecttyp(b)=odt_helper) or
(oo_is_classhelper in current_objectoptions) then
begin