Commit Graph

152 Commits

Author SHA1 Message Date
Takeshi Yoneda
3ab7e4b36d Ensures user-defined primitive types are usable in host func signatures (#1005)
Ensure primitive types are usable in host func signatures

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-04 15:32:32 +08:00
Takeshi Yoneda
ef3937ffed Simplifies spectest initialization (#1000)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-01-03 13:22:14 +09: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
d3c5e8655f Adds benchmarks from lib sodium (#948)
This adds benchmarks from lib sodium, but the results are hard to interpret. We may need to recompile them using zig so that we can export a function instead of using WASI to do it. Right now, we can't really see performance of functions because other runtimes aren't designed to re-instantiate like ours.

This only compares against wasmtime as that's the only runtime besides
ours that is safe to re-instantiate.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-21 09:17:13 +08: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
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
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
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
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
Takeshi Yoneda
65b2431b37 fuzz: enable imports in differential fuzzing (#886)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-06 16:05: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
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
dca3bfa683 Delete obsolete integration test from wat parser (#884)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-05 12:04:20 +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
651f71b8ab Merge wazero-fuzz into internal/integration_test (#872)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-01 10:22:58 +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
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
Crypt Keeper
62f1a32aac Updates test dependencies (#834)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-11-01 15:02:30 +08:00
Crypt Keeper
958b25e3a6 Extends build compatability to one version behind Go's support policy (#833)
This enforces that wazero will build and operate one version behind Go's
support policy, making wazero's Go policy effectively three versions.

This is to allow libraries with more conservative Go policies to be able
to use wazero, specifically mosn is the first to need this.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-11-01 13:19:57 +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
Takeshi Yoneda
2fc5f6d0c5 Update spectest v2 to latest (#818)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-10-03 14:25:56 +09:00
Crypt Keeper
761347db1e Replaces MemorySizer and CompileConfig with RuntimeConfig (#815)
We formerly introduced `MemorySizer` as a way to control capacity independently of size. This was the first and only feature in `CompileConfig`. While possibly used privately, `MemorySizer` has never been used in public GitHub code.

These APIs interfere with how we do caching of compiled modules. Notably, they can change the min or max defined in wasm, which invalidates some constants. This has also had a bad experience, forcing everyone to boilerplate`wazero.NewCompileConfig()` despite that API never being used in open source.

This addresses the use cases in a different way, by moving configuration to `RuntimeConfig` instead. This allows us to remove `MemorySizer` and `CompileConfig`, and the problems with them, yet still retaining functionality in case someone uses it.

* `RuntimeConfig.WithMemoryLimitPages(uint32)`: Prevents memory from growing to 4GB (spec limit) per instance.
  * This works regardless of whether the wasm encodes max or not. If there is no max, it becomes effectively this value.
* `RuntimeConfig.WithMemoryCapacityFromMax(bool)`: Prevents reallocations (when growing).
  * Wasm that never sets max will grow from min to the limit above.

Note: Those who want to change their wasm (ex insert a max where there was none), have to do that externally, ex via compiler settings or post-build transformations such as [wabin](https://github.com/tetratelabs/wabin)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-29 08:03:03 +08:00
Crypt Keeper
1561c4ca7b Adds MustInstantiate to host imports (#814)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-28 16:21:30 +08:00
Crypt Keeper
429334cf98 Renames ModuleBuilder to HostModuleBuilder and drops memory and globals (#812)
We at one point considered making `ModuleBuilder` create complete
WebAssembly binaries. However, we recently spun out
[wabin](https://github.com/tetratelabs/wabin), which allows this.

Meanwhile, the features in `ModuleBuilder` were confusing and misused.
For example, the only two cases memory was exported on GitHub were done
by accident. This is because host functions act on the guest's memory,
not their own.

Hence, this removes memory and globals from host side definitions, and
renames the type to HostModuleBuilder to clarify this is not ever going
to be used to construct normal Wasm binaries.

Most importantly, this simplifies the API and reduces a lot of code. It
is important to make changes like this, particularly deleting any
experimental things that didn't end up useful.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Anuraag Agrawal <anuraaga@gmail.com>
2022-09-28 14:42:14 +08:00
Takeshi Yoneda
5c64720b24 Update spectest v2 to latest (#809)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-09-21 10:06:43 +09:00
Crypt Keeper
003d41dd5e Updates all 3rd party dependencies (#802)
wazero has no runtime deps. This updates tools we use as well as
dependencies used in comparison with other runtimes.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-07 11:02:26 +08:00
Crypt Keeper
b01effc8a9 Top-levels CoreFeatures and defaults to 2.0 (#800)
While compilers should be conservative when targeting WebAssembly Core
features, runtimes should be lenient as otherwise people need to
constantly turn on all features. Currently, most examples have to turn
on 2.0 features because compilers such as AssemblyScript and TinyGo use
them by default. This matches the policy with the reality, and should
make first time use easier.

This top-levels an internal type as `api.CoreFeatures` and defaults to
2.0 as opposed to 1.0, our previous default. This is less cluttered than
the excess of `WithXXX` methods we had prior to implementing all
planned WebAssembly Core Specification 1.0 features.

Finally, this backfills rationale as flat config types were a distinct
decision even if feature set selection muddied the topic.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-09-06 15:14:36 +08:00
Takeshi Yoneda
9ad8af121a compiler: simplify calling convention (#782)
This simplifies the calling convention and consolidates the call frame stack
and value stack into a single stack.

As a result, the cost of function calls decreases because we now don't need
to check the boundary twice (value and call frame stacks) at each function call.

The following is the result of the benchmark for recursive Fibonacci
function in integration_test/bench/testdata/case.go, and it shows that
this actually improves the performance of function calls.

[amd64]
name                               old time/op  new time/op  delta
Invocation/compiler/fib_for_5-32    109ns ± 3%    81ns ± 1%  -25.86%  (p=0.008 n=5+5)
Invocation/compiler/fib_for_10-32   556ns ± 3%   473ns ± 3%  -14.99%  (p=0.008 n=5+5)
Invocation/compiler/fib_for_20-32  61.4µs ± 2%  55.9µs ± 5%   -8.98%  (p=0.008 n=5+5)
Invocation/compiler/fib_for_30-32  7.41ms ± 3%  6.83ms ± 3%   -7.90%  (p=0.008 n=5+5)


[arm64]
name                               old time/op    new time/op    delta
Invocation/compiler/fib_for_5-10     67.7ns ± 1%    60.2ns ± 1%  -11.12%  (p=0.000 n=9+9)
Invocation/compiler/fib_for_10-10     487ns ± 1%     460ns ± 0%   -5.56%  (p=0.000 n=10+9)
Invocation/compiler/fib_for_20-10    58.0µs ± 1%    54.3µs ± 1%   -6.38%  (p=0.000 n=10+10)
Invocation/compiler/fib_for_30-10    7.12ms ± 1%    6.67ms ± 1%   -6.31%  (p=0.000 n=10+9)

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-09-06 13:29:56 +09:00
Takeshi Yoneda
f95b95eecc compiler: zero-initializes moduleInstanceAddress of call engine (#783)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-31 12:33:36 +09:00
Crypt Keeper
5bd521eb3c Moves host function imports into their own directory (#784)
Our root directory is getting crowded and it is also difficult to
organize the "host imports" concept due to this.

This moves common and language-specific imports into their own
directory. This will break go import signatures on the next release, but
is more sustainable overall.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-08-31 10:22:15 +08:00
Crypt Keeper
69863c430d Removes Text Format (#778)
We've canceled the WebAssembly Text Format feature and moved it to another repository https://github.com/tetratelabs/watzero for resumption or archival.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-08-30 10:01:45 +08:00
Takeshi Yoneda
9d3260f94f vs: adds in-Wasm loop inside the memory bench (#768)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-26 14:49:14 +09:00
Takeshi Yoneda
bebd22ca33 exp: create the compilation cache dir when not exist (#767)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-26 13:01:02 +09:00
Takeshi Yoneda
62520e4ea8 vs: adds the benchmark on i32/i64 load/store insts (#766)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-26 07:32:05 +09:00
Takeshi Yoneda
df93d70654 Rename vs/jit -> vs/compiler (#765)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-25 14:18:11 +09:00
Takeshi Yoneda
0bd2beedac Introduce CallEngine assigned to api.Function implementation. (#761)
This introduces wasm.CallEngine internal type, and assign it to the api.Function
implementations. api.Function.Call now uses that CallEngine assigned to it
to make function calls.

Internally, when creating CallEngine implementation, the compiler engine allocates
call frames and values stack. Previously, we allocate these stacks for each function calls,
which was a severe overhead as we can recognize in the benchmarks. As a result,
this reduces the memory usage (== reduces the GC jobs) as long as we reuse
the same api.Function multiple times.

As a side effect, now api.Function.Call is not goroutine-safe. So this adds the comment
about it on that method.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-24 16:11:15 +09:00
Takeshi Yoneda
1a46d471f8 bench: compare host call costs on Wasm-impl vs Go-impl (#758)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-23 11:56:42 +09:00
Takeshi Yoneda
50cef32ae0 vs: adds the benchmark to see the cost of host function calls (#756)
This adds the new vs target to measure the cost of host function calls.
Notably, I can see that wazero is roughly 2x to 4x times faster than CGO-based
runtimes in terms of host call boundary crossing. One implication here is that
we can just focus on the native code generation rather than how to organize the
Go function calls. For example, it's not prioritized to call Go functions directly
from the native code.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-22 16:53:58 +09:00