static Variant reduce_func(CVarRef result, CVarRef operand, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant ret; TypedValue args[2]; tvDup(*result.asTypedValue(), args[0]); tvDup(*operand.asTypedValue(), args[1]); g_vmContext->invokeFuncFew(ret.asTypedValue(), *ctx, 2, args); return ret; }
static void walk_func(VRefParam value, CVarRef key, CVarRef userdata, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant sink; TypedValue args[3]; tvDup(*value->asTypedValue(), args[0]); tvDup(*key.asTypedValue(), args[1]); tvDup(*userdata.asTypedValue(), args[2]); g_vmContext->invokeFuncFew(sink.asTypedValue(), *ctx, 3, args); }
int init_closure(ActRec* ar, TypedValue* sp) { c_Closure* closure = static_cast<c_Closure*>(ar->getThis()); // Swap in the $this or late bound class or null if it is ony from a plain // function or pseudomain ar->setThisOrClassAllowNull(closure->getThisOrClass()); if (ar->hasThis()) { ar->getThis()->incRefCount(); } // Put in the correct context ar->m_func = closure->getInvokeFunc(); // The closure is the first local. // Similar to tvWriteObject() but we don't incref because it used to be $this // and now it is a local, so they cancel out TypedValue* firstLocal = --sp; firstLocal->m_type = KindOfObject; firstLocal->m_data.pobj = closure; // Copy in all the use vars TypedValue* prop = closure->getUseVars(); int n = closure->getNumUseVars(); for (int i=0; i < n; i++) { tvDup(*prop++, *--sp); } return n + 1; }
static bool filter_func(CVarRef value, const void *data) { CallCtx* ctx = (CallCtx*)data; Variant ret; TypedValue args[1]; tvDup(*value.asTypedValue(), args[0]); g_vmContext->invokeFuncFew((TypedValue*)&ret, *ctx, 1, args); return ret.toBoolean(); }
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; Variant doneFlag = true; Variant called_on; if (ar->hasThis()) { called_on = Variant(ar->getThis()); } else if (ar->hasClass()) { // For static methods, give handler the name of called class called_on = Variant(const_cast<StringData*>(ar->getClass()->name())); } Array intArgs = CREATE_VECTOR5(ar->m_func->fullNameRef(), called_on, get_frame_args_with_ref(ar), h->asCArrRef()[1], ref(doneFlag)); Variant ret = vm_call_user_func(h->asCArrRef()[0], intArgs); if (doneFlag.toBoolean()) { Offset pcOff; ActRec* outer = g_vmContext->getPrevVMState(ar, &pcOff); assert(outer); frame_free_locals_inl_no_hook<true>(ar, ar->m_func->numLocals()); Stack& stack = g_vmContext->getStack(); stack.top() = (Cell*)(ar + 1); tvDup(ret.asTypedValue(), stack.allocTV()); g_vmContext->m_fp = outer; g_vmContext->m_pc = outer->m_func->unit()->at(pcOff); return false; } g_vmContext->m_fp = ar; g_vmContext->m_pc = savePc; return true; }
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; }
ObjectData* c_Closure::clone() { auto const cls = getVMClass(); auto ret = c_Closure::fromObject(closureInstanceCtorRepoAuth(cls)); ret->hdr()->ctx = hdr()->ctx; if (auto t = getThis()) { t->incRefCount(); } auto src = getUseVars(); auto dest = ret->getUseVars(); auto const nProps = cls->numDeclProperties(); auto const stop = src + nProps; for (; src != stop; ++src, ++dest) { tvDup(*src, *dest); } return ret; }