bool ArrayData::hasInternalReference(PointerSet &vars, bool ds /* = false */) const { if (isSharedMap()) return false; for (ArrayIter iter(this); iter; ++iter) { CVarRef var = iter.secondRef(); if (var.isReferenced()) { Variant *pvar = var.getRefData(); if (vars.find(pvar) != vars.end()) { return true; } vars.insert(pvar); } if (var.isObject()) { ObjectData *pobj = var.getObjectData(); if (vars.find(pobj) != vars.end()) { return true; } vars.insert(pobj); if (ds && pobj->instanceof(SystemLib::s_SerializableClass)) { return true; } if (pobj->hasInternalReference(vars, ds)) { return true; } } else if (var.isArray() && var.getArrayData()->hasInternalReference(vars, ds)) { return true; } } return false; }
ObjectData *Variant::getArrayAccess() const { assert(is(KindOfObject)); ObjectData *obj = getObjectData(); assert(obj); if (!obj->instanceof(SystemLib::s_ArrayAccessClass)) { throw InvalidOperandException("not ArrayAccess objects"); } return obj; }
static Variant f_hphp_get_iterator(VRefParam iterable, bool isMutable) { if (iterable.isArray()) { if (isMutable) { return create_object(s_MutableArrayIterator, CREATE_VECTOR1(ref(iterable))); } return create_object(s_ArrayIterator, CREATE_VECTOR1(iterable)); } if (iterable.isObject()) { ObjectData *obj = iterable.getObjectData(); Variant iterator; while (obj->instanceof(SystemLib::s_IteratorAggregateClass)) { iterator = obj->o_invoke(s_getIterator, Array()); if (!iterator.isObject()) break; obj = iterator.getObjectData(); } VM::Class*ctx = g_vmContext->getContextClass(); CStrRef context = ctx ? ctx->nameRef() : empty_string; if (isMutable) { if (obj->instanceof(SystemLib::s_IteratorClass)) { throw FatalErrorException("An iterator cannot be used for " "iteration by reference"); } Array properties = obj->o_toIterArray(context, true); return create_object(s_MutableArrayIterator, CREATE_VECTOR1(ref(properties))); } else { if (obj->instanceof(SystemLib::s_IteratorClass)) { return obj; } return create_object(s_ArrayIterator, CREATE_VECTOR1(obj->o_toIterArray(context))); } } raise_warning("Invalid argument supplied for iteration"); if (isMutable) { return create_object(s_MutableArrayIterator, CREATE_VECTOR1(Array::Create())); } return create_object(s_ArrayIterator, CREATE_VECTOR1(Array::Create())); }
SharedVariant* SharedVariant::convertObj(CVarRef var) { if (!var.is(KindOfObject) || getObjAttempted()) { return nullptr; } setObjAttempted(); ObjectData *obj = var.getObjectData(); if (obj->instanceof(SystemLib::s_SerializableClass)) { // should also check the object itself return nullptr; } PointerSet seen; if (obj->hasInternalReference(seen, true)) { return nullptr; } SharedVariant *tmp = new SharedVariant(var, false, true, true); tmp->setObjAttempted(); return tmp; }
APCHandle* APCObject::MakeAPCObject(APCHandle* obj, CVarRef value) { if (!value.is(KindOfObject) || obj->getObjAttempted()) { return nullptr; } obj->setObjAttempted(); ObjectData *o = value.getObjectData(); if (o->instanceof(SystemLib::s_SerializableClass)) { // should also check the object itself return nullptr; } PointerSet seen; if (o->hasInternalReference(seen, true)) { return nullptr; } APCHandle* tmp = APCHandle::Create(value, false, true, true); tmp->setObjAttempted(); return tmp; }
bool f_is_callable(CVarRef v, bool syntax /* = false */, VRefParam name /* = null */) { bool ret = true; if (LIKELY(!syntax)) { CallerFrame cf; ObjectData* obj = NULL; HPHP::Class* cls = NULL; StringData* invName = NULL; const HPHP::Func* f = vm_decode_function(v, cf(), false, obj, cls, invName, false); if (f == NULL) { ret = false; } if (invName != NULL) { decRefStr(invName); } if (!name.isReferenced()) return ret; } auto const tv_func = v.asCell(); if (IS_STRING_TYPE(tv_func->m_type)) { if (name.isReferenced()) name = tv_func->m_data.pstr; return ret; } if (tv_func->m_type == KindOfArray) { CArrRef arr = tv_func->m_data.parr; CVarRef clsname = arr.rvalAtRef(int64_t(0)); CVarRef mthname = arr.rvalAtRef(int64_t(1)); if (arr.size() != 2 || &clsname == &null_variant || &mthname == &null_variant) { name = v.toString(); return false; } auto const tv_meth = mthname.asCell(); if (!IS_STRING_TYPE(tv_meth->m_type)) { if (name.isReferenced()) name = v.toString(); return false; } auto const tv_cls = clsname.asCell(); if (tv_cls->m_type == KindOfObject) { name = tv_cls->m_data.pobj->o_getClassName(); } else if (IS_STRING_TYPE(tv_cls->m_type)) { name = tv_cls->m_data.pstr; } else { name = v.toString(); return false; } name = concat3(name, s_colon2, tv_meth->m_data.pstr); return ret; } if (tv_func->m_type == KindOfObject) { ObjectData *d = tv_func->m_data.pobj; const Func* invoke = d->getVMClass()->lookupMethod(s__invoke.get()); if (name.isReferenced()) { if (d->instanceof(c_Closure::classof())) { // Hack to stop the mangled name from showing up name = s_Closure__invoke; } else { name = d->o_getClassName() + "::__invoke"; } } return invoke != NULL; } return false; }
bool f_is_callable(CVarRef v, bool syntax /* = false */, VRefParam name /* = null */) { bool ret = true; if (LIKELY(!syntax)) { CallerFrame cf; ObjectData* obj = NULL; HPHP::VM::Class* cls = NULL; StringData* invName = NULL; const HPHP::VM::Func* f = vm_decode_function(v, cf(), false, obj, cls, invName, false); if (f == NULL) { ret = false; } if (invName != NULL) { decRefStr(invName); } if (!name.isReferenced()) return ret; } Variant::TypedValueAccessor tv_func = v.getTypedAccessor(); if (Variant::IsString(tv_func)) { if (name.isReferenced()) name = Variant::GetStringData(tv_func); return ret; } if (Variant::GetAccessorType(tv_func) == KindOfArray) { CArrRef arr = Variant::GetAsArray(tv_func); CVarRef clsname = arr.rvalAtRef(int64_t(0)); CVarRef mthname = arr.rvalAtRef(int64_t(1)); if (arr.size() != 2 || &clsname == &null_variant || &mthname == &null_variant) { name = v.toString(); return false; } Variant::TypedValueAccessor tv_meth = mthname.getTypedAccessor(); if (!Variant::IsString(tv_meth)) { if (name.isReferenced()) name = v.toString(); return false; } Variant::TypedValueAccessor tv_cls = clsname.getTypedAccessor(); if (Variant::GetAccessorType(tv_cls) == KindOfObject) { name = Variant::GetObjectData(tv_cls)->o_getClassName(); } else if (Variant::IsString(tv_cls)) { name = Variant::GetStringData(tv_cls); } else { name = v.toString(); return false; } name = concat3(name, "::", Variant::GetAsString(tv_meth)); return ret; } if (Variant::GetAccessorType(tv_func) == KindOfObject) { ObjectData *d = Variant::GetObjectData(tv_func); static const StringData* sd__invoke = StringData::GetStaticString("__invoke"); const VM::Func* invoke = d->getVMClass()->lookupMethod(sd__invoke); if (name.isReferenced()) { if (d->instanceof(c_Closure::s_cls)) { // Hack to stop the mangled name from showing up name = "Closure::__invoke"; } else { name = d->o_getClassName() + "::__invoke"; } } return invoke != NULL; } return false; }
Object c_GenMapWaitHandle::ti_create(const Variant& dependencies) { ObjectData* obj; if (UNLIKELY(!dependencies.isObject() || !(obj = dependencies.getObjectData())->isCollection() || obj->collectionType() != CollectionType::Map)) { Object e(SystemLib::AllocInvalidArgumentExceptionObject( "Expected dependencies to be an instance of Map")); throw e; } assert(obj->instanceof(c_Map::classof())); auto deps = SmartPtr<c_Map>::attach(c_Map::Clone(obj)); for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); if (UNLIKELY(!c_WaitHandle::fromCell(current))) { Object e(SystemLib::AllocInvalidArgumentExceptionObject( "Expected dependencies to be a map of WaitHandle instances")); throw e; } } Object exception; for (ssize_t iter_pos = deps->iter_begin(); deps->iter_valid(iter_pos); iter_pos = deps->iter_next(iter_pos)) { auto* current = tvAssertCell(deps->iter_value(iter_pos)); assert(current->m_type == KindOfObject); assert(current->m_data.pobj->instanceof(c_WaitHandle::classof())); auto child = static_cast<c_WaitHandle*>(current->m_data.pobj); if (child->isSucceeded()) { auto k = deps->iter_key(iter_pos); auto result = child->getResult(); deps->set(k.asCell(), &result); } else if (child->isFailed()) { putException(exception, child->getException()); } else { assert(child->instanceof(c_WaitableWaitHandle::classof())); auto child_wh = static_cast<c_WaitableWaitHandle*>(child); auto my_wh = makeSmartPtr<c_GenMapWaitHandle>(); my_wh->initialize(exception, deps.get(), iter_pos, child_wh); AsioSession* session = AsioSession::Get(); if (UNLIKELY(session->hasOnGenMapCreateCallback())) { session->onGenMapCreate(my_wh.get(), dependencies); } return Object(std::move(my_wh)); } } if (exception.isNull()) { return Object::attach(c_StaticWaitHandle::CreateSucceeded( make_tv<KindOfObject>(deps.detach()))); } else { return Object::attach(c_StaticWaitHandle::CreateFailed(exception.detach())); } }