@@ -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
@@ -1099,11 +1096,19 @@ module Closure = struct
10991096 in
11001097 return (W. GlobalGet name)
11011098 else
1102- let free_variable_count = List. length free_variables in
1099+ let * env_type = expression_list variable_type free_variables in
1100+ let env_type_id =
1101+ try Hashtbl. find context.closure_types env_type
1102+ with Not_found ->
1103+ let id = Hashtbl. length context.closure_types in
1104+ Hashtbl. add context.closure_types env_type id;
1105+ id
1106+ in
1107+ info.id < - Some env_type_id;
11031108 match info.Closure_conversion. functions with
11041109 | [] -> assert false
11051110 | [ _ ] ->
1106- let * typ = Type. env_type ~cps ~arity free_variable_count in
1111+ let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type in
11071112 let * l = expression_list load free_variables in
11081113 return
11091114 (W. StructNew
@@ -1122,7 +1127,7 @@ module Closure = struct
11221127 @ l ))
11231128 | (g , _ ) :: _ as functions ->
11241129 let function_count = List. length functions in
1125- let * env_typ = Type. rec_env_type ~function_count ~free_variable_count in
1130+ let * env_typ = Type. rec_env_type ~function_count ~env_type_id ~env_type in
11261131 let env =
11271132 if Code.Var. equal f g
11281133 then
@@ -1144,7 +1149,7 @@ module Closure = struct
11441149 load env
11451150 in
11461151 let * typ =
1147- Type. rec_closure_type ~cps ~arity ~function_count ~free_variable_count
1152+ Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type
11481153 in
11491154 let res =
11501155 let * env = env in
@@ -1189,12 +1194,13 @@ module Closure = struct
11891194 let * _ = add_var (Code.Var. fresh () ) in
11901195 return ()
11911196 else
1197+ let env_type_id = Option. value ~default: (- 1 ) info.id in
11921198 let _, arity = List. find ~f: (fun (f' , _ ) -> Code.Var. equal f f') info.functions in
11931199 let arity = if cps then arity - 1 else arity in
11941200 let offset = Memory. env_start arity in
11951201 match info.Closure_conversion. functions with
11961202 | [ _ ] ->
1197- let * typ = Type. env_type ~cps ~arity free_variable_count in
1203+ let * typ = Type. env_type ~cps ~arity ~env_type_id ~env_type: [] in
11981204 let * _ = add_var f in
11991205 let env = Code.Var. fresh_n " env" in
12001206 let * () =
@@ -1214,11 +1220,11 @@ module Closure = struct
12141220 | functions ->
12151221 let function_count = List. length functions in
12161222 let * typ =
1217- Type. rec_closure_type ~cps ~arity ~function_count ~free_variable_count
1223+ Type. rec_closure_type ~cps ~arity ~function_count ~env_type_id ~env_type: []
12181224 in
12191225 let * _ = add_var f in
12201226 let env = Code.Var. fresh_n " env" in
1221- let * env_typ = Type. rec_env_type ~function_count ~free_variable_count in
1227+ let * env_typ = Type. rec_env_type ~function_count ~env_type_id ~env_type: [] in
12221228 let * () =
12231229 store
12241230 ~typ: (W. Ref { nullable = false ; typ = Type env_typ })
0 commit comments