void Variant::setEvalScalar() { switch (m_type) { case KindOfString: { StringData *pstr = m_data.pstr; if (!pstr->isStatic()) { StringData *sd = makeStaticString(pstr); decRefStr(pstr); m_data.pstr = sd; assert(m_data.pstr->isStatic()); m_type = KindOfStaticString; } break; } case KindOfArray: { ArrayData *parr = m_data.parr; if (!parr->isStatic()) { ArrayData *ad = ArrayData::GetScalarArray(parr); decRefArr(parr); m_data.parr = ad; assert(m_data.parr->isStatic()); } break; } case KindOfRef: not_reached(); break; case KindOfObject: case KindOfResource: not_reached(); // object shouldn't be in a scalar array break; default: break; } }
ArrayData* SharedMap::escalateForSort() { ArrayData *ret = NULL; bool keepRef = false; bool mapInit = true; m_arr->loadElems(ret, *this, keepRef, mapInit); assert(!ret->isStatic()); 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; }
void tvCastToArrayInPlace(TypedValue* tv) { assert(tvIsPlausible(*tv)); tvUnboxIfNeeded(tv); ArrayData* a; do { switch (tv->m_type) { case KindOfUninit: case KindOfNull: a = ArrayData::Create(); continue; case KindOfBoolean: case KindOfInt64: case KindOfDouble: case KindOfStaticString: a = ArrayData::Create(tvAsVariant(tv)); continue; case KindOfString: a = ArrayData::Create(tvAsVariant(tv)); tvDecRefStr(tv); continue; case KindOfArray: return; case KindOfObject: // For objects, we fall back on the Variant machinery tvAsVariant(tv) = tv->m_data.pobj->toArray(); return; case KindOfResource: a = ArrayData::Create(tvAsVariant(tv)); tvDecRefRes(tv); continue; case KindOfRef: case KindOfClass: break; } not_reached(); } while (0); assert(a->isStatic() || a->hasExactlyOneRef()); tv->m_data.parr = a; tv->m_type = KindOfArray; }
ArrayData* ArrayData::GetScalarArray(ArrayData* arr, const ScalarArrayKey& key) { if (arr->empty() && !arr->isDict()) return staticEmptyArray(); assert(key == GetScalarArrayKey(arr)); ArrayDataMap::accessor acc; if (s_arrayDataMap.insert(acc, key)) { ArrayData* ad; if (arr->isVectorData() && !arr->isPacked() && !arr->isDict()) { ad = PackedArray::ConvertStatic(arr); } else { ad = arr->copyStatic(); } assert(ad->isStatic()); ad->onSetEvalScalar(); acc->second = ad; } return acc->second; }
ArrayData* SharedVariant::loadElems(const SharedArray &array) { assert(is(KindOfArray)); auto count = arrSize(); ArrayData* elems; if (isPacked()) { PackedArrayInit ai(count); for (uint i = 0; i < count; i++) { ai.append(array.getValueRef(i)); } elems = ai.create(); } else { ArrayInit ai(count); for (uint i = 0; i < count; i++) { ai.add(m_data.array->getKeyIndex(i)->toLocal(), array.getValueRef(i), true); } elems = ai.create(); } if (elems->isStatic()) elems = elems->copy(); return elems; }
ArrayData* SharedVariant::loadElems(const SharedMap &sharedMap) { assert(is(KindOfArray)); auto count = arrSize(); ArrayData* elems; if (getIsVector()) { VectorInit ai(count); for (uint i = 0; i < count; i++) { ai.add(sharedMap.getValueRef(i)); } elems = ai.create(); } else { ArrayInit ai(count); for (uint i = 0; i < count; i++) { ai.add(m_data.map->getKeyIndex(i)->toLocal(), sharedMap.getValueRef(i), true); } elems = ai.create(); } if (elems->isStatic()) elems = elems->copy(); return elems; }
ArrayData* APCLocalArray::loadElems() const { auto count = m_arr->size(); ArrayData* elems; if (m_arr->isPacked()) { PackedArrayInit ai(count); for (uint i = 0; i < count; i++) { ai.append(GetValueRef(this, i)); } elems = ai.create(); } else { ArrayInit ai(count, ArrayInit::Mixed{}); for (uint i = 0; i < count; i++) { ai.add(getKey(i), GetValueRef(this, i), true); } elems = ai.create(); } if (elems->isStatic()) { elems = elems->copy(); } return elems; }
ArrayData* SharedVariant::loadElems(const SharedMap &sharedMap, bool mapInit /* = false */) { assert(is(KindOfArray)); uint count = arrSize(); bool isVector = getIsVector(); ArrayInit ai = mapInit ? ArrayInit(count, ArrayInit::mapInit) : isVector ? ArrayInit(count, ArrayInit::vectorInit) : ArrayInit(count); if (isVector) { for (uint i = 0; i < count; i++) { ai.set(sharedMap.getValueRef(i)); } } else { for (uint i = 0; i < count; i++) { ai.add(m_data.map->getKeyIndex(i)->toLocal(), sharedMap.getValueRef(i), true); } } ArrayData* elems = ai.create(); if (elems->isStatic()) elems = elems->copy(); return elems; }
ArrayData* APCLocalArray::loadElems() const { auto count = m_arr->size(); ArrayData* elems; if (m_arr->isPacked()) { PackedArrayInit ai(count); for (uint32_t i = 0; i < count; i++) { ai.append(RvalAtPos(this, i).tv()); } elems = ai.create(); } else { ArrayInit ai(count, ArrayInit::Mixed{}); for (uint32_t i = 0; i < count; i++) { ai.add(getKey(i), RvalAtPos(this, i).tv(), true); } elems = ai.create(); } if (elems->isStatic()) { elems = elems->copy(); } assert(elems->hasExactlyOneRef()); return elems; }
ArrayData* SharedMap::loadElems(bool mapInit /* = false */) const { uint count = size(); bool isVec = isVector(); auto ai = mapInit ? ArrayInit(count, ArrayInit::mapInit) : isVec ? ArrayInit(count, ArrayInit::vectorInit) : ArrayInit(count); if (isVec) { for (uint i = 0; i < count; i++) { ai.set(getValueRef(i)); } } else { for (uint i = 0; i < count; i++) { ai.add(m_map->getKey(i), getValueRef(i), true); } } ArrayData* elems = ai.create(); if (elems->isStatic()) elems = elems->copy(); return elems; }
void Variant::setEvalScalar() { switch (m_type) { DT_UNCOUNTED_CASE: return; case KindOfString: { StringData *pstr = m_data.pstr; if (!pstr->isStatic()) { StringData *sd = makeStaticString(pstr); decRefStr(pstr); m_data.pstr = sd; assert(m_data.pstr->isStatic()); m_type = KindOfStaticString; } return; } case KindOfArray: { ArrayData *parr = m_data.parr; if (!parr->isStatic()) { ArrayData *ad = ArrayData::GetScalarArray(parr); decRefArr(parr); m_data.parr = ad; assert(m_data.parr->isStatic()); } return; } case KindOfObject: case KindOfResource: case KindOfRef: case KindOfClass: break; } not_reached(); }
ArrayData* SharedMap::escalateForSort() { ArrayData *ret = loadElems(true /* mapInit */); assert(!ret->isStatic()); return ret; }
ArrayData *SharedMap::escalate() const { ArrayData *ret = loadElems(); assert(!ret->isStatic()); return ret; }
ArrayData *SharedMap::escalate() const { ArrayData *ret = nullptr; m_arr->loadElems(ret, *this); assert(!ret->isStatic()); return ret; }
ArrayData *SharedMap::escalate(bool mutableIteration /* = false */) const { ArrayData *ret = NULL; m_arr->loadElems(ret, *this, mutableIteration); assert(!ret->isStatic()); return ret; }
ArrayData* SharedMap::escalateForSort() { ArrayData *ret = nullptr; m_arr->loadElems(ret, *this, true /* mapInit */); assert(!ret->isStatic()); return ret; }