mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-06 02:07:19 +01:00
+ support for virtual constructors for the JVM platform. We simply
create a virtual class (factory) method that calls the constructor,
and then let the existing support for virtual class methods handle
everything
git-svn-id: branches/jvmbackend@18710 -
This commit is contained in:
parent
e38cfc307b
commit
1d0388d40a
@ -538,26 +538,36 @@ implementation
|
||||
function tjvmcallnode.pass_1: tnode;
|
||||
var
|
||||
sym: tsym;
|
||||
wrappername: shortstring;
|
||||
begin
|
||||
{ transform procvar calls }
|
||||
if assigned(right) then
|
||||
result:=dispatch_procvar
|
||||
else
|
||||
begin
|
||||
{ replace virtual class method calls in case they may be indirect }
|
||||
{ replace virtual class method and constructor calls in case they may
|
||||
be indirect; make sure we don't replace the callthrough to the
|
||||
original constructor with another call to the wrapper }
|
||||
if (procdefinition.typ=procdef) and
|
||||
([po_classmethod,po_virtualmethod]<=procdefinition.procoptions) and
|
||||
(current_procinfo.procdef.synthetickind<>tsk_callthrough) and
|
||||
((procdefinition.proctypeoption=potype_constructor) or
|
||||
(po_classmethod in procdefinition.procoptions)) and
|
||||
(po_virtualmethod in procdefinition.procoptions) and
|
||||
(methodpointer.nodetype<>loadvmtaddrn) then
|
||||
begin
|
||||
wrappername:=symtableprocentry.name+'__FPCVIRTUALCLASSMETHOD__';
|
||||
sym:=
|
||||
search_struct_member(tobjectdef(procdefinition.owner.defowner),
|
||||
upper(tprocdef(procdefinition).import_name^));
|
||||
wrappername);
|
||||
if not assigned(sym) or
|
||||
(sym.typ<>procsym) then
|
||||
internalerror(2011072801);
|
||||
{ check whether we can simply replace the symtableprocentry, or
|
||||
whether we have to reresolve overloads }
|
||||
if symtableprocentry.ProcdefList.count=1 then
|
||||
whether we have to reresolve overloads -- can never simply
|
||||
replace in case of constructor -> class method call, because
|
||||
constructors have a vmt parameter and class methods don't }
|
||||
if (procdefinition.proctypeoption<>potype_constructor) and
|
||||
(symtableprocentry.ProcdefList.count=1) then
|
||||
begin
|
||||
symtableprocentry:=tprocsym(sym);
|
||||
procdefinition:=tprocdef(symtableprocentry.ProcdefList[0]);
|
||||
|
||||
@ -545,11 +545,56 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
procedure jvm_wrap_virtual_constructor(pd: tprocdef);
|
||||
var
|
||||
wrapperpd: tprocdef;
|
||||
begin
|
||||
{ to avoid having to implement procvar-like support for dynamically
|
||||
invoking constructors, call the constructors from virtual class
|
||||
methods and replace calls to the constructors with calls to the
|
||||
virtual class methods -> we can reuse lots of infrastructure }
|
||||
if (po_external in pd.procoptions) or
|
||||
(oo_is_external in pd.struct.objectoptions) then
|
||||
exit;
|
||||
{ wrapper is part of the same symtable as the original procdef }
|
||||
symtablestack.push(pd.owner);
|
||||
{ get a copy of the constructor }
|
||||
wrapperpd:=tprocdef(pd.getcopyas(procdef,pc_bareproc));
|
||||
{ this one is is a class method rather than a constructor }
|
||||
include(wrapperpd.procoptions,po_classmethod);
|
||||
wrapperpd.proctypeoption:=potype_function;
|
||||
wrapperpd.returndef:=tobjectdef(pd.owner.defowner);
|
||||
|
||||
{ import/external name = name of original constructor (since
|
||||
constructors don't have names in Java, this won't conflict with the
|
||||
original constructor definition) }
|
||||
stringdispose(wrapperpd.import_name);
|
||||
wrapperpd.import_name:=stringdup(pd.procsym.realname);
|
||||
{ associate with wrapper procsym (Pascal-level name = wrapper name ->
|
||||
in callnodes, we will have to replace the calls to virtual
|
||||
constructors with calls to the wrappers) }
|
||||
finish_copied_procdef(wrapperpd,pd.procsym.realname+'__fpcvirtconstrwrapper__',pd.owner,tabstractrecorddef(pd.owner.defowner));
|
||||
{ since it was a bare copy, insert the self parameter (we can't just
|
||||
copy the vmt parameter from the constructor, that's different) }
|
||||
insert_self_and_vmt_para(wrapperpd);
|
||||
wrapperpd.calcparas;
|
||||
{ implementation: call through to the constructor }
|
||||
wrapperpd.synthetickind:=tsk_callthrough;
|
||||
wrapperpd.skpara:=pd;
|
||||
symtablestack.pop(pd.owner);
|
||||
{ and now wrap this generated virtual static method itself as well}
|
||||
jvm_wrap_virtual_class_method(wrapperpd);
|
||||
end;
|
||||
|
||||
|
||||
procedure jvm_wrap_virtual_class_methods(obj: tobjectdef);
|
||||
var
|
||||
i: longint;
|
||||
def: tdef;
|
||||
begin
|
||||
{ new methods will be inserted while we do this, but since
|
||||
symtable.deflist.count is evaluated at the start of the loop that
|
||||
doesn't matter }
|
||||
for i:=0 to obj.symtable.deflist.count-1 do
|
||||
begin
|
||||
def:=tdef(obj.symtable.deflist[i]);
|
||||
@ -557,6 +602,9 @@ implementation
|
||||
continue;
|
||||
if [po_classmethod,po_virtualmethod]<=tprocdef(def).procoptions then
|
||||
jvm_wrap_virtual_class_method(tprocdef(def))
|
||||
else if (tprocdef(def).proctypeoption=potype_constructor) and
|
||||
(po_virtualmethod in tprocdef(def).procoptions) then
|
||||
jvm_wrap_virtual_constructor(tprocdef(def));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user