Skip to content

Commit e8caec6

Browse files
authored
feat(compiler): Don't close over global values (#1134)
* fix(stdlib): Remove premature free in Map.toArray * feat(compiler): Don't close over global values
1 parent b9e9d59 commit e8caec6

File tree

126 files changed

+2691
-3686
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+2691
-3686
lines changed

compiler/src/codegen/compcore.re

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -683,8 +683,7 @@ let appropriate_incref = (wasm_mod, env, arg, b) =>
683683
| MLocalBind(_, Types.HeapAllocated)
684684
| MSwapBind(_, Types.HeapAllocated)
685685
| MClosureBind(_)
686-
| MGlobalBind(_, Types.HeapAllocated, true) =>
687-
call_incref(wasm_mod, env, arg)
686+
| MGlobalBind(_, Types.HeapAllocated) => call_incref(wasm_mod, env, arg)
688687
| MArgBind(_)
689688
| MLocalBind(_)
690689
| MSwapBind(_)
@@ -698,8 +697,7 @@ let appropriate_decref = (wasm_mod, env, arg, b) =>
698697
| MLocalBind(_, Types.HeapAllocated)
699698
| MSwapBind(_, Types.HeapAllocated)
700699
| MClosureBind(_)
701-
| MGlobalBind(_, Types.HeapAllocated, true) =>
702-
call_decref(wasm_mod, env, arg)
700+
| MGlobalBind(_, Types.HeapAllocated) => call_decref(wasm_mod, env, arg)
703701
| MArgBind(_)
704702
| MLocalBind(_)
705703
| MSwapBind(_)
@@ -852,16 +850,14 @@ let compile_bind =
852850
| BindSet(arg) => set_slot(slot, typ, arg)
853851
| BindTee(arg) => tee_slot(slot, typ, arg)
854852
};
855-
| MGlobalBind(slot, wasm_ty, gc) =>
853+
| MGlobalBind(slot, wasm_ty) =>
856854
let typ = wasm_type(wasm_ty);
857855
switch (action) {
858-
| BindGet when !gc => Expression.Global_get.make(wasm_mod, slot, typ)
859856
| BindGet =>
860857
appropriate_incref(
861858
wasm_mod,
862859
Expression.Global_get.make(wasm_mod, slot, typ),
863860
)
864-
| BindSet(arg) when !gc => Expression.Global_set.make(wasm_mod, slot, arg)
865861
| BindSet(arg) =>
866862
Expression.Global_set.make(
867863
wasm_mod,
@@ -881,15 +877,6 @@ let compile_bind =
881877
0,
882878
),
883879
)
884-
| BindTee(arg) when !gc =>
885-
Expression.Block.make(
886-
wasm_mod,
887-
gensym_label("BindTee"),
888-
[
889-
Expression.Global_set.make(wasm_mod, slot, arg),
890-
Expression.Global_get.make(wasm_mod, slot, typ),
891-
],
892-
)
893880
| BindTee(arg) =>
894881
Expression.Block.make(
895882
wasm_mod,

compiler/src/codegen/mashtree.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ type constant =
261261
type binding =
262262
| MArgBind(int32, Types.allocation_type)
263263
| MLocalBind(int32, Types.allocation_type)
264-
| MGlobalBind(string, Types.allocation_type, bool)
264+
| MGlobalBind(string, Types.allocation_type)
265265
| MClosureBind(int32)
266266
| MSwapBind(int32, Types.allocation_type) /* Used like a register would be */
267267
| MImport(int32); /* Index into list of imports */

compiler/src/codegen/transl_anf.re

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ open Mashtree;
99

1010
type compilation_env = {
1111
ce_binds: Ident.tbl(Mashtree.binding),
12-
/* Useful due to us needing a second pass over exports (for mutual recursion) */
13-
ce_exported_globals: Ident.tbl(int32),
1412
ce_stack_idx_ptr: int,
1513
ce_stack_idx_i32: int,
1614
ce_stack_idx_i64: int,
@@ -21,7 +19,6 @@ type compilation_env = {
2119

2220
let initial_compilation_env = {
2321
ce_binds: Ident.empty,
24-
ce_exported_globals: Ident.empty,
2522
ce_stack_idx_ptr: 0,
2623
ce_stack_idx_i32: 0,
2724
ce_stack_idx_i64: 0,
@@ -63,6 +60,16 @@ let next_lift = () => {
6360
ret;
6461
};
6562

63+
/** Imports which are always in scope */
64+
let global_imports = ref(Ident.Set.empty);
65+
66+
let set_global_imports = imports => {
67+
global_imports :=
68+
Ident.Set.of_list(
69+
Ident.fold_all((id, _, acc) => [id, ...acc], imports, []),
70+
);
71+
};
72+
6673
/** Global index (index of global variables) */
6774

6875
let global_table =
@@ -100,8 +107,14 @@ let next_global = (exported, id, ty: Types.allocation_type) =>
100107
ret;
101108
};
102109

103-
let find_id = (id, env) => Ident.find_same(id, env.ce_binds);
104-
let find_global = (id, env) => Ident.find_same(id, env.ce_exported_globals);
110+
let global_name = slot => Printf.sprintf("global_%d", slot);
111+
112+
let find_id = (id, env) =>
113+
try(Ident.find_same(id, env.ce_binds)) {
114+
| Not_found =>
115+
let (_, slot, alloc) = Ident.find_same(id, global_table^);
116+
MGlobalBind(global_name(Int32.to_int(slot)), alloc);
117+
};
105118

106119
let worklist_reset = () => Queue.clear(compilation_worklist);
107120
let worklist_enqueue = elt => Queue.add(elt, compilation_worklist);
@@ -544,17 +557,23 @@ let compile_lambda =
544557
register_function(id);
545558
let (body, return_type) = body;
546559
let used_var_set = Anf_utils.anf_free_vars(body);
547-
let free_var_set =
548-
Ident.Set.diff(used_var_set) @@
549-
Ident.Set.of_list(List.map(((arg, _)) => arg, args));
560+
let arg_vars = List.map(((arg, _)) => arg, args);
561+
let global_vars =
562+
Ident.fold_all((id, _, acc) => [id, ...acc], global_table^, []);
563+
let accessible_var_set =
564+
Ident.Set.union(
565+
global_imports^,
566+
Ident.Set.of_list(arg_vars @ global_vars),
567+
);
568+
let free_var_set = Ident.Set.diff(used_var_set, accessible_var_set);
550569
let free_vars = Ident.Set.elements(free_var_set);
551570
/* Bind all non-arguments in the function body to
552571
their respective closure slots */
553572
let free_binds =
554573
List_utils.fold_lefti(
555574
(acc, closure_idx, var) =>
556575
Ident.add(var, MClosureBind(Int32.of_int(closure_idx)), acc),
557-
Ident.empty,
576+
env.ce_binds,
558577
free_vars,
559578
);
560579
let closure_arg = (Ident.create("$self"), Types.HeapAllocated);
@@ -579,7 +598,6 @@ let compile_lambda =
579598
) =
580599
Anf_utils.anf_count_vars(body);
581600
let lam_env = {
582-
...env,
583601
ce_binds: arg_binds,
584602
ce_stack_idx_ptr: 0,
585603
ce_stack_idx_i32: 0,
@@ -650,7 +668,6 @@ let compile_wrapper = (id, env, func_name, args, rets): Mashtree.closure_data =>
650668
let idx = next_lift();
651669
let arity = List.length(args);
652670
let lam_env = {
653-
...env,
654671
ce_binds: Ident.empty,
655672
ce_stack_idx_ptr: 0,
656673
ce_stack_idx_i32: 0,
@@ -687,7 +704,7 @@ let compile_wrapper = (id, env, func_name, args, rets): Mashtree.closure_data =>
687704

688705
let next_global = (~exported=false, id, ty) => {
689706
let ret = next_global(exported, id, ty);
690-
Printf.sprintf("global_%d", ret);
707+
global_name(ret);
691708
};
692709

693710
let rec compile_comp = (~id=?, env, c) => {
@@ -882,44 +899,39 @@ and compile_anf_expr = (env, a) =>
882899
let rec get_locs = (env, binds) => {
883900
switch (binds) {
884901
| [(id, {comp_allocation_type}), ...rest] =>
885-
let (alloc, gc, stack_idx, next_env) =
902+
let (alloc, stack_idx, next_env) =
886903
switch (comp_allocation_type) {
887904
| HeapAllocated => (
888905
Types.HeapAllocated,
889-
true,
890906
env.ce_stack_idx_ptr,
891907
{...env, ce_stack_idx_ptr: env.ce_stack_idx_ptr + 1},
892908
)
893909
| StackAllocated(WasmI32) => (
894910
Types.StackAllocated(WasmI32),
895-
false,
896911
env.ce_stack_idx_i32,
897912
{...env, ce_stack_idx_i32: env.ce_stack_idx_i32 + 1},
898913
)
899914
| StackAllocated(WasmI64) => (
900915
Types.StackAllocated(WasmI64),
901-
false,
902916
env.ce_stack_idx_i64,
903917
{...env, ce_stack_idx_i64: env.ce_stack_idx_i64 + 1},
904918
)
905919
| StackAllocated(WasmF32) => (
906920
Types.StackAllocated(WasmF32),
907-
false,
908921
env.ce_stack_idx_f32,
909922
{...env, ce_stack_idx_f32: env.ce_stack_idx_f32 + 1},
910923
)
911924
| StackAllocated(WasmF64) => (
912925
Types.StackAllocated(WasmF64),
913-
false,
914926
env.ce_stack_idx_f64,
915927
{...env, ce_stack_idx_f64: env.ce_stack_idx_f64 + 1},
916928
)
917929
};
918930
let (env, loc) =
919931
switch (global) {
920-
| Global => (
932+
| Global({exported}) => (
921933
env,
922-
MGlobalBind(next_global(~exported=true, id, alloc), alloc, gc),
934+
MGlobalBind(next_global(~exported, id, alloc), alloc),
923935
)
924936
| Nonglobal => (
925937
next_env,
@@ -1022,10 +1034,9 @@ let lift_imports = (env, imports) => {
10221034
| GrainValue(mod_, name) =>
10231035
let mimp_mod = Ident.create_persistent(mod_);
10241036
let mimp_name = Ident.create_persistent(name);
1025-
let (alloc, gc) =
1037+
let alloc =
10261038
switch (imp_shape) {
1027-
| GlobalShape(HeapAllocated as alloc) => (alloc, true)
1028-
| GlobalShape(alloc) => (alloc, false)
1039+
| GlobalShape(alloc) => alloc
10291040
| FunctionShape(_) =>
10301041
failwith("internal: GrainValue had FunctionShape")
10311042
};
@@ -1051,7 +1062,6 @@ let lift_imports = (env, imports) => {
10511062
Ident.name(mimp_name),
10521063
),
10531064
alloc,
1054-
gc,
10551065
),
10561066
env.ce_binds,
10571067
),
@@ -1060,10 +1070,9 @@ let lift_imports = (env, imports) => {
10601070
| WasmValue(mod_, name) =>
10611071
let mimp_mod = Ident.create_persistent(mod_);
10621072
let mimp_name = Ident.create_persistent(name);
1063-
let (alloc, gc) =
1073+
let alloc =
10641074
switch (imp_shape) {
1065-
| GlobalShape(HeapAllocated as alloc) => (alloc, true)
1066-
| GlobalShape(alloc) => (alloc, false)
1075+
| GlobalShape(alloc) => alloc
10671076
| FunctionShape(_) =>
10681077
failwith("internal: WasmValue had FunctionShape")
10691078
};
@@ -1089,7 +1098,6 @@ let lift_imports = (env, imports) => {
10891098
Ident.name(mimp_name),
10901099
),
10911100
alloc,
1092-
gc,
10931101
),
10941102
env.ce_binds,
10951103
),
@@ -1098,7 +1106,7 @@ let lift_imports = (env, imports) => {
10981106
| WasmFunction(mod_, name) =>
10991107
let glob =
11001108
next_global(
1101-
~exported=imp_exported == Global,
1109+
~exported=imp_exported == Global({exported: true}),
11021110
imp_use_id,
11031111
Types.StackAllocated(WasmI32),
11041112
);
@@ -1129,11 +1137,7 @@ let lift_imports = (env, imports) => {
11291137
instr_desc:
11301138
MStore([
11311139
(
1132-
MGlobalBind(
1133-
glob,
1134-
Types.StackAllocated(WasmI32),
1135-
true,
1136-
),
1140+
MGlobalBind(glob, Types.HeapAllocated),
11371141
{
11381142
instr_desc:
11391143
MAllocate(
@@ -1163,7 +1167,7 @@ let lift_imports = (env, imports) => {
11631167
ce_binds:
11641168
Ident.add(
11651169
imp_use_id,
1166-
MGlobalBind(glob, Types.StackAllocated(WasmI32), true),
1170+
MGlobalBind(glob, HeapAllocated),
11671171
env.ce_binds,
11681172
),
11691173
},
@@ -1188,6 +1192,9 @@ let transl_anf_program =
11881192

11891193
let (imports, setups, env) =
11901194
lift_imports(initial_compilation_env, anf_prog.imports);
1195+
1196+
set_global_imports(env.ce_binds);
1197+
11911198
let (
11921199
stack_size_ptr,
11931200
stack_size_i32,

compiler/src/middle_end/analyze_closure_scoped_vars.re

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ module CSVArg: Anf_iterator.IterArgument = {
2121

2222
let leave_anf_expression = ({anf_desc: desc}) => {
2323
switch (desc) {
24-
| AELet(Global, _, _, binds, _) =>
25-
/* Assume that all globals are closure scope, since globals could
24+
| AELet(Global({exported: true}), _, _, binds, _) =>
25+
/* Assume that all exported globals are closure scope, since globals could
2626
appear in a closure scope in another module */
2727
let ids = List.map(fst, binds);
2828
closure_scoped_vars :=

compiler/src/middle_end/anf_utils.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,8 @@ let rec anf_count_vars = a =>
185185
List.map(((_, c)) => comp_count_vars(c), binds);
186186
let rec count_binds = (ptr, i32, i64, f32, f64, binds) => {
187187
switch (global, binds) {
188-
| (Global, [_, ...rest]) => count_binds(ptr, i32, i64, f32, f64, rest)
188+
| (Global(_), [_, ...rest]) =>
189+
count_binds(ptr, i32, i64, f32, f64, rest)
189190
| (_, [(_, {comp_allocation_type: HeapAllocated}), ...rest]) =>
190191
count_binds(ptr + 1, i32, i64, f32, f64, rest)
191192
| (

compiler/src/middle_end/anftree.re

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ open Types;
88
type rec_flag = Asttypes.rec_flag = | Nonrecursive | Recursive;
99
[@deriving sexp]
1010
type global_flag =
11-
| Global
11+
| Global({exported: bool})
1212
| Nonglobal;
1313

1414
type loc('a) = Location.loc('a);
@@ -387,6 +387,7 @@ type anf_program = {
387387

388388
type anf_bind =
389389
| BSeq(comp_expression)
390-
| BLet(Ident.t, comp_expression)
391-
| BLetRec(list((Ident.t, comp_expression)))
392-
| BLetExport(rec_flag, list((Ident.t, comp_expression)));
390+
| BLet(Ident.t, comp_expression, global_flag)
391+
| BLetMut(Ident.t, comp_expression, global_flag)
392+
| BLetRec(list((Ident.t, comp_expression)), global_flag)
393+
| BLetRecMut(list((Ident.t, comp_expression)), global_flag);

compiler/src/middle_end/anftree.rei

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ open Types;
99
type rec_flag = Asttypes.rec_flag = | Nonrecursive | Recursive;
1010
[@deriving sexp]
1111
type global_flag =
12-
| Global
12+
| Global({exported: bool})
1313
| Nonglobal;
1414

1515
type loc('a) = Location.loc('a);
@@ -371,6 +371,7 @@ type anf_program = {
371371

372372
type anf_bind =
373373
| BSeq(comp_expression)
374-
| BLet(Ident.t, comp_expression)
375-
| BLetRec(list((Ident.t, comp_expression)))
376-
| BLetExport(rec_flag, list((Ident.t, comp_expression)));
374+
| BLet(Ident.t, comp_expression, global_flag)
375+
| BLetMut(Ident.t, comp_expression, global_flag)
376+
| BLetRec(list((Ident.t, comp_expression)), global_flag)
377+
| BLetRecMut(list((Ident.t, comp_expression)), global_flag);

0 commit comments

Comments
 (0)