Description
Space-safety prohibits ConstantPropagation from globalizing all arrays and refs that are allocated at most once by a program. In particular, because globals are live for the duration of the program, globalizing an int list ref
(for example) would not be safe-for-space: an arbitrarily large list may be written to the reference and never garbage collected (whereas, when the int list ref
is not globalized, it will be garbage collected when it is no longer live). On the other hand, globalizing an int ref
is safe-for-space.
However, MLton currently uses a very conservative estimation for space safety. Only "small" types may be globalized, where smallness is defined as:
fun isSmall t =
case dest t of
Array _ => false
| Datatype _ => false
| Ref t => isSmall t
| Tuple ts => Vector.forall (ts, isSmall)
| Vector _ => false
| _ => true
Note that no Datatype
is small; this is conservative (since a recursive datatype could represent unbounded data), but prevents globalizing bool ref
. Also, no Array
is small; this is correct (because an int array ref
should not be globalized), but the globalization of a val a: t array = Array_alloc[t] (l)
is currently conditioned on the smallness of t array
, not the smallness of t
. It would be correct to globalize an array if t
were small; note that to globalize val a: t array = Array_alloc[t] (l)
, l
(the length) must be globalized and must, therefore, be a constant and the array is of constant size. (This is Stephen Weeks's relaxed notion of safe-for-space, where the constant factor blowup can be chosen per program.) In practice, it may be better to limit globalization of arrays to ones with "small" length in addition to small element type.
RefFlatten uses a more precise notion of small/large types (although RefFlatten was meant to be safe-for-space, the initial definition of small/large types was incorrect; see b1a0a80).