Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | RefFlatten |
2 | ========== | |
3 | ||
4 | <:RefFlatten:> is an optimization pass for the <:SSA2:> | |
5 | <:IntermediateLanguage:>, invoked from <:SSA2Simplify:>. | |
6 | ||
7 | == Description == | |
8 | ||
9 | This pass flattens a `ref` cell into its containing object. | |
10 | The idea is to replace, where possible, a type like | |
11 | ---- | |
12 | (int ref * real) | |
13 | ---- | |
14 | ||
15 | with a type like | |
16 | ---- | |
17 | (int[m] * real) | |
18 | ---- | |
19 | ||
20 | where the `[m]` indicates a mutable field of a tuple. | |
21 | ||
22 | == Implementation == | |
23 | ||
24 | * <!ViewGitFile(mlton,master,mlton/ssa/ref-flatten.fun)> | |
25 | ||
26 | == Details and Notes == | |
27 | ||
28 | The savings is obvious, I hope. We avoid an extra heap-allocated | |
29 | object for the `ref`, which in the above case saves two words. We | |
30 | also save the time and code for the extra indirection at each get and | |
31 | set. There are lots of useful data structures (singly-linked and | |
32 | doubly-linked lists, union-find, Fibonacci heaps, ...) that I believe | |
33 | we are paying through the nose right now because of the absence of ref | |
34 | flattening. | |
35 | ||
36 | The idea is to compute for each occurrence of a `ref` type in the | |
37 | program whether or not that `ref` can be represented as an offset of | |
38 | some object (constructor or tuple). As before, a unification-based | |
39 | whole-program with deep abstract values makes sure the analysis is | |
40 | consistent. | |
41 | ||
42 | The only syntactic part of the analysis that remains is the part that | |
43 | checks that for a variable bound to a value constructed by `Ref_ref`: | |
44 | ||
45 | * the object allocation is in the same block. This is pretty | |
46 | draconian, and it would be nice to generalize it some day to allow | |
47 | flattening as long as the `ref` allocation and object allocation "line | |
48 | up one-to-one" in the same loop-free chunk of code. | |
49 | ||
50 | * updates occur in the same block (and hence it is safe-for-space | |
51 | because the containing object is still alive). It would be nice to | |
52 | relax this to allow updates as long as it can be provedthat the | |
53 | container is live. | |
54 | ||
55 | Prevent flattening of `unit ref`-s. | |
56 | ||
57 | <:RefFlatten:> is safe for space. The idea is to prevent a `ref` | |
58 | being flattened into an object that has a component of unbounded size | |
59 | (other than possibly the `ref` itself) unless we can prove that at | |
60 | each point the `ref` is live, then the containing object is live too. | |
61 | I used a pretty simple approximation to liveness. |