Skip to content

Commit

Permalink
Merge with upstream
Browse files Browse the repository at this point in the history
  • Loading branch information
dhil committed Oct 11, 2024
2 parents 04e1411 + 292f136 commit 0da9592
Show file tree
Hide file tree
Showing 59 changed files with 1,909 additions and 604 deletions.
170 changes: 85 additions & 85 deletions Cargo.lock

Large diffs are not rendered by default.

22 changes: 11 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -274,19 +274,19 @@ io-lifetimes = { version = "2.0.3", default-features = false }
io-extras = "0.18.1"
rustix = "0.38.31"
# wit-bindgen:
wit-bindgen = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.33.0", default-features = false }
wit-bindgen-rust-macro = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.33.0", default-features = false }
wit-bindgen = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.34.0", default-features = false }
wit-bindgen-rust-macro = { git = "https://github.com/wasmfx/wit-bindgenfx", tag = "v0.34.0", default-features = false }

# wasm-tools family:
wasmparser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0", default-features = false }
wat = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wast = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wasmprinter = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wasm-encoder = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wasm-smith = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wasm-mutate = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wit-parser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wit-component = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.0" }
wasmparser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1", default-features = false }
wat = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wast = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wasmprinter = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wasm-encoder = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wasm-smith = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wasm-mutate = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wit-parser = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }
wit-component = { git = "https://github.com/wasmfx/wasmfx-tools", tag = "v1.219.1" }

