diff --git a/hphp/runtime/base/array_data-defs.h b/hphp/runtime/base/array_data-defs.h index 09e78e469..4cd6cff1f 100644 --- a/hphp/runtime/base/array_data-defs.h +++ b/hphp/runtime/base/array_data-defs.h @@ -167,37 +167,32 @@ inline Variant ArrayData::getKey(ssize_t pos) const { /////////////////////////////////////////////////////////////////////////////// -inline unsigned ArrayData::index() const { - assert(unsigned(m_kind) < unsigned(ArrayKind::kNumKinds)); - return unsigned(m_kind); -} - inline void ArrayData::release() { - return g_array_funcs.release[index()](this); + return g_array_funcs.release[m_kind](this); } inline ArrayData* ArrayData::append(CVarRef v, bool copy) { - return g_array_funcs.append[index()](this, v, copy); + return g_array_funcs.append[m_kind](this, v, copy); } inline TypedValue* ArrayData::nvGet(int64_t ikey) const { - return g_array_funcs.nvGetInt[index()](this, ikey); + return g_array_funcs.nvGetInt[m_kind](this, ikey); } inline TypedValue* ArrayData::nvGet(const StringData* skey) const { - return g_array_funcs.nvGetStr[index()](this, skey); + return g_array_funcs.nvGetStr[m_kind](this, skey); } inline void ArrayData::nvGetKey(TypedValue* out, ssize_t pos) const { - g_array_funcs.nvGetKey[index()](this, out, pos); + g_array_funcs.nvGetKey[m_kind](this, out, pos); } inline ArrayData* ArrayData::set(int64_t k, CVarRef v, bool copy) { - return g_array_funcs.setInt[index()](this, k, v, copy); + return g_array_funcs.setInt[m_kind](this, k, v, copy); } inline ArrayData* ArrayData::set(StringData* k, CVarRef v, bool copy) { - return g_array_funcs.setStr[index()](this, k, v, copy); + return g_array_funcs.setStr[m_kind](this, k, v, copy); } /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/base/array_data.cpp b/hphp/runtime/base/array_data.cpp index ab6100bd3..7fd25f07b 100644 --- a/hphp/runtime/base/array_data.cpp +++ b/hphp/runtime/base/array_data.cpp @@ -64,7 +64,7 @@ ArrayData *ArrayData::GetScalarArray(ArrayData *arr, /////////////////////////////////////////////////////////////////////////////// -// order: kVector, kHphpArray, kSharedMap, kNameValueTableWrapper, kPolicyArray +// order: kVectorKind, kMixedKind, kSharedKind, kNvtwKind, kPolicyKind extern const ArrayFunctions g_array_funcs = { // release { &HphpArray::ReleaseVec, &HphpArray::Release, @@ -503,12 +503,12 @@ CVarRef ArrayData::getNotFound(const StringData* k) { } CVarRef ArrayData::getNotFound(int64_t k, bool error) const { - return error && m_kind != ArrayKind::kNameValueTableWrapper ? getNotFound(k) : + return error && m_kind != kNvtwKind ? getNotFound(k) : null_variant; } CVarRef ArrayData::getNotFound(const StringData* k, bool error) const { - return error && m_kind != ArrayKind::kNameValueTableWrapper ? getNotFound(k) : + return error && m_kind != kNvtwKind ? getNotFound(k) : null_variant; } diff --git a/hphp/runtime/base/array_data.h b/hphp/runtime/base/array_data.h index 156f3f6ac..59fe5ebaa 100644 --- a/hphp/runtime/base/array_data.h +++ b/hphp/runtime/base/array_data.h @@ -38,13 +38,17 @@ class ArrayData : public Countable { enum class AllocationMode : bool { smart, nonSmart }; // enum of possible array types, so we can guard nonvirtual - // fast paths in runtime code. - enum class ArrayKind : uint8_t { - kVector, - kHphpArray, - kSharedMap, - kNameValueTableWrapper, - kPolicyArray, + // fast paths in runtime code. This is intentionally not + // an enum class, to avoid boilerplate when: + // - doing relational comparisons + // - using kind as an index + // - maybe doing bitops in the future + enum ArrayKind : uint8_t { + kVectorKind, // HphpArray vector-shape + kMixedKind, // HphpArray generic shape + kSharedKind, // SharedMap + kNvtwKind, // NameValueTableWrapper + kPolicyKind, // PolicyArray kNumKinds // insert new values before kNumKinds. }; @@ -134,7 +138,7 @@ public: * return the array kind for fast typechecks */ ArrayKind kind() const { - return (ArrayKind)m_kind; + return m_kind; } /** @@ -163,15 +167,15 @@ public: /* * Specific derived class type querying operators. */ - bool isPolicyArray() const { return m_kind == ArrayKind::kPolicyArray; } - bool isVector() const { return m_kind == ArrayKind::kVector; } + bool isPolicyArray() const { return m_kind == kPolicyKind; } + bool isVector() const { return m_kind == kVectorKind; } bool isHphpArray() const { - return m_kind <= ArrayKind::kHphpArray; - static_assert(ArrayKind::kVector < ArrayKind::kHphpArray, ""); + return m_kind <= kMixedKind; + static_assert(kVectorKind < kMixedKind, ""); } - bool isSharedMap() const { return m_kind == ArrayKind::kSharedMap; } + bool isSharedMap() const { return m_kind == kSharedKind; } bool isNameValueTableWrapper() const { - return m_kind == ArrayKind::kNameValueTableWrapper; + return m_kind == kNvtwKind; } @@ -463,8 +467,6 @@ public: static_assert(offsetof(ArrayData, _count) == FAST_REFCOUNT_OFFSET, "Offset of _count in ArrayData must be FAST_REFCOUNT_OFFSET"); } - // safely convert m_kind to an array index for dispatching - unsigned index() const; protected: void freeStrongIterators(); diff --git a/hphp/runtime/base/hphp_array-defs.h b/hphp/runtime/base/hphp_array-defs.h index 7a2dff48a..594e80321 100644 --- a/hphp/runtime/base/hphp_array-defs.h +++ b/hphp/runtime/base/hphp_array-defs.h @@ -104,7 +104,7 @@ void HphpArray::getArrayElm(ssize_t pos, TypedValue* valOut, } inline HphpArray* HphpArray::asVector(ArrayData* ad) { - assert(ad->kind() == ArrayKind::kVector); + assert(ad->kind() == kVectorKind); assert(dynamic_cast(ad)); auto a = static_cast(ad); assert(a->checkInvariants()); @@ -112,7 +112,7 @@ inline HphpArray* HphpArray::asVector(ArrayData* ad) { } inline const HphpArray* HphpArray::asVector(const ArrayData* ad) { - assert(ad->kind() == ArrayKind::kVector); + assert(ad->kind() == kVectorKind); assert(dynamic_cast(ad)); auto a = static_cast(ad); assert(a->checkInvariants()); @@ -120,7 +120,7 @@ inline const HphpArray* HphpArray::asVector(const ArrayData* ad) { } inline HphpArray* HphpArray::asHphpArray(ArrayData* ad) { - assert(ad->kind() == ArrayKind::kHphpArray); + assert(ad->kind() == kMixedKind); assert(dynamic_cast(ad)); auto a = static_cast(ad); assert(a->checkInvariants()); @@ -128,7 +128,7 @@ inline HphpArray* HphpArray::asHphpArray(ArrayData* ad) { } inline const HphpArray* HphpArray::asHphpArray(const ArrayData* ad) { - assert(ad->kind() == ArrayKind::kHphpArray); + assert(ad->kind() == kMixedKind); assert(dynamic_cast(ad)); auto a = static_cast(ad); assert(a->checkInvariants()); diff --git a/hphp/runtime/base/hphp_array.cpp b/hphp/runtime/base/hphp_array.cpp index 46630ef38..fe31a8a02 100644 --- a/hphp/runtime/base/hphp_array.cpp +++ b/hphp/runtime/base/hphp_array.cpp @@ -105,7 +105,7 @@ static inline uint32_t computeMaskFromNumElms(const uint32_t n) { // Construction/destruction. HphpArray::HphpArray(uint capacity) - : ArrayData(ArrayKind::kVector, AllocationMode::smart, 0) + : ArrayData(kVectorKind, AllocationMode::smart, 0) , m_used(0) { #ifdef PEDANTIC if (size > 0x7fffffffU) { @@ -120,7 +120,7 @@ HphpArray::HphpArray(uint capacity) } HphpArray::HphpArray(uint size, const TypedValue* values) - : ArrayData(ArrayKind::kVector, AllocationMode::smart, size) + : ArrayData(kVectorKind, AllocationMode::smart, size) , m_used(size) { #ifdef PEDANTIC if (size > 0x7fffffffU) { @@ -143,7 +143,7 @@ HphpArray::HphpArray(uint size, const TypedValue* values) } HphpArray::HphpArray(EmptyMode) - : ArrayData(ArrayKind::kVector, AllocationMode::smart, 0) + : ArrayData(kVectorKind, AllocationMode::smart, 0) , m_used(0) , m_tableMask(SmallHashSize - 1) { allocData(SmallSize, SmallHashSize); @@ -261,7 +261,7 @@ HphpArray* HphpArray::vectorToGeneric() { m_hash = hashSize <= sizeof(m_inline_hash) ? m_inline_hash : (ElmInd*)(uintptr_t(m_data) + dataSize); } - m_kind = ArrayKind::kHphpArray; + m_kind = kMixedKind; uint32_t i = 0; auto size = m_size; for (; i < size; ++i) { @@ -316,10 +316,10 @@ bool HphpArray::checkInvariants() const { assert(!isTombstone(m_data[m_used - 1].data.m_type)); } switch (m_kind) { - case ArrayKind::kVector: + case kVectorKind: assert(m_size == m_used); break; - case ArrayKind::kHphpArray: { + case kMixedKind: { assert(m_hash); assert(m_hLoad >= m_size); size_t load = 0; diff --git a/hphp/runtime/base/policy_array.cpp b/hphp/runtime/base/policy_array.cpp index b93531bc9..aaee8374b 100644 --- a/hphp/runtime/base/policy_array.cpp +++ b/hphp/runtime/base/policy_array.cpp @@ -186,7 +186,7 @@ void SimpleArrayStore::prepend(const Variant& v, uint length, IMPLEMENT_SMART_ALLOCATION(PolicyArray) PolicyArray::PolicyArray(uint capacity) - : ArrayData(ArrayKind::kPolicyArray) + : ArrayData(kPolicyKind) , Store(m_allocMode, capacity) { m_size = 0; m_pos = invalid_index; @@ -197,7 +197,7 @@ PolicyArray::PolicyArray(uint capacity) PolicyArray::PolicyArray(const PolicyArray& rhs, uint capacity, AllocationMode am) - : ArrayData(ArrayKind::kPolicyArray, am) + : ArrayData(kPolicyKind, am) , Store(rhs, rhs.m_size, capacity, am, &rhs) { m_size = rhs.m_size; m_pos = rhs.m_pos; @@ -216,13 +216,13 @@ void PolicyArray::Release(ArrayData* ad) { } inline PolicyArray* PolicyArray::asPolicyArray(ArrayData* ad) { - assert(ad->kind() == ArrayKind::kPolicyArray); + assert(ad->kind() == kPolicyKind); assert(dynamic_cast(ad)); return static_cast(ad); } inline const PolicyArray* PolicyArray::asPolicyArray(const ArrayData* ad) { - assert(ad->kind() == ArrayKind::kPolicyArray); + assert(ad->kind() == kPolicyKind); assert(dynamic_cast(ad)); return static_cast(ad); } diff --git a/hphp/runtime/base/shared_map.cpp b/hphp/runtime/base/shared_map.cpp index 6db8fd184..e283a3f35 100644 --- a/hphp/runtime/base/shared_map.cpp +++ b/hphp/runtime/base/shared_map.cpp @@ -62,13 +62,13 @@ void SharedMap::Release(ArrayData* ad) { } inline SharedMap* SharedMap::asSharedMap(ArrayData* ad) { - assert(ad->kind() == ArrayKind::kSharedMap); + assert(ad->kind() == kSharedKind); assert(dynamic_cast(ad)); return static_cast(ad); } inline const SharedMap* SharedMap::asSharedMap(const ArrayData* ad) { - assert(ad->kind() == ArrayKind::kSharedMap); + assert(ad->kind() == kSharedKind); assert(dynamic_cast(ad)); return static_cast(ad); } diff --git a/hphp/runtime/base/shared_map.h b/hphp/runtime/base/shared_map.h index 151078a7c..b7186d3e8 100644 --- a/hphp/runtime/base/shared_map.h +++ b/hphp/runtime/base/shared_map.h @@ -33,7 +33,7 @@ namespace HPHP { class SharedMap : public ArrayData { public: explicit SharedMap(SharedVariant* source) - : ArrayData(ArrayKind::kSharedMap) + : ArrayData(kSharedKind) , m_localCache(nullptr) { m_map = source->getMap(); m_isVector = source->getIsVector(); diff --git a/hphp/runtime/vm/name_value_table_wrapper.cpp b/hphp/runtime/vm/name_value_table_wrapper.cpp index acd0259db..914a52067 100644 --- a/hphp/runtime/vm/name_value_table_wrapper.cpp +++ b/hphp/runtime/vm/name_value_table_wrapper.cpp @@ -24,14 +24,14 @@ namespace HPHP { ////////////////////////////////////////////////////////////////////// inline NameValueTableWrapper* NameValueTableWrapper::asNVTW(ArrayData* ad) { - assert(ad->kind() == ArrayKind::kNameValueTableWrapper); + assert(ad->kind() == kNvtwKind); assert(dynamic_cast(ad)); return static_cast(ad); } inline const NameValueTableWrapper* NameValueTableWrapper::asNVTW(const ArrayData* ad) { - assert(ad->kind() == ArrayKind::kNameValueTableWrapper); + assert(ad->kind() == kNvtwKind); assert(dynamic_cast(ad)); return static_cast(ad); } diff --git a/hphp/runtime/vm/name_value_table_wrapper.h b/hphp/runtime/vm/name_value_table_wrapper.h index edc2e7e89..b67d78a43 100644 --- a/hphp/runtime/vm/name_value_table_wrapper.h +++ b/hphp/runtime/vm/name_value_table_wrapper.h @@ -54,7 +54,7 @@ namespace HPHP { */ struct NameValueTableWrapper : public ArrayData { explicit NameValueTableWrapper(NameValueTable* tab) - : ArrayData(ArrayKind::kNameValueTableWrapper) + : ArrayData(kNvtwKind) , m_tab(tab) { }