@@ -745,6 +745,75 @@ impl ComponentInstance {
745
745
_ = ( src_idx, src, dst) ;
746
746
todo ! ( )
747
747
}
748
+
749
+ #[ cfg( feature = "threads" ) ]
750
+ pub ( crate ) fn thread_spawn_indirect (
751
+ & mut self ,
752
+ table : u32 ,
753
+ element : u32 ,
754
+ _context : u32 ,
755
+ ) -> Result < u32 > {
756
+ use crate :: vm:: { Instance , TableElement } ;
757
+ use crate :: { Func , ValType } ;
758
+ use core:: iter;
759
+
760
+ // Retrieve the table referenced by the canonical builtin (i.e.,
761
+ // `table`). By validation this is guaranteed to be a `shared funcref`
762
+ // table.
763
+ let VMTable { vmctx, from } = self . runtime_table ( RuntimeTableIndex :: from_u32 ( table) ) ;
764
+ let element = u64:: from ( element) ;
765
+ let table = unsafe {
766
+ Instance :: from_vmctx ( vmctx. as_non_null ( ) , |handle| {
767
+ let idx = handle. table_index ( from. as_non_null ( ) . as_ref ( ) ) ;
768
+ handle
769
+ . get_defined_table_with_lazy_init ( idx, iter:: once ( element) )
770
+ . as_ref ( )
771
+ } )
772
+ } ;
773
+ let table = * table
774
+ . as_ref ( )
775
+ . ok_or_else ( || anyhow ! ( "failed to get table for thread spawn indirect" ) ) ?;
776
+
777
+ // Retrieve the actual function reference from the table. The CM
778
+ // specification tells us to trap if
779
+ let element = table. get ( None , element) ;
780
+ let element = element
781
+ . ok_or_else ( || anyhow ! ( "failed to get table element for thread spawn indirect" ) ) ?;
782
+ match element {
783
+ TableElement :: FuncRef ( Some ( func) ) => {
784
+ // Build a `Func` from the function reference--this is
785
+ // incorrect, but temporarily necessary! In the future this will
786
+ // require additional infrastructure to build a `SharedFunc` or
787
+ // some more-correct type. It is unclear yet how to do this from
788
+ // a `Store` (e.g., `SharedStore`) but this use here--never
789
+ // actually invoked!--makes the problem concrete (TODO).
790
+ let store = unsafe { ( * self . store ( ) ) . store_opaque_mut ( ) } ;
791
+ let func = unsafe { Func :: from_vm_func_ref ( store, func) } ;
792
+
793
+ // Check the function signature matches what we expect.
794
+ // Currently, this is temporarily set to `[i32] -> []` but in
795
+ // the future, with some additional plumbing of the core type
796
+ // index, we must check that the function signature matches
797
+ // that (TODO).
798
+ let ty = func. load_ty ( store) ;
799
+ if ty. params ( ) . len ( ) != 1
800
+ || !matches ! ( ty. params( ) . nth( 0 ) . unwrap( ) , ValType :: I32 )
801
+ || ty. results ( ) . len ( ) != 0
802
+ {
803
+ bail ! ( "thread start function signature is invalid" ) ;
804
+ }
805
+
806
+ // At this point we should spawn the thread with the function
807
+ // provided, returning 0 on success, -1 otherwise. None of that
808
+ // infrastructure is built yet so we crash instead (TODO).
809
+ unimplemented ! ( "`thread.spawn_indirect` is not implemented yet" ) ;
810
+ }
811
+ TableElement :: FuncRef ( None ) => {
812
+ bail ! ( "thread start function is not present in the table" )
813
+ }
814
+ _ => bail ! ( "thread start element is not a function reference" ) ,
815
+ }
816
+ }
748
817
}
749
818
750
819
impl VMComponentContext {
0 commit comments