Skip to content

Commit c2a49a5

Browse files
authored
Merge pull request #84 from ocaml-wasm/bigstring-perfs
Bigstring performance optimizations
2 parents a4e7b05 + c3ba995 commit c2a49a5

File tree

11 files changed

+312
-366
lines changed

11 files changed

+312
-366
lines changed

compiler/lib/wasm/wa_generate.ml

Lines changed: 92 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,71 @@ module Generate (Target : Wa_target_sig.S) = struct
3838
; debug : Parse_bytecode.Debug.t
3939
}
4040

41+
type repr =
42+
| Value
43+
| Float
44+
| Int32
45+
| Nativeint
46+
| Int64
47+
48+
let repr_type r =
49+
match r with
50+
| Value -> Value.value
51+
| Float -> F64
52+
| Int32 -> I32
53+
| Nativeint -> I32
54+
| Int64 -> I64
55+
56+
let specialized_func_type (params, result) =
57+
{ W.params = List.map ~f:repr_type params; result = [ repr_type result ] }
58+
59+
let box_value r e =
60+
match r with
61+
| Value -> e
62+
| Float -> Memory.box_float e
63+
| Int32 -> Memory.box_int32 e
64+
| Nativeint -> Memory.box_nativeint e
65+
| Int64 -> Memory.box_int64 e
66+
67+
let unbox_value r e =
68+
match r with
69+
| Value -> e
70+
| Float -> Memory.unbox_float e
71+
| Int32 -> Memory.unbox_int32 e
72+
| Nativeint -> Memory.unbox_nativeint e
73+
| Int64 -> Memory.unbox_int64 e
74+
75+
let specialized_primitives =
76+
let h = Hashtbl.create 18 in
77+
List.iter
78+
~f:(fun (nm, typ) -> Hashtbl.add h nm typ)
79+
[ "caml_int32_bswap", ([ Int32 ], Int32)
80+
; "caml_nativeint_bswap", ([ Nativeint ], Nativeint)
81+
; "caml_int64_bswap", ([ Int64 ], Int64)
82+
; "caml_int32_compare", ([ Int32; Int32 ], Value)
83+
; "caml_nativeint_compare", ([ Nativeint; Nativeint ], Value)
84+
; "caml_int64_compare", ([ Int64; Int64 ], Value)
85+
; "caml_string_get32", ([ Value; Value ], Int32)
86+
; "caml_string_get64", ([ Value; Value ], Int64)
87+
; "caml_bytes_get32", ([ Value; Value ], Int32)
88+
; "caml_bytes_get64", ([ Value; Value ], Int64)
89+
; "caml_bytes_set32", ([ Value; Value; Int32 ], Value)
90+
; "caml_bytes_set64", ([ Value; Value; Int64 ], Value)
91+
; "caml_lxm_next", ([ Value ], Int64)
92+
; "caml_ba_uint8_get32", ([ Value; Value ], Int32)
93+
; "caml_ba_uint8_get64", ([ Value; Value ], Int64)
94+
; "caml_ba_uint8_set32", ([ Value; Value; Int32 ], Value)
95+
; "caml_ba_uint8_set64", ([ Value; Value; Int64 ], Value)
96+
; "caml_nextafter_float", ([ Float; Float ], Float)
97+
; "caml_classify_float", ([ Float ], Value)
98+
; "caml_ldexp_float", ([ Float; Value ], Float)
99+
; "caml_signbit_float", ([ Float ], Value)
100+
; "caml_erf_float", ([ Float ], Float)
101+
; "caml_erfc_float", ([ Float ], Float)
102+
; "caml_float_compare", ([ Float; Float ], Value)
103+
];
104+
h
105+
41106
let func_type n =
42107
{ W.params = List.init ~len:n ~f:(fun _ -> Value.value); result = [ Value.value ] }
43108

@@ -386,6 +451,10 @@ module Generate (Target : Wa_target_sig.S) = struct
386451
int32_shift_op (Shr U) i j
387452
| Extern "caml_int32_to_int", [ i ] -> Value.val_int (Memory.unbox_int32 i)
388453
| Extern "caml_int32_of_int", [ i ] -> Memory.box_int32 (Value.int_val i)
454+
| Extern "caml_nativeint_of_int32", [ i ] ->
455+
Memory.box_nativeint (Memory.unbox_int32 i)
456+
| Extern "caml_nativeint_to_int32", [ i ] ->
457+
Memory.box_int32 (Memory.unbox_nativeint i)
389458
| Extern "caml_int64_bits_of_float", [ f ] ->
390459
let* f = Memory.unbox_float f in
391460
Memory.box_int64 (return (W.UnOp (I64 ReinterpretF, f)))
@@ -565,18 +634,30 @@ module Generate (Target : Wa_target_sig.S) = struct
565634
~init:(return [])
566635
in
567636
Memory.allocate ~tag:0 l
568-
| Extern name, l ->
637+
| Extern name, l -> (
569638
let name = Primitive.resolve name in
570-
(*ZZZ Different calling convention when large number of parameters *)
571-
let* f = register_import ~name (Fun (func_type (List.length l))) in
572-
let rec loop acc l =
573-
match l with
574-
| [] -> return (W.Call (f, List.rev acc))
575-
| x :: r ->
576-
let* x = x in
577-
loop (x :: acc) r
578-
in
579-
loop [] l
639+
try
640+
let typ = Hashtbl.find specialized_primitives name in
641+
let* f = register_import ~name (Fun (specialized_func_type typ)) in
642+
let rec loop acc arg_typ l =
643+
match arg_typ, l with
644+
| [], [] -> box_value (snd typ) (return (W.Call (f, List.rev acc)))
645+
| repr :: rem, x :: r ->
646+
let* x = unbox_value repr x in
647+
loop (x :: acc) rem r
648+
| [], _ :: _ | _ :: _, [] -> assert false
649+
in
650+
loop [] (fst typ) l
651+
with Not_found ->
652+
let* f = register_import ~name (Fun (func_type (List.length l))) in
653+
let rec loop acc l =
654+
match l with
655+
| [] -> return (W.Call (f, List.rev acc))
656+
| x :: r ->
657+
let* x = x in
658+
loop (x :: acc) r
659+
in
660+
loop [] l)
580661
| Not, [ x ] -> Value.not x
581662
| Lt, [ x; y ] -> Value.lt x y
582663
| Le, [ x; y ] -> Value.le x y

0 commit comments

Comments
 (0)