Skip to content

Commit 12eedcb

Browse files
committed
More precise environment type
Casting to the exact type should be slightly faster since we avoid the test for i31.
1 parent dcec0ac commit 12eedcb

File tree

8 files changed

+150
-80
lines changed

8 files changed

+150
-80
lines changed

compiler/lib-wasm/code_generation.ml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,31 @@ let tee ?typ x e =
503503

504504
let should_make_global x st = Var.Set.mem x st.context.globalized_variables, st
505505

506+
let get_constant x st = Var.Hashtbl.find_opt st.context.constants x, st
507+
508+
let placeholder_value typ f =
509+
let* c = get_constant typ in
510+
match c with
511+
| None ->
512+
let x = Var.fresh () in
513+
let* () = register_constant typ (W.GlobalGet x) in
514+
let* () =
515+
register_global
516+
~constant:true
517+
x
518+
{ mut = false; typ = Ref { nullable = false; typ = Type typ } }
519+
(f typ)
520+
in
521+
return (W.GlobalGet x)
522+
| Some c -> return c
523+
524+
let empty_struct =
525+
let* typ =
526+
register_type "empty_struct" (fun () ->
527+
return { supertype = None; final = true; typ = W.Struct [] })
528+
in
529+
placeholder_value typ (fun typ -> W.StructNew (typ, []))
530+
506531
let value_type st = st.context.value_type, st
507532

508533
let get_constant x st = Var.Hashtbl.find_opt st.context.constants x, st

compiler/lib-wasm/code_generation.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,5 @@ val array_placeholder : Code.Var.t -> expression
205205
val default_value :
206206
Wasm_ast.value_type
207207
-> (Wasm_ast.expression * Wasm_ast.value_type * Wasm_ast.ref_type option) t
208+
209+
val empty_struct : expression

compiler/lib-wasm/curry.ml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,12 @@ module Make (Target : Target_sig.S) = struct
3535

