* moved JVM-specific code of tloadvmtaddrnode.pass_1 to njvmmem

* create separate nodes for Objective-C in tloadvmtaddrnode.pass_1
    instead of implicitly relying on the fact that the Objective-C
    ISA field is at the same offset as the VMT of Object-Pascal
    classes
   o translate the resulting loads of ISA field into direct pointer
     accesses, so that even on non-fragile ABI platforms we don't
     go via an indirection (like clang/gcc)

git-svn-id: trunk@30947 -
This commit is contained in:
Jonas Maebe 2015-05-31 16:50:39 +00:00
parent 033c28e5ac
commit 703e31512d
3 changed files with 54 additions and 32 deletions

View File

@ -52,6 +52,7 @@ interface
end;
tjvmloadvmtaddrnode = class(tcgloadvmtaddrnode)
function pass_1: tnode; override;
procedure pass_generate_code; override;
end;
@ -317,6 +318,28 @@ implementation
TJVMLOADVMTADDRNODE
*****************************************************************************}
function tjvmloadvmtaddrnode.pass_1: tnode;
var
vs: tsym;
begin
result:=nil;
if is_javaclass(left.resultdef) and
(left.nodetype<>typen) and
(left.resultdef.typ<>classrefdef) then
begin
{ call java.lang.Object.getClass() }
vs:=search_struct_member(tobjectdef(left.resultdef),'GETCLASS');
if not assigned(vs) or
(tsym(vs).typ<>procsym) then
internalerror(2011041901);
result:=ccallnode.create(nil,tprocsym(vs),vs.owner,left,[]);
inserttypeconv_explicit(result,resultdef);
{ reused }
left:=nil;
end;
end;
procedure tjvmloadvmtaddrnode.pass_generate_code;
begin
current_asmdata.CurrAsmList.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(

View File

@ -153,7 +153,7 @@ implementation
globtype,systems,constexp,
cutils,verbose,globals,
symconst,symbase,defutil,defcmp,
nbas,ninl,nutils,
nbas,ninl,nutils,objcutil,
wpobase,
{$ifdef i8086}
cpuinfo,
@ -248,39 +248,26 @@ implementation
include(current_procinfo.flags,pi_needs_got);
if left.nodetype<>typen then
begin
if (target_info.system=system_aarch64_darwin) and
(is_objc_class_or_protocol(left.resultdef) or
if (is_objc_class_or_protocol(left.resultdef) or
is_objcclassref(left.resultdef)) then
begin
{ on Darwin/AArch64, the isa field is opaque and we must
call Object_getClass to obtain the actual ISA pointer }
result:=ccallnode.createinternfromunit('OBJC','OBJECT_GETCLASS',ccallparanode.create(left,nil));
inserttypeconv_explicit(result,resultdef);
{ reused }
left:=nil;
end
else if is_javaclass(left.resultdef) and
(left.nodetype<>typen) and
(left.resultdef.typ<>classrefdef) then
begin
{ call java.lang.Object.getClass() }
vs:=search_struct_member(tobjectdef(left.resultdef),'GETCLASS');
if not assigned(vs) or
(tsym(vs).typ<>procsym) then
internalerror(2011041901);
result:=ccallnode.create(nil,tprocsym(vs),vs.owner,left,[]);
inserttypeconv_explicit(result,resultdef);
if target_info.system=system_aarch64_darwin then
begin
{ on Darwin/AArch64, the isa field is opaque and we must
call Object_getClass to obtain the actual ISA pointer }
result:=ccallnode.createinternfromunit('OBJC','OBJECT_GETCLASS',ccallparanode.create(left,nil));
inserttypeconv_explicit(result,resultdef);
end
else
result:=objcloadbasefield(left,'ISA');
{ reused }
left:=nil;
end
else
firstpass(left)
firstpass(left);
end
else if not is_objcclass(left.resultdef) and
not is_objcclassref(left.resultdef) and
not is_javaclass(left.resultdef) and
not is_javaclassref(left.resultdef) and
not is_javainterface(left.resultdef) then
not is_objcclassref(left.resultdef) then
begin
if not(nf_ignore_for_wpo in flags) and
(not assigned(current_procinfo) or

View File

@ -45,6 +45,10 @@ interface
{ Exports all assembler symbols related to the obj-c class }
procedure exportobjcclass(def: tobjectdef);
{ loads a field of an Objective-C root class (such as ISA) }
function objcloadbasefield(n: tnode; const fieldname: string): tnode;
implementation
uses
@ -112,12 +116,23 @@ end;
var
vs : tsym;
begin
result:=cderefnode.create(ctypeconvnode.create_internal(n,objc_idtype));
vs:=tsym(tabstractrecorddef(objc_objecttype).symtable.Find(fieldname));
if not assigned(vs) or
(vs.typ<>fieldvarsym) then
internalerror(200911301);
result:=csubscriptnode.create(vs,result);
if fieldname='ISA' then
result:=ctypeconvnode.create_internal(
cderefnode.create(
ctypeconvnode.create_internal(n,
getpointerdef(getpointerdef(voidpointertype))
)
),tfieldvarsym(vs).vardef
)
else
begin
result:=cderefnode.create(ctypeconvnode.create_internal(n,objc_idtype));
result:=csubscriptnode.create(vs,result);
end;
end;
@ -147,10 +162,7 @@ end;
{$endif onlymacosx10_6 or arm aarch64}
result:=cloadvmtaddrnode.create(ctypenode.create(tobjectdef(tclassrefdef(def).pointeddef).childof.childof));
tloadvmtaddrnode(result).forcall:=true;
if target_info.system<>system_aarch64_darwin then
result:=objcloadbasefield(result,'ISA')
else
result:=cloadvmtaddrnode.create(result);
result:=cloadvmtaddrnode.create(result);
typecheckpass(result);
{ we're done }
exit;