Commit Graph

82 Commits

Author SHA1 Message Date
Takeshi Yoneda
cd1110c088 Avoids allocation of exports map per instance (#1275)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-23 16:37:56 +09:00
Takeshi Yoneda
cd05a22df2 Reduces allocations during instantiation (#1267)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-22 18:55:58 +09:00
Takeshi Yoneda
e17a85146a Holds wasm.Code as values on wasm.Module (#1243)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-15 14:45:54 +09:00
Takeshi Yoneda
350e81e632 Holds function types as values, not ptrs in wasm.Module (#1227)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-15 13:45:52 +09:00
Takeshi Yoneda
aba4ede088 Removes usage of host functions with Wasm optocdes (#1241)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-15 13:42:53 +09:00
Takeshi Yoneda
e42987a17a Holds memory/func defs, and validated elements as values in wasm.Module (#1224)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-13 14:52:01 +09:00
Takeshi Yoneda
7466f0e7bd Holds most fields as slice of values, not ptrs in wasm.Module (#1221)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-13 12:50:36 +09:00
Takeshi Yoneda
24e4d5dfa0 Generates typeIDs at compilation time (#1218)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-10 13:46:08 +09:00
Takeshi Yoneda
ad968dc3fe Pass correct api.Module to host functions (#1213)
Fixes #1211

Previously, host functions are getting api.Module for the "originating" module, 
which is the module for api.Function currently invoked, except that the api.Module 
is modified by withMemory with the caller's memory instance, therefore there 
haven't been no problem for most cases. The only issues were the methods 
besides Memory() of api.Module, and this commit fixes them.

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-03-08 15:05:48 +09:00
Edoardo Vacchi
117474c477 refactor binary encoding to its own package (#1187)
move binary encoder to its own package

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
2023-03-03 07:21:22 +08:00
Crypt Keeper
75aa6b2a6e examples: updates to the latest SDKs (#1169)
This updates our examples to the latest SDKs as particularly this can
help reveal issues around fan-out stats.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-27 09:05:48 +08:00
Crypt Keeper
4ca0858e57 sysfs: adds FS.Stat and companions in platform (#1140)
This centralizes filestat logic by making our own `Stat_t` similar to
`syscall.Stat_t`. This exposes utilities in the platform package and
adds a new function `FS.Stat` which avoids having to use `fs.File` to
get the same info. Doing so at the FS abstraction allows us to optimize
how it is implemented internally using portable means (e.g.
`os.StatFile`) or OS-specific means where necessary, e.g. in windows.

This also ensures `platform.OpenFile` returns syscall.Errno and
centralizes error checking with a new `require.EqualErrno` test.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-21 10:13:37 +08:00
Takeshi Yoneda
b68ee641cc ci: update TinyGo to 0.27 (#1120)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-13 17:38:53 +09:00
Takeshi Yoneda
92e0a488b6 Support context Cancelation/Timeout in function executions (#1108)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2023-02-10 09:39:04 +09:00
Crypt Keeper
f9db80624d zig: bumps to latest (#1080)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-30 16:30:52 +02:00
Edoardo Vacchi
599c097603 Add -hostlogging=crypto (#1064)
This allows you to specify multiple logging scopes, both in API and the CLI.

e.g for the CLI.
```bash
$ wazero run --hostlogging=crypto --hostlogging=filesystem --mount=.:/:ro cat.wasm
```

e.g. for Go
```go
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
	logging.NewHostLoggingListenerFactory(&log, logging.LogScopeCrypto|logging.LogScopeFilesystem))
```

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Adrian Cole <adrian@tetrate.io>
2023-01-28 12:51:44 +02:00
Crypt Keeper
105cdcdef7 cli: rewrites compositeFS to syscallfs and adds read-only (:ro) mounts (#1030)
This rewrites compositeFS to syscallfs.FS following wasi-sdk preopen
rules. Notably, this allows use of read-only mounts now.

For example,
```bash
$ GOOS=js GOARCH=wasm bin/go test -c -o template.wasm text/template
$ wazero run -mount=src/text/template:/ -mount=/tmp:/tmp template.wasm -test.v
=== RUN   TestExecute
--- PASS: TestExecute (0.07s)
--snip--
```

This is the first step to native WASI handling of multiple pre-opens.
After this change, it is still the case that there's only one pre-open
FD visible to wasm. A later change will make it possible for WASI to see
multiple pre-opens while `GOOS=js` which doesn't use preopens, remains
on a rootFS.

A future PR may need to add a CLI flag to disable escaping directories,
(e.g. make ../.. EINVAL), similar to `fs.FS` in Go. The simplest way to
allow this is to use a host-side RootFS even in WASI, and wrap that with
a `syscallfs` filename filter.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-01-13 15:50:11 +08:00
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
2045f71363 enginetest: fixes panic om memory def (#989)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-31 14:27:04 +09:00
Takeshi Yoneda
e7018d19ff compiler: force moduleContext initialization after Go function calls (#988)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-31 14:05:30 +09: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
Crypt Keeper
acf32dfa46 Hides internal logging (#956)
This makes it easier to do maintenance by hiding the implementation
details of using a proxy module to test host modules. What happens is we
skip logging of these proxy modules, which makes it easier to see what
log affects a change has.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-12-23 09:14:16 +08: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
Takeshi Yoneda
7bd1c1600f dwarf: fixes for non-exact matched lines (#916)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-13 13:37:40 +09:00
Takeshi Yoneda
45aa798a55 dwarf: include inlined function calls in stack traces (#912)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-12-12 11:20:14 +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
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
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
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
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
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
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
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
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
2706004b80 Removes testing/modgen fuzzing (#779)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-30 11:04:01 +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
076d3245e3 Pass context into NewRuntime (#748)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-18 14:47:49 +09:00
Takeshi Yoneda
ef19028513 Fixes function calls / memory access with wasm-implemented host functions (#737)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-08-07 09:50:34 +08:00
Takeshi Yoneda
b18b36c173 compiler: support for Wasm-implemented host functinos (#728)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-07-30 11:33:03 +09:00
Takeshi Yoneda
02c23d55db Disallow direct call of host functions (#723)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-07-30 09:33:20 +08:00
Takeshi Yoneda
ed068597cd ci: adds Go 1.19.0-rc.2 into matrix (#714)
This adds the 1.19.0-rc2. in the testing matrix.

This also formats the Godocs across the codebase, as
Go 1.19 has started auto-formatting Godoc. https://github.com/tetratelabs/wazero/issues/426

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-07-25 11:14:00 +09:00
Crypt Keeper
1689fc1bbf Allows wasm-defined host functions to use memory in interpreter (#713)
Before, we allowed stubbed host functions to be defined in wasm instead
of Go. This improves performance and reduces a chance of side-effects vs
Go. In fact, any pure function was supported in wasm, provided it only
called pure functions.

This changes internals so that a wasm-defined host function can use
memory. Notably, host functions use the caller's memory, so this is
simpler to initially support in the interpreter.

This is needed to simplify and reduce performance hit of GOARCH=wasm,
GOOS=js code, which perform a lot of memory reads and do not have
idiomatic signatures.

Note: wasm-defined host functions remain internal until we gain
experience, at least conclusion of the wasm_exec host module.


Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-07-25 09:12:44 +08:00
Crypt Keeper
b98a11e9c3 Refactors host function tests to stub with wasm (#710)
This refactors host functions with no-op or constant returns to be
implemented with wasm instead of the host function bridge. This allows
better performance.

This also breaks up and makes WASI tests consistent, in a way that shows
parameter name drifts easier.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-07-21 15:49:55 +08:00