void c_Closure::init(int numArgs, ActRec* ar, TypedValue* sp) { auto const cls = getVMClass(); auto const invokeFunc = getInvokeFunc(); if (invokeFunc->cls()) { setThisOrClass(ar->getThisOrClass()); if (invokeFunc->isStatic()) { if (!hasClass()) { setClass(getThisUnchecked()->getVMClass()); } } else if (!hasClass()) { getThisUnchecked()->incRefCount(); } } else { hdr()->ctx = nullptr; } /* * Copy the use vars to instance variables, and initialize any * instance properties that are for static locals to KindOfUninit. */ auto const numDeclProperties = cls->numDeclProperties(); assertx(numDeclProperties - numArgs == getInvokeFunc()->numStaticLocals()); auto beforeCurUseVar = sp + numArgs; auto curProperty = getUseVars(); int i = 0; assertx(numArgs <= numDeclProperties); for (; i < numArgs; i++) { // teleport the references in here so we don't incref tvCopy(*--beforeCurUseVar, *curProperty++); } for (; i < numDeclProperties; ++i) { tvWriteUninit(*curProperty++); } }
int init_closure(ActRec* ar, TypedValue* sp) { auto closure = c_Closure::fromObject(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; }
void c_Closure::init(int numArgs, ActRec* ar, TypedValue* sp) { auto const invokeFunc = getVMClass()->lookupMethod(s_uuinvoke.get()); m_ctx = ar->m_this; if (ar->hasThis()) { if (invokeFunc->isStatic()) { // Only set the class for static closures. setClass(ar->getThis()->getVMClass()); } else { ar->getThis()->incRefCount(); } } /* * Copy the use vars to instance variables, and initialize any * instance properties that are for static locals to KindOfUninit. */ auto const numDeclProperties = getVMClass()->numDeclProperties(); assert(numDeclProperties - numArgs == getInvokeFunc()->numStaticLocals()); TypedValue* beforeCurUseVar = sp + numArgs; TypedValue* curProperty = propVec(); int i = 0; assert(numArgs <= numDeclProperties); for (; i < numArgs; i++) { // teleport the references in here so we don't incref tvCopy(*--beforeCurUseVar, *curProperty++); } for (; i < numDeclProperties; ++i) { tvWriteUninit(curProperty++); } }
static Array HHVM_METHOD(Closure, __debugInfo) { auto closure = c_Closure::fromObject(this_); Array ret = Array::Create(); // Serialize 'use' parameters. if (auto useVars = closure->getUseVars()) { Array use; auto cls = this_->getVMClass(); auto propsInfo = cls->declProperties(); auto nProps = cls->numDeclProperties(); for (size_t i = 0; i < nProps; ++i) { auto value = &useVars[i]; use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value)); } if (!use.empty()) { ret.set(s_static, use); } } auto const func = closure->getInvokeFunc(); // Serialize function parameters. if (auto nParams = func->numParams()) { Array params; auto lNames = func->localNames(); for (int i = 0; i < nParams; ++i) { auto str = String::attach( StringData::Make(s_varprefix.get(), lNames[i]) ); bool optional = func->params()[i].phpCode; if (auto mi = func->methInfo()) { optional = optional || mi->parameters[i]->valueText; } params.set(str, optional ? s_optional : s_required); } ret.set(s_parameter, params); } // Serialize 'this' object. if (closure->hasThis()) { ret.set(s_this, Object(closure->getThis())); } return ret; }
Array c_Closure::t___debuginfo() { Array ret = Array::Create(); // Serialize 'use' parameters. if (auto propValues = propVec()) { Array use; auto propsInfo = getVMClass()->declProperties(); for (size_t i = 0; i < getVMClass()->numDeclProperties(); ++i) { auto value = &propValues[i]; use.setWithRef(Variant(StrNR(propsInfo[i].name)), tvAsCVarRef(value)); } if (!use.empty()) { ret.set(s_static, use); } } auto const func = getInvokeFunc(); // Serialize function parameters. if (func->numParams()) { Array params; for (int i = 0; i < func->numParams(); ++i) { auto str = String::attach( StringData::Make(s_varprefix.get(), func->localNames()[i]) ); bool optional = func->params()[i].phpCode; if (auto mi = func->methInfo()) { optional = optional || mi->parameters[i]->valueText; } params.set(str, optional ? s_optional : s_required); } ret.set(s_parameter, params); } // Serialize 'this' object. if (hasThis()) { ret.set(s_this, Object(getThis())); } return ret; }