Skip to content

Commit 7e02b23

Browse files
committed
add memory.{size,grow} execution handlers
1 parent 150080d commit 7e02b23

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

crates/wasmi/src/engine/executor/handler/dispatch.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ pub fn op_code_to_handler(code: OpCode) -> Handler {
366366
OpCode::CallInternal => exec::call_internal,
367367
OpCode::CallImported => exec::call_imported,
368368
OpCode::CallIndirect => exec::call_indirect,
369+
// memory
370+
OpCode::MemorySize => exec::memory_size,
371+
OpCode::MemoryGrow => exec::memory_grow,
369372
// unconditional branch
370373
OpCode::Branch => exec::branch,
371374
// unary

crates/wasmi/src/engine/executor/handler/exec.rs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,22 @@ use crate::{
1212
utils::{
1313
exec_copy_span_asc,
1414
exec_copy_span_des,
15+
extract_mem0,
1516
resolve_global,
1617
resolve_indirect_func,
18+
resolve_memory,
1719
set_global,
1820
update_instance,
1921
},
2022
},
2123
EngineFunc,
2224
},
23-
errors::FuelError,
25+
errors::{FuelError, MemoryError},
2426
func::FuncEntity,
2527
instance::InstanceEntity,
2628
ir,
2729
ir::{Slot, SlotSpan},
30+
TrapCode,
2831
};
2932
use core::ptr::NonNull;
3033

@@ -355,6 +358,79 @@ handler_return! {
355358
fn return64(Return64) = identity::<u64>;
356359
}
357360

361+
pub fn memory_size(
362+
state: &mut VmState,
363+
ip: Ip,
364+
sp: Sp,
365+
mem0: Mem0Ptr,
366+
mem0_len: Mem0Len,
367+
instance: NonNull<InstanceEntity>,
368+
) -> Done {
369+
let (ip, crate::ir::decode::MemorySize { memory, result }) = unsafe { decode_op(ip) };
370+
let memory = resolve_memory(instance, memory);
371+
let size = state.store.inner().resolve_memory(&memory).size();
372+
set_value(sp, result, size);
373+
dispatch!(state, ip, sp, mem0, mem0_len, instance)
374+
}
375+
376+
pub fn memory_grow(
377+
state: &mut VmState,
378+
ip: Ip,
379+
sp: Sp,
380+
mem0: Mem0Ptr,
381+
mem0_len: Mem0Len,
382+
instance: NonNull<InstanceEntity>,
383+
) -> Done {
384+
let (
385+
ip,
386+
crate::ir::decode::MemoryGrow {
387+
memory,
388+
result,
389+
delta,
390+
},
391+
) = unsafe { decode_op(ip) };
392+
let delta: u64 = get_value(delta, sp);
393+
let memref = resolve_memory(instance, memory);
394+
let mut mem0 = mem0;
395+
let mut mem0_len = mem0_len;
396+
let return_value = match state.store.grow_memory(&memref, delta) {
397+
Ok(return_value) => {
398+
// The `memory.grow` operation might have invalidated the cached
399+
// linear memory so we need to reset it in order for the cache to
400+
// reload in case it is used again.
401+
if memory.is_default() {
402+
(mem0, mem0_len) = extract_mem0(state.store, instance);
403+
}
404+
return_value
405+
}
406+
Err(MemoryError::OutOfBoundsGrowth | MemoryError::OutOfSystemMemory) => {
407+
let memory_ty = state.store.inner().resolve_memory(&memref).ty();
408+
match memory_ty.is_64() {
409+
true => u64::MAX,
410+
false => u64::from(u32::MAX),
411+
}
412+
}
413+
Err(MemoryError::OutOfFuel { required_fuel }) => {
414+
state.done(DoneReason::OutOfFuel { required_fuel });
415+
return exec_break!(ip, sp, mem0, mem0_len, instance);
416+
}
417+
Err(MemoryError::ResourceLimiterDeniedAllocation) => {
418+
break_with_trap!(
419+
TrapCode::GrowthOperationLimited,
420+
state,
421+
ip,
422+
sp,
423+
mem0,
424+
mem0_len,
425+
instance
426+
)
427+
}
428+
Err(error) => panic!("encountered an unexpected error: {error}"),
429+
};
430+
set_value(sp, result, return_value);
431+
dispatch!(state, ip, sp, mem0, mem0_len, instance)
432+
}
433+
358434
macro_rules! handler_unary {
359435
( $( fn $handler:ident($op:ident) = $eval:expr );* $(;)? ) => {
360436
$(

crates/wasmi/src/engine/executor/handler/utils.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
Error,
99
Func,
1010
Global,
11+
Memory,
1112
Ref,
1213
Table,
1314
TrapCode,
@@ -159,7 +160,10 @@ pub fn exec_copy_span_des(sp: Sp, dst: SlotSpan, src: SlotSpan, len: u16) {
159160
}
160161
}
161162

162-
pub fn extract_mem0(store: &mut PrunedStore, instance: NonNull<InstanceEntity>) -> (Mem0Ptr, Mem0Len) {
163+
pub fn extract_mem0(
164+
store: &mut PrunedStore,
165+
instance: NonNull<InstanceEntity>,
166+
) -> (Mem0Ptr, Mem0Len) {
163167
let instance = unsafe { instance.as_ref() };
164168
let Some(memory) = instance.get_memory(0) else {
165169
return (Mem0Ptr::from([].as_mut_ptr()), Mem0Len::from(0));
@@ -213,6 +217,14 @@ pub fn resolve_global(instance: NonNull<InstanceEntity>, global: index::Global)
213217
global
214218
}
215219

220+
pub fn resolve_memory(instance: NonNull<InstanceEntity>, memory: index::Memory) -> Memory {
221+
let inst = unsafe { instance.as_ref() };
222+
let Some(memory) = inst.get_memory(u32::from(u16::from(memory))) else {
223+
unreachable!("missing memory at: {}", u16::from(memory))
224+
};
225+
memory
226+
}
227+
216228
pub fn resolve_table(instance: NonNull<InstanceEntity>, table: index::Table) -> Table {
217229
let inst = unsafe { instance.as_ref() };
218230
let Some(table) = inst.get_table(u32::from(table)) else {

0 commit comments

Comments
 (0)