@@ -3,7 +3,7 @@ use super::{
33 Event , GlobalErrorContextRefCount , LocalErrorContextRefCount , StateTable , Waitable ,
44 WaitableCommon , WaitableState ,
55} ;
6- use crate :: component:: concurrent:: ConcurrentState ;
6+ use crate :: component:: concurrent:: { ConcurrentState , HostTaskOutput , tls } ;
77use crate :: component:: func:: { self , LiftContext , LowerContext , Options } ;
88use crate :: component:: matching:: InstanceType ;
99use crate :: component:: values:: { ErrorContextAny , FutureAny , StreamAny } ;
@@ -1746,34 +1746,61 @@ impl Instance {
17461746 }
17471747
17481748 let read_handle = transmit. read_handle ;
1749- let ( result, code) = accept_reader :: < T , B , U > (
1750- store. as_context_mut ( ) ,
1751- self ,
1752- Reader :: Guest {
1753- options : & options,
1754- ty,
1755- address,
1756- count,
1757- } ,
1758- buffer,
1759- kind,
1760- ) ?;
1761-
1762- self . concurrent_state_mut ( store. 0 ) . set_event (
1763- read_handle. rep ( ) ,
1764- match ty {
1765- TableIndex :: Future ( ty) => Event :: FutureRead {
1766- code,
1767- pending : Some ( ( ty, handle) ) ,
1749+ let accept = move |mut store : StoreContextMut < U > | {
1750+ let ( result, code) = accept_reader :: < T , B , U > (
1751+ store. as_context_mut ( ) ,
1752+ self ,
1753+ Reader :: Guest {
1754+ options : & options,
1755+ ty,
1756+ address,
1757+ count,
17681758 } ,
1769- TableIndex :: Stream ( ty) => Event :: StreamRead {
1770- code,
1771- pending : Some ( ( ty, handle) ) ,
1759+ buffer,
1760+ kind,
1761+ ) ?;
1762+
1763+ self . concurrent_state_mut ( store. 0 ) . set_event (
1764+ read_handle. rep ( ) ,
1765+ match ty {
1766+ TableIndex :: Future ( ty) => Event :: FutureRead {
1767+ code,
1768+ pending : Some ( ( ty, handle) ) ,
1769+ } ,
1770+ TableIndex :: Stream ( ty) => Event :: StreamRead {
1771+ code,
1772+ pending : Some ( ( ty, handle) ) ,
1773+ } ,
17721774 } ,
1773- } ,
1774- ) ?;
1775+ ) ?;
17751776
1776- Ok ( result)
1777+ anyhow:: Ok ( result)
1778+ } ;
1779+
1780+ if
1781+ // TODO: Check if payload is "flat"
1782+ false {
1783+ // Optimize flat payloads (i.e. those which do not require
1784+ // calling the guest's realloc function) by lowering
1785+ // directly instead of using a oneshot::channel and
1786+ // background task.
1787+ Ok ( accept ( store) ?)
1788+ } else {
1789+ // Otherwise, for payloads which may require a realloc call,
1790+ // use a oneshot::channel and background task. This is
1791+ // necessary because calling the guest while there are host
1792+ // embedder frames on the stack is unsound.
1793+ let ( tx, rx) = oneshot:: channel ( ) ;
1794+ let token = StoreToken :: new ( store. as_context_mut ( ) ) ;
1795+ self . concurrent_state_mut ( store. 0 )
1796+ . push_future ( Box :: pin ( async move {
1797+ HostTaskOutput :: Result ( tls:: get ( |store| {
1798+ _ = tx. send ( accept ( token. as_context_mut ( store) ) ?) ;
1799+ Ok ( ( ) )
1800+ } ) )
1801+ } ) ) ;
1802+ Err ( rx)
1803+ }
17771804 }
17781805
17791806 ReadState :: HostReady { accept } => {
0 commit comments