@@ -5,7 +5,7 @@ use crate::signature::{Signature, ValType};
55use crate :: wasm_memory:: WasmMemory ;
66use crate :: Module ;
77use paste:: paste;
8- use std:: cell:: RefCell ;
8+ use std:: cell:: { RefCell , Cell } ;
99use std:: collections:: HashMap ;
1010use std:: rc:: { Rc , Weak } ;
1111
@@ -244,7 +244,7 @@ impl WasmTable {
244244pub struct WasmGlobal {
245245 pub ty : ValType ,
246246 pub mutable : bool ,
247- pub value : WasmValue ,
247+ pub value : Cell < WasmValue > ,
248248}
249249
250250// --------------- Imports/Exports and Functions ---------------
@@ -419,7 +419,7 @@ impl Instance {
419419 // evaluate constant initializer
420420 let mut cpc = g. initializer_offset ;
421421 let val = Instance :: eval_const ( & module, & mut cpc, & inst. globals ) ?;
422- inst. globals . push ( Rc :: new ( RefCell :: new ( WasmGlobal { ty : g. ty , mutable : g. is_mutable , value : val } ) ) ) ;
422+ inst. globals . push ( Rc :: new ( RefCell :: new ( WasmGlobal { ty : g. ty , mutable : g. is_mutable , value : Cell :: new ( val) } ) ) ) ;
423423 }
424424 }
425425
@@ -578,7 +578,7 @@ impl Instance {
578578 0x42 => { let v: i64 = read_sleb128 ( bytes, pc) ?; stack. push ( WasmValue :: from_i64 ( v) ) ; }
579579 0x43 => { let bits = u32:: from_le_bytes ( bytes[ * pc..* pc+4 ] . try_into ( ) . unwrap ( ) ) ; * pc += 4 ; stack. push ( WasmValue :: from_f32_bits ( bits) ) ; }
580580 0x44 => { let bits = u64:: from_le_bytes ( bytes[ * pc..* pc+8 ] . try_into ( ) . unwrap ( ) ) ; * pc += 8 ; stack. push ( WasmValue :: from_f64_bits ( bits) ) ; }
581- 0x23 => { let gi: u32 = read_leb128 ( bytes, pc) ?; let g = gi as usize ; if g >= globals. len ( ) { return Err ( Error :: Validation ( UNKNOWN_GLOBAL ) ) ; } stack. push ( globals[ g] . borrow ( ) . value ) ; }
581+ 0x23 => { let gi: u32 = read_leb128 ( bytes, pc) ?; let g = gi as usize ; if g >= globals. len ( ) { return Err ( Error :: Validation ( UNKNOWN_GLOBAL ) ) ; } stack. push ( globals[ g] . borrow ( ) . value . get ( ) ) ; }
582582 0x6a => { let b = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; let a = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; stack. push ( WasmValue :: from_u32 ( a. wrapping_add ( b) ) ) ; }
583583 0x6b => { let b = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; let a = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; stack. push ( WasmValue :: from_u32 ( a. wrapping_sub ( b) ) ) ; }
584584 0x6c => { let b = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; let a = stack. pop ( ) . unwrap ( ) . as_u32 ( ) ; stack. push ( WasmValue :: from_u32 ( a. wrapping_mul ( b) ) ) ; }
@@ -685,6 +685,7 @@ impl Instance {
685685 ctrl_bases : & mut Vec < usize >
686686 ) -> Result < ( ) , Error > {
687687 let bytes = & self . module . bytes ;
688+ let mem_opt = self . memory . as_ref ( ) ;
688689
689690 macro_rules! next_op { ( ) => { { let byte = bytes[ pc] ; pc += 1 ; byte } } }
690691 macro_rules! pop_val { ( ) => { {
@@ -891,7 +892,7 @@ impl Instance {
891892 let _align: u32 = read_leb128( bytes, & mut pc) ?;
892893 let offset: u32 = read_leb128( bytes, & mut pc) ?;
893894 let addr = pop_val!( ) . as_u32( ) ;
894- let mem = self . memory . as_ref ( ) . ok_or_else( || Error :: Validation ( UNKNOWN_MEMORY ) ) ?;
895+ let mem = mem_opt . ok_or_else( || Error :: Validation ( UNKNOWN_MEMORY ) ) ?;
895896 let v = mem. borrow( ) . $method( addr, offset) . map_err( |e| Error :: Trap ( e) ) ?;
896897 let val = ( $push) ( v) ;
897898 stack. push( val) ;
@@ -902,7 +903,7 @@ impl Instance {
902903 let raw = pop_val!( ) ;
903904 let addr = pop_val!( ) . as_u32( ) ;
904905 let val = ( $from) ( raw) ;
905- let mem = self . memory . as_ref ( ) . ok_or_else( || Error :: Validation ( UNKNOWN_MEMORY ) ) ?;
906+ let mem = mem_opt . ok_or_else( || Error :: Validation ( UNKNOWN_MEMORY ) ) ?;
906907 mem. borrow_mut( ) . $method( addr, offset, val) . map_err( |e| Error :: Trap ( e) ) ?;
907908 } } }
908909
@@ -912,36 +913,36 @@ impl Instance {
912913 0x00 => return Err ( Error :: Trap ( UNREACHABLE ) ) ,
913914 0x01 | 0xbc | 0xbd | 0xbe | 0xbf => { } // nop and reinterprets (no-op on raw bits)
914915 0x02 => { // block
915- let sig = Signature :: read ( & self . module . types , bytes , & mut pc ) ? ;
916- let block_end = * self . module . block_ends . get ( & pc ) . unwrap ( ) ;
916+ let entry = * self . module . side_table . get ( & ( pc as u32 ) ) . unwrap ( ) ;
917+ pc = entry . body_pc as usize ;
917918 control. push ( ControlFrame {
918- stack_len : stack. len ( ) - sig . params . len ( ) ,
919- dest_pc : block_end ,
920- arity : sig . result . is_some ( ) as u32 ,
921- has_result : sig . result . is_some ( )
919+ stack_len : stack. len ( ) - ( entry . params_len as usize ) ,
920+ dest_pc : entry . end_pc as usize ,
921+ arity : entry . has_result as u32 ,
922+ has_result : entry . has_result
922923 } ) ;
923924 }
924925 0x03 => { // loop
925926 let loop_op_pc = pc - 1 ;
926- let sig = Signature :: read ( & self . module . types , bytes, & mut pc) ?;
927+ let entry = * self . module . side_table . get ( & ( pc as u32 ) ) . unwrap ( ) ;
928+ pc = entry. body_pc as usize ;
927929 control. push ( ControlFrame {
928- stack_len : stack. len ( ) - sig . params . len ( ) ,
930+ stack_len : stack. len ( ) - ( entry . params_len as usize ) ,
929931 dest_pc : loop_op_pc,
930- arity : sig . params . len ( ) as u32 ,
931- has_result : sig . result . is_some ( )
932+ arity : entry . params_len as u32 ,
933+ has_result : entry . has_result
932934 } ) ;
933935 }
934936 0x04 => { // if
935- let sig = Signature :: read ( & self . module . types , bytes , & mut pc ) ? ;
937+ let entry = * self . module . side_table . get ( & ( pc as u32 ) ) . unwrap ( ) ;
936938 let cond = pop_val ! ( ) . as_u32 ( ) ;
937- let if_jump = self . module . if_jumps . get ( & pc) . unwrap ( ) ;
938939 control. push ( ControlFrame {
939- stack_len : stack. len ( ) - sig . params . len ( ) ,
940- dest_pc : if_jump . end_offset ,
941- arity : sig . result . is_some ( ) as u32 ,
942- has_result : sig . result . is_some ( )
940+ stack_len : stack. len ( ) - ( entry . params_len as usize ) ,
941+ dest_pc : entry . end_pc as usize ,
942+ arity : entry . has_result as u32 ,
943+ has_result : entry . has_result
943944 } ) ;
944- if cond == 0 { pc = if_jump . else_offset ; }
945+ pc = if cond == 0 { entry . else_pc as usize } else { entry . body_pc as usize } ;
945946 }
946947 0x05 => { // else
947948 let _ = Instance :: branch ( & mut pc, stack, control, 0 ) ;
@@ -1009,6 +1010,9 @@ impl Instance {
10091010 }
10101011 // Call instructions
10111012 0x10 => { // call
1013+ // direct calls are fully type-checked at validation time; no
1014+ // structural type check is required here. we only use the
1015+ // runtime signature for fast param/result counts to set up frames.
10121016 let fi: u32 = read_leb128 ( bytes, & mut pc) ?;
10131017 let f = & self . functions [ fi as usize ] ;
10141018
@@ -1047,6 +1051,8 @@ impl Instance {
10471051 }
10481052 }
10491053 0x11 => { // call_indirect
1054+ // Indirect calls must enforce params at runtime
1055+ // Here we must parse the indices
10501056 let type_idx: u32 = read_leb128 ( bytes, & mut pc) ?;
10511057 pc += 1 ; // Skip the zero flag
10521058 let elem_idx = match stack. pop ( ) {
@@ -1206,7 +1212,7 @@ impl Instance {
12061212 if gi as usize >= self . globals . len ( ) {
12071213 return Err ( Error :: Trap ( UNKNOWN_GLOBAL ) ) ;
12081214 }
1209- stack. push ( self . globals [ gi as usize ] . borrow ( ) . value ) ;
1215+ stack. push ( self . globals [ gi as usize ] . borrow ( ) . value . get ( ) ) ;
12101216 }
12111217 0x24 => { // global.set
12121218 let gi: u32 = read_leb128 ( bytes, & mut pc) ?;
@@ -1217,7 +1223,7 @@ impl Instance {
12171223 Some ( v) => v,
12181224 None => return Err ( Error :: Trap ( STACK_UNDERFLOW ) )
12191225 } ;
1220- self . globals [ gi as usize ] . borrow_mut ( ) . value = val;
1226+ self . globals [ gi as usize ] . borrow ( ) . value . set ( val) ;
12211227 }
12221228 // Memory instructions - loads
12231229 0x28 => { load ! ( load_u32, |v: u32 | WasmValue :: from_u32( v) ) ; }
0 commit comments