@@ -34,20 +34,53 @@ let new_label () =
34
34
(* *** Operations on compilation environments. ****)
35
35
36
36
let empty_env =
37
- { ce_stack = Ident. empty; ce_heap = Ident. empty; ce_rec = Ident. empty }
37
+ { ce_stack = Ident. empty; ce_closure = Not_in_closure }
38
38
39
39
(* Add a stack-allocated variable *)
40
40
41
41
let add_var id pos env =
42
42
{ ce_stack = Ident. add id pos env.ce_stack;
43
- ce_heap = env.ce_heap;
44
- ce_rec = env.ce_rec }
43
+ ce_closure = env.ce_closure }
45
44
46
45
let rec add_vars idlist pos env =
47
46
match idlist with
48
47
[] -> env
49
48
| id :: rem -> add_vars rem (pos + 1 ) (add_var id pos env)
50
49
50
+ (* Compute the closure environment *)
51
+
52
+ let rec add_positions entries pos_to_entry ~pos ~delta = function
53
+ | [] -> entries, pos
54
+ | id :: rem ->
55
+ let entries =
56
+ Ident. add id (pos_to_entry pos) entries
57
+ in
58
+ add_positions entries pos_to_entry ~pos: (pos + delta) ~delta rem
59
+
60
+ type function_definition =
61
+ | Single_non_recursive
62
+ | Multiple_recursive of Ident .t list
63
+
64
+ let closure_entries fun_defs fvs =
65
+ let funct_entries, pos_end_functs =
66
+ match fun_defs with
67
+ | Single_non_recursive ->
68
+ (* No need to store the function in the environment, but we still need to
69
+ reserve a slot in the closure block *)
70
+ Ident. empty, 3
71
+ | Multiple_recursive functs ->
72
+ add_positions Ident. empty (fun pos -> Function pos) ~pos: 0 ~delta: 3 functs
73
+ in
74
+ (* Note: [pos_end_functs] is the position where we would store the next
75
+ function if there was one, and points after an eventual infix tag.
76
+ Since that was the last function, we don't need the last infix tag
77
+ and start storing free variables at [pos_end_functs - 1]. *)
78
+ let all_entries, _end_pos =
79
+ add_positions funct_entries (fun pos -> Free_variable pos)
80
+ ~pos: (pos_end_functs - 1 ) ~delta: 1 fvs
81
+ in
82
+ all_entries
83
+
51
84
(* *** Examination of the continuation ****)
52
85
53
86
(* Return a label to the beginning of the given continuation.
@@ -370,9 +403,8 @@ type function_to_compile =
370
403
{ params : Ident .t list ; (* function parameters *)
371
404
body : lambda ; (* the function body *)
372
405
label : label ; (* the label of the function entry *)
373
- free_vars : Ident .t list ; (* free variables of the function *)
374
- num_defs : int ; (* number of mutually recursive definitions *)
375
- rec_vars : Ident .t list ; (* mutually recursive fn names *)
406
+ entries : closure_entry Ident .tbl ; (* the offsets for the free variables
407
+ and mutually recursive functions *)
376
408
rec_pos : int } (* rank in recursive definition *)
377
409
378
410
let functions_to_compile = (Stack. create () : function_to_compile Stack. t)
@@ -570,15 +602,18 @@ let rec comp_expr stack_info env exp sz cont =
570
602
let pos = Ident. find_same id env.ce_stack in
571
603
Kacc (sz - pos) :: cont
572
604
with Not_found ->
573
- try
574
- let pos = Ident. find_same id env.ce_heap in
575
- Kenvacc (pos) :: cont
576
- with Not_found ->
577
- try
578
- let ofs = Ident. find_same id env.ce_rec in
579
- Koffsetclosure (ofs) :: cont
580
- with Not_found ->
605
+ let not_found () =
581
606
fatal_error (" Bytegen.comp_expr: var " ^ Ident. unique_name id)
607
+ in
608
+ match env.ce_closure with
609
+ | Not_in_closure -> not_found ()
610
+ | In_closure { entries; env_pos } ->
611
+ match Ident. find_same id entries with
612
+ | Free_variable pos ->
613
+ Kenvacc (pos - env_pos) :: cont
614
+ | Function pos ->
615
+ Koffsetclosure (pos - env_pos) :: cont
616
+ | exception Not_found -> not_found ()
582
617
end
583
618
| Lconst cst ->
584
619
Kconst cst :: cont
@@ -627,9 +662,10 @@ let rec comp_expr stack_info env exp sz cont =
627
662
let cont = add_pseudo_event loc ! compunit_name cont in
628
663
let lbl = new_label() in
629
664
let fv = Ident.Set. elements(free_variables exp) in
665
+ let entries = closure_entries Single_non_recursive fv in
630
666
let to_compile =
631
667
{ params = List. map fst params; body = body; label = lbl;
632
- free_vars = fv; num_defs = 1 ; rec_vars = [] ; rec_pos = 0 } in
668
+ entries = entries ; rec_pos = 0 } in
633
669
Stack. push to_compile functions_to_compile;
634
670
comp_args stack_info env (List. map (fun n -> Lvar n) fv) sz
635
671
(Kclosure (lbl, List. length fv) :: cont)
@@ -646,14 +682,16 @@ let rec comp_expr stack_info env exp sz cont =
646
682
let fv =
647
683
Ident.Set. elements (free_variables (Lletrec (decl, lambda_unit))) in
648
684
let rec_idents = List. map (fun (id , _lam ) -> id) decl in
685
+ let entries =
686
+ closure_entries (Multiple_recursive rec_idents) fv
687
+ in
649
688
let rec comp_fun pos = function
650
689
[] -> []
651
690
| (_id , Lfunction{params; body} ) :: rem ->
652
691
let lbl = new_label() in
653
692
let to_compile =
654
693
{ params = List. map fst params; body = body; label = lbl;
655
- free_vars = fv; num_defs = ndecl; rec_vars = rec_idents;
656
- rec_pos = pos} in
694
+ entries = entries; rec_pos = pos} in
657
695
Stack. push to_compile functions_to_compile;
658
696
lbl :: comp_fun (pos + 1 ) rem
659
697
| _ -> assert false in
@@ -1119,13 +1157,15 @@ let comp_block env exp sz cont =
1119
1157
1120
1158
let comp_function tc cont =
1121
1159
let arity = List. length tc.params in
1122
- let rec positions pos delta = function
1123
- [] -> Ident. empty
1124
- | id :: rem -> Ident. add id pos (positions (pos + delta) delta rem) in
1160
+ let ce_stack, _last_pos =
1161
+ add_positions Ident. empty Fun. id ~pos: arity ~delta: ( - 1 ) tc.params
1162
+ in
1125
1163
let env =
1126
- { ce_stack = positions arity (- 1 ) tc.params;
1127
- ce_heap = positions (3 * (tc.num_defs - tc.rec_pos) - 1 ) 1 tc.free_vars;
1128
- ce_rec = positions (- 3 * tc.rec_pos) 3 tc.rec_vars } in
1164
+ { ce_stack;
1165
+ ce_closure =
1166
+ In_closure { entries = tc.entries; env_pos = 3 * tc.rec_pos }
1167
+ }
1168
+ in
1129
1169
let cont =
1130
1170
comp_block env tc.body arity (Kreturn arity :: cont) in
1131
1171
if arity > 1 then
0 commit comments