Annotation of researchv10no/cmd/sml/src/cps/closure.sml, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.