3636
let call ?typ ~cps ~arity closure args =
3737
let funct = Var.fresh () in
38-
let* closure = tee ?typ funct closure in
38+
let closure = tee ?typ funct closure in
39+
let* closure =
40+
match typ with
41+
| None -> Memory.cast_closure ~cps ~arity closure
42+
| Some _ -> closure
43+
in
3944
let args = args @ [ closure ] in
4045
let* ty, funct =
4146
Memory.load_function_pointer
@@ -68,7 +73,7 @@ module Make (Target : Target_sig.S) = struct
6873
let body =
6974
let* () = no_event in
7075
let* () = bind_parameters args in
71-
let* _ = add_var f in
76+
let* _ = add_var ~typ:Type.closure f in
7277
let* args' = expression_list load args in
7378
let* _f = load f in
7479
let rec loop m args closure closure_typ =
@@ -126,7 +131,7 @@ module Make (Target : Target_sig.S) = struct
126131
let body =
127132
let* () = no_event in
128133
let* _ = add_var x in
129-
let* _ = add_var f in
134+
let* _ = add_var ~typ:Type.closure f in
130135
push (Closure.curry_allocate ~cps:false ~arity m ~f:name' ~closure:f ~arg:x)
131136
in
132137
let param_names = [ x; f ] in
@@ -154,7 +159,7 @@ module Make (Target : Target_sig.S) = struct
154159
let body =
155160
let* () = no_event in
156161
let* () = bind_parameters args in
157-
let* _ = add_var f in
162+
let* _ = add_var ~typ:Type.closure f in
158163
let* args' = expression_list load args in
159164
let* _f = load f in
160165
let rec loop m args closure closure_typ =
@@ -214,7 +219,7 @@ module Make (Target : Target_sig.S) = struct
214219
let* () = no_event in
215220
let* _ = add_var x in
216221
let* _ = add_var cont in
217-
let* _ = add_var f in
222+
let* _ = add_var ~typ:Type.closure f in
218223
let* e = Closure.curry_allocate ~cps:true ~arity m ~f:name' ~closure:f ~arg:x in
219224
let* c = call ~cps:false ~arity:1 (load cont) [ e ] in
220225
instr (W.Return (Some c))
@@ -333,7 +338,7 @@ module Make (Target : Target_sig.S) = struct
333338
let body =
334339
let* () = no_event in
335340
let* () = bind_parameters l in
336-
let* _ = add_var f in
341+
let* _ = add_var ~typ:Type.closure f in
337342
let* typ, closure = Memory.load_real_closure ~cps ~arity (load f) in
338343
let* l = expression_list load l in
339344
let* e =

compiler/lib-wasm/gc_target.ml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type expression = Wasm_ast.expression Code_generation.t
2525
module Type = struct
2626
let value = W.Ref { nullable = false; typ = Eq }
2727

28+
let closure = W.Ref { nullable = false; typ = Struct }
29+
2830
let block_type =
2931
register_type "block" (fun () ->
3032
return
@@ -203,7 +205,8 @@ module Type = struct
203205
let primitive_type n =
204206
{ W.params = List.init ~len:n ~f:(fun _ -> value); result = [ value ] }
205207

206-
let func_type n = primitive_type (n + 1)
208+
let func_type n =
209+
{ W.params = List.init ~len:n ~f:(fun _ -> value) @ [ closure ]; result = [ value ] }
207210

208211
let function_type ~cps n =
209212
let n = if cps then n + 1 else n in
@@ -327,7 +330,7 @@ module Type = struct
327330
(List.init
328331
~f:(fun i ->
329332
{ W.mut = i < function_count
330-
; typ = W.Value (Ref { nullable = false; typ = Eq })
333+
; typ = W.Value (Ref { nullable = false; typ = Struct })
331334
})
332335
~len:function_count
333336
@ make_env_type env_type)
@@ -441,6 +444,8 @@ module Value = struct
441444
let* t = Type.block_type in
442445
array_placeholder t
443446

447+
let dummy_closure = empty_struct
448+
444449
let as_block e =
445450
let* t = Type.block_type in
446451
let* e = e in
@@ -825,6 +830,15 @@ module Memory = struct
825830
| 0 | 1 -> 1
826831
| _ -> 2
827832

833+
let cast_closure ~cps ~arity closure =
834+
let arity = if cps then arity - 1 else arity in
835+
let* ty = Type.closure_type ~usage:`Access ~cps arity in
836+
wasm_cast ty closure
837+
838+
let cast_generic_closure closure =
839+
let* e = closure in
840+
return (W.RefCast ({ nullable = false; typ = Struct }, e))
841+
828842
let load_function_pointer ~cps ~arity ?(skip_cast = false) closure =
829843
let arity = if cps then arity - 1 else arity in
830844
let* ty = Type.closure_type ~usage:`Access ~cps arity in
@@ -1096,7 +1110,7 @@ module Closure = struct
10961110
if List.is_empty free_variables
10971111
then
10981112
if no_code_pointer
1099-
then Value.unit
1113+
then Value.dummy_closure
11001114
else
11011115
let* typ = Type.closure_type ~usage:`Alloc ~cps arity in
11021116
let name = Code.Var.fork f in
@@ -1151,12 +1165,11 @@ module Closure = struct
11511165
tee
11521166
~typ:(W.Ref { nullable = false; typ = Type env_typ })
11531167
env
1154-
(return
1168+
(let* dummy_closure = Value.dummy_closure in
1169+
return
11551170
(W.StructNew
11561171
( env_typ
1157-
, List.init ~len:function_count ~f:(fun _ ->
1158-
W.RefI31 (W.Const (I32 0l)))
1159-
@ l )))
1172+
, List.init ~len:function_count ~f:(fun _ -> dummy_closure) @ l )))
11601173
else
11611174
let* env = get_closure_env g in
11621175
let* () = set_closure_env f env in
@@ -1208,7 +1221,7 @@ module Closure = struct
12081221
if List.is_empty free_variables
12091222
then
12101223
(* The closures are all constants and the environment is empty. *)
1211-
let* _ = add_var (Code.Var.fresh ()) in
1224+
let* _ = add_var ~typ:Type.closure (Code.Var.fresh ()) in
12121225
return ()
12131226
else
12141227
let env_type_id = Option.value ~default:(-1) info.id in
@@ -1220,7 +1233,7 @@ module Closure = struct
12201233
let* typ =
12211234
Type.env_type ~cps ~arity ~no_code_pointer ~env_type_id ~env_type:[]
12221235
in
1223-
let* _ = add_var f in
1236+
let* _ = add_var ~typ:Type.closure f in
12241237
let env = Code.Var.fresh_n "env" in
12251238
let* () =
12261239
store
@@ -1247,7 +1260,7 @@ module Closure = struct
12471260
~env_type_id
12481261
~env_type:[]
12491262
in
1250-
let* _ = add_var f in
1263+
let* _ = add_var ~typ:Type.closure f in
12511264
let env = Code.Var.fresh_n "env" in
12521265
let* env_typ = Type.rec_env_type ~function_count ~env_type_id ~env_type:[] in
12531266
let* () =

compiler/lib-wasm/generate.ml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -800,17 +800,23 @@ module Generate (Target : Target_sig.S) = struct
800800
match closure with
801801
| GlobalGet global ->
802802
let* init = get_global global in
803-
if Option.is_some init then Value.unit else return closure
804-
| _ -> return closure
803+
if Option.is_some init then Value.dummy_closure else return closure
804+
| _ -> Memory.cast_generic_closure (return closure)
805805
in
806806
return (W.Call (g, args @ [ cl ]))
807807
| None -> (
808808
let funct = Var.fresh () in
809-
let* closure = tee funct (return closure) in
809+
let arity = List.length args in
810+
let* closure =
811+
Memory.cast_closure
812+
~cps:(Var.Set.mem x ctx.in_cps)
813+
~arity
814+
(tee funct (return closure))
815+
in
810816
let* ty, funct =
811817
Memory.load_function_pointer
812818
~cps:(Var.Set.mem x ctx.in_cps)
813-
~arity:(List.length args)
819+
~arity
814820
(load funct)
815821
in
816822
match funct with

compiler/lib-wasm/target_sig.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ module type S = sig
2727
-> [ `Expr of Wasm_ast.expression | `Var of Wasm_ast.var ] list
2828
-> expression
2929

30+
val cast_closure : cps:bool -> arity:int -> expression -> expression
31+
32+
val cast_generic_closure : expression -> expression
33+
3034
val load_function_pointer :
3135
cps:bool
3236
-> arity:int
@@ -100,6 +104,8 @@ module type S = sig
100104
module Type : sig
101105
val value : Wasm_ast.value_type
102106

107+
val closure : Wasm_ast.value_type
108+
103109
val func_type : int -> Wasm_ast.func_type
104110

105111
val primitive_type : int -> Wasm_ast.func_type
@@ -162,6 +168,8 @@ module type S = sig
162168

163169
val dummy_block : expression
164170

171+
val dummy_closure : expression
172+
165173
val as_block : expression -> expression
166174
end
167175

0 commit comments

Comments
 (0)