ALWAYS_INLINE MixedArray* PackedArray::ToMixedHeader(const ArrayData* old, size_t neededSize) { assert(PackedArray::checkInvariants(old)); auto const oldSize = old->m_size; auto const cmret = computeCapAndMask(neededSize); auto const cap = cmret.first; auto const mask = cmret.second; auto const ad = smartAllocArray(cap, mask); auto const shiftedSize = uint64_t{oldSize} << 32; ad->m_kindAndSize = shiftedSize | MixedArray::kMixedKind << 24; ad->m_posAndCount = static_cast<uint32_t>(old->m_pos); // zero count ad->m_capAndUsed = shiftedSize | cap; ad->m_maskAndLoad = shiftedSize | mask; ad->m_nextKI = oldSize; assert(ad->m_kind == ArrayData::kMixedKind); assert(ad->m_size == oldSize); assert(ad->m_pos == old->m_pos); assert(ad->m_count == 0); assert(ad->m_used == oldSize); assert(ad->m_cap == cap); assert(ad->m_tableMask = mask); assert(ad->m_hLoad == oldSize); assert(ad->m_nextKI == oldSize); // Can't checkInvariants yet, since we haven't populated the payload. return ad; }
/* * Creating a single-element mixed array with a integer key. The * value is already incref'd. */ std::pair<ArrayData*,TypedValue*> EmptyArray::MakeMixed(int64_t key, TypedValue val) { auto const ad = smartAllocArray(MixedArray::SmallScale); InitMixed(ad, 0/*count*/, 1/*size*/, (key >= 0) ? key + 1 : 0); auto const data = ad->data(); auto const hash = reinterpret_cast<int32_t*>(data + MixedArray::SmallSize); assert(ad->hashSize() == MixedArray::SmallHashSize); auto const emptyVal = int64_t{MixedArray::Empty}; reinterpret_cast<int64_t*>(hash)[0] = emptyVal; reinterpret_cast<int64_t*>(hash)[1] = emptyVal; auto const mask = MixedArray::SmallMask; hash[key & mask] = 0; data[0].setIntKey(key); auto& lval = data[0].data; lval.m_data = val.m_data; lval.m_type = val.m_type; assert(ad->kind() == ArrayData::kMixedKind); assert(ad->m_size == 1); assert(ad->m_pos == 0); assert(ad->getCount() == 0); assert(ad->m_scale == MixedArray::SmallScale); assert(ad->m_used == 1); assert(ad->checkInvariants()); return { ad, &lval }; }
/* * Helper for creating a single-element mixed array with a string key. * * Note: the key is not already incref'd, but the value must be. */ NEVER_INLINE std::pair<ArrayData*,TypedValue*> EmptyArray::MakeMixed(StringData* key, TypedValue val) { auto const ad = smartAllocArray(MixedArray::SmallScale); InitMixed(ad, 0/*count*/, 1/*size*/, 0/*nextIntKey*/); auto const data = ad->data(); auto const hash = reinterpret_cast<int32_t*>(data + MixedArray::SmallSize); auto const khash = key->hash(); auto const mask = MixedArray::SmallMask; hash[khash & mask] = 0; data[0].setStrKey(key, khash); auto& lval = data[0].data; lval.m_data = val.m_data; lval.m_type = val.m_type; assert(ad->m_size == 1); assert(ad->m_pos == 0); assert(ad->m_scale == MixedArray::SmallScale); assert(ad->kind() == ArrayData::kMixedKind); assert(ad->getCount() == 0); assert(ad->m_used == 1); assert(ad->checkInvariants()); return { ad, &lval }; }
/* * Helper for creating a single-element mixed array with a string key. * * Note: the key is not already incref'd, but the value must be. */ NEVER_INLINE std::pair<ArrayData*,TypedValue*> EmptyArray::MakeMixed(StringData* key, TypedValue val) { auto const mask = MixedArray::SmallMask; // 3 auto const cap = MixedArray::computeMaxElms(mask); // 3 auto const ad = smartAllocArray(cap, mask); ad->m_kindAndSize = uint64_t{1} << 32 | ArrayData::kMixedKind << 24; ad->m_posAndCount = 0; ad->m_capAndUsed = uint64_t{1} << 32 | cap; ad->m_tableMask = mask; ad->m_nextKI = 0; ad->m_hLoad = 1; auto const data = reinterpret_cast<MixedArray::Elm*>(ad + 1); auto const hash = reinterpret_cast<int32_t*>(data + cap); assert(mask + 1 == 4); auto const emptyVal = int64_t{MixedArray::Empty}; reinterpret_cast<int64_t*>(hash)[0] = emptyVal; reinterpret_cast<int64_t*>(hash)[1] = emptyVal; auto const khash = key->hash(); hash[khash & mask] = 0; data[0].setStrKey(key, khash); auto& lval = data[0].data; lval.m_data = val.m_data; lval.m_type = val.m_type; assert(ad->m_kind == ArrayData::kMixedKind); assert(ad->m_size == 1); assert(ad->m_pos == 0); assert(ad->m_count == 0); assert(ad->m_cap == cap); assert(ad->m_used == 1); assert(ad->checkInvariants()); return { ad, &lval }; }
/* * Creating a single-element mixed array with a integer key. The * value is already incref'd. */ std::pair<ArrayData*,TypedValue*> EmptyArray::MakeMixed(int64_t key, TypedValue val) { auto const mask = MixedArray::SmallMask; // 3 auto const cap = MixedArray::computeMaxElms(mask); // 3 auto const ad = smartAllocArray(cap, mask); ad->m_sizeAndPos = 1; // size=1, pos=0 ad->m_kindAndCount = MixedArray::kMixedKind << 24; // capcode=0, count=0 ad->m_capAndUsed = uint64_t{1} << 32 | cap; ad->m_tableMask = mask; ad->m_nextKI = (key >= 0) ? key + 1 : 0; auto const data = reinterpret_cast<MixedArray::Elm*>(ad + 1); auto const hash = reinterpret_cast<int32_t*>(data + cap); assert(mask + 1 == 4); auto const emptyVal = int64_t{MixedArray::Empty}; reinterpret_cast<int64_t*>(hash)[0] = emptyVal; reinterpret_cast<int64_t*>(hash)[1] = emptyVal; hash[key & mask] = 0; data[0].setIntKey(key); auto& lval = data[0].data; lval.m_data = val.m_data; lval.m_type = val.m_type; assert(ad->m_kind == ArrayData::kMixedKind); assert(ad->m_size == 1); assert(ad->m_pos == 0); assert(ad->m_count == 0); assert(ad->m_cap == cap); assert(ad->m_used == 1); assert(ad->checkInvariants()); return { ad, &lval }; }