diff --git a/hphp/runtime/base/array-data.h b/hphp/runtime/base/array-data.h index 9aa7af2c7..737d4cb31 100644 --- a/hphp/runtime/base/array-data.h +++ b/hphp/runtime/base/array-data.h @@ -51,9 +51,9 @@ class ArrayData { kNumKinds // insert new values before kNumKinds. }; -public: static const ssize_t invalid_index = -1; + protected: explicit ArrayData(ArrayKind kind) : m_kind(kind) , m_allocMode(AllocationMode::smart) @@ -89,9 +89,7 @@ public: , m_count(0) , m_strongIterators(nullptr) {} - - static HphpArray* Make(uint capacity); - static HphpArray* Make(uint size, const TypedValue*); + void setRefCount(RefCount n) { m_count = n; } void destroy() { // If there are any strong iterators pointing to this array, they need @@ -101,6 +99,7 @@ public: ~ArrayData() { destroy(); } +public: IMPLEMENT_COUNTABLE_METHODS /** @@ -112,6 +111,10 @@ public: static ArrayData *CreateRef(CVarRef value); static ArrayData *CreateRef(CVarRef name, CVarRef value); + static HphpArray* Make(uint capacity); + static HphpArray* MakeReserve(uint capacity); + static HphpArray* MakeTuple(uint size, const TypedValue*); + /** * Type conversion functions. All other types are handled inside Array class. */ diff --git a/hphp/runtime/base/hphp-array.cpp b/hphp/runtime/base/hphp-array.cpp index 512598815..487891146 100644 --- a/hphp/runtime/base/hphp-array.cpp +++ b/hphp/runtime/base/hphp-array.cpp @@ -1775,5 +1775,23 @@ NEVER_INLINE HphpArray* HphpArray::copyGeneric() const { HphpArray(*this, AllocationMode::smart, CopyGeneric()); } +//============================================================================= + +HOT_FUNC_VM +HphpArray* ArrayData::MakeTuple(uint size, const TypedValue* data) { + auto a = NEW(HphpArray)(size, data); + a->setRefCount(1); + TRACE(2, "MakeTuple: size %d\n", size); + return a; +} + +HOT_FUNC_VM +HphpArray* ArrayData::MakeReserve(uint capacity) { + auto a = NEW(HphpArray)(capacity); + a->setRefCount(1); + TRACE(2, "MakeReserve: capacity %d\n", capacity); + return a; +} + /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/runtime/base/hphp-array.h b/hphp/runtime/base/hphp-array.h index e3eb82d6d..b09b3f5dc 100644 --- a/hphp/runtime/base/hphp-array.h +++ b/hphp/runtime/base/hphp-array.h @@ -520,17 +520,12 @@ public: }; //============================================================================= - // inline for performance reasons inline HphpArray* ArrayData::Make(uint capacity) { return NEW(HphpArray)(capacity); } -inline HphpArray* ArrayData::Make(uint size, const TypedValue* data) { - return NEW(HphpArray)(size, data); -} - // HphpArray has more than one kind, so reuse ArrayData's virtual dispatch. inline void HphpArray::release() { ArrayData::release(); diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 94060de88..412c3e5a2 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -3424,18 +3424,17 @@ inline void OPTBLD_INLINE VMExecutionContext::iopArray(PC& pc) { inline void OPTBLD_INLINE VMExecutionContext::iopNewArray(PC& pc) { NEXT(); - // Clever sizing avoids extra work in HphpArray construction. - auto arr = ArrayData::Make(size_t(3U) << (HphpArray::MinLgTableSize-2)); - m_stack.pushArray(arr); + auto arr = ArrayData::MakeReserve(HphpArray::SmallSize); + m_stack.pushArrayNoRc(arr); } inline void OPTBLD_INLINE VMExecutionContext::iopNewTuple(PC& pc) { NEXT(); DECODE_IVA(n); // This constructor moves values, no inc/decref is necessary. - HphpArray* arr = ArrayData::Make(n, m_stack.topC()); + auto* a = HphpArray::MakeTuple(n, m_stack.topC()); m_stack.ndiscard(n); - m_stack.pushArray(arr); + m_stack.pushArrayNoRc(a); } inline void OPTBLD_INLINE VMExecutionContext::iopAddElemC(PC& pc) { diff --git a/hphp/runtime/vm/jit/hhbc-translator.cpp b/hphp/runtime/vm/jit/hhbc-translator.cpp index d2f846ff8..21d457593 100755 --- a/hphp/runtime/vm/jit/hhbc-translator.cpp +++ b/hphp/runtime/vm/jit/hhbc-translator.cpp @@ -474,7 +474,7 @@ void HhbcTranslator::emitNewArray(int capacity) { } void HhbcTranslator::emitNewTuple(int numArgs) { - // The new_tuple helper function needs array values passed to it + // The NewTuple opcode's helper needs array values passed to it // via the stack. We use spillStack() to flush the eval stack and // obtain a pointer to the topmost item; if over-flushing becomes // a problem then we should refactor the NewTuple opcode to take diff --git a/hphp/runtime/vm/jit/native-calls.cpp b/hphp/runtime/vm/jit/native-calls.cpp index 99e1a797b..d893c1d08 100644 --- a/hphp/runtime/vm/jit/native-calls.cpp +++ b/hphp/runtime/vm/jit/native-calls.cpp @@ -172,8 +172,8 @@ static CallMap s_callMap { {{SSA, 0}, {TV, 1}}}, {ArrayAdd, array_add, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {Box, box_value, DSSA, SNone, {{TV, 0}}}, - {NewArray, new_array, DSSA, SNone, {{SSA, 0}}}, - {NewTuple, new_tuple, DSSA, SNone, + {NewArray, ArrayData::MakeReserve, DSSA, SNone, {{SSA, 0}}}, + {NewTuple, ArrayData::MakeTuple, DSSA, SNone, {{SSA, 0}, {SSA, 1}}}, {AllocObj, newInstance, DSSA, SSync, {{SSA, 0}}}, diff --git a/hphp/runtime/vm/runtime.cpp b/hphp/runtime/vm/runtime.cpp index 3b76670c1..f7295de45 100644 --- a/hphp/runtime/vm/runtime.cpp +++ b/hphp/runtime/vm/runtime.cpp @@ -61,21 +61,6 @@ void print_boolean(bool val) { } } -HOT_FUNC_VM -ArrayData* new_array(int capacity) { - ArrayData *a = ArrayData::Make(capacity); - a->incRefCount(); - TRACE(2, "newArrayHelper: capacity %d\n", capacity); - return a; -} - -ArrayData* new_tuple(int n, const TypedValue* values) { - auto a = ArrayData::Make(n, values); - a->incRefCount(); - TRACE(2, "new_tuple: size %d\n", n); - return a; -} - #define NEW_COLLECTION_HELPER(name) \ ObjectData* \ new##name##Helper(int nElms) { \ diff --git a/hphp/runtime/vm/runtime.h b/hphp/runtime/vm/runtime.h index fbd8a66ab..088a05856 100644 --- a/hphp/runtime/vm/runtime.h +++ b/hphp/runtime/vm/runtime.h @@ -27,9 +27,6 @@ namespace HPHP { struct HhbcExtFuncInfo; struct HhbcExtClassInfo; -ArrayData* new_array(int capacity); -ArrayData* new_tuple(int numArgs, const TypedValue* args); - ObjectData* newVectorHelper(int nElms); ObjectData* newMapHelper(int nElms); ObjectData* newStableMapHelper(int nElms);