Exactly. Some functions are smaller than the code needed to call them, especially in object-oriented language. Consider:
Code:
class foo
{
int m_i;
public:
int get_i() { return i; }
};
The body of get_i would look about like this in assembly:
Code:
foo@get_i@:
mov ecx, [esp+4]
mov eax, [ecx+0] ; offsetof(m_i) = 0
ret
Of these three instructions, two are function overhead. And we haven't even established a proper stack frame. Nor have we (as I think we actually should) preserved ecx.
A call:
Code:
int i = foo.get_i();
Code:
; Save registers?
push &foo
call foo@get_i@
mov [esp-4], eax ; Assuming i is at esp-4
Inlined, the two together become
Code:
mov ecx, &foo ; Probably already there
mov eax, [ecx+0] ; Because mem->mem is not supported
mov [esp-4], eax
Three instructions instead of 6, no jump, and better predictability of register use. In fact, if foo's address is already in a register and if i has its own fixed register, the whole thing becomes a single instruction. Depending on the use of i and the aliasing of the foo object, the variable might be elided completely and the access placed there instead.