|
|
1.1 root 1: (* Copyright 1989 by AT&T Bell Laboratories *)
2: signature CLOSURE =
3: sig
4: val closeCPS : CPS.function * (CPS.lvar -> bool)
5: * (int * int * CPS.cexp -> CPS.cexp) ->
6: CPS.function * (CPS.lvar -> bool) * (CPS.lvar -> bool)
7: end
8:
9: functor Closure(val maxfree : int) : CLOSURE =
10: struct
11:
12: open CPS Access Profile SortedList
13: fun partition f l = fold (fn (e,(a,b)) => if f e then (e::a,b) else (a,e::b))
14: l ([],[])
15: fun sublist test =
16: let fun subl(a::r) = if test a then a::(subl r) else subl r
17: | subl [] = []
18: in subl
19: end
20: local val save = (!saveLvarNames before saveLvarNames := true)
21: val closure = namedLvar(Symbol.symbol "closure")
22: in val closureLvar = (saveLvarNames := save; fn () => dupLvar closure)
23: end
24: val error = ErrorMsg.impossible
25: datatype object = Value
26: | Function of {label:lvar,free:lvar list}
27: | Closure of {functions : (lvar * lvar) list,
28: contents : (lvar * object) list,
29: offset : int,
30: stamp : lvar}
31: datatype env = Env of (lvar * object) list
32: datatype access = Direct
33: | Path of (lvar * object * accesspath)
34:
35: fun mkClosure(functions,contents) =
36: Closure{functions=functions,contents=contents,
37: offset=0,stamp=mkLvar()}
38: val env0 = Env []
39: fun augment(m,Env e) = Env (m::e)
40:
41: val pr = output std_out
42: val vp = pr o Access.lvarName
43: fun plist p l = (app (fn v => (pr " "; p v)) l; pr "\n")
44: val ilist = plist vp
45: fun printEnv(Env e) =
46: let fun ip i = pr(Integer.makestring i)
47: fun sp() = pr " "
48: val tlist = plist (fn (a,b) => (vp a; pr "/L"; Integer.print b))
49: fun p(indent,l,seen) =
50: let fun v(true,(vl,Value)::tl) = (vp vl; sp(); v(true,tl))
51: | v(false,(vl,Value)::tl) = (indent(); vp vl; sp(); v(true,tl))
52: | v(nl,_::tl) = v(nl,tl)
53: | v(true,[]) = pr "\n"
54: | v(false,[]) = ()
55: fun f(true,(v,Function{label,...})::tl) =
56: (vp v; pr "/k"; vp label; sp(); f(true,tl))
57: | f(false,(v,Function{label,...})::tl) =
58: (indent(); vp v; pr "/k"; vp label; sp(); f(true,tl))
59: | f(nl,_::tl) = f(nl,tl)
60: | f(true,[]) = pr "\n"
61: | f(false,[]) = ()
62: fun c(v,Closure{functions,contents,offset,stamp}) =
63: (indent(); pr "Closure "; vp v; pr "/"; ip stamp;
64: pr " @"; ip offset;
65: if member seen stamp
66: then pr "(seen)\n"
67: else (pr ":\n";
68: case functions of
69: [] => ()
70: | _ => (indent(); pr " Funs:"; tlist functions; ());
71: p(fn() => (indent();pr " "),contents,enter(stamp,seen))))
72: | c _ = ()
73: in v(false,l); f(false,l); app c l
74: end
75: in p(fn () => (),e,[])
76: end
77:
78: (* "Alpha conversion": the closure converter introduces duplicate bindings
79: at function arguments (the free variables of known functions) and at
80: SELECT's and OFFSET's from closures. This function restores unique
81: bindings, and also eliminates OFFSET's of 0 (which are introduced as
82: a side effect of trying to improve lazy display). It assumes that a
83: FIX has no free variables. *)
84: fun unrebind ce =
85: let fun rename rebind v =
86: let fun f [] = v
87: | f ((w:int,v')::t) = if v=w then v' else f t
88: in f rebind
89: end
90: fun f (l,args,b) =
91: let val (args',rebind') = fold (fn(v,(args',rebind')) =>
92: let val v' = dupLvar v
93: in (v'::args',(v,v')::rebind')
94: end)
95: args ([],[])
96: in (l,args',g(b,rebind'))
97: end
98: and g(ce,rebind) =
99: let val rename = rename rebind
100: val rec h =
101: fn RECORD(vl,w,e) =>
102: RECORD(map (fn(v,p) => (rename v,p)) vl,w,h e)
103: | OFFSET(0,v,w,e) => g(e,(w,rename v)::rebind)
104: | OFFSET(i,v,w,e) =>
105: let val w' = dupLvar w
106: in OFFSET(i,rename v,w',g(e,(w,w')::rebind))
107: end
108: | SELECT(i,v,w,e as APP(x,args)) =>
109: let val w' = dupLvar w
110: in if w=x
111: then SELECT(i,rename v,w',APP(w',map rename args))
112: else SELECT(i,rename v,w',g(e,(w,w')::rebind))
113: end
114: | SELECT(i,v,w,e) =>
115: let val w' = dupLvar w
116: in SELECT(i,rename v,w',g(e,(w,w')::rebind))
117: end
118: | APP(f,vl) => APP(f,map rename vl)
119: (* HACK: f is always a label or from a SELECT, so
120: we never need rename. *)
121: | FIX(l,e) => FIX(map f l,h e)
122: | SWITCH(v,el) => SWITCH(rename v,map h el)
123: | PRIMOP(i,vl,wl,el) => PRIMOP(i,map rename vl,wl,map h el)
124: in h ce
125: end
126: in g(ce,[])
127: end
128:
129: (* TEMPORARY DEBUGGING STUFF *)
130: val alphac = System.Control.CG.alphac
131: val comment = ref false (* System.Control.CG.comment *)
132: val unrebind = fn x => if !alphac then unrebind x else x
133: fun COMMENT f = if !comment then (f(); ()) else ()
134:
135: fun formap f =
136: let fun iter([],_) = []
137: | iter(hd::tl,i) = f(hd,i)::iter(tl,i+1)
138: in iter o (fn l => (l,0))
139: end
140:
141: fun select(i,Closure{functions,contents,offset,stamp}) =
142: (let val index = offset + i - length functions
143: in (#2 o nth)(contents,index)
144: end handle Nth => error "bad select in cps/closure")
145: | select(_,Value) = Value
146: | select(_,Function _) = error "select from knownfunc in cps/closure"
147: fun offset(_,Value,_,_) = error "offset from value in cps/closure"
148: | offset(_,Function _,_,_) = error "offset from knownfunc in cps/closure"
149: | offset(i,Closure{functions,contents,offset,stamp},v,env) =
150: augment((v,Closure{functions=functions,contents=contents,
151: offset=offset+i,stamp=stamp}),env)
152: (* Merge the free variables of recursive register functions, and put
153: free variables into the closure if there are not enough registers.
154: A function which needs the closure for any reason (for example, to
155: call and escaping function of the fix) will always put all its free
156: variables in the closure - you can't use the closure and some registers
157: for free variables. *)
158: type info = {v:lvar,fns:lvar list,other:lvar list,args:lvar list,
159: body:cexp,label:lvar,env:env,callc:bool}
160: fun regf bindings =
161: let fun pack m =
162: let fun getother w =
163: let fun g(({v,...}:info,other,_)::tl) = if v=w then other
164: else g tl
165: | g [] = ErrorMsg.impossible "[] 4849 in cps/closure"
166: in g m
167: end
168: fun getcallc w =
169: let fun g(({v,...}:info,_,callc)::tl) = if v=w then callc
170: else g tl
171: | g [] = ErrorMsg.impossible "[] 4848 in cps/closure"
172: in g m
173: end
174: fun f (x as {args,fns,...}:info, other, callc) =
175: (x,
176: foldmerge(other :: map getother fns),
177: callc orelse
178: (length args + length other >= maxfree andalso
179: length other > 1) orelse
180: exists getcallc fns)
181: val m' = map f m
182: in if exists (fn ({callc,...}:info,_,callc') => callc <> callc') m'
183: then regf (map (fn ({v,fns,other,args,body,label,callc,env},_,cc') =>
184: {v=v,fns=fns,other=other,args=args,body=body,
185: label=label,env=env,callc=cc'}) m')
186: else if exists (fn x=>x)
187: (List2.map2 (fn ((_,other,_),(_,other',_)) =>
188: length other <> length other')
189: (m,m'))
190: then pack m'
191: else fold (fn(({v,args,body,label,env,...},other,callc),(b,f)) =>
192: if callc then
193: ({v=v,args=args,body=body,label=label,env=env,
194: free=[],callc=callc}::b,merge(other,f))
195: else
196: ({v=v,args=args,body=body,label=label,env=env,
197: free=other,callc=callc}::b,f))
198: m' ([],[])
199: end
200: in pack (map (fn (x as {other,callc,...}) => (x,other,callc)) bindings)
201: end
202:
203:
204: fun compute_escapes ce =
205: let val s = Intset.new()
206: val use = Intset.add s
207: val rec g =
208: fn RECORD (vl,_,e) => (app (use o #1) vl; g e)
209: | SELECT (_,v,_,e) => g e
210: | OFFSET (_,v,_,e) => g e
211: | APP(f,vl) => (app use vl)
212: | FIX(l, e) => (app (g o #3) l; g e)
213: | SWITCH(v,el) => app g el
214: | PRIMOP(_,vl,_,el) => (app use vl; app g el)
215: in g ce; Intset.mem s
216: end
217:
218:
219: fun closeCPS((f,vl,ce),constant,prof) =
220: let
221: val escapes = compute_escapes ce
222: val unknownset = Intset.new()
223: val knownset = Intset.new()
224: val markknown = Intset.add knownset
225: val markunknown = Intset.add unknownset
226: val freevars = FreeMap.freemapClose(ce,constant)
227: datatype looking = Found of object * access
228: | Pending of (lvar * object) list
229: exception Lookup
230: (* Closures may be duplicated in the 'tree'; don't look at them twice. *)
231: fun lookup(env as Env e,target) =
232: let fun bfs([],[],seen) = raise Lookup
233: | bfs([],next,seen) = bfs(next,[],seen)
234: | bfs((Closure{functions,contents,offset,stamp},p)::m,next,seen) =
235: let fun element i =
236: let val p' = i-offset
237: in if p'<0
238: then (print "\nNegSel target for ";
239: print(Access.lvarName target); print " in\n";
240: printEnv env)
241: else ();
242: p'::p
243: end
244: fun cnt([],i,next,seen) = bfs(m,next,seen)
245: | cnt((v,c as Closure{stamp,...})::t,i,next,seen) =
246: if target=v
247: then (element i,0,c)
248: else cnt(t,i+1,if member seen stamp
249: then next
250: else (c,element i)::next,seen)
251: | cnt((v,Value)::t,i,next,seen) =
252: if target=v
253: then (element i,0,Value)
254: else cnt(t,i+1,next,seen)
255: | cnt((_,Function _)::_,_,next,seen) =
256: error "Function in closure in lookup"
257: fun fns([],i,seen) = cnt(contents,i,next,seen)
258: | fns((v,l)::t,i,seen) =
259: if target=v
260: then (p,i-offset,Closure{functions=functions,
261: contents=contents,
262: stamp=stamp,
263: offset = i})
264: else fns(t,i+1,seen)
265: in if member seen stamp
266: then bfs(m,next,seen)
267: else fns(functions,0,enter(stamp,seen))
268: end
269: fun search closures =
270: let val (p,off,r) =
271: bfs(formap(fn((v,c),i) => (c,[i])) closures,[],[])
272: val (n::t) = rev p
273: fun f [] = OFFp off | f(h::t) = SELp(h,f t)
274: val (v,c) = nth(closures,n)
275: in (r,Path(v,c,f t))
276: end
277: fun look [] = raise Lookup
278: | look ((v,c as Closure{functions,contents,stamp,offset})::tl) =
279: if target=v then Found(c,Direct)
280: else let fun f(_,[]) = (false,0)
281: | f(i,(v,_)::t) = if target=v then (true,i) else f(i+1,t)
282: val (foundit,n) = f(0,functions)
283: (* this junk is a hack needed for linked closures *)
284: in if foundit
285: then Found(Closure{functions=functions,
286: contents=contents,
287: stamp=stamp,
288: offset=n},
289: Path(v,c,OFFp(n-offset)))
290: else ((case look tl of
291: f as Found _ => f
292: | Pending l => Pending ((v,c)::l))
293: handle Lookup => Pending [(v,c)])
294: end
295: | look ((v,f as Function _)::tl) =
296: if target=v then Found(f,Direct) else look tl
297: | look ((v,Value)::tl) =
298: if target=v then Found(Value,Direct) else look tl
299: in if constant target
300: then (Value,Direct)
301: else (case look e of
302: Found f => f
303: | Pending closures => search closures)
304: handle Lookup =>
305: (print "**LOOKUP: Can't find "; vp target;
306: print " in environment:\n";
307: printEnv env;
308: raise Lookup)
309: end
310:
311: fun flat(env,free) =
312: map (fn v => let val (obj,_) = lookup(env,v)
313: in case obj of Function _ => pr "weird\n"
314: | _ => ();
315: (v,obj)
316: end) free
317: fun link(env,free) =
318: let val contents = map (fn v => let val (obj,acc) = lookup(env,v)
319: in case obj of Function _ => pr "weird\n"
320: | _ => ();
321: (v,obj,acc)
322: end)
323: free
324: val direct = fold (fn ((v,obj,Direct),t) => (v,obj)::t
325: | ((v,obj,Path(_,_,OFFp _)),t) => (v,obj)::t
326: | (_,t) => t) contents []
327: in if length direct = length contents then direct
328: else case env of Env l =>
329: let fun getc ((m as (v,Closure _))::_) = m
330: | getc (_::tl) = getc tl
331: | getc [] = error "No closure in closureStrat"
332: val c = getc (rev l)
333: in c::direct
334: end
335: end
336:
337: fun closureStrategy(bindings,free,env) = (* temporary *)
338: let val m = case !CGoptions.closureStrategy
339: of 3 => link(env,free)
340: | 2 => link(env,free)
341: | _ => flat(env,free)
342: in mkClosure(map (fn(v,l,_,_) => (v,l)) bindings,m)
343: end
344:
345: (* Take a free variable list and replace knownfuncs by their
346: free variables. A new environment with the knownfunc mappings is
347: returned. Function aliasing could be added here. *)
348: fun funcAnalysis(free,env) =
349: fold (fn (v,(l,env')) =>
350: let val(obj,_) = lookup(env,v)
351: in case obj
352: of Function{free,...} => (merge(free,l),augment((v,obj),env'))
353: | _ => (enter(v,l),env')
354: end)
355: free ([],env0)
356: (* Function aliasing, separate for now, but always called after funcAnalysis. *)
357: fun sameClosureOpt(free,env) =
358: case !CGoptions.closureStrategy
359: of 0 => free (* flat without aliasing *)
360: | 2 => free (* linked without aliasing *)
361: | _ => (* all others have aliasing *)
362: let val mapping = map (fn v => let val (obj,_) = lookup(env,v)
363: in (v,obj)
364: end) free
365: fun uniq ((hd as (v,Closure{stamp,...}))::tl) =
366: let val m' = uniq tl
367: in if exists (fn (_,Closure{stamp=stamp',...}) => stamp=stamp'
368: | _ => false) m'
369: then m' else hd::m'
370: end
371: | uniq (hd::tl) = hd::uniq tl
372: | uniq [] = []
373: in map #1 (uniq mapping)
374: end
375:
376: fun fixAccess(args,env) =
377: let
378: fun access(rootvar,(env,header)) =
379: let val rec follow =
380: fn (_,Value,_,_,_) => error "fixAccess Value in cps/closure"
381: | (v,cl,env,OFFp off,h) =>
382: (offset(off,cl,rootvar,env),
383: h o (fn ce => OFFSET(off,v,rootvar,ce)))
384: | (v,cl,env,SELp(i,OFFp 0),h) =>
385: (augment((rootvar,select(i,cl)),env),
386: h o (fn ce => SELECT(i,v,rootvar,ce)))
387: | (v,cl,env,SELp(i,p),h) =>
388: let val w = mkLvar()
389: val cl = select(i,cl)
390: val env = augment((w,cl),env)
391: (* turn off lazy display here *)
392: in follow(w,cl,env,p,h o (fn ce => SELECT(i,v,w,ce)))
393: end
394: val (obj,acc) = lookup(env,rootvar)
395: in case acc
396: of Direct => (env,header)
397: | Path(start,cl,path) =>
398: let val a as (env,header) = follow(start,cl,env,path,header)
399: in if not(!CGoptions.profile) then a
400: else let val cost = lenp path
401: val h = if cost=0 then fn x => x else
402: if cost < LINKSLOTS
403: then fn ce => prof(LINKS+cost,1,ce)
404: else fn ce => prof(LINKS,1,prof(LINKOVFL,cost,ce))
405: in (env,h o header)
406: end
407: end
408: end
409: in fold access args (env,fn x => x)
410: end
411:
412: fun recordEl(l,env) =
413: if not(!CGoptions.profile)
414: then (map (fn (v,p) =>
415: case lookup(env,v)
416: of (_,Direct) => (v,p)
417: | (_,Path(start,_,path)) => (start,combinepaths(path,p))) l,
418: fn x => x)
419: else fold (fn ((v,p),(l,h)) =>
420: let val (_,acc) = lookup(env,v)
421: val (m,cost) = case acc of Direct => ((v,p),0)
422: | Path(start,_,path) =>
423: ((start,combinepaths(path,p)),lenp path)
424: val h' = if cost=0 then fn x => x else
425: if cost < LINKSLOTS then fn ce => prof(LINKS+cost,1,ce)
426: else fn ce => prof(LINKS,1,prof(LINKOVFL,cost,ce))
427: in (m::l,h o h')
428: end) l ([],fn x => x)
429:
430:
431: fun makenv(env,bindings: (lvar * lvar list * cexp) list) =
432: let
433: val _ = COMMENT(fn() => (pr "Beginning makenv.\nInitial environment:\n";
434: printEnv env; pr "\n"))
435:
436: (* A debugging version of freevars *)
437: fun fpr(v,free) = COMMENT(fn() => (pr "Free in "; vp v; pr ":"; ilist free))
438: val freevars =
439: (fn v => let val free = freevars v
440: in fpr(v,free);
441: free
442: end)
443:
444: (* Separate functions into those that escape and those which are knownfuncs *)
445: val (escape,known) = partition (escapes o #1) bindings
446: val escaping = uniq(map #1 escape)
447:
448: val _ = COMMENT(fn() => pr "Knownfuncs...\n")
449: (* Mark each known function of the FIX with its free variables. *)
450: val known
451: = map (fn(v,args,body) => {v=v,free=freevars v,args=args,body=body}) known
452:
453: (* For each known function of the FIX, remove any escaping functions of the
454: FIX from its free list and mark that the function requires the closure. *)
455: val known
456: = map (fn {v,free,args,body} =>
457: let val free' = difference(free,escaping)
458: in {v=v,free=free',
459: callc=(free<>free'),
460: args=args,body=body}
461: end) known
462:
463: (* Separate known functions defined in this FIX from other free variables. *)
464: local val knownlvars = map #v known
465: in val knownlvar = fn v => exists (fn w => v=w) knownlvars
466: end
467: val known
468: = map (fn {v,free,callc,args,body} =>
469: let val (fns,other) = partition knownlvar free
470: in {v=v,fns=fns,other=other,callc=callc,args=args,body=body}
471: end)
472: known
473:
474: (* Replace knownfuncs defined in other FIX'es by their free variables, and
475: escaping functions defined in other FIX'es by their closures. Label
476: each knownfunc. *)
477: val known
478: = map (fn{v,fns,other,callc,args,body} =>
479: let val (other,env') = funcAnalysis(other,env)
480: val other = sameClosureOpt(other,env)
481: in {v=v,fns=fns,other=other,callc=callc,args=args,body=body,
482: env=env',label=dupLvar v}
483: end)
484: known
485:
486: (* Merge free variables of knownfuncs that call each other. *)
487: (* Look at the number of free variables and arguments to each known function
488: to be defined. The cps converter ensures that there are enough registers
489: to hold the arguments and leaves one register free for the free variables,
490: if any. Therefore some free variables may have to be spilled into the closure,
491: and these must be collected. *)
492: val (known,collected)
493: = regf known
494:
495: val _ = COMMENT(fn() => pr "Escaping functions...\n")
496: (* Get the combined list of the free variables of all the escaping functions
497: of the FIX. *)
498: val free : lvar list = remove(escaping, foldmerge(map (freevars o #1) escape))
499: val _ = COMMENT(fn() => (pr "AAA"; ilist free))
500:
501: (* Replace knownfuncs defined in this FIX with their free variables. *)
502: val free : lvar list
503: = let val (fns,other) = partition knownlvar free
504: in fold (fn ({v,free,...},b) =>
505: if exists (fn w => v=w) fns
506: then merge(free,b)
507: else b) known other
508: end
509: val _ = COMMENT(fn() => (pr "BBB"; ilist free))
510:
511: val free = merge(collected,free)
512: val _ = COMMENT(fn() => (pr "CCC"; ilist free))
513:
514:
515: (* Replace knownfuncs defined elsewhere with their free variables, and escaping
516: functions defined elsewhere with their closures. The function environment
517: which tells that certain free variables are known functions and gives their
518: free variables must be kept for applications of the functions in the bodies
519: of the escaping functions of the FIX. *)
520: val (free,functionEnv) : lvar list * env (* only need function mapping here *)
521: = let val (free,env') = funcAnalysis(free,env)
522: val free = sameClosureOpt(free,env)
523: in (free,env')
524: end
525: val _ = COMMENT(fn() => (pr "DDD"; ilist free))
526:
527:
528: (* Given the functions to be defined in the closure (escape), the free variables
529: which should be contained in the closure (free), and their current locations
530: (env), decide on a closure representation. *)
531: val escape = map (fn(v,args,body) => (v,dupLvar v,args,body)) escape
532: val closure = closureStrategy(escape,free,env)
533: val _ = COMMENT(fn() =>
534: let val Closure{contents,...} = closure
535: in pr "EEE"; ilist (map #1 contents)
536: end)
537:
538: fun mkFnMap c : (lvar * object) list
539: = map (fn{v,free,callc,label,...} =>
540: if callc then (v,Function{label=label,free=enter(c,free)})
541: else (v,Function{label=label,free=free}))
542: known
543:
544: (* Final construction of the environment for each standard function. *)
545: val closureFrags : (lvar * lvar list * cexp * env) list
546: = case escape of [] => []
547: | ((v,_,_,_)::_) =>
548: let val env = fold augment (mkFnMap v) functionEnv
549: fun f ((v,l,args,body),i) =
550: let val cname = closureLvar()
551: val env = fold (fn (v,b) => augment((v,Value),b))
552: args (offset(i,closure,cname,env))
553: val _ = COMMENT(fn () => (print "\nEnvironment at escaping ";
554: vp v; print ":\n";
555: printEnv env))
556: in markunknown l; (l,cname::args,body,env)
557: end
558: in formap f escape
559: end
560:
561:
562: (* Final construction of the environment for each known function. *)
563: val cname = closureLvar()
564: val fnMap = mkFnMap cname
565: val registerFrags : (lvar * lvar list * cexp * env) list
566: = map (fn{v,free,callc,args,body,env=env',label} =>
567: let val env =
568: fold (fn (v,env') =>
569: case lookup(env,v)
570: of (Function _,_) => error "cps/closure.223"
571: | (obj,_) => augment((v,obj),env'))
572: free
573: (fold (fn (v,b) => augment((v,Value),b))
574: args
575: (fold augment fnMap
576: (if callc
577: then (inc System.Control.CG.knowncl;
578: augment((cname,closure),env'))
579: else env')))
580: val _ = COMMENT(fn () => (print "\nEnvironment at known ";
581: vp v; print ":\n";
582: printEnv env))
583: val args = args @ free @ if callc then [cname] else []
584: in markknown label; (label,args,body,env)
585: end)
586: known
587:
588:
589: val contents = let val Closure{functions,contents,...} = closure
590: in map #2 functions @ map #1 contents
591: end
592:
593:
594: (* Add profiling code if flag is on. *)
595: fun mkrexp(contents,cname) =
596: if not(!CGoptions.profile) then fn ce => RECORD(contents,cname,ce)
597: else let val len = length contents
598: val (closures,slots,ovfl) =
599: fold (fn((v,[_],_),b as (closures,_,_)) =>
600: if closures=CLOSURES then b
601: else if escapes v
602: then (CCLOSURES,CCLOSURESLOTS,CCLOSUREOVFL)
603: else b
604: |((v,args,_),b as (closures,_,_)) =>
605: if closures=CLOSURES then b
606: else if escapes v
607: then (CLOSURES,CLOSURESLOTS,CLOSUREOVFL)
608: else b)
609: bindings (KCLOSURES,KCLOSURESLOTS,KCLOSUREOVFL)
610: in if len < slots
611: then fn ce => prof(closures+len,1,RECORD(contents,cname,ce))
612: else fn ce => prof(closures,1,
613: prof(ovfl,len,RECORD(contents,cname,ce)))
614: end
615:
616:
617: in case contents
618: of [] => (fn ce => ce,registerFrags,fold augment fnMap env)
619: | _ =>
620: let val frags = closureFrags@registerFrags
621: val env = fold (fn(a,b) => augment((#1 a,Value),b)) closureFrags env
622: val (contents,header) = recordEl(recordpath contents,env)
623: val env = fold augment fnMap env
624: val env = augment((cname,closure),env)
625: val _ = COMMENT(fn () => (print "\nEnvironment after FIX:\n";
626: printEnv env))
627: in (header o mkrexp(contents,cname),frags,env)
628: end
629: before COMMENT(fn() => pr "makenv done.\n\n")
630: end
631:
632:
633: val env1 = fold (fn(v,b) => augment((v,Value),b)) (f::vl) env0
634: fun close(ce,env) =
635: case ce
636: of FIX(bindings,b) =>
637: (let val (header,frags,env') = makenv(env,bindings)
638: in FIX(map (fn(v,args,a,env) =>
639: (v,args,close(a,env))) frags,
640: header(close(b,env')))
641: end handle Lookup => APP(0,[]))
642: | APP(f,args) =>
643: let val(obj,_) = lookup(env,f)
644: handle Lookup => (print "LOOKUP FAILS in close(APP)\n"; (Value,Direct))
645: in case obj
646: of Closure{functions,offset,...} =>
647: let val (_,header) = fixAccess(f::args,env)
648: val (_,label) = nth(functions,offset)
649: val call = APP(label,f::args)
650: in if !CGoptions.profile
651: then header(prof(STDKCALLS,1,call))
652: else header call
653: end
654: | Function{label,free} =>
655: let val args' = args@free
656: val (_,header) = fixAccess(args',env)
657: val call = APP(label,args')
658: in if !CGoptions.profile
659: then header(prof(KNOWNCALLS,1,call))
660: else header call
661: end
662: | Value =>
663: let val l = mkLvar()
664: val (_,header) = fixAccess(f::args,env)
665: val call = SELECT(0,f,l,APP(l,f::args))
666: in if !CGoptions.profile
667: then case args
668: of [_] => header(prof(CNTCALLS,1,call))
669: | _ => header(prof(STDCALLS,1,call))
670: else header call
671: end
672: end
673: | SWITCH(v,l) =>
674: let val (env',header) = fixAccess([v],env)
675: in header (SWITCH(v,map (fn c => close(c,env')) l))
676: end
677: | RECORD(l,v,c) =>
678: let val (l,header) = recordEl(l,env)
679: val ce = close(c,augment((v,Value),env))
680: val len = length l
681: in header(
682: if not(!CGoptions.profile) then RECORD(l,v,ce)
683: else if len < RECORDSLOTS
684: then prof(RECORDS+len,1,RECORD(l,v,ce))
685: else prof(RECORDS,1,prof(RECORDOVFL,len,RECORD(l,v,ce))))
686: end
687: | SELECT(i,v,w,c) =>
688: let val (env,header) = fixAccess([v],env)
689: val (obj,_) = lookup(env,v)
690: handle Lookup => (print "LOOKUP FAILS in close(SELECT)\n"; (Value,Direct))
691: in header(SELECT(i,v,w,close(c,augment((w,select(i,obj)),env))))
692: end
693: | OFFSET(i,v,w,c) => error "OFFSET in cps/closure.sml!"
694: | PRIMOP(i,args,rets,l) =>
695: let val (env,header) = fixAccess(args,env)
696: val env = fold (fn (v,b) => augment((v,Value),b)) rets env
697: in header (PRIMOP(i,args,rets,map (fn c => close(c,env)) l))
698: end
699: in ((mkLvar(),f::vl,unrebind(close(ce,env1))),
700: Intset.mem knownset,Intset.mem unknownset)
701: end
702:
703: end (* structure Closure *)
704:
705:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.