void EventHook::onFunctionSuspendE(ActRec* suspending, const ActRec* resumableAR) { // When we're suspending an eagerly executing resumable, we've already // teleported the ActRec from suspending over to resumableAR, so we need to // make sure the unwinder knows not to touch the locals, $this, or // VarEnv/ExtraArgs. suspending->setThisOrClassAllowNull(nullptr); suspending->setLocalsDecRefd(); suspending->setVarEnv(nullptr); try { ssize_t flags = CheckSurprise(); onFunctionExit(resumableAR, nullptr, nullptr, flags); if ((flags & RequestInjectionData::AsyncEventHookFlag) && resumableAR->func()->isAsyncFunction()) { assert(resumableAR->resumed()); auto const afwh = frame_afwh(resumableAR); auto const session = AsioSession::Get(); if (session->hasOnResumableCreateCallback()) { session->onResumableCreate(afwh, afwh->getChild()); } } } catch (...) { auto const resumableObj = [&]() -> ObjectData* { if (resumableAR->func()->isAsyncFunction()) { return frame_afwh(resumableAR); } assert(resumableAR->func()->isGenerator()); return frame_base_generator(resumableAR); }(); decRefObj(resumableObj); throw; } }
void EventHook::onFunctionSuspend(const ActRec* ar, bool suspendingResumed) { // TODO(#2329497) can't CheckSurprise() yet, unwinder frees suspended locals ssize_t flags = GetConditionFlags(); onFunctionExit(ar, nullptr, nullptr, flags); // Async profiler if ((flags & RequestInjectionData::AsyncEventHookFlag) && ar->func()->isAsyncFunction()) { assert(ar->resumed()); auto afwh = frame_afwh(ar); auto session = AsioSession::Get(); // Blocking await @ eager execution => AsyncFunctionWaitHandle created. if (!suspendingResumed && session->hasOnResumableCreateCallback()) { session->onResumableCreate(afwh, afwh->getChild()); } // Blocking await @ resumed execution => AsyncFunctionWaitHandle awaiting. if (suspendingResumed && session->hasOnResumableAwaitCallback()) { session->onResumableAwait(afwh, afwh->getChild()); } } }