Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MMD vtable functions in bytecode

5 views
Skip to first unread message

Dan Sugalski

unread,
Mar 25, 2004, 2:13:20 PM3/25/04
to perl6-i...@perl.org
So, I'm doing these, because I need 'em, and we might as well get the
things in now. For the record, these things will be called as
functions (not methods), with three parameters, so the signature
looks like:

.pcc_sub thingie prototyped
.param pmc left
.param pmc right
.param pmc dest

.pcc_begin_return
.pcc_end_return
.end

dest will (or had better) be a valid PMC to assign into.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Leopold Toetsch

unread,
Mar 27, 2004, 2:40:50 AM3/27/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:
> So, I'm doing these, because I need 'em, and we might as well get the
> things in now. For the record, these things will be called as
> functions (not methods), with three parameters, so the signature
> looks like:

A short question WRT implementation: shouldn't all MMD functions just
use one function slot? You now seem to duplicate the whole table.

When a C function is inserted, it could be a CSub[1] PMC. When a
bytecode function is registered it overrides the existing (or default) slot
and gets called instead.

Both functions could be called by C<invoke>. The invoke vtable of the
function does the right thing.

One further question: the C<mmddispatch> opcode is supposed to
explicitely run the function, isn't it? Is it needed? Why not just do:

$P0 = $P1 + $P2 # call MMD func if registerd


[1] The current CSub PMC looks totally bogus and seems to be unused. S.
classes/nci.pmc::invoke. The CSub should have the same invoke call.

leo

Leopold Toetsch

unread,
Mar 27, 2004, 5:12:31 AM3/27/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski <d...@sidhe.org> wrote:

[ mmd functions ]

Another question:

