diff --git a/hphp/runtime/base/tv_helpers.cpp b/hphp/runtime/base/tv_helpers.cpp index 6440715a8..c71ff622a 100644 --- a/hphp/runtime/base/tv_helpers.cpp +++ b/hphp/runtime/base/tv_helpers.cpp @@ -205,5 +205,35 @@ void tvCastToObjectInPlace(TypedValue* tv) { tv->m_data.pobj->incRefCount(); } +bool tvIsPlausible(const TypedValue* tv) { + if (!tv) return false; + auto okPtr = [](void* ptr) { + return ptr && (uintptr_t(ptr) % sizeof(ptr) == 0); + }; + switch (tv->m_type) { + case KindOfUninit: + case KindOfNull: + return true; + case KindOfBoolean: + return tv->m_data.num == 0 || tv->m_data.num == 1; + case KindOfInt64: + case KindOfDouble: + return true; + case KindOfStaticString: + return okPtr(tv->m_data.pstr) && tv->m_data.pstr->isStatic(); + case KindOfString: + case KindOfArray: + return okPtr(tv->m_data.parr) && + is_refcount_realistic(tv->m_data.parr->getCount()); + case KindOfObject: + return okPtr(tv->m_data.pobj) && !tv->m_data.pobj->isStatic(); + case KindOfRef: + return okPtr(tv->m_data.pref) && + tv->m_data.pref->tv()->m_type != KindOfRef; + default: + return false; + } +} + /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/runtime/base/tv_helpers.h b/hphp/runtime/base/tv_helpers.h index e9b8f52d6..fdccdb64a 100644 --- a/hphp/runtime/base/tv_helpers.h +++ b/hphp/runtime/base/tv_helpers.h @@ -48,13 +48,7 @@ inline TypedValue tv(DataType type, Data data) { // Assumes 'IS_REFCOUNTED_TYPE(type)' void tvDecRefHelper(DataType type, uint64_t datum); -inline bool tvIsPlausibleType(DataType type) { - return type >= MinDataType && type < MaxNumDataTypes; -} - -inline bool tvIsPlausible(const TypedValue* tv) { - return tvIsPlausibleType(tv->m_type); -} +bool tvIsPlausible(const TypedValue* tv); inline bool tvWillBeReleased(TypedValue* tv) { return IS_REFCOUNTED_TYPE(tv->m_type) && diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 43bdc74cc..5c29060a3 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -4638,7 +4638,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopCGetG(PC& pc) { } else { \ tvReadCell(val, output); \ } \ - m_stack.popC(); \ + m_stack.popA(); \ SPROP_OP_POSTLUDE \ } while (0) @@ -4769,7 +4769,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopIssetS(PC& pc) { } else { e = isset(tvAsCVarRef(val)); } - m_stack.popC(); + m_stack.popA(); output->m_data.num = e; output->m_type = KindOfBoolean; SPROP_OP_POSTLUDE @@ -4898,7 +4898,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopEmptyS(PC& pc) { } else { e = empty(tvAsCVarRef(val)); } - m_stack.popC(); + m_stack.popA(); output->m_data.num = e; output->m_type = KindOfBoolean; SPROP_OP_POSTLUDE diff --git a/hphp/runtime/vm/bytecode.h b/hphp/runtime/vm/bytecode.h index 9f0f3181a..aa9ff11f1 100644 --- a/hphp/runtime/vm/bytecode.h +++ b/hphp/runtime/vm/bytecode.h @@ -543,6 +543,12 @@ public: m_top++; } + inline void ALWAYS_INLINE popA() { + assert(m_top != m_base); + assert(m_top->m_type == KindOfClass); + m_top++; + } + inline void ALWAYS_INLINE popV() { assert(m_top != m_base); assert(m_top->m_type == KindOfRef); @@ -553,7 +559,7 @@ public: inline void ALWAYS_INLINE popTV() { assert(m_top != m_base); - assert(tvIsPlausible(m_top)); + assert(m_top->m_type == KindOfClass || tvIsPlausible(m_top)); tvRefcountedDecRef(m_top); m_top++; } @@ -704,7 +710,7 @@ public: pushObjectNoRc(o); o->incRefCount(); } - + inline void ALWAYS_INLINE nalloc(size_t n) { assert((uintptr_t)&m_top[-n] <= (uintptr_t)m_base); m_top -= n;