Skip to content

Commit 67575f7

Browse files
authored
feat(compiler)!: Selectively include functions in the global function table (#1183)
* feat(compiler)!: Selectively include functions in the global function table * Snapshots * Add clarifying comments
1 parent ef2835a commit 67575f7

File tree

72 files changed

+2705
-2922
lines changed

Some content is hidden

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

72 files changed

+2705
-2922
lines changed

compiler/src/codegen/compcore.re

Lines changed: 86 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ let console_mod = Ident.create_persistent("console");
6161
let print_exception_ident = Ident.create_persistent("printException");
6262
let print_exception_closure_ident =
6363
Ident.create_persistent("GRAIN$EXPORT$printException");
64-
let assertion_error_ident =
64+
let assertion_error_ident = Ident.create_persistent("AssertionError");
65+
let assertion_error_closure_ident =
6566
Ident.create_persistent("GRAIN$EXPORT$AssertionError");
6667
let index_out_of_bounds_ident =
6768
Ident.create_persistent("GRAIN$EXPORT$IndexOutOfBounds");
@@ -88,7 +89,7 @@ let required_global_imports = [
8889
mimp_type: MGlobalImport(Types.StackAllocated(WasmI32), false),
8990
mimp_kind: MImportWasm,
9091
mimp_setup: MSetupNone,
91-
mimp_used: false,
92+
mimp_used: true,
9293
},
9394
{
9495
mimp_mod: grain_env_mod,
@@ -108,7 +109,7 @@ let required_global_imports = [
108109
},
109110
{
110111
mimp_mod: exception_mod,
111-
mimp_name: assertion_error_ident,
112+
mimp_name: assertion_error_closure_ident,
112113
mimp_type: MGlobalImport(Types.StackAllocated(WasmI32), true),
113114
mimp_kind: MImportWasm,
114115
mimp_setup: MSetupNone,
@@ -183,6 +184,18 @@ let required_function_imports = [
183184
mimp_setup: MSetupNone,
184185
mimp_used: false,
185186
},
187+
{
188+
mimp_mod: exception_mod,
189+
mimp_name: assertion_error_ident,
190+
mimp_type:
191+
MFuncImport(
192+
[Types.StackAllocated(WasmI32), Types.StackAllocated(WasmI32)],
193+
[Types.StackAllocated(WasmI32)],
194+
),
195+
mimp_kind: MImportWasm,
196+
mimp_setup: MSetupNone,
197+
mimp_used: false,
198+
},
186199
];
187200

188201
let grain_function_imports = [
@@ -296,7 +309,10 @@ let runtime_type_metadata_ptr = () => runtime_heap_ptr^ + 0x08;
296309

297310
let reset = () => {
298311
reset_labels();
299-
List.iter(imp => imp.mimp_used = false, runtime_imports);
312+
List.iter(
313+
imp => imp.mimp_used = imp.mimp_mod == grain_env_mod,
314+
runtime_imports,
315+
);
300316
runtime_heap_ptr :=
301317
(
302318
switch (Grain_utils.Config.memory_base^) {
@@ -741,7 +757,7 @@ let compile_bind =
741757
/* Closure bindings need to be calculated */
742758
if (!(action == BindGet)) {
743759
failwith(
744-
"Internal error: attempted to emit instruction which would mutate closure contents",
760+
"Internal error: attempted to emit instruction which would mutate closure values",
745761
);
746762
};
747763
appropriate_incref(
@@ -973,38 +989,31 @@ let compile_imm =
973989
};
974990

975991
let call_error_handler = (wasm_mod, env, err, args) => {
976-
let err_ident =
992+
let (err_value_ident, err_func_ident) =
977993
switch (err) {
978-
| Runtime_errors.MatchFailure => match_failure_ident
979-
| Runtime_errors.IndexOutOfBounds => index_out_of_bounds_ident
980-
| Runtime_errors.AssertionError => assertion_error_ident
994+
| Runtime_errors.MatchFailure => (match_failure_ident, None)
995+
| Runtime_errors.IndexOutOfBounds => (index_out_of_bounds_ident, None)
996+
| Runtime_errors.AssertionError => (
997+
assertion_error_closure_ident,
998+
Some(get_wasm_imported_name(exception_mod, assertion_error_ident)),
999+
)
9811000
};
9821001
let mk_err = () =>
9831002
Expression.Global_get.make(
9841003
wasm_mod,
985-
get_wasm_imported_name(exception_mod, err_ident),
1004+
get_wasm_imported_name(exception_mod, err_value_ident),
9861005
Type.int32,
9871006
);
9881007
let err =
9891008
switch (args) {
9901009
| [] => mk_err()
9911010
| _ =>
9921011
let compiled_args = args;
993-
Expression.Call_indirect.make(
1012+
Expression.Call.make(
9941013
wasm_mod,
995-
global_function_table,
996-
load(~offset=8, wasm_mod, mk_err()),
1014+
Option.get(err_func_ident),
9971015
[mk_err(), ...compiled_args],
998-
Type.create @@
999-
Array.map(
1000-
wasm_type,
1001-
Array.of_list([
1002-
Types.StackAllocated(WasmI32),
1003-
...List.map(_ => Types.StackAllocated(WasmI32), args),
1004-
]),
1005-
),
1006-
Type.create @@
1007-
Array.map(wasm_type, Array.of_list([Types.StackAllocated(WasmI32)])),
1016+
Type.int32,
10081017
);
10091018
};
10101019
Expression.Block.make(
@@ -1393,6 +1402,33 @@ let compile_record_op = (wasm_mod, env, rec_imm, op) => {
13931402
};
13941403
};
13951404

1405+
let compile_closure_op = (wasm_mod, env, closure_imm, op) => {
1406+
// We skip the incref here as this is akin to using a swap slot (the
1407+
// reference we create here cannot escape, so there isn't a need to add an
1408+
// incref/decref pair). Since it won't live in a local, it wouldn't be
1409+
// cleaned up automatically anyway.
1410+
let closure = () =>
1411+
compile_imm(~skip_incref=true, wasm_mod, env, closure_imm);
1412+
switch (op) {
1413+
| MClosureSetPtr(idx) =>
1414+
store(
1415+
~offset=8,
1416+
wasm_mod,
1417+
closure(),
1418+
Expression.Binary.make(
1419+
wasm_mod,
1420+
Op.add_int32,
1421+
Expression.Global_get.make(
1422+
wasm_mod,
1423+
get_wasm_imported_name(grain_env_mod, reloc_base),
1424+
Type.int32,
1425+
),
1426+
Expression.Const.make(wasm_mod, wrap_int32(idx)),
1427+
),
1428+
)
1429+
};
1430+
};
1431+
13961432
/** Heap allocations. */
13971433

13981434
/** Rounds the given number of words to be aligned correctly */
@@ -1729,6 +1765,22 @@ let allocate_closure =
17291765
);
17301766
patches := List.mapi(patch_var, variables);
17311767
};
1768+
let func_idx =
1769+
switch (func_idx) {
1770+
| Some(idx) =>
1771+
Expression.Binary.make(
1772+
wasm_mod,
1773+
Op.add_int32,
1774+
Expression.Global_get.make(
1775+
wasm_mod,
1776+
get_wasm_imported_name(grain_env_mod, reloc_base),
1777+
Type.int32,
1778+
),
1779+
Expression.Const.make(wasm_mod, wrap_int32(idx)),
1780+
)
1781+
// Use as a sentinel
1782+
| None => Expression.Const.make(wasm_mod, wrap_int32(-1l))
1783+
};
17321784
let preamble = [
17331785
store(
17341786
~offset=0,
@@ -1745,21 +1797,7 @@ let allocate_closure =
17451797
get_swap(),
17461798
Expression.Const.make(wasm_mod, wrap_int32(arity)),
17471799
),
1748-
store(
1749-
~offset=8,
1750-
wasm_mod,
1751-
get_swap(),
1752-
Expression.Binary.make(
1753-
wasm_mod,
1754-
Op.add_int32,
1755-
Expression.Global_get.make(
1756-
wasm_mod,
1757-
get_wasm_imported_name(grain_env_mod, reloc_base),
1758-
Type.int32,
1759-
),
1760-
Expression.Const.make(wasm_mod, wrap_int32(func_idx)),
1761-
),
1762-
),
1800+
store(~offset=8, wasm_mod, get_swap(), func_idx),
17631801
store(
17641802
~offset=12,
17651803
wasm_mod,
@@ -2939,6 +2977,8 @@ and compile_instr = (wasm_mod, env, instr) =>
29392977
| MAdtOp(adt_op, adt) => compile_adt_op(wasm_mod, env, adt, adt_op)
29402978
| MRecordOp(record_op, record) =>
29412979
compile_record_op(wasm_mod, env, record, record_op)
2980+
| MClosureOp(closure_op, closure) =>
2981+
compile_closure_op(wasm_mod, env, closure, closure_op)
29422982
| MPrim0(p0) => compile_prim0(wasm_mod, env, p0)
29432983
| MPrim1(p1, arg) => compile_prim1(wasm_mod, env, p1, arg, instr.instr_loc)
29442984
| MPrim2(p2, arg1, arg2) => compile_prim2(wasm_mod, env, p2, arg1, arg2)
@@ -3245,7 +3285,7 @@ let compile_function =
32453285
~preamble=?,
32463286
wasm_mod,
32473287
env,
3248-
{index, id, args, return_type, stack_size, body: body_instrs, func_loc},
3288+
{id, args, return_type, stack_size, body: body_instrs, func_loc},
32493289
) => {
32503290
sources := [];
32513291
let arity = List.length(args);
@@ -3312,8 +3352,8 @@ let compile_function =
33123352
func_ref;
33133353
};
33143354

3315-
let compute_table_size = (env, {functions}) => {
3316-
List.length(functions);
3355+
let compute_table_size = (env, {function_table_elements}) => {
3356+
List.length(function_table_elements);
33173357
};
33183358

33193359
let compile_imports = (wasm_mod, env, {imports}) => {
@@ -3448,14 +3488,12 @@ let compile_exports = (wasm_mod, env, {imports, exports, globals}) => {
34483488
);
34493489
};
34503490

3451-
let compile_tables = (wasm_mod, env, {functions}) => {
3452-
let function_names =
3453-
List.map(({id}) => Ident.unique_name(id), functions);
3491+
let compile_tables = (wasm_mod, env, {function_table_elements}) => {
34543492
Table.add_active_element_segment(
34553493
wasm_mod,
34563494
global_function_table,
34573495
"elem",
3458-
function_names,
3496+
function_table_elements,
34593497
Expression.Global_get.make(
34603498
wasm_mod,
34613499
get_wasm_imported_name(grain_env_mod, reloc_base),
@@ -3555,7 +3593,6 @@ let compile_main = (wasm_mod, env, prog) => {
35553593
wasm_mod,
35563594
env,
35573595
{
3558-
index: Int32.of_int(-99),
35593596
id: Ident.create(grain_main),
35603597
name: Some(grain_main),
35613598
args: [],
@@ -3687,11 +3724,11 @@ let compile_wasm_module = (~env=?, ~name=?, prog) => {
36873724
Memory.set_memory(wasm_mod, 0, Memory.unlimited, "memory", [], false);
36883725

36893726
let compile_all = () => {
3727+
ignore @@ compile_globals(wasm_mod, env, prog);
36903728
ignore @@ compile_functions(wasm_mod, env, prog);
3691-
ignore @@ compile_tables(wasm_mod, env, prog);
3692-
ignore @@ compile_imports(wasm_mod, env, prog);
36933729
ignore @@ compile_exports(wasm_mod, env, prog);
3694-
ignore @@ compile_globals(wasm_mod, env, prog);
3730+
ignore @@ compile_imports(wasm_mod, env, prog);
3731+
ignore @@ compile_tables(wasm_mod, env, prog);
36953732
};
36963733

36973734
if (Env.is_runtime_mode()) {

compiler/src/codegen/mashtree.re

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ type immediate =
301301

302302
[@deriving sexp]
303303
type closure_data = {
304-
func_idx: int32,
304+
func_idx: option(int32),
305305
arity: int32,
306306
variables: list(immediate),
307307
};
@@ -367,6 +367,10 @@ type record_op =
367367
| MRecordGet(int32)
368368
| MRecordSet(int32, immediate);
369369

370+
[@deriving sexp]
371+
type closure_op =
372+
| MClosureSetPtr(int32);
373+
370374
[@deriving sexp]
371375
type instr = {
372376
instr_desc,
@@ -420,6 +424,7 @@ and instr_desc =
420424
| MArrayOp(array_op, immediate)
421425
| MAdtOp(adt_op, immediate)
422426
| MRecordOp(record_op, immediate)
427+
| MClosureOp(closure_op, immediate)
423428
| MStore(list((binding, instr))) /* Items in the same list have their backpatching delayed until the end of that list */
424429
| MSet(binding, instr)
425430
| MDrop(instr, Types.allocation_type) /* Ignore the result of an expression. Used for sequences. */
@@ -468,7 +473,6 @@ type export =
468473

469474
[@deriving sexp]
470475
type mash_function = {
471-
index: int32,
472476
id: Ident.t,
473477
name: option(string),
474478
args: list(Types.allocation_type),
@@ -494,6 +498,7 @@ type mash_program = {
494498
main_body: block,
495499
main_body_stack_size: stack_size,
496500
globals: list((int32, Types.allocation_type)),
501+
function_table_elements: list(string),
497502
signature: Cmi_format.cmi_infos,
498503
type_metadata: list(Types.type_metadata),
499504
};

0 commit comments

Comments
 (0)