,--[ pdd15 ]------------------------------------------------------
| While vtable methods may take a continuation, those
| continuations may not escape the vtable method's
| execution. This is due to the way that vtable methods are
| called by the interpreter--once a vtable method is exited
| any continuation taken within it is no longer valid and
| may not be used.
`-----------------------------------------------------------------

This seems to indicate that there is no rule that this isn't allowed
generally. You could therefore pass a local label address to
another subroutine, which creates a Continuation and invokes that, or
pass the Continuation to yet another sub, which the returns to the
first.

How should we prepare a proper context then, so that when taking the
continuation, everything is restored? Its of course possible to achieve
that in PASM somehow but you can't do that with PIR.

I think, we need some higher-level constructs to deal with
Continuations (s. also a recent discussion with Piers).

Creating a continuation PMC is effectively the same as the call half of
a function call, w/o the call itself. The destination label of a
continuation is the other half of the function call, again w/o the call
itself.

E.g.

set P17, P1 # preserve retc & self
set P18, P2

pushtopp # setup context
cont = newcont cont_label
popttopp # restore contex
...
# return or branch

and:

cont_label:
poptopp
set P1, P17
set P2, P18

But his scheme can only work, when the continuation label is in the same
sub or method as the creation of the continuation.

leo

Dan Sugalski

unread,
Mar 29, 2004, 1:23:53 PM3/29/04
to Leopold Toetsch, perl6-i...@perl.org
At 8:16 PM +0200 3/29/04, Leopold Toetsch wrote:
>Dan Sugalski wrote:

>
>>At 8:40 AM +0100 3/27/04, Leopold Toetsch wrote:
>>>
>>>A short question WRT implementation: shouldn't all MMD functions just
>>>use one function slot? You now seem to duplicate the whole table.
>>
>>
>>Yes, I do.
>
>Did you consider ussng PMCs as instead of plain function pointers.
>As outlined a NCI, C, and PASM Sub PMC would be equally just
>invoke()d.

Yeah, I did. You end up with a twofold problem there--not only do you
have extra indirection but you've also got relatively fat entries in
the table.

For right now I'd like to keep it simple, and the two table approach
is simple. We can poke around and optimize it later, after it's
properly working. Ultimately it ought to be doable to have the JIT,
on JIT capable systems, construct custom C function headers which
means we could skip the second table *and* not bother with PMCs or
anything equally fat for the function entries.

Leopold Toetsch

unread,
Mar 29, 2004, 1:16:37 PM3/29/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:

> At 8:40 AM +0100 3/27/04, Leopold Toetsch wrote:
>>

>> A short question WRT implementation: shouldn't all MMD functions just
>> use one function slot? You now seem to duplicate the whole table.
>
>

> Yes, I do.

Did you consider ussng PMCs as instead of plain function pointers. As
outlined a NCI, C, and PASM Sub PMC would be equally just invoke()d.

leo

Dan Sugalski

unread,
Mar 29, 2004, 9:44:00 AM3/29/04
to l...@toetsch.at, perl6-i...@perl.org
At 8:40 AM +0100 3/27/04, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
>> So, I'm doing these, because I need 'em, and we might as well get the
>> things in now. For the record, these things will be called as
>> functions (not methods), with three parameters, so the signature
>> looks like:
>
>A short question WRT implementation: shouldn't all MMD functions just
>use one function slot? You now seem to duplicate the whole table.

Yes, I do.

There are two ways I can see to do this. The first is to have some
sort of unified table structure, which holds tagged entries, and the
dispatch code checks the entries and dispatches. This'll take as much
memory as we currently use. (Alternately the entries themselves can
be larger, in which case the usage will be based on the sparseness of
the table) It's also slower in all cases, since you're forced to do
the flag check and dispatch and you've drastically lowered the cache
coherency

The second way is to use the split table struct, which is what I did.
Still have the check, but it's unified with the C function case so it
takes a single word rather than two, which ups the cache density
some. If I could've managed, I'd build up a real C function for each
vtable entry in bytecode, but that's not portable, unfortunately. (I
*really* wish C did currying...) I considered having an "Execute the
vtable function in bytecode" generic function that got passed the X
and Y to look up in the table and dispatch, but that adds a pair of
parameters that're otherwise unneeded and that slows things down too.

Besides, this is all behind-the-scenes stuff--nothing external should
know about the inside structure. If we want real efficiency we're
going to need to compress the tables a lot better than we do now
(since we don't actually compress the tables now). I've a paper on
that which I'm trying to dig up an external reference for. (I'll post
when I have it)

Chromatic

unread,
Mar 29, 2004, 1:29:50 PM3/29/04
to Dan Sugalski, perl6-i...@perl.org
On Mon, 2004-03-29 at 10:23, Dan Sugalski wrote:

> Ultimately it ought to be doable to have the JIT,
> on JIT capable systems, construct custom C function headers which
> means we could skip the second table *and* not bother with PMCs or
> anything equally fat for the function entries.

Would being able to do that also make NCI thinner?

-- c

Dan Sugalski

unread,
Mar 29, 2004, 1:41:27 PM3/29/04
to chromatic, perl6-i...@perl.org

It'd use the same mechanism. NCI's currently quite thin on systems
where the JIT can create function headers.

Dan Sugalski

unread,
Mar 29, 2004, 12:04:52 PM3/29/04
to l...@toetsch.at, perl6-i...@perl.org
At 11:12 AM +0100 3/27/04, Leopold Toetsch wrote:
>Dan Sugalski <d...@sidhe.org> wrote:
>
>[ mmd functions ]
>
>Another question:
>
>,--[ pdd15 ]------------------------------------------------------
>| While vtable methods may take a continuation, those
>| continuations may not escape the vtable method's
>| execution. This is due to the way that vtable methods are
>| called by the interpreter--once a vtable method is exited
>| any continuation taken within it is no longer valid and
>| may not be used.
>`-----------------------------------------------------------------
>
>This seems to indicate that there is no rule that this isn't allowed
>generally.

You've got me confused here.

That note in PDD15 is there to try and make it clear that
continuations can't cross a C/Parrot boundary. For example, if we
have:

Parrot(1) -> C -> Parrot(2)

as a call scheme, such as we'd have with making a vtable function
call (since parrot calls into C, and the C code then calls back into
parrot) any continuation taken at the Parrot(2) level can't escape
back and be invoked in code at the Parrot(1) level. To do so we'd
need to save the system stack, which is problematic.

Leopold Toetsch

unread,
Mar 29, 2004, 2:40:40 PM3/29/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:

> You've got me confused here.

Well, the question is: Is it allowed to create a continuation in one
subroutine with the destination label being in a different subroutine?

