Commit Graph

127 Commits

Author SHA1 Message Date
Andrew Brown
6ebbab61b9 Update cfg-if dependency 2020-10-23 16:50:51 -07:00
Nick Fitzgerald
1532834f3e Merge pull request #2305 from alexcrichton/no-arc
Don't store `Arc<VMInterrupts>` in instances
2020-10-21 13:21:51 -07:00
Alex Crichton
461ed42772 Remove the finished_functions field in Instance
Turns out we don't actually need it anywhere any more! This removes an
allocation when instantiating.
2020-10-21 11:43:11 -07:00
Alex Crichton
04e85b044e Don't store Arc<VMInterrupts> in instances
Similar to other data structures owned by the `Store` there's no need
for `Instance` to have a strong `Arc` reference, instead it's sufficient
for `Store` to have the owning reference.
2020-10-21 11:42:57 -07:00
Alex Crichton
e659d5cecd Add initial support for the multi-memory proposal (#2263)
This commit adds initial (gated) support for the multi-memory wasm
proposal. This was actually quite easy since almost all of wasmtime
already expected multi-memory to be implemented one day. The only real
substantive change is the `memory.copy` intrinsic changes, which now
accounts for the source/destination memories possibly being different.
2020-10-13 19:13:52 -05:00
subtly
d91f0c3933 get pc for freebsd (#2270)
* get pc for freebsd

* whitespace :|

* fix; i386 to x86

* remove x86 since uc_mcontext isn't yet in libc

* freebsd build of rust uses libcc/unwind
2020-10-07 06:30:14 -05:00
Alex Crichton
5e08eb3b83 Bump wasmtime to 0.20.0 (#2222)
At the same time bump cranelift crates to 0.67.0
2020-09-23 13:54:02 -05:00
Benjamin Bouvier
04cf94cea3 runtime: fix nearest for NaN inputs;
According to wasm's spec, nearest must do the following, for NaN inputs:
- when the input is a canonical NaN, return a canonical NaN;
- when the input is a non-canonical NaN, return an arithmetic NaN.

This patch adds checks when the exponent is all ones if the input was a
NaN, and will set the significand's most significant bit in that case.
It works both for canonical inputs (which already had the bit set) and
makes other NaN inputs canonical.
2020-09-23 16:42:03 +02:00
MaxGraey
a8f7041296 new implementations for nearest lib calls
use approach with copysign for handling negative zero


format


refactor for better branch prediction


move copysign back to internal branch


format


fix


use abs instead branches


better comments


switch arms for better branch prediction
2020-08-31 09:39:20 -07:00
Alex Crichton
bd8e08fe4a Update error message for bad table init
Although the string description for `TableOutOfBounds` isn't quite
matching what this error case is, it's a bit more descriptive than
`HeapOutOfBounds` anyway.
2020-08-10 06:57:58 -07:00
Alex Crichton
c7cd70fcec wasmtime: Refactor how imports are resolved (#2102)
This commit removes all import resolution handling from the
`wasmtime-jit` crate, instead moving the logic to the `wasmtime` crate.
Previously `wasmtime-jit` had a generic `Resolver` trait and would do
all the import type matching itself, but with the upcoming
module-linking implementation this is going to get much trickier.

The goal of this commit is to centralize all meaty "preparation" logic
for instantiation into one location, probably the `wasmtime` crate
itself. Instantiation will soon involve recursive instantiation and
management of alias definitions as well. Having everything in one
location, especially with access to `Store` so we can persist
instances for safety, will be quite convenient.

Additionally the `Resolver` trait isn't really necessary any more since
imports are, at the lowest level, provided as a list rather than a map
of some kind. More generic resolution functionality is provided via
`Linker` or user layers on top of `Instance::new` itself. This makes
matching up provided items to expected imports much easier as well.

Overall this is largely just moving code around, but most of the code
in the previous `resolve_imports` phase can be deleted since a lot of it
is handled by surrounding pieces of `wasmtime` as well.
2020-08-07 16:38:01 -05:00
Nick Fitzgerald
05bf9ea3f3 Rename "Stackmap" to "StackMap"
And "stackmap" to "stack_map".

This commit is purely mechanical.
2020-08-07 10:08:44 -07:00
Alex Crichton
3d2e0e55f2 Remove the local field of Module (#2091)
This was added long ago at this point to assist with caching, but
caching has moved to a different level such that this wonky second level
of a `Module` isn't necessary. This commit removes the `ModuleLocal`
type to simplify accessors and generally make it easier to work with.
2020-08-04 12:29:16 -05:00
Alex Crichton
63d5b91930 Wasmtime 0.19.0 and Cranelift 0.66.0 (#2027)
This commit updates Wasmtime's version to 0.19.0, Cranelift's version to
0.66.0, and updates the release notes as well.
2020-07-16 12:46:21 -05:00
Rochet2
0387169934 Allow android compilation (#2002) 2020-07-09 11:03:55 -05:00
Nick Fitzgerald
a7c6433773 wasmtime: Support reference types in the Rust API
This is a mix of exposing new things (e.g. a `Table::fill` method) and extending
existing support to `externref`s (e.g. `Table::new`).

Part of #929
2020-07-06 14:21:32 -07:00
Nick Fitzgerald
3555f97906 wasmtime: Implement table.fill
Part of #929
2020-07-02 16:59:07 -07:00
Nick Fitzgerald
bffd54c016 wasmtime: Implement global.{get,set} for externref globals (#1969)
* wasmtime: Implement `global.{get,set}` for externref globals

We use libcalls to implement these -- unlike `table.{get,set}`, for which we
create inline JIT fast paths -- because no known toolchain actually uses
externref globals.

Part of #929

* wasmtime: Enable `{extern,func}ref` globals in the API
2020-07-02 16:04:01 -05:00
Nick Fitzgerald
98e899f6b3 fuzz: Add a fuzz target for table.{get,set} operations
This new fuzz target exercises sequences of `table.get`s, `table.set`s, and
GCs.

It already found a couple bugs:

* Some leaks due to ref count cycles between stores and host-defined functions
  closing over those stores.

* If there are no live references for a PC, Cranelift can avoid emiting an
  associated stack map. This was running afoul of a debug assertion.
2020-06-30 12:00:57 -07:00
Nick Fitzgerald
8c5f59c0cf wasmtime: Implement table.get and table.set
These instructions have fast, inline JIT paths for the common cases, and only
call out to host VM functions for the slow paths. This required some changes to
`cranelift-wasm`'s `FuncEnvironment`: instead of taking a `FuncCursor` to insert
an instruction sequence within the current basic block,
`FuncEnvironment::translate_table_{get,set}` now take a `&mut FunctionBuilder`
so that they can create whole new basic blocks. This is necessary for
implementing GC read/write barriers that involve branching (e.g. checking for
null, or whether a store buffer is at capacity).

Furthermore, it required that the `load`, `load_complex`, and `store`
instructions handle loading and storing through an `r{32,64}` rather than just
`i{32,64}` addresses. This involved making `r{32,64}` types acceptable
instantiations of the `iAddr` type variable, plus a few new instruction
encodings.

Part of #929
2020-06-30 12:00:57 -07:00
Alex Crichton
0acd2072c2 Fix doc warnings and link failures (#1948)
Also add configuration to CI to fail doc generation if any links are
broken. Unfortunately we can't blanket deny all warnings in rustdoc
since some are unconditional warnings, but for now this is hopefully
good enough.

Closes #1947
2020-06-30 13:01:49 -05:00
Valentin
c10c79b7ae Correct version of region dependency (#1933) 2020-06-29 08:55:37 -05:00
Nick Fitzgerald
58bb5dd953 wasmtime: Add support for func.ref and table.grow with funcrefs
`funcref`s are implemented as `NonNull<VMCallerCheckedAnyfunc>`.

This should be more efficient than using a `VMExternRef` that points at a
`VMCallerCheckedAnyfunc` because it gets rid of an indirection, dynamic
allocation, and some reference counting.

Note that the null function reference is *NOT* a null pointer; it is a
`VMCallerCheckedAnyfunc` that has a null `func_ptr` member.

Part of #929
2020-06-24 10:08:13 -07:00
Nick Fitzgerald
bbd99c5bfa reference types: Implement the table.size and table.grow instructions (#1894)
Part of #929
2020-06-18 08:57:18 -05:00
Nick Fitzgerald
647d2b4231 Merge pull request #1832 from fitzgen/externref-stack-maps
externref: implement stack map-based garbage collection
2020-06-15 18:26:24 -07:00
Nick Fitzgerald
7e167cae10 externref: Address review feedback 2020-06-15 15:39:26 -07:00
Nick Fitzgerald
8d671c21e2 wasmtime-runtime: Allow tables to internally hold externrefs (#1882)
This commit enables `wasmtime_runtime::Table` to internally hold elements of
either `funcref` (all that is currently supported) or `externref` (newly
introduced in this commit).

This commit updates `Table`'s API, but does NOT generally propagate those
changes outwards all the way through the Wasmtime embedding API. It only does
enough to get everything compiling and the current test suite passing. It is
expected that as we implement more of the reference types spec, we will bubble
these changes out and expose them to the embedding API.
2020-06-15 16:55:23 -05:00
Nick Fitzgerald
618c278e41 externref: implement a canary for GC stack walking
This allows us to detect when stack walking has failed to walk the whole stack,
and we are potentially missing on-stack roots, and therefore it would be unsafe
to do a GC because we could free objects too early, leading to use-after-free.
When we detect this scenario, we skip the GC.
2020-06-15 09:39:37 -07:00
Nick Fitzgerald
f30ce1fe97 externref: implement stack map-based garbage collection
For host VM code, we use plain reference counting, where cloning increments
the reference count, and dropping decrements it. We can avoid many of the
on-stack increment/decrement operations that typically plague the
performance of reference counting via Rust's ownership and borrowing system.
Moving a `VMExternRef` avoids mutating its reference count, and borrowing it
either avoids the reference count increment or delays it until if/when the
`VMExternRef` is cloned.

When passing a `VMExternRef` into compiled Wasm code, we don't want to do
reference count mutations for every compiled `local.{get,set}`, nor for
every function call. Therefore, we use a variation of **deferred reference
counting**, where we only mutate reference counts when storing
`VMExternRef`s somewhere that outlives the activation: into a global or
table. Simultaneously, we over-approximate the set of `VMExternRef`s that
are inside Wasm function activations. Periodically, we walk the stack at GC
safe points, and use stack map information to precisely identify the set of
`VMExternRef`s inside Wasm activations. Then we take the difference between
this precise set and our over-approximation, and decrement the reference
count for each of the `VMExternRef`s that are in our over-approximation but
not in the precise set. Finally, the over-approximation is replaced with the
precise set.

The `VMExternRefActivationsTable` implements the over-approximized set of
`VMExternRef`s referenced by Wasm activations. Calling a Wasm function and
passing it a `VMExternRef` moves the `VMExternRef` into the table, and the
compiled Wasm function logically "borrows" the `VMExternRef` from the
table. Similarly, `global.get` and `table.get` operations clone the gotten
`VMExternRef` into the `VMExternRefActivationsTable` and then "borrow" the
reference out of the table.

When a `VMExternRef` is returned to host code from a Wasm function, the host
increments the reference count (because the reference is logically
"borrowed" from the `VMExternRefActivationsTable` and the reference count
from the table will be dropped at the next GC).

For more general information on deferred reference counting, see *An
Examination of Deferred Reference Counting and Cycle Detection* by Quinane:
https://openresearch-repository.anu.edu.au/bitstream/1885/42030/2/hon-thesis.pdf

cc #929

Fixes #1804
2020-06-15 09:39:37 -07:00
Dan Gohman
caa87048ab Wasmtime 0.18.0 and Cranelift 0.65.0. 2020-06-11 17:49:56 -07:00
Maciej Woś
7ab5f2a869 Remove custom signal handler restrictions (#1843)
* remove custom signal handler origin restriction

* add a test for handling signals from a hostcall

* cargo fmt
2020-06-08 12:33:28 -05:00
whitequark
bc555468a7 cranelift: add i64.{ishl,ushr,ashr} libcalls.
These libcalls are useful for 32-bit platforms.

On x86_32 in particular, commit 4ec16fa0 added support for legalizing
64-bit shifts through SIMD operations. However, that legalization
requires SIMD to be enabled and SSE 4.1 to be supported, which is not
acceptable as a hard requirement.
2020-06-05 12:13:49 -07:00
Chris Fallin
b8e31d7c8e Fix build warnings (errors on CI) due to mmap flag rename and deprecation. 2020-06-03 09:48:22 -07:00
Dan Gohman
a76639c6fb Wasmtime 0.17.0 and Cranelift 0.64.0. (#1805) 2020-06-02 18:51:59 -07:00
Yury Delendik
15c68f2cc1 Disconnects Store state fields from Compiler (#1761)
*  Moves CodeMemory, VMInterrupts and SignatureRegistry from Compiler
*  CompiledModule holds CodeMemory and GdbJitImageRegistration
*  Store keeps track of its JIT code
*  Makes "jit_int.rs" stuff Send+Sync
*  Adds the threads example.
2020-06-02 13:44:39 -05:00
Nick Fitzgerald
b78eafcfd3 externref: Do not impl common traits, have free functions instead
If you aren't expecting `VMExternRef`'s pointer-equality semantics, then these
trait implementations can be foot guns. Instead of implementing the trait, make
free functions in the `VMExternRef` namespace. This way, callers have to be a
little more explicit.
2020-06-01 15:09:51 -07:00
Nick Fitzgerald
98da9ee8a9 Use std::alloc::handle_alloc_failure instead of home-rolled version 2020-06-01 15:09:51 -07:00
Nick Fitzgerald
25548d7fbe externref: Share more Layout-computing code 2020-06-01 15:09:51 -07:00
Nick Fitzgerald
a8ee0554a9 wasmtime: Initial, partial support for externref
This is enough to get an `externref -> externref` identity function
passing.

However, `externref`s that are dropped by compiled Wasm code are (safely)
leaked. Follow up work will leverage cranelift's stack maps to resolve this
issue.
2020-06-01 15:09:51 -07:00
Nick Fitzgerald
1898d52966 runtime: Introduce VMExternRef and VMExternData
`VMExternRef` is a reference-counted box for any kind of data that is
external and opaque to running Wasm. Sometimes it might hold a Wasmtime
thing, other times it might hold something from a Wasmtime embedder and is
opaque even to us. It is morally equivalent to `Rc<dyn Any>` in Rust, but
additionally always fits in a pointer-sized word. `VMExternRef` is
non-nullable, but `Option<VMExternRef>` is a null pointer.

The one part of `VMExternRef` that can't ever be opaque to us is the
reference count. Even when we don't know what's inside an `VMExternRef`, we
need to be able to manipulate its reference count as we add and remove
references to it. And we need to do this from compiled Wasm code, so it must
be `repr(C)`!

`VMExternRef` itself is just a pointer to an `VMExternData`, which holds the
opaque, boxed value, its reference count, and its vtable pointer.

The `VMExternData` struct is *preceded* by the dynamically-sized value boxed
up and referenced by one or more `VMExternRef`s:

```ignore
     ,-------------------------------------------------------.
     |                                                       |
     V                                                       |
    +----------------------------+-----------+-----------+   |
    | dynamically-sized value... | ref_count | value_ptr |---'
    +----------------------------+-----------+-----------+
                                 | VMExternData          |
                                 +-----------------------+
                                  ^
+-------------+                   |
| VMExternRef |-------------------+
+-------------+                   |
                                  |
+-------------+                   |
| VMExternRef |-------------------+
+-------------+                   |
                                  |
  ...                            ===
                                  |
+-------------+                   |
| VMExternRef |-------------------'
+-------------+
```

The `value_ptr` member always points backwards to the start of the
dynamically-sized value (which is also the start of the heap allocation for
this value-and-`VMExternData` pair). Because it is a `dyn` pointer, it is
fat, and also points to the value's `Any` vtable.

The boxed value and the `VMExternRef` footer are held a single heap
allocation. The layout described above is used to make satisfying the
value's alignment easy: we just need to ensure that the heap allocation used
to hold everything satisfies its alignment. It also ensures that we don't
need a ton of excess padding between the `VMExternData` and the value for
values with large alignment.
2020-06-01 14:53:10 -07:00
Dan Gohman
3715e19c67 Reactor support. (#1565)
* Reactor support.

This implements the new WASI ABI described here:

https://github.com/WebAssembly/WASI/blob/master/design/application-abi.md

It adds APIs to `Instance` and `Linker` with support for running
WASI programs, and also simplifies the process of instantiating
WASI API modules.

This currently only includes Rust API support.

* Add comments and fix a typo in a comment.

* Fix a rustdoc warning.

* Tidy an unneeded `mut`.

* Factor out instance initialization with `NewInstance`.

This also separates instantiation from initialization in a manner
similar to https://github.com/bytecodealliance/lucet/pull/506.

* Update fuzzing oracles for the API changes.

* Remove `wasi_linker` and clarify that Commands/Reactors aren't connected to WASI.

* Move Command/Reactor semantics into the Linker.

* C API support.

* Fix fuzzer build.

* Update usage syntax from "::" to "=".

* Remove `NewInstance` and `start()`.

* Elaborate on Commands and Reactors and add a spec link.

* Add more comments.

* Fix wat syntax.

* Fix wat.

* Use the `Debug` formatter to format an anyhow::Error.

* Fix wat.
2020-05-26 10:39:40 -05:00
whitequark
b2e8ed4dc9 cranelift: add i64.[us]{div,rem} libcalls.
These libcalls are useful for 32-bit platforms.
2020-05-22 11:41:56 +00:00
whitequark
26ee986c2f runtime: handle traps on Windows x32. (#1740) 2020-05-21 15:07:05 -05:00
Alex Crichton
962f057c8a Remove no-longer-needed C shims (#1686)
The published version of `libc` now has all that's necessary to natively
read these fields!
2020-05-12 16:01:13 -05:00
whitequark
b3a9882466 Add X86-32 support to wasm-runtime trap handler. 2020-05-09 03:27:06 -07:00
Alex Crichton
8e934e6762 Update Table::grow's return to be the previous size (#1653)
* Update `Table::grow`'s return to be the previous size

This brings it in line with `Memory::grow` and the `table.grow`
instruction which return the size of the table previously, not the size
of the table currently.

* Comment successful return
2020-05-05 12:03:31 -05:00
Alex Crichton
c284ffe6c0 Move trap handler initialization to per-Store (#1644)
Previously we initialized trap handling (signals/etc) once-per-instance
but that's a bit too granular since we only need to do this as
one-time per-program initialization. This moves the initialization to
`Store` instead which means that we'll call this at least once per
thread, which some platforms may need (none currently do, they all only
need per-program initialization, but Fuchsia will need per-thread
initialization).
2020-05-01 19:55:35 -05:00
Dan Gohman
864cf98c8d Update release notes, wasmtime 0.16, cranelift 0.63. 2020-04-29 17:30:25 -07:00
Alex Crichton
d719ec7e1c Don't try to handle non-wasmtime segfaults (#1577)
This commit fixes an issue in Wasmtime where Wasmtime would accidentally
"handle" non-wasm segfaults while executing host imports of wasm
modules. If a host import segfaulted then Wasmtime would recognize that
wasm code is on the stack, so it'd longjmp out of the wasm code. This
papers over real bugs though in host code and erroneously classified
segfaults as wasm traps.

The fix here was to add a check to our wasm signal handler for if the
faulting address falls in JIT code itself. Actually threading through
all the right information for that check to happen is a bit tricky,
though, so this involved some refactoring:

* A closure parameter to `catch_traps` was added. This closure is
  responsible for classifying addresses as whether or not they fall in
  JIT code. Anything returning `false` means that the trap won't get
  handled and we'll forward to the next signal handler.

* To avoid passing tons of context all over the place, the start
  function is now no longer automatically invoked by `InstanceHandle`.
  This avoids the need for passing all sorts of trap-handling contextual
  information like the maximum stack size and "is this a jit address"
  closure. Instead creators of `InstanceHandle` (like wasmtime) are now
  responsible for invoking the start function.

* To avoid excessive use of `transmute` with lifetimes since the
  traphandler state now has a lifetime the per-instance custom signal
  handler is now replaced with a per-store custom signal handler. I'm
  not entirely certain the purpose of the custom signal handler, though,
  so I'd look for feedback on this part.

A new test has been added which ensures that if a host function
segfaults we don't accidentally try to handle it, and instead we
correctly report the segfault.
2020-04-29 14:24:54 -05:00
Alex Crichton
654e953fbf Revamp memory management of InstanceHandle (#1624)
* Revamp memory management of `InstanceHandle`

This commit fixes a known but in Wasmtime where an instance could still
be used after it was freed. Unfortunately the fix here is a bit of a
hammer, but it's the best that we can do for now. The changes made in
this commit are:

* A `Store` now stores all `InstanceHandle` objects it ever creates.
  This keeps all instances alive unconditionally (along with all host
  functions and such) until the `Store` is itself dropped. Note that a
  `Store` is reference counted so basically everything has to be dropped
  to drop anything, there's no longer any partial deallocation of instances.

* The `InstanceHandle` type's own reference counting has been removed.
  This is largely redundant with what's already happening in `Store`, so
  there's no need to manage two reference counts.

* Each `InstanceHandle` no longer tracks its dependencies in terms of
  instance handles. This set was actually inaccurate due to dynamic
  updates to tables and such, so we needed to revamp it anyway.

* Initialization of an `InstanceHandle` is now deferred until after
  `InstanceHandle::new`. This allows storing the `InstanceHandle` before
  side-effectful initialization, such as copying element segments or
  running the start function, to ensure that regardless of the result of
  instantiation the underlying `InstanceHandle` is still available to
  persist in storage.

Overall this should fix a known possible way to safely segfault Wasmtime
today (yay!) and it should also fix some flaikness I've seen on CI.
Turns out one of the spec tests
(bulk-memory-operations/partial-init-table-segment.wast) exercises this
functionality and we were hitting sporating use-after-free, but only on
Windows.

* Shuffle some APIs around

* Comment weak cycle
2020-04-29 12:47:49 -05:00