|
8 | 8 | },
|
9 | 9 | mpk::{self, ProtectionMask},
|
10 | 10 | AsyncWasmCallState, PreviousAsyncWasmCallState, SendSyncPtr, VMFuncRef,
|
11 |
| - VMMemoryDefinition, VMStore, |
| 11 | + VMMemoryDefinition, VMStore, VMStoreRawPtr, |
12 | 12 | },
|
13 | 13 | AsContextMut, Engine, StoreContextMut, ValRaw,
|
14 | 14 | },
|
@@ -1456,6 +1456,51 @@ pub(crate) fn first_poll<T, R: Send + Sync + 'static>(
|
1456 | 1456 | .concurrent_state()
|
1457 | 1457 | .table
|
1458 | 1458 | .push_child(HostTask { caller_instance }, caller)?;
|
| 1459 | + |
| 1460 | + // Here we wrap the future in a `future::poll_fn` to ensure that we restore |
| 1461 | + // and save the `CallContext` for this task before and after polling it, |
| 1462 | + // respectively. This involves unsafe shenanigans in order to smuggle the |
| 1463 | + // store pointer into the wrapping future, alas. |
| 1464 | + |
| 1465 | + fn maybe_push<T>( |
| 1466 | + store: VMStoreRawPtr, |
| 1467 | + call_context: &mut Option<CallContext>, |
| 1468 | + task: TableId<HostTask>, |
| 1469 | + ) { |
| 1470 | + let store = unsafe { StoreContextMut::<T>(&mut *store.0.as_ptr().cast()) }; |
| 1471 | + if let Some(call_context) = call_context.take() { |
| 1472 | + log::trace!("push call context for {}", task.rep()); |
| 1473 | + store.0.component_resource_state().0.push(call_context); |
| 1474 | + } |
| 1475 | + } |
| 1476 | + |
| 1477 | + fn pop<T>( |
| 1478 | + store: VMStoreRawPtr, |
| 1479 | + call_context: &mut Option<CallContext>, |
| 1480 | + task: TableId<HostTask>, |
| 1481 | + ) { |
| 1482 | + log::trace!("pop call context for {}", task.rep()); |
| 1483 | + let store = unsafe { StoreContextMut::<T>(&mut *store.0.as_ptr().cast()) }; |
| 1484 | + *call_context = Some(store.0.component_resource_state().0.pop().unwrap()); |
| 1485 | + } |
| 1486 | + |
| 1487 | + let future = future::poll_fn({ |
| 1488 | + let mut future = Box::pin(future); |
| 1489 | + let store = VMStoreRawPtr(store.0.traitobj()); |
| 1490 | + let mut call_context = None; |
| 1491 | + move |cx| { |
| 1492 | + maybe_push::<T>(store, &mut call_context, task); |
| 1493 | + |
| 1494 | + match future.as_mut().poll(cx) { |
| 1495 | + Poll::Ready(output) => Poll::Ready(output), |
| 1496 | + Poll::Pending => { |
| 1497 | + pop::<T>(store, &mut call_context, task); |
| 1498 | + Poll::Pending |
| 1499 | + } |
| 1500 | + } |
| 1501 | + } |
| 1502 | + }); |
| 1503 | + |
1459 | 1504 | log::trace!("new child of {}: {}", caller.rep(), task.rep());
|
1460 | 1505 | let mut future = Box::pin(future.map(move |result| {
|
1461 | 1506 | (
|
|
0 commit comments