Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 25 additions & 31 deletions crates/cranelift/src/alias_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -808,23 +808,6 @@ where
)
}

fn vmctx_store(
&mut self,
cursor: &mut FuncCursor<'_>,
base_flags: ir::MemFlagsData,
vmctx: ir::Value,
offset: u32,
val: ir::Value,
) {
let region = self.vmctx_region(cursor.func, offset);
cursor.ins().store(
base_flags.with_alias_region(Some(region)),
val,
vmctx,
i32::try_from(offset).unwrap(),
);
}

/// Load the `VMContext::magic` field.
pub fn vmctx_magic(&mut self, cursor: &mut FuncCursor<'_>, vmctx: ir::Value) -> ir::Value {
self.vmctx_load(
Expand Down Expand Up @@ -1244,19 +1227,26 @@ impl AliasRegions<VMOffsets<u8>> {
}
}

// The runtime data arrays get one alias region each, keyed by the array's
// start, rather than one region per element: module startup initializes
// every data segment in one function, and a region per element gives a
// module with more than ~32k data segments more distinct `MemFlags` than
// a function can hold (`MemFlagsSetOverflow`).

/// Load the base of the given runtime data out of the `*mut VMContext`.
pub fn vmctx_runtime_data_base(
&mut self,
cursor: &mut FuncCursor<'_>,
vmctx: ir::Value,
runtime_data: RuntimeDataIndex,
) -> ir::Value {
self.vmctx_load(
cursor,
let region = self.vmctx_region(cursor.func, self.offsets.vmctx_runtime_data_bases_begin());
let offset = self.offsets.vmctx_runtime_data_base(runtime_data);
cursor.ins().load(
self.pointer_type,
ir::MemFlagsData::trusted(),
ir::MemFlagsData::trusted().with_alias_region(Some(region)),
vmctx,
self.offsets.vmctx_runtime_data_base(runtime_data),
i32::try_from(offset).unwrap(),
)
}

Expand All @@ -1267,12 +1257,14 @@ impl AliasRegions<VMOffsets<u8>> {
vmctx: ir::Value,
runtime_data: RuntimeDataIndex,
) -> ir::Value {
self.vmctx_load(
cursor,
let region =
self.vmctx_region(cursor.func, self.offsets.vmctx_runtime_data_lengths_begin());
let offset = self.offsets.vmctx_runtime_data_length(runtime_data);
cursor.ins().load(
ir::types::I32,
ir::MemFlagsData::trusted(),
ir::MemFlagsData::trusted().with_alias_region(Some(region)),
vmctx,
self.offsets.vmctx_runtime_data_length(runtime_data),
i32::try_from(offset).unwrap(),
)
}

Expand All @@ -1284,13 +1276,15 @@ impl AliasRegions<VMOffsets<u8>> {
runtime_data: RuntimeDataIndex,
new_length: ir::Value,
) {
self.vmctx_store(
cursor,
ir::MemFlagsData::trusted(),
vmctx,
self.offsets.vmctx_runtime_data_length(runtime_data),
let region =
self.vmctx_region(cursor.func, self.offsets.vmctx_runtime_data_lengths_begin());
let offset = self.offsets.vmctx_runtime_data_length(runtime_data);
cursor.ins().store(
ir::MemFlagsData::trusted().with_alias_region(Some(region)),
new_length,
)
vmctx,
i32::try_from(offset).unwrap(),
);
}
}

Expand Down
21 changes: 21 additions & 0 deletions tests/all/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,27 @@ fn large_add_chain_no_stack_overflow() -> Result<()> {
Ok(())
}

#[test]
#[cfg_attr(miri, ignore)]
fn many_data_segments_without_cow() -> Result<()> {
// Without CoW initialization every data segment is initialized by the
// module startup function, which once gave each segment's base and
// length its own alias region and overflowed the function's `MemFlags`
// past ~32k segments.
let mut config = Config::new();
config.memory_init_cow(false);
let engine = Engine::new(&config)?;
let mut wat = String::from("(module (memory 1)\n");
for i in 0..40_000 {
wat.push_str(&format!("(data (i32.const {}) \"x\")\n", i % 65536));
}
wat.push_str(")");
let module = Module::new(&engine, &wat)?;
let mut store = Store::new(&engine, ());
Instance::new(&mut store, &module, &[])?;
Ok(())
}

#[test]
fn compile_a_component() -> Result<()> {
let engine = Engine::default();
Expand Down
Loading