Hi Alan,
I'm short on time... so if I don't explain something well, just ask for
clarification and I'll provide more info later.
I know that if you are passing by reference, what is pushed onto the
stack is a pointer to the value and, of course, it must be a field,
not a constant or expression.
To make sure it's clear: Your code CAN pass a constant or expression by
reference, as long as you've coded the CONST keyword on your prototype.
In that case, RPG will evaluate the expression/constant into a temporary
variable and pass the address of that temporary variable.
I know that on other machines, when you pass by VALUE, the compiler
will evaluate what is being passed and decide how to pass it. For
example, if you are passing an integer, the compiler will push the
actual value on the stack. On the AS/400 people have said the AS/400
will create a temporary variable and then pass a pointer to it on the
stack. Is this always going to be true?
VALUE will never pass a pointer. You're confusing VALUE with CONST.
With VALUE, the value of your variable is copied onto the stack. If you
pass an expression or a constant, then the expression or constant is
evaluated and it's value is placed on the stack.
There's never a pointer with VALUE. (Unless you're passing a pointer
data type, of course!)
Will the compiler optimize how variables are passed or will it always
pass a pointer?
Pointers are for REFERENCE parameters. in RPG that means those that do
not specify VALUE (which includes CONST...)
If you are passing by reference, it will always pass a pointer.
Obviously it is a lot more efficient to push the integer on the stack
(4 bytes) instead of creating a work variable, copy the value to it,
get a pointer and push pointer onto the stack (16 bytes) and then
throw away when done.
I'm not sure that "a lot more efficient" is an accurate statement. We
have a 64-bit platform, so presumably it moves 64 bits at a time. Now I
haven't researched what happens under the covers, but it seems to me
that moving a pointer means two operations. Moving an integer would
mean moving 64 bits, but truncating it to 32 bits. Depending on how all
of that is implemented, I could see them both being two CPU operations,
and therefore identical in speed.
Purely a guess of course.. but I wouldn't say it's "a lot more
efficient" -- at best, the performance difference will be extremely slight.
However, for a bigger parameter (like a 64k string, for example) VALUE
will be dramatically slower, since the whole value has to be copied, vs.
16 bytes.
I say use the right tool for the job. Then, test it and determine
whether it performs well enough -- if not, THEN (and only then) optimize it.
The other thing that I have read is that some modern compilers will
reference to the variable straight off the stack instead of popping
the value off the stack.
AFIAK, pretty much all program calls work this way, because they use the
stack for automatic storage as well as parameters. So essentially,
parameters passed by value work just like parameters in automatic
storage. The data isn't copied to the stack, and then copied off into
automatic storage (at least, as far as I know?!)
However, return values, although passed by value, do end up being copied
twice. Return values are not as efficient -- so keep them small.
As an Amazon Associate we earn from qualifying purchases.