[perl #41733] invoke :vtable - execution stops

0 views
Skip to first unread message

Richard @ Hive-Systems . Com

unread,
Mar 7, 2007, 11:14:17 AM3/7/07
to bugs-bi...@rt.perl.org
# New Ticket Created by ric...@hive-systems.com
# Please include the string: [perl #41733]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=41733 >


Hi There,

Given the following (latest svn today - parrot 0.49+):


.namespace ['Foo']

.sub invoke :vtable
say "you invoked me!"
.return()
.end

.sub main :main
$P0 = newclass "Foo"
$P1 = new "Foo"
$P1()
say "got here"
.end

The final "got here" is never printed.

Also parrot segfaults with the signature:
.sub invoke :vtable :method
...
.end

Not sure if that's allowed (:vtable :method), though.

Cheers,
Rich

Alek Storm

unread,
Mar 7, 2007, 7:26:04 PM3/7/07
to perl6-i...@perl.org, bugs-bi...@rt.perl.org
The invoke vtable method is supposed to take one argument - the
address of the opcode immediately following the invokecc opcode, so we
can return to it later. It then returns the address of the subroutine
to jump into. The problem is that, in C, the invoke method takes and
returns an opcode_t*, and PIR can't handle that, so I've attached a
patch correcting the problem by converting the argument and return
value so the PIR plays nice.

Any ParrotObject overriding the invoke vtable method is probably not
going to care about addresses. Luckily, all we have to do is return
the address we're given, so everything goes back to normal after the
method's finished. The downside is that you're going to have to come
with a more creative workaround in order to be passed any arguments
that the method is called with.

.namespace ['Foo']

.sub __invoke :method
.param int address
say "you invoked me!"
.return(address)
.end

.sub main :main
$P0 = newclass "Foo"
$P1 = new "Foo"
$P1()
say "got here"
.end

Thanks,
Alek Storm

On 3/7/07, via RT richard @ hive-systems. com

invoke.patch

Matt Diephouse

unread,
Mar 7, 2007, 8:02:20 PM3/7/07
to Alek Storm, perl6-i...@perl.org, bugs-bi...@rt.perl.org
Alek Storm <alek....@gmail.com> wrote:
>
> The invoke vtable method is supposed to take one argument - the
> address of the opcode immediately following the invokecc opcode, so we
> can return to it later. It then returns the address of the subroutine
> to jump into. The problem is that, in C, the invoke method takes and
> returns an opcode_t*, and PIR can't handle that, so I've attached a
> patch correcting the problem by converting the argument and return
> value so the PIR plays nice.
>
> Any ParrotObject overriding the invoke vtable method is probably not
> going to care about addresses. Luckily, all we have to do is return
> the address we're given, so everything goes back to normal after the
> method's finished. The downside is that you're going to have to come
> with a more creative workaround in order to be passed any arguments
> that the method is called with.
>

I don't think that's the right route to take. Exposing the pc to PIR-land
code seems dangerous and I don't think there's much point. As a PIR user, I
want the invoke vtable to behave just like any other PIR subroutine.

This gets us close to what I want:

void* invoke(void *next) {

STRING *meth = CONST_STRING(interp, "__invoke");

STRING *meth_v = CONST_STRING(interp, "invoke");

PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);

if (PMC_IS_NULL(sub))

sub = find_or_die(interp, pmc, meth);

(void*) Parrot_run_meth_fromc_args(interp, sub,

pmc, meth, "??", next);

return next;

}

I've tested it and it works with the original code that Richard gave. The
only thing left to do is handle return values; I'm still working on that. If
I can get return values working properly, I'll check in a fix.

--
Matt Diephouse
http://matt.diephouse.com

Chromatic

unread,
Mar 7, 2007, 8:06:44 PM3/7/07
to perl6-i...@perl.org, ma...@diephouse.com, Alek Storm
On Wednesday 07 March 2007 17:02, Matt Diephouse wrote:

> I don't think that's the right route to take. Exposing the pc to PIR-land
> code seems dangerous and I don't think there's much point. As a PIR user, I
> want the invoke vtable to behave just like any other PIR subroutine.

Agreed.

> This gets us close to what I want:
>
>
>
> void* invoke(void *next) {
>
> STRING *meth = CONST_STRING(interp, "__invoke");
>
> STRING *meth_v = CONST_STRING(interp, "invoke");
>
> PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
>
> if (PMC_IS_NULL(sub))
>
> sub = find_or_die(interp, pmc, meth);
>
> (void*) Parrot_run_meth_fromc_args(interp, sub,
>
> pmc, meth, "??", next);

That probably works, with the caveat that the Parrot_run_*_fromc*() functions
seem to have big problems with multisubs.

-- c

Matt Diephouse via RT

unread,
Mar 8, 2007, 12:17:30 PM3/8/07
to perl6-i...@perl.org
On Wed Mar 07 17:02:47 2007, mdiep wrote:
> This gets us close to what I want:
>
>
>
> void* invoke(void *next) {
> STRING *meth = CONST_STRING(interp, "__invoke");
> STRING *meth_v = CONST_STRING(interp, "invoke");
> PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
> if (PMC_IS_NULL(sub))
> sub = find_or_die(interp, pmc, meth);
> (void*) Parrot_run_meth_fromc_args(interp, sub,
> pmc, meth, "??", next);
> return next;
> }

We all missed the obvious solution: just invoking the sub, rather than entering a new
runloop. This has the benefits of not creating a new runloop and of handling parameters and
return values properly. It may even make invoke work with :multi (it might need a bit more
work for that).

Fixed in r17385.

--
Matt Diephouse


void* invoke(void *next) {
STRING *meth = CONST_STRING(interp, "__invoke");
STRING *meth_v = CONST_STRING(interp, "invoke");
PMC *sub = Parrot_find_vtable_meth(interp, pmc, meth_v);
if (PMC_IS_NULL(sub))
sub = find_or_die(interp, pmc, meth);

INTERP->current_object = SELF;
return VTABLE_invoke(interp, sub, next);
}


Alek Storm

unread,
Mar 9, 2007, 9:58:59 PM3/9/07
to parrotbug...@parrotcode.org
That is definitely the most elegant solution. Now, the question is, shouldn't the invoke() vtable method behave that way in the first place, since passing a pc address to and returning another pc address from the invoke() method only makes sense for Sub, Coroutine, and Continuation? In other words, invoke() shouldn't be reliant on bytecode.

Alek Storm

unread,
Mar 9, 2007, 11:08:04 PM3/9/07
to parrotbug...@parrotcode.org
Following conversation with Matt Diephouse on #parrot, I realized that
that was pretty confusing. What I meant was that invoke() should
accept parameters and return values as a normal subroutine. This
would probably be done by moving the code that deals with the pc out
of the invoke() method and into the invokecc opcode. This would
result in invoke() being abstracted away from dealing with the pc.
Reply all
Reply to author
Forward
0 new messages