Commit Graph

247 Commits

Author SHA1 Message Date
Takeshi Yoneda
b63d4e6dcd Deletes namespace API (#1018)
Formerly, we introduced `wazero.Namespace` to help avoid module name or import conflicts while still sharing the runtime's compilation cache. Now that we've introduced `CompilationCache` `wazero.Namespace` is no longer necessary. By removing it, we reduce the conceptual load on end users as well internal complexity. Since most users don't use namespace, the change isn't very impactful.

Users who are only trying to avoid module name conflict can generate a name like below instead of using multiple runtimes:

```go
moduleName := fmt.Sprintf("%d", atomic.AddUint64(&m.instanceCounter, 1))
module, err := runtime.InstantiateModule(ctx, compiled, config.WithName(moduleName))
```

For `HostModuleBuilder` users, we no longer take `Namespace` as the last parameter of `Instantiate` method: 

```diff
 	// log to the console.
 	_, err := r.NewHostModuleBuilder("env").
 		NewFunctionBuilder().WithFunc(logString).Export("log").
-		Instantiate(ctx, r)
+		Instantiate(ctx)
 	if err != nil {
 		log.Panicln(err)
 	}
```


The following is an example diff a use of namespace can use to keep compilation cache while also ensuring their modules don't conflict:

```diff

 func useMultipleRuntimes(ctx context.Context, cache) {
-	r := wazero.NewRuntime(ctx)
+	cache := wazero.NewCompilationCache()
 
 	for i := 0; i < N; i++ {
-		// Create a new namespace to instantiate modules into.
-		ns := r.NewNamespace(ctx) // Note: this is closed when the Runtime is
+		r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfig().WithCompilationCache(cache))
 
 		// Instantiate a new "env" module which exports a stateful function.
 		_, err := r.NewHostModuleBuilder("env").
```

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-10 14:11:46 +09:00
Takeshi Yoneda
35500f9b85 Introduces Cache API (#1016)
This introduces the new API wazero.Cache interface which can be passed to wazero.RuntimeConfig. 
Users can configure this to share the underlying compilation cache across multiple wazero.Runtime. 
And along the way, this deletes the experimental file cache API as it's replaced by this new API.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
2023-01-10 09:32:42 +09:00
Takeshi Yoneda
e90e1985f3 Moves more func inst fields to comptime objects (#927)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-09 12:25:02 +09:00
Crypt Keeper
83e4b66659 Consolidates internal code to syscallfs (#1003)
This consolidates internal code to syscallfs, which removes the fs.FS
specific path rules, except when adapting one to syscallfs. For example,
this allows the underlying filesystem to decide if relative paths are
supported or not, as well any EINVAL related concerns.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-04 13:53:53 +08:00
Crypt Keeper
da3aa7a5ad Adds ExportedFunctionDefinitions and ExportedMemoryDefinitions (#986)
This adds ExportedFunctionDefinitions and ExportedMemoryDefinitions to
api.Module so that those who can't access CompileModule can see them.

Fixes #839

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-31 13:11:37 +08:00
Crypt Keeper
64a4ab3ba5 wasi: unexports errno and re-uses constants for logging (#971)
We originally exported WASI errno as we originally supported invoking
host functions directly (e.g. without a guest). This was an invalid call
pattern, and we removed that. However, we left the errnos exported even
though the caller of a guest won't ever see them. This prevented us from
re-using them cleanly in features such as logging.

This moves all constants including function names and flag enums
internal so that there is less duplication between logging and
implementation of wasi functions. This also helps in reference searches,
as we can analyze uses of a particular function name.

The only constant left exported is the module name, as there's a use
case for that (overriding implementations via FunctionBuilder).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-29 09:42:10 +08:00
Crypt Keeper
15dc3d7d37 Adds experimental write support and implements on gojs (#970)
This adds writefs.FS, allowing functions to create and delete files.
This begins by implementing them on `GOARCH=js GOOS=wasm`. The current
status is a lot farther than before, even if completing write on WASI is
left for a later PR (possibly by another volunteer).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-28 19:49:46 +08:00
Crypt Keeper
921df7e7a6 cli: adds -hostlogging=filesystem for diagnosing problems (#966)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-28 11:38:24 +08:00
Crypt Keeper
9dfe87531e logging: extracts utilities to read parameters and results from memory (#938)
This changes the listener signature to accept context and calling
module, so that all possible parameters and results can be logged. This
also changes the logging listener to make parameters visible when
logging results.

This infrastructure supports some helpful use cases, such as logging
WASI result parameters, such as the prestat path, which is only knowable
after the function has been called. The context parameter supposed
reading results of gojs functions, which are stored host-side in a go
context object.

Future pull requests will complete this as well backfill unit tests.
This is raised independently mainly to keep the PR size down of the
upcoming filesystem logger.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-27 16:08:25 +08:00
Takeshi Yoneda
7666a2a7f7 Disable comp cache for host modules (#949)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-21 14:08:30 +09:00
Takeshi Yoneda
d63c747d53 asm,compiler: reduce allocations during compilation (#936)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-20 12:49:47 +09:00
Crypt Keeper
b1cb9140dd Improves instantiation performance by removing ProxyFunc (#942)
This removes ProxyFunc, which was an internal experiment to make
functions that use memory to store parameters or results easier to see.
The main issue with the approach was instantiation performance, as it
needs to dynamically generate functions. Another approach to visibility
can happen later, for example via internal logging hooks.

Notably, this fixed the performance regression after switching WASI to ProxyFunc:
```
name                       old time/op    new time/op    delta
Allocation/Compile-16        39.8ms ± 0%    39.5ms ± 0%   -0.62%  (p=0.016 n=4+5)
Allocation/Instantiate-16    1.74ms ± 4%    0.86ms ± 1%  -50.19%  (p=0.008 n=5+5)
Allocation/Call-16           4.25µs ± 1%    4.21µs ± 2%     ~     (p=0.151 n=5+5)

name                       old alloc/op   new alloc/op   delta
Allocation/Compile-16        20.3MB ± 0%    20.3MB ± 0%     ~     (p=0.841 n=5+5)
Allocation/Instantiate-16    1.04MB ± 0%    0.56MB ± 0%  -45.88%  (p=0.008 n=5+5)
Allocation/Call-16            48.0B ± 0%     48.0B ± 0%     ~     (all equal)

name                       old allocs/op  new allocs/op  delta
Allocation/Compile-16          432k ± 0%      432k ± 0%     ~     (p=0.833 n=5+5)
Allocation/Instantiate-16     16.6k ± 0%      6.7k ± 0%  -59.34%  (p=0.008 n=5+5)
Allocation/Call-16             5.00 ± 0%      5.00 ± 0%     ~     (all equal)
```

Since we also removed it from `GOARCH=wasm GOOS=js`, we experienced a performance
benefit there as well:
```
name               old time/op    new time/op    delta
_main/gojs.Run-16    13.7ms ± 1%    12.2ms ± 3%  -10.76%  (p=0.008 n=5+5)

name               old alloc/op   new alloc/op   delta
_main/gojs.Run-16    25.4MB ± 0%    25.0MB ± 0%   -1.66%  (p=0.008 n=5+5)

name               old allocs/op  new allocs/op  delta
_main/gojs.Run-16      166k ± 0%      158k ± 0%   -4.79%  (p=0.016 n=4+5)

```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-19 18:18:19 +09:00
Takeshi Yoneda
229b4de678 Deletes encode caches (#934)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-16 12:01:13 +09:00
Takeshi Yoneda
1f2ed3c6a2 Fixes unnecessary allocation in decodeValueTypes (#933)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-16 11:31:36 +09:00
Clifton Kaznocha
5886f4e82e Cache FunctionType key in the binary pkg (#932)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-12-16 11:07:11 +09:00
Clifton Kaznocha
e44bdd040a Fix racy first instantiation (#930)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-12-16 08:53:31 +09:00
Takeshi Yoneda
c51a63058e Removes importedFn (#926)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-15 15:00:22 +09:00
Takeshi Yoneda
fafcb1cfee Removes unused FunctionInstance.LocalTypes (#925)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-15 14:40:09 +09:00
Crypt Keeper
126bd9050d Removes context parameter from instruction-scoped operations (#923)
We originally had a `context.Context` for anything that might be
traced, but it turned out to be only useful for lifecycle and host functions.

For instruction-scoped aspects like memory updates, a context parameter is too
fine-grained and also invisible in practice. For example, most users will use
the compiler engine, and its memory, global or table access will never use go's
context.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-14 16:08:07 +09:00
Crypt Keeper
0ed4002549 Removes experimental.WithFS (#922)
This removes the ability to override the current file system with Go
context, allowing us to simplify common paths and improve performance.

The context override was only used once in GitHub, in Trivy, and we
found another way to do that without it.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-14 15:00:17 +09:00
Clifton Kaznocha
3ec5928a83 Simplify namespace (#906)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-09 09:50:48 +09:00
Takeshi Yoneda
fccbc7b2aa dwarf: fixes for unordered addresses of DWARF line entries (#905)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-09 09:12:33 +09:00
Clifton Kaznocha
3b76d699e3 Reduce lock contention during module close (#900)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
Co-authored-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-12-08 12:37:11 +09:00
Takeshi Yoneda
a129cd7fd5 Removes ModuleInstance.TypeIDsIndex to reduce allocations (#897)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-07 13:49:12 +09:00
Takeshi Yoneda
8294521ec2 Deletes unused ModuleInstance.Types (#896)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-07 12:45:19 +09:00
Takeshi Yoneda
4a60a8f4eb ModuleInstance.Functions/Exports as non-pointer slice (#894)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-07 12:45:06 +09:00
Anuraag Agrawal
5de9c3b4bc Store function objects in contiguous memory in heap (#892)
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
2022-12-06 17:07:16 +09:00
Takeshi Yoneda
b8adb361e8 Fixes FuncRef global initialization with imported globals (#888)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-06 14:32:12 +09:00
Crypt Keeper
af8105ba0e Adds ResultNames to HostFunctionBuilder and FunctionDefinition (#887)
This adds ResultNames to HostFunctionBuilder and FunctionDefinition
which helps for multi-results or special-cased ones.

End users can access result names in `FunctionDefinition.ResultNames` or
set for their own host functions via
`HostFunctionBuilder.WithResultNames`. This change adds them for all
built-in functions where result names help.

Most notably, GOOS=js uses `ProxyFunc` to allow logging when a function
returns multiple results. Before, the results were returned without
names: e.g. `11231,1` and now they are named like `n=11231,ok=1`.

We soon plan to allow more visibility in WASI, for example, logging
results that will write to memory offsets. This infrastructure makes it
possible to do that.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-06 14:30:55 +09:00
Takeshi Yoneda
6c4dd1cfd9 Adds support for DWARF based stack traces (#881)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-05 14:59:45 +09:00
Takeshi Yoneda
0e9af73038 validation: not panic with redundant Else instrs (#883)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-05 09:04:42 +09:00
Takeshi Yoneda
e9de52c5d6 fuzz: adds validation target for maybe invalid module compilation (#879)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-02 10:56:13 +09:00
Takeshi Yoneda
40e698e068 binary: adds custom section decoder (#877)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-01 20:08:40 +09:00
Takeshi Yoneda
610af79719 Fixes applyTableInits for many extern null inits (#874)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-30 15:32:06 +09:00
Takeshi Yoneda
721327decc Consolidates table init logics (#873)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-30 14:28:37 +09:00
Takeshi Yoneda
8339045657 Ensures listeners only bound to compile time objects (#870)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-29 17:25:59 +09:00
Takeshi Yoneda
84d733eb0a compiler: adds support for FunctionListeners (#869)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-29 15:15:49 +09:00
Takeshi Yoneda
61a7001897 Update spectest v2 to latest (#863)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-28 16:12:10 +09:00
Takeshi Yoneda
19aab2d998 Upgrade wabt to 1.0.31 (#861)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-28 11:03:29 +09:00
Crypt Keeper
0e851b71a8 Optimizes GoModuleFunction signature and ensures function result slices are unique (#860)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-11-28 10:00:07 +08:00
Crypt Keeper
3cd9cbcfb5 Adds emscripten invoke_xxx functions needed for PDFium (#856)
This adds host functions that work on dynamic function tables. These are
only used by emscripten, but require some infrastructure to support it.
I added the least possible to due the task. This also only handles i32
and void returns with up to four parameters as that covers the needs of
PDFium. Future integrations may need more parameters or a mix of floats.
Such use cases should be addressed as they come as otherwise it is a lot
of work for the cartesian product of all combinations.

See 1b0d724fd5/test/passes/post-emscripten.wast
See https://github.com/jerbob92/go-pdfium-wasm

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-11-22 16:23:59 +07:00
Clifton Kaznocha
d507d8666f Optimize setting the ModuleInstance.DataInstances (#852)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-11-12 14:52:11 -08:00
Crypt Keeper
329ccca6b1 Switches from gofmt to gofumpt (#848)
This switches to gofumpt and applies changes, as I've noticed working
in dapr (who uses this) that it finds some things that are annoying,
such as inconsistent block formatting in test tables.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-11-09 05:48:24 +01:00
Clifton Kaznocha
483dfe17c3 Replace module name check linear scan with map lookup (#844)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-11-07 22:38:29 +01:00
Clifton Kaznocha
0f19bb21ff Optimizes slice initializations (#842)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
2022-11-07 08:25:37 +09:00
Clifton Kaznocha
45fc45c499 Reduces lock contention in store on type IDs (#843)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-11-06 10:26:49 +09:00
Clifton Kaznocha
f391a1d312 add ieee754 and leb128 byte slice funcs (#837)
Signed-off-by: Clifton Kaznocha <ckaznocha@users.noreply.github.com>
2022-11-03 10:23:35 +08:00
Crypt Keeper
d108ce4c43 Restores ability to define host functions w/o context via reflection (#832)
This restores the ability to leave out the initial context parameter
when defining functions with reflection. This is important because some
projects are porting from a different library to wazero, and all the
alternatives are not contextualized.

For example, this project is porting envoy host functions, and the
original definitions (in mosn) don't have a context parameter. By being
lenient, they can migrate easier.

See 6b813482b6/pkg/proxywasm/wazero/imports_v1.go

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-10-28 12:44:12 -07:00
Crypt Keeper
be33572289 Adds HostFunctionBuilder to enable high performance host functions (#828)
This PR follows @hafeidejiangyou advice to not only enable end users to
avoid reflection when calling host functions, but also use that approach
ourselves internally. The performance results are staggering and will be
noticable in high performance applications.

Before
```
BenchmarkHostCall/Call
BenchmarkHostCall/Call-16            	 1000000	      1050 ns/op
Benchmark_EnvironGet/environGet
Benchmark_EnvironGet/environGet-16         	  525492	      2224 ns/op
```

Now
```
BenchmarkHostCall/Call
BenchmarkHostCall/Call-16            	14807203	        83.22 ns/op
Benchmark_EnvironGet/environGet
Benchmark_EnvironGet/environGet-16         	  951690	      1054 ns/op
```

To accomplish this, this PR consolidates code around host function
definition and enables a fast path for functions where the user takes
responsibility for defining its WebAssembly mappings. Existing users
will need to change their code a bit, as signatures have changed.

For example, we are now more strict that all host functions require a
context parameter zero. Also, we've replaced
`HostModuleBuilder.ExportFunction` and `ExportFunctions` with a new type
`HostFunctionBuilder` that consolidates the responsibility and the
documentation.

```diff
 ctx := context.Background()
-hello := func() {
+hello := func(context.Context) {
         fmt.Fprintln(stdout, "hello!")
 }
-_, err := r.NewHostModuleBuilder("env").ExportFunction("hello", hello).Instantiate(ctx, r)
+_, err := r.NewHostModuleBuilder("env").
+        NewFunctionBuilder().WithFunc(hello).Export("hello").
+        Instantiate(ctx, r)
```

Power users can now use `HostFunctionBuilder` to define functions that
won't use reflection. There are two choices of interfaces to use
depending on if that function needs access to the calling module or not:
`api.GoFunction` and `api.GoModuleFunction`. Here's an example defining
one.

```go
builder.WithGoFunction(api.GoFunc(func(ctx context.Context, params []uint64) []uint64 {
	x, y := uint32(params[0]), uint32(params[1])
	sum := x + y
	return []uint64{sum}
}, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32})
```
As you'll notice and as documented, this approach is more verbose and
not for everyone. If you aren't making a low-level library, you are
likely able to afford the 1us penalty for the convenience of reflection.
However, we are happy to enable this option for foundational libraries
and those with high performance requirements (like ourselves)!

Fixes #825

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-10-28 07:51:08 -07:00
Crypt Keeper
1cbb496c26 Stops using "ex." to abbreviate "for example" (#827)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-10-24 11:51:48 +09:00