[MLton] Bug in IntInf implementation
Matthew Fluet
fluet at tti-c.org
Fri Dec 7 13:30:23 PST 2007
On Fri, 7 Dec 2007, Wesley W. Terpstra wrote:
> The version: (at least) svn/HEAD
> boom.sml:
>> val x : IntInf.int = 1
>> val y = IntInf.<< (x, 0w838860800) (* 100MB *)
>> val () = print "unreached\n"
>
> The bug:
> initIntInfRes in runtime/gc/int-inf.c points a GMP limb buffer at the heap.
> It has no reason to believe the current heap can contain the result. Normally
> the mpz_* functions will gmp_realloc memory when needed. I have no idea what
> will happen when calling this on a pointer in the ML heap. It seems to hang.
Incorrect. initIntInfRes has every reason to believe that the current
heap can contain the result of the operation. (Indeed, there are numerous
'assert's to that effect in the code.) All of the IntInf primitives (both
internally as manipulated by the compiler and externally as implemented in
runtime/gc/int-inf.c) take a size_t argument which, at runtime, will be
the maximum size of the resulting IntInf. The limit check insertion pass
integrates these arguments into the limit checks to ensure that there is
always sufficient space in the heap to contain the result.
In fact, the program does not hang, but is simply computing the result
rather slowly. See <src>/basis-library/integer/int-inf.sml. IntInf
shifts are limited to 128 bits at a time. I know I'm the one who wrote
that code, and I have a very vague recollection that there was a reason,
but I can't recall it now. One issue is that if one compiles with
'-default-type word64', then the shift argument of IntInf.~>> and
IntInf.<< (as exported by the Basis Library) is a Word64.word, but on a
32-bit platform, the GMP primitives will only accept a 32-bit word as the
shift amount. And, in any case, we've made the IntInf shift primitives
require a 32-bit shift, so one needs a cap. But, obviously, it could be
much higher than 128.
More information about the MLton
mailing list