diff --git a/src/lib_scoru_wasm/fast/exec.ml b/src/lib_scoru_wasm/fast/exec.ml index 1d72df6e4e93bd0da79ec4ec979060a8bbe2c529..ddae356a21d2d6a4b5f09b788989fa8819b0057e 100644 --- a/src/lib_scoru_wasm/fast/exec.ml +++ b/src/lib_scoru_wasm/fast/exec.ml @@ -95,6 +95,8 @@ let compute ~version ~reveal_builtins ~write_debug durable buffers = Lwt.finalize kernel_run (fun () -> (* Make sure that the instance is deleted regardless of whether [kernel_run] succeeds or not. *) + main_mem := None ; + Wasmer.Exports.delete exports ; Wasmer.Instance.delete instance ; Lwt.return_unit) in diff --git a/src/lib_wasmer/api_funcs_desc.ml b/src/lib_wasmer/api_funcs_desc.ml index e811a04d910d1d7b1786310a1449d10593ea67bb..8742e2536374b5652f3971e08e4c6600c45a7632 100644 --- a/src/lib_wasmer/api_funcs_desc.ml +++ b/src/lib_wasmer/api_funcs_desc.ml @@ -256,6 +256,9 @@ module Functions (S : FOREIGN) = struct foreign "wasm_extern_as_memory" (ptr Types.Extern.t @-> returning (ptr Types.Memory.t)) + + let delete = + foreign "wasm_extern_delete" (ptr Types.Extern.t @-> returning void) end (** Functions with the [wasm_extern_vec_] prefix *) @@ -278,6 +281,9 @@ module Functions (S : FOREIGN) = struct foreign "wasm_functype_results" (ptr Types.Functype.t @-> returning (ptr Types.Valtype.Vec.t)) + + let delete = + foreign "wasm_functype_delete" (ptr Types.Functype.t @-> returning void) end (** Functions with the [wasm_func_] prefix *) @@ -416,6 +422,11 @@ module Functions (S : FOREIGN) = struct foreign "wasm_exporttype_type" (ptr Types.Exporttype.t @-> returning (ptr Types.Externtype.t)) + + let delete = + foreign + "wasm_exporttype_delete" + (ptr Types.Exporttype.t @-> returning void) end (** Functions with the [wasm_exporttype_vec_] prefix *) diff --git a/src/lib_wasmer/exports.ml b/src/lib_wasmer/exports.ml index 56a15b3fc320ed577f412476efa93f7f4fbc9e38..e3945fbeaf9eee730badf60ef4de712f73c901ca 100644 --- a/src/lib_wasmer/exports.ml +++ b/src/lib_wasmer/exports.ml @@ -44,20 +44,27 @@ type t = Types.Extern.t Ctypes.ptr Resolver.t let from_instance inst = - let exports = - Module.exports inst.Instance.module_ |> Export_type_vector.to_list + let exports_vec = Module.exports inst.Instance.module_ in + let exports = Export_type_vector.to_list exports_vec in + let externs_vec = Extern_vector.empty () in + Functions.Instance.exports inst.instance (Ctypes.addr externs_vec) ; + let externs = Extern_vector.to_list externs_vec in + let resolved = + List.fold_right2 + (fun export extern tail -> + let name = Export_type.name export in + let kind = Export_type.type_ export |> Functions.Externtype.kind in + Resolver.add (name, kind) extern tail) + exports + externs + Resolver.empty in - let externs = Extern_vector.empty () in - Functions.Instance.exports inst.instance (Ctypes.addr externs) ; - let externs = Extern_vector.to_list externs in - List.fold_right2 - (fun export extern tail -> - let name = Export_type.name export in - let kind = Export_type.type_ export |> Functions.Externtype.kind in - Resolver.add (name, kind) extern tail) - exports - externs - Resolver.empty + (* The exports vector is consumed in read-only or copying fashion, therefore + there are no references to it at this point. We can clean it up. *) + Functions.Exporttype_vec.delete (Ctypes.addr exports_vec) ; + resolved + +let delete = Resolver.iter (fun _ extern -> Functions.Extern.delete extern) exception Export_not_found of {name : string; kind : Unsigned.uint8} @@ -104,6 +111,8 @@ let mem_of_extern extern = (Functions.Memory.data mem) (Functions.Memory.data_size mem |> Unsigned.Size_t.to_int) in + (* The memory type is no longer used after this, so we must delete it. *) + Functions.Memory_type.delete mem_type ; Memory.{raw; min; max} let mem exports name = diff --git a/src/lib_wasmer/function.ml b/src/lib_wasmer/function.ml index 693aeb14320c60971230d2fc43f7838a310003cb..a9b07ca51262b145785d20457dbe5ecb8edbb9d9 100644 --- a/src/lib_wasmer/function.ml +++ b/src/lib_wasmer/function.ml @@ -96,7 +96,11 @@ let create : type f. Store.t -> f Function_type.t -> f -> owned * (unit -> unit) let try_run = Ctypes.coerce Func_callback_maker.t Types.Func_callback.t try_run in - (Functions.Func.new_ store func_type try_run, free) + let owned = Functions.Func.new_ store func_type try_run in + (* [wasm_func_new] doesn't consume [func_type], therefore we must manually + garbage collect it. *) + Functions.Functype.delete func_type ; + (owned, free) let call_raw func inputs = let open Lwt.Syntax in @@ -160,6 +164,9 @@ let unpack_outputs results outputs = go results 0 Fun.id let call func typ = - Function_type.check_types typ (Functions.Func.type_ func) ; + let func_type = Functions.Func.type_ func in + Function_type.check_types typ func_type ; + (* Once the types have been checked, [func_type] can be deleted. *) + Functions.Functype.delete func_type ; let (Function_type.Function (params, results)) = typ in pack_inputs params func (unpack_outputs results) diff --git a/src/lib_wasmer/function_type.ml b/src/lib_wasmer/function_type.ml index bd19742b922496eafb0f22872a94affc69fca680..88f3c828dcb5d5013766f8521062f221073c1410 100644 --- a/src/lib_wasmer/function_type.ml +++ b/src/lib_wasmer/function_type.ml @@ -97,10 +97,14 @@ type 'f t = Function : ('f, 'r Lwt.t) params * 'r results -> 'f t let to_owned (Function (params, results)) = let inputs = param_types params in let outputs = result_types results in - (* Note, this consumes the elements in [inputs] and [outputs] but not the - structures themselves. Ctypes will free the structures once they go out - of scope. *) - Functions.Functype.new_ (Ctypes.addr inputs) (Ctypes.addr outputs) + let type_ = + Functions.Functype.new_ (Ctypes.addr inputs) (Ctypes.addr outputs) + in + (* Since creating a new function type does not consume the input and output + type vectors, we can safely delete them here. *) + Functions.Valtype_vec.delete (Ctypes.addr inputs) ; + Functions.Valtype_vec.delete (Ctypes.addr outputs) ; + type_ exception Wrong_number_of_params of {expected : Unsigned.size_t; got : Unsigned.size_t} diff --git a/src/lib_wasmer/instance.ml b/src/lib_wasmer/instance.ml index 9e22812b2f7d81001bd71d6c174e57e2fc7e8fe0..1abbec20a24252c12e14c01a3991ae0da075f67b 100644 --- a/src/lib_wasmer/instance.ml +++ b/src/lib_wasmer/instance.ml @@ -67,9 +67,8 @@ let resolve_imports store modul resolver = | None -> raise (Unsatisfied_import {module_; name; kind}) | Some m -> Extern.to_extern store m in - let imports = - Module.imports modul |> Import_type_vector.to_array |> Array.map lookup - in + let imports_vec = Module.imports modul in + let imports = Import_type_vector.to_array imports_vec |> Array.map lookup in let externs = Extern_vector.from_array (Array.map fst imports) in let clean = Array.fold_left @@ -81,6 +80,9 @@ let resolve_imports store modul resolver = Fun.id imports in + (* There are no references to the imports vector after this, so we can + delete it. *) + Functions.Importtype_vec.delete (Ctypes.addr imports_vec) ; (externs, clean) let create store module_ externs = diff --git a/src/lib_wasmer/tezos_wasmer.mli b/src/lib_wasmer/tezos_wasmer.mli index ca241475d7ec2c23c25c602602714ea328fa561d..53bef3e462adad5922f2aa8982536d49e8cd443f 100644 --- a/src/lib_wasmer/tezos_wasmer.mli +++ b/src/lib_wasmer/tezos_wasmer.mli @@ -187,6 +187,11 @@ module Exports : sig (** [from_intance instance] extracts the exports from the given instance. *) val from_instance : Instance.t -> t + (** [delete exports] cleans up the exports collection to free its associated + objects. You must not use previously extracted export objects after + calling call. *) + val delete : t -> unit + (** [fn exports name typ] looks for a function called [name] and type checks it against [typ]. *) val fn : t -> string -> 'a fn -> 'a