Re: function pointers vs internal procedures as arguments

Re: function pointers vs internal procedures as arguments

Steve Lionel (Intel)'s picture

Passing an internal procedure as an argument does not involve copying routine code to the stack! (At least not in CVF.) There is some context information for up-level referencing pushed, however.

Any problems with CVF should be sent to vf-support@compaq.com, as always. That won't change for quite a while.

Steve

Steve
5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.
Steve Lionel (Intel)'s picture

I'm not aware of any penalty other than perhaps a few instructions to set up the up-level context. The contents of the routine shouldn't matter. The only thing that would give me pause is that this is non-standard, so if you don't need to do this, it might be best to avoid it.

Steve

Steve
Jugoslav Dujic's picture

Steve, I think it's mea culpa about the information on copying code to stack -- just, I'd swear I've heard it from you... maybe I'm wrong.

Nevertheless, out of curiosity, how are references to host's dummy arguments & automatic variables resolved then? I'm not sufficiently profficient in assembly to check it myself; one way that comes to my mind is to use a prologue/epilogue "driver" routine, kind of (pseudo code):

old_esp = ESP
ESP = host_esp
push arguments
call internal_routine
ESP = old_esp
ret

and put address of that "routine" to callee's list. Is it something along these lines?

Jugoslav

Jugoslav www.xeffort.com
Jugoslav Dujic's picture

Oh, just realized the code above won't do good, since it will create mess out of callee's stack -- instead, all host's stack environment must be copied to stack instead of messing with ESP.

Jugoslav www.xeffort.com
Steve Lionel (Intel)'s picture

I had to ask some people and do some research - here's what it does...

There is an address used as a base for the local context (local being the host of the contained procedure). From this base, all accessible variables are at (or can be located through) known offsets.

When you pass a contained procedure, eight instructions are used to construct the following code sequence on the stack (but in a fixed location in the caller's stack frame):

mov ecx, actual routine address
mov eax, context pointer
jmp ecx

The address of this constructed routine is what is passed as an argument. Note that this routine doesn't modify the stack, so the normal stack pushes and pops for the real arguments will work ok. The internal procedure uses eax to find the context and locate the host-associated variables.

Therefore, the overhead for passing an internal procedure is eight instructions to pass, plus another three when the routine is actually called.

We do much the same thing for VFEs, which have the same general need.

I note that there's room for improvement here - if you pass the same internal procedure more than once in a given routine, the same mini-routine is rebuilt each time.

We're currently in the middle of "reimplementing" this using the Intel code generator, since Intel Fortran doesn't yet support this extension (and they do VFEs in a rather inelegant fashion.) The details may vary slightly in the new Intel Visual Fortran from the way CVF does it.

Steve

Steve

Login to leave a comment.