@@ -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} ;
2932use 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+
358434macro_rules! handler_unary {
359435 ( $( fn $handler: ident( $op: ident) = $eval: expr ) ;* $( ; ) ? ) => {
360436 $(
0 commit comments