summaryrefslogtreecommitdiff
path: root/bytecomp
diff options
context:
space:
mode:
Diffstat (limited to 'bytecomp')
-rw-r--r--bytecomp/translcore.ml182
-rw-r--r--bytecomp/transljoin.ml162
-rw-r--r--bytecomp/transljoin.mli10
3 files changed, 255 insertions, 99 deletions
diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml
index a793a1e2a7..5f9e7553c5 100644
--- a/bytecomp/translcore.ml
+++ b/bytecomp/translcore.ml
@@ -32,6 +32,23 @@ type error =
exception Error of Location.t * error
+(* Optimisation of channnel send/calls,
+ Done with side effect so as not to distroy code structure *)
+
+let chan_env = ref (Ident.empty)
+
+let add_chan_env ids =
+ chan_env :=
+ List.fold_left
+ (fun k (id,x) -> Ident.add id x k)
+ !chan_env
+ ids
+
+let get_chan_env id =
+ try Some (Ident.find_same id !chan_env)
+ with Not_found -> None
+
+
(* Forward declaration -- to be filled in by Translmod.transl_module *)
let transl_module =
ref((fun cc rootpath modl -> assert false) :
@@ -631,7 +648,7 @@ and transl_exp0 e =
raise(Error(e.exp_loc, Free_super_var))
| Texp_ident
(path, _,
- {val_kind = Val_reg|Val_self _|Val_channel (_,_)|Val_alone _}) ->
+ {val_kind = Val_reg|Val_self _}) ->
transl_path path
| Texp_ident _ -> fatal_error "Translcore.transl_exp: bad Texp_ident"
| Texp_constant cst ->
@@ -641,8 +658,8 @@ and transl_exp0 e =
rec_flag pat_expr_list (event_before body (transl_exp body))
(*> JOCAML *)
| Texp_def (d,body) ->
- do_transl_def d (transl_exp body)
-(*>JOCAML*)
+ do_transl_def d (fun () -> transl_exp body)
+(*<JOCAML*)
| Texp_function (_, pat_expr_list, partial) ->
let ((kind, params), body) =
event_function e
@@ -651,20 +668,6 @@ and transl_exp0 e =
transl_function e.exp_loc !Clflags.native_code repr partial pl)
in
Lfunction(kind, params, body)
-(* two small optimizations *)
- | Texp_apply
- ({exp_desc = Texp_ident(path, _, {val_kind = Val_alone id})},
- [_,Some arg,_])
- ->
- Lapply (Lvar id,[transl_exp arg],e.exp_loc)
- | Texp_apply
- ({exp_desc = Texp_ident(path, _, {val_kind = Val_channel (auto,idx)})},
- [_,Some arg,_])
- ->
- Transljoin.local_send_sync
- auto idx (transl_exp arg)
- e.exp_loc
-(*<JOCAML*)
| Texp_apply({exp_desc = Texp_ident(path, _, {val_kind = Val_prim p})}, oargs)
when List.length oargs >= p.prim_arity
&& List.for_all (fun (_, arg,_) -> arg <> None) oargs ->
@@ -703,7 +706,24 @@ and transl_exp0 e =
end
end
| Texp_apply(funct, oargs) ->
- event_after e (transl_apply (transl_exp funct) oargs e.exp_loc)
+(* two small optimizations *)
+ begin match funct.exp_desc,oargs with
+ | Texp_ident(Pident id, _, {val_kind = Val_reg}),
+ [_,Some arg,_] ->
+ begin match get_chan_env id with
+ | Some (Alone id) ->
+ Lapply (Lvar id,[transl_exp arg],e.exp_loc)
+ | Some (Chan (id,idx)) ->
+ Transljoin.local_send_sync
+ id idx (transl_exp arg)
+ e.exp_loc
+ | None ->
+ event_after e
+ (transl_apply (transl_exp funct) oargs e.exp_loc)
+ end
+ | _,_ ->
+ event_after e (transl_apply (transl_exp funct) oargs e.exp_loc)
+ end
| Texp_match({exp_desc = Texp_tuple argl}, pat_expr_list, partial) ->
Matching.for_multiple_match (id_lam,e.exp_loc)
(transl_list transl_exp argl)
@@ -930,7 +950,7 @@ and transl_proc die sync p = match p.exp_desc with
(fun e -> Transljoin.reply_handler sync p transl_exp e)
rec_flag pat_expr_list (transl_proc die sync body)
| Texp_def (d,body) ->
- do_transl_def d (transl_proc die sync body)
+ do_transl_def d (fun () -> transl_proc die sync body)
| Texp_ifthenelse(cond, ifso, Some ifnot) ->
Lifthenelse
(Transljoin.reply_handler sync p transl_exp cond,
@@ -1012,7 +1032,7 @@ and transl_simple_proc die sync p = match p.exp_desc with
transl_exp
rec_flag pat_expr_list (transl_simple_proc die sync body)
| Texp_def (d,body) ->
- do_transl_def d (transl_simple_proc die sync body)
+ do_transl_def d (fun () -> transl_simple_proc die sync body)
| Texp_ifthenelse(cond, ifso, Some ifnot) ->
Lifthenelse
(transl_exp cond,
@@ -1045,19 +1065,25 @@ and transl_simple_proc die sync p = match p.exp_desc with
make_sequence
(transl_simple_proc false sync p1)
(transl_simple_proc die sync p2)
-| Texp_asyncsend
- ({exp_desc=Texp_ident (_,_,{val_kind=Val_channel (auto,num)})},e2) ->
- (if die then Transljoin.local_tail_send_async
- else Transljoin.local_send_async)
- auto num (transl_exp e2) p.exp_loc
-| Texp_asyncsend
- ({exp_desc=Texp_ident (_,_,{val_kind=Val_alone (guard)})},e2) ->
- (if die then Transljoin.local_tail_send_alone
- else Transljoin.local_send_alone)
- guard (transl_exp e2) p.exp_loc
| Texp_asyncsend (e1,e2) ->
- (if die then Transljoin.tail_send_async else Transljoin.send_async)
- (transl_exp e1) (transl_exp e2) p.exp_loc
+ let default e1 e2 =
+ (if die then Transljoin.tail_send_async else Transljoin.send_async)
+ (transl_exp e1) (transl_exp e2) p.exp_loc in
+ begin match e1.exp_desc with
+ | Texp_ident (Pident id,_,{val_kind=Val_reg}) ->
+ begin match get_chan_env id with
+ | Some (Alone id) ->
+ (if die then Transljoin.local_tail_send_alone
+ else Transljoin.local_send_alone)
+ id (transl_exp e2) p.exp_loc
+ | Some (Chan (id,idx)) ->
+ (if die then Transljoin.local_tail_send_async
+ else Transljoin.local_send_async)
+ id idx (transl_exp e2) p.exp_loc
+ | None -> default e1 e2
+ end
+ | _ -> default e1 e2
+ end
| Texp_reply (e, id) ->
begin match sync with
| Some main_id when main_id = id -> transl_exp e
@@ -1080,7 +1106,7 @@ and transl_simple_proc die sync p = match p.exp_desc with
(* Parameter list for a guarded process *)
-and transl_reaction (name,_) (Reac reac) =
+and transl_reaction (name,_) reac =
let (x, _ , actuals, idpats, p) = reac in
(* Principal continuation, as computed by typing *)
let sync = Transljoin.principal p in
@@ -1119,14 +1145,15 @@ and transl_reaction (name,_) (Reac reac) =
x, sync, lam
and transl_dispatcher disp =
- let Disp (d_id, chan, cls, partial) = disp in
+ let d_id, (chan,_) , cls, partial = disp in
let z = Ident.create "#z#" in
- let rhs chan =
- if chan.jchannel_sync then match chan.jchannel_id with
+
+ let rhs (chan,opt) =
+ if chan.jchannel_sync then match opt with
| Chan (name, i) ->
Transljoin.local_send_sync name i (Lvar z) Location.none
| Alone g -> Lapply (Lvar g, [Lvar z],Location.none)
- else match chan.jchannel_id with
+ else match opt with
| Chan (name, i) ->
Transljoin.local_tail_send_async name i
(Lvar z) Location.none
@@ -1136,28 +1163,28 @@ and transl_dispatcher disp =
let body =
try
let allchans =
- List.map
- (fun (p, chan) -> match chan.jchannel_id with
- | Chan (auto,i) -> auto,(p,i)
- | Alone _ -> raise Exit)
- cls in
- match allchans with
- | [] -> assert false
- | (auto,_)::_ ->
- let cls =
- List.map
- (fun (_,(p,i)) ->
- p,Lconst (Const_base (Const_int i)))
- allchans in
- (if chan.jchannel_sync then
- Transljoin.local_send_sync2
- else
- Transljoin.local_tail_send_async2)
- auto
- (Matching.for_function
- (id_lam,Location.none) None (Lvar z)
- cls partial)
- (Lvar z)
+ List.map
+ (fun (p, (chan,opt)) -> match opt with
+ | Chan (auto,i) -> auto,(p,i)
+ | Alone _ -> raise Exit)
+ cls in
+ match allchans with
+ | [] -> assert false
+ | (auto,_)::_ ->
+ let cls =
+ List.map
+ (fun (_,(p,i)) ->
+ p,Lconst (Const_base (Const_int i)))
+ allchans in
+ (if chan.jchannel_sync then
+ Transljoin.local_send_sync2
+ else
+ Transljoin.local_tail_send_async2)
+ auto
+ (Matching.for_function
+ (id_lam,Location.none) None (Lvar z)
+ cls partial)
+ (Lvar z)
with Exit ->
let cls = List.map (fun (p, chan) -> p, rhs chan) cls in
Matching.for_function
@@ -1166,7 +1193,7 @@ and transl_dispatcher disp =
let lam = Lfunction (Curried, params, body) in
d_id, chan, lam
-and transl_forwarder (Fwd reac) =
+and transl_forwarder reac =
let (x, jpat, _, idpats, p) = reac in
let sync = Transljoin.principal p in
let body =
@@ -1327,16 +1354,27 @@ and transl_let reply_handler transl_exp rec_flag pat_expr_list body =
Lletrec(List.map2 transl_case pat_expr_list idlist, body)
(*> JOCAML *)
-and do_transl_def autos body =
-
+(* Compile pattern matching in join patterns *)
+
+and do_transl_def autos kbody =
+(* Precompile automata, this includes PM compilation *)
+ let autos = List.map Transljoin.compile_auto autos in
+(* Add info and compile body *)
+ let saved_chan_env = !chan_env in
+ List.iter
+ (fun a ->
+ add_chan_env
+ (List.map (fun (id,(_,opt)) ->id,opt) a.cauto_original))
+ autos ;
+ let body = kbody () in
(* compile (and name) real guarded processes *)
let reactions =
List.map
(fun auto ->
- if auto.jauto_nchans = 0 then []
+ if auto.cauto_nchans = 0 then []
else
- let _,reacs,_ = auto.jauto_desc in
- List.map (transl_reaction auto.jauto_name) reacs)
+ let reacs = auto.cauto_reactions in
+ List.map (transl_reaction auto.cauto_name) reacs)
autos in
(* compile firing of guarded processes (aka automaton table) *)
@@ -1358,13 +1396,13 @@ and do_transl_def autos body =
let disps =
List.map
(fun auto ->
- let disps,_,_ = auto.jauto_desc in
+ let disps = auto.cauto_dispatchers in
List.map transl_dispatcher disps)
autos
and fwds =
List.map
(fun auto ->
- let _,_,fwds = auto.jauto_desc in
+ let fwds = auto.cauto_forwarders in
List.map transl_forwarder fwds)
autos in
let r =
@@ -1376,11 +1414,11 @@ and do_transl_def autos body =
Transljoin.create_forwarders autos disps fwds r in
(* create channels structures *)
- let r =
- List.fold_right Transljoin.create_channels autos r in
+ let r = List.fold_right Transljoin.create_channels autos r in
(* create automata structures *)
- let r =
- List.fold_right Transljoin.create_auto autos r in
+ let r = List.fold_right Transljoin.create_auto autos r in
+(* Restore channel env *)
+ chan_env := saved_chan_env ;
r
@@ -1455,7 +1493,7 @@ and transl_record all_labels repres lbl_expr_list opt_init_expr =
(*> JOCAML *)
(* For external usage *)
-let transl_def d k = do_transl_def d k
+let transl_def d k = do_transl_def d (fun () -> k)
and transl_let = transl_let id_lam transl_exp
(*< JOCAML *)
diff --git a/bytecomp/transljoin.ml b/bytecomp/transljoin.ml
index ff8267e7d8..7007771a27 100644
--- a/bytecomp/transljoin.ml
+++ b/bytecomp/transljoin.ml
@@ -421,14 +421,130 @@ let as_procs sync e =
let rec get_chan_rec id = function
| [] -> raise Not_found
| (oid,x)::rem ->
- if id = oid then x else get_chan_rec id rem
+ if Ident.same id oid then x else get_chan_rec id rem
-let dump_idx fp (id, _) = fprintf fp "%s" (Ident.unique_name id)
+open Printf
+
+let dump_chan fp chan =
+ fprintf fp "{id=%s, sync=%b}"
+ (Ident.unique_name chan.jchannel_ident)
+ chan.jchannel_sync
+let compile_auto a =
+(*
+ eprintf "AUTO:" ;
+ List.iter (fun (_,chan) -> eprintf " %a" dump_chan chan) a.jauto_names ;
+ eprintf "\n%!" ;
+*)
+ let get_chan tag id =
+ try get_chan_rec id a.jauto_names
+ with Not_found ->
+ fatal_error
+ (Printf.sprintf "Transljoin.compile_auto [%s]: %s" tag
+ (Ident.unique_name id)) in
+
+ let (disps, reacs), new_names =
+ Joinmatching.compile a.jauto_loc
+ (List.map
+ (fun cl ->
+ let jpats,g = cl.jclause_desc in
+ cl.jclause_loc,jpats,g)
+ a.jauto_desc) in
+(* Allocate new names for dispatchers and guarded processes *)
+ let disps = List.map (fun disp -> Ident.create "#d#", disp) disps
+ and reacs,fwds = match reacs with
+ | [((_,[_],_),_) as reac] -> (* Case of (single) forwarder *)
+ [],[Ident.create "#f", reac]
+ | _ ->
+ List.map (fun reac -> Ident.create "#g#", reac) reacs, [] in
+(* Automaton names *)
+ let name = Ident.create "#auto#"
+ and name_wrapped = Ident.create "#wrapped#" in
+(* Collect forwarders *)
+ let fwd_names =
+ List.map
+ (fun (d_id,(id,_,_)) ->
+ let chan = get_chan "dispatchers" id in
+ id,(chan,(Alone d_id)))
+ disps in
+ let fwd_names =
+ List.fold_right
+ (fun fwd r ->
+ let g_id,(_old,(patss,_gd)) = fwd in
+ List.fold_right
+ (fun pats r ->
+ List.fold_right
+ (fun pat r ->
+ let jid,_ = pat.jpat_desc in
+ let id = jid.jident_desc in
+ let chan = get_chan "forwarders" id in
+ (id,(chan,Alone g_id))::r)
+ pats r)
+ patss r)
+ fwds fwd_names in
+(* Collect channels *)
+ let is_fwd id =
+ try ignore(get_chan_rec id fwd_names) ; true
+ with Not_found -> false in
+
+(* First orignal names unsplit by compilation, and not a forwarder *)
+ let all_names,nchans =
+ List.fold_right
+ (fun (id,chan) (chans,nchans as k) ->
+ if is_fwd id then k
+ else
+ (id,(chan,Chan (name,nchans)))::chans,nchans+1)
+ a.jauto_names (fwd_names,0) in
+(* Then new names, introduced by pattern matching compilation *)
+ let all_names,nchans =
+ List.fold_right
+ (fun (id,ids) k ->
+ let chan = get_chan "old_name" id in
+ List.fold_right
+ (fun id (chans,nchans) ->
+ let chan = { chan with jchannel_ident = id} in
+ (id,(chan,Chan (name,nchans)))::chans,nchans+1)
+ ids k)
+ new_names (all_names,nchans) in
+(* Original names, with information *)
+ let is_orig id =
+ try ignore(get_chan_rec id a.jauto_names) ; true
+ with Not_found -> false in
+ let original = List.filter (fun (id,_) -> is_orig id) all_names in
+(* Precompile dispatchers *)
+ let disps =
+ let find_channel id =
+ try get_chan_rec id all_names
+ with Not_found ->
+ fatal_error
+ (Printf.sprintf "find_channel: %s"
+ (Ident.unique_name id)) in
+ List.map
+ (fun disp ->
+ let d_id,(chan_id, cls, par) = disp in
+ let chan = find_channel chan_id
+ and cls = List.map (fun (p,id) -> p,find_channel id) cls in
+ d_id,chan,cls,par)
+ disps in
+(* Precompile reactions, little to do: flatten *)
+ let precomp_reac (id,((_loc,pat,e),(pats,bv))) = id,pat,pats,bv,e in
+ let fwds = List.map precomp_reac fwds
+ and reacs = List.map precomp_reac reacs in
+(* Gather everything... *)
+ {
+ cauto_name = name,name_wrapped;
+ cauto_channels = all_names;
+ cauto_nchans = nchans;
+ cauto_original = original;
+ cauto_loc = a.jauto_loc;
+ cauto_dispatchers = disps;
+ cauto_forwarders = fwds;
+ cauto_reactions = reacs;
+ }
let get_num msg names id =
try
- let {jchannel_id=x} = get_chan_rec id names in
- match x with
+ let _,opt = get_chan_rec id names in
+ match opt with
| Chan (_,num) -> num
| _ ->
fatal_error
@@ -441,8 +557,8 @@ let get_num msg names id =
let get_chan msg names id =
try
- let {jchannel_id=x} = get_chan_rec id names in
- x
+ let _,opt = get_chan_rec id names in
+ opt
with
| Not_found ->
fatal_error
@@ -464,17 +580,18 @@ let rec principal_param ipri params nums = match params, nums with
let names_block nchans names =
let t = Array.create nchans "" in
List.iter
- (fun (id, {jchannel_id=x}) ->match x with
- | Chan (_,i) -> t.(i) <- Ident.unique_name id
- | _ -> ())
+ (fun (id, (_,opt)) ->
+ match opt with
+ | Chan (_,i) -> t.(i) <- Ident.unique_name id
+ | _ -> ())
names ;
Lconst
(Const_block
(0, Array.fold_right (fun s r -> Const_base (Const_string s)::r) t []))
let create_auto
- { jauto_name=(auto_name, wrapped_name);
- jauto_names = names ; jauto_nchans=nchans ; } k =
+ { cauto_name=(auto_name, wrapped_name);
+ cauto_channels = names ; cauto_nchans=nchans ; } k =
if nchans > 0 then
Llet
(Strict, auto_name,
@@ -485,15 +602,14 @@ let create_auto
(Strict, wrapped_name, wrap_automaton auto_name Location.none, k))
else k
-let create_channels {jauto_name=(raw_name, name) ; jauto_names=names} k =
+let create_channels {cauto_name=(raw_name, name) ; cauto_channels=names} k =
List.fold_right
- (fun (id,jc) k ->
- let {jchannel_sync=sync ; jchannel_id=x} = jc in
- match x with
+ (fun (id,(jc,opt)) k ->
+ match opt with
| Chan (_,num) ->
Llet
(StrictOpt, id,
- (if sync then
+ (if jc.jchannel_sync then
create_sync
else
create_async) name num Location.none,
@@ -543,10 +659,10 @@ let create_forwarders autos dispss fwdss r =
List.fold_right
(fun auto r ->
List.fold_right
- (fun (_,chan) r -> match chan.jchannel_id with
+ (fun (_,(chan,opt)) r -> match opt with
| Alone g -> make_g "fwd" chan g::r
| Chan (_,_) -> r)
- auto.jauto_names r)
+ auto.cauto_channels r)
autos id2g in
(* patch forwarder data structure *)
let r =
@@ -707,13 +823,13 @@ let lapply (f,args) = Lapply (f,args,Location.none)
(* gs is a list of compiled guarded processes *)
let create_table auto gs r =
- let n_chans = auto.jauto_nchans in
+ let n_chans = auto.cauto_nchans in
if n_chans =0 then r
else
- let name,_ = auto.jauto_name (* wrapped name of automaton *)
- and names = auto.jauto_names in (* all channels *)
+ let name,_ = auto.cauto_name (* wrapped name of automaton *)
+ and names = auto.cauto_channels in (* all channels *)
- let rec do_guard (Reac reac) (_, sync, _) k =
+ let rec do_guard reac (_, sync, _) k =
let (g, _, actual, _, _) = reac in
let create_reaction jpats r =
@@ -773,7 +889,7 @@ let create_table auto gs r =
let pats = explode actual in
List.fold_right create_reaction pats k in
- let _, reacs, _ = auto.jauto_desc in
+ let reacs = auto.cauto_reactions in
Lsequence
(patch_table name
(List.fold_right2 do_guard reacs gs []) Location.none,
diff --git a/bytecomp/transljoin.mli b/bytecomp/transljoin.mli
index 027f79ab66..e5066fb547 100644
--- a/bytecomp/transljoin.mli
+++ b/bytecomp/transljoin.mli
@@ -72,25 +72,27 @@ val principal : Typedtree.expression -> Ident.t option
(* Building definitions and locations *)
+val compile_auto : Typedtree.joinautomaton -> Typedtree.compiledautomaton
+
val create_auto :
- 'a Typedtree.joinautomaton_gen ->
+ Typedtree.compiledautomaton ->
Lambda.lambda -> Lambda.lambda
val create_channels :
- 'a Typedtree.joinautomaton_gen -> Lambda.lambda -> Lambda.lambda
+ Typedtree.compiledautomaton -> Lambda.lambda -> Lambda.lambda
val create_dispatchers :
(Ident.t * Typedtree.joinchannel * Lambda.lambda) list ->
Lambda.lambda -> Lambda.lambda
val create_forwarders :
- 'a Typedtree.joinautomaton_gen list ->
+ Typedtree.compiledautomaton list ->
(Ident.t * Typedtree.joinchannel * Lambda.lambda) list list ->
(Ident.t * Lambda.lambda) list list ->
Lambda.lambda -> Lambda.lambda
val create_table:
- Typedtree.joinautomaton ->
+ Typedtree.compiledautomaton ->
(Ident.t * Ident.t option * 'a) list -> Lambda.lambda ->
Lambda.lambda