For a trampoline to have no overhead, you need the call to the trampoline to be changed to a call to the underlying function.
That's not an optimization that can easily happen due to the traditional compilation model.
Even if inlining were to happen, you end up with bloat, and few compilers are able to merge similar code like this (which can only happen at link-time, obviously, since the functions might be in different translation units). This optimization is known as ICF, and is not commonly enabled.
In practice I don't think the inliner takes ICF into consideration when deciding whether to inline anyway, so you just end up calling a function that calls another function.
You're talking about C/C++'s compilation model and ABI and there are plenty of others. ICF is a hack to deal with C++'s naive template expansion. There are lots of other languages that don't work that way at all and don't need a linker optimization like that.
For a trampoline to have no overhead, you need the call to the trampoline to be changed to a call to the underlying function.
That's not an optimization that can easily happen due to the traditional compilation model.
Even if inlining were to happen, you end up with bloat, and few compilers are able to merge similar code like this (which can only happen at link-time, obviously, since the functions might be in different translation units). This optimization is known as ICF, and is not commonly enabled.
In practice I don't think the inliner takes ICF into consideration when deciding whether to inline anyway, so you just end up calling a function that calls another function.