On Sun, 14 Sep 2003, Steve Fink wrote:
> I'm not sure how to use the current pdd03's calling conventions to
> implement what I want right now. Let's consider Perl6:
>
> sub f ($a, $b) { ... }
> f(1, 2);
> &f(1, 2);
>
> (I'm not sure if that is correct Perl6 code -- what I mean is that I
> call f once with a perl-level prototype, and once without. Note that a
> perl-level prototype may or may not correspond directly to pdd03's
> notion of a prototype, and most probably will not. See below.)
>
> In the first case, it's easy -- I just do
>
> I0 = 1 # have prototype
> I5 = 1
> I6 = 2
Nope. f is declared as taking two PMCs, so that'd be P5 and P6.
> &f([EMAIL PROTECTED], 2);
>
> Where should I put the value 2? If @x is empty, then it has to go into
> P5 in order for the caller to find it.
[Snip]
> Because we have only up to P15 before we start overflowing into the P3
> aggregate, this is doable. &f([EMAIL PROTECTED], [EMAIL PROTECTED]) isn't even much
> worse; it just
> means you have to concatenate @x and @y into a single destination
> array and then do the same thing. But it's darn ugly and slow.
Dunno about slow, but it is a bit ugly. Indirect register access can help
there.
> Another question for something that will soon be related: why does I1
> contain the number of elements in P3? All of our current aggregates
> can report their current size just fine, and that doesn't seem like
> it's a difficult restriction on the types of aggregates that may be
> used for P3. Unless it's useful to use only a subset of an aggregate
> as function arguments?
It seemed to make sense at the time.
> But that's really just shifting the burden to the receiving end, which
> will now have to filter P5..P(5+L1-1), P3[0..] into the appropriate
> local variables. So what would be even easier, and probably just as
> fast, would be to say that unprototyped functions pass *all* of their
> arguments through the overflow array.
I considered that. The standard is set up for two common cases:
1) The function is prototyped as taking a list of PMCs, with 10 or fewer
named parameters passed in
2) The function is unprototyped but can be found, by static code
inspection, to be taking 10 or fewer named parameters.
In this case, the scheme, while a pain on the calling end, makes the
callee end very simple--the parameters map directly to registers. If
you've a declaration:
sub foo($bar, $baz) {
}
or
sub foo {
my ($bar, $baz) = @_;
}
two common perl idioms, then the compiler can map $bar to P5 and $baz to
P6 directly, without having to do anything. Since the majority of the subs
and/or methods behave like this--taking a small number of parameters, it's
a win on the callee end.
As for the caller... the majority of function/method calls are also made
with a fixed list of unflattened parameters, in which case making a call
like:
foo($xyzzy, $plugh);
is a matter of:
fetch_lex P5, '$xyzzy'
fetch_lex P6, '$plugh'
call 'foo'
(Yeah, I know, sloppy, but you get the idea)
Yes, this does mean that dealing with splatted arrays and hashes is a
bigger pain than it ought otherwise to be, but that's supposed to be (and
generally is now) an uncommon occurrence. That doesn't mean we can't give
engine support to it, however--adding in an op that took a parameter array
in P3 and took the first few items out and loaded them into P5-P15 in one
go (and a corresponding version that respected the calling conventions and
took the elements out of P5-15 and put them onto the beginning of the
array in P3, or any other P we might want)
Having the parameters in the registers will make things easier for
multimethod dispatch as well, which is a not-inconsiderable issue.
> I suppose that was a question for the language list. But then I'd have
> to read the language list.
A fate worse than razor burn, to be sure. Possibly one worse than really
bad Mexican food, but either way I'd not wish it on anyone. :)
Dan