At 01:35 PM 2/7/2001 -0200, Branden wrote:
>Dan Sugalski wrote:
> > At 05:41 PM 2/6/2001 -0200, Branden wrote:
> > > > >I actually don't see a reason why the vtable entries should be the
> > >opcodes.
> > > > >Is there?
> > > >
> > > > Speed.
> > > >
> > >
> > >Actually, I don't see the problem of defining a C function that would do:
> > >
> > > void add(SVAR *result, SVAR *lop, SVAR *rop, SVAL *tmp1, SVAL *tmp2)
>{
> > > /* tmp comes from the temporary file */
> > > lop->vtable->FETCH(tmp1, lop);
> > > rop->vtable->FETCH(tmp2, rop);
> > > lop->vtable->ADD(tmp1, tmp1, tmp2);
> > > result->vtable->STORE(result, tmp1, tmp2);
> > > }
> > >
> > >And have it be my opcode. Passing the indexes wouldn't be a problem
>either.
> > >Is there any problem here?
> >
> > Well, no, but what's the point? If you're calling lop's ADD vtable entry,
> > why not have that entry deal with the rest of it, rather than stick things
> > into, and later remove them, from temp slots?
> >
>
>
>Dan,
>
>I see you talk about vtables and opcodes as related things. I really don't
>see why you think that's necessary, I'd like to hear why you think it.
They are. Since the only code that will be calling vtable routines will be
the opcode functions, designing the two to go hand in hand makes sense to me.
>As far as I know (and I could be _very_ wrong), the primary objectives of
>vtables are:
>1. Allowing extensible datatypes to be created by extensions and used in
>Perl.
Secondarily, yes.
>2. Making the implementation of `tie' and `overload' more efficient ('cause
>it's very slow in Perl 5).
No, not at all. This isn't really a consideration as such. (The vtable
functions as desinged are inadequate for most overloading, for example)
>3. Replacing Perl5's SV*,AV*,HV*,... (I don't know if it should replace or
>complement -- ?)
Not really a goal.
You forgot #0.
Go faster.
The big reason is to make the functions that perl calls smaller with fewer
branches. We can't avoid branches--code that makes no decisions is
generally dull--but we want to make as few as we can. Making the vtable
code targeted means the functions don't have to check much at runtime.
>And some secondary objectives are:
>4. Allow the use of different string encodings internally.
Nope. Happy side-effect.
>5. Allow int's and float's to become bigint's and bigfloat's when an
>overflow occurs.
Nope, not a reason for vtables. You can do it just fine without them. (Just
means more code in the opcode functions that do math)
>Is this right or am I missing something?
Missing something, as you can see. That's OK, though. The vtable PDD should
have made all this stuff clear in the preamble text. I've been assuming
folks have been following along since the beginning. (And possibly know
about the other stuff in my head (no, not *that* stuff. The other other
stuff...))
>The point I want to make, is that vtables are directly related to what tie
>and overload are today (or sv_magic, if you want the underlying thing [I
>don't know what's underlying in overload case, as it's apparently not
>documented]).
No, they aren't. tie and overloading are a level or three up from this.
>So I don't really see why opcodes are in the discussion. For
>me, at least, tie and overload are related to data, and opcodes with
>execution. They are orthogonal things, or at least should be (sure that
>doesn't mean they are not related and should be implemented separately, but
>they sure can).
You're thinking at too high a level, or have too many levels jammed
together into one. This really isn't the place to be doing all of
overloading, nor all of tying. Also, since the vtable won't be exposed to
the rest of the world, we don't want to force ties and overloads to use it,
since it means we'll need to change lots of stuff if we toss vtables for
some reason. (like, say, their performance turns out to be bad)
>Of course I understand some opcodes are related to data manipulation, and
>should of course be modelled after vtables, but they surely can be
>separated. Before I proposed the code above for `add', taking 3 SVAR's and
>doing the same as what you proposed (considering no arrays/hashes). I
>thought about it, and I saw that it could be extended to handle 3 PMC's,
>instead of SVAR's. If they are SVAL's, they are passed directly to the
>vtable, otherwise they are fetched/stored using keys that are passed by
>parameters. The add method would be able to determine it by the TYPE vtable
>entry (finally found a use for it...). That would actually result in the
>exact same opcodes that your approach would.
Well, not exactly. If you're fetching data out of arrays and hashes, the
fetch_scalar/get_value pair may well end up creating temporary scalars. If
the source array's declaration is:
my @foo : int;
Then there aren't any scalars inside of @foo, and fetching them out means
creating new ones.
That's why the keys are used, so we can avoid that in some cases.
>Some more about opcode dispatching. What it has to do is:
>1. Fetch an instruction (that would be a byte indicating which operation)
>2. Find the function that handles this instruction (that would be lookup in
>a table)
>3. Call the function (here I refer to the stack handling, of passing and
>returning parameters and return addresses...)
>4. [ Here goes the instruction computing, made by the fetched function ]
>5. Some cleanup (I think nothing really expensive)
>6. Loop. Go back to 1 and fetch the next instruction.
>
>Ok. Am I right here or I'm missing something really dumb?
That's pretty much it, yes.
>If it's this way, what is so expensive here that makes 4 instructions so
>much slower than 1 if the 4 together make the same thing as the 1?
opcode dispatch isn't free. Really, it isn't. It also tends to blow cache.
We can write things so that opcode dispatch is cheaper in perl 6 than it is
in perl 5 (and it's not cheap in perl 5, by any means) but it's still overhead.
Shaving off a few microseconds on an opcode, or by making an opcode that
does the work of two, doesn't seem like much, but it adds up. Quickly.
What we're doing here is, for all intents and purposes, working at the very
lowest level. Microseconds count. Cache misses count. Processor pipeline
stalls count. Every little bit of performance we eat up is paid by every
invocation of every perl program, and indirectly it's paid by every other
program on the system that runs at the same time, since there are fewer CPU
cycles available for them.
At this level we absolutely *must* be near-insanely mindful of performance.
It's second only to adhering to the rules of the perl language in importance.
>Compared
>to what an `add' function would tipically do, testing the argument types,
>and possibly converting things to bigints, or even a `concat' function
>having to allocate memory and copy possibly big blocks of bytes, I don't see
>what's the problem with some CPU cycles to push the parameters to a stack...
The point of the vtables is to avoid most type checking. And while you
might not think it's all that big a deal, it is. Or, rather, it's a little
deal that happens a *lot*.
Try this as an experiment. Build perl 5 with -DDEBUGGING. Then go find a
program that grovels through some data and run it with the -D8 or -Dt flag
set. Look at the output from it. Then go decide whether it's worth it to
cut down on the number of opcode transitions, or the win we'd get from
cutting down the number of opcodes executed by, say, 10%.
Dan
--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
[EMAIL PROTECTED] have teddy bears and even
teddy bears get drunk