[Python-Dev] Re: a serious threat to 2.3's speed?

Duncan Booth duncan at rcp.co.uk
Thu Dec 11 11:35:57 EST 2003

Skip Montanaro <skip at pobox.com> wrote in
news:16344.38379.89674.176847 at montanaro.dyndns.org: 

> Python's function call machinery is complex, mostly in the argument
> marshalling area I think.  Take a look in Python/ceval.c at
>     call_function
>     fast_function
>     do_call
>     ext_do_call
>     update_keyword_args
>     update_star_args
> If Jim's compiler doesn't yet support any of varargs, keyword args,
> calling C functions or calling bound method objects, I suspect his
> code is more streamlined.

I've been working on my own implementation of Python for .Net, although 
I've now emailed Jim to ask if I can help him with his since he seems to be 
further on that I am with my version.

The way I was planning to do function calls (and had partially implemented 
it), was to have an IPyCallable interface, and a set of classes that 
implement that interface.

The interface includes methods:

   PyObject __call__();
   PyObject __call__(PyObject arg1);
   PyObject __call__(PyObject arg1, PyObject arg2);
   PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3);
   PyObject __call__(PyObject[] args);
   PyObject __call__(PyObject[] args, PyDict keywordArgs);

Concrete classes exist for functions and for bound methods taking 0, 1, 2, 
3 or more arguments. The constructor for a function object takes a 
delegate, a list of argument names and a list of defaults.

The idea was that, say you had a function taking 3 arguments and you call 
it with 3 arguments, the call can be passed straight through without doing 
any checking at all for default args or keyword args, so one virtual call 
then a delegate call. If you call it with fewer arguments the earlier 
overloads simply add in the missing defaults. This should allow pretty well 
all calls to be streamlined so you only pay for the overhead of variable 
number of arguments or keywords if you actually use them in the call, and 
even then you don't have a string to interpret at runtime.

I was planning to create function wrappers at runtime, so that a method 
that took say a string and an integer would be wrapped by a static function 
taking three PyObject arguments and casting them appropriately before 
forwarding to the wrapped method. So a Python call to a method would get 
directed through the function object which calls the delegate to the 
wrapper which does any necessary casts and calls the underlying method. In 
practice some of these nested calls should be optimisable by the JIT.

Anyway, that was my scheme. I wonder what Jim's is.

Duncan Booth                                             duncan at rcp.co.uk
int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3"
"\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure?

More information about the Python-Dev mailing list