diff --git a/hphp/runtime/base/array/array_data.cpp b/hphp/runtime/base/array/array_data.cpp index cbf1591b1..e31f81893 100644 --- a/hphp/runtime/base/array/array_data.cpp +++ b/hphp/runtime/base/array/array_data.cpp @@ -13,8 +13,11 @@ | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ - #include "hphp/runtime/base/array/array_data.h" + +#include "tbb/concurrent_hash_map.h" + +#include "hphp/util/exception.h" #include "hphp/runtime/base/array/array_init.h" #include "hphp/runtime/base/array/array_iterator.h" #include "hphp/runtime/base/type_conversions.h" @@ -24,9 +27,8 @@ #include "hphp/runtime/base/runtime_option.h" #include "hphp/runtime/base/macros.h" #include "hphp/runtime/base/shared/shared_map.h" -#include "hphp/util/exception.h" -#include "tbb/concurrent_hash_map.h" #include "hphp/runtime/base/array/policy_array.h" +#include "hphp/runtime/base/comparisons.h" namespace HPHP { /////////////////////////////////////////////////////////////////////////////// @@ -175,8 +177,8 @@ bool ArrayData::equal(const ArrayData *v2, bool strict) const { if (strict) { for (ArrayIter iter1(this), iter2(v2); iter1; ++iter1, ++iter2) { assert(iter2); - if (!iter1.first().same(iter2.first()) - || !iter1.second().same(iter2.secondRef())) return false; + if (!same(iter1.first(), iter2.first()) + || !same(iter1.second(), iter2.secondRef())) return false; } } else { for (ArrayIter iter(this); iter; ++iter) { diff --git a/hphp/runtime/base/array/array_data.h b/hphp/runtime/base/array/array_data.h index aa7c8da75..a1915bbf4 100644 --- a/hphp/runtime/base/array/array_data.h +++ b/hphp/runtime/base/array/array_data.h @@ -443,7 +443,7 @@ public: virtual void dump(std::ostream &os); /** - * Comparisons. Similar to serialize(), we implemented it here generically. + * Comparisons. */ int compare(const ArrayData *v2) const; bool equal(const ArrayData *v2, bool strict) const; diff --git a/hphp/runtime/base/comparisons.h b/hphp/runtime/base/comparisons.h index cb615264b..3be48bdec 100644 --- a/hphp/runtime/base/comparisons.h +++ b/hphp/runtime/base/comparisons.h @@ -20,6 +20,7 @@ #include "hphp/runtime/base/type_conversions.h" #include "hphp/runtime/base/builtin_functions.h" #include "hphp/runtime/base/complex_types.h" +#include "hphp/runtime/base/tv_comparisons.h" namespace HPHP { /////////////////////////////////////////////////////////////////////////////// @@ -34,7 +35,9 @@ bool same(CVarRef v1, CStrRef v2); bool same(CVarRef v1, litstr v2); bool same(CVarRef v1, CArrRef v2); bool same(CVarRef v1, CObjRef v2); -inline bool same(CVarRef v1, CVarRef v2) { return v1.same(v2); } +inline bool same(CVarRef v1, CVarRef v2) { + return tvSame(v1.asTypedValue(), v2.asTypedValue()); +} inline bool equal(CVarRef v1, bool v2) { return v1.equal(v2);} inline bool equal(CVarRef v1, int v2) { return v1.equal(v2);} diff --git a/hphp/runtime/base/hphp_value.h b/hphp/runtime/base/hphp_value.h index 033f6e616..05533112f 100644 --- a/hphp/runtime/base/hphp_value.h +++ b/hphp/runtime/base/hphp_value.h @@ -42,7 +42,7 @@ union Value { StringData *pstr; // KindOfString, KindOfStaticString ArrayData *parr; // KindOfArray ObjectData *pobj; // KindOfObject - Class *pcls; // only in vm stack, no type tag. + Class *pcls; // only in vm stack, no type tag. RefData *pref; // KindOfRef TypedValue *pind; // only for KindOfIndirect }; diff --git a/hphp/runtime/base/tv_comparisons.cpp b/hphp/runtime/base/tv_comparisons.cpp new file mode 100644 index 000000000..750c1d045 --- /dev/null +++ b/hphp/runtime/base/tv_comparisons.cpp @@ -0,0 +1,65 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ +#include "hphp/runtime/base/tv_comparisons.h" + +#include "hphp/runtime/base/complex_types.h" +#include "hphp/runtime/base/comparisons.h" + +namespace HPHP { + +////////////////////////////////////////////////////////////////////// + +bool tvSame(const TypedValue* tv1, const TypedValue* tv2) { + bool const null1 = IS_NULL_TYPE(tv1->m_type); + bool const null2 = IS_NULL_TYPE(tv2->m_type); + if (null1 && null2) return true; + if (null1 || null2) return false; + + if (tv1->m_type == KindOfRef) tv1 = tv1->m_data.pref->tv(); + if (tv2->m_type == KindOfRef) tv2 = tv2->m_data.pref->tv(); + + switch (tv1->m_type) { + case KindOfInt64: + case KindOfBoolean: + if (tv2->m_type != tv1->m_type) return false; + return tv1->m_data.num == tv2->m_data.num; + case KindOfDouble: + if (tv2->m_type != tv1->m_type) return false; + return tv1->m_data.dbl == tv2->m_data.dbl; + + case KindOfStaticString: + case KindOfString: + if (!IS_STRING_TYPE(tv2->m_type)) return false; + return tv1->m_data.pstr->same(tv2->m_data.pstr); + + case KindOfArray: + if (tv2->m_type != KindOfArray) return false; + return tv1->m_data.parr->equal(tv2->m_data.parr, true); + + case KindOfObject: + return tv2->m_type == KindOfObject && + tv1->m_data.pobj == tv2->m_data.pobj; + + default: + break; + } + not_reached(); +} + +////////////////////////////////////////////////////////////////////// + +} + diff --git a/hphp/runtime/base/tv_comparisons.h b/hphp/runtime/base/tv_comparisons.h new file mode 100644 index 000000000..4f6e6874c --- /dev/null +++ b/hphp/runtime/base/tv_comparisons.h @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ +#ifndef incl_HPHP_TV_COMPARISONS_H_ +#define incl_HPHP_TV_COMPARISONS_H_ + +namespace HPHP { + +////////////////////////////////////////////////////////////////////// + +struct TypedValue; + +////////////////////////////////////////////////////////////////////// + +/* + * Returns whether two TypedValues have the same value, in sense of + * php's === operator. + */ +bool tvSame(const TypedValue*, const TypedValue*); + +////////////////////////////////////////////////////////////////////// + +} + +#endif diff --git a/hphp/runtime/base/tv_helpers.h b/hphp/runtime/base/tv_helpers.h index 915aeb451..101c0c218 100644 --- a/hphp/runtime/base/tv_helpers.h +++ b/hphp/runtime/base/tv_helpers.h @@ -420,13 +420,6 @@ inline bool tvIsStronglyBound(const TypedValue* tv) { return (tv->m_type == KindOfRef && tv->m_data.pref->_count > 1); } -inline bool tvSame(const TypedValue* tv1, const TypedValue* tv2) { - if (tv1->m_type == KindOfUninit || tv2->m_type == KindOfUninit) { - return tv1->m_type == tv2->m_type; - } - return tvAsCVarRef(tv1).same(tvAsCVarRef(tv2)); -} - // Assumes 'fr' is live and 'to' is dead, and does not mutate to->_count inline void tvDupFlattenVars(const TypedValue* fr, TypedValue* to, const ArrayData* container) { diff --git a/hphp/runtime/base/type_array.cpp b/hphp/runtime/base/type_array.cpp index 2c50d7cb8..6c20d4be6 100644 --- a/hphp/runtime/base/type_array.cpp +++ b/hphp/runtime/base/type_array.cpp @@ -644,7 +644,7 @@ Variant &Array::addLval(CVarRef key, bool isKey /* = false */) { bool Array::valueExists(CVarRef search_value, bool strict /* = false */) const { for (ArrayIter iter(*this); iter; ++iter) { - if ((strict && iter.secondRef().same(search_value)) || + if ((strict && HPHP::same(iter.secondRef(), search_value)) || (!strict && iter.secondRef().equal(search_value))) { return true; } @@ -654,7 +654,7 @@ bool Array::valueExists(CVarRef search_value, Variant Array::key(CVarRef search_value, bool strict /* = false */) const { for (ArrayIter iter(*this); iter; ++iter) { - if ((strict && iter.secondRef().same(search_value)) || + if ((strict && HPHP::same(iter.secondRef(), search_value)) || (!strict && iter.secondRef().equal(search_value))) { return iter.first(); } @@ -673,7 +673,7 @@ Array Array::keys(CVarRef search_value /* = null_variant */, } else { Array ret = Array::Create(); for (ArrayIter iter(*this); iter; ++iter) { - if ((strict && iter.secondRef().same(search_value)) || + if ((strict && HPHP::same(iter.secondRef(), search_value)) || (!strict && iter.secondRef().equal(search_value))) { ret.append(iter.first()); } diff --git a/hphp/runtime/base/type_variant.cpp b/hphp/runtime/base/type_variant.cpp index e6fd704b9..fffef7e71 100644 --- a/hphp/runtime/base/type_variant.cpp +++ b/hphp/runtime/base/type_variant.cpp @@ -1542,51 +1542,6 @@ Variant::operator Object() const { return toObject(); } -/////////////////////////////////////////////////////////////////////////////// -// comparisons - -bool Variant::same(CVarRef v2) const { - bool null1 = isNull(); - bool null2 = v2.isNull(); - if (null1 && null2) return true; - if (null1 || null2) return false; - - TypedValueAccessor acc = getTypedAccessor(); - switch (GetAccessorType(acc)) { - case KindOfInt64: { - TypedValueAccessor acc2 = v2.getTypedAccessor(); - switch (GetAccessorType(acc2)) { - case KindOfInt64: - return HPHP::equal(GetInt64(acc), GetInt64(acc2)); - default: - break; - } - break; - } - case KindOfStaticString: - case KindOfString: { - TypedValueAccessor acc2 = v2.getTypedAccessor(); - switch (GetAccessorType(acc2)) { - case KindOfStaticString: - case KindOfString: - return GetStringData(acc)->same(v2.GetStringData(acc2)); - default: - return false; - } - } - case KindOfArray: - if (v2.is(KindOfArray)) { - return Array(getArrayData()).same(Array(v2.getArrayData())); - } - break; - case KindOfObject: - return v2.is(KindOfObject) && getObjectData() == v2.getObjectData(); - default: - break; - } - return getType() == v2.getType() && equal(v2); -} - /////////////////////////////////////////////////////////////////////////////// #define UNWRAP(reverse) \ diff --git a/hphp/runtime/base/type_variant.h b/hphp/runtime/base/type_variant.h index 466d83309..f0e6e9f8d 100644 --- a/hphp/runtime/base/type_variant.h +++ b/hphp/runtime/base/type_variant.h @@ -694,19 +694,9 @@ class Variant : private TypedValue { return ObjNR(getObjectData()); } - /** + /* * Comparisons */ - bool same(bool v2) const = delete; - bool same(int v2) const = delete; - bool same(int64_t v2) const = delete; - bool same(double v2) const = delete; - bool same(litstr v2) const = delete; - bool same(const StringData *v2) const = delete; - bool same(CStrRef v2) const = delete; - bool same(CArrRef v2) const = delete; - bool same(CObjRef v2) const = delete; - bool same(CVarRef v2) const; bool equal(bool v2) const; bool equal(int v2) const; diff --git a/hphp/runtime/ext/ext_collections.cpp b/hphp/runtime/ext/ext_collections.cpp index 077b35437..417bf7fdf 100644 --- a/hphp/runtime/ext/ext_collections.cpp +++ b/hphp/runtime/ext/ext_collections.cpp @@ -485,7 +485,7 @@ void c_Vector::t_splice(CVarRef offset, CVarRef len /* = null */, int64_t c_Vector::t_linearsearch(CVarRef search_value) { uint sz = m_size; for (uint i = 0; i < sz; ++i) { - if (search_value.same(tvAsCVarRef(&m_data[i]))) { + if (same(search_value, tvAsCVarRef(&m_data[i]))) { return i; } } diff --git a/hphp/test/ext/test_base.cpp b/hphp/test/ext/test_base.cpp index be9bfb78c..2c0490a9a 100644 --- a/hphp/test/ext/test_base.cpp +++ b/hphp/test/ext/test_base.cpp @@ -51,7 +51,7 @@ bool TestBase::CountSkip() { bool TestBase::VerifySame(const char *exp1, const char *exp2, CVarRef v1, CVarRef v2) { - if (!v1.same(v2)) { + if (!same(v1, v2)) { g_context->obEndAll(); printf("%s = \n", exp1); f_var_dump(v1); printf("%s = \n", exp2); f_var_dump(v2);