Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function pointers: performance penalty?

47 views
Skip to first unread message

Rui Maciel

unread,
Oct 11, 2009, 11:53:48 AM10/11/09
to
Is there a performance penalty associated with the use of function pointers? If so, how bad is it?


Thanks in advance,
Rui Maciel

Nick Keighley

unread,
Oct 11, 2009, 12:43:04 PM10/11/09
to

yes. Small. Say one extra instruction and extra memory access.

If you don't use a funtion pointer what will you do instead
and is *that* cheaper?

Malcolm McLean

unread,
Oct 11, 2009, 1:07:32 PM10/11/09
to
"Rui Maciel" <rui.m...@gmail.com> wrote in message news:

> Is there a performance penalty associated with the use of function
> pointers? If >so, how bad is it?
>
With an aggressively optimising compiler there shouldn't be much of a
penalty, in typical use.
This is because you use a function pointer to make a function more general.
The classic example form the library is qsort(). Typically this will be used
as

int compfunc(const void *e1, const void *e2)
{
const char **str1 = e1;
const char **str2 = e2;

return strcmp(*str1, *str2);
}

...
qsort(array, N, sizeof(char *), compfunc);
...

So if there is significant penalty in calling a function indirectly, in
machine code, a compiler can replace the indirect jump with a hard-linked
one, or even inline the function totally.
Of course rarely the comparison function will be a variable and not
resolveable at compile time, in which case the call will have to be via an
indirect jump. However the penalty is unlikely to be very large, though it
will be something.


Richard

unread,
Oct 11, 2009, 1:12:39 PM10/11/09
to
Nick Keighley <nick_keigh...@hotmail.com> writes:

You could suggest that it is, in fact, faster for an oft called
function. No 32/64 bit address read required each and every call.

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

Eric Sosman

unread,
Oct 11, 2009, 2:54:14 PM10/11/09
to
Rui Maciel wrote:
> Is there a performance penalty associated with the use of function pointers?

Perhaps. What do your measurements tell you?

> If so, how bad is it?

What do your measurements tell you?

--
Eric Sosman
eso...@ieee-dot-org.invalid

Malcolm McLean

unread,
Oct 11, 2009, 2:58:07 PM10/11/09
to

"Eric Sosman" <eso...@ieee-dot-org.invalid> wrote in message

> Rui Maciel wrote:
>> Is there a performance penalty associated with the use of function
>> pointers?
>
> Perhaps. What do your measurements tell you?
>
>> If so, how bad is it?
>
> What do your measurements tell you?
>
If the code is portable, or even designed to run on different versions of
the same operating system, or on different but binary-compatible hardware,
then that's not a very viable strategy. It will tell you something, but the
figures could change when the Pentium is replaced by the Hexium,.


jacob navia

unread,
Oct 11, 2009, 3:02:52 PM10/11/09
to
Rui Maciel a �crit :

> Is there a performance penalty associated with the use of function pointers? If so, how bad is it?
>
>
> Thanks in advance,
> Rui Maciel

This depends on the CPU, the deep of the pipeline (if any) and many other things.
If there is a pipeline, coupled with speculative execution, an indirect jump
will provoke a flush of the pipeline, since all instructions after the indirect jump
can't be known, unless the value of the jump is loaded very early in the register,
a,d the speculative execution machine can determine it wont be affected by subsequent
operations...

A call instruction has its destination embedded in the code stream. The CPU will know it
in advance and will know that it will not change. Using that knowledge, it can start
executing the call instruction in advance.

Within the context of lcc-win, i was forced to use ALWAYS for all function calls
ONLY indirect calls. This slowed down the code considerably, more than 15-20%.

If you are using the indirect jump within a tight loop, it is better if you
could avoid it, but if you are using an indirect call anyway, it is because of
some reason, and that is not going to change and it is not going to be replaced
by something else.

Seebs

unread,
Oct 11, 2009, 3:07:35 PM10/11/09
to
On 2009-10-11, Malcolm McLean <regn...@btinternet.com> wrote:
> If the code is portable, or even designed to run on different versions of
> the same operating system, or on different but binary-compatible hardware,
> then that's not a very viable strategy. It will tell you something, but the
> figures could change when the Pentium is replaced by the Hexium,.

And for much the same reason, asking people what the performance penalty
is won't do you much better.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Gordon Burditt

unread,
Oct 11, 2009, 3:15:34 PM10/11/09
to
>Is there a performance penalty associated with the use of function
>pointers?

Compared to what?

There is almost always a performance penalty for using code compared
with not using it.

>If so, how bad is it?

About 42.7284756373292183746565465768797462, give or take a few
orders of magnitude.

Nick Keighley

unread,
Oct 11, 2009, 3:18:42 PM10/11/09
to
On 11 Oct, 18:12, Richard <rgrd...@gmail.com> wrote:

> Nick Keighley <nick_keighley_nos...@hotmail.com> writes:
> > On 11 Oct, 16:53, Rui Maciel <rui.mac...@gmail.com> wrote:
>
> >> Is there a performance penalty associated with the use of
> >> function pointers? If so, how bad is it?
>
> >> Thanks in advance,
> >> Rui Maciel
>
> > yes. Small. Say one extra instruction and extra memory access.
>
> > If you don't use a funtion pointer what will you do instead
> > and is *that* cheaper?
>
> You could suggest that it is, in fact, faster for an oft called
> function. No 32/64 bit address read required each and every call.

what? The function address will be sitting in a register?
I'd not thought of that.

Phil Carmody

unread,
Oct 11, 2009, 3:24:24 PM10/11/09
to
Rui Maciel <rui.m...@gmail.com> writes:
> Is there a performance penalty associated with the use of function pointers? If so, how bad is it?

Nope, function pointers are faster.

Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1

Malcolm McLean

unread,
Oct 11, 2009, 3:28:17 PM10/11/09
to

"Seebs" <usenet...@seebs.net> wrote in message

> And for much the same reason, asking people what the performance penalty
> is won't do you much better.
>
A human has got some insight into how a processor works.He can predict the
future to some extent, if an expert. (I'm not, I didn't realise the cache
effects could be so severe as Jacob describes).


jacob navia

unread,
Oct 11, 2009, 3:34:31 PM10/11/09
to
Phil Carmody a �crit :

> Rui Maciel <rui.m...@gmail.com> writes:
>> Is there a performance penalty associated with the use of function pointers? If so, how bad is it?
>
> Nope, function pointers are faster.
>
> Phil

What? AN indirect call using a function pointer is faster than a direct
call?

You are just talking nonsense (as always).

Antoninus Twink

unread,
Oct 11, 2009, 3:49:13 PM10/11/09
to
On 11 Oct 2009 at 19:34, jacob navia wrote:
> Phil Carmody a écrit :

>> Nope, function pointers are faster.
>
> What? AN indirect call using a function pointer is faster than a direct
> call?
>
> You are just talking nonsense (as always).

Yes.

"Phil" is obviously clueless - a couple days ago he showed us all that
he doesn't know what a heap is, now we learn that he's completely
ignorant about function pointers too.

All Carmodey brings to this group is a sycophantic blind support for
Heathfield, and a lot of bile directed against anyone and everyone who
dares to point out how inadequate his purported knowledge of C is.

Gordon Burditt

unread,
Oct 11, 2009, 3:53:14 PM10/11/09
to
>Within the context of lcc-win, i was forced to use ALWAYS for all function calls
>ONLY indirect calls.

Why? What would force you to do that?

Seebs

unread,
Oct 11, 2009, 4:47:20 PM10/11/09
to
On 2009-10-11, jacob navia <ja...@nospam.org> wrote:
> What? AN indirect call using a function pointer is faster than a direct
> call?

> You are just talking nonsense (as always).

It's actually not totally impossible in at least one fairly common case.

Imagine that you are in the fairly normal case on a modern system where
many functions you call are reached through dynamically-linked libraries.
When you call such a function, you actually call through a little bit of
dummy code which makes sure the right library is loaded and then rewrites
itself to be a jump to the correct function. However, if you have obtained
a pointer to the function, you may well have a pointer to the "real" function
-- the actual address at which something was loaded. In which case the call
through the function pointer may be one step faster.

I don't think it makes sense to try to come up with a general answer. The
indirect call and direct call are not intrinsically different; ultimately,
a "direct" call is still a call through a pointer anyway.

Seebs

unread,
Oct 11, 2009, 4:47:44 PM10/11/09
to
On 2009-10-11, Antoninus Twink <nos...@nospam.invalid> wrote:
> All Carmodey brings to this group is a sycophantic blind support for
> Heathfield, and a lot of bile directed against anyone and everyone who
> dares to point out how inadequate his purported knowledge of C is.

Wow, he sure pissed in your anonymous cheerios!

Seebs

unread,
Oct 11, 2009, 4:48:35 PM10/11/09
to
On 2009-10-11, Malcolm McLean <regn...@btinternet.com> wrote:
> A human has got some insight into how a processor works.He can predict the
> future to some extent, if an expert. (I'm not, I didn't realise the cache
> effects could be so severe as Jacob describes).

On OOO processors, I'm told, it's quite common for it to be impossible to
know until runtime which of two things will be faster in a given case...

Stephen Sprunk

unread,
Oct 11, 2009, 4:52:20 PM10/11/09
to
Nick Keighley wrote:
> On 11 Oct, 18:12, Richard <rgrd...@gmail.com> wrote:
>> Nick Keighley <nick_keighley_nos...@hotmail.com> writes:
>>> On 11 Oct, 16:53, Rui Maciel <rui.mac...@gmail.com> wrote:
>>>> Is there a performance penalty associated with the use of
>>>> function pointers? If so, how bad is it?
>>>
>>> yes. Small. Say one extra instruction and extra memory access.
>>> If you don't use a funtion pointer what will you do instead
>>> and is *that* cheaper?
>>
>> You could suggest that it is, in fact, faster for an oft called
>> function. No 32/64 bit address read required each and every call.
>
> what? The function address will be sitting in a register?
> I'd not thought of that.

On every system I'm familiar with, yes. For instance, on x86, this is a
direct call:

CALL 0xDEADBEEF

and this is an indirect call:

CALL [EAX]

One obviously has to load the function address into the register before
that instruction, of course, but that can often be hoisted quite a bit,
making the memory/cache access latency disappear.

S

--
Stephen Sprunk "God does not play dice." --Albert Einstein
CCIE #3723 "God is an inveterate gambler, and He throws the
K5SSS dice at every possible opportunity." --Stephen Hawking

jacob navia

unread,
Oct 11, 2009, 4:55:10 PM10/11/09
to
Gordon Burditt a �crit :

The 64 bit AMD-Intel processor is not a fully 64 bit processor.
The CALL instruction accepts a signed 2GB offset. If you want the
code that you generate to be able to be relocated in memory
ANYWHERE within the 64 bit address space you can't use plain
call instructions and you have to go through an indirect
call.

Stephen Sprunk

unread,
Oct 11, 2009, 5:03:38 PM10/11/09
to
Rui Maciel wrote:
> Is there a performance penalty associated with the use of function
> pointers? If so, how bad is it?

It completely depends on the system you're using; on some it may be
significant, while on others it may be negligible. Measure for yourself
and find out.

<OT>
This comes down to the cost of a direct call vs. an indirect call. An
indirect call costs you an extra register, though that probably won't
hurt. More importantly, an indirect call requires that the CPU
correctly predict the _target_ of the call. Modern high-end CPUs have a
branch target predictor that is responsible for that, similar to the
branch predictor that is responsible for guessing whether a conditional
branch is taken or not. If either of those predictions is wrong, the
pipeline will stall, which could burn dozens or even hundreds of cycles.

In the context of function pointers, if you use the same one over and
over, the cost is likely to be negligible--at least after the first
time. If you keep changing the pointer, though, you're going to have to
pay that cost _every time you change it_.

Embedded CPUs may not have a branch target predictor at all because it
adds die size, heat, power consumption, and cost. In that case, an
indirect branch is going to hurt every time, regardless of whether the
pointer is changed, because the CPU isn't even _attempting_ to predict
what the target is and has to stall the pipeline to find out.
</OT>

Richard

unread,
Oct 11, 2009, 5:20:44 PM10/11/09
to
jacob navia <ja...@nospam.org> writes:

Its no more indirect than anything else if the compiler does its job in
the case of an oft called address stored in a register.

