Skip to content

Commit

Permalink
Implement limiting WebAssembly execution with fuel (bytecodealliance#…
Browse files Browse the repository at this point in the history
…2611)

* Consume fuel during function execution

This commit adds codegen infrastructure necessary to instrument wasm
code to consume fuel as it executes. Currently nothing is really done
with the fuel, but that'll come in later commits.

The focus of this commit is to implement the codegen infrastructure
necessary to consume fuel and account for fuel consumed correctly.

* Periodically check remaining fuel in wasm JIT code

This commit enables wasm code to periodically check to see if fuel has
run out. When fuel runs out an intrinsic is called which can do what it
needs to do in the result of fuel running out. For now a trap is thrown
to have at least some semantics in synchronous stores, but another
planned use for this feature is for asynchronous stores to periodically
yield back to the host based on fuel running out.

Checks for remaining fuel happen in the same locations as interrupt
checks, which is to say the start of the function as well as loop
headers.

* Improve codegen by caching `*const VMInterrupts`

The location of the shared interrupt value and fuel value is through a
double-indirection on the vmctx (load through the vmctx and then load
through that pointer). The second pointer in this chain, however, never
changes, so we can alter codegen to account for this and remove some
extraneous load instructions and hopefully reduce some register
pressure even maybe.

* Add tests fuel can abort infinite loops

* More fuzzing with fuel

Use fuel to time out modules in addition to time, using fuzz input to
figure out which.

* Update docs on trapping instructions

* Fix doc links

* Fix a fuzz test

* Change setting fuel to adding fuel

* Fix a doc link

* Squelch some rustdoc warnings
  • Loading branch information
alexcrichton authored Jan 29, 2021
1 parent 78f3127 commit 0e41861
Show file tree
Hide file tree
Showing 26 changed files with 936 additions and 67 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ test-programs = { path = "crates/test-programs" }
wasmtime-fuzzing = { path = "crates/fuzzing" }
wasmtime-runtime = { path = "crates/runtime" }
tracing-subscriber = "0.2.0"
wast = "32.0.0"

[build-dependencies]
anyhow = "1.0.19"
Expand Down
2 changes: 1 addition & 1 deletion cranelift/src/souper_harvest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ static WASM_MAGIC: &[u8] = &[0x00, 0x61, 0x73, 0x6D];
/// Harvest candidates for superoptimization from a Wasm or Clif file.
///
/// Candidates are emitted in Souper's text format:
/// https://github.com/google/souper
/// <https://github.com/google/souper>
#[derive(StructOpt)]
pub struct Options {
/// Specify an input file to be used. Use '-' for stdin.
Expand Down
2 changes: 1 addition & 1 deletion cranelift/wasm/src/code_translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
.extend_from_slice(builder.block_params(loop_body));

builder.switch_to_block(loop_body);
environ.translate_loop_header(builder.cursor())?;
environ.translate_loop_header(builder)?;
}
Operator::If { ty } => {
let val = state.pop1();
Expand Down
8 changes: 7 additions & 1 deletion cranelift/wasm/src/environ/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ pub trait FuncEnvironment: TargetEnvironment {
ReturnMode::NormalReturns
}

/// Called after the locals for a function have been parsed, and the number
/// of variables defined by this function is provided.
fn after_locals(&mut self, num_locals_defined: usize) {
drop(num_locals_defined);
}

/// Set up the necessary preamble definitions in `func` to access the global variable
/// identified by `index`.
///
Expand Down Expand Up @@ -637,7 +643,7 @@ pub trait FuncEnvironment: TargetEnvironment {
///
/// This can be used to insert explicit interrupt or safepoint checking at
/// the beginnings of loops.
fn translate_loop_header(&mut self, _pos: FuncCursor) -> WasmResult<()> {
fn translate_loop_header(&mut self, _builder: &mut FunctionBuilder) -> WasmResult<()> {
// By default, don't emit anything.
Ok(())
}
Expand Down
2 changes: 2 additions & 0 deletions cranelift/wasm/src/func_translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ fn parse_local_decls<FE: FuncEnvironment + ?Sized>(
declare_locals(builder, count, ty, &mut next_local, environ)?;
}

environ.after_locals(next_local);

Ok(())
}

Expand Down
1 change: 1 addition & 0 deletions crates/cranelift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ cranelift-wasm = { path = "../../cranelift/wasm", version = "0.69.0" }
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.69.0" }
cranelift-frontend = { path = "../../cranelift/frontend", version = "0.69.0" }
cranelift-entity = { path = "../../cranelift/entity", version = "0.69.0" }
wasmparser = "0.73.0"
Loading

0 comments on commit 0e41861

Please sign in to comment.