Skip to content

Commit

Permalink
Use u32 for delta field of Instruction::MemoryGrowBy (#1193)
Browse files Browse the repository at this point in the history
use `u32` for `delta` field of Instruction::MemoryGrowBy
  • Loading branch information
Robbepop authored Sep 24, 2024
1 parent 0b39af8 commit 903bb5c
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 50 deletions.
2 changes: 1 addition & 1 deletion crates/ir/src/for_each_op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5623,7 +5623,7 @@ macro_rules! for_each_op {
MemoryGrowBy {
@result: Reg,
/// The number of pages to add to the memory.
delta: Const16<u32>,
delta: u32,
},

/// Wasm `memory.copy` instruction.
Expand Down
3 changes: 1 addition & 2 deletions crates/wasmi/src/engine/executor/instrs/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,8 @@ impl<'engine> Executor<'engine> {
&mut self,
store: &mut Store<T>,
result: Reg,
delta: Const16<u32>,
delta: u32,
) -> Result<(), Error> {
let delta: u32 = delta.into();
let (store, mut resource_limiter) = store.store_inner_and_resource_limiter_ref();
self.execute_memory_grow_impl(store, result, delta, &mut resource_limiter)
}
Expand Down
8 changes: 8 additions & 0 deletions crates/wasmi/src/engine/translator/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@ impl<T> Provider<T> {
Self::Const(_) => None,
}
}

/// Maps the constant value with `f` if `self` is [`Provider::Const`] and returns the result.
pub fn map_const<U>(self, f: impl FnOnce(T) -> U) -> Provider<U> {
match self {
Provider::Register(reg) => Provider::Register(reg),
Provider::Const(value) => Provider::Const(f(value)),
}
}
}

/// An untyped [`Provider`].
Expand Down
38 changes: 5 additions & 33 deletions crates/wasmi/src/engine/translator/tests/op/memory/memory_grow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn reg() {
}

fn test_imm16(delta: u32) {
assert!(1 <= delta && delta <= u32::from(u16::MAX));
assert!(delta != 0);
let wasm = &format!(
r"
(module
Expand All @@ -35,7 +35,7 @@ fn test_imm16(delta: u32) {
);
TranslationTest::from_wat(wasm)
.expect_func_instrs([
Instruction::memory_grow_by(Reg::from(0), u32imm16(delta)),
Instruction::memory_grow_by(Reg::from(0), delta),
Instruction::memory_index(0),
Instruction::return_reg(Reg::from(0)),
])
Expand All @@ -49,6 +49,9 @@ fn imm16() {
test_imm16(42);
test_imm16(u32::from(u16::MAX) - 1);
test_imm16(u32::from(u16::MAX));
test_imm16(u32::from(u16::MAX) + 1);
test_imm16(u32::MAX - 1);
test_imm16(u32::MAX);
}

#[test]
Expand All @@ -69,34 +72,3 @@ fn imm_zero() {
])
.run();
}

fn test_imm(delta: u32) {
let wasm = &format!(
r"
(module
(memory $m 10)
(func (result i32)
(i32.const {delta})
(memory.grow $m)
)
)",
);
TranslationTest::from_wat(wasm)
.expect_func(
ExpectedFunc::new([
Instruction::memory_grow(Reg::from(0), Reg::from(-1)),
Instruction::memory_index(0),
Instruction::return_reg(Reg::from(0)),
])
.consts([delta]),
)
.run();
}

#[test]
#[cfg_attr(miri, ignore)]
fn imm() {
test_imm(u32::from(u16::MAX) + 1);
test_imm(u32::MAX - 1);
test_imm(u32::MAX);
}
24 changes: 10 additions & 14 deletions crates/wasmi/src/engine/translator/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -998,23 +998,19 @@ impl<'a> VisitOperator<'a> for FuncTranslator {

fn visit_memory_grow(&mut self, mem: u32, _mem_byte: u8) -> Self::Output {
bail_unreachable!(self);
let delta = self.alloc.stack.pop();
let delta = <Provider<Const16<u32>>>::new(delta, &mut self.alloc.stack)?;
let delta = self.alloc.stack.pop().map_const(u32::from);
let memory = index::Memory::from(mem);
let result = self.alloc.stack.push_dynamic()?;
if let Provider::Const(0) = delta {
// Case: growing by 0 pages.
//
// Since `memory.grow` returns the `memory.size` before the
// operation a `memory.grow` with `delta` of 0 can be translated
// as `memory.size` instruction instead.
self.push_fueled_instr(Instruction::memory_size(result, memory), FuelCosts::entity)?;
return Ok(());
}
let instr = match delta {
Provider::Const(delta) if u32::from(delta) == 0 => {
// Case: growing by 0 pages.
//
// Since `memory.grow` returns the `memory.size` before the
// operation a `memory.grow` with `delta` of 0 can be translated
// as `memory.size` instruction instead.
self.push_fueled_instr(
Instruction::memory_size(result, memory),
FuelCosts::entity,
)?;
return Ok(());
}
Provider::Const(delta) => Instruction::memory_grow_by(result, delta),
Provider::Register(delta) => Instruction::memory_grow(result, delta),
};
Expand Down

0 comments on commit 903bb5c

Please sign in to comment.