注意上面箭头处是被内联化了的isFn2()代码。内联函数
可以看到对于函数指针变量pf的调用call *%esi,说明这个地方仍然是无法被内联化的。
通过函数指针调用的函数不能内联化,因此通过基类指针调用的多态函数自然也就无法被内联化,因为多态函数实际是通过虚函数表和偏移项来定位实际调用的函数指针,然后通过这个函数指针访问实际的函数代码。
通过函数指针调用的函数甚至也是不可能被优化消除的。
举个例子:
class A{
public:
void virtual fn(){}
};
class SubA:public A{
public:
void virtual fn(){}
};
int main(){
SubA suba;
A* a=&suba;
a->fn();
}
这段代码在O3优化下,汇编为:
00000014 <_main>: 14: 55 push %ebp 15: 89 e5 mov %esp,%ebp 17: 83 e4 f0 and $0xfffffff0,%esp 1a: 83 ec 20 sub $0x20,%esp 1d: e8 00 00 00 00 call 22 <_main+0xe> 22: c7 44 24 1c 08 00 00 movl $0x8,0x1c(%esp) 29: 00 2a: 8d 44 24 1c lea 0x1c(%esp),%eax 2e: 89 04 24 mov %eax,(%esp) 31: ff 15 08 00 00 00 call *0x8 37: 31 c0 xor %eax,%eax 39: c9 leave 3a: c3 ret 3b: 90 nop
可以看到函数fn()仍然通过虚表的虚函数指针被调用(call *0x8).
而如果代码
int main(){
SubA suba;

A* a=&suba;
a->fn();
} 换为:
int main(){
SubA suba;
SubA* a=&suba;
a->fn();
}
则对应的O3优化为:
00000014 <_main>: 14: 55 push %ebp 15: 89 e5 mov %esp,%ebp 17: 83 e4 f0 and $0xfffffff0,%esp 1a: e8 00 00 00 00 call 1f <_main+0xb> 1f: 31 c0 xor %eax,%eax 21: c9 leave 22: c3 ret 23: 90 nop
上面可以看到O3将 a->fn()的调用完全优化清除掉了。
根据文章开头所给链接的文章提到,Java能运行时动态将基类指针的多态调用替换成内联,那么有个疑问,对于这样逻辑的代码:
for(int i=0;i<1000;i++) {
base=get RandomBaseOrChild();
base.fn();
}
java又如何能做到动态内联呢?
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-34432-5.html
反向营销
然后对伊拉克说虽然自己根本不愿意也没能力负责伊拉克一辈子
晒出来啊