Skip to content

Commit

Permalink
chore: upgrade wasmtime to 26 (#2205)
Browse files Browse the repository at this point in the history
This PR upgrades Wasmtime to version 26. The special case about this
release is that it adds support for the "table64" extension of the
memory64 proposals to WebAssembly.

---------

Co-authored-by: Alexandru Uta <alexandru.uta@gmail.com>
Co-authored-by: IDX GitHub Automation <infra+github-automation@dfinity.org>
  • Loading branch information
3 people authored Nov 5, 2024
1 parent 2481ad5 commit e069357
Show file tree
Hide file tree
Showing 10 changed files with 1,254 additions and 976 deletions.
749 changes: 414 additions & 335 deletions Cargo.Bazel.Fuzzing.json.lock

Large diffs are not rendered by default.

194 changes: 105 additions & 89 deletions Cargo.Bazel.Fuzzing.toml.lock

Large diffs are not rendered by default.

749 changes: 414 additions & 335 deletions Cargo.Bazel.json.lock

Large diffs are not rendered by default.

194 changes: 105 additions & 89 deletions Cargo.Bazel.toml.lock

Large diffs are not rendered by default.

208 changes: 109 additions & 99 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions bazel/external_crates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1425,7 +1425,7 @@ def external_crates_repository(name, cargo_lockfile, lockfile, sanitizers_enable
version = "^0.217.0",
),
"wasmtime": crate.spec(
version = "=25.0.2",
version = "^26.0.0",
default_features = False,
features = [
"cranelift",
Expand All @@ -1435,7 +1435,7 @@ def external_crates_repository(name, cargo_lockfile, lockfile, sanitizers_enable
],
),
"wasmtime-environ": crate.spec(
version = "^25.0.0",
version = "^26.0.0",
),
"wast": crate.spec(
version = "^212.0.0",
Expand Down
4 changes: 2 additions & 2 deletions rs/embedders/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ slog = { workspace = true }
slog-term = { workspace = true }
wasm-encoder = { workspace = true }
wasmparser = { workspace = true }
wasmtime = { version = "25.0.0", default-features = false, features = [
wasmtime = { version = "26.0.0", default-features = false, features = [
'cranelift',
'gc',
'parallel-compilation',
'runtime',
] }
wasmtime-environ = "25.0.0"
wasmtime-environ = "26.0.0"

# Wasmtime depends on 0.4.2 but specifies 0.4.1 in the toml file.
# Enforce 0.4.2 using a dummy dependency until the upstream issue
Expand Down
4 changes: 2 additions & 2 deletions rs/embedders/src/wasmtime_embedder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub(crate) const STABLE_MEMORY_NAME: &str = "stable_memory";
pub(crate) const STABLE_BYTEMAP_MEMORY_NAME: &str = "stable_bytemap_memory";

pub(crate) const MAX_STORE_TABLES: usize = 1;
pub(crate) const MAX_STORE_TABLE_ELEMENTS: u32 = 1_000_000;
pub(crate) const MAX_STORE_TABLE_ELEMENTS: usize = 1_000_000;

fn demangle(func_name: &str) -> String {
if let Ok(name) = rustc_demangle::try_demangle(func_name) {
Expand Down Expand Up @@ -1043,7 +1043,7 @@ impl WasmtimeInstance {
.ok_or_else(|| HypervisorError::ToolchainContractViolation {
error: "export 'table' is not a table".to_string(),
})?
.get(&mut self.store, closure.func_idx)
.get(&mut self.store, closure.func_idx as u64)
.ok_or(HypervisorError::FunctionNotFound(0, closure.func_idx))?
.as_func()
.ok_or_else(|| HypervisorError::ToolchainContractViolation {
Expand Down
97 changes: 74 additions & 23 deletions rs/embedders/tests/instrumentation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1080,41 +1080,92 @@ fn charge_for_dirty_stable() {
run_charge_for_dirty_stable_test(FlagStatus::Disabled);
}

#[test]
fn table_modifications_are_unsupported() {
fn test(code: &str) -> String {
let wat = format!(
r#"(module
(table $table 101 funcref)
(elem func 0)
(func $f {code})
)"#
);
let embedder = WasmtimeEmbedder::new(EmbeddersConfig::default(), no_op_logger());
let wasm = wat::parse_str(wat).expect("Failed to convert wat to wasm");

wasm_utils::compile(&embedder, &BinaryEncodedWasm::new(wasm))
.1
.unwrap_err()
.to_string()
}
/// Helper method to generate a wasm module with tables in both
/// 32 and 64 bit modes and compile that module. The method
/// is then used to check if instrumentation of tables works
/// correctly for both Wasm32 and Wasm64 wrt tables.
fn test_table_validation(code: &str, is_wasm64: bool) -> String {
let execution_mode = if is_wasm64 { "i64" } else { "" };
let wat = format!(
r#"(module
(table $table {execution_mode} 101 funcref)
(elem func 0)
(func $f {code})
)"#
);
use ic_config::embedders::FeatureFlags;
use ic_config::flag_status::FlagStatus;

let embedders_config = EmbeddersConfig {
feature_flags: FeatureFlags {
wasm64: if is_wasm64 {
FlagStatus::Enabled
} else {
FlagStatus::Disabled
},
..Default::default()
},
..Default::default()
};

let embedder = WasmtimeEmbedder::new(embedders_config, no_op_logger());
let wasm = wat::parse_str(wat).expect("Failed to convert wat to wasm");

wasm_utils::compile(&embedder, &BinaryEncodedWasm::new(wasm))
.1
.unwrap_err()
.to_string()
}

fn table_modifications_are_unsupported_for_wasm_version(is_wasm64: bool) {
let address_type = if is_wasm64 { "i64" } else { "i32" };

let err = test("(drop (table.grow $table (ref.func 0) (i32.const 0)))");
let err = test_table_validation(
&format!("(drop (table.grow $table (ref.func 0) ({address_type}.const 0)))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.grow"));

let err = test("(table.set $table (i32.const 0) (ref.func 0))");
let err = test_table_validation(
&format!("(table.set $table ({address_type}.const 0) (ref.func 0))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.set"));

let err = test("(table.fill $table (i32.const 0) (ref.func 0) (i32.const 50))");
let err = test_table_validation(
&format!(
"(table.fill $table ({address_type}.const 0) (ref.func 0) ({address_type}.const 50))"
),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.fill"));

let err = test("(table.copy (i32.const 0) (i32.const 0) (i32.const 0))");
let err = test_table_validation(
&format!(
"(table.copy ({address_type}.const 0) ({address_type}.const 0) ({address_type}.const 0))"
),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.copy"));

let err = test("(table.init 0 (i32.const 0) (i32.const 0) (i32.const 0))");
let err = test_table_validation(
&format!("(table.init 0 ({address_type}.const 0) (i32.const 0) (i32.const 0))"),
is_wasm64,
);
assert!(err.contains("unsupported instruction table.init"));
}

#[test]
fn table_modifications_are_unsupported_for_wasm32() {
table_modifications_are_unsupported_for_wasm_version(false);
}

#[test]
fn table_modifications_are_unsupported_for_wasm64() {
table_modifications_are_unsupported_for_wasm_version(true);
}

#[test]
fn metering_wasm64_load_store_canister() {
let wat = r#"
Expand Down
27 changes: 27 additions & 0 deletions rs/embedders/tests/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1196,3 +1196,30 @@ fn test_wasm64_initial_wasm_memory_size_validation() {
})
);
}

#[test]
fn test_validate_table64() {
use ic_config::embedders::FeatureFlags;
use ic_config::flag_status::FlagStatus;

let embedders_config = EmbeddersConfig {
feature_flags: FeatureFlags {
wasm64: FlagStatus::Enabled,
..Default::default()
},
..Default::default()
};

let wasm = wat2wasm(
r#"(module
(table i64 1 funcref)
(memory i64 1 1)
)"#,
)
.unwrap();

assert_eq!(
validate_wasm_binary(&wasm, &embedders_config),
Ok(WasmValidationDetails::default())
);
}

0 comments on commit e069357

Please sign in to comment.