Leopold Toetsch wrote:

Sam Ruby <[EMAIL PROTECTED]> wrote:

Leopold Toetsch wrote:


... But that doesn't
work fur user methods, especially if there is no indication that a user
function is used as a method in the first place.

 def find(s, sub):
   ...


In Python, this is statically determinable.  If that sequence is
directly nested inside a class, it is a method, otherwise it is a
function.


No, we had that several times. You did show examples, where this isn't
true. Here is another one:

def add(l, r):
    print "in add"
    return 42

class C(object):
    __add__ = add

c = C()
print c + 1

"add" is just a plain function. There is no indication whatsoever that
it might be used as a method, when "add" is compiled. But as infix<+> is
a method call "l.__add__(r)" this doesn't work, if the object is in P2.


I've proposed several times that arguments including the object should be
passed from P5 up. The invocant - if any - can still be reachable with
the C<interpinfo> opcode, but it'll be probably used just in calls to SUPER
or next_method or such.


Less shifting will be required if the object is passed in P2.


That's only true for NCI methods. And IIRC, your arguments were the same
some time ago. How do you compile the "add" above, when the object is in
P2?


Notes: at the moment, every Python method call creates a bound object,
and shifts PMC arguments.

This shouldn't be necessary for "normal" method calls like:

s.f("r")


But this translates into two VTABLE calls.  find_method and invoke.
find_method needs to return a bound method.


Why don't you just use the "callmethodcc" opcode? That's exactly what is
happening here.


A find_method_and_invoke VTABLE entry (or more simply call_method) would
not need to return the intermediary bound method.


There is no need for an intermediate object, if it's a plain method
call.


If there were a call_method VTABLE entry and if P2 were passed into
methods, all of this would be unecessary in the majority of cases.

A separate vtable slot doesn't really help. Code that looks like a function call can actually be a method call (and vv). Separating the call into two vtables will just duplicate the call sequence. But let's first convince Dan that all arguments are passed from P5 up, then we'll see what we have.


Less shifting will be required if the object is passed in P2.


See above.

And why are you duplicating object arguments into P5, if the object
should go into P2?

,--[ dynclasses/pyint.pmc ]-----------
|     METHOD PMC* __hex__(PMC *self) {
`-------------------------------------

You are inventing an additional "self" argument here just to work around
the problem that the object is passed in P2. The actual object "pmc" is
ignored:

,--[ dynclasses/pyint.c ]---------------------------------------
| PMC*
| Parrot_PyInt___hex__(Interp* interpreter, PMC* pmc, PMC *self)
`---------------------------------------------------------------

As said in another message, there is no problem with NCI methods. It's
just a matter of translating the "O" signature char.

The problem are user functions. There might be an indication that's a
method (like a definition inside a class block) - but not always. And if
the latter is the case *only once*, we just have to call all methods
with plain function call argument passing. Or prepend *all* functions
with an argument check wrapper that shift arguments around, if the call
was actually a method call.

The current CVS is in a state of transition.

I originally implemented to the current set of PDDs. Unhappy with the amount of copying of PMC registers, I optimistically converted over to the "pass self as P5" approach that you suggested. I found that that simply moved the problem to other places, and copying was unavoidable. In fact, it generally made things worse.

Given that copying is unavoidable, what I would like to do is to optimize for what I consider the most common cases, and make all the remaining cases work properly.

The common cases I want to optimize for are common functions being called as common functions. And common methods being called as methods.

The easiest way to optimize for the common methods being called as methods is if the current object is not passed as the first argument.

Yes, copying will be required in cases where functions are called as methods.

- Sam Ruby

Reply via email to