ArrayData: consolidate m_nonsmart and m_allocMode into one field

The in-situ allocation case can be easily detected by checking m_data == m_inline_data.slots. Therefore there's no need for two distinct flags to track current and future allocation strategy.
Esse commit está contido em:
Andrei Alexandrescu
2013-06-05 20:33:08 -07:00
commit de Sara Golemon
commit 4debf268f7
8 arquivos alterados com 139 adições e 127 exclusões
+6 -1
Ver Arquivo
@@ -31,6 +31,11 @@
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
static_assert(
sizeof(ArrayData) == 32,
"Performance is sensitive to sizeof(ArrayData)."
" Make sure you changed it with good reason and then update this assert.");
typedef tbb::concurrent_hash_map<const StringData *, ArrayData *,
StringDataHashCompare> ArrayDataMap;
static ArrayDataMap s_arrayDataMap;
@@ -121,7 +126,7 @@ void ArrayData::release() {
that->release();
return;
}
assert(m_kind == kNameValueTableWrapper);
assert(m_kind == ArrayKind::kNameValueTableWrapper);
// NameValueTableWrapper: nop.
}
+34 -37
Ver Arquivo
@@ -34,6 +34,8 @@ class HphpArray;
*/
class ArrayData : public Countable {
public:
enum class AllocationMode : bool { smart, nonSmart };
enum ArrayOp {
Plus,
Merge,
@@ -41,50 +43,47 @@ class ArrayData : public Countable {
// enum of possible array types, so we can guard nonvirtual
// fast paths in runtime code.
enum ArrayKind : uint8_t {
enum class ArrayKind : uint8_t {
kHphpArray,
kSharedMap,
kNameValueTableWrapper,
kArrayShell,
};
protected:
// used in subclasses but declared here.
enum AllocMode : uint8_t { kInline, kSmart, kMalloc };
public:
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_nonsmart(false)
, m_strongIterators(nullptr) {
}
, m_allocMode(AllocationMode::smart)
{}
ArrayData(ArrayKind kind, bool nonsmart)
: m_size(-1)
, m_pos(0)
, m_kind(kind)
, m_nonsmart(nonsmart)
, m_strongIterators(nullptr) {
}
explicit ArrayData(ArrayKind kind, AllocationMode m)
: m_size(-1)
, m_strongIterators(nullptr)
, m_pos(0)
, m_kind(kind)
, m_allocMode(m)
{}
ArrayData(ArrayKind kind, bool nonsmart, uint size)
ArrayData(ArrayKind kind, AllocationMode m, uint size)
: m_size(size)
, m_strongIterators(nullptr)
, m_pos(size ? 0 : ArrayData::invalid_index)
, m_kind(kind)
, m_nonsmart(nonsmart)
, m_strongIterators(nullptr) {
}
, m_allocMode(m)
{}
ArrayData(const ArrayData *src, ArrayKind kind, bool nonsmart = false)
: m_pos(src->m_pos)
, m_kind(src->m_kind)
, m_nonsmart(nonsmart)
, 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_allocMode(m)
{}
static HphpArray* Make(uint capacity);
static HphpArray* Make(uint size, const TypedValue*);
@@ -172,11 +171,11 @@ class ArrayData : public Countable {
/*
* Specific derived class type querying operators.
*/
bool isArrayShell() const { return m_kind == kArrayShell; }
bool isHphpArray() const { return m_kind == kHphpArray; }
bool isSharedMap() const { return m_kind == kSharedMap; }
bool isArrayShell() const { return m_kind == ArrayKind::kArrayShell; }
bool isHphpArray() const { return m_kind == ArrayKind::kHphpArray; }
bool isSharedMap() const { return m_kind == ArrayKind::kSharedMap; }
bool isNameValueTableWrapper() const {
return m_kind == kNameValueTableWrapper;
return m_kind == ArrayKind::kNameValueTableWrapper;
}
@@ -503,14 +502,12 @@ class ArrayData : public Countable {
// Layout starts with 64 bits for vtable, then 32 bits for m_count
// from Countable base, then...
uint m_size;
int32_t m_pos;
protected:
const ArrayKind m_kind;
AllocMode m_allocMode;
const bool m_nonsmart; // never use smartalloc to allocate Elms
uint8_t m_slack8; // use this for whatever you wanna
private:
private:
FullPos* m_strongIterators; // head of linked list
protected:
int32_t m_pos;
const ArrayKind m_kind;
const AllocationMode m_allocMode;
public: // for the JIT
static uint32_t getKindOff() {
+44 -39
Ver Arquivo
@@ -41,6 +41,11 @@
namespace HPHP {
static_assert(
sizeof(HphpArray) == 160,
"Performance is sensitive to sizeof(HphpArray)."
" Make sure you changed it with good reason and then update this assert.");
static const Trace::Module TRACEMOD = Trace::runtime;
///////////////////////////////////////////////////////////////////////////////
@@ -114,19 +119,22 @@ inline void HphpArray::init(uint capacity) {
initHash(m_hash, tableSize);
}
HphpArray::HphpArray(uint size) : ArrayData(kHphpArray, false, 0),
m_lastE(ElmIndEmpty), m_hLoad(0), m_nextKI(0) {
HphpArray::HphpArray(uint capacity)
: ArrayData(ArrayKind::kHphpArray, AllocationMode::smart, 0)
, m_lastE(ElmIndEmpty)
, m_hLoad(0)
, m_nextKI(0) {
#ifdef PEDANTIC
if (size > 0x7fffffffU) {
raise_error("Cannot create an array with more than 2^31 - 1 elements");
}
#endif
assert(m_size == 0);
init(size);
init(capacity);
}
HphpArray::HphpArray(uint size, const TypedValue* values)
: ArrayData(kHphpArray, false, size)
: ArrayData(ArrayKind::kHphpArray, AllocationMode::smart, size)
, m_lastE(size - 1)
, m_hLoad(size)
, m_nextKI(size) {
@@ -163,33 +171,36 @@ HphpArray::HphpArray(uint size, const TypedValue* values)
}
HphpArray::HphpArray(EmptyMode)
: ArrayData(kHphpArray, false, 0)
, m_lastE(ElmIndEmpty)
, m_hLoad(0)
, m_nextKI(0) {
: ArrayData(ArrayKind::kHphpArray, AllocationMode::smart, 0)
, m_lastE(ElmIndEmpty)
, m_hLoad(0)
, m_nextKI(0) {
init(0);
setStatic();
}
// Empty constructor for internal use by nonSmartCopy() and copyImpl()
HphpArray::HphpArray(AllocMode mode) :
ArrayData(kHphpArray, /*nonsmart*/ mode == kMalloc) {
HphpArray::HphpArray(AllocationMode mode) :
ArrayData(ArrayKind::kHphpArray, mode) {
}
HOT_FUNC_VM
HphpArray::~HphpArray() {
Elm* elms = m_data;
ssize_t lastE = (ssize_t)m_lastE;
auto const elms = m_data;
auto const lastE = (ssize_t)m_lastE;
for (ssize_t /*ElmInd*/ pos = 0; pos <= lastE; ++pos) {
Elm* e = &elms[pos];
if (e->data.m_type == KindOfTombstone) continue;
if (e->hasStrKey()) decRefStr(e->key);
tvRefcountedDecRef(&e->data);
auto& e = elms[pos];
if (e.data.m_type == KindOfTombstone) continue;
if (e.hasStrKey()) decRefStr(e.key);
tvRefcountedDecRef(&e.data);
}
if (m_allocMode == kSmart) {
smart_free(m_data);
} else if (m_allocMode == kMalloc) {
free(m_data);
if (m_data == m_inline_data.slots) {
return;
}
if (m_allocMode == AllocationMode::smart) {
smart_free(elms);
} else {
free(elms);
}
}
@@ -724,19 +735,16 @@ void HphpArray::allocData(size_t maxElms, size_t tableSize) {
if (maxElms <= SmallSize) {
m_data = m_inline_data.slots;
m_hash = m_inline_data.hash;
m_allocMode = kInline;
return;
}
size_t hashSize = tableSize * sizeof(ElmInd);
size_t dataSize = maxElms * sizeof(Elm);
size_t allocSize = hashSize <= sizeof(m_inline_hash) ? dataSize :
dataSize + hashSize;
if (!m_nonsmart) {
if (m_allocMode == AllocationMode::smart) {
m_data = (Elm*) smart_malloc(allocSize);
m_allocMode = kSmart;
} else {
m_data = (Elm*) Util::safe_malloc(allocSize);
m_allocMode = kMalloc;
}
m_hash = hashSize <= sizeof(m_inline_hash) ? m_inline_hash :
(ElmInd*)(uintptr_t(m_data) + dataSize);
@@ -749,24 +757,21 @@ void HphpArray::reallocData(size_t maxElms, size_t tableSize, uint oldMask) {
size_t allocSize = hashSize <= sizeof(m_inline_hash) ? dataSize :
dataSize + hashSize;
size_t oldDataSize = computeMaxElms(oldMask) * sizeof(Elm); // slots only.
if (!m_nonsmart) {
assert(m_allocMode == kInline || m_allocMode == kSmart);
if (m_allocMode == kInline) {
if (m_allocMode == AllocationMode::smart) {
if (m_data == m_inline_data.slots) {
m_data = (Elm*) smart_malloc(allocSize);
copyData:
memcpy(m_data, m_inline_data.slots, oldDataSize);
m_allocMode = kSmart;
} else {
m_data = (Elm*) smart_realloc(m_data, allocSize);
}
} else {
assert(m_allocMode == kInline || m_allocMode == kMalloc);
if (m_allocMode == kInline) {
if (m_data == m_inline_data.slots) {
m_data = (Elm*) Util::safe_malloc(allocSize);
memcpy(m_data, m_inline_data.slots, oldDataSize);
m_allocMode = kMalloc;
} else {
m_data = (Elm*) Util::safe_realloc(m_data, allocSize);
// This goto doesn't loop, just saves the memcpy call code.
goto copyData;
}
m_data = (Elm*) Util::safe_realloc(m_data, allocSize);
}
m_hash = hashSize <= sizeof(m_inline_hash) ? m_inline_hash :
(ElmInd*)(uintptr_t(m_data) + dataSize);
@@ -1855,8 +1860,8 @@ ArrayData* array_add(ArrayData* a1, ArrayData* a2) {
//=============================================================================
ALWAYS_INLINE HphpArray* HphpArray::clone(AllocMode am) const {
const auto p = am == kSmart
ALWAYS_INLINE HphpArray* HphpArray::clone(AllocationMode am) const {
const auto p = am == AllocationMode::smart
? HphpArray::AllocatorType::getNoCheck()->alloc(sizeof(HphpArray))
: operator new(sizeof(HphpArray));
auto target = new(p) HphpArray(am);
@@ -1870,7 +1875,7 @@ ALWAYS_INLINE HphpArray* HphpArray::clone(AllocMode am) const {
// frequent. Do this only for arrays that actually don't allocate
// data so the copied array doesn't lose capacity.
target->ArrayData::m_pos = invalid_index;
target->ArrayData::m_allocMode = kInline;
assert(target->ArrayData::m_allocMode == am);
// Conservatively copy m_nextKI
target->m_nextKI = m_nextKI;
target->m_tableMask = SmallHashSize - 1;
@@ -1889,11 +1894,11 @@ ALWAYS_INLINE HphpArray* HphpArray::clone(AllocMode am) const {
}
NEVER_INLINE ArrayData* HphpArray::nonSmartCopy() const {
return clone(kMalloc);
return clone(AllocationMode::nonSmart);
}
NEVER_INLINE HphpArray* HphpArray::copyImpl() const {
return clone(kSmart);
return clone(AllocationMode::smart);
}
NEVER_INLINE void HphpArray::cloneNonEmpty(HphpArray* target) const {
+2 -2
Ver Arquivo
@@ -45,7 +45,7 @@ public:
private:
// for copy-on-write escalation
explicit HphpArray(AllocMode);
explicit HphpArray(AllocationMode);
public:
// Create an empty array with enough capacity for nSize elements.
@@ -507,7 +507,7 @@ public:
}
private:
HphpArray* clone(AllocMode am) const;
HphpArray* clone(AllocationMode am) const;
void cloneNonEmpty(HphpArray* target) const;
};
+35 -33
Ver Arquivo
@@ -46,11 +46,12 @@ static string valstr(const Variant& v) {
SimpleArrayStore::SimpleArrayStore(const SimpleArrayStore& rhs,
uint length, uint capacity,
bool nonSmart, const ArrayData* owner)
ArrayData::AllocationMode am,
const ArrayData* owner)
: m_capacity(std::max<uint>(startingCapacity, capacity))
, m_nextKey(rhs.m_nextKey) {
assert(length <= capacity && this != &rhs);
allocate(m_keys, m_vals, m_capacity, nonSmart);
allocate(m_keys, m_vals, m_capacity, am);
// Copy data with flattening
FOR_EACH_RANGE (i, 0, length) {
tvDupFlattenVars(rhs.m_vals + i, m_vals + i, owner);
@@ -63,26 +64,26 @@ SimpleArrayStore::SimpleArrayStore(const SimpleArrayStore& rhs,
}
void SimpleArrayStore::grow(uint length, uint minCap, uint idealCap,
bool nonSmart) {
ArrayData::AllocationMode am) {
assert(idealCap >= minCap);
if (m_capacity >= minCap) return;
MYLOG << (void*)this << "->grow(" << length << ", " << minCap << ", "
<< idealCap << ", " << nonSmart << "); m_capacity=" << m_capacity;
<< idealCap << ", " << uint(am) << "); m_capacity=" << m_capacity;
idealCap = std::max<uint>(startingCapacity, idealCap);
Key* newKeys;
TypedValueAux* newVals;
allocate(newKeys, newVals, idealCap, nonSmart);
allocate(newKeys, newVals, idealCap, am);
// Move data
memcpy(newKeys, m_keys, length * sizeof(*m_keys));
memcpy(newVals, m_vals, length * sizeof(*m_vals));
deallocate(m_keys, m_vals, nonSmart);
deallocate(m_keys, m_vals, am);
// Change state
m_capacity = idealCap;
m_keys = newKeys;
m_vals = newVals;
}
void SimpleArrayStore::destroy(uint length, bool nonSmart) {
void SimpleArrayStore::destroy(uint length, ArrayData::AllocationMode am) {
FOR_EACH_RANGE (i, 0, length) {
if (hasStrKey(toPos(i))) {
auto k = m_keys[i].s;
@@ -91,7 +92,7 @@ void SimpleArrayStore::destroy(uint length, bool nonSmart) {
}
lval(toPos(i)).~Variant();
}
deallocate(m_keys, m_vals, nonSmart);
deallocate(m_keys, m_vals, am);
#ifndef NDEBUG
m_keys = nullptr;
m_vals = nullptr;
@@ -130,7 +131,7 @@ PosType SimpleArrayStore::find(const StringData* key, uint length) const {
template <class K>
bool SimpleArrayStore::update(K key, const Variant& val, uint length,
bool nonSmart) {
ArrayData::AllocationMode am) {
assert(length <= m_capacity && m_vals);
auto const pos = find(key, length);
if (pos != PosType::invalid) {
@@ -142,7 +143,7 @@ bool SimpleArrayStore::update(K key, const Variant& val, uint length,
// not found, insert
assert(length <= m_capacity);
if (length == m_capacity) {
grow(length, length + 1, length * 2 + 1, nonSmart);
grow(length, length + 1, length * 2 + 1, am);
}
assert(m_keys && m_vals && length < m_capacity);
new(&lval(toPos(length))) Variant(val);
@@ -166,9 +167,10 @@ void SimpleArrayStore::erase(PosType pos, uint length) {
memmove(m_vals + ipos, m_vals + ipos + 1, itemsToMove * sizeof(*m_vals));
}
void SimpleArrayStore::prepend(const Variant& v, uint length, bool nonSmart) {
void SimpleArrayStore::prepend(const Variant& v, uint length,
ArrayData::AllocationMode am) {
if (length == capacity()) {
grow(length, length + 1, length * 2 + 1, nonSmart);
grow(length, length + 1, length * 2 + 1, am);
}
assert(length < capacity());
// Shift stuff over
@@ -183,8 +185,8 @@ void SimpleArrayStore::prepend(const Variant& v, uint length, bool nonSmart) {
IMPLEMENT_SMART_ALLOCATION(ArrayShell)
ArrayShell::ArrayShell(uint capacity)
: ArrayData(kArrayShell)
, Store(m_nonsmart, capacity) {
: ArrayData(ArrayKind::kArrayShell)
, Store(m_allocMode, capacity) {
m_size = 0;
m_pos = invalid_index;
// Log at the end of the ctor so as to show the properly initialized
@@ -193,19 +195,19 @@ ArrayShell::ArrayShell(uint capacity)
}
ArrayShell::ArrayShell(const ArrayShell& rhs, uint capacity,
bool nonSmart)
: ArrayData(kArrayShell, nonSmart)
, Store(rhs, rhs.m_size, capacity, nonSmart, &rhs) {
AllocationMode am)
: ArrayData(ArrayKind::kArrayShell, am)
, Store(rhs, rhs.m_size, capacity, am, &rhs) {
m_size = rhs.m_size;
m_pos = rhs.m_pos;
// Log at the end of the ctor so as to show the properly initialized
// members.
APILOG << "(" << &rhs << ", " << capacity << ", " << nonSmart << ");";
APILOG << "(" << &rhs << ", " << capacity << ", " << uint(am) << ");";
}
ArrayShell::~ArrayShell() {
APILOG << "()";
destroy(m_size, m_nonsmart);
destroy(m_size, m_allocMode);
}
Variant ArrayShell::getKey(ssize_t pos) const {
@@ -391,7 +393,7 @@ ArrayData *ArrayShell::lvalImpl(K k, Variant*& ret,
} else {
// not found, initialize
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
ret = appendNoGrow(k, Variant::NullInit());
@@ -431,7 +433,7 @@ ArrayShell* ArrayShell::setImpl(K k, const Variant& v, bool copy) {
<< ")";
ArrayShell* result = this;
if (copy) result = ArrayShell::copy();
if (result->update(k, v, result->m_size, result->m_nonsmart)) {
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;
result->m_size++;
@@ -457,7 +459,7 @@ ArrayData *ArrayShell::setRefImpl(K k, CVarRef v, bool copy) {
MYLOG << "setRef: not found, appending at " << m_size;
if (m_size == capacity()) {
MYLOG << "grow";
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
appendNoGrow(k, Variant::NoInit())->constructRefHelper(v);
}
@@ -475,7 +477,7 @@ ArrayData *ArrayShell::addImpl(K k, const Variant& v, bool copy) {
assert(!exists(k));
// Make sure there's enough capacity
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
appendNoGrow(k, v);
return this;
@@ -489,7 +491,7 @@ ArrayShell *ArrayShell::addLvalImpl(K k, Variant*& ret, bool copy) {
}
assert(!exists(k) && m_size <= capacity());
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
ret = appendNoGrow(k, Variant::NullInit());
MYLOG << (void*)this << "->lval:" << "added";
@@ -635,14 +637,14 @@ ArrayShell *ArrayShell::copy() const {
auto result = NEW(ArrayShell)(
*this,
capacity() + (m_size == capacity()),
m_nonsmart);
m_allocMode);
assert(result->getCount() == 0);
return result;
}
ArrayShell* ArrayShell::copy(uint capacity) {
APILOG << "(" << capacity << ")";
return NEW(ArrayShell)(*this, capacity, m_nonsmart);
return NEW(ArrayShell)(*this, capacity, m_allocMode);
}
ArrayShell *ArrayShell::copyWithStrongIterators() const {
@@ -664,7 +666,7 @@ ArrayShell *ArrayShell::append(const Variant& v, bool copy) {
if (copy) {
return ArrayShell::copy()->append(v, false);
}
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
appendNoGrow(nextKeyBump(), v);
return this;
}
@@ -677,7 +679,7 @@ ArrayShell *ArrayShell::appendRef(const Variant& v, bool copy) {
//addValWithRef(nextKeyBump(), v);
auto const k = nextKeyBump();
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(k, Variant::NoInit())->constructRefHelper(v);
@@ -693,7 +695,7 @@ ArrayData *ArrayShell::appendWithRef(CVarRef v, bool copy) {
return ArrayShell::copy()->appendWithRef(v, false);
}
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(nextKeyBump(), Variant::NullInit())->setWithRef(v);
@@ -710,7 +712,7 @@ void ArrayShell::addValWithRef(K k, const Variant& v) {
return;
}
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(k, Variant::NullInit())->setWithRef(v);
@@ -730,7 +732,7 @@ void ArrayShell::nextInsertWithRef(const Variant& v) {
// always false [-Werror=strict-overflow]
auto const k = nextKeyBump();
if (m_size == capacity()) {
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
}
assert(m_size < capacity());
appendNoGrow(k, Variant::NullInit())->setWithRef(v);
@@ -744,7 +746,7 @@ ArrayData *ArrayShell::append(const ArrayData *elems, ArrayOp op, bool copy) {
assert(elems);
assert(op == Plus || op == Merge);
grow(m_size, m_size + 1, m_size * 2 + 1, m_nonsmart);
grow(m_size, m_size + 1, m_size * 2 + 1, m_allocMode);
for (ArrayIter it(elems); !it.end(); it.next()) {
Variant key = it.first();
@@ -827,7 +829,7 @@ ArrayData* ArrayShell::prepend(CVarRef v, bool copy) {
// 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_nonsmart);
Store::prepend(v, m_size, m_allocMode);
++m_size;
auto first = firstIndex(m_size);
setKey(first, int64_t(0));
+15 -12
Ver Arquivo
@@ -99,11 +99,12 @@ class SimpleArrayStore {
Allocate keys and values at a given capacity and with a given
allocation strategy.
*/
static void allocate(Key*& ks, TypedValueAux*& vs, uint cap, bool nonSmart) {
static void allocate(Key*& ks, TypedValueAux*& vs, uint cap,
ArrayData::AllocationMode am) {
/* To save time, only one allocation is done and keys are stored
right next to the values. */
auto const totSize = (sizeof(*ks) + sizeof(*vs)) * cap;
auto const raw = nonSmart
auto const raw = am == ArrayData::AllocationMode::nonSmart
? Util::safe_malloc(totSize)
: smart_malloc(totSize);
vs = static_cast<TypedValueAux*>(raw);
@@ -111,9 +112,10 @@ class SimpleArrayStore {
}
/** Inverse of allocate */
static void deallocate(Key* ks, TypedValueAux* vs, bool nonSmart) {
static void deallocate(Key* ks, TypedValueAux* vs,
ArrayData::AllocationMode am) {
assert(ks && vs);
if (nonSmart) {
if (am == ArrayData::AllocationMode::nonSmart) {
Util::safe_free(vs);
} else {
smart_free(vs);
@@ -139,7 +141,7 @@ protected:
required by tvDupFlattenVars).
*/
SimpleArrayStore(const SimpleArrayStore& rhs, uint length, uint capacity,
bool nonSmart, const ArrayData* owner);
ArrayData::AllocationMode am, const ArrayData* owner);
~SimpleArrayStore() {
/* If this fails, it means someone didn't call destroy. */
assert(!m_keys && !m_vals);
@@ -151,7 +153,7 @@ protected:
separate function in order to obtain length and nonSmart
information.
*/
void destroy(uint length, bool nonSmart);
void destroy(uint length, ArrayData::AllocationMode);
/**
The following four methods implement bidirectional iteration for
@@ -188,7 +190,7 @@ protected:
Prepend v to the array. An uninitialized hole is left in the first
key slot; you MUST use setKey subsequently to initialize it.
*/
void prepend(const Variant& v, uint length, bool nonSmart);
void prepend(const Variant& v, uint length, ArrayData::AllocationMode);
/**
Erase at position pos from the array. Cleans up data and
@@ -200,10 +202,10 @@ protected:
Construct an array store with the given allocation strategy and
capacity.
*/
SimpleArrayStore(bool nonSmart, uint capacity)
SimpleArrayStore(ArrayData::AllocationMode am, uint capacity)
: m_capacity(std::max<uint>(startingCapacity, capacity))
, m_nextKey(0) {
allocate(m_keys, m_vals, m_capacity, nonSmart);
allocate(m_keys, m_vals, m_capacity, am);
}
/**
@@ -218,7 +220,7 @@ protected:
<= minSize && minSize = idealSize. No actual objects are allocated
in the grown store.
*/
void grow(uint size, uint minSize, uint idealSize, bool nonSmart);
void grow(uint size, uint minSize, uint idealSize, ArrayData::AllocationMode);
/**
Returns true iff the key at pos is a string.
@@ -277,7 +279,8 @@ protected:
its refcount.
*/
template <class K>
bool update(K key, const Variant& val, uint length, bool nonSmart);
bool update(K key, const Variant& val, uint length,
ArrayData::AllocationMode);
/**
Returns a const reference to the Variant held at position
@@ -326,7 +329,7 @@ class ArrayShell : public ArrayData, private SimpleArrayStore {
ArrayShell(const ArrayShell& rhs) = delete;
ArrayShell& operator=(const ArrayShell& rhs) = delete;
ArrayShell(const ArrayShell& rhs, uint capacity, bool nonSmart);
ArrayShell(const ArrayShell& rhs, uint capacity, ArrayData::AllocationMode);
template <class K>
void addValWithRef(K k, const Variant& value);
+2 -2
Ver Arquivo
@@ -32,8 +32,8 @@ namespace HPHP {
class SharedMap : public ArrayData {
public:
explicit SharedMap(SharedVariant* source)
: ArrayData(kSharedMap)
, m_localCache(nullptr) {
: ArrayData(ArrayKind::kSharedMap)
, m_localCache(nullptr) {
m_map = source->getMap();
m_isVector = source->getIsVector();
}
+1 -1
Ver Arquivo
@@ -54,7 +54,7 @@ namespace HPHP {
*/
struct NameValueTableWrapper : public ArrayData {
explicit NameValueTableWrapper(NameValueTable* tab)
: ArrayData(kNameValueTableWrapper)
: ArrayData(ArrayKind::kNameValueTableWrapper)
, m_tab(tab)
{ }