HOT_FUNC_VM int64_t decodeCufIterHelper(Iter* it, TypedValue func) { DECLARE_FRAME_POINTER(framePtr); ObjectData* obj = nullptr; HPHP::Class* cls = nullptr; StringData* invName = nullptr; auto ar = (ActRec*)framePtr->m_savedRbp; if (LIKELY(ar->m_func->isBuiltin())) { ar = g_vmContext->getOuterVMFrame(ar); } const Func* f = vm_decode_function(tvAsVariant(&func), ar, false, obj, cls, invName, false); if (UNLIKELY(!f)) return false; CufIter &cit = it->cuf(); cit.setFunc(f); if (obj) { cit.setCtx(obj); obj->incRefCount(); } else { cit.setCtx(cls); } cit.setName(invName); return true; }
/* * Helper method from converting between a PHP function and a CufIter. */ static bool vm_decode_function_cufiter(const Variant& function, SmartCufIterPtr& cufIter) { ObjectData* obj = nullptr; HPHP::Class* cls = nullptr; HPHP::JIT::CallerFrame cf; StringData* invName = nullptr; // Don't warn here, let the caller decide what to do if the func is nullptr. const HPHP::Func* func = vm_decode_function(function, cf(), false, obj, cls, invName, false); if (func == nullptr) { return false; } cufIter = smart::make_unique<CufIter>(); cufIter->setFunc(func); cufIter->setName(invName); if (obj) { cufIter->setCtx(obj); obj->incRefCount(); } else { cufIter->setCtx(cls); } return true; }
Variant::Variant(const Object& v) { m_type = KindOfObject; ObjectData *o = v.get(); if (o) { m_data.pobj = o; o->incRefCount(); } else { m_type = KindOfNull; } }
Variant do_callback(CVarRef cb, CArrRef args) { ASSERT(!m_exception); try { return f_call_user_func_array(cb, args); } catch (Object &e) { ObjectData *od = e.get(); od->incRefCount(); m_exception = od; m_phpException = true; } catch (Exception &e) { m_exception = e.clone(); m_phpException = false; } return null; }
static ObjectData * create_object(const StaticString * className, Array params) { TypedValue ret; Class * cls = Unit::loadClass(className -> get()); ObjectData * obj = ObjectData::newInstance(cls); obj->incRefCount(); g_context->invokeFunc( &ret, cls->getCtor(), params, obj ); return obj; }
Variant do_callback(CVarRef cb, CArrRef args) { assert(!m_exception); try { return vm_call_user_func(cb, args); } catch (Object &e) { ObjectData *od = e.get(); od->incRefCount(); m_exception = od; m_phpException = true; } catch (Exception &e) { m_exception = e.clone(); m_phpException = false; } return uninit_null(); }
int hphp_ffi_exportVariant(CVarRef v, void** result) { switch (v.getType()) { case KindOfNull: return 0; case KindOfBoolean: *result = (void*)v.toBoolean(); return 1; case KindOfByte: case KindOfInt16: case KindOfInt32: case KindOfInt64: { *result = (void*)v.toInt64(); return 2; } case KindOfDouble: { union { double d; void* p; } u; u.d = v.toDouble(); *result = u.p; return 3; } case LiteralString: *result = (void*)v.getLiteralString(); return 4; case KindOfString: { StringData *sd = v.getStringData(); sd->incRefCount(); *result = (void*)sd; return 5; } case KindOfArray: { ArrayData *ad = v.getArrayData(); ad->incRefCount(); *result = (void*)ad; return 6; } case KindOfObject: { ObjectData *od = v.getObjectData(); od->incRefCount(); *result = (void*)od; return 7; } default: ASSERT(false); return 0; } }
void loadArrayFunctionContext(ArrayData* arr, ActRec* preLiveAR, ActRec* fp) { ObjectData* inst = nullptr; HPHP::Class* cls = nullptr; StringData* invName = nullptr; try { // if size != 2, throws exception // if the first element of the array is a string classname, will autoload it const Func* func = vm_decode_function( Variant(arr), fp, /* forwarding */ false, inst, cls, invName, /* warn */ false ); if (UNLIKELY(func == nullptr)) { raise_error("Invalid callable (array)"); } assert(cls != nullptr); // array should resolve only to a method preLiveAR->m_func = func; if (inst) { inst->incRefCount(); preLiveAR->setThis(inst); } else { preLiveAR->setClass(cls); } if (UNLIKELY(invName != nullptr)) { preLiveAR->setInvName(invName); } } catch (...) { // This is extreme shadiness. See the comments of // arPreliveOverwriteCells() for more info on how this code gets the // unwinder to restore the pre-FPush state. auto firstActRecCell = arPreliveOverwriteCells(preLiveAR); firstActRecCell->m_type = KindOfArray; firstActRecCell->m_data.parr = arr; throw; } }
ObjectData* newPairHelper() { ObjectData *obj = NEWOBJ(c_Pair)(); obj->incRefCount(); TRACE(2, "newPairHelper: capacity 2\n"); return obj; }
Object c_Closure::t_bindto(const Variant& newthis, const Variant& scope) { if (RuntimeOption::RepoAuthoritative && RuntimeOption::EvalAllowScopeBinding) { raise_warning("Closure binding is not supported in RepoAuthoritative mode"); return Object{}; } auto const cls = getVMClass(); auto const invoke = cls->getCachedInvoke(); ObjectData* od = nullptr; if (newthis.isObject()) { if (invoke->isStatic()) { raise_warning("Cannot bind an instance to a static closure"); } else { od = newthis.getObjectData(); } } else if (!newthis.isNull()) { raise_warning("Closure::bindto() expects parameter 1 to be object"); return Object{}; } auto const curscope = invoke->cls(); auto newscope = curscope; if (scope.isObject()) { newscope = scope.getObjectData()->getVMClass(); } else if (scope.isString()) { auto const className = scope.getStringData(); if (!className->equal(s_static.get())) { newscope = Unit::loadClass(className); if (!newscope) { raise_warning("Class '%s' not found", className->data()); return Object{}; } } } else if (scope.isNull()) { newscope = nullptr; } else { raise_warning("Closure::bindto() expects parameter 2 " "to be string or object"); return Object{}; } if (od && !newscope) { // Bound closures should be scoped. If no scope is specified, scope it to // the Closure class. newscope = static_cast<Class*>(c_Closure::classof()); } bool thisNotOfCtx = od && !od->getVMClass()->classof(newscope); if (!RuntimeOption::EvalAllowScopeBinding) { if (newscope != curscope) { raise_warning("Re-binding closure scopes is disabled"); return Object{}; } if (thisNotOfCtx) { raise_warning("Binding to objects not subclassed from closure " "context is disabled"); return Object{}; } } c_Closure* clone = Clone(this); clone->setClass(nullptr); Attr curattrs = invoke->attrs(); Attr newattrs = static_cast<Attr>(curattrs & ~AttrHasForeignThis); if (od) { od->incRefCount(); clone->setThis(od); if (thisNotOfCtx) { // If the bound $this is not a subclass of the context class, then we // have to pessimize translation. newattrs |= AttrHasForeignThis; } } else if (newscope) { // If we attach a scope to a function with no bound $this we need to make // the function static. newattrs |= AttrStatic; clone->setClass(newscope); } // If we are changing either the scope or the attributes of the closure, we // need to re-scope its Closure subclass. if (newscope != curscope || newattrs != curattrs) { assert(newattrs != AttrNone); auto newcls = cls->rescope(newscope, newattrs); clone->setVMClass(newcls); } return Object(clone); }
ObjectData* newColHelper(uint32_t type, uint32_t size) { ObjectData* obj = newCollectionHelper(type, size); obj->incRefCount(); return obj; }