[Cython] Out of order side effects of argument evaluation in function calls (ticket #654)
robertwb at math.washington.edu
Fri Mar 11 19:33:02 CET 2011
On Fri, Mar 11, 2011 at 9:36 AM, Stefan Behnel <stefan_ml at behnel.de> wrote:
> Stefan Behnel, 11.03.2011 15:08:
>> Vitja Makarov, 11.03.2011 15:04:
>>> 2011/3/11 Stefan Behnel:
>>>> Personally, I think it would be nice to keep up Python's semantics, but
>>>> I implemented this I broke quite some code in Sage (you may have noticed
>>>> that the sage-build project in Hudson has been red for a while). There
>>>> things in C and especially in C++ that cannot be easily copied into a
>>>> temporary variable in order to make sure they are evaluated before the
>>>> following arguments. This is not a problem for Python function calls
>>>> all arguments end up being copied (and often converted) anyway. It is a
>>>> problem for C function calls, though.
>>>> f(g(a), a.x, h(a))
>>> Why could not this be translated into:
>>> tmp1 = g(a)
>>> tmp2 = a.x
>>> tmp3 = h(a)
>>> f(tmp1, tmp2, tmp3)
>> See above.
> To be a little clearer here, it's a problem in C for example with struct
> values. Copying them by value into a temp variable can be expensive,
> potentially twice as expensive as simply passing them into the function
Yep, and some types (e.g. array types) can't be assigned to at all.
FWIW, the issues with Sage is that many libraries use the "stack
allocated, pass-by-reference" trick
typedef foo_struct foo_t
but we have declared them to be of type "void*" because we don't care
about or want to muck with the internals. Cleaning this up is
something we should do, but is taking a while, and aside from that it
makes Cython even more dependent on correct type declarations (and
backwards incompatible in this regard). Sage is a great test for the
buildbot, so keeping it red for so long is not a good thing either.
> Not sure what kind of additional devilry C++ provides here, but I'd expect
> that object values can exhibit bizarre behaviour when being assigned. Maybe
> others can enlighten me here.
Yes, C++ allows overloading of the assignment operator, so assigning
may lead to arbitrary code (as well as probably an expensive copy, as
with structs, and structs in C++ are really just classes with a
> I have no idea how many cases there actually are that we can't handle or
> that may lead to a performance degradation when using temps, but the problem
> is that they exist at all.
Note that this applies not just to function arguments, but a host of
other places, e.g. the order of evaluation of "f() + g()" in C is
unspecified. Fleshing this out completely will lead to a lot more
temps and verbose C code. And then we'd just cross our fingers that
the C compiler was able to optimize all these temps away (though still
possibly producing inferior code if it were able to switch order of
Whatever we do, we need a flag/directive. Perhaps there's a way to
guarantee correct ordering for all valid Python code, even in the
presence of (function and variable) type inference, but allow some
leeway for explicitly declared C functions.
More information about the cython-devel