@@ -281,11 +281,19 @@ module Type = struct
281281 ])
282282 })
283283
284- let env_type ~cps ~arity n =
284+ let make_env_type env_type =
285+ List. map
286+ ~f: (fun typ ->
287+ { W. mut = false
288+ ; typ = W. Value (Option. value ~default: (W. Ref { nullable = false ; typ = Eq }) typ)
289+ })
290+ env_type
291+
292+ let env_type ~cps ~arity ~env_type_id ~env_type =
285293 register_type
286294 (if cps
287- then Printf. sprintf " cps_env_%d_%d" arity n
288- else Printf. sprintf " env_%d_%d" arity n )
295+ then Printf. sprintf " cps_env_%d_%d" arity env_type_id
296+ else Printf. sprintf " env_%d_%d" arity env_type_id )
289297 (fun () ->
290298 let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
291299 let * common = closure_common_fields ~cps in
@@ -309,18 +317,11 @@ module Type = struct
309317 ; typ = Value (Ref { nullable = false ; typ = Type fun_ty' })
310318 }
311319 ])
312- @ List. init
313- ~f: (fun _ ->
314- { W. mut = false
315- ; typ = W. Value (Ref { nullable = false ; typ = Eq })
316- })
317- ~len: n)
320+ @ make_env_type env_type)
318321 })
319322
320- let rec_env_type ~function_count ~free_variable_count =
321- register_type
322- (Printf. sprintf " rec_env_%d_%d" function_count free_variable_count)
323- (fun () ->
323+ let rec_env_type ~function_count ~env_type_id ~env_type =
324+ register_type (Printf. sprintf " rec_env_%d_%d" function_count env_type_id) (fun () ->
324325 return
325326 { supertype = None
326327 ; final = true
@@ -331,24 +332,20 @@ module Type = struct
331332 { W. mut = i < function_count
332333 ; typ = W. Value (Ref { nullable = false ; typ = Eq })
333334 })
334- ~len: (function_count + free_variable_count))
335+ ~len: function_count
336+ @ make_env_type env_type)
335337 })
336338
337- let rec_closure_type ~cps ~arity ~function_count ~free_variable_count =
339+ let rec_closure_type ~cps ~arity ~function_count ~env_type_id ~ env_type =
338340 register_type
339341 (if cps
340- then
341- Printf. sprintf
342- " cps_closure_rec_%d_%d_%d"
343- arity
344- function_count
345- free_variable_count
346- else Printf. sprintf " closure_rec_%d_%d_%d" arity function_count free_variable_count)
342+ then Printf. sprintf " cps_closure_rec_%d_%d_%d" arity function_count env_type_id
343+ else Printf. sprintf " closure_rec_%d_%d_%d" arity function_count env_type_id)
347344 (fun () ->
348345 let * cl_typ = closure_type ~usage: `Alloc ~cps arity in
349346 let * common = closure_common_fields ~cps in
350347 let * fun_ty' = function_type ~cps arity in
351- let * env_ty = rec_env_type ~function_count ~free_variable_count in
348+ let * env_ty = rec_env_type ~function_count ~env_type_id ~env_type in
352349 return
353350 { supertype = Some cl_typ
354351 ; final = true
@@ -1110,11 +1107,19 @@ module Closure = struct
11101107 in
11111108 return (W. GlobalGet name)
11121109 else
1113- let free_variable_count = List. length free_variables in
1110+ let * env_type = expression_list variable_type free_variables in
1111+ let env_type_id =
1112+ try Hashtbl. find context.closure_types env_type
1113+ with Not_found ->
1114+ let id = Hashtbl. length context.closure_types in
1115+ Hashtbl. add context.closure_types env_type id;
1116+ id
1117+ in
1118+ info.id < - Some env_type_id;
11141119 match info.Closure_conversion. functions with
11151120 | [] -> assert false
11161121 | [ _ ] ->
1117- let * typ = Type. env_type ~cps ~arity free_variable_count in
1122+ let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type in
11181123 let * l = expression_list load free_variables in
11191124 return
11201125 (W. StructNew
@@ -1133,7 +1138,7 @@ module Closure = struct
11331138 @ l ))
11341139 | (g , _ ) :: _ as functions ->
11351140 let function_count = List. length functions in
1136- let * env_typ = Type. rec_env_type ~function_count ~free_variable_count in
1141+ let * env_typ = Type. rec_env_type ~function_count ~env_type_id ~env_type in
11371142 let env =
11381143 if Code.Var. equal f g
11391144 then
@@ -1155,7 +1160,7 @@ module Closure = struct
11551160 load env
11561161 in
11571162 let * typ =
1158- Type. rec_closure_type ~cps ~arity ~function_count ~free_variable_count
1163+ Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type
11591164 in
11601165 let res =
11611166 let * env = env in
@@ -1200,12 +1205,13 @@ module Closure = struct
12001205 let * _ = add_var (Code.Var. fresh () ) in
12011206 return ()
12021207 else
1208+ let env_type_id = Option. value ~default: (- 1 ) info.id in
12031209 let _, arity = List. find ~f: (fun (f' , _ ) -> Code.Var. equal f f') info.functions in
12041210 let arity = if cps then arity - 1 else arity in
12051211 let offset = Memory. env_start arity in
12061212 match info.Closure_conversion. functions with
12071213 | [ _ ] ->
1208- let * typ = Type. env_type ~cps ~arity free_variable_count in
1214+ let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type: [] in
12091215 let * _ = add_var f in
12101216 let env = Code.Var. fresh_n " env" in
12111217 let * () =
@@ -1225,11 +1231,11 @@ module Closure = struct
12251231 | functions ->
12261232 let function_count = List. length functions in
12271233 let * typ =
1228- Type. rec_closure_type ~cps ~arity ~function_count ~free_variable_count
1234+ Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type: []
12291235 in
12301236 let * _ = add_var f in
12311237 let env = Code.Var. fresh_n " env" in
1232- let * env_typ = Type. rec_env_type ~function_count ~free_variable_count in
1238+ let * env_typ = Type. rec_env_type ~function_count ~env_type_id ~env_type: [] in
12331239 let * () =
12341240 store
12351241 ~typ: (W. Ref { nullable = false ; typ = Type env_typ })
0 commit comments