Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / closure-convert / globalize.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 1999-2005 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
4 *
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
7 *)
8
9functor Globalize (S: GLOBALIZE_STRUCTS): GLOBALIZE =
10struct
11
12open S
13open Dec PrimExp
14
15fun globalize {program = Program.T {datatypes, body, ...},
16 lambdaFree,
17 varGlobal: Var.t -> bool ref} =
18 let
19 val noConts =
20 not (Exp.hasPrim (body, fn p =>
21 case Prim.name p of
22 Prim.Name.Thread_switchTo => true
23 | _ => false))
24 local
25 val {get: Tycon.t -> bool, set, destroy} =
26 Property.destGetSetOnce (Tycon.plist, Property.initConst false)
27 fun makeBig tycon = set (tycon, true)
28 val _ = (Vector.foreach (datatypes, makeBig o #tycon)
29 ; makeBig Tycon.array
30 ; makeBig Tycon.arrow
31 ; makeBig Tycon.vector)
32 in
33 val tyconIsBig = get
34 val destroyTycon = destroy
35 end
36 fun typeIsSmall t =
37 let open Type
38 in
39 case dest t of
40 Con (c, ts) =>
41 not (tyconIsBig c)
42 andalso if (Tycon.equals (c, Tycon.tuple)
43 orelse Tycon.equals (c, Tycon.reff))
44 then Vector.forall (ts, typeIsSmall)
45 else true
46 | _ => Error.bug "Globalize.typeIsSmall: type variable"
47 end
48 val typeIsSmall =
49 Trace.trace ("Globalize.typeIsSmall", Type.layout, Bool.layout)
50 typeIsSmall
51 val varIsGlobal = ! o varGlobal
52 val isGlobal = varIsGlobal o VarExp.var
53 fun areGlobal xs = Vector.forall (xs, isGlobal)
54 fun makeGlobal x = varGlobal x := true
55 val traceLoopExp =
56 Trace.trace2 ("Globalize.loopExp", Exp.layout, Bool.layout, Bool.layout)
57 val traceLoopDec =
58 Trace.trace2 ("Globalize.loopDec", Dec.layout, Bool.layout, Bool.layout)
59 fun loopExp arg =
60 traceLoopExp (fn (e: Exp.t, once: bool) =>
61 List.fold (Exp.decs e, once, loopDec))
62 arg
63 and loopDec arg =
64 traceLoopDec
65 (fn (d, once) =>
66 case d of
67 MonoVal {var, ty, exp} =>
68 let
69 val (global, once) =
70 case exp of
71 App _ =>
72 (* If conts are used, then the application might
73 * call Thread_copyCurrent, in which case,
74 * subsequent stuff might run many times.
75 *)
76 (false, once andalso noConts)
77 | Case {cases, default, ...} =>
78 let
79 val once' =
80 Cases.fold
81 (cases, once, fn (e, b) =>
82 loopExp (e, once) andalso b)
83 val once' =
84 Option.fold (default, once',
85 fn ((e, _), b) =>
86 loopExp (e, once) andalso b)
87 in (false, once')
88 end
89 | ConApp {arg, ...} =>
90 (case arg of
91 NONE => true
92 | SOME x => isGlobal x,
93 once)
94 | Const _ => (true, once)
95 | Handle {try, handler, ...} =>
96 (false,
97 loopExp (handler, loopExp (try, once)))
98 | Lambda l =>
99 (loopLambda l
100 ; (Vector.forall (lambdaFree l, varIsGlobal),
101 once))
102 | PrimApp {prim, args, ...} =>
103 let
104 val global =
105 areGlobal args andalso
106 ((Prim.isFunctional prim
107 (* Don't want to move MLton_equal or MLton_hash
108 * into the globals because polymorphic
109 * equality and hasing isn't implemented
110 * there.
111 *)
112 andalso
113 (case Prim.name prim of
114 Prim.Name.MLton_equal => false
115 | Prim.Name.MLton_hash => false
116 | _ => true))
117 orelse
118 (once andalso
119 (case Prim.name prim of
120 Prim.Name.Ref_ref => typeIsSmall ty
121 | _ => false)))
122 val once =
123 once andalso
124 (case Prim.name prim of
125 Prim.Name.Thread_copyCurrent => false
126 | _ => true)
127 in
128 (global, once)
129 end
130 | Profile _ => (false, once)
131 | Raise _ => (false, once)
132 | Select {tuple, ...} => (isGlobal tuple, once)
133 | Tuple xs => (areGlobal xs, once)
134 | Var x => (isGlobal x, once)
135 val _ = if global then makeGlobal var else ()
136 in once
137 end
138 | Fun {decs, ...} =>
139 (if Vector.isEmpty decs
140 then ()
141 else
142 let
143 val {lambda, ...} = Vector.first decs
144 in
145 if Vector.forall (lambdaFree lambda, varIsGlobal)
146 then Vector.foreach (decs, makeGlobal o #var)
147 else ()
148 end
149 ; Vector.foreach (decs, loopLambda o #lambda)
150 ; once)
151 | _ => Error.bug "Globalize.loopDec: strange dec") arg
152 and loopLambda (l: Lambda.t): unit =
153 ignore (loopExp (Lambda.body l, false))
154 val _ = loopExp (body, true)
155 val _ = destroyTycon ()
156 in
157 ()
158 end
159
160end