.sub _f1
label = get_addr dest_label
_f2(label)
...
dest_label:
.end

.sub _f2
.param int lab
cont = newcont lab
...
cont()
.end

That's technically possible. But it's not solvable to create proper code
at the dest_label to restore register stacks.

leo

Dan Sugalski

unread,
Mar 29, 2004, 2:59:00 PM3/29/04
to Leopold Toetsch, perl6-i...@perl.org
At 9:40 PM +0200 3/29/04, Leopold Toetsch wrote:
>Dan Sugalski wrote:
>
>>You've got me confused here.
>
>Well, the question is: Is it allowed to create a continuation in one
>subroutine with the destination label being in a different
>subroutine?

Oh, OK.

Erm. No. Mostly.

Subs must be considered self-contained--the only way to get out of
them is to invoke a continuation. However.... I can see uses for
leaving the body of a sub, for example if the compiler decided to
factor out code common across multiple subs into a single chunk
that's bsr'd into.

For now, let's say subs are self-contained and you can't use
addresses outside them. We may lift that restriction later, though.

Leopold Toetsch

unread,
Mar 29, 2004, 3:24:09 PM3/29/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:

> At 8:16 PM +0200 3/29/04, Leopold Toetsch wrote:
>> Did you consider ussng PMCs as instead of plain function pointers. As
>> outlined a NCI, C, and PASM Sub PMC would be equally just invoke()d.
>
>
> Yeah, I did. You end up with a twofold problem there--not only do you
> have extra indirection but you've also got relatively fat entries in the
> table.

Indirection yes. But the entry is of course a pointer to a sub-like PMC.
I think such PMCs (CSub, NCI, PASM-Sub) would be rather long-lived, so
they could be constructed in the constant PMC pool. The overhead is only
at construction time (at module load or such). The indirection remains
(which is about one if () ). But this scheme needs just one table.
Second is symmetry: Currently only C code can register a C MMD function.
If the function pointer is a PMC*, PASM code can register a C function
(via NCI) or a PASM function too.


> For right now I'd like to keep it simple, and the two table approach is
> simple. We can poke around and optimize it later, after it's properly
> working.

Ack

leo

Leopold Toetsch

unread,
Mar 29, 2004, 3:28:24 PM3/29/04
to Dan Sugalski, perl6-i...@perl.org
Dan Sugalski wrote:

[ cvs ci library/vtable_constants.pasm ]

Isn't working IMHO. C<.const int ..> is PIR syntax. *And* that file
could be easily auto-created like almost all inside
F<runtime/parrot/include/>

leo

Dan Sugalski

unread,
Mar 29, 2004, 4:03:12 PM3/29/04
to Leopold Toetsch, perl6-i...@perl.org

Ah, damn, that's what I get for not double-checking my working
directory stuff. I'll see about fixing that.

Dan Sugalski

unread,
Mar 29, 2004, 4:13:50 PM3/29/04
to Leopold Toetsch, perl6-i...@perl.org
At 10:24 PM +0200 3/29/04, Leopold Toetsch wrote:
>Dan Sugalski wrote:
>
>>At 8:16 PM +0200 3/29/04, Leopold Toetsch wrote:
>>>Did you consider ussng PMCs as instead of plain function pointers.
>>>As outlined a NCI, C, and PASM Sub PMC would be equally just
>>>invoke()d.
>>
>>
>>Yeah, I did. You end up with a twofold problem there--not only do
>>you have extra indirection but you've also got relatively fat
>>entries in the table.
>
>Indirection yes. But the entry is of course a pointer to a sub-like
>PMC. I think such PMCs (CSub, NCI, PASM-Sub) would be rather
>long-lived, so they could be constructed in the constant PMC pool.
>The overhead is only at construction time (at module load or such).
>The indirection remains (which is about one if () ). But this scheme
>needs just one table.
>Second is symmetry: Currently only C code can register a C MMD
>function. If the function pointer is a PMC*, PASM code can register
>a C function (via NCI) or a PASM function too.

Sure, but if you've an NCI function you might as well directly
register it and skip the extra indirection. :)

Anyway, it won't be too long before bytecode can register MMD
functions, albeit only bytecode functions. I'll expose that API to C
code as well while I'm at it.

0 new messages