/* * Converts a packed array to mixed, leaving the packed array in an * empty state. You need ToMixedCopy in cases where the old array * needs to remain un-modified (usually if `copy' is true). * * The returned array is mixed, and is guaranteed not to be isFull(). * (Note: only unset can call ToMixed when we aren't about to insert.) */ MixedArray* PackedArray::ToMixed(ArrayData* old) { auto const oldSize = old->m_size; auto const ad = ToMixedHeader(old, oldSize + 1); auto const mask = ad->m_tableMask; auto dstData = ad->data(); auto dstHash = ad->hashTab(); auto const srcData = packedData(old); auto i = uint32_t{0}; for (; i < oldSize; ++i) { dstData->setIntKey(i); tvCopy(srcData[i], dstData->data); *dstHash = i; ++dstData; ++dstHash; } for (; i <= mask; ++i) { *dstHash++ = MixedArray::Empty; } old->m_size = 0; assert(ad->checkInvariants()); assert(!ad->isFull()); return ad; }
MixedArray* StructArray::ToMixed(StructArray* old) { auto const oldSize = old->size(); auto const ad = ToMixedHeader(oldSize + 1); auto const srcData = old->data(); auto shape = old->shape(); memset(ad->hashTab(), static_cast<uint8_t>(MixedArray::Empty), sizeof(int32_t) * ad->hashSize()); for (auto i = 0; i < oldSize; ++i) { auto key = const_cast<StringData*>(shape->keyForOffset(i)); auto& e = ad->addKeyAndGetElem(key); tvCopy(srcData[i], e.data); } old->m_size = 0; ad->m_pos = old->m_pos; if (debug) { // For debug builds, set m_pos to 0 as well to make the // asserts in checkInvariants() happy. old->m_pos = 0; } assert(ad->checkInvariants()); assert(!ad->isFull()); assert(ad->hasExactlyOneRef()); return ad; }
/* * Convert to mixed, reserving space for at least `neededSize' elems. * The `neededSize' should include old->size(), but may be equal to * it. * * Unlike the other ToMixed functions, the returned array already has * a reference count of 1. */ MixedArray* PackedArray::ToMixedCopyReserve(const ArrayData* old, size_t neededSize) { assert(neededSize >= old->m_size); auto const ad = ToMixedHeader(old, neededSize); ad->m_count = 1; auto const oldSize = old->m_size; auto const mask = ad->m_tableMask; auto dstData = ad->data(); auto dstHash = ad->hashTab(); auto const srcData = packedData(old); auto i = uint32_t{0}; for (; i < oldSize; ++i) { dstData->setIntKey(i); tvDupFlattenVars(&srcData[i], &dstData->data, old); *dstHash = i; ++dstData; ++dstHash; } for (; i <= mask; ++i) { *dstHash++ = MixedArray::Empty; } assert(ad->checkInvariants()); return ad; }
MixedArray* StructArray::ToMixedCopy(const StructArray* old) { auto const oldSize = old->size(); auto const ad = ToMixedHeader(oldSize + 1); auto const srcData = old->data(); auto shape = old->shape(); memset(ad->hashTab(), static_cast<uint8_t>(MixedArray::Empty), sizeof(int32_t) * ad->hashSize()); for (auto i = 0; i < oldSize; ++i) { auto key = const_cast<StringData*>(shape->keyForOffset(i)); auto& e = ad->addKeyAndGetElem(key); tvDupFlattenVars(&srcData[i], &e.data, old); } ad->m_pos = old->m_pos; assert(ad->checkInvariants()); assert(!ad->isFull()); assert(ad->hasExactlyOneRef()); return ad; }