Vtable-overridden invokable loses itself as argument #1013

Closed
Util opened this Issue Oct 8, 2013 · 2 comments

2 participants

@Util
Parrot Virtual Machine member

Reported by: zefram@fysh.org

If I override the "invoke" vtable entry for a user-defined class, and then call an object of that class as a function, and pass in the object being invoked as the first argument, then that first argument gets dropped from the invocation. Demonstration (two working cases and then the failing case):

$ cat t52.pir 
.sub "" :anon :init :load
       $P0 = newclass "MyFunc"
.end
.namespace ["MyFunc"]
.sub invoke :vtable
       .param pmc a
       say "ok"
       .return ()
.end
.namespace []
.sub main :main
       $P0 = new "MyFunc"
       $P1 = new "MyFunc"
       $P0("a")
       $P0($P1)
       $P0($P0)
.end
$ ./parrot t52.pir 
ok
ok
too few positional arguments: 1 passed, 2 (or more) expected
current instr.: 'parrot;MyFunc;invoke' pc 6 (t52.pir:5)
called from Sub 'main' pc 40 (t52.pir:16)

As you can see, passing in an unrelated object (a string being autoboxed) works fine. Passing in a different object of the invokable class also works. The failure occurs only when the first argument is the object being invoked. The object does still get invoked; if the signature will accept fewer arguments then the body of the invoke method runs. If there are arguments after the one that disappears then they are received normally, even if they are also the object being invoked.

It looks as though the culprit is this code in the invoke method in object.pmc:

    if ((VTABLE_elements(INTERP, call_sig) == 0
    ||   VTABLE_get_pmc_keyed_int(INTERP, call_sig, 0) != SELF))
        VTABLE_unshift_pmc(INTERP, call_sig, SELF);

It should unshift the invocant unconditionally.

I see no way to work around this bug. If I know that I'm calling an invoke-overridden object, I could pass in the invocant as an extra first argument, suppressing the conditional unshift. But the point of overriding invoke is that I don't have to know what kind of thing I'm calling. If I pass an ordinary Sub itself as a first argument then that behaves as an ordinary argument. So there's no way to call an invokable that works consistently.

-zefram

Summary of my parrot 5.7.0 configuration:
 configdate='Sat Oct  5 12:42:43 2013 GMT'
 Platform:
   osname=linux, archname=x86_64-linux-gnu-thread-multi
   perl=/usr/bin/perl
@rurban rurban self-assigned this Nov 13, 2014
@rurban rurban added a commit that referenced this issue Nov 13, 2014
@rurban rurban [pmc] Object.invoke as vtable: do not strip 2x self
Change experimental usage of vtable overridden invokable of calling
itself. For consistency do not strip self, even when calling itself.

Closes #1013. Thanks to Zefram
dbaf3c9
@rurban
Parrot Virtual Machine member

See branch smoke-me/invoke-self-gh1013
It broke the generated source of ext/winxed/compiler.pir

@rurban rurban added a commit that referenced this issue Nov 13, 2014
@rurban rurban [pmc] Object.invoke as vtable: do not strip 2x self
Change experimental usage of vtable overridden invokable of calling
itself. For consistency do not strip self, even when calling itself.
Instead of pushing we rather change the arg 0 to self.

TODO This broke winxed compiler.compile_from_file()

Closes #1013. Thanks to Zefram
e3209d0
@rurban
Parrot Virtual Machine member

smoke-me/invoke-self-gh1013 is now consistent, the fragile heuristic to see if the first argument is self already is gone.

self is now always pushed, as the semantics of Object.invoke is always in method context.
So self is always accessible and does not need to passed to such methods explictly.
The argument semantics is now also consistent. A :method modifier does not change anything.
Also see http://trac.parrot.org/parrot/ticket/103

@rurban rurban added a commit that referenced this issue Nov 15, 2014
@rurban rurban [pmc] Object.invoke as vtable override: fix unstable self heuristic
Change experimental usage of vtable overridden subs.
Only push self if the sub is a method, otherwise replace it.

Closes #1013. Thanks to Zefram
54e24e9
@rurban rurban added a commit that referenced this issue Nov 15, 2014
@rurban rurban [pmc] Object.invoke as vtable override: fix unstable self heuristic
Change experimental usage of vtable overridden subs.
Only push self if the sub is a method, otherwise replace it.

Closes #1013. Thanks to Zefram
02bf178
@rurban rurban added a commit that referenced this issue Nov 15, 2014
@rurban rurban [test] Clarify Object.invoke access to self
Add to tests that we always have access to self within
Object.invoke'd methods, even if not explictly passed.
This was one unhandled concern in http://trac.parrot.org/parrot/ticket/103
and fixed with GH #1013.
14271cb
@rurban rurban added a commit that closed this issue Nov 15, 2014
@rurban rurban [pmc] Object.invoke as vtable override: fix unstable self heuristic
Change experimental usage of vtable overridden subs.
Always push self, it is always called in method semantics.
$P1($P1) is not needed and not stripped anymore.

Change t/pmc/parrotobject.t tests, and add t/pmc/object-meths.t tests.

Closes #1013. Thanks to Zefram
55a3ccb
@rurban rurban closed this in 55a3ccb Nov 15, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment