@@ -82,7 +82,6 @@ impl Default for Store {
8282///
8383/// Data should only be addressable by the module that owns it
8484/// See <https://webassembly.github.io/spec/core/exec/runtime.html#store>
85- // TODO: Arena allocate these?
8685pub ( crate ) struct StoreData {
8786 pub ( crate ) funcs : Vec < Rc < FunctionInstance > > ,
8887 pub ( crate ) tables : Vec < Rc < RefCell < TableInstance > > > ,
@@ -178,6 +177,7 @@ impl Store {
178177 pub ( crate ) fn init_elements (
179178 & mut self ,
180179 table_addrs : & [ TableAddr ] ,
180+ func_addrs : & [ FuncAddr ] ,
181181 elements : Vec < Element > ,
182182 idx : ModuleInstanceAddr ,
183183 ) -> Result < Box < [ Addr ] > > {
@@ -194,6 +194,8 @@ impl Store {
194194 } )
195195 . collect :: < Result < Vec < _ > > > ( ) ?;
196196
197+ log:: error!( "element kind: {:?}" , element. kind) ;
198+
197199 let items = match element. kind {
198200 // doesn't need to be initialized, can be initialized lazily using the `table.init` instruction
199201 ElementKind :: Passive => Some ( init) ,
@@ -218,7 +220,7 @@ impl Store {
218220 // d. Execute the instruction i32.const n
219221 // e. Execute the instruction table.init tableidx i
220222 if let Some ( table) = self . data . tables . get_mut ( table_addr as usize ) {
221- table. borrow_mut ( ) . init ( offset, & init) ?;
223+ table. borrow_mut ( ) . init ( func_addrs , offset, & init) ?;
222224 } else {
223225 log:: error!( "table {} not found" , table) ;
224226 }
@@ -385,8 +387,6 @@ impl Store {
385387/// See <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances>
386388pub struct FunctionInstance {
387389 pub ( crate ) func : Function ,
388-
389- // TODO: this is important for call_indirect
390390 pub ( crate ) _type_idx : TypeAddr ,
391391 pub ( crate ) _owner : ModuleInstanceAddr , // index into store.module_instances, none for host functions
392392}
@@ -408,52 +408,77 @@ impl FunctionInstance {
408408 }
409409}
410410
411+ #[ derive( Debug , Clone , Copy ) ]
412+ pub ( crate ) enum TableElement {
413+ Uninitialized ,
414+ Initialized ( Addr ) ,
415+ }
416+
417+ impl TableElement {
418+ pub ( crate ) fn addr ( & self ) -> Option < Addr > {
419+ match self {
420+ TableElement :: Uninitialized => None ,
421+ TableElement :: Initialized ( addr) => Some ( * addr) ,
422+ }
423+ }
424+ }
425+
411426/// A WebAssembly Table Instance
412427///
413428/// See <https://webassembly.github.io/spec/core/exec/runtime.html#table-instances>
414429#[ derive( Debug ) ]
415430pub ( crate ) struct TableInstance {
416- pub ( crate ) elements : Vec < Option < Addr > > ,
431+ pub ( crate ) elements : Vec < TableElement > ,
417432 pub ( crate ) kind : TableType ,
418433 pub ( crate ) _owner : ModuleInstanceAddr , // index into store.module_instances
419434}
420435
421436impl TableInstance {
422437 pub ( crate ) fn new ( kind : TableType , owner : ModuleInstanceAddr ) -> Self {
423- Self { elements : vec ! [ None ; kind. size_initial as usize ] , kind, _owner : owner }
438+ Self { elements : vec ! [ TableElement :: Uninitialized ; kind. size_initial as usize ] , kind, _owner : owner }
424439 }
425440
426441 pub ( crate ) fn get_wasm_val ( & self , addr : usize ) -> Result < WasmValue > {
442+ let val = self . get ( addr) ?. addr ( ) ;
443+
427444 Ok ( match self . kind . element_type {
428- ValType :: RefFunc => {
429- self . get ( addr) ?. map ( |v| WasmValue :: RefFunc ( v) ) . unwrap_or ( WasmValue :: RefNull ( ValType :: RefFunc ) )
430- }
445+ ValType :: RefFunc => val. map ( |v| WasmValue :: RefFunc ( v) ) . unwrap_or ( WasmValue :: RefNull ( ValType :: RefFunc ) ) ,
431446 ValType :: RefExtern => {
432- self . get ( addr ) ? . map ( |v| WasmValue :: RefExtern ( v) ) . unwrap_or ( WasmValue :: RefNull ( ValType :: RefExtern ) )
447+ val . map ( |v| WasmValue :: RefExtern ( v) ) . unwrap_or ( WasmValue :: RefNull ( ValType :: RefExtern ) )
433448 }
434449 _ => unimplemented ! ( "unsupported table type: {:?}" , self . kind. element_type) ,
435450 } )
436451 }
437452
438- pub ( crate ) fn get ( & self , addr : usize ) -> Result < Option < Addr > > {
439- self . elements . get ( addr) . copied ( ) . ok_or_else ( || Error :: Trap ( Trap :: UndefinedElement { index : addr } ) )
453+ pub ( crate ) fn get ( & self , addr : usize ) -> Result < & TableElement > {
454+ self . elements . get ( addr) . ok_or_else ( || Error :: Trap ( Trap :: UndefinedElement { index : addr } ) )
440455 }
441456
442- pub ( crate ) fn set ( & mut self , addr : usize , value : Addr ) -> Result < ( ) > {
443- if addr > = self . elements . len ( ) {
444- return Err ( Error :: Other ( format ! ( "table element {} not found" , addr ) ) ) ;
445- }
446-
447- self . elements [ addr ] = Some ( value) ;
457+ pub ( crate ) fn set ( & mut self , table_idx : usize , value : Addr ) -> Result < ( ) > {
458+ let el = self
459+ . elements
460+ . get_mut ( table_idx )
461+ . ok_or_else ( || Error :: Other ( format ! ( "table element {} not found" , table_idx ) ) ) ? ;
462+ * el = TableElement :: Initialized ( value) ;
448463 Ok ( ( ) )
449464 }
450465
451466 pub ( crate ) fn size ( & self ) -> i32 {
452467 self . elements . len ( ) as i32
453468 }
454469
455- pub ( crate ) fn init ( & mut self , offset : i32 , init : & [ Addr ] ) -> Result < ( ) > {
456- let init = init. iter ( ) . map ( |item| Some ( * item) ) . collect :: < Vec < _ > > ( ) ;
470+ pub ( crate ) fn init ( & mut self , func_addrs : & [ u32 ] , offset : i32 , init : & [ Addr ] ) -> Result < ( ) > {
471+ let init = init
472+ . iter ( )
473+ . map ( |item| {
474+ TableElement :: Initialized ( match self . kind . element_type == ValType :: RefFunc {
475+ true => * func_addrs. get ( * item as usize ) . expect (
476+ "error initializing table: function not found. This should have been caught by the validator" ,
477+ ) ,
478+ false => * item,
479+ } )
480+ } )
481+ . collect :: < Vec < _ > > ( ) ;
457482
458483 let offset = offset as usize ;
459484 let end = offset. checked_add ( init. len ( ) ) . ok_or_else ( || {
@@ -465,6 +490,7 @@ impl TableInstance {
465490 }
466491
467492 self . elements [ offset..end] . copy_from_slice ( & init) ;
493+ log:: debug!( "table: {:?}" , self . elements) ;
468494 Ok ( ( ) )
469495 }
470496}
0 commit comments