ArrayData* PackedArray::NonSmartCopy(const ArrayData* adIn) { assert(checkInvariants(adIn)); // There's no reason to use the full capacity, since non-smart // arrays are not mutable. auto const cap = adIn->m_size; auto const size = adIn->m_size; auto const ad = static_cast<ArrayData*>( std::malloc(sizeof(ArrayData) + cap * sizeof(TypedValue)) ); ad->m_kindAndSize = uint64_t{size} << 32 | cap; // zero kind ad->m_posAndCount = static_cast<uint32_t>(adIn->m_pos); auto const srcData = packedData(adIn); auto const stop = srcData + size; auto targetData = reinterpret_cast<TypedValue*>(ad + 1); for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) { tvDupFlattenVars(ptr, targetData, adIn); } assert(ad->m_kind == ArrayData::kPackedKind); assert(ad->m_packedCap == cap); assert(ad->m_size == size); assert(ad->m_pos == adIn->m_pos); assert(ad->m_count == 0); assert(checkInvariants(ad)); return ad; }
NEVER_INLINE ArrayData* PackedArray::Copy(const ArrayData* adIn) { assert(checkInvariants(adIn)); auto const cap = adIn->m_packedCap; auto const size = adIn->m_size; auto const ad = static_cast<ArrayData*>( MM().objMallocLogged(sizeof(ArrayData) + cap * sizeof(TypedValue)) ); ad->m_kindAndSize = uint64_t{size} << 32 | cap; // zero kind ad->m_posAndCount = static_cast<uint32_t>(adIn->m_pos); auto const srcData = packedData(adIn); auto const stop = srcData + size; auto targetData = reinterpret_cast<TypedValue*>(ad + 1); for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) { tvDupFlattenVars(ptr, targetData, adIn); } assert(ad->m_kind == ArrayData::kPackedKind); assert(ad->m_packedCap == cap); assert(ad->m_size == size); assert(ad->m_pos == adIn->m_pos); assert(ad->m_count == 0); assert(checkInvariants(ad)); 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; }
void c_Continuation::dupContVar(const StringData* name, TypedValue* src) { ActRec *fp = actRec(); Id destId = fp->m_func->lookupVarId(name); if (destId != kInvalidId) { // Copy the value of the local to the cont object. tvDupFlattenVars(src, frame_local(fp, destId)); } else { if (!fp->hasVarEnv()) { fp->setVarEnv(VarEnv::createLocal(fp)); } fp->getVarEnv()->setWithRef(name, src); } }
void c_Continuation::dupContVar(const StringData* name, TypedValue* src) { ActRec *fp = actRec(); Id destId = fp->m_func->lookupVarId(name); if (destId != kInvalidId) { // Copy the value of the local to the cont object. tvDupFlattenVars(src, frame_local(fp, destId)); } else { if (!fp->hasVarEnv()) { // This VarEnv may potentially outlive the most recently stack-allocated // VarEnv, so we need to heap allocate it. fp->setVarEnv(VarEnv::createLocalOnHeap(fp)); } fp->getVarEnv()->setWithRef(name, src); } }
ArrayData* StructArray::CopyStatic(const ArrayData* ad) { auto structArray = asStructArray(ad); auto shape = structArray->shape(); auto ret = StructArray::createStatic(shape, structArray->size()); ret->m_pos = structArray->m_pos; auto const srcData = structArray->data(); auto const size = structArray->size(); auto const stop = srcData + size; auto targetData = ret->data(); for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) { tvDupFlattenVars(ptr, targetData, structArray); } assert(ret->isStatic()); return ret; }
ArrayData* StructArray::Copy(const ArrayData* ad) { auto old = asStructArray(ad); auto shape = old->shape(); auto result = StructArray::createNoCopy(shape, shape->size()); result->m_pos = old->m_pos; assert(result->m_size == result->shape()->size()); assert(result->size() == old->size()); auto const srcData = old->data(); auto const stop = srcData + old->size(); auto targetData = result->data(); for (auto ptr = srcData; ptr != stop; ++ptr, ++targetData) { tvDupFlattenVars(ptr, targetData, old); } assert(result->m_size == result->shape()->size()); assert(result->hasExactlyOneRef()); return result; }
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; }
void Generator::copyVars(const ActRec* srcFp) { const auto dstFp = actRec(); const auto func = dstFp->func(); assert(srcFp->func() == dstFp->func()); for (Id i = 0; i < func->numLocals(); ++i) { tvDupFlattenVars(frame_local(srcFp, i), frame_local(dstFp, i)); } if (dstFp->hasThis()) { dstFp->getThis()->incRefCount(); } if (LIKELY(!(srcFp->func()->attrs() & AttrMayUseVV))) return; if (LIKELY(srcFp->m_varEnv == nullptr)) return; if (srcFp->hasExtraArgs()) { dstFp->setExtraArgs(srcFp->getExtraArgs()->clone(dstFp)); } else { assert(srcFp->hasVarEnv()); dstFp->setVarEnv(srcFp->getVarEnv()->clone(dstFp)); } }
NameValueTable::NameValueTable(const NameValueTable& nvTable, ActRec* fp) : m_fp(fp) , m_elms(nvTable.m_elms) { allocate(nvTable.m_tabMask + 1); assert(m_tabMask == nvTable.m_tabMask); for (int i = 0; i <= m_tabMask; ++i) { Elm& src = nvTable.m_table[i]; Elm& dst = m_table[i]; dst.m_name = src.m_name; if (dst.m_name) { dst.m_name->incRefCount(); if (src.m_tv.m_type == kNamedLocalDataType) { dst.m_tv.m_type = kNamedLocalDataType; dst.m_tv.m_data.num = src.m_tv.m_data.num; } else { tvDupFlattenVars(&src.m_tv, &dst.m_tv); } } } }
void c_Continuation::copyContinuationVars(ActRec* srcFp) { const auto dstFp = actRec(); const auto func = dstFp->func(); assert(srcFp->func() == dstFp->func()); for (Id i = 0; i < func->numLocals(); ++i) { tvDupFlattenVars(frame_local(srcFp, i), frame_local(dstFp, i)); } if (dstFp->hasThis()) { dstFp->getThis()->incRefCount(); } if (LIKELY(srcFp->m_varEnv == nullptr)) { return; } if (srcFp->hasExtraArgs()) { dstFp->setExtraArgs(srcFp->getExtraArgs()->clone(dstFp)); } else { assert(srcFp->hasVarEnv()); dstFp->setVarEnv(srcFp->getVarEnv()->clone(dstFp)); } }