jacob navia

unread,
Oct 11, 2009, 6:23:40 PM10/11/09
to
Richard a �crit :

> Its no more indirect than anything else if the compiler does its job in
> the case of an oft called address stored in a register.
>

You mean

fnptr = sqrt
fnptr(2.3);


Yes, in this case it *could* be optimized, and maybe some
compiler does optimize this... But this usage of function pointers
is highly unusual... We are speaking about the general case of course, when
it is NOT known which address is going to be called.

Richard

unread,
Oct 11, 2009, 6:30:58 PM10/11/09
to
jacob navia <ja...@nospam.org> writes:

My point holds that it can indeed by faster and that a blanket "no its
not" is simply wrong.

Anyway, does ISO C even have registers :-; ?

Time for that preening idiot Carmody to come barrelling in insulting
people I suspect.

Ben Bacarisse

unread,
Oct 11, 2009, 6:47:15 PM10/11/09
to
"Malcolm McLean" <regn...@btinternet.com> writes:

> "Rui Maciel" <rui.m...@gmail.com> wrote in message news:
>> Is there a performance penalty associated with the use of function
>> pointers? If >so, how bad is it?
>>
> With an aggressively optimising compiler there shouldn't be much of a
> penalty, in typical use.
> This is because you use a function pointer to make a function more general.
> The classic example form the library is qsort(). Typically this will be used
> as
>
> int compfunc(const void *e1, const void *e2)
> {
> const char **str1 = e1;
> const char **str2 = e2;
>
> return strcmp(*str1, *str2);
> }
>
> ...
> qsort(array, N, sizeof(char *), compfunc);
> ...
>
> So if there is significant penalty in calling a function indirectly, in
> machine code, a compiler can replace the indirect jump with a hard-linked
> one, or even inline the function totally.

This is theoretically possible, but does it ever happen in a C
compiler? In many implementations, qsort is just a function compiled
long ago that simply has code in it to do an indirect call. Have you
come across a system that does inline or re-write this call?

> Of course rarely the comparison function will be a variable and not
> resolveable at compile time, in which case the call will have to be via an
> indirect jump. However the penalty is unlikely to be very large, though it
> will be something.

--
Ben.

Flash Gordon

unread,
Oct 11, 2009, 7:59:26 PM10/11/09
to
Stephen Sprunk wrote:
> Rui Maciel wrote:
>> Is there a performance penalty associated with the use of function
>> pointers? If so, how bad is it?
>
> It completely depends on the system you're using; on some it may be
> significant, while on others it may be negligible. Measure for yourself
> and find out.

and repeat on all implementations of interest, since each one might be
different. That includes each version of the each processor even if you
are using the same binary in case the instruction speeds vary (which
they sometimes do).

<snip>

> Embedded CPUs may not have a branch target predictor at all because it
> adds die size, heat, power consumption, and cost. In that case, an
> indirect branch is going to hurt every time, regardless of whether the
> pointer is changed, because the CPU isn't even _attempting_ to predict
> what the target is and has to stall the pipeline to find out.
> </OT>

<OT>

It may still not hurt... some processors have instructions such as,
"branch in two instructions time", "call in two instructions time" and
"return in two instructions time" so that the instruction pipeline is
not broken.
--
Flash Gordon

BGB / cr88192

unread,
Oct 11, 2009, 10:59:26 PM10/11/09
to

"jacob navia" <ja...@nospam.org> wrote in message
news:hatgnj$vks$1...@aioe.org...


this still need not force all calls to be full 64-bits though...

if the code produced is PIC code, then one can simply use relative jumps and
calls, and make the simplifying assumption that all calls are within the
+-2GB window.

at link time, if this assumption fails for some reason, it can be thunked.
so, with a little creative handling, nearly all such long-distance calls can
be eliminated...


the problem then is Linux x86-64, which has a bad habit of wanting people to
use the GOT for everything (however, with a tiny amount of creative code and
some link-time trickery, likely this could be worked around as well...).

so, really, I am not sure what is the reason for your issues...


for variables, it is slightly harder.

however, Windows itself imposes some simplifying assumptions, so this can be
largely ignored as well.

in Linux-land though, one might be forced (absent linker trickery) to resort
to using the GOT...


or such...


Stephen Sprunk

unread,
Oct 12, 2009, 2:49:30 AM10/12/09
to
jacob navia wrote:
> Gordon Burditt a écrit :

Last I heard, nobody has yet implemented the x86-64 ABI's "large" code
model. Difficulty with the CALL instruction is probably one major
reason for that; AMD didn't leave any particularly good way to implement
it, though if demand ever arises, I bet we'll see a new CALL opcode
appear that will accept a 64-bit offset.

The other code models require all code to be in the first 4GB of RAM
(positive 2GB for user code, negative 2GB for kernel code), just like
x86, and the rest of memory is for data only.

Rui Maciel

unread,
Oct 12, 2009, 3:36:38 AM10/12/09
to
Eric Sosman wrote:

>> Is there a performance penalty associated with the use of function
>> pointers?
>
> Perhaps. What do your measurements tell you?

Isn't this issue deterministic? Why should anyone employ empirical methods to try to understand the behavior
of deterministic systems? And why do you believe that measurements would enable you to arrive at a meaningful
conclusion?


Rui Maciel

Rui Maciel

unread,
Oct 12, 2009, 3:40:49 AM10/12/09
to
Seebs wrote:

> And for much the same reason, asking people what the performance penalty
> is won't do you much better.

Programming languages, particularly those defined by international standards such as C, are implemented
according to specific rules. Even the aspects which are left undefined are still implemented from a concrete
set of instructions. Therefore, if you are dealing with a deterministic system then things happen for a very
good, tangible and meticulously defined reason. They don't just happen due to unexplainable whims.


Rui Maciel

jacob navia

unread,
Oct 12, 2009, 5:20:29 AM10/12/09
to
BGB / cr88192 a �crit :

>
> if the code produced is PIC code, then one can simply use relative jumps and
> calls, and make the simplifying assumption that all calls are within the
> +-2GB window.
>

This is precisely the assumption I can't do...

bartc

unread,
Oct 12, 2009, 6:07:55 AM10/12/09
to

"Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
news:877hv1o...@kilospaz.fatphil.org...

> Rui Maciel <rui.m...@gmail.com> writes:
>> Is there a performance penalty associated with the use of function
>> pointers? If so, how bad is it?
>
> Nope, function pointers are faster.

If that was the case then all function calls would be via pointers, with the
compiler pointerfying direct function calls.

But oddly I haven't noticed that when I look at asm output.

--
Bartc

Nick Keighley

unread,
Oct 12, 2009, 6:14:35 AM10/12/09
to
your posts should make sense standalone

[Subject: Funtion pointers: performance penalty?]

so what? The fact is the penalty will vary from harware architecture
to hardware
architecture and even compiler to compiler so in general the question
cannot be
answered.

Other posters seem to be suggesting that once caching and pipeling are
added to the mix then the behaviour of "deterministic" processors can
be quite
difficult to "determine"

Tim Rentsch

unread,
Oct 12, 2009, 6:25:37 AM10/12/09
to
Seebs <usenet...@seebs.net> writes:

> [snip] The


> indirect call and direct call are not intrinsically different; ultimately,
> a "direct" call is still a call through a pointer anyway.

That's true in the abstract machine, but for actual hardware
the difference can be substantial (eg, speed ratio of more
than a factor of 10). So conceptual similarity and practical
similarly may not be the same here, depending on what
processor architecture and implementation is being used.

Richard Heathfield

unread,
Oct 12, 2009, 6:54:23 AM10/12/09
to

Then look at the machine code. (Seriously.)

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

James Kuyper

unread,
Oct 12, 2009, 7:03:59 AM10/12/09
to
Rui Maciel wrote:
> Seebs wrote:
>
>> And for much the same reason, asking people what the performance penalty
>> is won't do you much better.
>
> Programming languages, particularly those defined by international standards such as C, are implemented
> according to specific rules. Even the aspects which are left undefined are still implemented from a concrete
> set of instructions. ...

Yes, but it can be a very different set of of instructions on different
platforms, and the C standard itself tells you nothing about those
instruction sets.

> ... Therefore, if you are dealing with a deterministic system then things happen for a very

> good, tangible and meticulously defined reason. They don't just happen due to unexplainable whims.

"very good ... reason"? Implementors often make decisions for bad
reasons, just like anyone else. "Meticulously defined"? That depends
upon how good the software development process is that the implementor
uses; as with any other kind of software, there are some C implementors
who use a very poor software development process. No "unexplainable
whims"? These systems are designed by human beings - unexplainable whims
are routine occurrences.

None of that is relevant, however. The point is not whether the relevant
reasons for a decision are "very good", or "meticulously defined",
rather than "unexplained whims". What matters is that different
decisions are made even when the same implementor produces a new version
of a compiler for the same platform targeted to the same market; when
you add in the variety of choices made by different implementors on
different platforms for compilers targeted at different markets, the
variety is nearly endless. Paying too close attention to the details of
performance is pointless for software that is intended to be portable.

You have not yet identified which alternative approach you'd like
function pointers to be compared with. However, once that's decided,
issues like "is it better to use function pointers or ... (alternative)
", are more appropriately resolved by considering which approach makes
the code easier to understand, than by worrying about inherently
platform-specific details such as efficiency.

James Kuyper

unread,
Oct 12, 2009, 7:27:40 AM10/12/09
to
Rui Maciel wrote:
> Eric Sosman wrote:
>
>>> Is there a performance penalty associated with the use of function
>>> pointers?

Compared to what alternative? In any situation where use of function
pointers is appropriate, the alternative is more complicated than simply
calling the function directly. Example:

fptr = (condition ? func1 : func2);

x = fptr(y);

Could be changed to

x = (condition ? func1(y) : func2(y));

or
x = bigfunc(condition, y);

where bigfunc(true, y) behaves just like func1(y), while bigfunc(false,
y) behaves just like func2(y). Note that either of these approaches
requires storage of the condition that controls the choice, rather than
storage of a function pointer.

There's many other alternatives, as well. Which one are you thinking of?

>> Perhaps. What do your measurements tell you?
>
> Isn't this issue deterministic?

No, not in general. It can become deterministic if you're restricting
your attention to one particular machine, and one particular compiler,
running in single-user mode so that the performance does not depend upon
any other programs that might be running at the same time. Also, your
program must not be engaged in any real-time activities such as waiting
on a device, which can have side-effects that influence the performance
even of code that is completely unrelated to the the wait.

> ... Why should anyone employ empirical methods to try to understand the behavior
> of deterministic systems?

Even if you do have a deterministic system, figuring out the performance
penalty by deriving it from the rules governing that system can be
prohibitively difficult and error-prone. Empirical testing is often
simpler and more robust.

In any event, determinism is not the relevant problem; it's the fact
that the answer will, in general, be different on different
deterministic systems.

bartc

unread,
Oct 12, 2009, 7:36:17 AM10/12/09
to

"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:P4adnZYAS8GtlE7X...@bt.com...

> In <%dDAm.2271$KR3...@text.news.virginmedia.com>, bartc wrote:
>
>>
>> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
>> news:877hv1o...@kilospaz.fatphil.org...
>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>> Is there a performance penalty associated with the use of function
>>>> pointers? If so, how bad is it?
>>>
>>> Nope, function pointers are faster.
>>
>> If that was the case then all function calls would be via pointers,
>> with the compiler pointerfying direct function calls.
>>
>> But oddly I haven't noticed that when I look at asm output.
>
> Then look at the machine code. (Seriously.)

What's the difference between that and assembler code? Are you suggesting
that assembler code that looks like this:

call userfn

is silently converted to the following machine code equivalent:

call [userfnaddr]
...
userfnaddr: dd userfn

or perhaps to:

load Rn,userfn
...
call [Rn] ?

--
Bartc

James Kuyper

unread,
Oct 12, 2009, 7:43:01 AM10/12/09
to
bartc wrote:
>
> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
> news:877hv1o...@kilospaz.fatphil.org...
>> Rui Maciel <rui.m...@gmail.com> writes:
>>> Is there a performance penalty associated with the use of function
>>> pointers? If so, how bad is it?
>>
>> Nope, function pointers are faster.
>
> If that was the case then all function calls would be via pointers, with
> the compiler pointerfying direct function calls.

