Skip to content

Commit

Permalink
feat(compiler): Don't close over global values
Browse files Browse the repository at this point in the history
  • Loading branch information
ospencer committed Feb 27, 2022
1 parent ab63bb5 commit 536ba56
Show file tree
Hide file tree
Showing 125 changed files with 2,042 additions and 2,312 deletions.
19 changes: 3 additions & 16 deletions compiler/src/codegen/compcore.re
Original file line number Diff line number Diff line change
Expand Up @@ -687,8 +687,7 @@ let appropriate_incref = (wasm_mod, env, arg, b) =>
| MLocalBind(_, Types.HeapAllocated)
| MSwapBind(_, Types.HeapAllocated)
| MClosureBind(_)
| MGlobalBind(_, Types.HeapAllocated, true) =>
call_incref(wasm_mod, env, arg)
| MGlobalBind(_, Types.HeapAllocated) => call_incref(wasm_mod, env, arg)
| MArgBind(_)
| MLocalBind(_)
| MSwapBind(_)
Expand All @@ -702,8 +701,7 @@ let appropriate_decref = (wasm_mod, env, arg, b) =>
| MLocalBind(_, Types.HeapAllocated)
| MSwapBind(_, Types.HeapAllocated)
| MClosureBind(_)
| MGlobalBind(_, Types.HeapAllocated, true) =>
call_decref(wasm_mod, env, arg)
| MGlobalBind(_, Types.HeapAllocated) => call_decref(wasm_mod, env, arg)
| MArgBind(_)
| MLocalBind(_)
| MSwapBind(_)
Expand Down Expand Up @@ -856,16 +854,14 @@ let compile_bind =
| BindSet(arg) => set_slot(slot, typ, arg)
| BindTee(arg) => tee_slot(slot, typ, arg)
};
| MGlobalBind(slot, wasm_ty, gc) =>
| MGlobalBind(slot, wasm_ty) =>
let typ = wasm_type(wasm_ty);
switch (action) {
| BindGet when !gc => Expression.Global_get.make(wasm_mod, slot, typ)
| BindGet =>
appropriate_incref(
wasm_mod,
Expression.Global_get.make(wasm_mod, slot, typ),
)
| BindSet(arg) when !gc => Expression.Global_set.make(wasm_mod, slot, arg)
| BindSet(arg) =>
Expression.Global_set.make(
wasm_mod,
Expand All @@ -885,15 +881,6 @@ let compile_bind =
0,
),
)
| BindTee(arg) when !gc =>
Expression.Block.make(
wasm_mod,
gensym_label("BindTee"),
[
Expression.Global_set.make(wasm_mod, slot, arg),
Expression.Global_get.make(wasm_mod, slot, typ),
],
)
| BindTee(arg) =>
Expression.Block.make(
wasm_mod,
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/codegen/mashtree.re
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ type constant =
type binding =
| MArgBind(int32, Types.allocation_type)
| MLocalBind(int32, Types.allocation_type)
| MGlobalBind(string, Types.allocation_type, bool)
| MGlobalBind(string, Types.allocation_type)
| MClosureBind(int32)
| MSwapBind(int32, Types.allocation_type) /* Used like a register would be */
| MImport(int32); /* Index into list of imports */
Expand Down
77 changes: 42 additions & 35 deletions compiler/src/codegen/transl_anf.re
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ open Mashtree;

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

let initial_compilation_env = {
ce_binds: Ident.empty,
ce_exported_globals: Ident.empty,
ce_stack_idx_ptr: 0,
ce_stack_idx_i32: 0,
ce_stack_idx_i64: 0,
Expand Down Expand Up @@ -63,6 +60,16 @@ let next_lift = () => {
ret;
};

/** Imports which are always in scope */
let global_imports = ref(Ident.Set.empty);

let set_global_imports = imports => {
global_imports :=
Ident.Set.of_list(
Ident.fold_all((id, _, acc) => [id, ...acc], imports, []),
);
};

/** Global index (index of global variables) */

let global_table =
Expand Down Expand Up @@ -100,8 +107,14 @@ let next_global = (exported, id, ty: Types.allocation_type) =>
ret;
};

let find_id = (id, env) => Ident.find_same(id, env.ce_binds);
let find_global = (id, env) => Ident.find_same(id, env.ce_exported_globals);
let global_name = slot => Printf.sprintf("global_%d", slot);

let find_id = (id, env) =>
try(Ident.find_same(id, env.ce_binds)) {
| Not_found =>
let (_, slot, alloc) = Ident.find_same(id, global_table^);
MGlobalBind(global_name(Int32.to_int(slot)), alloc);
};

let worklist_reset = () => Queue.clear(compilation_worklist);
let worklist_enqueue = elt => Queue.add(elt, compilation_worklist);
Expand Down Expand Up @@ -544,17 +557,23 @@ let compile_lambda =
register_function(id);
let (body, return_type) = body;
let used_var_set = Anf_utils.anf_free_vars(body);
let free_var_set =
Ident.Set.diff(used_var_set) @@
Ident.Set.of_list(List.map(((arg, _)) => arg, args));
let arg_vars = List.map(((arg, _)) => arg, args);
let global_vars =
Ident.fold_all((id, _, acc) => [id, ...acc], global_table^, []);
let accessible_var_set =
Ident.Set.union(
global_imports^,
Ident.Set.of_list(arg_vars @ global_vars),
);
let free_var_set = Ident.Set.diff(used_var_set, accessible_var_set);
let free_vars = Ident.Set.elements(free_var_set);
/* Bind all non-arguments in the function body to
their respective closure slots */
let free_binds =
List_utils.fold_lefti(
(acc, closure_idx, var) =>
Ident.add(var, MClosureBind(Int32.of_int(closure_idx)), acc),
Ident.empty,
env.ce_binds,
free_vars,
);
let closure_arg = (Ident.create("$self"), Types.HeapAllocated);
Expand All @@ -579,7 +598,6 @@ let compile_lambda =
) =
Anf_utils.anf_count_vars(body);
let lam_env = {
...env,
ce_binds: arg_binds,
ce_stack_idx_ptr: 0,
ce_stack_idx_i32: 0,
Expand Down Expand Up @@ -650,7 +668,6 @@ let compile_wrapper = (id, env, func_name, args, rets): Mashtree.closure_data =>
let idx = next_lift();
let arity = List.length(args);
let lam_env = {
...env,
ce_binds: Ident.empty,
ce_stack_idx_ptr: 0,
ce_stack_idx_i32: 0,
Expand Down Expand Up @@ -687,7 +704,7 @@ let compile_wrapper = (id, env, func_name, args, rets): Mashtree.closure_data =>

let next_global = (~exported=false, id, ty) => {
let ret = next_global(exported, id, ty);
Printf.sprintf("global_%d", ret);
global_name(ret);
};

let rec compile_comp = (~id=?, env, c) => {
Expand Down Expand Up @@ -882,44 +899,39 @@ and compile_anf_expr = (env, a) =>
let rec get_locs = (env, binds) => {
switch (binds) {
| [(id, {comp_allocation_type}), ...rest] =>
let (alloc, gc, stack_idx, next_env) =
let (alloc, stack_idx, next_env) =
switch (comp_allocation_type) {
| HeapAllocated => (
Types.HeapAllocated,
true,
env.ce_stack_idx_ptr,
{...env, ce_stack_idx_ptr: env.ce_stack_idx_ptr + 1},
)
| StackAllocated(WasmI32) => (
Types.StackAllocated(WasmI32),
false,
env.ce_stack_idx_i32,
{...env, ce_stack_idx_i32: env.ce_stack_idx_i32 + 1},
)
| StackAllocated(WasmI64) => (
Types.StackAllocated(WasmI64),
false,
env.ce_stack_idx_i64,
{...env, ce_stack_idx_i64: env.ce_stack_idx_i64 + 1},
)
| StackAllocated(WasmF32) => (
Types.StackAllocated(WasmF32),
false,
env.ce_stack_idx_f32,
{...env, ce_stack_idx_f32: env.ce_stack_idx_f32 + 1},
)
| StackAllocated(WasmF64) => (
Types.StackAllocated(WasmF64),
false,
env.ce_stack_idx_f64,
{...env, ce_stack_idx_f64: env.ce_stack_idx_f64 + 1},
)
};
let (env, loc) =
switch (global) {
| Global => (
| Global({exported}) => (
env,
MGlobalBind(next_global(~exported=true, id, alloc), alloc, gc),
MGlobalBind(next_global(~exported, id, alloc), alloc),
)
| Nonglobal => (
next_env,
Expand Down Expand Up @@ -1022,10 +1034,9 @@ let lift_imports = (env, imports) => {
| GrainValue(mod_, name) =>
let mimp_mod = Ident.create_persistent(mod_);
let mimp_name = Ident.create_persistent(name);
let (alloc, gc) =
let alloc =
switch (imp_shape) {
| GlobalShape(HeapAllocated as alloc) => (alloc, true)
| GlobalShape(alloc) => (alloc, false)
| GlobalShape(alloc) => alloc
| FunctionShape(_) =>
failwith("internal: GrainValue had FunctionShape")
};
Expand All @@ -1051,7 +1062,6 @@ let lift_imports = (env, imports) => {
Ident.name(mimp_name),
),
alloc,
gc,
),
env.ce_binds,
),
Expand All @@ -1060,10 +1070,9 @@ let lift_imports = (env, imports) => {
| WasmValue(mod_, name) =>
let mimp_mod = Ident.create_persistent(mod_);
let mimp_name = Ident.create_persistent(name);
let (alloc, gc) =
let alloc =
switch (imp_shape) {
| GlobalShape(HeapAllocated as alloc) => (alloc, true)
| GlobalShape(alloc) => (alloc, false)
| GlobalShape(alloc) => alloc
| FunctionShape(_) =>
failwith("internal: WasmValue had FunctionShape")
};
Expand All @@ -1089,7 +1098,6 @@ let lift_imports = (env, imports) => {
Ident.name(mimp_name),
),
alloc,
gc,
),
env.ce_binds,
),
Expand All @@ -1098,7 +1106,7 @@ let lift_imports = (env, imports) => {
| WasmFunction(mod_, name) =>
let glob =
next_global(
~exported=imp_exported == Global,
~exported=imp_exported == Global({exported: true}),
imp_use_id,
Types.StackAllocated(WasmI32),
);
Expand Down Expand Up @@ -1129,11 +1137,7 @@ let lift_imports = (env, imports) => {
instr_desc:
MStore([
(
MGlobalBind(
glob,
Types.StackAllocated(WasmI32),
true,
),
MGlobalBind(glob, Types.HeapAllocated),
{
instr_desc:
MAllocate(
Expand Down Expand Up @@ -1163,7 +1167,7 @@ let lift_imports = (env, imports) => {
ce_binds:
Ident.add(
imp_use_id,
MGlobalBind(glob, Types.StackAllocated(WasmI32), true),
MGlobalBind(glob, HeapAllocated),
env.ce_binds,
),
},
Expand All @@ -1188,6 +1192,9 @@ let transl_anf_program =

let (imports, setups, env) =
lift_imports(initial_compilation_env, anf_prog.imports);

set_global_imports(env.ce_binds);

let (
stack_size_ptr,
stack_size_i32,
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/middle_end/analyze_closure_scoped_vars.re
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ module CSVArg: Anf_iterator.IterArgument = {

let leave_anf_expression = ({anf_desc: desc}) => {
switch (desc) {
| AELet(Global, _, _, binds, _) =>
/* Assume that all globals are closure scope, since globals could
| AELet(Global({exported: true}), _, _, binds, _) =>
/* Assume that all exported globals are closure scope, since globals could
appear in a closure scope in another module */
let ids = List.map(fst, binds);
closure_scoped_vars :=
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/middle_end/anf_utils.re
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ let rec anf_count_vars = a =>
List.map(((_, c)) => comp_count_vars(c), binds);
let rec count_binds = (ptr, i32, i64, f32, f64, binds) => {
switch (global, binds) {
| (Global, [_, ...rest]) => count_binds(ptr, i32, i64, f32, f64, rest)
| (Global(_), [_, ...rest]) =>
count_binds(ptr, i32, i64, f32, f64, rest)
| (_, [(_, {comp_allocation_type: HeapAllocated}), ...rest]) =>
count_binds(ptr + 1, i32, i64, f32, f64, rest)
| (
Expand Down
9 changes: 5 additions & 4 deletions compiler/src/middle_end/anftree.re
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ open Types;
type rec_flag = Asttypes.rec_flag = | Nonrecursive | Recursive;
[@deriving sexp]
type global_flag =
| Global
| Global({exported: bool})
| Nonglobal;

type loc('a) = Location.loc('a);
Expand Down Expand Up @@ -387,6 +387,7 @@ type anf_program = {

type anf_bind =
| BSeq(comp_expression)
| BLet(Ident.t, comp_expression)
| BLetRec(list((Ident.t, comp_expression)))
| BLetExport(rec_flag, list((Ident.t, comp_expression)));
| BLet(Ident.t, comp_expression, global_flag)
| BLetMut(Ident.t, comp_expression, global_flag)
| BLetRec(list((Ident.t, comp_expression)), global_flag)
| BLetRecMut(list((Ident.t, comp_expression)), global_flag);
9 changes: 5 additions & 4 deletions compiler/src/middle_end/anftree.rei
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ open Types;
type rec_flag = Asttypes.rec_flag = | Nonrecursive | Recursive;
[@deriving sexp]
type global_flag =
| Global
| Global({exported: bool})
| Nonglobal;

type loc('a) = Location.loc('a);
Expand Down Expand Up @@ -371,6 +371,7 @@ type anf_program = {

type anf_bind =
| BSeq(comp_expression)
| BLet(Ident.t, comp_expression)
| BLetRec(list((Ident.t, comp_expression)))
| BLetExport(rec_flag, list((Ident.t, comp_expression)));
| BLet(Ident.t, comp_expression, global_flag)
| BLetMut(Ident.t, comp_expression, global_flag)
| BLetRec(list((Ident.t, comp_expression)), global_flag)
| BLetRecMut(list((Ident.t, comp_expression)), global_flag);
Loading

0 comments on commit 536ba56

Please sign in to comment.