Devirtualize ArrayData part 2

Convert remaining virtual methods to static methods dispatched
by kind.  This makes ArrayData a non-virtual class, so shuffle
fields and adjust static_asserts.
Esse commit está contido em:
Edwin Smith
2013-07-16 14:32:52 -07:00
commit de Sara Golemon
commit 7204d561e5
15 arquivos alterados com 768 adições e 487 exclusões
+88
Ver Arquivo
@@ -173,6 +173,14 @@ inline ArrayData* ArrayData::append(CVarRef v, bool copy) {
return g_array_funcs.append[m_kind](this, v, copy);
}
inline ArrayData* ArrayData::appendRef(CVarRef v, bool copy) {
return g_array_funcs.appendRef[m_kind](this, v, copy);
}
inline ArrayData* ArrayData::appendWithRef(CVarRef v, bool copy) {
return g_array_funcs.appendWithRef[m_kind](this, v, copy);
}
inline TypedValue* ArrayData::nvGet(int64_t ikey) const {
return g_array_funcs.nvGetInt[m_kind](this, ikey);
}
@@ -287,6 +295,86 @@ inline ssize_t ArrayData::iter_rewind(ssize_t pos) const {
return g_array_funcs.iterRewind[m_kind](this, pos);
}
inline bool ArrayData::validFullPos(const FullPos& fp) const {
return g_array_funcs.validFullPos[m_kind](this, fp);
}
inline bool ArrayData::advanceFullPos(FullPos& fp) {
return g_array_funcs.advanceFullPos[m_kind](this, fp);
}
inline ArrayData* ArrayData::escalateForSort() {
return g_array_funcs.escalateForSort[m_kind](this);
}
inline void ArrayData::ksort(int sort_flags, bool ascending) {
return g_array_funcs.ksort[m_kind](this, sort_flags, ascending);
}
inline void ArrayData::sort(int sort_flags, bool ascending) {
return g_array_funcs.sort[m_kind](this, sort_flags, ascending);
}
inline void ArrayData::asort(int sort_flags, bool ascending) {
return g_array_funcs.asort[m_kind](this, sort_flags, ascending);
}
inline void ArrayData::uksort(CVarRef compare) {
return g_array_funcs.uksort[m_kind](this, compare);
}
inline void ArrayData::usort(CVarRef compare) {
return g_array_funcs.usort[m_kind](this, compare);
}
inline void ArrayData::uasort(CVarRef compare) {
return g_array_funcs.uasort[m_kind](this, compare);
}
inline ArrayData* ArrayData::copy() const {
return g_array_funcs.copy[m_kind](this);
}
inline ArrayData* ArrayData::copyWithStrongIterators() const {
return g_array_funcs.copyWithStrongIterators[m_kind](this);
}
inline ArrayData* ArrayData::nonSmartCopy() const {
return g_array_funcs.nonSmartCopy[m_kind](this);
}
inline ArrayData* ArrayData::pop(Variant& value) {
return g_array_funcs.pop[m_kind](this, value);
}
inline ArrayData* ArrayData::dequeue(Variant& value) {
return g_array_funcs.dequeue[m_kind](this, value);
}
inline ArrayData* ArrayData::prepend(CVarRef value, bool copy) {
return g_array_funcs.prepend[m_kind](this, value, copy);
}
inline void ArrayData::renumber() {
return g_array_funcs.renumber[m_kind](this);
}
inline void ArrayData::onSetEvalScalar() {
return g_array_funcs.onSetEvalScalar[m_kind](this);
}
inline ArrayData* ArrayData::escalate() const {
return g_array_funcs.escalate[m_kind](this);
}
inline ArrayData* ArrayData::plus(const ArrayData* elms, bool copy) {
return g_array_funcs.plus[m_kind](this, elms, copy);
}
inline ArrayData* ArrayData::merge(const ArrayData* elms, bool copy) {
return g_array_funcs.merge[m_kind](this, elms, copy);
}
///////////////////////////////////////////////////////////////////////////////
}
+153 -32
Ver Arquivo
@@ -36,7 +36,7 @@ namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
static_assert(
sizeof(ArrayData) == 32,
sizeof(ArrayData) == 24,
"Performance is sensitive to sizeof(ArrayData)."
" Make sure you changed it with good reason and then update this assert.");
@@ -76,11 +76,6 @@ extern const ArrayFunctions g_array_funcs = {
&SharedMap::Release,
&NameValueTableWrapper::Release,
&PolicyArray::Release },
// append
{ &HphpArray::AppendVec, &HphpArray::Append,
&SharedMap::Append,
&NameValueTableWrapper::Append,
&PolicyArray::Append },
// nvGetInt
{ &HphpArray::NvGetIntVec, &HphpArray::NvGetInt,
&SharedMap::NvGetInt,
@@ -221,6 +216,121 @@ extern const ArrayFunctions g_array_funcs = {
&SharedMap::IterRewind,
&NameValueTableWrapper::IterRewind,
&PolicyArray::IterRewind },
// validFullPos
{ &HphpArray::ValidFullPos, &HphpArray::ValidFullPos,
&SharedMap::ValidFullPos,
&NameValueTableWrapper::ValidFullPos,
&PolicyArray::ValidFullPos },
// advanceFullPos
{ &HphpArray::AdvanceFullPos, &HphpArray::AdvanceFullPos,
&SharedMap::AdvanceFullPos,
&NameValueTableWrapper::AdvanceFullPos,
&PolicyArray::AdvanceFullPos },
// escalateForSort
{ &HphpArray::EscalateForSort, &HphpArray::EscalateForSort,
&SharedMap::EscalateForSort,
&NameValueTableWrapper::EscalateForSort,
&PolicyArray::EscalateForSort },
// ksort
{ &HphpArray::Ksort, &HphpArray::Ksort,
&ArrayData::Ksort,
&NameValueTableWrapper::Ksort,
&ArrayData::Ksort },
// sort
{ &HphpArray::Sort, &HphpArray::Sort,
&ArrayData::Sort,
&NameValueTableWrapper::Sort,
&ArrayData::Sort },
// asort
{ &HphpArray::Asort, &HphpArray::Asort,
&ArrayData::Asort,
&NameValueTableWrapper::Asort,
&ArrayData::Asort },
// uksort
{ &HphpArray::Uksort, &HphpArray::Uksort,
&ArrayData::Uksort,
&NameValueTableWrapper::Uksort,
&ArrayData::Uksort },
// usort
{ &HphpArray::Usort, &HphpArray::Usort,
&ArrayData::Usort,
&NameValueTableWrapper::Usort,
&ArrayData::Usort },
// uasort
{ &HphpArray::Uasort, &HphpArray::Uasort,
&ArrayData::Uasort,
&NameValueTableWrapper::Uasort,
&ArrayData::Uasort },
// copy
{ &HphpArray::CopyVec, &HphpArray::Copy,
&SharedMap::Copy,
&NameValueTableWrapper::Copy,
&PolicyArray::Copy },
// copyWithStrongIterators
{ &HphpArray::CopyWithStrongIterators, &HphpArray::CopyWithStrongIterators,
&SharedMap::CopyWithStrongIterators,
&NameValueTableWrapper::CopyWithStrongIterators,
&PolicyArray::CopyWithStrongIterators },
// nonSmartCopy
{ &HphpArray::NonSmartCopy, &HphpArray::NonSmartCopy,
&ArrayData::NonSmartCopy,
&ArrayData::NonSmartCopy,
&PolicyArray::NonSmartCopy },
// append
{ &HphpArray::AppendVec, &HphpArray::Append,
&SharedMap::Append,
&NameValueTableWrapper::Append,
&PolicyArray::Append },
// appendRef
{ &HphpArray::AppendRefVec, &HphpArray::AppendRef,
&SharedMap::AppendRef,
&NameValueTableWrapper::AppendRef,
&PolicyArray::AppendRef },
// appendWithRef
{ &HphpArray::AppendWithRefVec, &HphpArray::AppendWithRef,
&SharedMap::AppendRef,
&NameValueTableWrapper::AppendRef,
&PolicyArray::AppendRef },
// plus
{ &HphpArray::Plus, &HphpArray::Plus,
&SharedMap::Plus,
&NameValueTableWrapper::Plus,
&PolicyArray::Plus },
// merge
{ &HphpArray::Merge, &HphpArray::Merge,
&SharedMap::Merge,
&NameValueTableWrapper::Merge,
&PolicyArray::Merge },
// pop
{ &HphpArray::PopVec, &HphpArray::Pop,
&SharedMap::Pop,
&NameValueTableWrapper::Pop,
&PolicyArray::Pop },
// dequeue
{ &HphpArray::Dequeue, &HphpArray::Dequeue,
&SharedMap::Dequeue,
&NameValueTableWrapper::Dequeue,
&PolicyArray::Dequeue },
// prepend
{ &HphpArray::Prepend, &HphpArray::Prepend,
&SharedMap::Prepend,
&NameValueTableWrapper::Prepend,
&PolicyArray::Prepend },
// renumber
{ &HphpArray::RenumberVec, &HphpArray::Renumber,
&SharedMap::Renumber,
&NameValueTableWrapper::Renumber,
&PolicyArray::Renumber },
// onSetEvalScalar
{ &HphpArray::OnSetEvalScalarVec, &HphpArray::OnSetEvalScalar,
&SharedMap::OnSetEvalScalar,
&NameValueTableWrapper::OnSetEvalScalar,
&PolicyArray::OnSetEvalScalar },
// escalate
{ &ArrayData::Escalate, &ArrayData::Escalate,
&SharedMap::Escalate,
&ArrayData::Escalate,
&PolicyArray::Escalate },
};
///////////////////////////////////////////////////////////////////////////////
@@ -272,7 +382,7 @@ ArrayData *ArrayData::CreateRef(CVarRef name, CVarRef value) {
return init.create();
}
ArrayData *ArrayData::nonSmartCopy() const {
ArrayData *ArrayData::NonSmartCopy(const ArrayData*) {
throw FatalErrorException("nonSmartCopy not implemented.");
}
@@ -351,28 +461,28 @@ ArrayData *ArrayData::GetLvalPtr(ArrayData* ad, StringData* k,
///////////////////////////////////////////////////////////////////////////////
// stack and queue operations
ArrayData *ArrayData::pop(Variant &value) {
if (!empty()) {
ssize_t pos = iter_end();
value = getValue(pos);
return remove(getKey(pos), getCount() > 1);
ArrayData *ArrayData::Pop(ArrayData* a, Variant &value) {
if (!a->empty()) {
ssize_t pos = a->iter_end();
value = a->getValue(pos);
return a->remove(a->getKey(pos), a->getCount() > 1);
}
value = uninit_null();
return this;
return a;
}
ArrayData *ArrayData::dequeue(Variant &value) {
if (!empty()) {
auto const pos = iter_begin();
value = getValue(pos);
ArrayData *ret = remove(getKey(pos), getCount() > 1);
ArrayData *ArrayData::Dequeue(ArrayData* a, Variant &value) {
if (!a->empty()) {
auto const pos = a->iter_begin();
value = a->getValue(pos);
ArrayData *ret = a->remove(a->getKey(pos), a->getCount() > 1);
// In PHP, array_shift() will cause all numerically key-ed values re-keyed
ret->renumber();
return ret;
}
value = uninit_null();
return this;
return a;
}
///////////////////////////////////////////////////////////////////////////////
@@ -430,31 +540,31 @@ CVarRef ArrayData::endRef() {
throw FatalErrorException("invalid ArrayData::m_pos");
}
ArrayData* ArrayData::escalateForSort() {
if (getCount() > 1) {
return copy();
}
return this;
}
void ArrayData::ksort(int sort_flags, bool ascending) {
void ArrayData::Ksort(ArrayData*, int sort_flags, bool ascending) {
throw FatalErrorException("Unimplemented ArrayData::ksort");
}
void ArrayData::sort(int sort_flags, bool ascending) {
void ArrayData::Sort(ArrayData*, int sort_flags, bool ascending) {
throw FatalErrorException("Unimplemented ArrayData::sort");
}
void ArrayData::asort(int sort_flags, bool ascending) {
void ArrayData::Asort(ArrayData*, int sort_flags, bool ascending) {
throw FatalErrorException("Unimplemented ArrayData::asort");
}
void ArrayData::uksort(CVarRef cmp_function) {
void ArrayData::Uksort(ArrayData*, CVarRef cmp_function) {
throw FatalErrorException("Unimplemented ArrayData::uksort");
}
void ArrayData::usort(CVarRef cmp_function) {
void ArrayData::Usort(ArrayData*, CVarRef cmp_function) {
throw FatalErrorException("Unimplemented ArrayData::usort");
}
void ArrayData::uasort(CVarRef cmp_function) {
void ArrayData::Uasort(ArrayData*, CVarRef cmp_function) {
throw FatalErrorException("Unimplemented ArrayData::uasort");
}
ArrayData* ArrayData::copyWithStrongIterators() const {
ArrayData* ArrayData::CopyWithStrongIterators(const ArrayData* ad) {
throw FatalErrorException("Unimplemented ArrayData::copyWithStrongIterators");
}
@@ -624,6 +734,17 @@ CVarRef ArrayData::getNotFound(CVarRef k) {
return null_variant;
}
void ArrayData::Renumber(ArrayData*) {
}
void ArrayData::OnSetEvalScalar(ArrayData*) {
assert(false);
}
ArrayData* ArrayData::Escalate(const ArrayData* ad) {
return const_cast<ArrayData*>(ad);
}
void ArrayData::dump() {
string out; dump(out); fwrite(out.c_str(), out.size(), 1, stdout);
}
+111 -67
Ver Arquivo
@@ -33,7 +33,7 @@ class HphpArray;
/**
* Base class/interface for all types of specialized array data.
*/
class ArrayData : public Countable {
class ArrayData {
public:
enum class AllocationMode : bool { smart, nonSmart };
@@ -56,46 +56,54 @@ public:
static const ssize_t invalid_index = -1;
explicit ArrayData(ArrayKind kind)
: m_size(-1)
, m_strongIterators(nullptr)
, m_pos(0)
, m_kind(kind)
: m_kind(kind)
, m_allocMode(AllocationMode::smart)
, m_size(-1)
, _count(0)
, m_pos(0)
, m_strongIterators(nullptr)
{}
explicit ArrayData(ArrayKind kind, AllocationMode m)
: m_size(-1)
, m_strongIterators(nullptr)
, m_pos(0)
, m_kind(kind)
, m_allocMode(m)
: m_kind(kind)
, m_allocMode(m)
, m_size(-1)
, _count(0)
, m_pos(0)
, m_strongIterators(nullptr)
{}
ArrayData(ArrayKind kind, AllocationMode m, uint size)
: m_size(size)
, m_strongIterators(nullptr)
, m_pos(size ? 0 : ArrayData::invalid_index)
, m_kind(kind)
, m_allocMode(m)
: m_kind(kind)
, m_allocMode(m)
, m_size(size)
, _count(0)
, m_pos(size ? 0 : ArrayData::invalid_index)
, m_strongIterators(nullptr)
{}
ArrayData(const ArrayData *src, ArrayKind kind,
AllocationMode m = AllocationMode::smart)
: m_strongIterators(nullptr)
, m_pos(src->m_pos)
, m_kind(src->m_kind)
: m_kind(src->m_kind)
, m_allocMode(m)
, _count(0)
, m_pos(src->m_pos)
, m_strongIterators(nullptr)
{}
static HphpArray* Make(uint capacity);
static HphpArray* Make(uint size, const TypedValue*);
virtual ~ArrayData() {
void destroy() {
// If there are any strong iterators pointing to this array, they need
// to be invalidated.
freeStrongIterators();
if (UNLIKELY(m_strongIterators != nullptr)) freeStrongIterators();
}
~ArrayData() { destroy(); }
IMPLEMENT_COUNTABLE_METHODS
/**
* Create a new ArrayData with specified array element(s).
*/
@@ -150,8 +158,8 @@ public:
}
// 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.
// to the 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;
}
@@ -185,10 +193,9 @@ public:
return m_kind == kNvtwKind;
}
/*
* Returns whether or not this array contains "vector-like" data.
* I.e. all the keys are contiguous increasing integers.
* I.e. iteration order produces int keys 0 to m_size-1 in sequence.
*/
bool isVectorData() const;
@@ -201,8 +208,8 @@ public:
bool detectSerializable = false) const;
/**
* non-virtual Position-based iterations, implemented using iter_begin,
* iter_advance, iter_prev, iter_rewind pure virtual methods.
* Position-based iterations, implemented using iter_begin,
* iter_advance, iter_prev, iter_rewind.
*/
Variant reset();
Variant prev();
@@ -226,15 +233,13 @@ public:
/**
* Interface for VM helpers. ArrayData implements generic versions
* using the other ArrayData api; subclasses may customize methods either
* by overriding a virtual method or providing a custom static method,
* depending on how the method is dispatched.
* todo: t2608483 eliminate the remaining virtual methods.
* by providing a custom static method in g_array_funcs.
*/
TypedValue* nvGet(int64_t k) const;
TypedValue* nvGet(const StringData* k) const;
void nvGetKey(TypedValue* out, ssize_t pos) const;
// nonvirtual wrappers that call virtual getValueRef()
// wrappers that call getValueRef()
TypedValue* nvGetValueRef(ssize_t pos);
Variant getValue(ssize_t pos) const;
Variant getKey(ssize_t pos) const;
@@ -303,7 +308,8 @@ public:
/**
* Inline accessors that convert keys to StringData* before delegating to
* the virtual method.
* the virtual method. Helpers that take a CVarRef key dispatch to either
* the StringData* or int64_t key-type helpers.
*/
bool exists(CStrRef k) const;
bool exists(CVarRef k) const;
@@ -368,24 +374,32 @@ 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 = 0;
bool validFullPos(const FullPos& fp) const;
/**
* 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) = 0;
bool advanceFullPos(FullPos& fp);
CVarRef endRef();
virtual ArrayData* escalateForSort();
virtual void ksort(int sort_flags, bool ascending);
virtual void sort(int sort_flags, bool ascending);
virtual void asort(int sort_flags, bool ascending);
virtual void uksort(CVarRef cmp_function);
virtual void usort(CVarRef cmp_function);
virtual void uasort(CVarRef cmp_function);
ArrayData* escalateForSort();
void ksort(int sort_flags, bool ascending);
void sort(int sort_flags, bool ascending);
void asort(int sort_flags, bool ascending);
void uksort(CVarRef cmp_function);
void usort(CVarRef cmp_function);
void uasort(CVarRef cmp_function);
// default sort implementations
static void Ksort(ArrayData*, int sort_flags, bool ascending);
static void Sort(ArrayData*, int sort_flags, bool ascending);
static void Asort(ArrayData*, int sort_flags, bool ascending);
static void Uksort(ArrayData*, CVarRef cmp_function);
static void Usort(ArrayData*, CVarRef cmp_function);
static void Uasort(ArrayData*, CVarRef cmp_function);
/**
* Make a copy of myself.
@@ -394,9 +408,11 @@ public:
* Is only implemented for array types that need to be able to go
* into the static array list.
*/
virtual ArrayData *copy() const = 0;
virtual ArrayData *copyWithStrongIterators() const;
virtual ArrayData *nonSmartCopy() const;
ArrayData* copy() const;
ArrayData* copyWithStrongIterators() const;
ArrayData* nonSmartCopy() const;
static ArrayData* CopyWithStrongIterators(const ArrayData*);
static ArrayData* NonSmartCopy(const ArrayData*);
/**
* Append a value to the array. If "copy" is true, make a copy first
@@ -404,42 +420,42 @@ public:
* escalated array data.
*/
ArrayData* append(CVarRef v, bool copy);
virtual ArrayData* appendRef(CVarRef v, bool copy) = 0;
ArrayData* appendRef(CVarRef v, bool copy);
/**
* Similar to append(v, copy), with reference in v preserved.
*/
virtual ArrayData *appendWithRef(CVarRef v, bool copy) = 0;
ArrayData* appendWithRef(CVarRef v, bool copy);
/**
* Implementing array appending and merging. If "copy" is true, make a copy
* first then append/merge arrays. Return NULL if escalation is not needed,
* or an escalated array data.
*/
virtual ArrayData *plus(const ArrayData *elems, bool copy) = 0;
virtual ArrayData *merge(const ArrayData *elems, bool copy) = 0;
ArrayData* plus(const ArrayData *elems, bool copy);
ArrayData* merge(const ArrayData *elems, bool copy);
/**
* Stack function: pop the last item and return it.
*/
virtual ArrayData *pop(Variant &value);
ArrayData* pop(Variant &value);
/**
* Queue function: remove the 1st item and return it.
*/
virtual ArrayData *dequeue(Variant &value);
ArrayData* dequeue(Variant &value);
/**
* Array function: prepend a new item.
*/
virtual ArrayData *prepend(CVarRef v, bool copy) = 0;
ArrayData* prepend(CVarRef v, bool copy);
/**
* Only map classes need this. Re-index all numeric keys to start from 0.
*/
virtual void renumber() {}
void renumber();
virtual void onSetEvalScalar() { assert(false);}
void onSetEvalScalar();
/**
* Serialize this array. We could have made this virtual function to ask
@@ -452,9 +468,9 @@ public:
void serialize(VariableSerializer *serializer,
bool skipNestCheck = false) const;
virtual void dump();
virtual void dump(std::string &out);
virtual void dump(std::ostream &os);
void dump();
void dump(std::string &out);
void dump(std::ostream &os);
/**
* Comparisons.
@@ -464,9 +480,17 @@ public:
void setPosition(ssize_t p) { m_pos = p; }
virtual ArrayData *escalate() const {
return const_cast<ArrayData *>(this);
}
ArrayData *escalate() const;
// default implementations
static ArrayData* Plus(ArrayData*, const ArrayData *elems, bool copy);
static ArrayData* Merge(ArrayData*, const ArrayData *elems, bool copy);
static ArrayData* Pop(ArrayData*, Variant &value);
static ArrayData* Dequeue(ArrayData*, Variant &value);
static ArrayData* Prepend(ArrayData*, CVarRef v, bool copy);
static void Renumber(ArrayData*);
static void OnSetEvalScalar(ArrayData*);
static ArrayData* Escalate(const ArrayData* ad);
static ArrayData *GetScalarArray(ArrayData *arr,
const StringData *key = nullptr);
@@ -505,22 +529,20 @@ public:
void modeFree(void* ptr) const;
protected:
// Layout starts with 64 bits for vtable, then 32 bits for m_count
// from Countable base, then...
uint m_size;
private:
FullPos* m_strongIterators; // head of linked list
protected:
int32_t m_pos;
ArrayKind m_kind;
const AllocationMode m_allocMode;
uint32_t m_size;
mutable int32_t _count;
int32_t m_pos;
private:
FullPos* m_strongIterators; // head of linked list
public: // for the JIT
static uint32_t getKindOff() {
return (uintptr_t)&((ArrayData*)0)->m_kind;
}
public:
public: // for heap profiler
void getChildren(std::vector<TypedValue *> &out);
};
@@ -534,7 +556,6 @@ struct ArrayFunctions {
// NK stands for number of array kinds; here just for shorthand.
static auto const NK = size_t(ArrayData::ArrayKind::kNumKinds);
void (*release[NK])(ArrayData*);
ArrayData* (*append[NK])(ArrayData*, CVarRef v, bool copy);
TypedValue* (*nvGetInt[NK])(const ArrayData*, int64_t k);
TypedValue* (*nvGetStr[NK])(const ArrayData*, const StringData* k);
void (*nvGetKey[NK])(const ArrayData*, TypedValue* out, ssize_t pos);
@@ -569,6 +590,29 @@ struct ArrayFunctions {
ssize_t (*iterEnd[NK])(const ArrayData*);
ssize_t (*iterAdvance[NK])(const ArrayData*, ssize_t pos);
ssize_t (*iterRewind[NK])(const ArrayData*, ssize_t pos);
bool (*validFullPos[NK])(const ArrayData*, const FullPos&);
bool (*advanceFullPos[NK])(ArrayData*, FullPos&);
ArrayData* (*escalateForSort[NK])(ArrayData*);
void (*ksort[NK])(ArrayData* ad, int sort_flags, bool ascending);
void (*sort[NK])(ArrayData* ad, int sort_flags, bool ascending);
void (*asort[NK])(ArrayData* ad, int sort_flags, bool ascending);
void (*uksort[NK])(ArrayData* ad, CVarRef cmp_function);
void (*usort[NK])(ArrayData* ad, CVarRef cmp_function);
void (*uasort[NK])(ArrayData* ad, CVarRef cmp_function);
ArrayData* (*copy[NK])(const ArrayData*);
ArrayData* (*copyWithStrongIterators[NK])(const ArrayData*);
ArrayData* (*nonSmartCopy[NK])(const ArrayData*);
ArrayData* (*append[NK])(ArrayData*, CVarRef v, bool copy);
ArrayData* (*appendRef[NK])(ArrayData*, CVarRef v, bool copy);
ArrayData* (*appendWithRef[NK])(ArrayData*, CVarRef v, bool copy);
ArrayData* (*plus[NK])(ArrayData*, const ArrayData* elems, bool copy);
ArrayData* (*merge[NK])(ArrayData*, const ArrayData* elems, bool copy);
ArrayData* (*pop[NK])(ArrayData*, Variant& value);
ArrayData* (*dequeue[NK])(ArrayData*, Variant& value);
ArrayData* (*prepend[NK])(ArrayData*, CVarRef value, bool copy);
void (*renumber[NK])(ArrayData*);
void (*onSetEvalScalar[NK])(ArrayData*);
ArrayData* (*escalate[NK])(const ArrayData*);
};
extern const ArrayFunctions g_array_funcs;
+1 -2
Ver Arquivo
@@ -78,7 +78,7 @@ inline DEBUG_ONLY bool is_refcount_realistic(int32_t count) {
} \
bool isStatic() const { \
assert(is_refcount_realistic(_count)); \
return _count == STATIC_FLAG; \
return _count == RefCountStaticValue; \
} \
IMPLEMENT_COUNTABLE_METHODS_NO_STATIC
@@ -89,7 +89,6 @@ inline DEBUG_ONLY bool is_refcount_realistic(int32_t count) {
*/
class Countable {
public:
static const int32_t STATIC_FLAG = RefCountStaticValue;
Countable() : _count(0) {}
IMPLEMENT_COUNTABLE_METHODS
protected:
-2
Ver Arquivo
@@ -119,7 +119,6 @@ inline const HphpArray* HphpArray::asHphpArray(const ArrayData* ad) {
inline HphpArray* HphpArray::asVector(ArrayData* ad) {
assert(ad->kind() == kVectorKind);
assert(dynamic_cast<HphpArray*>(ad));
auto a = static_cast<HphpArray*>(ad);
assert(a->checkInvariants());
return a;
@@ -127,7 +126,6 @@ inline HphpArray* HphpArray::asVector(ArrayData* ad) {
inline const HphpArray* HphpArray::asVector(const ArrayData* ad) {
assert(ad->kind() == kVectorKind);
assert(dynamic_cast<const HphpArray*>(ad));
auto a = static_cast<const HphpArray*>(ad);
assert(a->checkInvariants());
return a;
+104 -85
Ver Arquivo
@@ -46,7 +46,7 @@
namespace HPHP {
static_assert(
sizeof(HphpArray) == 160,
sizeof(HphpArray) == 152,
"Performance is sensitive to sizeof(HphpArray)."
" Make sure you changed it with good reason and then update this assert.");
@@ -238,7 +238,7 @@ HOT_FUNC_VM
void HphpArray::ReleaseVec(ArrayData* ad) {
auto a = asVector(ad);
a->destroyVec();
if (UNLIKELY(a->strongIterators() != nullptr)) a->freeStrongIterators();
a->ArrayData::destroy();
HphpArray::AllocatorType::getNoCheck()->dealloc(a);
}
@@ -246,7 +246,7 @@ HOT_FUNC_VM
void HphpArray::Release(ArrayData* ad) {
auto a = asGeneric(ad);
a->destroy();
if (UNLIKELY(a->strongIterators() != nullptr)) a->freeStrongIterators();
a->ArrayData::destroy();
HphpArray::AllocatorType::getNoCheck()->dealloc(a);
}
@@ -1455,15 +1455,18 @@ HphpArray::RemoveStr(ArrayData* ad, const StringData* key, bool copy) {
return a->erase(a->findForInsert(key, key->hash()));
}
ArrayData* HphpArray::copy() const {
assert(checkInvariants());
return copyImpl();
ArrayData* HphpArray::CopyVec(const ArrayData* ad) {
return asVector(ad)->copyVec();
}
ArrayData* HphpArray::copyWithStrongIterators() const {
assert(checkInvariants());
HphpArray* copied = copyImpl();
moveStrongIterators(copied, const_cast<HphpArray*>(this));
ArrayData* HphpArray::Copy(const ArrayData* ad) {
return asGeneric(ad)->copyGeneric();
}
ArrayData* HphpArray::CopyWithStrongIterators(const ArrayData* ad) {
auto a = asHphpArray(ad);
auto copied = a->copyImpl();
moveStrongIterators(copied, const_cast<HphpArray*>(a));
return copied;
}
@@ -1590,32 +1593,38 @@ ArrayData* HphpArray::AddNewElemC(ArrayData* a, TypedValue value) {
return genericAddNewElemC(a, value);
}
ArrayData* HphpArray::appendRef(CVarRef v, bool copy) {
assert(checkInvariants());
HphpArray *a = !copy ? this : copyImpl();
if (a->isVector()) {
auto &tv = a->allocNextElm(a->m_size);
tvAsUninitializedVariant(&tv).constructRefHelper(v);
return a;
}
ArrayData* HphpArray::AppendRefVec(ArrayData* ad, CVarRef v, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
auto &tv = a->allocNextElm(a->m_size);
tvAsUninitializedVariant(&tv).constructRefHelper(v);
return a;
}
ArrayData* HphpArray::AppendRef(ArrayData* ad, CVarRef v, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->nextInsertRef(v);
}
ArrayData *HphpArray::appendWithRef(CVarRef v, bool copy) {
assert(checkInvariants());
HphpArray *a = !copy ? this : copyImpl();
if (a->isVector()) {
auto& tv = a->allocNextElm(a->m_size);
tvWriteNull(&tv);
tvAsVariant(&tv).setWithRef(v);
return a;
}
ArrayData *HphpArray::AppendWithRefVec(ArrayData* ad, CVarRef v, bool copy) {
auto a = asVector(ad);
if (copy) a = a->copyVec();
auto& tv = a->allocNextElm(a->m_size);
tvWriteNull(&tv);
tvAsVariant(&tv).setWithRef(v);
return a;
}
ArrayData *HphpArray::AppendWithRef(ArrayData* ad, CVarRef v, bool copy) {
auto a = asGeneric(ad);
if (copy) a = a->copyGeneric();
return a->nextInsertWithRef(v);
}
ArrayData* HphpArray::plus(const ArrayData* elems, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
ArrayData* HphpArray::Plus(ArrayData* ad, const ArrayData* elems, bool copy) {
auto a = asHphpArray(ad);
if (copy) a = a->copyImpl();
if (a->isVector()) {
// todo t2606310: is there a fast path if elems is also a vector?
a->vectorToGeneric();
@@ -1632,9 +1641,9 @@ ArrayData* HphpArray::plus(const ArrayData* elems, bool copy) {
return a;
}
ArrayData* HphpArray::merge(const ArrayData* elems, bool copy) {
assert(checkInvariants());
HphpArray* a = !copy ? this : copyImpl();
ArrayData* HphpArray::Merge(ArrayData* ad, const ArrayData* elems, bool copy) {
auto a = asHphpArray(ad);
if (copy) a = a->copyImpl();
if (a->isVector()) {
// todo t2606310: is there a fast path if elems is also a vector?
a->vectorToGeneric();
@@ -1654,22 +1663,30 @@ ArrayData* HphpArray::merge(const ArrayData* elems, bool copy) {
return a;
}
ArrayData* HphpArray::pop(Variant& value) {
assert(checkInvariants());
HphpArray* a = getCount() <= 1 ? this : copyImpl();
ArrayData* HphpArray::PopVec(ArrayData* ad, Variant& value) {
auto a = asVector(ad);
if (a->getCount() > 1) a = a->copyImpl();
if (a->m_size > 0) {
auto i = a->m_size - 1;
value = tvAsCVarRef(&a->m_data[i].data);
a->m_size = a->m_used = i;
a->m_pos = i > 0 ? 0 : invalid_index; // reset internal iterator
} else {
value = uninit_null();
a->m_pos = invalid_index; // reset internal iterator
}
return a;
}
ArrayData* HphpArray::Pop(ArrayData* ad, Variant& value) {
auto a = asGeneric(ad);
if (a->getCount() > 1) a = a->copyImpl();
Elm* elms = a->m_data;
ElmInd pos = IterEnd(a);
if (validElmInd(pos)) {
Elm* e = &elms[pos];
assert(!isTombstone(e->data.m_type));
value = tvAsCVarRef(&e->data);
if (a->isVector()) {
assert(pos == a->m_size - 1);
a->m_size = a->m_used = pos;
a->m_pos = pos ? 0 : invalid_index;
tvRefcountedDecRef(&e->data);
return a;
}
ElmInd* ei = e->hasStrKey()
? a->findForInsert(e->key, e->hash())
: a->findForInsert(e->ikey);
@@ -1683,9 +1700,9 @@ ArrayData* HphpArray::pop(Variant& value) {
return a;
}
ArrayData* HphpArray::dequeue(Variant& value) {
assert(checkInvariants());
HphpArray* a = getCount() <= 1 ? this : copyImpl();
ArrayData* HphpArray::Dequeue(ArrayData* ad, Variant& value) {
auto a = asHphpArray(ad);
if (a->getCount() > 1) a = a->copyImpl();
// To conform to PHP behavior, we invalidate all strong iterators when an
// element is removed from the beginning of the array.
a->freeStrongIterators();
@@ -1717,9 +1734,9 @@ ArrayData* HphpArray::dequeue(Variant& value) {
return a;
}
ArrayData* HphpArray::prepend(CVarRef v, bool copy) {
assert(checkInvariants());
HphpArray* a = getCount() <= 1 ? this : copyImpl();
ArrayData* HphpArray::Prepend(ArrayData* ad, CVarRef v, bool copy) {
auto a = asHphpArray(ad);
if (a->getCount() > 1) a = a->copyImpl();
if (a->isVector()) {
// todo t2606310: fast path - same as add for empty vectors
a->vectorToGeneric();
@@ -1757,69 +1774,71 @@ ArrayData* HphpArray::prepend(CVarRef v, bool copy) {
return a;
}
void HphpArray::renumber() {
assert(checkInvariants());
if (isVector()) {
// iterators don't move and nothing else happens.
return;
}
compact(true);
void HphpArray::RenumberVec(ArrayData* ad) {
assert(asVector(ad)); // for the checkInvariants() call
// renumber has no effect on Vector and doesn't move internal pos
}
void HphpArray::onSetEvalScalar() {
assert(checkInvariants());
Elm* elms = m_data;
if (isVector()) {
for (uint32_t i = 0, limit = m_used; i < limit; ++i) {
tvAsVariant(&elms[i].data).setEvalScalar();
}
} else {
for (uint32_t i = 0, limit = m_used; i < limit; ++i) {
Elm* e = &elms[i];
if (!isTombstone(e->data.m_type)) {
StringData *key = e->key;
if (e->hasStrKey() && !key->isStatic()) {
e->key = StringData::GetStaticString(key);
decRefStr(key);
}
tvAsVariant(&e->data).setEvalScalar();
void HphpArray::Renumber(ArrayData* ad) {
asGeneric(ad)->compact(true);
}
void HphpArray::OnSetEvalScalarVec(ArrayData* ad) {
auto a = asVector(ad);
Elm* elms = a->m_data;
for (uint32_t i = 0, limit = a->m_size; i < limit; ++i) {
tvAsVariant(&elms[i].data).setEvalScalar();
}
}
void HphpArray::OnSetEvalScalar(ArrayData* ad) {
auto a = asGeneric(ad);
Elm* elms = a->m_data;
for (uint32_t i = 0, limit = a->m_used; i < limit; ++i) {
Elm* e = &elms[i];
if (!isTombstone(e->data.m_type)) {
StringData *key = e->key;
if (e->hasStrKey() && !key->isStatic()) {
e->key = StringData::GetStaticString(key);
decRefStr(key);
}
tvAsVariant(&e->data).setEvalScalar();
}
}
}
bool HphpArray::validFullPos(const FullPos &fp) const {
assert(checkInvariants());
assert(fp.getContainer() == (ArrayData*)this);
bool HphpArray::ValidFullPos(const ArrayData* ad, const FullPos &fp) {
assert(fp.getContainer() == asHphpArray(ad));
if (fp.getResetFlag()) return false;
return (fp.m_pos != ssize_t(ElmIndEmpty));
}
bool HphpArray::advanceFullPos(FullPos& fp) {
assert(checkInvariants());
Elm* elms = m_data;
bool HphpArray::AdvanceFullPos(ArrayData* ad, FullPos& fp) {
auto a = asHphpArray(ad);
Elm* elms = a->m_data;
if (fp.getResetFlag()) {
fp.setResetFlag(false);
fp.m_pos = ElmIndEmpty;
} else if (fp.m_pos == ssize_t(ElmIndEmpty)) {
return false;
}
fp.m_pos = nextElm(elms, fp.m_pos);
fp.m_pos = a->nextElm(elms, fp.m_pos);
if (fp.m_pos == ssize_t(ElmIndEmpty)) {
return false;
}
// To conform to PHP behavior, we need to set the internal
// cursor to point to the next element.
m_pos = nextElm(elms, fp.m_pos);
a->m_pos = a->nextElm(elms, fp.m_pos);
return true;
}
//=============================================================================
NEVER_INLINE ArrayData* HphpArray::nonSmartCopy() const {
return isVector() ?
new HphpArray(*this, AllocationMode::nonSmart, CopyVector()) :
new HphpArray(*this, AllocationMode::nonSmart, CopyGeneric());
NEVER_INLINE ArrayData* HphpArray::NonSmartCopy(const ArrayData* ad) {
auto a = asHphpArray(ad);
return a->isVector() ?
new HphpArray(*a, AllocationMode::nonSmart, CopyVector()) :
new HphpArray(*a, AllocationMode::nonSmart, CopyGeneric());
}
NEVER_INLINE HphpArray* HphpArray::copyVec() const {
+29 -23
Ver Arquivo
@@ -70,7 +70,7 @@ public:
// moving (without refcounting) and reversing vals.
HphpArray(uint size, const TypedValue* vals); // make tuple
virtual ~HphpArray();
~HphpArray();
void destroyVec();
void destroy();
@@ -177,30 +177,36 @@ public:
static ArrayData* RemoveIntVec(ArrayData*, int64_t k, bool copy);
static ArrayData* RemoveStrVec(ArrayData*, const StringData* k, bool copy);
// overrides/implements ArrayData
ArrayData* copy() const;
ArrayData* copyWithStrongIterators() const;
// overrides ArrayData
static ArrayData* Copy(const ArrayData*);
static ArrayData* CopyVec(const ArrayData*);
static ArrayData* CopyWithStrongIterators(const ArrayData*);
static ArrayData* NonSmartCopy(const ArrayData*);
ArrayData* nonSmartCopy() const;
HphpArray* copyImpl() const;
HphpArray* copyVec() const;
HphpArray* copyGeneric() const;
static ArrayData* AppendVec(ArrayData*, CVarRef v, bool copy);
static ArrayData* Append(ArrayData*, CVarRef v, bool copy);
ArrayData* appendRef(CVarRef v, bool copy);
ArrayData* appendWithRef(CVarRef v, bool copy);
ArrayData* plus(const ArrayData* elems, bool copy);
ArrayData* merge(const ArrayData* elems, bool copy);
ArrayData* pop(Variant& value);
ArrayData* dequeue(Variant& value);
ArrayData* prepend(CVarRef v, bool copy);
void renumber();
void onSetEvalScalar();
static ArrayData* AppendRef(ArrayData*, CVarRef v, bool copy);
static ArrayData* AppendRefVec(ArrayData*, CVarRef v, bool copy);
static ArrayData* AppendWithRef(ArrayData*, CVarRef v, bool copy);
static ArrayData* AppendWithRefVec(ArrayData*, CVarRef v, bool copy);
static ArrayData* Plus(ArrayData*, const ArrayData* elems, bool copy);
static ArrayData* Merge(ArrayData*, const ArrayData* elems, bool copy);
static ArrayData* Pop(ArrayData*, Variant& value);
static ArrayData* PopVec(ArrayData*, Variant& value);
static ArrayData* Dequeue(ArrayData*, Variant& value);
static ArrayData* Prepend(ArrayData*, CVarRef v, bool copy);
static void Renumber(ArrayData*);
static void RenumberVec(ArrayData*);
static void OnSetEvalScalar(ArrayData*);
static void OnSetEvalScalarVec(ArrayData*);
// overrides ArrayData
bool validFullPos(const FullPos &fp) const;
bool advanceFullPos(FullPos& fp);
static bool ValidFullPos(const ArrayData*, const FullPos &fp);
static bool AdvanceFullPos(ArrayData*, FullPos& fp);
// END overide/implements section
@@ -245,13 +251,13 @@ private:
void postSort(bool resetKeys);
public:
ArrayData* escalateForSort();
void ksort(int sort_flags, bool ascending);
void sort(int sort_flags, bool ascending);
void asort(int sort_flags, bool ascending);
void uksort(CVarRef cmp_function);
void usort(CVarRef cmp_function);
void uasort(CVarRef cmp_function);
static ArrayData* EscalateForSort(ArrayData* ad);
static void Ksort(ArrayData*, int sort_flags, bool ascending);
static void Sort(ArrayData*, int sort_flags, bool ascending);
static void Asort(ArrayData*, int sort_flags, bool ascending);
static void Uksort(ArrayData*, CVarRef cmp_function);
static void Usort(ArrayData*, CVarRef cmp_function);
static void Uasort(ArrayData*, CVarRef cmp_function);
// Elm's data.m_type == KindOfInvalid for deleted slots.
static bool isTombstone(DataType t) {
+32 -26
Ver Arquivo
@@ -143,19 +143,19 @@ void HphpArray::postSort(bool resetKeys) {
m_hLoad = m_size;
}
ArrayData* HphpArray::escalateForSort() {
ArrayData* HphpArray::EscalateForSort(ArrayData* ad) {
// task #1910931 only do this for refCount() > 1
return copyImpl();
return asHphpArray(ad)->copyImpl();
}
#define SORT_CASE(flag, cmp_type, acc_type) \
case flag: { \
if (ascending) { \
cmp_type##Compare<acc_type, flag, true> comp; \
HPHP::Sort::sort(m_data, m_data + m_size, comp); \
HPHP::Sort::sort(a->m_data, a->m_data + a->m_size, comp); \
} else { \
cmp_type##Compare<acc_type, flag, false> comp; \
HPHP::Sort::sort(m_data, m_data + m_size, comp); \
HPHP::Sort::sort(a->m_data, a->m_data + a->m_size, comp); \
} \
break; \
}
@@ -179,34 +179,37 @@ ArrayData* HphpArray::escalateForSort() {
}
#define SORT_BODY(acc_type, resetKeys) \
do { \
freeStrongIterators(); \
if (!m_size) { \
a->freeStrongIterators(); \
if (!a->m_size) { \
if (resetKeys) { \
m_nextKI = 0; \
a->m_nextKI = 0; \
} \
return; \
} \
SortFlavor flav = preSort<acc_type>(acc_type(), true); \
m_pos = ssize_t(0); \
SortFlavor flav = a->preSort<acc_type>(acc_type(), true); \
a->m_pos = ssize_t(0); \
try { \
CALL_SORT(acc_type); \
} catch (...) { \
/* Make sure we leave the array in a consistent state */ \
postSort(resetKeys); \
a->postSort(resetKeys); \
throw; \
} \
postSort(resetKeys); \
a->postSort(resetKeys); \
} while (0)
void HphpArray::ksort(int sort_flags, bool ascending) {
void HphpArray::Ksort(ArrayData* ad, int sort_flags, bool ascending) {
auto a = asHphpArray(ad);
SORT_BODY(KeyAccessor, false);
}
void HphpArray::sort(int sort_flags, bool ascending) {
void HphpArray::Sort(ArrayData* ad, int sort_flags, bool ascending) {
auto a = asHphpArray(ad);
SORT_BODY(ValAccessor, true);
}
void HphpArray::asort(int sort_flags, bool ascending) {
void HphpArray::Asort(ArrayData* ad, int sort_flags, bool ascending) {
auto a = asHphpArray(ad);
SORT_BODY(ValAccessor, false);
}
@@ -216,39 +219,42 @@ void HphpArray::asort(int sort_flags, bool ascending) {
#define USER_SORT_BODY(acc_type, resetKeys) \
do { \
freeStrongIterators(); \
if (!m_size) { \
a->freeStrongIterators(); \
if (!a->m_size) { \
if (resetKeys) { \
m_nextKI = 0; \
a->m_nextKI = 0; \
} \
return; \
} \
preSort<acc_type>(acc_type(), false); \
m_pos = ssize_t(0); \
a->preSort<acc_type>(acc_type(), false); \
a->m_pos = ssize_t(0); \
try { \
ElmUCompare<acc_type> comp; \
Transl::CallerFrame cf; \
Transl::CallerFrame cf; \
CallCtx ctx; \
vm_decode_function(cmp_function, cf(), false, ctx); \
comp.ctx = &ctx; \
HPHP::Sort::sort(m_data, m_data + m_size, comp); \
HPHP::Sort::sort(a->m_data, a->m_data + a->m_size, comp); \
} catch (...) { \
/* Make sure we leave the array in a consistent state */ \
postSort(resetKeys); \
a->postSort(resetKeys); \
throw; \
} \
postSort(resetKeys); \
a->postSort(resetKeys); \
} while (0)
void HphpArray::uksort(CVarRef cmp_function) {
void HphpArray::Uksort(ArrayData* ad, CVarRef cmp_function) {
auto a = asHphpArray(ad);
USER_SORT_BODY(KeyAccessor, false);
}
void HphpArray::usort(CVarRef cmp_function) {
void HphpArray::Usort(ArrayData* ad, CVarRef cmp_function) {
auto a = asHphpArray(ad);
USER_SORT_BODY(ValAccessor, true);
}
void HphpArray::uasort(CVarRef cmp_function) {
void HphpArray::Uasort(ArrayData* ad, CVarRef cmp_function) {
auto a = asHphpArray(ad);
USER_SORT_BODY(ValAccessor, false);
}
+139 -139
Ver Arquivo
@@ -208,7 +208,7 @@ PolicyArray::PolicyArray(const PolicyArray& rhs, uint capacity,
PolicyArray::~PolicyArray() {
APILOG(this) << "()";
destroy(m_size, m_allocMode);
SimpleArrayStore::destroy(m_size, m_allocMode);
}
void PolicyArray::Release(ArrayData* ad) {
@@ -217,13 +217,11 @@ void PolicyArray::Release(ArrayData* ad) {
inline PolicyArray* PolicyArray::asPolicyArray(ArrayData* ad) {
assert(ad->kind() == kPolicyKind);
assert(dynamic_cast<PolicyArray*>(ad));
return static_cast<PolicyArray*>(ad);
}
inline const PolicyArray* PolicyArray::asPolicyArray(const ArrayData* ad) {
assert(ad->kind() == kPolicyKind);
assert(dynamic_cast<const PolicyArray*>(ad));
return static_cast<const PolicyArray*>(ad);
}
@@ -285,7 +283,7 @@ ArrayData *PolicyArray::lvalImpl(K k, Variant*& ret, bool copy) {
<< copy << ", " << ")";
if (copy) {
return PolicyArray::copy()->lvalImpl(k, ret, false);
return asPolicyArray(Copy(this))->lvalImpl(k, ret, false);
}
PosType pos = find(k, m_size);
@@ -319,7 +317,7 @@ ArrayData* PolicyArray::LvalStr(ArrayData* ad, StringData* k, Variant*& ret,
ArrayData *PolicyArray::LvalNew(ArrayData* ad, Variant *&ret, bool copy) {
auto a = asPolicyArray(ad);
if (copy) a = a->PolicyArray::copy();
if (copy) a = asPolicyArray(Copy(a));
// Andrei: TODO - append() currently never fails, probably it
// should.
@@ -346,9 +344,7 @@ ArrayData *PolicyArray::GetLvalPtr(ArrayData* ad, StringData* k,
Variant *&ret, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << keystr(k) << ", " << ret << ", " << copy << ")";
if (copy) {
return a->PolicyArray::copy()->getLvalPtr(k, ret, false);
}
if (copy) a = asPolicyArray(Copy(a));
const auto pos = a->find(k, a->m_size);
ret = pos != PosType::invalid
? &a->Store::lval(pos)
@@ -361,7 +357,7 @@ PolicyArray* PolicyArray::setImpl(K k, const Variant& v, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << valstr(v) << ", " << copy
<< ")";
PolicyArray* result = this;
if (copy) result = PolicyArray::copy();
if (copy) result = asPolicyArray(Copy(this));
if (result->update(k, v, result->m_size, result->m_allocMode)) {
// Added a new element, must update size and possibly m_pos
if (m_pos == invalid_index) m_pos = result->m_size;
@@ -385,7 +381,7 @@ ArrayData *PolicyArray::setRefImpl(K k, CVarRef v, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << valstr(v) << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->setRef(k, v, false);
return asPolicyArray(Copy(this))->setRef(k, v, false);
}
auto const pos = find(k, m_size);
@@ -446,7 +442,7 @@ template <class K>
ArrayData* PolicyArray::addLvalImpl(K k, Variant*& ret, bool copy) {
APILOG(this) << "(" << k << ", " << ret << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->addLval(k, ret, false);
return asPolicyArray(Copy(this))->addLval(k, ret, false);
}
assert(!exists(k) && m_size <= capacity());
if (m_size == capacity()) {
@@ -472,7 +468,7 @@ ArrayData *PolicyArray::removeImpl(K k, bool copy) {
APILOG(this) << "(" << keystr(k) << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->remove(k, false);
return asPolicyArray(Copy(this))->remove(k, false);
}
auto const pos = find(k, m_size);
@@ -541,28 +537,30 @@ ssize_t PolicyArray::IterRewind(const ArrayData* ad, ssize_t prev) {
return toInt<int64_t>(a->prevIndex(toPos(prev), a->m_size));
}
bool PolicyArray::validFullPos(const FullPos& fp) const {
APILOG(this) << "(" << fp.m_pos << ";" << fp.getResetFlag() << ")";
assert(fp.getContainer() == this);
bool PolicyArray::ValidFullPos(const ArrayData* ad, const FullPos& fp) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << fp.m_pos << ";" << fp.getResetFlag() << ")";
assert(fp.getContainer() == a);
return fp.m_pos != invalid_index;
}
bool PolicyArray::advanceFullPos(FullPos &fp) {
APILOG(this) << "(" << fp.m_pos << ";" << fp.getResetFlag() << ")";
assert(fp.getContainer() == this);
bool PolicyArray::AdvanceFullPos(ArrayData* ad, FullPos &fp) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << fp.m_pos << ";" << fp.getResetFlag() << ")";
assert(fp.getContainer() == a);
if (fp.getResetFlag()) {
fp.setResetFlag(false);
fp.m_pos = invalid_index;
} else if (fp.m_pos == invalid_index) {
return false;
}
fp.m_pos = toInt<int64_t>(nextIndex(toPos(fp.m_pos), m_size));
fp.m_pos = toInt<int64_t>(a->nextIndex(toPos(fp.m_pos), a->m_size));
if (fp.m_pos == invalid_index) {
return false;
}
// To conform to PHP behavior, we need to set the internal
// cursor to point to the next element.
m_pos = toInt<int64_t>(nextIndex(toPos(fp.m_pos), m_size));
a->m_pos = toInt<int64_t>(a->nextIndex(toPos(fp.m_pos), a->m_size));
return true;
}
@@ -578,17 +576,17 @@ HphpArray* PolicyArray::toHphpArray() const {
return result;
}
ArrayData* PolicyArray::escalateForSort() {
APILOG(this) << "()";
return toHphpArray();
ArrayData* PolicyArray::EscalateForSort(ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
return a->toHphpArray();
}
PolicyArray *PolicyArray::copy() const {
APILOG(this) << "()";
auto result = NEW(PolicyArray)(
*this,
capacity() + (m_size == capacity()),
m_allocMode);
ArrayData* PolicyArray::Copy(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
auto result = NEW(PolicyArray)(*a,
a->capacity() + (a->m_size == a->capacity()), a->m_allocMode);
assert(result->getCount() == 0);
return result;
}
@@ -598,58 +596,56 @@ PolicyArray* PolicyArray::copy(uint capacity) {
return NEW(PolicyArray)(*this, capacity, m_allocMode);
}
PolicyArray *PolicyArray::copyWithStrongIterators() const {
APILOG(this) << "()";
auto result = PolicyArray::copy();
moveStrongIterators(result, const_cast<PolicyArray*>(this));
ArrayData* PolicyArray::CopyWithStrongIterators(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
auto result = Copy(a);
moveStrongIterators(result, const_cast<PolicyArray*>(a));
assert(result->getCount() == 0);
return result;
}
ArrayData *PolicyArray::nonSmartCopy() const {
APILOG(this) << "()";
//return NEW(PolicyArray)(*this, capacity(), true);
return toHphpArray()->nonSmartCopy();
ArrayData* PolicyArray::NonSmartCopy(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
return a->toHphpArray()->nonSmartCopy();
}
ArrayData *PolicyArray::Append(ArrayData* ad, const Variant& v, bool copy) {
auto a = static_cast<PolicyArray*>(ad);
ArrayData* PolicyArray::Append(ArrayData* ad, const Variant& v, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << valstr(v) << ", " << copy << ")";
if (copy) a = a->PolicyArray::copy();
if (copy) a = asPolicyArray(Copy(a));
a->grow(a->m_size, a->m_size + 1, a->m_size * 2 + 1, a->m_allocMode);
a->appendNoGrow(a->nextKeyBump(), v);
return a;
}
PolicyArray *PolicyArray::appendRef(const Variant& v, bool copy) {
APILOG(this) << "(" << valstr(v) << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->appendRef(v, false);
ArrayData* PolicyArray::AppendRef(ArrayData* ad, const Variant& v, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << valstr(v) << ", " << copy << ")";
if (copy) a = asPolicyArray(Copy(a));
auto const k = a->nextKeyBump();
if (a->m_size == a->capacity()) {
a->grow(a->m_size, a->m_size + 1, a->m_size * 2 + 1, a->m_allocMode);
}
//addValWithRef(nextKeyBump(), v);
auto const k = nextKeyBump();
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(k, Variant::NoInit())->constructRefHelper(v);
return this;
assert(a->m_size < a->capacity());
a->appendNoGrow(k, Variant::NoInit())->constructRefHelper(v);
return a;
}
/**
* Similar to append(v, copy), with reference in v preserved.
*/
ArrayData *PolicyArray::appendWithRef(CVarRef v, bool copy) {
APILOG(this) << "(" << valstr(v) << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->appendWithRef(v, false);
ArrayData* PolicyArray::AppendWithRef(ArrayData* ad, CVarRef v, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << valstr(v) << ", " << copy << ")";
if (copy) a = asPolicyArray(Copy(a));
if (a->m_size == a->capacity()) {
a->grow(a->m_size, a->m_size + 1, a->m_size * 2 + 1, a->m_allocMode);
}
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(nextKeyBump(), Variant::NullInit())->setWithRef(v);
return this;
assert(a->m_size < a->capacity());
a->appendNoGrow(a->nextKeyBump(), Variant::NullInit())->setWithRef(v);
return a;
}
template <class K>
@@ -688,127 +684,125 @@ void PolicyArray::nextInsertWithRef(const Variant& v) {
appendNoGrow(k, Variant::NullInit())->setWithRef(v);
}
ArrayData *PolicyArray::plus(const ArrayData *elems, bool copy) {
APILOG(this) << "(" << elems << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->plus(elems, false);
}
ArrayData*
PolicyArray::Plus(ArrayData* ad, const ArrayData *elems, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << elems << ", " << copy << ")";
if (copy) a = asPolicyArray(Copy(a));
assert(elems);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
a->grow(a->m_size, a->m_size + 1, a->m_size * 2 + 1, a->m_allocMode);
for (ArrayIter it(elems); !it.end(); it.next()) {
Variant key = it.first();
const Variant& value = it.secondRef();
if (key.isNumeric()) {
addValWithRef(key.toInt64(), value);
a->addValWithRef(key.toInt64(), value);
} else {
addValWithRef(key.getStringData(), value);
a->addValWithRef(key.getStringData(), value);
}
}
return this;
return a;
}
ArrayData *PolicyArray::merge(const ArrayData *elems, bool copy) {
APILOG(this) << "(" << elems << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->merge(elems, false);
}
ArrayData*
PolicyArray::Merge(ArrayData* ad, const ArrayData *elems, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << elems << ", " << copy << ")";
if (copy) a = asPolicyArray(Copy(a));
assert(elems);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
a->grow(a->m_size, a->m_size + 1, a->m_size * 2 + 1, a->m_allocMode);
for (ArrayIter it(elems); !it.end(); it.next()) {
Variant key = it.first();
const Variant& value = it.secondRef();
if (key.isNumeric()) {
nextInsertWithRef(value);
a->nextInsertWithRef(value);
} else {
StringData *s = key.getStringData();
Variant *p;
// Andrei TODO: make sure this is the right semantics
LvalStr(this, s, p, false);
LvalStr(a, s, p, false);
p->setWithRef(value);
}
}
return this;
return a;
}
/**
* Stack function: pop the last item and return it.
*/
ArrayData* PolicyArray::pop(Variant &value) {
APILOG(this) << "(" << &value << ")";
if (getCount() > 1) {
return PolicyArray::copy()->pop(value);
}
if (!m_size) {
/**
* Stack function: pop the last item and return it.
*/
ArrayData* PolicyArray::Pop(ArrayData* ad, Variant &value) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << &value << ")";
if (a->getCount() > 1) a = asPolicyArray(Copy(a));
if (!a->m_size) {
value = uninit_null();
return this;
return a;
}
auto pos = lastIndex(m_size);
assert(size_t(pos) < m_size);
value = val(pos);
auto pos = a->lastIndex(a->m_size);
assert(size_t(pos) < a->m_size);
value = a->val(pos);
// Match PHP 5.3.1 semantics
if (!hasStrKey(pos)
&& Store::nextKey() == 1 + key(pos).toInt64()) {
nextKeyPop();
if (!a->hasStrKey(pos)
&& a->Store::nextKey() == 1 + a->key(pos).toInt64()) {
a->nextKeyPop();
}
Store::erase(pos, m_size);
--m_size;
a->Store::erase(pos, a->m_size);
--a->m_size;
// To match PHP-like semantics, the pop operation resets the array's
// internal iterator.
m_pos = m_size ? toInt<int64_t>(firstIndex(m_size)) : invalid_index;
return this;
a->m_pos = a->m_size ? toInt<int64_t>(a->firstIndex(a->m_size)) :
invalid_index;
return a;
}
ArrayData *PolicyArray::dequeue(Variant &value) {
APILOG(this) << "(" << &value << ")";
if (getCount() > 1) {
return PolicyArray::copy()->dequeue(value);
}
ArrayData* PolicyArray::Dequeue(ArrayData* ad, Variant &value) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << &value << ")";
if (a->getCount() > 1) a = asPolicyArray(Copy(ad));
// To match PHP-like semantics, we invalidate all strong iterators when an
// element is removed from the beginning of the array.
freeStrongIterators();
if (!m_size) {
a->freeStrongIterators();
if (!a->m_size) {
value = uninit_null();
return this;
return a;
}
auto& front = lval(firstIndex(m_size));
auto& front = a->lval(a->firstIndex(a->m_size));
value = std::move(front);
new(&front) Variant;
erase(firstIndex(m_size), m_size);
--m_size;
renumber();
a->erase(a->firstIndex(a->m_size), a->m_size);
--a->m_size;
a->renumber();
// To match PHP-like semantics, the dequeue operation resets the array's
// internal iterator
m_pos = m_size ? toInt<int64_t>(firstIndex(m_size)) : invalid_index;
return this;
a->m_pos = a->m_size ? toInt<int64_t>(a->firstIndex(a->m_size)) :
invalid_index;
return a;
}
ArrayData* PolicyArray::prepend(CVarRef v, bool copy) {
APILOG(this) << "(" << valstr(v) << ", " << copy << ")";
if (copy) {
return PolicyArray::copy()->prepend(v, false);
}
ArrayData* PolicyArray::Prepend(ArrayData* ad, CVarRef v, bool copy) {
auto a = asPolicyArray(ad);
APILOG(a) << "(" << valstr(v) << ", " << copy << ")";
if (copy) a = asPolicyArray(Copy(a));
// To match PHP-like semantics, we invalidate all strong iterators when an
// element is added to the beginning of the array.
freeStrongIterators();
Store::prepend(v, m_size, m_allocMode);
++m_size;
auto first = firstIndex(m_size);
setKey(first, int64_t(0));
// Renumber.
renumber();
a->freeStrongIterators();
a->Store::prepend(v, a->m_size, a->m_allocMode);
++a->m_size;
auto first = a->firstIndex(a->m_size);
a->setKey(first, int64_t(0));
a->renumber();
// To match PHP-like semantics, the prepend operation resets the array's
// internal iterator
m_pos = toInt<int64_t>(first);
return this;
a->m_pos = toInt<int64_t>(first);
return a;
}
void PolicyArray::renumber() {
@@ -867,30 +861,36 @@ void PolicyArray::renumber() {
assert(i == siKeys.cend());
}
void PolicyArray::onSetEvalScalar() {
APILOG(this) << "()";
void PolicyArray::Renumber(ArrayData* ad) {
return asPolicyArray(ad)->renumber();
}
void PolicyArray::OnSetEvalScalar(ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
//FOR_EACH_RANGE (pos, 0, m_size) {
for (auto pos = firstIndex(m_size); pos != PosType::invalid;
pos = nextIndex(pos, m_size)) {
if (hasStrKey(pos)) {
auto k = key(pos).getStringData();
for (auto pos = a->firstIndex(a->m_size); pos != PosType::invalid;
pos = a->nextIndex(pos, a->m_size)) {
if (a->hasStrKey(pos)) {
auto k = a->key(pos).getStringData();
if (!k->isStatic()) {
auto sk = StringData::GetStaticString(k);
if (k->decRefCount() == 0) {
DELETE(StringData)(k);
}
// Andrei TODO: inefficient, does one incref and then decref
setKey(pos, sk);
a->setKey(pos, sk);
sk->decRefCount();
}
}
lval(pos).setEvalScalar();
a->lval(pos).setEvalScalar();
}
}
ArrayData *PolicyArray::escalate() const {
APILOG(this) << "()";
return ArrayData::escalate();
ArrayData *PolicyArray::Escalate(const ArrayData* ad) {
auto a = asPolicyArray(ad);
APILOG(a) << "()";
return ArrayData::Escalate(a);
}
} // namespace HPHP
+18 -17
Ver Arquivo
@@ -329,7 +329,7 @@ public:
explicit PolicyArray(uint size);
virtual ~PolicyArray() FOLLY_OVERRIDE;
~PolicyArray();
/**
* getValueRef() gets a reference to value at position "pos".
@@ -475,16 +475,16 @@ 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 FOLLY_OVERRIDE;
static bool ValidFullPos(const ArrayData*, const FullPos& fp);
/**
* 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) FOLLY_OVERRIDE;
static bool AdvanceFullPos(ArrayData* ad, FullPos& fp);
virtual ArrayData* escalateForSort() FOLLY_OVERRIDE;
static ArrayData* EscalateForSort(ArrayData* ad);
/**
* Make a copy of myself.
@@ -494,9 +494,9 @@ public:
* into the static array list.
*/
PolicyArray* copy(uint minCapacity);
virtual PolicyArray *copy() const FOLLY_OVERRIDE;
virtual PolicyArray *copyWithStrongIterators() const FOLLY_OVERRIDE;
virtual ArrayData *nonSmartCopy() const FOLLY_OVERRIDE;
static ArrayData* Copy(const ArrayData* ad);
static ArrayData* CopyWithStrongIterators(const ArrayData* ad);
static ArrayData* NonSmartCopy(const ArrayData* ad);
private:
template <class K, class V>
@@ -520,44 +520,45 @@ public:
* escalated array data.
*/
static ArrayData* Append(ArrayData*, CVarRef v, bool copy);
virtual PolicyArray *appendRef(CVarRef v, bool copy) FOLLY_OVERRIDE;
static ArrayData* AppendRef(ArrayData*, CVarRef v, bool copy);
/**
* Similar to append(v, copy), with reference in v preserved.
*/
virtual ArrayData *appendWithRef(CVarRef v, bool copy) FOLLY_OVERRIDE;
static ArrayData* AppendWithRef(ArrayData*, CVarRef v, bool copy);
/**
* Implementing array appending and merging. If "copy" is true, make a copy
* first then append/merge arrays. Return NULL if escalation is not needed,
* or an escalated array data.
*/
virtual ArrayData *plus(const ArrayData *elems, bool copy) FOLLY_OVERRIDE;
virtual ArrayData *merge(const ArrayData *elems, bool copy) FOLLY_OVERRIDE;
static ArrayData* Plus(ArrayData* ad, const ArrayData *elems, bool copy);
static ArrayData* Merge(ArrayData* ad, const ArrayData *elems, bool copy);
/**
* Stack function: pop the last item and return it.
*/
virtual ArrayData *pop(Variant &value) FOLLY_OVERRIDE;
static ArrayData* Pop(ArrayData*, Variant &value);
/**
* Queue function: remove the 1st item and return it.
*/
virtual ArrayData *dequeue(Variant &value) FOLLY_OVERRIDE;
static ArrayData* Dequeue(ArrayData*, Variant &value);
/**
* Array function: prepend a new item.
*/
virtual ArrayData *prepend(CVarRef v, bool copy) FOLLY_OVERRIDE;
static ArrayData* Prepend(ArrayData*, CVarRef v, bool copy);
/**
* Only map classes need this. Re-index all numeric keys to start from 0.
*/
virtual void renumber() FOLLY_OVERRIDE;
void renumber();
static void Renumber(ArrayData*);
virtual void onSetEvalScalar() FOLLY_OVERRIDE;
static void OnSetEvalScalar(ArrayData*);
virtual ArrayData *escalate() const FOLLY_OVERRIDE;
static ArrayData* Escalate(const ArrayData*);
};
///////////////////////////////////////////////////////////////////////////////
+32 -34
Ver Arquivo
@@ -67,13 +67,11 @@ void SharedMap::Release(ArrayData* ad) {
inline SharedMap* SharedMap::asSharedMap(ArrayData* ad) {
assert(ad->kind() == kSharedKind);
assert(dynamic_cast<SharedMap*>(ad));
return static_cast<SharedMap*>(ad);
}
inline const SharedMap* SharedMap::asSharedMap(const ArrayData* ad) {
assert(ad->kind() == kSharedKind);
assert(dynamic_cast<const SharedMap*>(ad));
return static_cast<const SharedMap*>(ad);
}
@@ -118,104 +116,103 @@ inline ArrayData* releaseIfCopied(ArrayData* a1, ArrayData* a2) {
ArrayData *SharedMap::LvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->lval(k, ret, false));
}
ArrayData *SharedMap::LvalStr(ArrayData* ad, StringData* k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->lval(k, ret, false));
}
ArrayData *SharedMap::LvalNew(ArrayData* ad, Variant *&ret, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->lvalNew(ret, false));
}
ArrayData*
SharedMap::SetInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->set(k, v, false));
}
ArrayData*
SharedMap::SetStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->set(k, v, false));
}
ArrayData*
SharedMap::SetRefInt(ArrayData* ad, int64_t k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->setRef(k, v, false));
}
ArrayData*
SharedMap::SetRefStr(ArrayData* ad, StringData* k, CVarRef v, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->setRef(k, v, false));
}
ArrayData *SharedMap::AddLvalInt(ArrayData* ad, int64_t k, Variant *&ret,
bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
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();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->addLval(k, ret, false));
}
ArrayData *SharedMap::RemoveInt(ArrayData* ad, int64_t k, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->remove(k, false));
}
ArrayData *SharedMap::RemoveStr(ArrayData* ad, const StringData* k, bool copy) {
ArrayData *escalated = asSharedMap(ad)->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->remove(k, false));
}
ArrayData *SharedMap::copy() const {
return SharedMap::escalate();
ArrayData* SharedMap::Copy(const ArrayData* ad) {
return Escalate(ad);
}
ArrayData *SharedMap::Append(ArrayData* ad, CVarRef v, bool copy) {
auto a = asSharedMap(ad);
ArrayData *escalated = a->SharedMap::escalate();
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->append(v, false));
}
ArrayData *SharedMap::appendRef(CVarRef v, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::AppendRef(ArrayData* ad, CVarRef v, bool copy) {
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->appendRef(v, false));
}
ArrayData *SharedMap::appendWithRef(CVarRef v, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::AppendWithRef(ArrayData* ad, CVarRef v, bool copy) {
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->appendWithRef(v, false));
}
ArrayData *SharedMap::plus(const ArrayData *elems, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::Plus(ArrayData* ad, const ArrayData *elems, bool copy) {
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->plus(elems, false));
}
ArrayData *SharedMap::merge(const ArrayData *elems, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::Merge(ArrayData* ad, const ArrayData *elems, bool copy) {
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->merge(elems, false));
}
ArrayData *SharedMap::prepend(CVarRef v, bool copy) {
ArrayData *escalated = SharedMap::escalate();
ArrayData *SharedMap::Prepend(ArrayData* ad, CVarRef v, bool copy) {
ArrayData *escalated = Escalate(ad);
return releaseIfCopied(escalated, escalated->prepend(v, false));
}
ArrayData *SharedMap::escalate() const {
ArrayData *ret = loadElems();
ArrayData *SharedMap::Escalate(const ArrayData* ad) {
auto ret = asSharedMap(ad)->loadElems();
assert(!ret->isStatic());
return ret;
}
@@ -249,8 +246,9 @@ void SharedMap::NvGetKey(const ArrayData* ad, TypedValue* out, ssize_t pos) {
}
}
ArrayData* SharedMap::escalateForSort() {
ArrayData *ret = loadElems(true /* mapInit */);
ArrayData* SharedMap::EscalateForSort(ArrayData* ad) {
auto a = asSharedMap(ad);
auto ret = a->loadElems(true /* mapInit */);
assert(!ret->isStatic());
return ret;
}
@@ -279,12 +277,12 @@ ssize_t SharedMap::IterRewind(const ArrayData* ad, ssize_t prev) {
return next >= 0 ? next : invalid_index;
}
bool SharedMap::validFullPos(const FullPos& fp) const {
assert(fp.getContainer() == (ArrayData*)this);
bool SharedMap::ValidFullPos(const ArrayData* ad, const FullPos& fp) {
assert(fp.getContainer() == ad);
return false;
}
bool SharedMap::advanceFullPos(FullPos& fp) {
bool SharedMap::AdvanceFullPos(ArrayData* ad, FullPos& fp) {
return false;
}
+12 -15
Ver Arquivo
@@ -42,8 +42,6 @@ public:
~SharedMap();
virtual bool isSharedMap() const { return true; }
// these using directives ensure the full set of overloaded functions
// are visible in this class, to avoid triggering implicit conversions
// from a CVarRef key to int64.
@@ -85,20 +83,19 @@ public:
static ArrayData *RemoveInt(ArrayData* ad, int64_t k, bool copy);
static ArrayData *RemoveStr(ArrayData* ad, const StringData* k, bool copy);
ArrayData *copy() const;
static ArrayData* Copy(const ArrayData*);
/**
* Copy (escalate) the SharedMap without triggering local cache.
*/
static ArrayData *Append(ArrayData* a, CVarRef v, bool copy);
ArrayData *appendRef(CVarRef v, bool copy);
ArrayData *appendWithRef(CVarRef v, bool copy);
ArrayData *plus(const ArrayData *elems, bool copy);
ArrayData *merge(const ArrayData *elems, bool copy);
ArrayData *prepend(CVarRef v, bool copy);
static ArrayData* Append(ArrayData* a, CVarRef v, bool copy);
static ArrayData* AppendRef(ArrayData*, CVarRef v, bool copy);
static ArrayData* AppendWithRef(ArrayData*, CVarRef v, bool copy);
static ArrayData* Plus(ArrayData*, const ArrayData *elems, bool copy);
static ArrayData* Merge(ArrayData*, const ArrayData *elems, bool copy);
static ArrayData* Prepend(ArrayData*, CVarRef v, bool copy);
/**
* Non-Variant virtual methods that override ArrayData
* Non-Variant methods that override ArrayData
*/
static TypedValue* NvGetInt(const ArrayData*, int64_t k);
static TypedValue* NvGetStr(const ArrayData*, const StringData* k);
@@ -111,8 +108,8 @@ public:
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);
static bool ValidFullPos(const ArrayData*, const FullPos& fp);
static bool AdvanceFullPos(ArrayData*, FullPos& fp);
/**
* Memory allocator methods.
@@ -120,8 +117,8 @@ public:
DECLARE_SMART_ALLOCATION(SharedMap);
static void Release(ArrayData*);
virtual ArrayData *escalate() const;
virtual ArrayData* escalateForSort();
static ArrayData* Escalate(const ArrayData*);
static ArrayData* EscalateForSort(ArrayData*);
ArrayData* loadElems(bool mapInit = false) const;
-4
Ver Arquivo
@@ -378,10 +378,6 @@ struct GarbageCollector {
}
void dealloc(SmartAllocatorImpl* sa, ArrayData* ar) const {
if (Sweepable* s = dynamic_cast<Sweepable*>(ar)) {
s->sweep();
s->unregister();
}
sa->dealloc(ar);
}
+32 -25
Ver Arquivo
@@ -25,14 +25,12 @@ namespace HPHP {
inline NameValueTableWrapper* NameValueTableWrapper::asNVTW(ArrayData* ad) {
assert(ad->kind() == kNvtwKind);
assert(dynamic_cast<NameValueTableWrapper*>(ad));
return static_cast<NameValueTableWrapper*>(ad);
}
inline const NameValueTableWrapper*
NameValueTableWrapper::asNVTW(const ArrayData* ad) {
assert(ad->kind() == kNvtwKind);
assert(dynamic_cast<const NameValueTableWrapper*>(ad));
return static_cast<const NameValueTableWrapper*>(ad);
}
@@ -170,27 +168,33 @@ NameValueTableWrapper::RemoveStr(ArrayData* ad, const StringData* k,
* is currently $GLOBALS.
*/
ArrayData* NameValueTableWrapper::Append(ArrayData*, CVarRef v, bool copy) {
ArrayData*
NameValueTableWrapper::Append(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("append on $GLOBALS");
}
ArrayData* NameValueTableWrapper::appendRef(CVarRef v, bool copy) {
ArrayData*
NameValueTableWrapper::AppendRef(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("appendRef on $GLOBALS");
}
ArrayData* NameValueTableWrapper::appendWithRef(CVarRef v, bool copy) {
ArrayData*
NameValueTableWrapper::AppendWithRef(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("appendWithRef on $GLOBALS");
}
ArrayData* NameValueTableWrapper::plus(const ArrayData* elems, bool copy) {
ArrayData*
NameValueTableWrapper::Plus(ArrayData*, const ArrayData* elems, bool copy) {
throw NotImplementedException("plus on $GLOBALS");
}
ArrayData* NameValueTableWrapper::merge(const ArrayData* elems, bool copy) {
ArrayData*
NameValueTableWrapper::Merge(ArrayData*, const ArrayData* elems, bool copy) {
throw NotImplementedException("merge on $GLOBALS");
}
ArrayData* NameValueTableWrapper::prepend(CVarRef v, bool copy) {
ArrayData*
NameValueTableWrapper::Prepend(ArrayData*, CVarRef v, bool copy) {
throw NotImplementedException("prepend on $GLOBALS");
}
@@ -219,19 +223,22 @@ ssize_t NameValueTableWrapper::IterRewind(const ArrayData* ad, ssize_t prev) {
return iter.toInteger();
}
bool NameValueTableWrapper::validFullPos(const FullPos & fp) const {
assert(fp.getContainer() == (ArrayData*)this);
bool
NameValueTableWrapper::ValidFullPos(const ArrayData* ad, const FullPos & fp) {
assert(fp.getContainer() == ad);
auto a = asNVTW(ad);
if (fp.getResetFlag()) return false;
if (fp.m_pos == ArrayData::invalid_index) return false;
NameValueTable::Iterator iter(m_tab, fp.m_pos);
return (iter.valid());
if (fp.m_pos == invalid_index) return false;
NameValueTable::Iterator iter(a->m_tab, fp.m_pos);
return iter.valid();
}
bool NameValueTableWrapper::advanceFullPos(FullPos& fp) {
bool NameValueTableWrapper::AdvanceFullPos(ArrayData* ad, FullPos& fp) {
auto a = asNVTW(ad);
bool reset = fp.getResetFlag();
NameValueTable::Iterator iter = reset ?
NameValueTable::Iterator(m_tab) :
NameValueTable::Iterator(m_tab, fp.m_pos);
NameValueTable::Iterator(a->m_tab) :
NameValueTable::Iterator(a->m_tab, fp.m_pos);
if (reset) {
fp.setResetFlag(false);
} else {
@@ -245,20 +252,20 @@ bool NameValueTableWrapper::advanceFullPos(FullPos& fp) {
// To conform to PHP behavior, we need to set the internal
// cursor to point to the next element.
iter.next();
m_pos = iter.toInteger();
a->m_pos = iter.toInteger();
return true;
}
ArrayData* NameValueTableWrapper::escalateForSort() {
ArrayData* NameValueTableWrapper::EscalateForSort(ArrayData* ad) {
raise_warning("Sorting the $GLOBALS array is not supported");
return this;
return ad;
}
void NameValueTableWrapper::ksort(int sort_flags, bool ascending) {}
void NameValueTableWrapper::sort(int sort_flags, bool ascending) {}
void NameValueTableWrapper::asort(int sort_flags, bool ascending) {}
void NameValueTableWrapper::uksort(CVarRef cmp_function) {}
void NameValueTableWrapper::usort(CVarRef cmp_function) {}
void NameValueTableWrapper::uasort(CVarRef cmp_function) {}
void NameValueTableWrapper::Ksort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Sort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Asort(ArrayData*, int sort_flags, bool ascending) {}
void NameValueTableWrapper::Uksort(ArrayData*, CVarRef cmp_function) {}
void NameValueTableWrapper::Usort(ArrayData*, CVarRef cmp_function) {}
void NameValueTableWrapper::Uasort(ArrayData*, CVarRef cmp_function) {}
bool NameValueTableWrapper::IsVectorData(const ArrayData*) {
return false;
+17 -16
Ver Arquivo
@@ -103,33 +103,34 @@ public: // ArrayData implementation
static ArrayData* RemoveInt(ArrayData*, int64_t k, bool copy);
static ArrayData* RemoveStr(ArrayData*, const StringData* k, bool copy);
virtual ArrayData* copy() const { return 0; }
static ArrayData* Copy(const ArrayData* ad) {
return const_cast<ArrayData*>(ad);
}
static ArrayData* Append(ArrayData*, CVarRef v, bool copy);
virtual ArrayData* appendRef(CVarRef v, bool copy);
virtual ArrayData* appendWithRef(CVarRef v, bool copy);
static ArrayData* AppendRef(ArrayData*, CVarRef v, bool copy);
static ArrayData* AppendWithRef(ArrayData*, CVarRef v, bool copy);
virtual ArrayData* plus(const ArrayData* elems, bool copy);
virtual ArrayData* merge(const ArrayData* elems, bool copy);
virtual ArrayData* prepend(CVarRef v, bool copy);
static ArrayData* Plus(ArrayData*, const ArrayData* elems, bool copy);
static ArrayData* Merge(ArrayData*, const ArrayData* elems, bool copy);
static ArrayData* Prepend(ArrayData*, CVarRef v, bool copy);
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&);
static bool ValidFullPos(const ArrayData*, const FullPos & fp);
static bool AdvanceFullPos(ArrayData*, FullPos&);
static bool IsVectorData(const ArrayData*);
virtual ArrayData* escalateForSort();
virtual void ksort(int sort_flags, bool ascending);
virtual void sort(int sort_flags, bool ascending);
virtual void asort(int sort_flags, bool ascending);
virtual void uksort(CVarRef cmp_function);
virtual void usort(CVarRef cmp_function);
virtual void uasort(CVarRef cmp_function);
static ArrayData* EscalateForSort(ArrayData*);
static void Ksort(ArrayData*, int sort_flags, bool ascending);
static void Sort(ArrayData*, int sort_flags, bool ascending);
static void Asort(ArrayData*, int sort_flags, bool ascending);
static void Uksort(ArrayData*, CVarRef cmp_function);
static void Usort(ArrayData*, CVarRef cmp_function);
static void Uasort(ArrayData*, CVarRef cmp_function);
private:
static NameValueTableWrapper* asNVTW(ArrayData* ad);