Commit | Line | Data |
---|---|---|
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 | ||
9 | functor Globalize (S: GLOBALIZE_STRUCTS): GLOBALIZE = | |
10 | struct | |
11 | ||
12 | open S | |
13 | open Dec PrimExp | |
14 | ||
15 | fun 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 | ||
160 | end |