ALWAYS_INLINE void BaseSet::addImpl(StringData *key) { if (!raw) { mutate(); } strhash_t h = key->hash(); auto p = findForInsert(key, h); assert(p); if (validPos(*p)) { return; } if (UNLIKELY(isFull())) { makeRoom(); p = findForInsert(key, h); } auto& e = allocElm(p); // This increments the string's refcount twice, once for // the key and once for the value e.setStrKey(key, h); cellDup(make_tv<KindOfString>(key), e.data); updateIntLikeStrKeys(key); if (!raw) { ++m_version; } }
ALWAYS_INLINE void BaseSet::addImpl(int64_t k) { if (!raw) { mutate(); } auto h = hashint(k); auto p = findForInsert(k, h); assert(p); if (validPos(*p)) { // When there is a conflict, the add() API is supposed to replace the // existing element with the new element in place. However since Sets // currently only support integer and string elements, there is no way // user code can really tell whether the existing element was replaced // so for efficiency we do nothing. return; } if (UNLIKELY(isFull())) { makeRoom(); p = findForInsert(k, h); } auto& e = allocElm(p); e.setIntKey(k, h); e.data.m_type = KindOfInt64; e.data.m_data.num = k; updateNextKI(k); if (!raw) { ++m_version; } }
HOT_FUNC_HPHP bool ZendArray::addLvalImpl(int64 h, Variant **pDest, bool doFind /* = true */) { ASSERT(pDest != NULL); Bucket *p; if (doFind) { p = findForInsert(h); if (p) { *pDest = &p->data; return false; } } p = NEW(Bucket)(); p->setIntKey(h); if (pDest) { *pDest = &p->data; } uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (h >= m_nNextFreeElement && m_nNextFreeElement >= 0) { m_nNextFreeElement = h + 1; } if (++m_size > tableSize()) { resize(); } return true; }
ALWAYS_INLINE void BaseMap::setImpl(StringData* key, const TypedValue* val) { if (!raw) { mutate(); } assert(val->m_type != KindOfRef); assert(canMutateBuffer()); retry: strhash_t h = key->hash(); auto* p = findForInsert(key, h); assert(p); if (validPos(*p)) { auto& e = data()[*p]; TypedValue old = e.data; cellDup(*val, e.data); tvRefcountedDecRef(old); return; } if (UNLIKELY(isFull())) { makeRoom(); goto retry; } if (!raw) { ++m_version; } auto& e = allocElm(p); cellDup(*val, e.data); e.setStrKey(key, h); updateIntLikeStrKeys(key); }
ALWAYS_INLINE void BaseMap::setImpl(int64_t h, const TypedValue* val) { if (!raw) { mutate(); } assert(val->m_type != KindOfRef); assert(canMutateBuffer()); retry: auto p = findForInsert(h); assert(p); if (validPos(*p)) { auto& e = data()[*p]; TypedValue old = e.data; cellDup(*val, e.data); tvRefcountedDecRef(old); return; } if (UNLIKELY(isFull())) { makeRoom(); goto retry; } if (!raw) { ++m_version; } auto& e = allocElm(p); cellDup(*val, e.data); e.setIntKey(h); updateNextKI(h); }
HOT_FUNC_HPHP bool ZendArray::addValWithRef(StringData *key, CVarRef data) { int64 h = key->hash(); Bucket *p = findForInsert(key->data(), key->size(), h); if (p) { return false; } p = NEW(Bucket)(withRefBind(data)); p->setStrKey(key, h); uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (++m_size > tableSize()) { resize(); } return true; }
HOT_FUNC_HPHP bool ZendArray::addValWithRef(int64 h, CVarRef data) { Bucket *p = findForInsert(h); if (p) { return false; } p = NEW(Bucket)(withRefBind(data)); p->setIntKey(h); uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (h >= m_nNextFreeElement && m_nNextFreeElement >= 0) { m_nNextFreeElement = h + 1; } if (++m_size > tableSize()) { resize(); } return true; }
ArrayData *ZendArray::lval(int64 k, Variant *&ret, bool copy, bool checkExist /* = false */) { if (!copy) { addLvalImpl(k, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret); return a; } Bucket *p = findForInsert(k); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(k, &ret, p); return a; }
bool ZendArray::updateRef(StringData *key, CVarRef data) { int64 h = key->hash(); Bucket *p = findForInsert(key->data(), key->size(), h); if (p) { p->data.assignRefHelper(data); return true; } p = NEW(Bucket)(strongBind(data)); p->setStrKey(key, h); uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (++m_size > tableSize()) { resize(); } return true; }
bool ZendArray::updateRef(int64 h, CVarRef data) { Bucket *p = findForInsert(h); if (p) { p->data.assignRefHelper(data); return true; } p = NEW(Bucket)(strongBind(data)); p->setIntKey(h); uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (h >= m_nNextFreeElement && m_nNextFreeElement >= 0) { m_nNextFreeElement = h + 1; } if (++m_size > tableSize()) { resize(); } return true; }
HOT_FUNC_HPHP ArrayData *ZendArray::lval(CStrRef k, Variant *&ret, bool copy, bool checkExist /* = false */) { StringData *key = k.get(); int64 prehash = key->hash(); if (!copy) { addLvalImpl(key, prehash, &ret); return NULL; } if (!checkExist) { ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret); return a; } Bucket *p = findForInsert(key->data(), key->size(), prehash); if (p && (p->data.isReferenced() || p->data.isObject())) { ret = &p->data; return NULL; } ZendArray *a = copyImpl(); a->addLvalImpl(key, prehash, &ret, p); return a; }
HOT_FUNC_HPHP bool ZendArray::addLvalImpl(StringData *key, int64 h, Variant **pDest, bool doFind /* = true */) { ASSERT(key != NULL && pDest != NULL); Bucket *p; if (doFind) { p = findForInsert(key->data(), key->size(), h); if (p) { *pDest = &p->data; return false; } } p = NEW(Bucket)(); p->setStrKey(key, h); *pDest = &p->data; uint nIndex = (h & m_nTableMask); CONNECT_TO_BUCKET_LIST(p, m_arBuckets[nIndex]); SET_ARRAY_BUCKET_HEAD(m_arBuckets, nIndex, p); CONNECT_TO_GLOBAL_DLLIST(p); if (++m_size > tableSize()) { resize(); } return true; }