Devirtualize ArrayData part 1

Moves about half of ArrayData virtual methods to g_array_funcs as
static functions instead of virtual functions.  This is mostly a
mechanical factor, except a handful of methods that are specialized
for Vector instead of generic HphpArray.
Esse commit está contido em:
Edwin Smith
2013-07-06 15:02:49 -07:00
commit de Sara Golemon
commit 49915fe2e6
12 arquivos alterados com 932 adições e 465 exclusões
+94
Ver Arquivo
@@ -193,6 +193,100 @@ inline ArrayData* ArrayData::set(StringData* k, CVarRef v, bool copy) {
return g_array_funcs.setStr[m_kind](this, k, v, copy);
}
inline size_t ArrayData::vsize() const {
return g_array_funcs.vsize[m_kind](this);
}
inline CVarRef ArrayData::getValueRef(ssize_t pos) const {
return g_array_funcs.getValueRef[m_kind](this, pos);
}
inline bool ArrayData::noCopyOnWrite() const {
return g_array_funcs.noCopyOnWrite[m_kind];
}
inline bool ArrayData::isVectorData() const {
return g_array_funcs.isVectorData[m_kind](this);
}
inline bool ArrayData::exists(int64_t k) const {
return g_array_funcs.existsInt[m_kind](this, k);
}
inline bool ArrayData::exists(const StringData* k) const {
return g_array_funcs.existsStr[m_kind](this, k);
}
inline ArrayData* ArrayData::lval(int64_t k, Variant*& ret, bool copy) {
return g_array_funcs.lvalInt[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::lval(StringData* k, Variant*& ret, bool copy) {
return g_array_funcs.lvalStr[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::lvalNew(Variant*& ret, bool copy) {
return g_array_funcs.lvalNew[m_kind](this, ret, copy);
}
inline ArrayData* ArrayData::createLvalPtr(StringData* k, Variant*& ret,
bool copy) {
return g_array_funcs.createLvalPtr[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::getLvalPtr(StringData* k, Variant*& ret,
bool copy) {
return g_array_funcs.getLvalPtr[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::setRef(int64_t k, CVarRef v, bool copy) {
return g_array_funcs.setRefInt[m_kind](this, k, v, copy);
}
inline ArrayData* ArrayData::setRef(StringData* k, CVarRef v, bool copy) {
return g_array_funcs.setRefStr[m_kind](this, k, v, copy);
}
inline ArrayData* ArrayData::add(int64_t k, CVarRef v, bool copy) {
return g_array_funcs.addInt[m_kind](this, k, v, copy);
}
inline ArrayData* ArrayData::add(StringData* k, CVarRef v, bool copy) {
return g_array_funcs.addStr[m_kind](this, k, v, copy);
}
inline ArrayData* ArrayData::addLval(int64_t k, Variant *&ret, bool copy) {
return g_array_funcs.addLvalInt[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::addLval(StringData* k, Variant *&ret, bool copy) {
return g_array_funcs.addLvalStr[m_kind](this, k, ret, copy);
}
inline ArrayData* ArrayData::remove(int64_t k, bool copy) {
return g_array_funcs.removeInt[m_kind](this, k, copy);
}
inline ArrayData* ArrayData::remove(const StringData* k, bool copy) {
return g_array_funcs.removeStr[m_kind](this, k, copy);
}
inline ssize_t ArrayData::iter_begin() const {
return g_array_funcs.iterBegin[m_kind](this);
}
inline ssize_t ArrayData::iter_end() const {
return g_array_funcs.iterEnd[m_kind](this);
}
inline ssize_t ArrayData::iter_advance(ssize_t pos) const {
return g_array_funcs.iterAdvance[m_kind](this, pos);
}
inline ssize_t ArrayData::iter_rewind(ssize_t pos) const {
return g_array_funcs.iterRewind[m_kind](this, pos);
}
///////////////////////////////////////////////////////////////////////////////
}
+124 -22
Ver Arquivo
@@ -64,6 +64,11 @@ ArrayData *ArrayData::GetScalarArray(ArrayData *arr,
///////////////////////////////////////////////////////////////////////////////
static size_t VsizeNop(const ArrayData* ad) {
assert(false);
return ad->getSize();
}
// order: kVectorKind, kMixedKind, kSharedKind, kNvtwKind, kPolicyKind
extern const ArrayFunctions g_array_funcs = {
// release
@@ -101,6 +106,121 @@ extern const ArrayFunctions g_array_funcs = {
&SharedMap::SetStr,
&NameValueTableWrapper::SetStr,
&PolicyArray::SetStr },
// vsize
{ &VsizeNop, &VsizeNop,
&VsizeNop,
&NameValueTableWrapper::Vsize,
&VsizeNop },
// getValueRef
{ &HphpArray::GetValueRef, &HphpArray::GetValueRef,
&SharedMap::GetValueRef,
&NameValueTableWrapper::GetValueRef,
&PolicyArray::GetValueRef },
// noCopyOnWrite
{ false, false,
false,
true, // NameValueTableWrapper doesn't support COW.
false },
// isVectorData
{ &HphpArray::IsVectorDataVec, &HphpArray::IsVectorData,
&SharedMap::IsVectorData,
&NameValueTableWrapper::IsVectorData,
&PolicyArray::IsVectorData },
// existsInt
{ &HphpArray::ExistsIntVec, &HphpArray::ExistsInt,
&SharedMap::ExistsInt,
&NameValueTableWrapper::ExistsInt,
&PolicyArray::ExistsInt },
// existsStr
{ &HphpArray::ExistsStrVec, &HphpArray::ExistsStr,
&SharedMap::ExistsStr,
&NameValueTableWrapper::ExistsStr,
&PolicyArray::ExistsStr },
// lvalInt
{ &HphpArray::LvalIntVec, &HphpArray::LvalInt,
&SharedMap::LvalInt,
&NameValueTableWrapper::LvalInt,
&PolicyArray::LvalInt },
// lvalStr
{ &HphpArray::LvalStrVec, &HphpArray::LvalStr,
&SharedMap::LvalStr,
&NameValueTableWrapper::LvalStr,
&PolicyArray::LvalStr },
// lvalNew
{ &HphpArray::LvalNewVec, &HphpArray::LvalNew,
&SharedMap::LvalNew,
&NameValueTableWrapper::LvalNew,
&PolicyArray::LvalNew },
// createLvalPtr
{ &HphpArray::CreateLvalPtrVec, &HphpArray::CreateLvalPtr,
&ArrayData::CreateLvalPtr, // fatal
&ArrayData::CreateLvalPtr, // fatal
&PolicyArray::CreateLvalPtr },
// getLvalPtr
{ &HphpArray::GetLvalPtrVec, &HphpArray::GetLvalPtr,
&ArrayData::GetLvalPtr, // fatal
&ArrayData::GetLvalPtr, // fatal
&PolicyArray::GetLvalPtr },
// setRefInt
{ &HphpArray::SetRefIntVec, &HphpArray::SetRefInt,
&SharedMap::SetRefInt,
&NameValueTableWrapper::SetRefInt,
&PolicyArray::SetRefInt },
// setRefStr
{ &HphpArray::SetRefStrVec, &HphpArray::SetRefStr,
&SharedMap::SetRefStr,
&NameValueTableWrapper::SetRefStr,
&PolicyArray::SetRefStr },
// addInt
{ &HphpArray::AddIntVec, &HphpArray::AddInt,
&SharedMap::SetInt, // reuse set
&NameValueTableWrapper::SetInt, // reuse set
&PolicyArray::AddInt },
// addStr
{ &HphpArray::AddStrVec, &HphpArray::AddStr,
&SharedMap::SetStr, // reuse set
&NameValueTableWrapper::SetStr, // reuse set
&PolicyArray::AddStr },
// addLvalInt
{ &HphpArray::AddLvalIntVec, &HphpArray::AddLvalInt,
&SharedMap::AddLvalInt,
&NameValueTableWrapper::AddLvalInt,
&PolicyArray::AddLvalInt },
// addLvalStr
{ &HphpArray::AddLvalStrVec, &HphpArray::AddLvalStr,
&SharedMap::AddLvalStr,
&NameValueTableWrapper::AddLvalStr,
&PolicyArray::AddLvalStr },
// removeInt
{ &HphpArray::RemoveIntVec, &HphpArray::RemoveInt,
&SharedMap::RemoveInt,
&NameValueTableWrapper::RemoveInt,
&PolicyArray::RemoveInt },
// removeStr
{ &HphpArray::RemoveStrVec, &HphpArray::RemoveStr,
&SharedMap::RemoveStr,
&NameValueTableWrapper::RemoveStr,
&PolicyArray::RemoveStr },
// iterBegin
{ &HphpArray::IterBegin, &HphpArray::IterBegin,
&SharedMap::IterBegin,
&NameValueTableWrapper::IterBegin,
&PolicyArray::IterBegin },
// iterEnd
{ &HphpArray::IterEnd, &HphpArray::IterEnd,
&SharedMap::IterEnd,
&NameValueTableWrapper::IterEnd,
&PolicyArray::IterEnd },
// iterAdvance
{ &HphpArray::IterAdvance, &HphpArray::IterAdvance,
&SharedMap::IterAdvance,
&NameValueTableWrapper::IterAdvance,
&PolicyArray::IterAdvance },
// iterRewind
{ &HphpArray::IterRewind, &HphpArray::IterRewind,
&SharedMap::IterRewind,
&NameValueTableWrapper::IterRewind,
&PolicyArray::IterRewind },
};
///////////////////////////////////////////////////////////////////////////////
@@ -218,34 +338,16 @@ bool ArrayData::equal(const ArrayData *v2, bool strict) const {
return true;
}
ArrayData *ArrayData::createLvalPtr(StringData* k, Variant *&ret, bool copy) {
ArrayData *ArrayData::CreateLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
throw FatalErrorException("Unimplemented ArrayData::createLvalPtr");
}
ArrayData *ArrayData::getLvalPtr(StringData* k, Variant *&ret, bool copy) {
ArrayData *ArrayData::GetLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
throw FatalErrorException("Unimplemented ArrayData::getLvalPtr");
}
ArrayData *ArrayData::add(int64_t k, CVarRef v, bool copy) {
assert(!exists(k));
return set(k, v, copy);
}
ArrayData *ArrayData::add(StringData* k, CVarRef v, bool copy) {
assert(!exists(k));
return set(k, v, copy);
}
ArrayData *ArrayData::addLval(int64_t k, Variant *&ret, bool copy) {
assert(!exists(k));
return lval(k, ret, copy);
}
ArrayData *ArrayData::addLval(StringData* k, Variant *&ret, bool copy) {
assert(!exists(k));
return lval(k, ret, copy);
}
///////////////////////////////////////////////////////////////////////////////
// stack and queue operations
+64 -24
Ver Arquivo
@@ -144,25 +144,32 @@ public:
/**
* Number of elements this array has.
*/
ssize_t size() const {
size_t size() const {
if (UNLIKELY((int)m_size) < 0) return vsize();
return m_size;
}
// unlike ArrayData::size(), this functions doesn't delegate
// to the virtual Vsize() function, so its more efficient to
// use this when you know you don't have a NameValueTableWrapper.
size_t getSize() const {
return m_size;
}
/**
* Number of elements this array has.
*/
virtual ssize_t vsize() const = 0;
size_t vsize() const;
/**
* getValueRef() gets a reference to value at position "pos".
*/
virtual CVarRef getValueRef(ssize_t pos) const = 0;
CVarRef getValueRef(ssize_t pos) const;
/*
* Return true for array types that don't have COW semantics.
*/
virtual bool noCopyOnWrite() const { return false; }
bool noCopyOnWrite() const;
/*
* Specific derived class type querying operators.
@@ -183,7 +190,7 @@ public:
* Returns whether or not this array contains "vector-like" data.
* I.e. all the keys are contiguous increasing integers.
*/
virtual bool isVectorData() const = 0;
bool isVectorData() const;
/**
* Whether or not this array has a referenced Variant or Object appearing
@@ -213,8 +220,8 @@ public:
/**
* Testing whether a key exists.
*/
virtual bool exists(int64_t k) const = 0;
virtual bool exists(const StringData* k) const = 0;
bool exists(int64_t k) const;
bool exists(const StringData* k) const;
/**
* Interface for VM helpers. ArrayData implements generic versions
@@ -236,8 +243,8 @@ public:
* Getting l-value (that Variant pointer) at specified key. Return this if
* escalation is not needed, or an escalated array data.
*/
virtual ArrayData *lval(int64_t k, Variant *&ret, bool copy) = 0;
virtual ArrayData *lval(StringData* k, Variant *&ret, bool copy) = 0;
ArrayData *lval(int64_t k, Variant *&ret, bool copy);
ArrayData *lval(StringData* k, Variant *&ret, bool copy);
/**
* Getting l-value (that Variant pointer) of a new element with the next
@@ -246,15 +253,19 @@ public:
* available integer key may fail, in which case ret is set to point to
* the lval blackhole (see Variant::lvalBlackHole() for details).
*/
virtual ArrayData *lvalNew(Variant *&ret, bool copy) = 0;
ArrayData *lvalNew(Variant *&ret, bool copy);
/**
* Helper functions used for getting a reference to elements of
* the dynamic property array in ObjectData or the local cache array
* in ShardMap.
*/
virtual ArrayData *createLvalPtr(StringData* k, Variant *&ret, bool copy);
virtual ArrayData *getLvalPtr(StringData* k, Variant *&ret, bool copy);
ArrayData *createLvalPtr(StringData* k, Variant *&ret, bool copy);
ArrayData *getLvalPtr(StringData* k, Variant *&ret, bool copy);
static ArrayData *CreateLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy);
static ArrayData *GetLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy);
/**
* Setting a value at specified key. If "copy" is true, make a copy first
@@ -264,31 +275,31 @@ public:
ArrayData *set(int64_t k, CVarRef v, bool copy);
ArrayData *set(StringData* k, CVarRef v, bool copy);
virtual ArrayData *setRef(int64_t k, CVarRef v, bool copy) = 0;
virtual ArrayData *setRef(StringData* k, CVarRef v, bool copy) = 0;
ArrayData *setRef(int64_t k, CVarRef v, bool copy);
ArrayData *setRef(StringData* k, CVarRef v, bool copy);
/**
* The same as set(), but with the precondition that the key does
* not already exist in this array. (This is to allow more
* efficient implementation of this case in some derived classes.)
*/
virtual ArrayData *add(int64_t k, CVarRef v, bool copy);
virtual ArrayData *add(StringData* k, CVarRef v, bool copy);
ArrayData *add(int64_t k, CVarRef v, bool copy);
ArrayData *add(StringData* k, CVarRef v, bool copy);
/*
* Same semantics as lval(), except with the precondition that the
* key doesn't already exist in the array.
*/
virtual ArrayData *addLval(int64_t k, Variant *&ret, bool copy);
virtual ArrayData *addLval(StringData* k, Variant *&ret, bool copy);
ArrayData *addLval(int64_t k, Variant *&ret, bool copy);
ArrayData *addLval(StringData* k, Variant *&ret, bool copy);
/**
* Remove a value at specified key. If "copy" is true, make a copy first
* then remove the value. Return this if escalation is not needed, or an
* escalated array data.
*/
virtual ArrayData *remove(int64_t k, bool copy) = 0;
virtual ArrayData *remove(const StringData* k, bool copy) = 0;
ArrayData *remove(int64_t k, bool copy);
ArrayData *remove(const StringData* k, bool copy);
/**
* Inline accessors that convert keys to StringData* before delegating to
@@ -317,10 +328,10 @@ public:
ArrayData *remove(CStrRef k, bool copy);
ArrayData *remove(CVarRef k, bool copy);
virtual ssize_t iter_begin() const = 0;
virtual ssize_t iter_end() const = 0;
virtual ssize_t iter_advance(ssize_t prev) const = 0;
virtual ssize_t iter_rewind(ssize_t prev) const = 0;
ssize_t iter_begin() const;
ssize_t iter_end() const;
ssize_t iter_advance(ssize_t prev) const;
ssize_t iter_rewind(ssize_t prev) const;
/**
* Mutable iteration APIs
@@ -529,6 +540,35 @@ struct ArrayFunctions {
void (*nvGetKey[NK])(const ArrayData*, TypedValue* out, ssize_t pos);
ArrayData* (*setInt[NK])(ArrayData*, int64_t k, CVarRef v, bool copy);
ArrayData* (*setStr[NK])(ArrayData*, StringData* k, CVarRef v, bool copy);
size_t (*vsize[NK])(const ArrayData*);
CVarRef (*getValueRef[NK])(const ArrayData*, ssize_t pos);
bool noCopyOnWrite[NK];
bool (*isVectorData[NK])(const ArrayData*);
bool (*existsInt[NK])(const ArrayData*, int64_t k);
bool (*existsStr[NK])(const ArrayData*, const StringData* k);
ArrayData* (*lvalInt[NK])(ArrayData*, int64_t k, Variant*& ret,
bool copy);
ArrayData* (*lvalStr[NK])(ArrayData*, StringData* k, Variant*& ret,
bool copy);
ArrayData* (*lvalNew[NK])(ArrayData*, Variant *&ret, bool copy);
ArrayData* (*createLvalPtr[NK])(ArrayData*, StringData* k, Variant *&ret,
bool copy);
ArrayData* (*getLvalPtr[NK])(ArrayData*, StringData* k, Variant *&ret,
bool copy);
ArrayData* (*setRefInt[NK])(ArrayData*, int64_t k, CVarRef v, bool copy);
ArrayData* (*setRefStr[NK])(ArrayData*, StringData* k, CVarRef v, bool copy);
ArrayData* (*addInt[NK])(ArrayData*, int64_t k, CVarRef v, bool copy);
ArrayData* (*addStr[NK])(ArrayData*, StringData* k, CVarRef v, bool copy);
ArrayData* (*addLvalInt[NK])(ArrayData*, int64_t k, Variant *&ret,
bool copy);
ArrayData* (*addLvalStr[NK])(ArrayData*, StringData* k, Variant *&ret,
bool copy);
ArrayData* (*removeInt[NK])(ArrayData*, int64_t k, bool copy);
ArrayData* (*removeStr[NK])(ArrayData*, const StringData* k, bool copy);
ssize_t (*iterBegin[NK])(const ArrayData*);
ssize_t (*iterEnd[NK])(const ArrayData*);
ssize_t (*iterAdvance[NK])(const ArrayData*, ssize_t pos);
ssize_t (*iterRewind[NK])(const ArrayData*, ssize_t pos);
};
extern const ArrayFunctions g_array_funcs;
+16 -4
Ver Arquivo
@@ -103,6 +103,20 @@ void HphpArray::getArrayElm(ssize_t pos, TypedValue* valOut,
}
}
inline HphpArray* HphpArray::asHphpArray(ArrayData* ad) {
assert(ad->isHphpArray());
auto a = static_cast<HphpArray*>(ad);
assert(a->checkInvariants());
return a;
}
inline const HphpArray* HphpArray::asHphpArray(const ArrayData* ad) {
assert(ad->isHphpArray());
auto a = static_cast<const HphpArray*>(ad);
assert(a->checkInvariants());
return a;
}
inline HphpArray* HphpArray::asVector(ArrayData* ad) {
assert(ad->kind() == kVectorKind);
assert(dynamic_cast<HphpArray*>(ad));
@@ -119,17 +133,15 @@ inline const HphpArray* HphpArray::asVector(const ArrayData* ad) {
return a;
}
inline HphpArray* HphpArray::asHphpArray(ArrayData* ad) {
inline HphpArray* HphpArray::asGeneric(ArrayData* ad) {
assert(ad->kind() == kMixedKind);
assert(dynamic_cast<HphpArray*>(ad));
auto a = static_cast<HphpArray*>(ad);
assert(a->checkInvariants());
return a;
}
inline const HphpArray* HphpArray::asHphpArray(const ArrayData* ad) {
inline const HphpArray* HphpArray::asGeneric(const ArrayData* ad) {
assert(ad->kind() == kMixedKind);
assert(dynamic_cast<const HphpArray*>(ad));
auto a = static_cast<const HphpArray*>(ad);
assert(a->checkInvariants());
return a;
+260 -159
Ver Arquivo
@@ -244,7 +244,7 @@ void HphpArray::ReleaseVec(ArrayData* ad) {
HOT_FUNC_VM
void HphpArray::Release(ArrayData* ad) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
a->destroy();
if (UNLIKELY(a->strongIterators() != nullptr)) a->freeStrongIterators();
HphpArray::AllocatorType::getNoCheck()->dealloc(a);
@@ -345,12 +345,6 @@ bool HphpArray::checkInvariants() const {
return true;
}
ssize_t HphpArray::vsize() const {
assert(false && "vsize() called, but m_size should "
"never be -1 in HphpArray");
return m_size;
}
//=============================================================================
// Iteration.
@@ -365,26 +359,26 @@ inline ssize_t HphpArray::prevElm(Elm* elms, ssize_t ei) const {
return (ssize_t)ElmIndEmpty;
}
ssize_t HphpArray::iter_begin() const {
assert(checkInvariants());
return nextElm(m_data, ElmIndEmpty);
ssize_t HphpArray::IterBegin(const ArrayData* ad) {
auto a = asHphpArray(ad);
return a->nextElm(a->m_data, ElmIndEmpty);
}
ssize_t HphpArray::iter_end() const {
assert(checkInvariants());
return prevElm(m_data, m_used);
ssize_t HphpArray::IterEnd(const ArrayData* ad) {
auto a = asHphpArray(ad);
return a->prevElm(a->m_data, a->m_used);
}
ssize_t HphpArray::iter_advance(ssize_t pos) const {
assert(checkInvariants());
assert(ArrayData::invalid_index == -1);
ssize_t HphpArray::IterAdvance(const ArrayData* ad, ssize_t pos) {
auto a = asHphpArray(ad);
// Since m_used is always less than 2^32 and invalid_index == -1,
// we can save a check by doing an unsigned comparison instead
// of a signed comparison.
if (size_t(++pos) < m_used && !isTombstone(m_data[pos].data.m_type)) {
if (size_t(++pos) < a->m_used && !isTombstone(a->m_data[pos].data.m_type)) {
return pos;
}
return iter_advance_helper(pos);
return a->iter_advance_helper(pos);
static_assert(invalid_index == -1, "");
}
// caller has already incremented pos but encountered a tombstone
@@ -398,40 +392,43 @@ ssize_t HphpArray::iter_advance_helper(ssize_t next_pos) const {
return next_pos;
}
}
return ArrayData::invalid_index;
return invalid_index;
}
ssize_t HphpArray::iter_rewind(ssize_t pos) const {
assert(checkInvariants());
if (pos == ArrayData::invalid_index) {
return ArrayData::invalid_index;
}
return prevElm(m_data, pos);
ssize_t HphpArray::IterRewind(const ArrayData* ad, ssize_t pos) {
if (pos == invalid_index) return invalid_index;
auto a = asHphpArray(ad);
return a->prevElm(a->m_data, pos);
}
CVarRef HphpArray::getValueRef(ssize_t pos) const {
assert(checkInvariants());
CVarRef HphpArray::GetValueRef(const ArrayData* ad, ssize_t pos) {
auto a = asHphpArray(ad);
assert(a->checkInvariants());
assert(pos != ArrayData::invalid_index);
Elm* e = &m_data[pos];
Elm* e = &a->m_data[pos];
assert(!isTombstone(e->data.m_type));
return tvAsCVarRef(&e->data);
}
bool HphpArray::isVectorData() const {
assert(checkInvariants());
if (m_size == 0 || isVector()) {
bool HphpArray::IsVectorDataVec(const ArrayData*) {
return true;
}
bool HphpArray::IsVectorData(const ArrayData* ad) {
auto a = asGeneric(ad);
if (a->m_size == 0) {
// any 0-length array is "vector-like" for the sake of this
// function, even if m_kind != kVector.
return true;
}
Elm* elms = m_data;
auto const elms = a->m_data;
int64_t i = 0;
for (uint32_t pos = 0, limit = m_used; pos < limit; ++pos) {
Elm* e = &elms[pos];
if (isTombstone(e->data.m_type)) {
for (uint32_t pos = 0, limit = a->m_used; pos < limit; ++pos) {
auto const& e = elms[pos];
if (isTombstone(e.data.m_type)) {
continue;
}
if (e->hasStrKey() || e->ikey != i) {
if (e.hasStrKey() || e.ikey != i) {
return false;
}
++i;
@@ -606,16 +603,24 @@ HphpArray::findForNewInsertLoop(size_t tableMask, size_t h0) const {
}
}
bool HphpArray::exists(int64_t k) const {
assert(checkInvariants());
if (isVector()) return size_t(k) < m_size;
return find(k) != ElmIndEmpty;
bool HphpArray::ExistsIntVec(const ArrayData* ad, int64_t k) {
auto a = asVector(ad);
return size_t(k) < a->m_size;
}
bool HphpArray::exists(const StringData* k) const {
assert(checkInvariants());
if (isVector()) return false;
return find(k, k->hash()) != ElmIndEmpty;
bool HphpArray::ExistsInt(const ArrayData* ad, int64_t k) {
auto a = asGeneric(ad);
return a->find(k) != ElmIndEmpty;
}
bool HphpArray::ExistsStrVec(const ArrayData* ad, const StringData* k) {
assert(asVector(ad));
return false;
}
bool HphpArray::ExistsStr(const ArrayData* ad, const StringData* k) {
auto a = asGeneric(ad);
return a->find(k, k->hash()) != ElmIndEmpty;
}
//=============================================================================
@@ -1069,19 +1074,7 @@ ArrayData* HphpArray::update(StringData* key, CVarRef data) {
}
ArrayData* HphpArray::updateRef(int64_t ki, CVarRef data) {
if (isVector()) {
if (size_t(ki) < m_size) {
tvAsVariant(&m_data[ki].data).assignRefHelper(data);
return this;
}
if (size_t(ki) == m_size) {
auto& tv = allocNextElm(ki);
tvAsUninitializedVariant(&tv).constructRefHelper(data);
return this;
}
vectorToGeneric();
// todo t2606310: key can't exist. use add/findForNewInsert
}
assert(!isVector());
ElmInd* ei = findForInsert(ki);
if (validElmInd(*ei)) {
Elm* e = &m_data[*ei];
@@ -1096,10 +1089,7 @@ ArrayData* HphpArray::updateRef(int64_t ki, CVarRef data) {
}
ArrayData* HphpArray::updateRef(StringData* key, CVarRef data) {
if (isVector()) {
vectorToGeneric();
// todo t2606310: key can't exist. use add/findForNewInsert
}
assert(!isVector());
strhash_t h = key->hash();
ElmInd* ei = findForInsert(key, h);
if (validElmInd(*ei)) {
@@ -1111,44 +1101,90 @@ ArrayData* HphpArray::updateRef(StringData* key, CVarRef data) {
return this;
}
ArrayData* HphpArray::lval(int64_t k, Variant*& ret, bool copy) {
assert(checkInvariants());
return (!copy ? this : copyImpl())->addLvalImpl(k, &ret);
// return true if Elm contains a Reference that won't be flattened
// by a copy, or an object.
static inline bool isContainer(const TypedValue& tv) {
auto& v = tvAsCVarRef(&tv);
return v.isReferenced() || v.isObject();
}
ArrayData* HphpArray::lval(StringData* key, Variant*& ret, bool copy) {
assert(checkInvariants());
return (!copy ? this : copyImpl())->addLvalImpl(key, key->hash(), &ret);
ArrayData* HphpArray::LvalIntVec(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
auto a = asVector(ad);
return (!copy ? a : a->copyImpl())->addLvalImpl(k, &ret);
}
ArrayData *HphpArray::createLvalPtr(StringData* key, Variant*& ret, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
ArrayData* HphpArray::LvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
auto a = asGeneric(ad);
return (!copy ? a : a->copyImpl())->addLvalImpl(k, &ret);
}
ArrayData* HphpArray::LvalStrVec(ArrayData* ad, StringData* key, Variant*& ret,
bool copy) {
auto a = asVector(ad);
return (!copy ? a : a->copyImpl())->addLvalImpl(key, key->hash(), &ret);
}
ArrayData* HphpArray::LvalStr(ArrayData* ad, StringData* key, Variant*& ret,
bool copy) {
auto a = asGeneric(ad);
return (!copy ? a : a->copyImpl())->addLvalImpl(key, key->hash(), &ret);
}
ArrayData *HphpArray::CreateLvalPtrVec(ArrayData* ad, StringData* key,
Variant*& ret, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
return a->vectorToGeneric()->addLvalImpl(key, key->hash(), &ret);
// todo: we know the key can't exist; use specialized addLvalImpl
}
ArrayData *HphpArray::CreateLvalPtr(ArrayData* ad, StringData* key,
Variant*& ret, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->addLvalImpl(key, key->hash(), &ret);
}
ArrayData *HphpArray::getLvalPtr(StringData* key, Variant*& ret, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
auto pos = a->find(key, key->hash());
if (pos != ElmIndEmpty) {
Elm* e = &a->m_data[pos];
ret = &tvAsVariant(&e->data);
} else {
ret = nullptr;
}
ArrayData *HphpArray::GetLvalPtrVec(ArrayData* ad, StringData* key,
Variant*& ret, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
// todo: we didn't have to copy since we didn't mutate. Or, should
// we have just escalate to generic anyway? and, why isn't this
// method const?
ret = nullptr;
return a;
}
ArrayData* HphpArray::lvalNew(Variant*& ret, bool copy) {
assert(checkInvariants());
TypedValue* tv;
ArrayData* a = nvNew(tv, copy);
if (tv == nullptr) {
ret = &(Variant::lvalBlackHole());
} else {
ret = &tvAsVariant(tv);
ArrayData *HphpArray::GetLvalPtr(ArrayData* ad, StringData* key,
Variant*& ret, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
auto pos = a->find(key, key->hash());
ret = pos != ElmIndEmpty ? &tvAsVariant(&a->m_data[pos].data) :
nullptr;
return a;
}
ArrayData* HphpArray::LvalNewVec(ArrayData* ad, Variant*& ret, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
auto& tv = a->allocNextElm(a->m_size);
tvWriteUninit(&tv);
ret = &tvAsVariant(&tv);
return a;
}
ArrayData* HphpArray::LvalNew(ArrayData* ad, Variant*& ret, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
if (UNLIKELY(!a->nextInsert(uninit_null()))) {
ret = &Variant::lvalBlackHole();
return a;
}
ret = &tvAsVariant(&a->m_data[a->m_used - 1].data);
return a;
}
@@ -1170,7 +1206,7 @@ HphpArray::SetIntVec(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
}
ArrayData* HphpArray::SetInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->update(k, v);
}
@@ -1185,58 +1221,127 @@ HphpArray::SetStrVec(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
ArrayData*
HphpArray::SetStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->update(k, v);
}
ArrayData* HphpArray::setRef(int64_t k, CVarRef v, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
return a->updateRef(k, v);
}
ArrayData* HphpArray::setRef(StringData* k, CVarRef v, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
return a->updateRef(k, v);
}
ArrayData* HphpArray::add(int64_t k, CVarRef v, bool copy) {
assert(checkInvariants());
assert(!exists(k));
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) {
if (size_t(k) == a->m_size) {
auto& tv = a->allocNextElm(k);
elemConstruct((TypedValue*)&v, &tv);
return a;
}
a->vectorToGeneric();
ArrayData*
HphpArray::SetRefIntVec(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
if (size_t(k) < a->m_size) {
tvAsVariant(&a->m_data[k].data).assignRefHelper(v);
return a;
}
if (size_t(k) == a->m_size) {
auto& tv = a->allocNextElm(k);
tvAsUninitializedVariant(&tv).constructRefHelper(v);
return a;
}
// todo t2606310: key can't exist. use add/findForNewInsert
return a->vectorToGeneric()->updateRef(k, v);
}
ArrayData*
HphpArray::SetRefInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->updateRef(k, v);
}
ArrayData*
HphpArray::SetRefStrVec(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
return a->vectorToGeneric()->updateRef(k, v);
}
ArrayData*
HphpArray::SetRefStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyVec();
// todo t2606310: key can't exist. use add/findForNewInsert
return a->updateRef(k, v);
}
ArrayData*
HphpArray::AddIntVec(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
assert(!ad->exists(k));
auto a = asVector(ad);
if (copy) a = a->copyVec();
if (size_t(k) == a->m_size) {
auto& tv = a->allocNextElm(k);
elemConstruct((TypedValue*)&v, &tv);
return a;
}
return a->vectorToGeneric()->addVal(k, v);
}
ArrayData*
HphpArray::AddInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
assert(!ad->exists(k));
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->addVal(k, v);
}
ArrayData* HphpArray::add(StringData* k, CVarRef v, bool copy) {
assert(checkInvariants());
assert(!exists(k));
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) a->vectorToGeneric();
ArrayData*
HphpArray::AddStrVec(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
assert(!ad->exists(k));
auto a = asVector(ad);
if (copy) a = a->copyVec();
return a->vectorToGeneric()->addVal(k, v);
}
ArrayData*
HphpArray::AddStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
assert(!ad->exists(k));
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->addVal(k, v);
}
ArrayData* HphpArray::addLval(int64_t k, Variant*& ret, bool copy) {
assert(checkInvariants());
assert(!exists(k));
HphpArray* a = !copy ? this : copyImpl();
ArrayData*
HphpArray::AddLvalIntVec(ArrayData* ad, int64_t k, Variant*& ret, bool copy) {
assert(!ad->exists(k));
auto a = asVector(ad);
if (copy) a = a->copyVec();
if (size_t(k) < a->m_size) {
ret = &tvAsVariant(&a->m_data[k].data);
return a;
}
if (size_t(k) == a->m_size) {
auto& tv = a->allocNextElm(k);
tvWriteNull(&tv);
ret = &(tvAsVariant(&tv));
return a;
}
return a->vectorToGeneric()->addLvalImpl(k, &ret);
}
ArrayData*
HphpArray::AddLvalInt(ArrayData* ad, int64_t k, Variant*& ret, bool copy) {
assert(!ad->exists(k));
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->addLvalImpl(k, &ret);
}
ArrayData* HphpArray::addLval(StringData* k, Variant*& ret, bool copy) {
assert(checkInvariants());
assert(!exists(k));
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) a->vectorToGeneric();
ArrayData*
HphpArray::AddLvalStrVec(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
assert(!ad->exists(k));
auto a = asVector(ad);
if (copy) a = a->copyVec();
return a->vectorToGeneric()->addLvalImpl(k, k->hash(), &ret);
}
ArrayData*
HphpArray::AddLvalStr(ArrayData* ad, StringData* k, Variant*& ret, bool copy) {
assert(!ad->exists(k));
auto a = asGeneric(ad);
if (copy) a = a->copyVec();
return a->addLvalImpl(k, k->hash(), &ret);
}
@@ -1319,20 +1424,34 @@ ArrayData* HphpArray::erase(ElmInd* ei, bool updateNext /* = false */) {
return this;
}
ArrayData* HphpArray::remove(int64_t k, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) {
// todo t2606310: what is probability of (k == size-1)
ArrayData* HphpArray::RemoveIntVec(ArrayData* ad, int64_t k, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyImpl();
// todo t2606310: what is probability of (k == size-1)
if (size_t(k) < a->m_size) {
a->vectorToGeneric();
return a->erase(a->findForInsert(k));
}
return a; // key didn't exist, so we're still vector
}
ArrayData* HphpArray::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyImpl();
return a->erase(a->findForInsert(k));
}
ArrayData* HphpArray::remove(const StringData* key, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) return a; // since key cannot exist
ArrayData*
HphpArray::RemoveStrVec(ArrayData* ad, const StringData* key, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyImpl();
return a;
}
ArrayData*
HphpArray::RemoveStr(ArrayData* ad, const StringData* key, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyImpl();
return a->erase(a->findForInsert(key, key->hash()));
}
@@ -1357,7 +1476,7 @@ TypedValue* HphpArray::NvGetIntVec(const ArrayData* ad, int64_t ki) {
}
TypedValue* HphpArray::NvGetInt(const ArrayData* ad, int64_t ki) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
auto i = a->find(ki);
return LIKELY(i != ElmIndEmpty) ? &a->m_data[i].data : nullptr;
}
@@ -1368,7 +1487,7 @@ TypedValue* HphpArray::NvGetStrVec(const ArrayData* ad, const StringData* k) {
}
TypedValue* HphpArray::NvGetStr(const ArrayData* ad, const StringData* k) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
auto i = a->find(k, k->hash());
if (LIKELY(i != ElmIndEmpty)) {
return &a->m_data[i].data;
@@ -1376,24 +1495,6 @@ TypedValue* HphpArray::NvGetStr(const ArrayData* ad, const StringData* k) {
return nullptr;
}
ArrayData* HphpArray::nvNew(TypedValue*& ret, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
if (a->isVector()) {
auto& tv = a->allocNextElm(a->m_size);
tv.m_type = KindOfUninit;
ret = &tv;
return a;
}
if (UNLIKELY(!a->nextInsert(uninit_null()))) {
ret = nullptr;
return a;
}
assert(a->m_used > 0);
ret = &a->m_data[a->m_used - 1].data;
return a;
}
// nvGetKey does not touch out->_count, so can be used
// for inner or outer cells.
void HphpArray::NvGetKeyVec(const ArrayData* ad, TypedValue* out, ssize_t pos) {
@@ -1405,7 +1506,7 @@ void HphpArray::NvGetKeyVec(const ArrayData* ad, TypedValue* out, ssize_t pos) {
}
void HphpArray::NvGetKey(const ArrayData* ad, TypedValue* out, ssize_t pos) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
assert(pos != ArrayData::invalid_index);
assert(!isTombstone(a->m_data[pos].data.m_type));
getElmKey(a->m_data[pos], out);
@@ -1444,7 +1545,7 @@ ArrayData* HphpArray::AppendVec(ArrayData* ad, CVarRef v, bool copy) {
}
ArrayData* HphpArray::Append(ArrayData* ad, CVarRef v, bool copy) {
auto a = asHphpArray(ad);
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
a->nextInsert(v);
return a;
@@ -1557,7 +1658,7 @@ ArrayData* HphpArray::pop(Variant& value) {
assert(checkInvariants());
HphpArray* a = getCount() <= 1 ? this : copyImpl();
Elm* elms = a->m_data;
ElmInd pos = a->HphpArray::iter_end();
ElmInd pos = IterEnd(a);
if (validElmInd(pos)) {
Elm* e = &elms[pos];
assert(!isTombstone(e->data.m_type));
+59 -33
Ver Arquivo
@@ -57,6 +57,8 @@ private:
// Safe downcast helpers
static HphpArray* asVector(ArrayData* ad);
static const HphpArray* asVector(const ArrayData* ad);
static HphpArray* asGeneric(ArrayData* ad);
static const HphpArray* asGeneric(const ArrayData* ad);
static HphpArray* asHphpArray(ArrayData* ad);
static const HphpArray* asHphpArray(const ArrayData* ad);
@@ -72,13 +74,6 @@ public:
void destroyVec();
void destroy();
// unlike ArrayData::size(), this functions doesn't delegate
// to the virtual vsize() functions, so its more efficient to
// use this when you know you have an HphpArray.
ssize_t getSize() const {
return m_size;
}
// This behaves the same as iter_begin except that it assumes
// this array is not empty and its not virtual.
ssize_t getIterBegin() const {
@@ -107,28 +102,43 @@ public:
using ArrayData::nvGet;
// implements ArrayData
ssize_t vsize() const;
CVarRef getValueRef(ssize_t pos) const;
static CVarRef GetValueRef(const ArrayData*, ssize_t pos);
// overrides ArrayData
bool isVectorData() const;
ssize_t iter_begin() const;
ssize_t iter_end() const;
ssize_t iter_advance(ssize_t prev) const;
ssize_t iter_rewind(ssize_t prev) const;
static bool IsVectorData(const ArrayData*);
static bool IsVectorDataVec(const ArrayData*);
static ssize_t IterBegin(const ArrayData*);
static ssize_t IterEnd(const ArrayData*);
static ssize_t IterAdvance(const ArrayData*, ssize_t pos);
static ssize_t IterRewind(const ArrayData*, ssize_t pos);
// implements ArrayData
bool exists(int64_t k) const;
bool exists(const StringData* k) const;
static bool ExistsInt(const ArrayData*, int64_t k);
static bool ExistsStr(const ArrayData*, const StringData* k);
static bool ExistsIntVec(const ArrayData*, int64_t k);
static bool ExistsStrVec(const ArrayData*, const StringData* k);
// implements ArrayData
ArrayData* lval(int64_t k, Variant*& ret, bool copy);
ArrayData* lval(StringData* k, Variant*& ret, bool copy);
ArrayData* lvalNew(Variant*& ret, bool copy);
static ArrayData* LvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy);
static ArrayData* LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy);
static ArrayData* LvalIntVec(ArrayData* ad, int64_t k, Variant*& ret,
bool copy);
static ArrayData* LvalStrVec(ArrayData* ad, StringData* k, Variant*& ret,
bool copy);
static ArrayData* LvalNew(ArrayData*, Variant*& ret, bool copy);
static ArrayData* LvalNewVec(ArrayData*, Variant*& ret, bool copy);
// overrides ArrayData
ArrayData* createLvalPtr(StringData* k, Variant*& ret, bool copy);
ArrayData* getLvalPtr(StringData* k, Variant*& ret, bool copy);
static ArrayData* CreateLvalPtr(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* GetLvalPtr(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* CreateLvalPtrVec(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* GetLvalPtrVec(ArrayData*, StringData* k, Variant*& ret,
bool copy);
// implements ArrayData
static ArrayData* SetIntVec(ArrayData*, int64_t k, CVarRef v, bool copy);
@@ -137,18 +147,35 @@ public:
static ArrayData* SetStr(ArrayData*, StringData* k, CVarRef v, bool copy);
// implements ArrayData
ArrayData* setRef(int64_t k, CVarRef v, bool copy);
ArrayData* setRef(StringData* k, CVarRef v, bool copy);
static ArrayData* SetRefInt(ArrayData* ad, int64_t k, CVarRef v,
bool copy);
static ArrayData* SetRefStr(ArrayData* ad, StringData* k, CVarRef v,
bool copy);
static ArrayData* SetRefIntVec(ArrayData* ad, int64_t k, CVarRef v,
bool copy);
static ArrayData* SetRefStrVec(ArrayData* ad, StringData* k, CVarRef v,
bool copy);
// overrides ArrayData
ArrayData *add(int64_t k, CVarRef v, bool copy);
ArrayData *add(StringData* k, CVarRef v, bool copy);
ArrayData *addLval(int64_t k, Variant*& ret, bool copy);
ArrayData *addLval(StringData* k, Variant*& ret, bool copy);
static ArrayData* AddInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* AddStr(ArrayData*, StringData* k, CVarRef v, bool copy);
static ArrayData* AddIntVec(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* AddStrVec(ArrayData*, StringData* k, CVarRef v, bool copy);
static ArrayData* AddLvalInt(ArrayData*, int64_t k, Variant*& ret,
bool copy);
static ArrayData* AddLvalStr(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* AddLvalIntVec(ArrayData*, int64_t k, Variant*& ret,
bool copy);
static ArrayData* AddLvalStrVec(ArrayData*, StringData* k, Variant*& ret,
bool copy);
// implements ArrayData
ArrayData* remove(int64_t k, bool copy);
ArrayData* remove(const StringData* k, bool copy);
static ArrayData* RemoveInt(ArrayData*, int64_t k, bool copy);
static ArrayData* RemoveStr(ArrayData*, const StringData* k, bool copy);
static ArrayData* RemoveIntVec(ArrayData*, int64_t k, bool copy);
static ArrayData* RemoveStrVec(ArrayData*, const StringData* k, bool copy);
// overrides/implements ArrayData
ArrayData* copy() const;
@@ -189,16 +216,15 @@ public:
static TypedValue* NvGetStrVec(const ArrayData*, const StringData* k);
static TypedValue* NvGetStr(const ArrayData*, const StringData* k);
void nvBind(int64_t ki, const TypedValue* v) {
updateRef(ki, tvAsCVarRef(v));
void nvBind(int64_t k, const TypedValue* v) {
ArrayData::setRef(k, tvAsCVarRef(v), false);
}
void nvBind(StringData* k, const TypedValue* v) {
updateRef(k, tvAsCVarRef(v));
ArrayData::setRef(k, tvAsCVarRef(v), false);
}
void nvAppend(const TypedValue* v) {
nextInsertVec(tvAsCVarRef(v));
}
ArrayData* nvNew(TypedValue*& v, bool copy);
static void NvGetKeyVec(const ArrayData*, TypedValue* out, ssize_t pos);
static void NvGetKey(const ArrayData*, TypedValue* out, ssize_t pos);
bool nvInsert(StringData* k, TypedValue *v);
+111 -43
Ver Arquivo
@@ -227,20 +227,32 @@ inline const PolicyArray* PolicyArray::asPolicyArray(const ArrayData* ad) {
return static_cast<const PolicyArray*>(ad);
}
const Variant& PolicyArray::getValueRef(ssize_t pos) const {
APILOG(this) << "(" << pos << ")";
assert(size_t(pos) < m_size);
return val(toPos(pos));
const Variant& PolicyArray::GetValueRef(const ArrayData* ad, ssize_t pos) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << pos << ")";
assert(size_t(pos) < a->m_size);
return a->val(toPos(pos));
}
bool PolicyArray::isVectorData() const {
APILOG(this) << "()";
for (ssize_t i = 0; i < m_size; ++i) {
if (Store::find(i, m_size) != toPos(i)) return false;
bool PolicyArray::IsVectorData(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
for (ssize_t i = 0; i < a->m_size; ++i) {
if (a->Store::find(i, a->m_size) != toPos(i)) return false;
}
return true;
}
bool PolicyArray::ExistsInt(const ArrayData* ad, int64_t k) {
auto a = asPolicyArray(ad);
return a->Store::find(k, a->m_size) < toPos(a->m_size);
}
bool PolicyArray::ExistsStr(const ArrayData* ad, const StringData* k) {
auto a = asPolicyArray(ad);
return a->Store::find(k, a->m_size) < toPos(a->m_size);
}
static_assert(ArrayData::invalid_index == size_t(-1), "ehm");
template <class K>
@@ -295,41 +307,53 @@ ArrayData *PolicyArray::lvalImpl(K k, Variant*& ret, bool copy) {
return this;
}
ArrayData *PolicyArray::lvalNew(Variant *&ret, bool copy) {
if (copy) {
return PolicyArray::copy()->lvalNew(ret, false);
}
ArrayData* PolicyArray::LvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy) {
return asPolicyArray(ad)->lvalImpl(k, ret, copy);
}
ArrayData* PolicyArray::LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
return asPolicyArray(ad)->lvalImpl(k, ret, copy);
}
ArrayData *PolicyArray::LvalNew(ArrayData* ad, Variant *&ret, bool copy) {
auto a = asPolicyArray(ad);
if (copy) a = a->PolicyArray::copy();
// Andrei: TODO - append() currently never fails, probably it
// should.
auto oldSize = m_size;
append(uninit_null(), false);
assert(m_size == oldSize + 1);
if (UNLIKELY(oldSize == m_size)) {
auto oldSize = a->m_size;
a->append(uninit_null(), false);
assert(a->m_size == oldSize + 1);
if (UNLIKELY(oldSize == a->m_size)) {
ret = &Variant::lvalBlackHole();
} else {
assert(lastIndex(m_size) != PosType::invalid);
ret = &lval(lastIndex(m_size));
assert(a->lastIndex(a->m_size) != PosType::invalid);
ret = &a->lval(a->lastIndex(a->m_size));
}
return this;
return a;
}
ArrayData *PolicyArray::createLvalPtr(StringData* k, Variant *&ret, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << ret << ", " << copy << ")";
return addLval(k, ret, copy);
ArrayData *PolicyArray::CreateLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << keystr(k) << ", " << ret << ", " << copy << ")";
return a->addLval(k, ret, copy);
}
ArrayData *PolicyArray::getLvalPtr(StringData* k, Variant *&ret, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << ret << ", " << copy << ")";
ArrayData *PolicyArray::GetLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << keystr(k) << ", " << ret << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->getLvalPtr(k, ret, false);
return a->PolicyArray::copy()->getLvalPtr(k, ret, false);
}
const auto pos = find(k, m_size);
const auto pos = a->find(k, a->m_size);
ret = pos != PosType::invalid
? &Store::lval(pos)
? &a->Store::lval(pos)
: nullptr;
return this;
return a;
}
template <class K>
@@ -381,6 +405,16 @@ ArrayData *PolicyArray::setRefImpl(K k, CVarRef v, bool copy) {
return this;
}
ArrayData*
PolicyArray::SetRefInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
return asPolicyArray(ad)->setRefImpl(k, v, copy);
}
ArrayData*
PolicyArray::SetRefStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
return asPolicyArray(ad)->setRefImpl(k, v, copy);
}
template <class K>
ArrayData *PolicyArray::addImpl(K k, const Variant& v, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << valstr(v) << ", " << copy << ");";
@@ -398,8 +432,18 @@ ArrayData *PolicyArray::addImpl(K k, const Variant& v, bool copy) {
return this;
}
ArrayData*
PolicyArray::AddInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
return asPolicyArray(ad)->addImpl(k, v, copy);
}
ArrayData*
PolicyArray::AddStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
return asPolicyArray(ad)->addImpl(k, v, copy);
}
template <class K>
PolicyArray *PolicyArray::addLvalImpl(K k, Variant*& ret, bool copy) {
ArrayData* PolicyArray::addLvalImpl(K k, Variant*& ret, bool copy) {
APILOG(this) << "(" << k << ", " << ret << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->addLval(k, ret, false);
@@ -413,6 +457,16 @@ PolicyArray *PolicyArray::addLvalImpl(K k, Variant*& ret, bool copy) {
return this;
}
ArrayData* PolicyArray::AddLvalInt(ArrayData* ad, int64_t k,
Variant *&ret, bool copy) {
return asPolicyArray(ad)->addLvalImpl(k, ret, copy);
}
ArrayData* PolicyArray::AddLvalStr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
return asPolicyArray(ad)->addLvalImpl(k, ret, copy);
}
template <class K>
ArrayData *PolicyArray::removeImpl(K k, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << copy << ")";
@@ -451,26 +505,40 @@ ArrayData *PolicyArray::removeImpl(K k, bool copy) {
return this;
}
ssize_t PolicyArray::iter_begin() const {
APILOG(this) << "()";
return m_size ? toInt<int64_t>(firstIndex(m_size)) : invalid_index;
ArrayData*
PolicyArray::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
return asPolicyArray(ad)->removeImpl(k, copy);
}
ssize_t PolicyArray::iter_end() const {
APILOG(this) << "()";
return ssize_t(lastIndex(m_size));
ArrayData*
PolicyArray::RemoveStr(ArrayData* ad, const StringData* k, bool copy) {
return asPolicyArray(ad)->removeImpl(k, copy);
}
ssize_t PolicyArray::iter_advance(ssize_t prev) const {
APILOG(this) << "(" << prev << ")";
auto const result = toInt<int64_t>(nextIndex(toPos(prev), m_size));
ssize_t PolicyArray::IterBegin(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
return a->m_size ? toInt<int64_t>(a->firstIndex(a->m_size)) : invalid_index;
}
ssize_t PolicyArray::IterEnd(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
return ssize_t(a->lastIndex(a->m_size));
}
ssize_t PolicyArray::IterAdvance(const ArrayData* ad, ssize_t prev) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << prev << ")";
auto const result = toInt<int64_t>(a->nextIndex(toPos(prev), a->m_size));
MYLOG << "returning " << result;
return result;
}
ssize_t PolicyArray::iter_rewind(ssize_t prev) const {
APILOG(this) << "(" << prev << ")";
return toInt<int64_t>(prevIndex(toPos(prev), m_size));
ssize_t PolicyArray::IterRewind(const ArrayData* ad, ssize_t prev) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << prev << ")";
return toInt<int64_t>(a->prevIndex(toPos(prev), a->m_size));
}
bool PolicyArray::validFullPos(const FullPos& fp) const {
@@ -659,7 +727,7 @@ ArrayData *PolicyArray::merge(const ArrayData *elems, bool copy) {
StringData *s = key.getStringData();
Variant *p;
// Andrei TODO: make sure this is the right semantics
lval(s, p, false);
LvalStr(this, s, p, false);
p->setWithRef(value);
}
}
+30 -64
Ver Arquivo
@@ -331,35 +331,22 @@ public:
virtual ~PolicyArray() FOLLY_OVERRIDE;
/**
* Number of elements this array has.
*/
virtual ssize_t vsize() const FOLLY_OVERRIDE {
// vsize() called, but m_size should never be -1 in PolicyArray
assert(false);
return m_size;
}
/**
* getValueRef() gets a reference to value at position "pos".
*/
virtual CVarRef getValueRef(ssize_t pos) const FOLLY_OVERRIDE;
static CVarRef GetValueRef(const ArrayData*, ssize_t pos);
/*
* Returns whether or not this array contains "vector-like" data.
* I.e. all the keys are contiguous increasing integers.
*/
virtual bool isVectorData() const FOLLY_OVERRIDE;
static bool IsVectorData(const ArrayData*);
/**
* Testing whether a key exists.
*/
virtual bool exists(int64_t k) const FOLLY_OVERRIDE {
return Store::find(k, m_size) < toPos(m_size);
}
virtual bool exists(const StringData* k) const FOLLY_OVERRIDE {
return Store::find(k, m_size) < toPos(m_size);
}
static bool ExistsInt(const ArrayData*, int64_t k);
static bool ExistsStr(const ArrayData*, const StringData* k);
private:
template <class K> TypedValue* nvGetImpl(K k) const;
@@ -384,16 +371,10 @@ public:
* Getting l-value (that Variant pointer) at specified key. Return NULL if
* escalation is not needed, or an escalated array data.
*/
virtual ArrayData *lval(int64_t k,
Variant *&ret,
bool copy) FOLLY_OVERRIDE {
return lvalImpl(k, ret, copy);
}
virtual ArrayData *lval(StringData* k,
Variant*& ret,
bool copy) FOLLY_OVERRIDE {
return lvalImpl(k, ret, copy);
}
static ArrayData* LvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy);
static ArrayData* LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy);
/**
* Getting l-value (that Variant pointer) of a new element with the next
@@ -402,17 +383,17 @@ public:
* available integer key may fail, in which case ret is set to point to
* the lval blackhole (see Variant::lvalBlackHole() for details).
*/
virtual ArrayData *lvalNew(Variant *&ret, bool copy) FOLLY_OVERRIDE;
static ArrayData *LvalNew(ArrayData* ad, Variant *&ret, bool copy);
/**
* Helper functions used for getting a reference to elements of
* the dynamic property array in ObjectData or the local cache array
* in ShardMap.
*/
virtual ArrayData *createLvalPtr(StringData* k, Variant *&ret, bool copy)
FOLLY_OVERRIDE;
virtual ArrayData *getLvalPtr(StringData* k, Variant *&ret, bool copy)
FOLLY_OVERRIDE;
static ArrayData *CreateLvalPtr(ArrayData*, StringData* k, Variant *&ret,
bool copy);
static ArrayData *GetLvalPtr(ArrayData*, StringData* k, Variant *&ret,
bool copy);
/**
* Setting a value at specified key. If "copy" is true, make a copy first
@@ -432,12 +413,9 @@ private:
ArrayData *setRefImpl(K k, CVarRef v, bool copy);
public:
virtual ArrayData *setRef(int64_t k, CVarRef v, bool copy) FOLLY_OVERRIDE {
return setRefImpl(k, v, copy);
}
virtual ArrayData *setRef(StringData* k, CVarRef v, bool cpy) FOLLY_OVERRIDE {
return setRefImpl(k, v, cpy);
}
static ArrayData* SetRefInt(ArrayData* ad, int64_t k, CVarRef v, bool copy);
static ArrayData* SetRefStr(ArrayData* ad, StringData* k, CVarRef v,
bool cpy);
/**
* The same as set(), but with the precondition that the key does
@@ -446,15 +424,11 @@ public:
*/
private:
template <class K>
ArrayData *addImpl(K k, CVarRef v, bool copy);
ArrayData* addImpl(K k, CVarRef v, bool copy);
public:
virtual ArrayData *add(int64_t k, CVarRef v, bool copy) FOLLY_OVERRIDE {
return addImpl(k, v, copy);
}
virtual ArrayData *add(StringData* k, CVarRef v, bool copy) FOLLY_OVERRIDE {
return addImpl(k, v, copy);
}
static ArrayData* AddInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* AddStr(ArrayData*, StringData* k, CVarRef v, bool copy);
/*
* Same semantics as lval(), except with the precondition that the
@@ -462,17 +436,13 @@ public:
*/
private:
template <class K>
PolicyArray* addLvalImpl(K k, Variant*& ret, bool copy);
ArrayData* addLvalImpl(K k, Variant*& ret, bool copy);
public:
virtual PolicyArray *addLval(int64_t k, Variant *&ret, bool copy)
FOLLY_OVERRIDE {
return addLvalImpl(k, ret, copy);
}
virtual PolicyArray *addLval(StringData* k, Variant *&ret, bool copy)
FOLLY_OVERRIDE {
return addLvalImpl(k, ret, copy);
}
static ArrayData* AddLvalInt(ArrayData*, int64_t k, Variant *&ret,
bool copy);
static ArrayData* AddLvalStr(ArrayData*, StringData* k, Variant *&ret,
bool copy);
/**
* Remove a value at specified key. If "copy" is true, make a copy first
@@ -483,17 +453,13 @@ private:
template <class K> ArrayData *removeImpl(K k, bool copy);
public:
virtual ArrayData *remove(int64_t k, bool copy) FOLLY_OVERRIDE {
return removeImpl(k, copy);
}
virtual ArrayData *remove(const StringData* k, bool copy) FOLLY_OVERRIDE {
return removeImpl(k, copy);
}
static ArrayData *RemoveInt(ArrayData*, int64_t k, bool copy);
static ArrayData *RemoveStr(ArrayData*, const StringData* k, bool copy);
virtual ssize_t iter_begin() const FOLLY_OVERRIDE;
virtual ssize_t iter_end() const FOLLY_OVERRIDE;
virtual ssize_t iter_advance(ssize_t prev) const FOLLY_OVERRIDE;
virtual ssize_t iter_rewind(ssize_t prev) const FOLLY_OVERRIDE;
static ssize_t IterBegin(const ArrayData*);
static ssize_t IterEnd(const ArrayData*);
static ssize_t IterAdvance(const ArrayData*, ssize_t prev);
static ssize_t IterRewind(const ArrayData*, ssize_t prev);
/**
* Mutable iteration APIs
+58 -37
Ver Arquivo
@@ -45,6 +45,10 @@ CVarRef SharedMap::getValueRef(ssize_t pos) const {
return tvAsCVarRef(tv);
}
CVarRef SharedMap::GetValueRef(const ArrayData* ad, ssize_t pos) {
return asSharedMap(ad)->getValueRef(pos);
}
HOT_FUNC
SharedMap::~SharedMap() {
if (m_localCache) {
@@ -86,22 +90,24 @@ ssize_t SharedMap::getIndex(int64_t k) const {
return m_map->indexOf(k);
}
bool SharedMap::isVectorData() const {
if (isVector()) return true;
const auto n = size();
bool SharedMap::IsVectorData(const ArrayData* ad) {
auto a = asSharedMap(ad);
if (a->isVector()) return true;
const auto n = a->size();
for (ssize_t i = 0; i < n; i++) {
if (m_map->indexOf(i) != i) return false;
if (a->m_map->indexOf(i) != i) return false;
}
return true;
}
bool SharedMap::exists(const StringData* k) const {
if (isVector()) return false;
return m_map->indexOf(k) != -1;
bool SharedMap::ExistsStr(const ArrayData* ad, const StringData* k) {
auto a = asSharedMap(ad);
if (a->isVector()) return false;
return a->m_map->indexOf(k) != -1;
}
bool SharedMap::exists(int64_t k) const {
return getIndex(k) != -1;
bool SharedMap::ExistsInt(const ArrayData* ad, int64_t k) {
return asSharedMap(ad)->getIndex(k) != -1;
}
/* if a2 is modified copy of a1 (i.e. != a1), then release a1 and return a2 */
@@ -110,18 +116,20 @@ inline ArrayData* releaseIfCopied(ArrayData* a1, ArrayData* a2) {
return a2;
}
ArrayData *SharedMap::lval(int64_t k, Variant *&ret, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::LvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->lval(k, ret, false));
}
ArrayData *SharedMap::lval(StringData* k, Variant *&ret, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::LvalStr(ArrayData* ad, StringData* k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->lval(k, ret, false));
}
ArrayData *SharedMap::lvalNew(Variant *&ret, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::LvalNew(ArrayData* ad, Variant *&ret, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->lvalNew(ret, false));
}
@@ -137,23 +145,37 @@ SharedMap::SetStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
return releaseIfCopied(escalated, escalated->set(k, v, false));
}
ArrayData *SharedMap::setRef(int64_t k, CVarRef v, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData*
SharedMap::SetRefInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->setRef(k, v, false));
}
ArrayData *SharedMap::setRef(StringData* k, CVarRef v, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData*
SharedMap::SetRefStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->setRef(k, v, false));
}
ArrayData *SharedMap::remove(int64_t k, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::AddLvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->addLval(k, ret, false));
}
ArrayData *SharedMap::AddLvalStr(ArrayData* ad, StringData* k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->addLval(k, ret, false));
}
ArrayData *SharedMap::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->remove(k, false));
}
ArrayData *SharedMap::remove(const StringData* k, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::RemoveStr(ArrayData* ad, const StringData* k, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
return releaseIfCopied(escalated, escalated->remove(k, false));
}
@@ -233,28 +255,27 @@ ArrayData* SharedMap::escalateForSort() {
return ret;
}
ssize_t SharedMap::vsize() const {
assert(false); // should never be called since we set size already.
return m_size;
ssize_t SharedMap::IterBegin(const ArrayData* ad) {
auto a = asSharedMap(ad);
return a->m_size > 0 ? 0 : invalid_index;
}
ssize_t SharedMap::iter_begin() const {
return !empty() ? 0 : invalid_index;
}
ssize_t SharedMap::iter_end() const {
auto n = size();
ssize_t SharedMap::IterEnd(const ArrayData* ad) {
auto a = asSharedMap(ad);
auto n = a->m_size;
return n > 0 ? ssize_t(n - 1) : invalid_index;
}
ssize_t SharedMap::iter_advance(ssize_t prev) const {
assert(prev >= 0 && prev < size());
ssize_t SharedMap::IterAdvance(const ArrayData* ad, ssize_t prev) {
auto a = asSharedMap(ad);
assert(prev >= 0 && prev < a->m_size);
ssize_t next = prev + 1;
return next < size() ? next : invalid_index;
return next < a->m_size ? next : invalid_index;
}
ssize_t SharedMap::iter_rewind(ssize_t prev) const {
assert(prev >= 0 && prev < size());
ssize_t SharedMap::IterRewind(const ArrayData* ad, ssize_t prev) {
auto a = asSharedMap(ad);
assert(prev >= 0 && prev < a->m_size);
ssize_t next = prev - 1;
return next >= 0 ? next : invalid_index;
}
+24 -18
Ver Arquivo
@@ -56,28 +56,34 @@ public:
using ArrayData::addLval;
using ArrayData::remove;
ssize_t vsize() const;
SharedVariant* getValueImpl(ssize_t pos) const {
return isVector() ? m_vec->getValue(pos) : m_map->getValue(pos);
}
CVarRef getValueRef(ssize_t pos) const;
static CVarRef GetValueRef(const ArrayData* ad, ssize_t pos);
bool exists(int64_t k) const;
bool exists(const StringData* k) const;
static bool ExistsInt(const ArrayData* ad, int64_t k);
static bool ExistsStr(const ArrayData* ad, const StringData* k);
virtual ArrayData *lval(int64_t k, Variant *&ret, bool copy);
virtual ArrayData *lval(StringData* k, Variant *&ret, bool copy);
ArrayData *lvalNew(Variant *&ret, bool copy);
static ArrayData* LvalInt(ArrayData*, int64_t k, Variant *&ret,
bool copy);
static ArrayData* LvalStr(ArrayData*, StringData* k, Variant *&ret,
bool copy);
static ArrayData* LvalNew(ArrayData*, Variant *&ret, bool copy);
static ArrayData *SetInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData *SetStr(ArrayData*, StringData* k, CVarRef v, bool copy);
ArrayData *setRef(int64_t k, CVarRef v, bool copy);
ArrayData *setRef(StringData* k, CVarRef v, bool copy);
static ArrayData* SetInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* SetStr(ArrayData*, StringData* k, CVarRef v, bool copy);
static ArrayData* SetRefInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* SetRefStr(ArrayData*, StringData* k, CVarRef v, bool copy);
ArrayData *remove(int64_t k, bool copy);
ArrayData *remove(const StringData* k, bool copy);
static ArrayData* AddLvalInt(ArrayData*, int64_t k, Variant *&ret,
bool copy);
static ArrayData* AddLvalStr(ArrayData*, StringData* k, Variant *&ret,
bool copy);
static ArrayData *RemoveInt(ArrayData* ad, int64_t k, bool copy);
static ArrayData *RemoveStr(ArrayData* ad, const StringData* k, bool copy);
ArrayData *copy() const;
/**
@@ -98,12 +104,12 @@ public:
static TypedValue* NvGetStr(const ArrayData*, const StringData* k);
static void NvGetKey(const ArrayData*, TypedValue* out, ssize_t pos);
bool isVectorData() const;
static bool IsVectorData(const ArrayData* ad);
ssize_t iter_begin() const;
ssize_t iter_end() const;
ssize_t iter_advance(ssize_t prev) const;
ssize_t iter_rewind(ssize_t prev) const;
static ssize_t IterBegin(const ArrayData*);
static ssize_t IterEnd(const ArrayData*);
static ssize_t IterAdvance(const ArrayData*, ssize_t prev);
static ssize_t IterRewind(const ArrayData*, ssize_t prev);
bool validFullPos(const FullPos& fp) const;
bool advanceFullPos(FullPos& fp);
+71 -44
Ver Arquivo
@@ -36,14 +36,15 @@ NameValueTableWrapper::asNVTW(const ArrayData* ad) {
return static_cast<const NameValueTableWrapper*>(ad);
}
ssize_t NameValueTableWrapper::vsize() const {
size_t NameValueTableWrapper::Vsize(const ArrayData* ad) {
// We need to iterate to find out the actual size, since
// KindOfIndirect elements in the array may have been set to
// KindOfUninit.
ssize_t count = 0;
for (ssize_t iter = iter_begin();
iter != ArrayData::invalid_index;
iter = iter_advance(iter)) {
auto a = asNVTW(ad);
size_t count = 0;
for (auto iter = IterBegin(a);
iter != invalid_index;
iter = IterAdvance(a, iter)) {
++count;
}
return count;
@@ -63,23 +64,20 @@ void NameValueTableWrapper::NvGetKey(const ArrayData* ad, TypedValue* out,
}
}
CVarRef NameValueTableWrapper::getValueRef(ssize_t pos) const {
NameValueTable::Iterator iter(m_tab, pos);
CVarRef NameValueTableWrapper::GetValueRef(const ArrayData* ad, ssize_t pos) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, pos);
return iter.valid() ? tvAsCVarRef(iter.curVal()) : null_variant;
}
bool NameValueTableWrapper::noCopyOnWrite() const {
// This just disables a few places that will call copy() on an array
// if it has more than one reference.
return true;
bool
NameValueTableWrapper::ExistsInt(const ArrayData* ad, int64_t k) {
return ExistsStr(ad, String(k).get());
}
bool NameValueTableWrapper::exists(int64_t k) const {
return exists(String(k));
}
bool NameValueTableWrapper::exists(const StringData* k) const {
return m_tab->lookup(k);
bool
NameValueTableWrapper::ExistsStr(const ArrayData* ad, const StringData* k) {
return asNVTW(ad)->m_tab->lookup(k) != nullptr;
}
TypedValue*
@@ -91,24 +89,42 @@ TypedValue* NameValueTableWrapper::NvGetInt(const ArrayData* ad, int64_t k) {
return asNVTW(ad)->m_tab->lookup(String(k).get());
}
ArrayData* NameValueTableWrapper::lval(int64_t k, Variant*& ret, bool) {
return lval(String(k), ret, false);
ArrayData*
NameValueTableWrapper::LvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
return LvalStr(ad, String(k).get(), ret, copy);
}
ArrayData* NameValueTableWrapper::lval(StringData* k, Variant*& ret, bool) {
TypedValue* tv = m_tab->lookup(k);
ArrayData*
NameValueTableWrapper::LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
auto a = asNVTW(ad);
TypedValue* tv = a->m_tab->lookup(k);
if (!tv) {
TypedValue nulVal;
tvWriteNull(&nulVal);
tv = m_tab->set(k, &nulVal);
tv = a->m_tab->set(k, &nulVal);
}
ret = &tvAsVariant(tv);
return this;
return a;
}
ArrayData* NameValueTableWrapper::lvalNew(Variant*& ret, bool copy) {
ArrayData*
NameValueTableWrapper::AddLvalInt(ArrayData* ad, int64_t k, Variant*& ret,
bool copy) {
return LvalStr(ad, String(k).get(), ret, copy);
}
ArrayData*
NameValueTableWrapper::AddLvalStr(ArrayData* ad, StringData* k, Variant*& ret,
bool copy) {
return LvalStr(ad, k, ret, copy);
}
ArrayData*
NameValueTableWrapper::LvalNew(ArrayData* ad, Variant*& ret, bool copy) {
ret = &Variant::lvalBlackHole();
return this;
return ad;
}
ArrayData* NameValueTableWrapper::SetInt(ArrayData* ad, int64_t k,
@@ -123,22 +139,29 @@ ArrayData* NameValueTableWrapper::SetStr(ArrayData* ad, StringData* k,
return a;
}
ArrayData* NameValueTableWrapper::setRef(int64_t k, CVarRef v, bool copy) {
return setRef(String(k), v, copy);
ArrayData* NameValueTableWrapper::SetRefInt(ArrayData* ad, int64_t k,
CVarRef v, bool copy) {
return asNVTW(ad)->setRef(String(k).get(), v, copy);
}
ArrayData* NameValueTableWrapper::setRef(StringData* k, CVarRef v, bool copy) {
tvAsVariant(m_tab->lookupAdd(k)).assignRef(v);
return this;
ArrayData* NameValueTableWrapper::SetRefStr(ArrayData* ad, StringData* k,
CVarRef v, bool copy) {
auto a = asNVTW(ad);
tvAsVariant(a->m_tab->lookupAdd(k)).assignRef(v);
return a;
}
ArrayData* NameValueTableWrapper::remove(int64_t k, bool copy) {
return remove(String(k), copy);
ArrayData*
NameValueTableWrapper::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
return RemoveStr(ad, String(k).get(), copy);
}
ArrayData* NameValueTableWrapper::remove(const StringData* k, bool copy) {
m_tab->unset(k);
return this;
ArrayData*
NameValueTableWrapper::RemoveStr(ArrayData* ad, const StringData* k,
bool copy) {
auto a = asNVTW(ad);
a->m_tab->unset(k);
return a;
}
/*
@@ -171,23 +194,27 @@ ArrayData* NameValueTableWrapper::prepend(CVarRef v, bool copy) {
throw NotImplementedException("prepend on $GLOBALS");
}
ssize_t NameValueTableWrapper::iter_begin() const {
NameValueTable::Iterator iter(m_tab);
ssize_t NameValueTableWrapper::IterBegin(const ArrayData* ad) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab);
return iter.toInteger();
}
ssize_t NameValueTableWrapper::iter_end() const {
return NameValueTable::Iterator::getEnd(m_tab).toInteger();
ssize_t NameValueTableWrapper::IterEnd(const ArrayData* ad) {
auto a = asNVTW(ad);
return NameValueTable::Iterator::getEnd(a->m_tab).toInteger();
}
ssize_t NameValueTableWrapper::iter_advance(ssize_t prev) const {
NameValueTable::Iterator iter(m_tab, prev);
ssize_t NameValueTableWrapper::IterAdvance(const ArrayData* ad, ssize_t prev) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, prev);
iter.next();
return iter.toInteger();
}
ssize_t NameValueTableWrapper::iter_rewind(ssize_t prev) const {
NameValueTable::Iterator iter(m_tab, prev);
ssize_t NameValueTableWrapper::IterRewind(const ArrayData* ad, ssize_t prev) {
auto a = asNVTW(ad);
NameValueTable::Iterator iter(a->m_tab, prev);
iter.prev();
return iter.toInteger();
}
@@ -233,7 +260,7 @@ void NameValueTableWrapper::uksort(CVarRef cmp_function) {}
void NameValueTableWrapper::usort(CVarRef cmp_function) {}
void NameValueTableWrapper::uasort(CVarRef cmp_function) {}
bool NameValueTableWrapper::isVectorData() const {
bool NameValueTableWrapper::IsVectorData(const ArrayData*) {
return false;
}
+21 -17
Ver Arquivo
@@ -77,27 +77,31 @@ public: // ArrayData implementation
return tvAsVariant(nvGet(k.get()));
}
virtual ssize_t vsize() const;
static size_t Vsize(const ArrayData*);
static void NvGetKey(const ArrayData* ad, TypedValue* out, ssize_t pos);
virtual CVarRef getValueRef(ssize_t pos) const;
virtual bool noCopyOnWrite() const;
static CVarRef GetValueRef(const ArrayData*, ssize_t pos);
virtual bool exists(int64_t k) const;
virtual bool exists(const StringData* k) const;
static bool ExistsInt(const ArrayData* ad, int64_t k);
static bool ExistsStr(const ArrayData* ad, const StringData* k);
static TypedValue* NvGetInt(const ArrayData*, int64_t k);
static TypedValue* NvGetStr(const ArrayData*, const StringData* k);
virtual ArrayData* lval(int64_t k, Variant*& ret, bool copy);
virtual ArrayData* lval(StringData* k, Variant*& ret, bool copy);
virtual ArrayData* lvalNew(Variant*& ret, bool copy);
static ArrayData* LvalInt(ArrayData*, int64_t k, Variant*& ret, bool copy);
static ArrayData* LvalStr(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* LvalNew(ArrayData*, Variant*& ret, bool copy);
static ArrayData* SetInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* SetStr(ArrayData*, StringData* k, CVarRef v, bool copy);
virtual ArrayData* setRef(int64_t k, CVarRef v, bool copy);
virtual ArrayData* setRef(StringData* k, CVarRef v, bool copy);
virtual ArrayData* remove(int64_t k, bool copy);
virtual ArrayData* remove(const StringData* k, bool copy);
static ArrayData* SetRefInt(ArrayData*, int64_t k, CVarRef v, bool copy);
static ArrayData* SetRefStr(ArrayData*, StringData* k, CVarRef v, bool copy);
static ArrayData* AddLvalInt(ArrayData*, int64_t k, Variant*& ret,
bool copy);
static ArrayData* AddLvalStr(ArrayData*, StringData* k, Variant*& ret,
bool copy);
static ArrayData* RemoveInt(ArrayData*, int64_t k, bool copy);
static ArrayData* RemoveStr(ArrayData*, const StringData* k, bool copy);
virtual ArrayData* copy() const { return 0; }
@@ -110,14 +114,14 @@ public: // ArrayData implementation
virtual ArrayData* prepend(CVarRef v, bool copy);
virtual ssize_t iter_begin() const;
virtual ssize_t iter_end() const;
virtual ssize_t iter_advance(ssize_t prev) const;
virtual ssize_t iter_rewind(ssize_t prev) const;
static ssize_t IterBegin(const ArrayData*);
static ssize_t IterEnd(const ArrayData*);
static ssize_t IterAdvance(const ArrayData*, ssize_t prev);
static ssize_t IterRewind(const ArrayData*, ssize_t prev);
virtual bool validFullPos(const FullPos & fp) const;
virtual bool advanceFullPos(FullPos&);
virtual bool isVectorData() const;
static bool IsVectorData(const ArrayData*);
virtual ArrayData* escalateForSort();
virtual void ksort(int sort_flags, bool ascending);