Commit Graph

20 Commits

Author SHA1 Message Date
Anuraag Agrawal
714368bcea Remove threads support (#1487)
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
2023-05-22 12:18:36 +10:00
Anuraag Agrawal
bc96257575 Implement WebAssembly threads proposal with interpreter (#1460)
Signed-off-by: Anuraag Agrawal <anuraaga@gmail.com>
2023-05-16 12:22:17 +08: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
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
Edoardo Vacchi
94743cc21e Set Memory.Max to min(user-memory-limit, sys-memory-limit) on load (#1165)
Updated `newMemorySizer()` to return the updated value, but also
ensure that an invalid `max` still throws an error (invalid module).

- Minor cleanup to use the `memorySizer` type instead of the full
  func signature for clarity
- Added a wat+wasm under `internal/integration_test/vs/testdata/`
  simply because that's where the other cache-related testdata was.

Closes #1153.

Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
2023-02-25 07:31:23 +08: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
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
Crypt Keeper
8f8c9ee205 Extracts CompileConfig and consolidates code. (#533)
This performs several changes to allow compilation config to be
centralized and scoped properly. The immediate effects are that we can
now process external types during `Runtime.CompileModule` instead of
doing so later during `Runtime.InstantiateModule`. Another nice side
effect is memory size problems can err at a source line instead of
having to be handled in several places.

There are some API effects to this, and to pay for them, some less used
APIs were removed. The "easy APIs" are left alone. For example, the APIs
to compile and instantiate a module from Go or Wasm in one step are left
alone.

Here are the changes, some of which are only for consistency. Rationale
is summarized in each point.
* ModuleBuilder.Build -> ModuleBuilder.Compile
  * The result of this is similar to `CompileModule`, and pairs better
    with `ModuleBuilder.Instantiate` which is like `InstantiateModule`.
* CompiledCode -> CompiledModule
  * We punted on this name, the result is more than just code. This is
    better I think and more consistent as it introduces less terms.
* Adds CompileConfig param to Runtime.CompileModule.
  * This holds existing features and will have future ones, such as
    mapping externtypes to uint64 for wasm that doesn't yet support it.
* Merges Runtime.InstantiateModuleWithConfig with Runtime.InstantiateModule
  * This allows us to explain APIs in terms of implicit or explicit
    compilation and config, vs implicit, kindof implicit, and explicit.
* Removes Runtime.InstantiateModuleFromCodeWithConfig
  * Similar to above, this API only saves the compilation step and also
    difficult to reason with from a name POV.
* RuntimeConfig.WithMemory(CapacityPages|LimitPages) -> CompileConfig.WithMemorySizer
  * This allows all error handling to be attached to the source line
  * This also allows someone to reduce unbounded memory while knowing
    what its minimum is.
* ModuleConfig.With(Import|ImportModule) -> CompileConfig.WithImportRenamer
  * This allows more types of import manipulation, also without
    conflating functions with globals.
* Adds api.ExternType
  * Needed for ImportRenamer and will be needed later for ExportRenamer.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-05-09 11:02:32 +08:00
Takeshi Yoneda
72f16d21eb Adds support for multi tables (#517)
This commit adds support for multiple tables per module.
Notably, if the WithFeatureReferenceTypes is enabled,
call_indirect, table.init and table.copy instructions
can reference non-zero indexed tables.

part of #484

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-05-03 11:38:51 +09:00
Crypt Keeper
2c03098dba Adds Runtime.WithCapacityPages to avoid allocations during runtime. (#514)
`Runtime.WithMemoryCapacityPages` is a function that determines memory
capacity in pages (65536 bytes per page). The inputs are the min and
possibly nil max defined by the module, and the default is to return
the min.

Ex. To set capacity to max when exists:
```golang
c.WithMemoryCapacityPages(func(minPages uint32, maxPages *uint32) uint32 {
	if maxPages != nil {
		return *maxPages
	}
	return minPages
})
```

Note: This applies at compile time, ModuleBuilder.Build or Runtime.CompileModule.

Fixes #500

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-04-29 17:54:48 +08:00
Takeshi Yoneda
266320e257 Complete bulk memory operations proposal (#511)
This commit implements the rest of the unimplemented instructions in the
bulk-memory-operations proposal.

Notably, this adds support for table.init, table.copy and elem.drop
instructions toggled by FeatureBulkMemoryOperations.

Given that, now wazero has the complete support for the  bulk-memory-operations
proposal as described in https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md

fixes #321

Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-04-28 15:08:24 +09:00
Takeshi Yoneda
e3035b5a76 binary: complete encoder (#463)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-04-14 16:55:53 +09:00
Crypt Keeper
2664b1eb62 Simplifies API per feedback (#427)
During #425, @neilalexander gave constructive feedback that the API is
both moving fast, and not good enough yet. This attempts to reduce the
incidental complexity at the cost of a little conflation.

### odd presence of `wasm` and `wasi` packages -> `api` package

We had public API packages in wasm and wasi, which helped us avoid
leaking too many internals as public. That these had names that look
like there should be implementations in them cause unnecessary
confusion. This squashes both into one package "api" which has no
package collission with anything.

We've long struggled with the poorly specified and non-uniformly
implemented WASI specification. Trying to bring visibility to its
constraints knowing they are routinely invalid taints our API for no
good reason. This removes all `WASI` commands for a default to invoke
the function `_start` if it exists. In doing so, there's only one path
to start a module.

Moreover, this puts all wasi code in a top-level package "wasi" as it
isn't re-imported by any internal types.

### Reuse of Module for pre and post instantiation to `Binary` -> `Module`

Module is defined by WebAssembly in many phases, from decoded to
instantiated. However, using the same noun in multiple packages is very
confusing. We at one point tried a name "DecodedModule" or
"InstantiatedModule", but this is a fools errand. By deviating slightly
from the spec we can make it unambiguous what a module is.

This make a result of compilation a `Binary`, retaining `Module` for an
instantiated one. In doing so, there's no longer any name conflicts
whatsoever.

### Confusion about config -> `ModuleConfig`

Also caused by splitting wasm into wasm+wasi is configuration. This
conflates both into the same type `ModuleConfig` as it is simpler than
trying to explain a "will never be finished" api of wasi snapshot-01 in
routine use of WebAssembly. In other words, this further moves WASI out
of the foreground as it has been nothing but burden.

```diff
--- a/README.md
+++ b/README.md
@@ -49,8 +49,8 @@ For example, here's how you can allow WebAssembly modules to read
-wm, err := r.InstantiateModule(wazero.WASISnapshotPreview1())
-defer wm.Close()
+wm, err := wasi.InstantiateSnapshotPreview1(r)
+defer wm.Close()

-sysConfig := wazero.NewSysConfig().WithFS(os.DirFS("/work/home"))
-module, err := wazero.StartWASICommandWithConfig(r, compiled, sysConfig)
+config := wazero.ModuleConfig().WithFS(os.DirFS("/work/home"))
+module, err := r.InstantiateModule(binary, config)
 defer module.Close()
 ...
```
2022-04-02 06:42:36 +08:00
Crypt Keeper
8f461f6f12 Makes memory limit configurable and a compile error (#419)
This allows users to reduce the memory limit per module below 4 Gi. This
is often needed because Wasm routinely leaves off the max, which implies
spec max (4 Gi). This uses Ki Gi etc in error messages because the spec
chooses to, though we can change to make it less awkward.

This also fixes an issue where we instantiated an engine inside config.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-31 08:57:28 +08:00
Crypt Keeper
97c759b9d8 Flattens Memory and Table types and backfills Table encoder (#356)
This flattens Memory and Table types, particularly making it a
compilation error to add multiple of either.

This also backfills binary encoding of Table.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-10 15:47:49 +08:00
Crypt Keeper
5f29edb9a3 Adds global binary encoder and fixes scope of mutable-global flag (#352)
Before, we denied mutable globals when mutable-global=false, when really
that flag is about import/export. This fixes the flag so that it
disables externalizing a mutable global. Non-exported mutable globals
are common as implenented by compilers such as Emscripten.

See https://github.com/emscripten-core/emscripten/blob/main/system%2Flib%2Fcompiler-rt%2Fstack_ops.S

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takaya Saeki <takaya@tetrate.io>
2022-03-09 19:50:43 +08:00
Crypt Keeper
cfb11f352a Adds ability to disable mutable globals and improves decode perf (#315)
This adds `RuntimeConfig.WithFeatureMutableGlobal(enabled bool)`, which
allows disabling of mutable globals. When disabled, any attempt to add a
mutable global, either explicitly or implicitly via decoding wasm will
fail.

To support this, there's a new `Features` bitflag that can allow up to
63 feature toggles without passing structs.

While here, I fixed a significant performance problem in decoding
binary:

Before
```
BenchmarkCodecExample/binary.DecodeModule-16         	  184243	      5623 ns/op	    3848 B/op	     184 allocs/op
```

Now
```
BenchmarkCodecExample/binary.DecodeModule-16         	  294084	      3520 ns/op	    2176 B/op	      91 allocs/op

```

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-03 10:31:10 +08:00
Crypt Keeper
22945a3ff4 Folds ImportKind and ExportKind into ExternType (#297)
This centralizes our management of external types by choosing the word
"external" also used in the spec instead of defining the same constants
for imports vs exports. One advantage is more coherent reference
searching as constants are no longer split. Another is future work can
use a single type to manage namespace length checks.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-28 10:21:11 +08:00
Crypt Keeper
119144ece8 Stops proliferation of MVP jargon (#295)
MVP was a term used by WebAssembly insiders when ramping up to the 1.0
spec. While these folks still use that term it is confusing and
unnecessary way to qualify a W3C version. Here are some of the problems:

* MVP does not match a W3C published URL
* MVP does not match a git tag on the spec repo
* MVP was a work in progress, so there are text that say "not in MVP"
  which ended up in 1.0 (as MVP became more than it was).
* MVP is jargon to people who don't know that stands for Minimum Viable Product.

This stops this practice and instead uses the W3C 1.0 Draft version
instead: 20191205

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-25 09:34:05 +08:00
Crypt Keeper
5180d2d9c3 Refactors out public API from internals (#238)
This moves to a new end-user API under the root package `wazero`. This
simplifies call sites while hardening function calls to their known
return value. Most importantly, this moves most logic internal, as
noted in the RATIONALE.md.

Ex.

```go
	// Read WebAssembly binary containing an exported "fac" function.
	source, _ := os.ReadFile("./tests/engine/testdata/fac.wasm")

	// Decode the binary as WebAssembly module.
	mod, _ := wazero.DecodeModuleBinary(source)

	// Initialize the execution environment called "store" with Interpreter-based engine.
	store := wazero.NewStore()

	// Instantiate the module, which returns its exported functions
	functions, _ := store.Instantiate(mod)

	// Get the factorial function
	fac, _ := functions.GetFunctionI64Return("fac")

	// Discover 7! is 5040
	fmt.Println(fac(context.Background(), 7))

```

PS I changed the README to factorial because the wat version of
fibonacci is not consistent with the TinyGo one!

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takaya Saeki <takaya@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-02-17 17:39:28 +08:00