// An Await opcode is used in the codegen for an async function to suspend // execution until the given wait handle is finished. In eager execution, // the state is suspended into a new AsyncFunctionWaitHandle object so that // the execution can continue later. We have just completed an Await, so // the new AsyncFunctionWaitHandle is now available, and it can predict // where execution will resume. void CmdNext::stepAfterAwait() { auto topObj = vmsp()->m_data.pobj; assertx(topObj->instanceof(c_AsyncFunctionWaitHandle::classof())); auto wh = static_cast<c_AsyncFunctionWaitHandle*>(topObj); auto func = wh->actRec()->func(); Offset nextInst = wh->getNextExecutionOffset(); assertx(nextInst != InvalidAbsoluteOffset); m_stepResumableId = wh->actRec(); TRACE(2, "CmdNext: patch for cont step after Await at '%s' offset %d\n", func->fullName()->data(), nextInst); m_stepResumable = StepDestination(func->unit(), nextInst); }
// A AsyncESuspend is used in the codegen for an async function to setup // a Continuation and return a wait handle so execution can continue // later. We have just completed a AsyncESuspend, so the new // Continuation is available, and it can predict where execution will // resume. void CmdNext::stepAfterAsyncESuspend() { auto topObj = g_context->getStack().topTV()->m_data.pobj; assert(topObj->instanceof(c_AsyncFunctionWaitHandle::classof())); auto wh = static_cast<c_AsyncFunctionWaitHandle*>(topObj); auto func = wh->getActRec()->m_func; Offset nextInst = wh->getNextExecutionOffset(); assert(nextInst != InvalidAbsoluteOffset); m_stepContTag = wh->getActRec(); TRACE(2, "CmdNext: patch for cont step after AsyncESuspend at '%s' offset %d\n", func->fullName()->data(), nextInst); m_stepCont = StepDestination(func->unit(), nextInst); }