win64 fails a complicated test when run with the JIT in scipy
xref https://github.com/scipy/scipy/issues/15121 and the smaller reproducer in in https://gist.github.com/mattip/346234bc51a8a3afca10ea8929a53df0.
The problem only happens when PyPy JIT kicks in: eventually the python callback in dqegie is called with -1 as an argument instead of a valid value. The code works like this:
-
call
integrate(self, *args, depth=0)
with depth = 0 -
this calls a scipy C function
_quadpack._qagie(func, bound, infbounds, args, full_output, epsabs, epsrel, limit)
wherefunc
is a partial-wrapped version ofintegrate()
wheredepth = 1
,args
is from the call, and the other arguments are float or int. -
inside _qagie(), the C code calls a fortran function where
quadpack_f_t
is the pointer tofunc
void DQAGIE(quadpack_f_t f, double *bound, F_INT *inf, double *epsabs, double *epsrel, F_INT *limit, double *result, double *abserr, F_INT *neval, F_INT *ier, double *alist, double *blist, double *rlist, double *elist, F_INT *iord, F_INT *last);
-
DQAGIE
does an approximation of the integral offunc
by evaluatingfunc
at various values, it ends up callingfunc
many times -
the partial-wrapped call to integrate with
depth=1
calls_quadpack._qagie
again, this timefunc
is a pointer to a C function.
So integrate
is called once as integrate()
, then _qagie
calls DOAGIE
with
func = integrate(floatval, depth=1)
func = c function
func = c function
func = c function
...
func = c function
func = c function
func = c function
func = integrate(floatval, depth=1)
func = c function
func = c function
func = c function
...
func = c function
func = c function
func = c function
...
At some point, when run with the JIT, the floatval
that func
is called with is wrong: it is -1.00
instead of other values. That value get "stuck" and the evaluation of the function fails. This can be seen in the last file in the gist.
I suspect there is some register corruption in the JIT: the calling convention expects a register to be preserved but it is corrupted. Another possibility is some kind of stack smashing, but I would expect that to be detected and crash the process.
@cfbolz suggested running the rpython/jit/backend/test/test_random*
tests, but I don't think they simulate a function call with so many arguments.