# Non-Bytecode Alliance maintained dependencies:
# --------------------------
Expand Down
2 changes: 1 addition & 1 deletion crates/c-api/src/ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ pub unsafe extern "C" fn wasmtime_externref_data(
externref
.and_then(|e| e.as_wasmtime())
.and_then(|e| {
let data = e.data(cx).ok()?;
let data = e.data(cx).ok()??;
Some(data.downcast_ref::<crate::ForeignData>().unwrap().data)
})
.unwrap_or(ptr::null_mut())
Expand Down
105 changes: 99 additions & 6 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ wasmtime_option_group! {

/// The number of decommits to do per batch. A batch size of 1
/// effectively disables decommit batching. (default: 1)
pub pooling_decommit_batch_size: Option<u32>,
pub pooling_decommit_batch_size: Option<usize>,

/// How many bytes to keep resident between instantiations for the
/// pooling allocator in linear memories.
Expand All @@ -86,7 +86,11 @@ wasmtime_option_group! {

/// Enable memory protection keys for the pooling allocator; this can
/// optimize the size of memory slots.
pub memory_protection_keys: Option<bool>,
pub pooling_memory_protection_keys: Option<bool>,

/// Sets an upper limit on how many memory protection keys (MPK) Wasmtime
/// will use. (default: 16)
pub pooling_max_memory_protection_keys: Option<usize>,

/// Configure attempting to initialize linear memory via a
/// copy-on-write mapping (default: yes)
Expand Down Expand Up @@ -124,6 +128,43 @@ wasmtime_option_group! {
/// when using the pooling allocator.
pub pooling_max_core_instance_size: Option<usize>,

/// Configures the maximum number of "unused warm slots" to retain in the
/// pooling allocator. (default: 100)
pub pooling_max_unused_warm_slots: Option<u32>,

/// Configures whether or not stacks used for async futures are reset to
/// zero after usage. (default: false)
pub pooling_async_stack_zeroing: Option<bool>,

/// How much memory, in bytes, to keep resident for async stacks allocated
/// with the pooling allocator. (default: 0)
pub pooling_async_stack_keep_resident: Option<usize>,

/// The maximum size, in bytes, allocated for a component instance's
/// `VMComponentContext` metadata. (default: 1MiB)
pub pooling_max_component_instance_size: Option<usize>,

/// The maximum number of core instances a single component may contain
/// (default is unlimited).
pub pooling_max_core_instances_per_component: Option<u32>,

/// The maximum number of Wasm linear memories that a single component may
/// transitively contain (default is unlimited).
pub pooling_max_memories_per_component: Option<u32>,

/// The maximum number of tables that a single component may transitively
/// contain (default is unlimited).
pub pooling_max_tables_per_component: Option<u32>,

/// The maximum number of defined tables for a core module. (default: 1)
pub pooling_max_tables_per_module: Option<u32>,

/// The maximum number of defined linear memories for a module. (default: 1)
pub pooling_max_memories_per_module: Option<u32>,

/// The maximum number of concurrent GC heaps supported. (default: 1000)
pub pooling_total_gc_heaps: Option<u32>,

/// Enable or disable the use of host signal handlers for traps.
pub signals_based_traps: Option<bool>,
}
Expand Down Expand Up @@ -663,30 +704,82 @@ impl CommonOptions {
limit => cfg.total_stacks(limit),
_ => err,
}
if let Some(limit) = self.opts.pooling_max_memory_size {
cfg.max_memory_size(limit);
if let Some(max) = self.opts.pooling_max_memory_size {
cfg.max_memory_size(max);
}
if let Some(size) = self.opts.pooling_decommit_batch_size {
cfg.decommit_batch_size(size);
}
if let Some(max) = self.opts.pooling_max_unused_warm_slots {
cfg.max_unused_warm_slots(max);
}
match_feature! {
["async" : self.opts.pooling_async_stack_zeroing]
enable => cfg.async_stack_zeroing(enable),
_ => err,
}
match_feature! {
["async" : self.opts.pooling_async_stack_keep_resident]
size => cfg.async_stack_keep_resident(size),
_ => err,
}
if let Some(max) = self.opts.pooling_max_component_instance_size {
cfg.max_component_instance_size(max);
}
if let Some(max) = self.opts.pooling_max_core_instances_per_component {
cfg.max_core_instances_per_component(max);
}
if let Some(max) = self.opts.pooling_max_memories_per_component {
cfg.max_memories_per_component(max);
}
if let Some(max) = self.opts.pooling_max_tables_per_component {
cfg.max_tables_per_component(max);
}
if let Some(max) = self.opts.pooling_max_tables_per_module {
cfg.max_tables_per_module(max);
}
if let Some(max) = self.opts.pooling_max_memories_per_module {
cfg.max_memories_per_module(max);
}
match_feature! {
["memory-protection-keys" : self.opts.memory_protection_keys]
["memory-protection-keys" : self.opts.pooling_memory_protection_keys]
enable => cfg.memory_protection_keys(if enable {
wasmtime::MpkEnabled::Enable
} else {
wasmtime::MpkEnabled::Disable
}),
_ => err,
}
match_feature! {
["memory-protection-keys" : self.opts.pooling_max_memory_protection_keys]
max => cfg.max_memory_protection_keys(max),
_ => err,
}
match_feature! {
["gc" : self.opts.pooling_total_gc_heaps]
max => cfg.total_gc_heaps(max),
_ => err,
}
config.allocation_strategy(wasmtime::InstanceAllocationStrategy::Pooling(cfg));
}
},
true => err,
}

if self.opts.memory_protection_keys.unwrap_or(false)
if self.opts.pooling_memory_protection_keys.unwrap_or(false)
&& !self.opts.pooling_allocator.unwrap_or(false)
{
anyhow::bail!("memory protection keys require the pooling allocator");
}

if self.opts.pooling_max_memory_protection_keys.is_some()
&& !self.opts.pooling_memory_protection_keys.unwrap_or(false)
{
anyhow::bail!(
"max memory protection keys requires memory protection keys to be enabled"
);
}

match_feature! {
["async" : self.wasm.async_stack_size]
size => config.async_stack_size(size),
Expand Down
103 changes: 69 additions & 34 deletions crates/cranelift/src/func_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use cranelift_frontend::FunctionBuilder;
use cranelift_frontend::Variable;
use smallvec::SmallVec;
use std::mem;
use wasmparser::Operator;
use wasmparser::{Operator, WasmFeatures};
use wasmtime_environ::{
BuiltinFunctionIndex, DataIndex, ElemIndex, EngineOrModuleTypeIndex, FuncIndex, GlobalIndex,
IndexType, Memory, MemoryIndex, MemoryPlan, MemoryStyle, Module, ModuleInternedTypeIndex,
Expand Down Expand Up @@ -1304,13 +1304,15 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
/// Do an indirect call through the given funcref table.
pub fn indirect_call(
mut self,
features: &WasmFeatures,
table_index: TableIndex,
ty_index: TypeIndex,
sig_ref: ir::SigRef,
callee: ir::Value,
call_args: &[ir::Value],
) -> WasmResult<Option<ir::Inst>> {
let (code_ptr, callee_vmctx) = match self.check_and_load_code_and_callee_vmctx(
features,
table_index,
ty_index,
callee,
Expand All @@ -1326,6 +1328,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {

fn check_and_load_code_and_callee_vmctx(
&mut self,
features: &WasmFeatures,
table_index: TableIndex,
ty_index: TypeIndex,
callee: ir::Value,
Expand All @@ -1343,7 +1346,8 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
);

// If necessary, check the signature.
let check = self.check_indirect_call_type_signature(table_index, ty_index, funcref_ptr);
let check =
self.check_indirect_call_type_signature(features, table_index, ty_index, funcref_ptr);

let trap_code = match check {
// `funcref_ptr` is checked at runtime that its type matches,
Expand Down Expand Up @@ -1377,6 +1381,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {

fn check_indirect_call_type_signature(
&mut self,
features: &WasmFeatures,
table_index: TableIndex,
ty_index: TypeIndex,
funcref_ptr: ir::Value,
Expand Down Expand Up @@ -1412,33 +1417,40 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
};
}

// Otherwise if the types don't match then either (a) this is a
// null pointer or (b) it's a pointer with the wrong type.
// Figure out which and trap here.
//
// If it's possible to have a null here then try to load the
// type information. If that fails due to the function being a
// null pointer, then this was a call to null. Otherwise if it
// succeeds then we know it won't match, so trap anyway.
if table.table.ref_type.nullable {
if self.env.signals_based_traps() {
let mem_flags = ir::MemFlags::trusted().with_readonly();
self.builder.ins().load(
sig_id_type,
mem_flags.with_trap_code(Some(crate::TRAP_INDIRECT_CALL_TO_NULL)),
funcref_ptr,
i32::from(self.env.offsets.ptr.vm_func_ref_type_index()),
);
} else {
self.env.trapz(
self.builder,
funcref_ptr,
crate::TRAP_INDIRECT_CALL_TO_NULL,
);
if features.gc() {
// If we are in the Wasm GC world, then we need to perform
// an actual subtype check at runtime. Fall through to below
// to do that.
} else {
// Otherwise if the types don't match then either (a) this
// is a null pointer or (b) it's a pointer with the wrong
// type. Figure out which and trap here.
//
// If it's possible to have a null here then try to load the
// type information. If that fails due to the function being
// a null pointer, then this was a call to null. Otherwise
// if it succeeds then we know it won't match, so trap
// anyway.
if table.table.ref_type.nullable {
if self.env.signals_based_traps() {
let mem_flags = ir::MemFlags::trusted().with_readonly();
self.builder.ins().load(
sig_id_type,
mem_flags.with_trap_code(Some(crate::TRAP_INDIRECT_CALL_TO_NULL)),
funcref_ptr,
i32::from(self.env.offsets.ptr.vm_func_ref_type_index()),
);
} else {
self.env.trapz(
self.builder,
funcref_ptr,
crate::TRAP_INDIRECT_CALL_TO_NULL,
);
}
}
self.env.trap(self.builder, crate::TRAP_BAD_SIGNATURE);
return CheckIndirectCallTypeSignature::StaticTrap;
}
self.env.trap(self.builder, crate::TRAP_BAD_SIGNATURE);
return CheckIndirectCallTypeSignature::StaticTrap;
}

// Tables of `nofunc` can only be inhabited by null, so go ahead and
Expand Down Expand Up @@ -1494,12 +1506,25 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> {
self.env
.load_funcref_type_index(&mut self.builder.cursor(), mem_flags, funcref_ptr);

// Check that they match.
let cmp = self
.builder
.ins()
.icmp(IntCC::Equal, callee_sig_id, caller_sig_id);
self.env.trapz(self.builder, cmp, crate::TRAP_BAD_SIGNATURE);
// Check that they match: in the case of Wasm GC, this means doing a
// full subtype check. Otherwise, we do a simple equality check.
let matches = if features.gc() {
#[cfg(feature = "gc")]
{
self.env
.is_subtype(self.builder, callee_sig_id, caller_sig_id)
}
#[cfg(not(feature = "gc"))]
{
unreachable!()
}
} else {
self.builder
.ins()
.icmp(IntCC::Equal, callee_sig_id, caller_sig_id)
};
self.env
.trapz(self.builder, matches, crate::TRAP_BAD_SIGNATURE);
CheckIndirectCallTypeSignature::Runtime
}

Expand Down Expand Up @@ -2701,13 +2726,21 @@ impl<'module_environment> crate::translate::FuncEnvironment
fn translate_call_indirect(
&mut self,
builder: &mut FunctionBuilder,
features: &WasmFeatures,
table_index: TableIndex,
ty_index: TypeIndex,
sig_ref: ir::SigRef,
callee: ir::Value,
call_args: &[ir::Value],
) -> WasmResult<Option<ir::Inst>> {
Call::new(builder, self).indirect_call(table_index, ty_index, sig_ref, callee, call_args)
Call::new(builder, self).indirect_call(
features,
table_index,
ty_index,
sig_ref,
callee,
call_args,
)
}

fn translate_call(
Expand Down Expand Up @@ -2744,13 +2777,15 @@ impl<'module_environment> crate::translate::FuncEnvironment
fn translate_return_call_indirect(
&mut self,
builder: &mut FunctionBuilder,
features: &WasmFeatures,
table_index: TableIndex,
ty_index: TypeIndex,
sig_ref: ir::SigRef,
callee: ir::Value,
call_args: &[ir::Value],
) -> WasmResult<()> {
Call::new_tail(builder, self).indirect_call(
features,
table_index,
ty_index,
sig_ref,
Expand Down
2 changes: 2 additions & 0 deletions crates/cranelift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub const TRAP_CONTINUATION_ALREADY_CONSUMED: TrapCode =
TrapCode::unwrap_user(Trap::ContinuationAlreadyConsumed as u8 + TRAP_OFFSET);
pub const TRAP_DEBUG_ASSERTION: TrapCode =
TrapCode::unwrap_user(Trap::DebugAssertion as u8 + TRAP_OFFSET);
pub const TRAP_CAST_FAILURE: TrapCode =
TrapCode::unwrap_user(Trap::CastFailure as u8 + TRAP_OFFSET);

/// Creates a new cranelift `Signature` with no wasm params/results for the
/// given calling convention.
Expand Down
Loading

0 comments on commit 0da9592

Please sign in to comment.