At 9:50 AM +1000 4/29/02, Andrew J Bromage wrote:
>G'day all.
>
>On Sun, Apr 28, 2002 at 11:44:04AM -0400, Dan Sugalski wrote:
>
>>  We're going caller-save. I think I made this declaration before,  but
>>  now it's backed up with pure PDD goodness. :)
>
>The first thing to realise is that this violates the principle of
>"callee does everything important to it". :-)

Sure, but saving registers isn't something the callee finds 
important. The saved registers aren't important to it.

>More seriously, this is the opposite extreme, and IMO it's also not
>a good idea.

Welcome to my world. They're all bad ideas in some way or, rather, 
they're all equally as good.

>OO code is full of subs which a) are called very often and b) look
>like this:
>
>       sub code
>       {
>         my $self = shift;
>         return $self->{CODE};
>       }
>
>       sub body
>       {
>         my $self = shift;
>         if (@_) {
>           $self->{BODY} = shift;
>         }
>
>         return $self->{BODY};
>       }

Yup, caller save doesn't necessarily favor code like this. On the 
other hand, it does favor recursive code and code with heavier-weight 
bodies. It's always a toss-up. Nothing's free, and all decisions have 
consequences of some sort.

>Maybe half a dozen registers used in each one at the most.  A caller is
>obliged to save _all_ its registers in order to call these trivial
>subs.

Nope, just the registers it needs preserved across calls. It needs to 
save the data that *is* relevant, where on callee save the data that 
*might* be relevant needs saving. The question, of course, is whether 
there's as much potentially relevant data as actually relevant data.

Assuming that the caller and callee spend about the same amount of 
time saving data (An assumption that's a bit dodgy there, as it's 
based on the coding style the language encourages) caller-save is 
ultimately a bit less expensive, as making tail calls avoids a 
push/pop pair, which callee-save can't avoid.

>Now admittedly we have a single op for this, so at least in the
>interpreter it may not cost as much as a whole bunch of individual
>register saves.  For other targets (JIT), unnecessary caller saves will
>almost certainly cause a measurable performance hit on OO-like code.

Just for chuckles, I went and benchmarked things, as meaningless 
numbers are useful to have. With my current GCC3/-O3 build of parrot, 
the cost to do 10,000,000 sets of saves is as follows:

save all: 5.3 sec usertime
   save 1: 2.6 sec user
   save 2: 4.7 sec user
   save 3: 6.8 sec user

Saving all of them was done with pushp. The empty loop took .48 
seconds if you want to factor that out. JITting, at the moment, 
doesn't do much for the time, but that's mainly because the push and 
pop routines are relatively heavyweight as these things go.
-- 
                                         Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski                          even samurai
[EMAIL PROTECTED]                         have teddy bears and even
                                       teddy bears get drunk

Reply via email to