c_AsyncFunctionWaitHandle::~c_AsyncFunctionWaitHandle() { if (LIKELY(isFinished())) { return; } assert(!isRunning()); frame_free_locals_inl_no_hook(actRec(), actRec()->func()->numLocals()); decRefObj(m_children[0].getChild()); }
AsyncGenerator::~AsyncGenerator() { if (LIKELY(getState() == State::Done)) { return; } assert(!isRunning()); // Free locals, but don't trigger the EventHook for FunctionReturn since // the generator has already been exited. We don't want redundant calls. ActRec* ar = actRec(); frame_free_locals_inl_no_hook(ar, ar->m_func->numLocals()); }
bool EventHook::RunInterceptHandler(ActRec* ar) { const Func* func = ar->m_func; if (LIKELY(func->maybeIntercepted() == 0)) return true; Variant *h = get_intercept_handler(func->fullNameRef(), &func->maybeIntercepted()); if (!h) return true; Transl::VMRegAnchor _; PC savePc = g_vmContext->m_pc; Offset pcOff; ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff); assert(outer); g_vmContext->m_fp = outer; g_vmContext->m_pc = outer->m_func->unit()->at(pcOff); try { Variant doneFlag = true; Variant obj = ar->hasThis() ? Variant(Object(ar->getThis())) : uninit_null(); Array intArgs = CREATE_VECTOR5(ar->m_func->fullNameRef(), obj, get_frame_args_with_ref(ar), h->asCArrRef()[1], ref(doneFlag)); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { frame_free_locals_inl_no_hook(ar, ar->m_func->numLocals()); Stack& stack = g_vmContext->getStack(); stack.top() = (Cell*)(ar + 1); tvDup(ret.asTypedValue(), stack.allocTV()); return false; } g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; } catch (...) { g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; g_vmContext->m_stack.top() = Stack::frameStackBase(ar); throw; } return true; }