As far as the C standard is concerned, all function calls are via
pointer values: "The expression that denotes the called function shall
have type pointer to function". (6.5.2.2p1)

"Except when it is the operand of the sizeof operator or the unary &
operator, a function designator with type ‘‘function returning type’’ is
converted to an expression that has type ‘‘pointer to function returning
type’’." (6.3.2.1p4)

A compiler that uses any other method of calling the function would be,
"directifying" pointer function calls.

> But oddly I haven't noticed that when I look at asm output.

The three assembly languages I'm familiar with all perform function
calls by loading a special register with the memory address (a pointer
value) of the entry point to the function to be called. I'm curious -
how does the non-pointer way of implementing function calls work?

Seebs

unread,
Oct 12, 2009, 8:04:16 AM10/12/09
to
On 2009-10-12, Rui Maciel <rui.m...@gmail.com> wrote:
> Isn't this issue deterministic?

No.

(Not only is there not a single general answer which is determined by
something, I think there's plenty of real-world cases where the performance
penalty or advantage on a given target is not deterministic for a specific
program, because there can be other programs running which impose
non-deterministic variance on the environment.)

Richard Heathfield

unread,
Oct 12, 2009, 8:16:23 AM10/12/09
to

Are you suggesting that the name of the function is (necessarily)
present in the binary?

Observe:

1) source (cat foo.c)

#include <stdio.h>
#include <stdlib.h>

int foo(int i)
{
return i % 2 ? EXIT_SUCCESS : EXIT_FAILURE;
}

int main(int argc, char **argv)
{
return foo(argc);
}

2) readable contents of binary (strings foo) after a normal make:

/lib/ld-linux.so.2
libm.so.6
_IO_stdin_used
__gmon_start__
libncurses.so.5
_DYNAMIC
_init
_fini
_GLOBAL_OFFSET_TABLE_
libc.so.6
__monstartup
__cxa_finalize
malloc
__deregister_frame_info
mcount
_mcleanup
__libc_start_main
__register_frame_info
free
__cxa_atexit
_edata
__bss_start
_end
GLIBC_2.1.3
GLIBC_2.0
PTRh@

Note the complete absence of the function name, foo.

<snip>

Seebs

unread,
Oct 12, 2009, 8:06:56 AM10/12/09
to
On 2009-10-12, Rui Maciel <rui.m...@gmail.com> wrote:
> Programming languages, particularly those defined by international
> standards such as C, are implemented according to specific rules.

Performance is, as the nice people say, "a quality of implementation
issue".

> Even the aspects which are left undefined are still implemented
> from a concrete set of instructions. Therefore, if you are dealing
> with a deterministic system then things happen for a very good,
> tangible and meticulously defined reason. They don't just happen
> due to unexplainable whims.

If the original poster had asked "using gcc 3.4.4, with the following
compiled-in options and the following command line options, running bare
metal code on a TI OMAP 2430 CPU, what is the performance penalty of
function pointers", it is quite possible that it would be meaningful
to speak of a deterministic answer.

In the general case, there's no answer. It's not even entirely obvious
that there will be a penalty at all.

Seebs

unread,
Oct 12, 2009, 8:09:08 AM10/12/09
to
On 2009-10-12, bartc <ba...@freeuk.com> wrote:
> What's the difference between that and assembler code?

Assembly is, itself, a rather higher-level language than people
often expect.

> Are you suggesting
> that assembler code that looks like this:

> call userfn

[...]

> load Rn,userfn
> ...
> call [Rn] ?

Quite possibly.

Modern assemblers often hide a surprising amount of Stuff.

Seebs

unread,
Oct 12, 2009, 8:17:18 AM10/12/09
to
On 2009-10-12, Tim Rentsch <t...@alumni.caltech.edu> wrote:
> That's true in the abstract machine, but for actual hardware
> the difference can be substantial (eg, speed ratio of more
> than a factor of 10). So conceptual similarity and practical
> similarly may not be the same here, depending on what
> processor architecture and implementation is being used.

True.

I guess I'm more looking at the question "is there a definite answer",
and the answer to that is "no, not in general".

bartc

unread,
Oct 12, 2009, 8:24:08 AM10/12/09
to

You mean this register is loaded using explicit instructions that a compiler
will generate, or are you just explaining how a conventional call
instruction works, by loading the address of the function into the program
counter?

The direct call method looks like this:

(A) call immediate-function-address (or, sometimes, immediate-offset)

An indirect call looks something like this:

(B) call [address-of-location-containing-address-of-function]

What I'm saying is that if method (B) was always faster than (A), then only
(B) would ever be generated, which sounds unlikely.

A variation of (B) is to have the function address permanently in a
register. This could conceivably be faster than (A), but there aren't enough
registers to treat every function like this.

--
bartc

bartc

unread,
Oct 12, 2009, 8:39:43 AM10/12/09
to
Richard Heathfield wrote:
> In <RwEAm.2301$KR3....@text.news.virginmedia.com>, bartc wrote:
>
>>
>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
>> news:P4adnZYAS8GtlE7X...@bt.com...
>>> In <%dDAm.2271$KR3...@text.news.virginmedia.com>, bartc wrote:
>>>
>>>>
>>>> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
>>>> news:877hv1o...@kilospaz.fatphil.org...

>>>>> Nope, function pointers are faster.


>>>>
>>>> If that was the case then all function calls would be via
>>>> pointers, with the compiler pointerfying direct function calls.
>>>>
>>>> But oddly I haven't noticed that when I look at asm output.
>>>
>>> Then look at the machine code. (Seriously.)
>>
>> What's the difference between that and assembler code? Are you
>> suggesting that assembler code that looks like this:
>>
>> call userfn
>>
>> is silently converted to the following machine code equivalent:
>>
>> call [userfnaddr]
>
> Are you suggesting that the name of the function is (necessarily)
> present in the binary?

No. I said machine code 'equivalent', ie. the mnemonic that might be
associated with an indirect call instruction.

My implication is that assembler code maps pretty much one-to-one with
machine code, so that you normally wouldn't mistake a direct call with an
indirect call (unless you're using Masm then it's anyone's guess what a
particular line might mean).

I've since looked at some disassembled code from my x86 machine and most
calls do seem to be direct (and to avoid misunderstanding, since apparently
assembler source is not to be trusted, they all start with the E8 opcode for
direct call instructions).

--
bartc

Richard Heathfield

unread,
Oct 12, 2009, 9:02:15 AM10/12/09
to
In <jsFAm.2321$KR3...@text.news.virginmedia.com>, bartc wrote:

> Richard Heathfield wrote:
>> In <RwEAm.2301$KR3....@text.news.virginmedia.com>, bartc wrote:
>>
>>>
>>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
>>> news:P4adnZYAS8GtlE7X...@bt.com...
>>>> In <%dDAm.2271$KR3...@text.news.virginmedia.com>, bartc wrote:
>>>>
>>>>>
>>>>> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in
>>>>> message news:877hv1o...@kilospaz.fatphil.org...
>
>>>>>> Nope, function pointers are faster.
>>>>>
>>>>> If that was the case then all function calls would be via
>>>>> pointers, with the compiler pointerfying direct function calls.
>>>>>
>>>>> But oddly I haven't noticed that when I look at asm output.
>>>>
>>>> Then look at the machine code. (Seriously.)
>>>
>>> What's the difference between that and assembler code? Are you
>>> suggesting that assembler code that looks like this:
>>>
>>> call userfn
>>>
>>> is silently converted to the following machine code equivalent:
>>>
>>> call [userfnaddr]
>>
>> Are you suggesting that the name of the function is (necessarily)
>> present in the binary?
>
> No. I said machine code 'equivalent', ie. the mnemonic that might be
> associated with an indirect call instruction.

It's not clear to me what distinction you are making. The obvious way
to call a function is by loading its address into the instruction
pointer register. You seem to be suggesting that there is some other
way. Could you possibly enlighten us?

> My implication is that assembler code maps pretty much one-to-one
> with machine code,

That isn't anything like as true as it used to be.

bartc

unread,
Oct 12, 2009, 9:08:46 AM10/12/09
to
"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:rtWdndGQa460uk7X...@bt.com...

> In <jsFAm.2321$KR3...@text.news.virginmedia.com>, bartc wrote:

>> No. I said machine code 'equivalent', ie. the mnemonic that might be
>> associated with an indirect call instruction.
>
> It's not clear to me what distinction you are making. The obvious way
> to call a function is by loading its address into the instruction
> pointer register. You seem to be suggesting that there is some other
> way. Could you possibly enlighten us?

And it's not clear to me why you are blurring such an obvious distinction,
since that would render the subject of this thread meaningless.

I've already replied on this to James, but to summarise, a direct call might
use an immediate instruction operand, while an indirect call might use an
indirect operand, ie. to be fetched from another location first. Both end up
with the function address in the program counter.

But I've sure you guys are just pretending not to know what I'm on about.

--
Bartc

Richard

unread,
Oct 12, 2009, 9:13:33 AM10/12/09
to
"bartc" <ba...@freeuk.com> writes:

Welcome to c.l.c

I have actually seem them stroke their beards while pretending not
to recognise a main declaration like

