* 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 '); 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 ');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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