diff --git a/hphp/runtime/base/array/array_data.cpp b/hphp/runtime/base/array/array_data.cpp index c5e312bb7..a680a667f 100644 --- a/hphp/runtime/base/array/array_data.cpp +++ b/hphp/runtime/base/array/array_data.cpp @@ -281,15 +281,6 @@ void ArrayData::freeFullPos(FullPos &fp) { assert(false); } -bool ArrayData::validFullPos(const FullPos& fp) const { - assert(fp.getContainer() == (ArrayData*)this); - return false; -} - -bool ArrayData::advanceFullPos(FullPos& fp) { - return false; -} - void ArrayData::freeStrongIterators() { for (FullPosRange r(strongIterators()); !r.empty(); r.popFront()) { r.front()->setContainer(nullptr); @@ -477,31 +468,6 @@ CVarRef ArrayData::get(CVarRef k, bool error) const { : get(getStringKey(cell), error); } -void ArrayData::nvGetKey(TypedValue* out, ssize_t pos) { - Variant k = getKey(pos); - TypedValue* tv = k.asTypedValue(); - // copy w/out clobbering out->_count. - out->m_type = tv->m_type; - out->m_data.num = tv->m_data.num; - if (tv->m_type != KindOfInt64) out->m_data.pstr->incRefCount(); -} - -TypedValue* ArrayData::nvGetValueRef(ssize_t pos) { - return const_cast(getValueRef(pos).asTypedValue()); -} - -TypedValue* ArrayData::nvGetCell(int64_t k) const { - TypedValue* tv = (TypedValue*)&get(k, false); - return LIKELY(tv != (TypedValue*)&null_variant) ? tvToCell(tv) : - nvGetNotFound(k); -} - -TypedValue* ArrayData::nvGetCell(const StringData* key) const { - TypedValue* tv = (TypedValue*)&get(key, false); - return LIKELY(tv != (TypedValue*)&null_variant) ? tvToCell(tv) : - nvGetNotFound(key); -} - CVarRef ArrayData::getNotFound(int64_t k) { raise_notice("Undefined index: %" PRId64, k); return null_variant; diff --git a/hphp/runtime/base/array/array_data.h b/hphp/runtime/base/array/array_data.h index 49a6f4077..4ac2818ce 100644 --- a/hphp/runtime/base/array/array_data.h +++ b/hphp/runtime/base/array/array_data.h @@ -147,12 +147,6 @@ public: */ virtual ssize_t vsize() const = 0; - /** - * For ArrayIter to work. Get key or value at position "pos". - */ - virtual Variant getKey(ssize_t pos) const = 0; - virtual Variant getValue(ssize_t pos) const = 0; - /** * getValueRef() gets a reference to value at position "pos". */ @@ -217,10 +211,14 @@ public: */ virtual TypedValue* nvGet(int64_t k) const = 0; virtual TypedValue* nvGet(const StringData* k) const = 0; - virtual void nvGetKey(TypedValue* out, ssize_t pos); - virtual TypedValue* nvGetValueRef(ssize_t pos); - virtual TypedValue* nvGetCell(int64_t ki) const; - virtual TypedValue* nvGetCell(const StringData* k) const; + virtual void nvGetKey(TypedValue* out, ssize_t pos) const = 0; + virtual TypedValue* nvGetCell(int64_t ki) const = 0; + virtual TypedValue* nvGetCell(const StringData* k) const = 0; + + // nonvirtual wrappers that call virtual getValueRef() + TypedValue* nvGetValueRef(ssize_t pos); + Variant getValue(ssize_t pos) const; + Variant getKey(ssize_t pos) const; /** * Getting l-value (that Variant pointer) at specified key. Return NULL if @@ -349,14 +347,14 @@ public: * This will return false if the iterator points past the last element, or * if the iterator points before the first element. */ - virtual bool validFullPos(const FullPos& fp) const; + virtual bool validFullPos(const FullPos& fp) const = 0; /** * Advances the mutable iterator to the next element in the array. Returns * false if the iterator has moved past the last element, otherwise returns * true. */ - virtual bool advanceFullPos(FullPos& fp); + virtual bool advanceFullPos(FullPos& fp) = 0; CVarRef endRef(); diff --git a/hphp/runtime/base/array/array_inline.h b/hphp/runtime/base/array/array_inline.h index 29112e903..243bf201d 100644 --- a/hphp/runtime/base/array/array_inline.h +++ b/hphp/runtime/base/array/array_inline.h @@ -151,6 +151,20 @@ inline ArrayData* ArrayData::remove(CVarRef k, bool copy) { : remove(getStringKey(cell), copy); } +inline Variant ArrayData::getValue(ssize_t pos) const { + return getValueRef(pos); +} + +inline TypedValue* ArrayData::nvGetValueRef(ssize_t pos) { + return const_cast(getValueRef(pos).asTypedValue()); +} + +inline Variant ArrayData::getKey(ssize_t pos) const { + TypedValue tv; + nvGetKey(&tv, pos); + return std::move(tvAsVariant(&tv)); +} + /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/runtime/base/array/hphp_array.cpp b/hphp/runtime/base/array/hphp_array.cpp index 115f51aa4..18ea7a843 100644 --- a/hphp/runtime/base/array/hphp_array.cpp +++ b/hphp/runtime/base/array/hphp_array.cpp @@ -264,23 +264,6 @@ ssize_t HphpArray::iter_rewind(ssize_t pos) const { return prevElm(m_data, pos); } -Variant HphpArray::getKey(ssize_t pos) const { - assert(pos != ArrayData::invalid_index); - Elm* e = &m_data[pos]; - assert(!isTombstone(e->data.m_type)); - if (e->hasStrKey()) { - return e->key; // String key. - } - return e->ikey; // Integer key. -} - -Variant HphpArray::getValue(ssize_t pos) const { - assert(pos != ArrayData::invalid_index); - Elm* e = &m_data[pos]; - assert(!isTombstone(e->data.m_type)); - return tvAsCVarRef(&e->data); -} - CVarRef HphpArray::getValueRef(ssize_t pos) const { assert(pos != ArrayData::invalid_index); Elm* e = &m_data[pos]; @@ -1202,16 +1185,9 @@ ArrayData* HphpArray::nvNew(TypedValue*& ret, bool copy) { return a; } -TypedValue* HphpArray::nvGetValueRef(ssize_t pos) { - assert(pos != ArrayData::invalid_index); - Elm* e = &m_data[/*(ElmInd)*/pos]; - assert(!isTombstone(e->data.m_type)); - return &e->data; -} - // nvGetKey does not touch out->_count, so can be used // for inner or outer cells. -void HphpArray::nvGetKey(TypedValue* out, ssize_t pos) { +void HphpArray::nvGetKey(TypedValue* out, ssize_t pos) const { assert(pos != ArrayData::invalid_index); assert(!isTombstone(m_data[pos].data.m_type)); Elm* e = &m_data[/*(ElmInd)*/pos]; diff --git a/hphp/runtime/base/array/hphp_array.h b/hphp/runtime/base/array/hphp_array.h index 0ffc05f5d..f504ff60b 100644 --- a/hphp/runtime/base/array/hphp_array.h +++ b/hphp/runtime/base/array/hphp_array.h @@ -92,8 +92,6 @@ public: // implements ArrayData ssize_t vsize() const; - Variant getKey(ssize_t pos) const; - Variant getValue(ssize_t pos) const; CVarRef getValueRef(ssize_t pos) const; // overrides ArrayData @@ -184,8 +182,7 @@ public: nextInsert(tvAsCVarRef(v)); } ArrayData* nvNew(TypedValue*& v, bool copy); - TypedValue* nvGetValueRef(ssize_t pos); - void nvGetKey(TypedValue* out, ssize_t pos); + void nvGetKey(TypedValue* out, ssize_t pos) const; bool nvInsert(StringData* k, TypedValue *v); /** diff --git a/hphp/runtime/base/array/policy_array.cpp b/hphp/runtime/base/array/policy_array.cpp index b2bb7d8ad..414cffc1d 100644 --- a/hphp/runtime/base/array/policy_array.cpp +++ b/hphp/runtime/base/array/policy_array.cpp @@ -210,18 +210,6 @@ PolicyArray::~PolicyArray() { destroy(m_size, m_allocMode); } -Variant PolicyArray::getKey(ssize_t pos) const { - APILOG << "(" << pos << ")"; - assert(size_t(pos) < m_size); - return key(toPos(pos)); -} - -Variant PolicyArray::getValue(ssize_t pos) const { - APILOG << "(" << pos << ")"; - assert(size_t(pos) < m_size); - return getValueRef(pos); -} - const Variant& PolicyArray::getValueRef(ssize_t pos) const { APILOG << "(" << pos << ")"; assert(size_t(pos) < m_size); @@ -247,18 +235,12 @@ TypedValue* PolicyArray::nvGetImpl(K k) const { : nullptr; } -void PolicyArray::nvGetKey(TypedValue* out, ssize_t pos) { +void PolicyArray::nvGetKey(TypedValue* out, ssize_t pos) const { APILOG << "(" << out << ", " << pos << ")"; assert(size_t(pos) < m_size); new(out) Variant(key(toPos(pos))); } -TypedValue* PolicyArray::nvGetValueRef(ssize_t pos) { - APILOG << "(" << pos << ")"; - assert(size_t(pos) < m_size); - return reinterpret_cast(&lval(toPos(pos))); -} - template TypedValue* PolicyArray::nvGetCellImpl(K k) const { APILOG << "(" << keystr(k) << ")"; diff --git a/hphp/runtime/base/array/policy_array.h b/hphp/runtime/base/array/policy_array.h index 844f41600..74c278f7c 100644 --- a/hphp/runtime/base/array/policy_array.h +++ b/hphp/runtime/base/array/policy_array.h @@ -357,22 +357,11 @@ public: return m_size; } - /** - * For ArrayIter to work. Get key or value at position "pos". - */ - virtual Variant getKey(ssize_t pos) const FOLLY_OVERRIDE; - virtual Variant getValue(ssize_t pos) const FOLLY_OVERRIDE; - /** * getValueRef() gets a reference to value at position "pos". */ virtual CVarRef getValueRef(ssize_t pos) const FOLLY_OVERRIDE; - /* - * Return true for array types that don't have COW semantics. - */ - virtual bool noCopyOnWrite() const FOLLY_OVERRIDE { return false; } - /* * Returns whether or not this array contains "vector-like" data. * I.e. all the keys are contiguous increasing integers. @@ -403,8 +392,7 @@ public: virtual TypedValue* nvGet(const StringData* k) const FOLLY_OVERRIDE { return nvGetImpl(k); } - virtual void nvGetKey(TypedValue* out, ssize_t pos) FOLLY_OVERRIDE; - virtual TypedValue* nvGetValueRef(ssize_t pos) FOLLY_OVERRIDE; + virtual void nvGetKey(TypedValue* out, ssize_t pos) const FOLLY_OVERRIDE; private: template TypedValue* nvGetCellImpl(K k) const; diff --git a/hphp/runtime/base/shared/shared_map.cpp b/hphp/runtime/base/shared/shared_map.cpp index 8983722d8..42094f0fb 100644 --- a/hphp/runtime/base/shared/shared_map.cpp +++ b/hphp/runtime/base/shared/shared_map.cpp @@ -196,17 +196,18 @@ TypedValue* SharedMap::nvGet(const StringData* key) const { return (TypedValue*)&getValueRef(index); } -void SharedMap::nvGetKey(TypedValue* out, ssize_t pos) { - Variant k = getKey(pos); - TypedValue* tv = k.asTypedValue(); - // copy w/out clobbering out->_count. - out->m_type = tv->m_type; - out->m_data.num = tv->m_data.num; - if (tv->m_type != KindOfInt64) out->m_data.pstr->incRefCount(); -} - -TypedValue* SharedMap::nvGetValueRef(ssize_t pos) { - return const_cast(SharedMap::getValueRef(pos).asTypedValue()); +void SharedMap::nvGetKey(TypedValue* out, ssize_t pos) const { + if (isVector()) { + out->m_data.num = pos; + out->m_type = KindOfInt64; + } else { + Variant k = m_map->getKey(pos); + TypedValue* tv = k.asTypedValue(); + // copy w/out clobbering out->_count. + out->m_type = tv->m_type; + out->m_data.num = tv->m_data.num; + if (tv->m_type != KindOfInt64) out->m_data.pstr->incRefCount(); + } } TypedValue* SharedMap::nvGetCell(int64_t k) const { @@ -253,6 +254,15 @@ ssize_t SharedMap::iter_rewind(ssize_t prev) const { return next >= 0 ? next : invalid_index; } +bool SharedMap::validFullPos(const FullPos& fp) const { + assert(fp.getContainer() == (ArrayData*)this); + return false; +} + +bool SharedMap::advanceFullPos(FullPos& fp) { + return false; +} + ArrayData* SharedMap::loadElems(bool mapInit /* = false */) const { uint count = size(); bool isVec = isVector(); diff --git a/hphp/runtime/base/shared/shared_map.h b/hphp/runtime/base/shared/shared_map.h index fa2e86135..ef8ed8b34 100644 --- a/hphp/runtime/base/shared/shared_map.h +++ b/hphp/runtime/base/shared/shared_map.h @@ -57,19 +57,10 @@ public: ssize_t vsize() const; - Variant getKey(ssize_t pos) const { - if (isVector()) { - assert(pos < (ssize_t)m_vec->m_size); - return pos; - } - return m_map->getKey(pos); - } - SharedVariant* getValueImpl(ssize_t pos) const { return isVector() ? m_vec->getValue(pos) : m_map->getValue(pos); } - Variant getValue(ssize_t pos) const { return getValueRef(pos); } CVarRef getValueRef(ssize_t pos) const; bool exists(int64_t k) const; @@ -106,8 +97,7 @@ public: */ TypedValue* nvGet(int64_t k) const; TypedValue* nvGet(const StringData* k) const; - void nvGetKey(TypedValue* out, ssize_t pos); - TypedValue* nvGetValueRef(ssize_t pos); + void nvGetKey(TypedValue* out, ssize_t pos) const; TypedValue* nvGetCell(int64_t ki) const; TypedValue* nvGetCell(const StringData* k) const; @@ -118,6 +108,9 @@ public: ssize_t iter_advance(ssize_t prev) const; ssize_t iter_rewind(ssize_t prev) const; + bool validFullPos(const FullPos& fp) const; + bool advanceFullPos(FullPos& fp); + /** * Memory allocator methods. */ diff --git a/hphp/runtime/vm/name_value_table_wrapper.cpp b/hphp/runtime/vm/name_value_table_wrapper.cpp index 23f14ec4c..f15d59f9b 100644 --- a/hphp/runtime/vm/name_value_table_wrapper.cpp +++ b/hphp/runtime/vm/name_value_table_wrapper.cpp @@ -35,14 +35,16 @@ ssize_t NameValueTableWrapper::vsize() const { return count; } -Variant NameValueTableWrapper::getKey(ssize_t pos) const { +void NameValueTableWrapper::nvGetKey(TypedValue* out, ssize_t pos) const { NameValueTable::Iterator iter(m_tab, pos); - return iter.valid() ? Variant(StrNR(iter.curKey())) : uninit_null(); -} - -Variant NameValueTableWrapper::getValue(ssize_t pos) const { - NameValueTable::Iterator iter(m_tab, pos); - return iter.valid() ? tvAsCVarRef(iter.curVal()) : null_variant; + if (iter.valid()) { + auto k = iter.curKey(); + out->m_data.pstr = const_cast(k); + out->m_type = KindOfString; + k->incRefCount(); + } else { + out->m_type = KindOfUninit; + } } CVarRef NameValueTableWrapper::getValueRef(ssize_t pos) const { @@ -76,6 +78,16 @@ TypedValue* NameValueTableWrapper::nvGet(int64_t k) const { return m_tab->lookup(String(k).get()); } +TypedValue* NameValueTableWrapper::nvGetCell(int64_t k) const { + TypedValue* tv = NameValueTableWrapper::nvGet(k); + return tv ? tvToCell(tv) : nvGetNotFound(k); +} + +TypedValue* NameValueTableWrapper::nvGetCell(const StringData* key) const { + TypedValue* tv = NameValueTableWrapper::nvGet(key); + return tv ? tvToCell(tv) : nvGetNotFound(key); +} + ArrayData* NameValueTableWrapper::lval(int64_t k, Variant*& ret, bool copy, bool checkExist) { return lval(String(k), ret, copy, checkExist); diff --git a/hphp/runtime/vm/name_value_table_wrapper.h b/hphp/runtime/vm/name_value_table_wrapper.h index 2b384bd68..75f572084 100644 --- a/hphp/runtime/vm/name_value_table_wrapper.h +++ b/hphp/runtime/vm/name_value_table_wrapper.h @@ -77,8 +77,7 @@ public: // ArrayData implementation } virtual ssize_t vsize() const; - virtual Variant getKey(ssize_t pos) const; - virtual Variant getValue(ssize_t pos) const; + virtual void nvGetKey(TypedValue* out, ssize_t pos) const; virtual CVarRef getValueRef(ssize_t pos) const; virtual bool noCopyOnWrite() const; @@ -88,6 +87,8 @@ public: // ArrayData implementation virtual TypedValue* nvGet(int64_t k) const; virtual TypedValue* nvGet(const StringData* k) const; + virtual TypedValue* nvGetCell(int64_t ki) const; + virtual TypedValue* nvGetCell(const StringData* k) const; virtual ArrayData* lval(int64_t k, Variant*& ret, bool copy, bool checkExist = false);