void c_MutableArrayIterator::t___construct(VRefParam array) { INSTANCE_METHOD_INJECTION_BUILTIN(MutableArrayIterator, MutableArrayIterator::__construct); if (m_valid) { MIterCtx& mi = marr(); mi.~MIterCtx(); m_valid = false; } Variant var(strongBind(array)); TypedValue* tv = (TypedValue*)(&var); ASSERT(tv->m_type == KindOfRef); if (tv->m_data.ptv->m_type == KindOfArray) { ArrayData* ad = tv->m_data.ptv->m_data.parr; if (ad->getCount() > 1) { ArrayData* copy = ad->copy(); copy->incRefCount(); ad->decRefCount(); // count > 1 to begin with; don't need release ad = tv->m_data.ptv->m_data.parr = copy; } MIterCtx& mi = marr(); (void) new (&mi) MIterCtx(tv->m_data.pref); m_valid = mi.m_mArray->advance(); if (!m_valid) mi.~MIterCtx(); } else if (tv->m_data.ptv->m_type == KindOfObject) { CStrRef ctxStr = hhvm ? g_vmContext->getContextClassName(true) : FrameInjection::GetClassName(true); bool isIterator; Object obj = tv->m_data.ptv->m_data.pobj->iterableObject(isIterator); if (isIterator) { raise_error("An iterator cannot be used with foreach by reference"); } Array iterArray = obj->o_toIterArray(ctxStr, true); ArrayData* ad = iterArray.getArrayData(); if (ad->getCount() > 1) { ArrayData* copy = ad->copy(); copy->incRefCount(); ad->decRefCount(); // count > 1 to begin with; don't need release ad = copy; } MIterCtx& mi = marr(); (void) new (&mi) MIterCtx(ad); m_valid = mi.m_mArray->advance(); if (!m_valid) mi.~MIterCtx(); } else { raise_warning("Invalid argument supplied for foreach()"); } }
Variant &Array::lvalAt() { if (!m_px) ArrayBase::operator=(ArrayData::Create()); Variant *ret = nullptr; ArrayData *arr = m_px; ArrayData *escalated = arr->lvalNew(ret, arr->getCount() > 1); if (escalated != arr) ArrayBase::operator=(escalated); assert(ret); return *ret; }
ArrayData* APCLocalArray::EscalateForSort(ArrayData* ad, SortFunction sf) { auto a = asApcArray(ad); ArrayData* elems = a->loadElems(); ArrayData* ret = elems->escalateForSort(sf); if (ret != elems) { elems->release(); } assert(ret->getCount() == 0); assert(!ret->isStatic()); return ret; }
ArrayData* MutableArrayIter::cowCheck() { ArrayData* data; if (m_var) { data = getData(); if (!data) return NULL; if (data->getCount() > 1 && !data->noCopyOnWrite()) { *const_cast<Variant*>(m_var) = (data = data->copyWithStrongIterators()); } } else { assert(m_data); data = m_data; if (data->getCount() > 1 && !data->noCopyOnWrite()) { ArrayData* copied = data->copyWithStrongIterators(); copied->incRefCount(); decRefArr(data); m_data = data = copied; } } return data; }
Variant &Array::lvalAt() { if (!m_px) { SmartPtr<ArrayData>::operator=(ArrayData::Create()); } Variant *ret = NULL; ArrayData *arr = m_px; ArrayData *escalated = arr->lvalNew(ret, arr->getCount() > 1); if (escalated) { SmartPtr<ArrayData>::operator=(escalated); } ASSERT(ret); return *ret; }