void main()
{

James Kuyper

unread,
Oct 12, 2009, 9:26:08 AM10/12/09
to
bartc wrote:
> James Kuyper wrote:
>> bartc wrote:
...

>>> If that was the case then all function calls would be via pointers,
>>> with the compiler pointerfying direct function calls.
>>
>> As far as the C standard is concerned, all function calls are via
>> pointer values: "The expression that denotes the called function shall
>> have type pointer to function". (6.5.2.2p1)
>>
>> "Except when it is the operand of the sizeof operator or the unary &
>> operator, a function designator with type ‘‘function returning type’’
>> is converted to an expression that has type ‘‘pointer to function
>> returning type’’." (6.3.2.1p4)
>>
>> A compiler that uses any other method of calling the function would
>> be, "directifying" pointer function calls.
>>
>>> But oddly I haven't noticed that when I look at asm output.
>>
>> The three assembly languages I'm familiar with all perform function
>> calls by loading a special register with the memory address (a pointer
>> value) of the entry point to the function to be called. I'm curious -
>> how does the non-pointer way of implementing function calls work?
>
> You mean this register is loaded using explicit instructions that a
> compiler will generate, ...

I said nothing to imply that.

> ... or are you just explaining how a conventional

> call instruction works, by loading the address of the function into the
> program counter?

Of course. If it's the only method I'm familiar with after learning
three different assembly languages, you can be reasonably sure that I'm
referring to something fairly conventional.

> The direct call method looks like this:
>
> (A) call immediate-function-address (or, sometimes, immediate-offset)

That would, in C terms, be comparable to calling a function through a
function pointer value.

> An indirect call looks something like this:
>
> (B) call [address-of-location-containing-address-of-function]

Again, in C terms, that would be comparable to calling a function
through the value stored in a pointer object.

Either way, it's a call by pointer; which is good, since it matches the
way that the C standard describes function calls.

Eric Sosman

unread,
Oct 12, 2009, 10:41:43 AM10/12/09
to

No; many reasons; false premise.

--
Eric....@sun.com

Nick Keighley

unread,
Oct 12, 2009, 10:48:11 AM10/12/09
to
On 11 Oct, 17:43, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:

> On 11 Oct, 16:53, Rui Maciel <rui.mac...@gmail.com> wrote:


> > Is there a performance penalty associated with the use of

> > function pointers? If so, how bad is it?

> If you don't use a funtion pointer what will you do instead
> and is *that* cheaper?

you never addressed this point.
If you don't use a function pointer what will you use?

Keith Thompson

unread,
Oct 12, 2009, 10:47:00 AM10/12/09
to
James Kuyper <james...@verizon.net> writes:
> bartc wrote:
[...]

>> The direct call method looks like this:
>>
>> (A) call immediate-function-address (or, sometimes, immediate-offset)
>
> That would, in C terms, be comparable to calling a function through a
> function pointer value.
>
>> An indirect call looks something like this:
>>
>> (B) call [address-of-location-containing-address-of-function]
>
> Again, in C terms, that would be comparable to calling a function
> through the value stored in a pointer object.
>
> Either way, it's a call by pointer; which is good, since it matches
> the way that the C standard describes function calls.

In general, the generated code for a C function call might use
mechanism X when the identity of the called function is known at
compile time, and mechanism Y when it isn't.

Assumptions: Mechanisms X and Y are distinct, and mechanism X
*cannot* be used unless the identity of the called function is
known at compile time. These assumptions might not be true for
some platforms.

Whatever they look like, whether or not the function's address
is stored in a register at some point, let's call Mechanism X a
"direct call" and Mechanism Y an "indirect call".

Now that we've defined our terms in (I think) a sufficiently
abstract way, the question is: are direct calls more efficient than
indirect calls? And as we've discussed, there's no definitive
answer, though I'd expect direct calls to be faster, or at least
no slower, on most systems. (If indirect calls are faster, the
compiler probably would never generate direct calls.)

And, as others have pointed out, you can't typically replace an
indirect call with a direct call to get better speed; they serve
different purposes.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Nick Keighley

unread,
Oct 12, 2009, 11:01:23 AM10/12/09
to
On 12 Oct, 14:02, Richard Heathfield <r...@see.sig.invalid> wrote:

> In <jsFAm.2321$KR3....@text.news.virginmedia.com>, bartc wrote:
> > Richard Heathfield wrote:
> >> In <RwEAm.2301$KR3.1...@text.news.virginmedia.com>, bartc wrote:
> >>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
> >>>news:P4adnZYAS8GtlE7X...@bt.com...
> >>>> In <%dDAm.2271$KR3....@text.news.virginmedia.com>, bartc wrote:
> >>>>> "Phil Carmody" <thefatphil_demun...@yahoo.co.uk> wrote in
> >>>>> messagenews:877hv1o...@kilospaz.fatphil.org...


> >>>>>> Nope, function pointers are faster.
>
> >>>>> If that was the case then all function calls would be via
> >>>>> pointers, with the compiler pointerfying direct function calls.
>
> >>>>> But oddly I haven't noticed that when I look at asm output.
>
> >>>> Then look at the machine code. (Seriously.)

if there isn't a 1 -to-1 mapping between assembler and machine code
doesn't that kind of defeat the purpose of assembler? By the time
we're
down this low we want to know what the processor is *really* doing.
(ignoring the fact it is actually JITing the x86 code into some pseudo
RISC stream which it then executes out of order).

Why would you want assembly code that lied to you?


> >>> What's the difference between that and assembler code? Are you
> >>> suggesting that assembler code that looks like this:
>
> >>>  call userfn
>
> >>> is silently converted to the following machine code equivalent:
>
> >>>  call [userfnaddr]
>
> >> Are you suggesting that the name of the function is (necessarily)
> >> present in the binary?

I never saw him say that. Going back to the Z80 (the last assembler I
actually
memorised)

call fun -> CD 00 50

CD "is equivalent to" "call"

> > No. I said machine code 'equivalent', ie. the mnemonic that might be
> > associated with an indirect call instruction.
>
> It's not clear to me what distinction you are making. The obvious way
> to call a function is by loading its address into the instruction
> pointer register. You seem to be suggesting that there is some other
> way. Could you possibly enlighten us?

some machines can't load directly from memory to the rI- well not as
an instruction. So

*f (i); /* I know I don't need the * */

might assemble to something like (RISC-like assembler)

ld r1 i
push r1
ld r1 f
call r1

> > My implication is that assembler code maps pretty much one-to-one
> > with machine code,
>
> That isn't anything like as true as it used to be.

doesn't seem like a great step forward

Gene

unread,
Oct 12, 2009, 11:24:53 AM10/12/09
to
On Oct 11, 6:47 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> "Malcolm McLean" <regniz...@btinternet.com> writes:
> > "Rui Maciel" <rui.mac...@gmail.com> wrote in message news:

> >> Is there a performance penalty associated with the use of function
> >> pointers? If >so, how bad is it?
>
> > With an aggressively optimising compiler there shouldn't be much of a
> > penalty, in typical use.
> > This is because you use a function pointer to make a function more general.
> > The classic example form the library is qsort(). Typically this will be used
> > as
>
> > int compfunc(const void *e1, const void *e2)
> > {
> >    const char **str1 = e1;
> >    const char **str2 = e2;
>
> >    return strcmp(*str1, *str2);
> > }
>
> > ...
> >   qsort(array, N, sizeof(char *), compfunc);
> > ...
>
> > So if there is significant penalty in calling a function indirectly, in
> > machine code, a compiler can replace the indirect jump with a hard-linked
> > one, or even inline the function totally.
>
> This is theoretically possible, but does it ever happen in a C
> compiler?  In many implementations, qsort is just a function compiled
> long ago that simply has code in it to do an indirect call.  Have you
> come across a system that does inline or re-write this call?  
>
I don't know specifically about qsort(), but JIT compilers based on
technologies like LLVM would do this as a matter of course. See
llvm.org.

Richard Tobin

unread,
Oct 12, 2009, 1:04:05 PM10/12/09
to
In article <rtWdndGQa460uk7X...@bt.com>,
Richard Heathfield <r...@see.sig.invalid> wrote:

>The obvious way
>to call a function is by loading its address into the instruction
>pointer register.

The obvious way to call a function is by using the processor's
function call instruction. In the past, this often corresponded
fairly directly to putting the address into an instruction pointer
register, and on some architectures it might even be the same as a
"move" instruction to that register. This is much less common today:
any such instruction pointer register is likely to be a substantial
abstraction from the real hardware.

-- Richard
--
Please remember to mention me / in tapes you leave behind.

jacob navia

unread,
Oct 12, 2009, 12:55:41 PM10/12/09
to
Seebs a �crit :

>
> In the general case, there's no answer. It's not even entirely obvious
> that there will be a penalty at all.
>

Interesting, very interesting.

All the research papers about this subject (and there are hundreds
of research papers in the literature on this subject)
are done by people that missed your point. Interesting really.

For instance:
http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf
The Direct Cost of Virtual Function Calls in C++

That is just nonsense research. All those papers that try to improve
the direct cost of virtual function calls are just wrong...

Incredible how much nonsense can be written here.

There are TWO costs associated with an indirect function call (i.e.
through a function pointer)

(1) The direct cost of pipeline problems as I described in my other
message
(2) The INDIRECT cost because the call graph is not explicit, what makes
many optimizations impossible. This second cost is often neglected but
it is very real.

And I will forget about the nonsense of heathfield that tries to make
a distinction between assembler mnemonics and machine code, or even
kuyper that says that all function calls are pointer function calls
with some citation from the C standard... (even saying that loading the
value of the call into the instruction pointer is a "pointer" call).

jacob navia

unread,
Oct 12, 2009, 12:59:43 PM10/12/09
to
Richard Tobin a �crit :

heathfield is (as always) playing with words, implying that the
call instruction loads the address of the function into the
instruction pointer...

The fact that the offset is an explicit one in the case of a
call instruction or an implicit offset not readily available
to the speculative instruction execution module goes beyond
his knowledge of assembly... It is the same when he says that
the ascii mnemonics differ from the machine code, or all those
word games that he plays here.

Richard Tobin

unread,
Oct 12, 2009, 1:18:20 PM10/12/09
to
In article <havna7$hbf$1...@aioe.org>, jacob navia <j...@nospam.org> wrote:

>The fact that the offset is an explicit one in the case of a
>call instruction or an implicit offset not readily available
>to the speculative instruction execution module

I think your use of "readily" may be significant here. Depending on
when the value for an indirect call is loaded into the register, the
pipeline may be still be able to make use of it.

Richard Tobin

unread,
Oct 12, 2009, 1:20:09 PM10/12/09
to
By the way, I am sure that those interested could have a better-informed
discussion over in comp.arch.

Richard Heathfield

unread,
Oct 12, 2009, 1:25:02 PM10/12/09
to
In <93e42a85-f9f4-4196...@k4g2000yqb.googlegroups.com>,
Nick Keighley wrote:

> On 12 Oct, 14:02, Richard Heathfield <r...@see.sig.invalid> wrote:
>> In <jsFAm.2321$KR3....@text.news.virginmedia.com>, bartc wrote:
>> > Richard Heathfield wrote:
>> >> In <RwEAm.2301$KR3.1...@text.news.virginmedia.com>, bartc wrote:
>> >>> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
>> >>>news:P4adnZYAS8GtlE7X...@bt.com...
>> >>>> In <%dDAm.2271$KR3....@text.news.virginmedia.com>, bartc
>> >>>> wrote:
>> >>>>> "Phil Carmody" <thefatphil_demun...@yahoo.co.uk> wrote in
>> >>>>> messagenews:877hv1o...@kilospaz.fatphil.org...
>
>
>> >>>>>> Nope, function pointers are faster.
>>
>> >>>>> If that was the case then all function calls would be via
>> >>>>> pointers, with the compiler pointerfying direct function
>> >>>>> calls.
>>
>> >>>>> But oddly I haven't noticed that when I look at asm output.
>>
>> >>>> Then look at the machine code. (Seriously.)
>
> if there isn't a 1 -to-1 mapping between assembler and machine code
> doesn't that kind of defeat the purpose of assembler?

Not entirely, but it does kind of make you wonder, doesn't it? After
all, if I want C I know where to find it.

> By the time we're
> down this low we want to know what the processor is *really* doing.
> (ignoring the fact it is actually JITing the x86 code into some
> pseudo RISC stream which it then executes out of order).
>
> Why would you want assembly code that lied to you?

Great question.

>
>
>> >>> What's the difference between that and assembler code? Are you
>> >>> suggesting that assembler code that looks like this:
>>
>> >>> call userfn
>>
>> >>> is silently converted to the following machine code equivalent:
>>
>> >>> call [userfnaddr]
>>
>> >> Are you suggesting that the name of the function is
>> >> (necessarily) present in the binary?
>
> I never saw him say that.

Neither did I. It is not clear to me what he actually means. I took a
guess, and asked him whether that guess was correct. It seems he now
thinks I'm playing games with him, and I don't have the patience for
that kind of discussion right now.

>> > My implication is that assembler code maps pretty much one-to-one
>> > with machine code,
>>
>> That isn't anything like as true as it used to be.
>
> doesn't seem like a great step forward

I entirely agree.

Seebs

unread,
Oct 12, 2009, 1:31:02 PM10/12/09
to
On 2009-10-12, Nick Keighley <nick_keigh...@hotmail.com> wrote:
> if there isn't a 1 -to-1 mapping between assembler and machine code
> doesn't that kind of defeat the purpose of assembler?

No.

The purpose of the assembler is to let you pick the instructions you want,
and to handle the fiddly bits. Thus, assemblers typically do things like
translate symbolic names for labels, so you can write "foo:" and later to
a branch to "foo" and expect the right thing to happen. But on processors
where, say, there's a difference between immediate branches within 128
bytes and immediate branches within 32768 bytes, or something similar,
you might not want to have to know -- so you write a generic branch and
the assembler uses the right one once it knows the actual distance.

Etcetera.

> Why would you want assembly code that lied to you?

Because otherwise you couldn't write it. :)

It's not a hugely common thing, but it does come up; the other thing is,
a lot of assembly systems support some degree of macro writing, and often
calling sequences can be among the things for which you emit macro
calls...

Ben Bacarisse

unread,
Oct 12, 2009, 1:38:14 PM10/12/09
to
Nick Keighley <nick_keigh...@hotmail.com> writes:
<snip>

Small point:

> *f (i); /* I know I don't need the * */

you need *that* star. You meant (*f)(i), I think, where the * is
indeed redundant but usefully adds clarity to the discussion you were
having.

<snip>
--
Ben.

Seebs

unread,
Oct 12, 2009, 1:40:30 PM10/12/09
to
On 2009-10-12, jacob navia <ja...@nospam.org> wrote:
> All the research papers about this subject (and there are hundreds
> of research papers in the literature on this subject)
> are done by people that missed your point. Interesting really.

Uh.

> For instance:
> http://www.cs.ucsb.edu/~urs/oocsb/papers/oopsla96.pdf
> The Direct Cost of Virtual Function Calls in C++

> That is just nonsense research. All those papers that try to improve
> the direct cost of virtual function calls are just wrong...

No, they're quite right. They're answering, though, a VERY different
question.

Direct call:
puts("hello, world!\n");

Function pointer:

int (*foo)(const char *) = puts;
foo("hello, world!\n");

Virtual function call:

struct funcs {
struct funcs *next;
int (*foo)(const char *)puts_func;
};
struct foo {
struct funcs *functable;
char *s;
};
struct funcs stdio_functable = { NULL, puts };
struct foo greet_user = { &stdio_functable, "hello, world!\n" };
struct foo *greeter = &greet_user;

/* ... */
if (greeter->functable) {
struct funcs *vtable = greeter->functable;
while (vtable) {
if (vtable->puts_func) {
return vtable->puts_func(greeter->s);
}
vtable = vtable->next;
}
}

... Oh, you're right, there's NO DIFFERENCE AT ALL between a virtual
function call using virtual function tables and a call through a function
pointer, I'm sure they're exactly the same thing and have identical
performance characteristics.

(Disclaimer: The above vtable interface was written on the fly
and is untested, but things of roughly this sort have been used in the
past, and are about the right mapping for the behavior of a virtual
function implementation, complete with the dynamic runtime calculation,
not just of what address to call, but where to find the address you plan
to call...)

> And I will forget about the nonsense of heathfield that tries to make
> a distinction between assembler mnemonics and machine code, or even
> kuyper that says that all function calls are pointer function calls
> with some citation from the C standard... (even saying that loading the
> value of the call into the instruction pointer is a "pointer" call).

Of course you will.

Except that, in both cases, they're right. Assembler mnemonics are not always
1:1 with machine code in modern assemblers, and a call through an external
symbol is not necessarily noticably different between a symbol which the
linker maps to a function's address and a symbol which the compiler maps to a
variable holding a function's address.

Tim Rentsch

unread,
Oct 12, 2009, 1:50:26 PM10/12/09
to
Seebs <usenet...@seebs.net> writes:

> On 2009-10-12, Tim Rentsch <t...@alumni.caltech.edu> wrote:
>> That's true in the abstract machine, but for actual hardware
>> the difference can be substantial (eg, speed ratio of more
>> than a factor of 10). So conceptual similarity and practical
>> similarly may not be the same here, depending on what
>> processor architecture and implementation is being used.
>
> True.
>
> I guess I'm more looking at the question "is there a definite answer",
> and the answer to that is "no, not in general".

I don't disagree, but I would choose a different phrasing,
because I think there is useful information to give.
Of course, even on a specific platform what the cost
is of calling through a function pointer depends on
lots of different things, often too numerous to know.
But in general, the answer I'd be inclined to give
is "it depends /a lot/ on which processor architecture(s)
the code is expected to run on."

Antoninus Twink

unread,
Oct 12, 2009, 2:08:32 PM10/12/09
to
On 11 Oct 2009 at 22:47, Ben Bacarisse wrote:
> This is theoretically possible, but does it ever happen in a C
> compiler?

You should be careful, Ben.

That's the sort of subversive question that gets you branded as a
"troll" in this group.

bartc

unread,
Oct 12, 2009, 2:29:11 PM10/12/09
to

"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:0O6dndKs745d-U7X...@bt.com...

> Neither did I. It is not clear to me what he actually means. I took a
> guess, and asked him whether that guess was correct. It seems he now
> thinks I'm playing games with him, and I don't have the patience for
> that kind of discussion right now.

I don't have much patience for those games either.

I said I hadn't seen any evidence, from asm listings, that compilers were
generating indirect call instructions in preference to regular ones, if
calling via function pointers was in fact always faster, as claimed by Mr
Carmody.

The discussion then went off at a tangent, but I still haven't seen such
evidence (and I'm familiar enough with asm to know what's what). Your reply
suggested that if I looked at machine instead code, I would actually see
that evidence.

Now if Mr Carmody had some particular machine in mind where his statement
would be correct, then it would be intriguing to know what it was.
Memory-indirect calls require an extra memory access which usually involves
some of performance penalty (everything else being equal...).

--
Bartc


Keith Thompson

unread,
Oct 12, 2009, 2:39:56 PM10/12/09
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:

> Rui Maciel <rui.m...@gmail.com> writes:
>> Is there a performance penalty associated with the use of function
>> pointers? If so, how bad is it?
>
> Nope, function pointers are faster.

Could you please expand on this statement? Was it intended as
a joke? If not, what exactly do you mean?

Seebs

unread,
Oct 12, 2009, 2:52:43 PM10/12/09
to
On 2009-10-12, bartc <ba...@freeuk.com> wrote:
> I said I hadn't seen any evidence, from asm listings, that compilers were
> generating indirect call instructions in preference to regular ones, if
> calling via function pointers was in fact always faster, as claimed by Mr
> Carmody.

I don't know about "always" faster. I would not be surprised if there existed
cases in which a call through a function pointer were faster.

> Now if Mr Carmody had some particular machine in mind where his statement
> would be correct, then it would be intriguing to know what it was.
> Memory-indirect calls require an extra memory access which usually involves
> some of performance penalty (everything else being equal...).

I would guess that at least some cases exist in which the direct call can't
be fully figured out at compile time, so it'd be a direct call to something
else which figures out what to actually call. (On at least some common
implementations, this is nearly always the case for, say, everything in the
standard C library.) And there might then exist cases in which a function
pointer call could be to the "target" function. In which case it'd be faster.

Consider, though, a case like:

for (i = 0; i < 100; ++i) {
foo(a[i]);
}

It might be that, if foo is a function pointer, this ends up being:

load r1,<dereference-of-memory>
...
push a[i]
call r1

and if it's immediate, it ends up being

...
push a[i]
load r1,<immediate value>
call r1

or something comparable. In such a case, the call through a pointer
may be enough of a hint to tell the compiler to keep that address loaded
in a suitable register.

So I think in the real world, the answer is you'd have to test to find out.

On my Mac, I see no difference at all between the two cases.

Unless the function is "printf" and the argument is "", in which case the
direct call gets a free printf-specific optimization that makes more than an
order of magnitude difference... But that's not the call overhead, it's
a special-case optimization.

Otherwise, they seem to be the same. I see:

call *%rax
call _y

user923005

unread,
Oct 12, 2009, 3:28:43 PM10/12/09
to

Given this code:
#include<math.h>
#include<stdio.h>
typedef double (*f_t) (double);
static f_t f[] =
{log, log10, sqrt, cos, cosh, exp, sin, sinh, tan, tanh, 0};
int main(void)
{
int i;
f_t *flist = f;
for (i = 0; f[i]; i++) {
printf("new style function %d = %g\n", i, f[i] (0.5));
}
for (i = 0; f[i]; i++) {
printf("old style function %d = %g\n", i, (*f[i]) (0.5));
}
while (*flist) {
f_t ff = *flist;
printf("function pointer = %g\n", ff(0.5));
flist++;
}
printf("direct function call = %g\n", log(0.5));
printf("direct function call = %g\n", log10(0.5));
printf("direct function call = %g\n", sqrt(0.5));
printf("direct function call = %g\n", cos(0.5));
printf("direct function call = %g\n", cosh(0.5));
printf("direct function call = %g\n", exp(0.5));
printf("direct function call = %g\n", sin(0.5));
printf("direct function call = %g\n", sinh(0.5));
printf("direct function call = %g\n", tan(0.5));
printf("direct function call = %g\n", tanh(0.5));
return 0;
}

The following 64 bit Intel assembly is generated:
; Listing generated by Microsoft (R) Optimizing Compiler Version
15.00.30729.01

include listing.inc

INCLUDELIB OLDNAMES

PUBLIC ??_C@_0BM@CKAFHGKH@new?5style?5function?5?$CFd?5?$DN?5?$CFg?6?
$AA@ ; `string'
PUBLIC ??_C@_0BM@NPLLPAPB@old?5style?5function?5?$CFd?5?$DN?5?$CFg?6?
$AA@ ; `string'
PUBLIC ??_C@_0BH@LIMEHMAH@function?5pointer?5?$DN?5?$CFg?6?$AA@ ;
`string'
PUBLIC ??_C@_0BL@KHOEBBJB@direct?5function?5call?5?$DN?5?$CFg?6?$AA@ ;
`string'
EXTRN __imp_printf:PROC
EXTRN cosh:PROC
EXTRN cos:PROC
EXTRN exp:PROC
EXTRN log10:PROC
EXTRN log:PROC
EXTRN sqrt:PROC
EXTRN sinh:PROC
EXTRN sin:PROC
EXTRN tanh:PROC
EXTRN tan:PROC
; COMDAT ??_C@_0BL@KHOEBBJB@direct?5function?5call?5?$DN?5?$CFg?6?$AA@
CONST SEGMENT
??_C@_0BL@KHOEBBJB@direct?5function?5call?5?$DN?5?$CFg?6?$AA@ DB
'direct '
DB 'function call = %g', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0BH@LIMEHMAH@function?5pointer?5?$DN?5?$CFg?6?$AA@
CONST SEGMENT
??_C@_0BH@LIMEHMAH@function?5pointer?5?$DN?5?$CFg?6?$AA@ DB 'function
poi'
DB 'nter = %g', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0BM@NPLLPAPB@old?5style?5function?5?$CFd?5?$DN?5?$CFg?6?
$AA@
CONST SEGMENT
??_C@_0BM@NPLLPAPB@old?5style?5function?5?$CFd?5?$DN?5?$CFg?6?$AA@ DB
'ol'
DB 'd style function %d = %g', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0BM@CKAFHGKH@new?5style?5function?5?$CFd?5?$DN?5?$CFg?6?
$AA@
CONST SEGMENT
??_C@_0BM@CKAFHGKH@new?5style?5function?5?$CFd?5?$DN?5?$CFg?6?$AA@ DB
'ne'
DB 'w style function %d = %g', 0aH, 00H ; `string'
f DQ FLAT:log
DQ FLAT:log10
DQ FLAT:sqrt
DQ FLAT:cos
DQ FLAT:cosh
DQ FLAT:exp
DQ FLAT:sin
DQ FLAT:sinh
DQ FLAT:tan
DQ FLAT:tanh
DQ 0000000000000000H
PUBLIC __real@3fe0000000000000
PUBLIC main
EXTRN _fltused:DWORD
; COMDAT pdata
; File c:\tmp\tt.c
pdata SEGMENT
$pdata$main DD imagerel $LN17
DD imagerel $LN17+571
DD imagerel $unwind$main
pdata ENDS
; COMDAT xdata
xdata SEGMENT
$unwind$main DD 0a2201H
DD 026822H
DD 0a6414H
DD 095414H
DD 083414H
DD 070105214H
xdata ENDS
; COMDAT __real@3fe0000000000000
CONST SEGMENT
__real@3fe0000000000000 DQ 03fe0000000000000r ; 0.5
; Function compile flags: /Ogtpy
CONST ENDS
; COMDAT main
_TEXT SEGMENT
main PROC ; COMDAT

; 7 : {

$LN17:
00000 48 89 5c 24 08 mov QWORD PTR [rsp+8], rbx
00005 48 89 6c 24 10 mov QWORD PTR [rsp+16], rbp
0000a 48 89 74 24 18 mov QWORD PTR [rsp+24], rsi
0000f 57 push rdi
00010 48 83 ec 30 sub rsp, 48 ; 00000030H

; 8 : int i;
; 9 : f_t *flist = f;
; 10 : for (i = 0; f[i]; i++) {

00014 48 8b 05 00 00
00 00 mov rax, QWORD PTR f
0001b 33 ff xor edi, edi
0001d 0f 29 74 24 20 movaps XMMWORD PTR [rsp+32], xmm6
00022 f2 0f 10 35 00
00 00 00 movsdx xmm6, QWORD PTR __real@3fe0000000000000
0002a 48 8d 1d 00 00
00 00 lea rbx, OFFSET FLAT:f
00031 8b f7 mov esi, edi
00033 48 8b ef mov rbp, rdi
00036 48 85 c0 test rax, rax
00039 74 39 je SHORT $LN6@main
0003b 0f 1f 44 00 00 npad 5
$LL8@main:

; 11 : printf("new style function %d = %g\n", i, f[i]
(0.5));

00040 66 0f 28 c6 movapd xmm0, xmm6
00044 ff d0 call rax
00046 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BM@CKAFHGKH@new?5style?5function?
5?$CFd?5?$DN?5?$CFg?6?$AA@
0004d 8b d6 mov edx, esi
0004f 66 0f 28 d0 movapd xmm2, xmm0
00053 66 49 0f 7e d0 movd r8, xmm2
00058 ff 15 00 00 00
00 call QWORD PTR __imp_printf
0005e 48 8b 44 eb 08 mov rax, QWORD PTR [rbx+rbp*8+8]
00063 48 ff c5 inc rbp
00066 ff c6 inc esi
00068 48 85 c0 test rax, rax
0006b 75 d3 jne SHORT $LL8@main

; 8 : int i;
; 9 : f_t *flist = f;
; 10 : for (i = 0; f[i]; i++) {

0006d 48 8b 05 00 00
00 00 mov rax, QWORD PTR f
$LN6@main:

; 12 : }
; 13 : for (i = 0; f[i]; i++) {

00074 48 8b f7 mov rsi, rdi
00077 48 85 c0 test rax, rax
0007a 74 6d je SHORT $LN1@main
0007c 0f 1f 40 00 npad 4
$LL5@main:

; 14 : printf("old style function %d = %g\n", i, (*f[i])
(0.5));

00080 66 0f 28 c6 movapd xmm0, xmm6
00084 ff d0 call rax
00086 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BM@NPLLPAPB@old?5style?5function?
5?$CFd?5?$DN?5?$CFg?6?$AA@
0008d 8b d7 mov edx, edi
0008f 66 0f 28 d0 movapd xmm2, xmm0
00093 66 49 0f 7e d0 movd r8, xmm2
00098 ff 15 00 00 00
00 call QWORD PTR __imp_printf
0009e 48 8b 44 f3 08 mov rax, QWORD PTR [rbx+rsi*8+8]
000a3 48 ff c6 inc rsi
000a6 ff c7 inc edi
000a8 48 85 c0 test rax, rax
000ab 75 d3 jne SHORT $LL5@main

; 15 : }
; 16 : while (*flist) {

000ad 48 8b 05 00 00
00 00 mov rax, QWORD PTR f
000b4 48 85 c0 test rax, rax
000b7 74 30 je SHORT $LN1@main
000b9 0f 1f 80 00 00
00 00 npad 7
$LL2@main:

; 17 : f_t ff = *flist;
; 18 : printf("function pointer = %g\n", ff(0.5));

000c0 66 0f 28 c6 movapd xmm0, xmm6
000c4 ff d0 call rax
000c6 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BH@LIMEHMAH@function?5pointer?5?
$DN?5?$CFg?6?$AA@
000cd 66 0f 28 c8 movapd xmm1, xmm0
000d1 66 48 0f 7e ca movd rdx, xmm1
000d6 ff 15 00 00 00
00 call QWORD PTR __imp_printf
000dc 48 8b 43 08 mov rax, QWORD PTR [rbx+8]

; 19 : flist++;

000e0 48 83 c3 08 add rbx, 8
000e4 48 85 c0 test rax, rax
000e7 75 d7 jne SHORT $LL2@main
$LN1@main:

; 20 : }
; 21 : printf("direct function call = %g\n", log(0.5));

000e9 66 0f 28 c6 movapd xmm0, xmm6
000ed e8 00 00 00 00 call log
000f2 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
000f9 66 0f 28 c8 movapd xmm1, xmm0
000fd 66 48 0f 7e ca movd rdx, xmm1
00102 ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 22 : printf("direct function call = %g\n", log10(0.5));

00108 66 0f 28 c6 movapd xmm0, xmm6
0010c e8 00 00 00 00 call log10
00111 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00118 66 0f 28 c8 movapd xmm1, xmm0
0011c 66 48 0f 7e ca movd rdx, xmm1
00121 ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 23 : printf("direct function call = %g\n", sqrt(0.5));

00127 66 0f 28 c6 movapd xmm0, xmm6
0012b e8 00 00 00 00 call sqrt
00130 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00137 66 0f 28 c8 movapd xmm1, xmm0
0013b 66 48 0f 7e ca movd rdx, xmm1
00140 ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 24 : printf("direct function call = %g\n", cos(0.5));

00146 66 0f 28 c6 movapd xmm0, xmm6
0014a e8 00 00 00 00 call cos
0014f 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00156 66 0f 28 c8 movapd xmm1, xmm0
0015a 66 48 0f 7e ca movd rdx, xmm1
0015f ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 25 : printf("direct function call = %g\n", cosh(0.5));

00165 66 0f 28 c6 movapd xmm0, xmm6
00169 e8 00 00 00 00 call cosh
0016e 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00175 66 0f 28 c8 movapd xmm1, xmm0
00179 66 48 0f 7e ca movd rdx, xmm1
0017e ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 26 : printf("direct function call = %g\n", exp(0.5));

00184 66 0f 28 c6 movapd xmm0, xmm6
00188 e8 00 00 00 00 call exp
0018d 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00194 66 0f 28 c8 movapd xmm1, xmm0
00198 66 48 0f 7e ca movd rdx, xmm1
0019d ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 27 : printf("direct function call = %g\n", sin(0.5));

001a3 66 0f 28 c6 movapd xmm0, xmm6
001a7 e8 00 00 00 00 call sin
001ac 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
001b3 66 0f 28 c8 movapd xmm1, xmm0
001b7 66 48 0f 7e ca movd rdx, xmm1
001bc ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 28 : printf("direct function call = %g\n", sinh(0.5));

001c2 66 0f 28 c6 movapd xmm0, xmm6
001c6 e8 00 00 00 00 call sinh
001cb 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
001d2 66 0f 28 c8 movapd xmm1, xmm0
001d6 66 48 0f 7e ca movd rdx, xmm1
001db ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 29 : printf("direct function call = %g\n", tan(0.5));

001e1 66 0f 28 c6 movapd xmm0, xmm6
001e5 e8 00 00 00 00 call tan
001ea 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
001f1 66 0f 28 c8 movapd xmm1, xmm0
001f5 66 48 0f 7e ca movd rdx, xmm1
001fa ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 30 : printf("direct function call = %g\n", tanh(0.5));

00200 66 0f 28 c6 movapd xmm0, xmm6
00204 e8 00 00 00 00 call tanh
00209 48 8d 0d 00 00
00 00 lea rcx, OFFSET FLAT:??_C@_0BL@KHOEBBJB@direct?5function?
5call?5?$DN?5?$CFg?6?$AA@
00210 66 0f 28 c8 movapd xmm1, xmm0
00214 66 48 0f 7e ca movd rdx, xmm1
00219 ff 15 00 00 00
00 call QWORD PTR __imp_printf

; 31 : return 0;
; 32 : }

0021f 48 8b 5c 24 40 mov rbx, QWORD PTR [rsp+64]
00224 48 8b 6c 24 48 mov rbp, QWORD PTR [rsp+72]
00229 0f 28 74 24 20 movaps xmm6, XMMWORD PTR [rsp+32]
0022e 48 8b 74 24 50 mov rsi, QWORD PTR [rsp+80]
00233 33 c0 xor eax, eax
00235 48 83 c4 30 add rsp, 48 ; 00000030H
00239 5f pop rdi
0023a c3 ret 0
main ENDP
_TEXT ENDS
END

Showing that the only real differences here are 'spelling' differences
(IOW 'call rax' verses 'call tan').

If we add in virtual functions, we can toss in the cost of a hash
table lookup.

All in all, I think that it is a big waste of time to worry about how
efficient the function calls will be unless you have a deeply nested
loop doing a bazillion function calls where the function execution
time is trivial.

If we choose to use virtual functions, that means it is important to
have replaceable function pointers on the fly. Of course, there is a
small cost to that (essentially a hash table lookup), but it is a cost
we request because of the needed functionality.

Herbert Rosenau

unread,
Oct 12, 2009, 3:55:00 PM10/12/09
to
On Mon, 12 Oct 2009 11:43:01 UTC, James Kuyper
<james...@verizon.net> wrote:

> The three assembly languages I'm familiar with all perform function
> calls by loading a special register with the memory address (a pointer
> value) of the entry point to the function to be called. I'm curious -
> how does the non-pointer way of implementing function calls work?

I know a lot of different assembly languages but none of them has only
a call indirectly.

jsr target, r7 # call subroutine at address given by target,
# use register 7 as stackpointer

jsr r4, r7 # call subroutine whoes target address is in register 4,
# use register 7 as stackpointer

jsr (r6(r2)), r7 # call subroutine
# r6 is a base address and r2 an index, so
# r6 + r2 gives the target address and r7 is the
# stackpointer

another mashine:

jsr <subroutine> ; address of subroutine immediate

jsr @:x ; address to call is in accu (the only general purpose
register)
; store return address in register x
; beside rx index register 1 and ry index register 2
;

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!

Phil Carmody

unread,
Oct 12, 2009, 4:19:09 PM10/12/09
to
Seebs <usenet...@seebs.net> writes:
> On 2009-10-11, Antoninus Twink <nos...@nospam.invalid> wrote:
>> All Carmodey brings to this group is a sycophantic blind support for
>> Heathfield, and a lot of bile directed against anyone and everyone who
>> dares to point out how inadequate his purported knowledge of C is.
>
> Wow, he sure pissed in your anonymous cheerios!

I'm sure the blind sycophantic blind support that I show for Richard
will come as an even greater surprise to Richard than it does to me!

So, are oranges heavier?

Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1

Phil Carmody

unread,
Oct 12, 2009, 4:23:29 PM10/12/09
to
"bartc" <ba...@freeuk.com> writes:
> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
> news:877hv1o...@kilospaz.fatphil.org...

>> Rui Maciel <rui.m...@gmail.com> writes:
>>> Is there a performance penalty associated with the use of function
>>> pointers? If so, how bad is it?
>>
>> Nope, function pointers are faster.
>
> If that was the case then all function calls would be via pointers,
> with the compiler pointerfying direct function calls.

Direct function calls through fixed pointers can indeed often be faster
than calls via function pointers.

But where did he mention the former? Message-id and line number please.

> But oddly I haven't noticed that when I look at asm output.

Maybe you're too busy making ASSumptions.

robert...@yahoo.com

unread,
Oct 12, 2009, 4:52:05 PM10/12/09
to
On Oct 12, 2:55 pm, "Herbert Rosenau" <os2...@pc-rosenau.de> wrote:
> On Mon, 12 Oct 2009 11:43:01 UTC, James Kuyper
>
> <jameskuy...@verizon.net> wrote:
> > The three assembly languages I'm familiar with all perform function
> > calls by loading a special register with the memory address (a pointer
> > value) of the entry point to the function to be called. I'm curious -
> > how does the non-pointer way of implementing function calls work?
>
> I know a lot of different assembly languages but none of them has only
> a call indirectly.


S/360, S/370, etc. until recently. There were basic flavors of
subroutine call, one that was purely indirect, the other was register-
plus-offset. The typical conventions assigned one or more GP
registers as base pointers, each covering 4KB of memory. You could
then directly access (and call or branch to) addresses in one of those
4KB areas by using the reg+offset form of the instructions.

There was no relative or absolute branch or call (well, the reg+offset
form could be used to call any location in the first 4096 bytes of
memory, given the register-0-reads-as-zero implemented on S/360 for
most address computations). Some relative branches and calls did get
added more recently.

James Kuyper

unread,
Oct 12, 2009, 5:08:51 PM10/12/09
to
Herbert Rosenau wrote:
> On Mon, 12 Oct 2009 11:43:01 UTC, James Kuyper
> <james...@verizon.net> wrote:
>
>> The three assembly languages I'm familiar with all perform function
>> calls by loading a special register with the memory address (a pointer
>> value) of the entry point to the function to be called. I'm curious -
>> how does the non-pointer way of implementing function calls work?
>
> I know a lot of different assembly languages but none of them has only
> a call indirectly.

My description was intended to cover both direct and indirect calls. The
only difference between them is the way in which the pointer value ends
up in the register.

jacob navia

unread,
Oct 12, 2009, 5:47:31 PM10/12/09
to
Phil Carmody a �crit :

This person then, calls a constant value "a fixed pointer". When I use
a call instruction, the offset to the start of the called function is
an immediate number embedded in the instruction stream. For this
person this is "a fixed pointer"...

When I write
int a = 543;

then, with the same logic, I am assigning a pointer to an integer,
since 543 is a "fixed pointer". Strange that the compiler doesn't
complain.

Then, (as always) this person starts with insults:

"You are making ASSumptions"

of course that is not an insult to anybody... just , well, just
the caps lock key stuck.

<quote Antoninus>
"Phil" is obviously clueless - a couple days ago he showed us all that
he doesn't know what a heap is, now we learn that he's completely
ignorant about function pointers too.

All Carmodey brings to this group is a sycophantic blind support for
Heathfield, and a lot of bile directed against anyone and everyone who
dares to point out how inadequate his purported knowledge of C is.

<end quote>

bartc

unread,
Oct 12, 2009, 5:51:47 PM10/12/09
to

"Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
news:87r5t8m...@kilospaz.fatphil.org...

> "bartc" <ba...@freeuk.com> writes:
>> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
>> news:877hv1o...@kilospaz.fatphil.org...
>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>> Is there a performance penalty associated with the use of function
>>>> pointers? If so, how bad is it?
>>>
>>> Nope, function pointers are faster.
>>
>> If that was the case then all function calls would be via pointers,
>> with the compiler pointerfying direct function calls.
>
> Direct function calls through fixed pointers can indeed often be faster
> than calls via function pointers.
>
> But where did he mention the former? Message-id and line number please.

So, function pointers are faster than... what then?

>> But oddly I haven't noticed that when I look at asm output.
>
> Maybe you're too busy making ASSumptions.

I've now looked at compiler output for the following program snippet, for
x86 compilers lccwin32, gcc 3.4.5 and DMC. None use indirect calls even at
maximum optimisation levels:

int fib(n) {
if (n<2)
return n;
else
return fib(n- 2)+fib(n- 1);
}

I've even temporarily modified the output of one my compiler projects for a
very similar language to C. Changing the two calls in this function to
memory-indirect calls, at first made it 10% faster! Very interesting.
Unfortunately when I repeated the test it was 10% slower! (But trying to get
meaningful and consistent timings with Intel processors is not easy.)

(Interestingly, my compiler was some 30% faster, on fib(40), than any of the
highly optimised compilers above, usually the performance is abysmal
compared with a proper compiler.)

--
bartc

Phil Carmody

unread,
Oct 12, 2009, 5:52:39 PM10/12/09
to
ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
> By the way, I am sure that those interested could have a better-informed
> discussion over in comp.arch.

Why - do they actually ask sensible questions over there?

Phil Carmody

unread,
Oct 12, 2009, 6:04:10 PM10/12/09
to
Keith Thompson <ks...@mib.org> writes:
> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>> Rui Maciel <rui.m...@gmail.com> writes:
>>> Is there a performance penalty associated with the use of function
>>> pointers? If so, how bad is it?
>>
>> Nope, function pointers are faster.
>
> Could you please expand on this statement? Was it intended as
> a joke? If not, what exactly do you mean?

Was it meaningful?
Was it a direct analogue to the question asked?

If you haven't answered "no, yes" in that order, then let's try a
non-computing analogue:

Subject: Oranges: heavier?
Are oranges heavy? If so, how much heavier are they?

Keith Thompson

unread,
Oct 12, 2009, 6:32:49 PM10/12/09
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:
> Keith Thompson <ks...@mib.org> writes:
>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>> Is there a performance penalty associated with the use of function
>>>> pointers? If so, how bad is it?
>>>
>>> Nope, function pointers are faster.
>>
>> Could you please expand on this statement? Was it intended as
>> a joke? If not, what exactly do you mean?
>
> Was it meaningful?
> Was it a direct analogue to the question asked?
[...]

So you were pointing out that the question, as asked, was
meaningless. And apparently we were supposed to know that your
meaningless answer, unlike the meaningless question, was intended
ironically.

Thanks for (finally) clarifying that.

Alan Curry

unread,
Oct 12, 2009, 6:39:04 PM10/12/09
to
In article <vpCdndvrVe_0gU7X...@bt.com>,
Richard Heathfield <r...@see.sig.invalid> wrote:
>
>Observe:
>
>1) source (cat foo.c)
>
>#include <stdio.h>
>#include <stdlib.h>
>
>int foo(int i)
>{
[...]
>2) readable contents of binary (strings foo) after a normal make:

Might be more convincing if you'd said strings -n 3 since the default
threshold is 4 consecutive printable characters.

--
Alan Curry

Flash Gordon

unread,
Oct 12, 2009, 6:08:37 PM10/12/09
to
jacob navia wrote:

<snip>

> There are TWO costs associated with an indirect function call (i.e.
> through a function pointer)
>
> (1) The direct cost of pipeline problems as I described in my other
> message

I've come across processors with a "call in two instructions time"
instrution, which avoids breaking the pipeline because the processor
executes all of the instructions in the pipeline when the call
instruction is encountered.

> (2) The INDIRECT cost because the call graph is not explicit, what makes
> many optimizations impossible. This second cost is often neglected but
> it is very real.

There may or may not be a cost, it depends on what opportunities there
might be for optimising with a direct call. For example, it might be a
call to a function in a third-party pre-compiled library, so there would
not be any optimisation possible. As others said, it all depends.

> And I will forget about the nonsense of heathfield that tries to make
> a distinction between assembler mnemonics and machine code,

I was using assemblers where the mapping was not 1:1 in the 80s.

> or even
> kuyper that says that all function calls are pointer function calls
> with some citation from the C standard... (even saying that loading the
> value of the call into the instruction pointer is a "pointer" call).

I didn't spot anyone saying anything like that, although I might have
missed the odd post.
--
Flash Gordon

Phil Carmody

unread,
Oct 12, 2009, 7:21:56 PM10/12/09
to
"bartc" <ba...@freeuk.com> writes:
> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
> news:87r5t8m...@kilospaz.fatphil.org...
>> "bartc" <ba...@freeuk.com> writes:
>>> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
>>> news:877hv1o...@kilospaz.fatphil.org...
>>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>>> Is there a performance penalty associated with the use of function
>>>>> pointers? If so, how bad is it?
>>>>
>>>> Nope, function pointers are faster.
>>>
>>> If that was the case then all function calls would be via pointers,
>>> with the compiler pointerfying direct function calls.
>>
>> Direct function calls through fixed pointers can indeed often be faster
>> than calls via function pointers.
>>
>> But where did he mention the former? Message-id and line number please.
>
> So, function pointers are faster than... what then?

Looks like you're finally working it out (clue - if you don't
understand something, there are often additional hints in my
headers).

Anyway, if you think that I can't say they're faster, then
similarly you must agree that others can't say they're slower
for precisely the same reason?

Phil Carmody

unread,
Oct 12, 2009, 7:23:47 PM10/12/09
to
Keith Thompson <ks...@mib.org> writes:
> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>> Keith Thompson <ks...@mib.org> writes:
>>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>>> Is there a performance penalty associated with the use of function
>>>>> pointers? If so, how bad is it?
>>>>
>>>> Nope, function pointers are faster.
>>>
>>> Could you please expand on this statement? Was it intended as
>>> a joke? If not, what exactly do you mean?
>>
>> Was it meaningful?
>> Was it a direct analogue to the question asked?
> [...]
>
> So you were pointing out that the question, as asked, was
> meaningless. And apparently we were supposed to know that your
> meaningless answer, unlike the meaningless question, was intended
> ironically.
>
> Thanks for (finally) clarifying that.

Well, there was always the X-Planation header. ;-)

bartc

unread,
Oct 12, 2009, 7:27:22 PM10/12/09
to

"Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
news:87iqekm...@kilospaz.fatphil.org...

> Keith Thompson <ks...@mib.org> writes:
>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>> Is there a performance penalty associated with the use of function
>>>> pointers? If so, how bad is it?
>>>
>>> Nope, function pointers are faster.
>>
>> Could you please expand on this statement? Was it intended as
>> a joke? If not, what exactly do you mean?
>
> Was it meaningful?
> Was it a direct analogue to the question asked?

No. One was a reasonable question that was understood by most participants
in the thread. The other was apparently a statement of fact by you, and
presumably incorrect.

> If you haven't answered "no, yes" in that order, then let's try a
> non-computing analogue:
>
> Subject: Oranges: heavier?
> Are oranges heavy? If so, how much heavier are they?

That's not the same thing. The implication in the question was clear. A
better analogy would be: Wrapped oranges: is there a weight penalty
associated with the use of wrapped oranges? If so how bad it it?

Which of course depends on the weight of the specific orange and the
properties of the wrapping material. In a few cases a wrapped orange might
be lighter.

For most people, this is not critical. But if you have a lot of oranges...

--
Bart


Keith Thompson

unread,
Oct 12, 2009, 7:50:46 PM10/12/09
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:
> Keith Thompson <ks...@mib.org> writes:
>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>> Keith Thompson <ks...@mib.org> writes:
>>>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>>>> Is there a performance penalty associated with the use of function
>>>>>> pointers? If so, how bad is it?
>>>>>
>>>>> Nope, function pointers are faster.
>>>>
>>>> Could you please expand on this statement? Was it intended as
>>>> a joke? If not, what exactly do you mean?
>>>
>>> Was it meaningful?
>>> Was it a direct analogue to the question asked?
>> [...]
>>
>> So you were pointing out that the question, as asked, was
>> meaningless. And apparently we were supposed to know that your
>> meaningless answer, unlike the meaningless question, was intended
>> ironically.
>>
>> Thanks for (finally) clarifying that.
>
> Well, there was always the X-Planation header. ;-)

Obviously the rest of us just aren't clever enough for your subtle
humor. You might want to consider dumbing it down for us. Or,
equivalently, just write more clearly and directly.

If taken seriously, your "Nope, function pointers are faster" would
have been a dumb statement; it's incomplete (faster than what?) and
most likely incorrect in most contexts if given the obvious
interpretation (function calls made via a pointer-to-function object
are faster than equivalent calls using the name of the function).

You're probably smart enough not to make such mistakes very often,
but I suggest not assuming that everyone else *knows* you're smart
enough not to make such mistakes. As you've seen in this thread,
it didn't work; several people assumed you were serious, and several
others were just confused.

When I write something here, I consider it more my responsibility
to make myself understood than my readers' responsibility to
understand me.

Phil Carmody

unread,
Oct 12, 2009, 7:59:58 PM10/12/09
to
"bartc" <ba...@freeuk.com> writes:
> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
> news:87iqekm...@kilospaz.fatphil.org...
>> Keith Thompson <ks...@mib.org> writes:
>>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>>> Is there a performance penalty associated with the use of function
>>>>> pointers? If so, how bad is it?
>>>>
>>>> Nope, function pointers are faster.
>>>
>>> Could you please expand on this statement? Was it intended as
>>> a joke? If not, what exactly do you mean?
>>
>> Was it meaningful?
>> Was it a direct analogue to the question asked?
>
> No. One was a reasonable question that was understood by most
> participants in the thread. The other was apparently a statement of
> fact by you, and presumably incorrect.
>
>> If you haven't answered "no, yes" in that order, then let's try a
>> non-computing analogue:
>>
>> Subject: Oranges: heavier?
>> Are oranges heavy? If so, how much heavier are they?
>
> That's not the same thing. The implication in the question was
> clear. A better analogy would be: Wrapped oranges: is there a weight
> penalty associated with the use of wrapped oranges? If so how bad it
> it?

That's a worse analogy. I would consider unwrapped oranges to
satisfy the same needs that I originally wanted wrapped oranges
for, and I would consider wrapped oranges to satisfy the same
needs that I originally wanted unwrapped oranges for. The concept
of chosing one or the other is perfectly natural, no matter which
one I had first looked at.

But I would rarely, if ever, treat direct calls to functions
and calls via function pointers to be mutually interchangeable
in the same way. Chosing one or the other would seldom be
an option if I'm already considering function pointers.

If I'm considering function pointers, I'm most likely not looking
at a scenario where direct calls to functions make much sense.
So the comparison should surely not by default be against direct
calls to functions but to other mechanisms of selecting code paths
dynamically, such as switch statements, or echelons of ifs, or
whatever. In which case, function pointers would quite often win.
Unless the compiler not only implemented the fixed function calls
within a switch statement as a jump table, but also realised that
the jumps were all to calls, and thence optimised it to a call
table rather than a jump table. In which case, what it did was
simply create an array of function pointers, because function
pointers were faster for that task.

So my apparently meaningless initial answer wasn't there *just* to
get you to question the question (such as the way an answer of
nothing more than 'mu' might do, perhaps, or a more direct "what
would you be doing otherwise?"), but also to encourage you to
think why I deliberately chose what seemed to be exactly the
wrong answer if you barge through with all assumptions blazing
regarding the original question.

For what I use them for, function pointers /are/ faster*.

Phil

[* than all simple alternatives available to me in the languages
where I use them.]

Seebs

unread,
Oct 12, 2009, 9:56:36 PM10/12/09
to
On 2009-10-12, Phil Carmody <thefatphi...@yahoo.co.uk> wrote:
> ric...@cogsci.ed.ac.uk (Richard Tobin) writes:
>> By the way, I am sure that those interested could have a better-informed
>> discussion over in comp.arch.

> Why - do they actually ask sensible questions over there?

comp.arch is surprisingly good much of the time, once you learn to filter
stuff a bit.

It tends to be a bit over my head, but I keep thinking someday I'll
get more serious about learning this stuff.

Seebs

unread,
Oct 12, 2009, 9:58:32 PM10/12/09
to
On 2009-10-12, Alan Curry <pac...@kosh.dhis.org> wrote:
> Might be more convincing if you'd said strings -n 3 since the default
> threshold is 4 consecutive printable characters.

That depends! Many modern systems, rather than "finding sequences of
printable characters", "find strings" -- meaning, for a file in a known
binary format, they will actually decode the headers and display all
of the symbols and string literals defined, regardless of length.

... Which, let me tell you, is a bit of a shock if you don't know about
it.

Richard Heathfield

unread,
Oct 12, 2009, 10:31:26 PM10/12/09
to
In <87vdikm...@kilospaz.fatphil.org>, Phil Carmody wrote:

> Seebs <usenet...@seebs.net> writes:
>> On 2009-10-11, Antoninus Twink <nos...@nospam.invalid> wrote:
>>> All Carmodey brings to this group is a sycophantic blind support
>>> for Heathfield, and a lot of bile directed against anyone and
>>> everyone who dares to point out how inadequate his purported
>>> knowledge of C is.
>>
>> Wow, he sure pissed in your anonymous cheerios!
>
> I'm sure the blind sycophantic blind support that I show for Richard
> will come as an even greater surprise to Richard than it does to me!

Not at all. All our violent disagreements and public spats are
carefully stage-managed and scripted via the cabal mailing list.
(TINC.)

> So, are oranges heavier?

Unlike apples, oranges are utterly irrelevant to the question of
universal gravitational attraction, so their weight doesn't enter
into it.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Richard Heathfield

unread,
Oct 12, 2009, 10:41:08 PM10/12/09
to

Fair enough. So I did that, without it changing the results. Then I
renamed foo to foofoofoo (in both the caller and the call), and
re-ran the original test, again without it changing the results.

But as it turns out, bartc didn't mean that the function is called by
a name lookup. So I'm darned if I can work out what he /does/ mean -
if you don't call it by name lookup (which is a weird way to do it
but it is at least a vaguely plausible mechanism) and you don't call
it via its address, how the heck /do/ you call it?

James Kuyper

unread,
Oct 12, 2009, 10:37:30 PM10/12/09
to
bartc wrote:
>
> "Phil Carmody" <thefatphi...@yahoo.co.uk> wrote in message
> news:87iqekm...@kilospaz.fatphil.org...
>> Keith Thompson <ks...@mib.org> writes:
>>> Phil Carmody <thefatphi...@yahoo.co.uk> writes:
>>>> Rui Maciel <rui.m...@gmail.com> writes:
>>>>> Is there a performance penalty associated with the use of function
>>>>> pointers? If so, how bad is it?
>>>>
>>>> Nope, function pointers are faster.
>>>
>>> Could you please expand on this statement? Was it intended as
>>> a joke? If not, what exactly do you mean?
>>
>> Was it meaningful?
>> Was it a direct analogue to the question asked?
>
> No. One was a reasonable question that was understood by most
> participants in the thread. ...

Maybe you can enlighten the rest of us to what seems to be missing from
the the original question, and which Rui has failed to explain, despite
repeated requests: "performance penalty" relative to what?

>> If you haven't answered "no, yes" in that order, then let's try a
>> non-computing analogue:
>>
>> Subject: Oranges: heavier?
>> Are oranges heavy? If so, how much heavier are they?
>
> That's not the same thing. The implication in the question was clear. A
> better analogy would be: Wrapped oranges: is there a weight penalty
> associated with the use of wrapped oranges? If so how bad it it?
>
> Which of course depends on the weight of the specific orange and the
> properties of the wrapping material. In a few cases a wrapped orange
> might be lighter.

It also depends upon which alternative you're considering to to
"wrapped oranges": it might be "boxed oranges" or "bagged oranges". One
thing it cannot be, if we're to maintain this analogy, is "unwrapped
oranges", because direct function calls are almost never an adequate
substitute for function pointers in contexts where function pointers are
appropriate.

Seebs

unread,
Oct 12, 2009, 10:41:21 PM10/12/09
to
On 2009-10-13, Richard Heathfield <r...@see.sig.invalid> wrote:
> But as it turns out, bartc didn't mean that the function is called by
> a name lookup. So I'm darned if I can work out what he /does/ mean -
> if you don't call it by name lookup (which is a weird way to do it
> but it is at least a vaguely plausible mechanism) and you don't call
> it via its address, how the heck /do/ you call it?

Maybe you don't; the compiler might have optimized it away.

More likely, I think, would be that you call it as an immediate value
which is looked up by the assembler during the assembly phase, such that
the generated binary just has a jump with an immediate offset of some
sort.

Seebs

unread,
Oct 12, 2009, 10:42:35 PM10/12/09
to
On 2009-10-13, James Kuyper <james...@verizon.net> wrote:
> Maybe you can enlighten the rest of us to what seems to be missing from
> the the original question, and which Rui has failed to explain, despite
> repeated requests: "performance penalty" relative to what?

I assumed "to calling a function by name the ordinary way".

e.g.:

extern int (*p)(int) = putc;

p('\n');
putc('\n');

I would guess that there's no meaningful answer. I would not expect to
see a significant difference in performance between these -- it wouldn't
have even occurred to me to expect that there might be one, although perhaps
there is on some targets.

Richard Heathfield

unread,
Oct 12, 2009, 10:54:23 PM10/12/09
to

> On 2009-10-13, Richard Heathfield <r...@see.sig.invalid> wrote:
>> But as it turns out, bartc didn't mean that the function is called
>> by a name lookup. So I'm darned if I can work out what he /does/
>> mean - if you don't call it by name lookup (which is a weird way to
>> do it but it is at least a vaguely plausible mechanism) and you
>> don't call it via its address, how the heck /do/ you call it?
>
> Maybe you don't; the compiler might have optimized it away.
>
> More likely, I think, would be that you call it as an immediate
> value which is looked up by the assembler during the assembly phase,
> such that the generated binary just has a jump with an immediate
> offset of some sort.

In other words, it's (effectively) a pointer dereference.

Alan Curry

unread,
Oct 12, 2009, 11:17:53 PM10/12/09
to
In article <hLydnX-uasWKek7X...@bt.com>,

Richard Heathfield <r...@see.sig.invalid> wrote:
>In <hb0b68$9ke$1...@aioe.org>, Alan Curry wrote:
>
>>
>> Might be more convincing if you'd said strings -n 3 since the
>> default threshold is 4 consecutive printable characters.
>
>Fair enough. So I did that, without it changing the results. Then I
>renamed foo to foofoofoo (in both the caller and the call), and
>re-ran the original test, again without it changing the results.

Oops, also need -a to search the whole file.

>
>But as it turns out, bartc didn't mean that the function is called by
>a name lookup. So I'm darned if I can work out what he /does/ mean -
>if you don't call it by name lookup (which is a weird way to do it
>but it is at least a vaguely plausible mechanism) and you don't call
>it via its address, how the heck /do/ you call it?

With a direct call instruction, you can determine the destination address if
you know the address of the call instruction, the opcode used, and the value
of its argument. An indirect call requires some extra information from
another memory location and/or another register.

--
Alan Curry

Seebs

unread,
Oct 13, 2009, 12:49:25 AM10/13/09
to
On 2009-10-13, Richard Heathfield <r...@see.sig.invalid> wrote:
> In other words, it's (effectively) a pointer dereference.

Not exactly. At least on some chips, an immediate call is different from
a call through a register; in particular, it's MUCH easier to branch-predict,
because you actually know the exact next location, while a call through
an address register (or an address stored in memory) might be riskier.
(Consider, for instance, what happens to an address stored in memory on
a multi-core machine...)

But!

So far as I can tell, the difference is essentially always trivial. Jacob
pointed out some resources on serious issues with indirect function execution
costs, but they appeared to be primarily about virtual methods in C++, which
are a WILDLY different kind of beast.

Phil Carmody

unread,
Oct 13, 2009, 4:34:09 AM10/13/09
to

Why didn't you all challenge the OP equivalently?

> and
> most likely incorrect in most contexts if given the obvious
> interpretation (function calls made via a pointer-to-function object
> are faster than equivalent calls using the name of the function).
>
> You're probably smart enough not to make such mistakes very often,

As mentioned to Bartc, if you select the right context there isn't
even any mistake.

> but I suggest not assuming that everyone else *knows* you're smart
> enough not to make such mistakes. As you've seen in this thread,
> it didn't work; several people assumed you were serious, and several
> others were just confused.

And what happened when Nick asked:
"""
Message-ID: <3a9651ff-3c8d-4bc3...@g31g2000yqc.googlegroups.com>
If you don't use a funtion pointer what will you do instead
and is that cheaper?
"""
?

Nothing.

And what happens when he then re-iterates:

"""
Message-ID: <ee662df0-3b6d-4373...@p35g2000yqh.googlegroups.com>
> If you don't use a funtion pointer what will you do instead
> and is that cheaper?

you never addressed this point.
If you don't use a function pointer what will you use?
"""
?

Nothing.

Irony apparently worked far better /in the long run/ than the simpler
more direct approach Nick adopted. More direct? It's about as straight
and direct as you can get, and yet it was apparently completely over-
looked! That's quite a negative thing to highlight about the readership
of c.l.c.

It would have been fun if Richard had contributed just a 'mu', to see
what response that would have got.

> When I write something here, I consider it more my responsibility
> to make myself understood than my readers' responsibility to
> understand me.

Whilst that's true, I've never particularly like spoon-feeding
unless there's been a specific request to take things in slow
steady increments.

Phil Carmody

unread,
Oct 13, 2009, 4:37:09 AM10/13/09
to
Seebs <usenet...@seebs.net> writes:
> On 2009-10-12, Alan Curry <pac...@kosh.dhis.org> wrote:
>> Might be more convincing if you'd said strings -n 3 since the default
>> threshold is 4 consecutive printable characters.
>
> That depends! Many modern systems, rather than "finding sequences of
> printable characters", "find strings" -- meaning, for a file in a known
> binary format, they will actually decode the headers and display all
> of the symbols and string literals defined, regardless of length.
>
> ... Which, let me tell you, is a bit of a shock if you don't know about
> it.

The fact that there could be strings which that approach misses would
annoy me greatly. Strings disappearing just because you changed
optimisation flags, for example.

Phil Carmody

unread,
Oct 13, 2009, 4:42:25 AM10/13/09
to
Richard Heathfield <r...@see.sig.invalid> writes:
> In <87vdikm...@kilospaz.fatphil.org>, Phil Carmody wrote:
>> Seebs <usenet...@seebs.net> writes:
>>> On 2009-10-11, Antoninus Twink <nos...@nospam.invalid> wrote:
>>>> All Carmodey brings to this group is a sycophantic blind support
>>>> for Heathfield, and a lot of bile directed against anyone and
>>>> everyone who dares to point out how inadequate his purported
>>>> knowledge of C is.
>>>
>>> Wow, he sure pissed in your anonymous cheerios!
>>
>> I'm sure the blind sycophantic blind support that I show for Richard
>> will come as an even greater surprise to Richard than it does to me!
>
> Not at all. All our violent disagreements and public spats are
> carefully stage-managed and scripted via the cabal mailing list.
> (TINC.)

E-mail's down - it now I hit you over the head with Plaugher, and you
shove burning pages of Shildt down my back, in which case I'll put on
my asbestos underwear?

>> So, are oranges heavier?
>
> Unlike apples, oranges are utterly irrelevant to the question of
> universal gravitational attraction, so their weight doesn't enter
> into it.

Initially I had thought of using 'apple' in the X-planation, but
my g/f persuaded me that apples were, alas, light, and thus would
most likely invoke "no, duh!" responses.

It is loading more messages.
0 new messages