Move bytecode.cpp use of comparisons to tv_comparisons functions
Instead of calling into the comparisons.h stuff, call into the cell/tv functions. This meant moving more_or_equal and less_or_equal to tv_comparisons and moving cellToBool out of its unnamed namespace. Also replaces the global tv() function with some make_tv() and make_value() thing---it looked like it was incorrect for doubles, and since the correct compile-time type for the unconstrained template parameter essentially depended on the runtime value of the first parameter it seemed more reasonable to move that to compile-time, too.
Esse commit está contido em:
@@ -543,11 +543,11 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
|
||||
case '<':
|
||||
result = less(v1, v2); break;
|
||||
case T_IS_SMALLER_OR_EQUAL:
|
||||
result = less_or_equal(v1, v2); break;
|
||||
result = cellLessOrEqual(v1.asCell(), v2.asCell()); break;
|
||||
case '>':
|
||||
result = more(v1, v2); break;
|
||||
case T_IS_GREATER_OR_EQUAL:
|
||||
result = more_or_equal(v1, v2); break;
|
||||
result = cellGreaterOrEqual(v1.asCell(), v2.asCell()); break;
|
||||
case '+':
|
||||
result = plus(v1, v2); break;
|
||||
case '-':
|
||||
|
||||
@@ -85,38 +85,6 @@ bool same(CVarRef v1, CObjRef v2) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool less_or_equal(CVarRef v1, CVarRef v2) {
|
||||
// To be PHP-compatible, when comparing two arrays or two objects we
|
||||
// cannot assume that "($x <= $y)" is equivalent to "!($x > $y)".
|
||||
if (v1.is(KindOfArray) && v2.is(KindOfArray)) {
|
||||
Array a1 = v1.toArray();
|
||||
Array a2 = v2.toArray();
|
||||
return a1.less(a2) || a1.equal(a2);
|
||||
}
|
||||
if (v1.is(KindOfObject) && v2.is(KindOfObject)) {
|
||||
Object o1 = v1.toObject();
|
||||
Object o2 = v2.toObject();
|
||||
return o1.less(o2) || o1.equal(o2);
|
||||
}
|
||||
return !more(v1, v2);
|
||||
}
|
||||
|
||||
bool more_or_equal(CVarRef v1, CVarRef v2) {
|
||||
// To be PHP-compatible, when comparing two arrays or two objects we
|
||||
// cannot assume that "($x >= $y)" is equivalent to "!($x < $y)".
|
||||
if (v1.is(KindOfArray) && v2.is(KindOfArray)) {
|
||||
Array a1 = v1.toArray();
|
||||
Array a2 = v2.toArray();
|
||||
return a1.more(a2) || a1.equal(a2);
|
||||
}
|
||||
if (v1.is(KindOfObject) && v2.is(KindOfObject)) {
|
||||
Object o1 = v1.toObject();
|
||||
Object o2 = v2.toObject();
|
||||
return o1.more(o2) || o1.equal(o2);
|
||||
}
|
||||
return !less(v1, v2);
|
||||
}
|
||||
|
||||
bool equal(int v1, const StringData *v2) {
|
||||
return equal((int64_t)v1, v2);
|
||||
}
|
||||
|
||||
@@ -687,15 +687,6 @@ inline bool more(CObjRef v1, CArrRef v2) { return less(v2, v1);}
|
||||
inline bool more(CObjRef v1, CObjRef v2) { return v1.more(v2);}
|
||||
inline bool more(CObjRef v1, CVarRef v2) { return less(v2, v1);}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Special-casing comparisons between arrays to get the same results from
|
||||
* comparisons between uncomparable arrays.
|
||||
*/
|
||||
bool less_or_equal(CVarRef v1, CVarRef v2);
|
||||
|
||||
bool more_or_equal(CVarRef v1, CVarRef v2);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
@@ -483,6 +483,7 @@ private:
|
||||
template <unsigned mdepth>
|
||||
void setHelperPost(unsigned ndiscard, Variant& tvRef,
|
||||
Variant& tvRef2);
|
||||
template<class Op> void implCellBinOpBool(PC&, Op op);
|
||||
bool cellInstanceOf(TypedValue* c, const HPHP::NamedEntity* s);
|
||||
bool initIterator(PC& pc, PC& origPc, Iter* it,
|
||||
Offset offset, Cell* c1);
|
||||
|
||||
@@ -13,21 +13,22 @@
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
#ifndef incl_HPHP_HPHPVALUE_H_
|
||||
#define incl_HPHP_HPHPVALUE_H_
|
||||
|
||||
#ifndef incl_HPHP_INSIDE_HPHP_COMPLEX_TYPES_H_
|
||||
#error Directly including 'hphp_value.h' is prohibited. \
|
||||
Include 'complex_types.h' instead.
|
||||
#endif
|
||||
|
||||
#ifndef incl_HPHP_HPHPVALUE_H_
|
||||
#define incl_HPHP_HPHPVALUE_H_
|
||||
#include <type_traits>
|
||||
|
||||
#include "hphp/runtime/base/types.h"
|
||||
|
||||
namespace HPHP {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Class;
|
||||
class Class;
|
||||
|
||||
struct TypedValue;
|
||||
|
||||
@@ -138,6 +139,72 @@ private:
|
||||
typedef TypedValue Cell;
|
||||
typedef TypedValue Var;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* make_value and make_tv are helpers for creating TypedValues and
|
||||
* Values as temporaries, without messing up the conversions.
|
||||
*/
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<
|
||||
std::is_integral<T>::value,
|
||||
Value
|
||||
>::type make_value(T t) { Value v; v.num = t; return v; }
|
||||
|
||||
template<class T>
|
||||
typename std::enable_if<
|
||||
std::is_pointer<T>::value,
|
||||
Value
|
||||
>::type make_value(T t) {
|
||||
Value v;
|
||||
v.num = reinterpret_cast<int64_t>(t);
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value make_value(double d) { Value v; v.dbl = d; return v; }
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<DataType> struct DataTypeCPPType;
|
||||
#define X(dt, cpp) \
|
||||
template<> struct DataTypeCPPType<dt> { typedef cpp type; }
|
||||
|
||||
X(KindOfNull, void);
|
||||
X(KindOfBoolean, bool);
|
||||
X(KindOfInt64, int64_t);
|
||||
X(KindOfDouble, double);
|
||||
X(KindOfArray, ArrayData*);
|
||||
X(KindOfObject, ObjectData*);
|
||||
X(KindOfRef, RefData*);
|
||||
X(KindOfString, StringData*);
|
||||
X(KindOfStaticString, StringData*);
|
||||
|
||||
#undef X
|
||||
|
||||
}
|
||||
|
||||
template<DataType DType>
|
||||
typename std::enable_if<
|
||||
!std::is_same<typename detail::DataTypeCPPType<DType>::type,void>::value,
|
||||
TypedValue
|
||||
>::type make_tv(typename detail::DataTypeCPPType<DType>::type val) {
|
||||
TypedValue ret;
|
||||
ret.m_data = make_value(val);
|
||||
ret.m_type = DType;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<DataType DType>
|
||||
typename std::enable_if<
|
||||
std::is_same<typename detail::DataTypeCPPType<DType>::type,void>::value,
|
||||
TypedValue
|
||||
>::type make_tv() {
|
||||
TypedValue ret;
|
||||
ret.m_type = DType;
|
||||
return ret;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
@@ -32,28 +32,6 @@ namespace {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool cellToBool(const Cell* cell) {
|
||||
assert(tvIsPlausible(cell));
|
||||
assert(cell->m_type != KindOfRef);
|
||||
|
||||
switch (cell->m_type) {
|
||||
case KindOfUninit:
|
||||
case KindOfNull: return false;
|
||||
case KindOfInt64: return cell->m_data.num != 0;
|
||||
case KindOfBoolean: return cell->m_data.num;
|
||||
case KindOfDouble: return cell->m_data.dbl != 0;
|
||||
case KindOfStaticString:
|
||||
case KindOfString: return cell->m_data.pstr->toBoolean();
|
||||
case KindOfArray: return !cell->m_data.parr->empty();
|
||||
case KindOfObject: // TODO: should handle o_toBoolean?
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
not_reached();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Family of relative op functions.
|
||||
*
|
||||
@@ -247,31 +225,36 @@ bool cellRelOp(Op op, const Cell* cell, const ObjectData* od) {
|
||||
}
|
||||
|
||||
template<class Op>
|
||||
bool tvRelOp(Op op, const TypedValue* tv1, const TypedValue* tv2) {
|
||||
assert(tvIsPlausible(tv1));
|
||||
assert(tvIsPlausible(tv2));
|
||||
tv1 = tvToCell(tv1);
|
||||
tv2 = tvToCell(tv2);
|
||||
bool cellRelOp(Op op, const Cell* c1, const Cell* c2) {
|
||||
assert(c1->m_type != KindOfRef);
|
||||
assert(c2->m_type != KindOfRef);
|
||||
|
||||
switch (tv2->m_type) {
|
||||
switch (c2->m_type) {
|
||||
case KindOfUninit:
|
||||
case KindOfNull:
|
||||
return IS_STRING_TYPE(tv1->m_type)
|
||||
? op(tv1->m_data.pstr, empty_string.get())
|
||||
: cellRelOp(op, tv1, false);
|
||||
case KindOfInt64: return cellRelOp(op, tv1, tv2->m_data.num);
|
||||
case KindOfBoolean: return cellRelOp(op, tv1, !!tv2->m_data.num);
|
||||
case KindOfDouble: return cellRelOp(op, tv1, tv2->m_data.dbl);
|
||||
return IS_STRING_TYPE(c1->m_type)
|
||||
? op(c1->m_data.pstr, empty_string.get())
|
||||
: cellRelOp(op, c1, false);
|
||||
case KindOfInt64: return cellRelOp(op, c1, c2->m_data.num);
|
||||
case KindOfBoolean: return cellRelOp(op, c1, !!c2->m_data.num);
|
||||
case KindOfDouble: return cellRelOp(op, c1, c2->m_data.dbl);
|
||||
case KindOfStaticString:
|
||||
case KindOfString: return cellRelOp(op, tv1, tv2->m_data.pstr);
|
||||
case KindOfArray: return cellRelOp(op, tv1, tv2->m_data.parr);
|
||||
case KindOfObject: return cellRelOp(op, tv1, tv2->m_data.pobj);
|
||||
case KindOfString: return cellRelOp(op, c1, c2->m_data.pstr);
|
||||
case KindOfArray: return cellRelOp(op, c1, c2->m_data.parr);
|
||||
case KindOfObject: return cellRelOp(op, c1, c2->m_data.pobj);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
not_reached();
|
||||
}
|
||||
|
||||
template<class Op>
|
||||
bool tvRelOp(Op op, const TypedValue* tv1, const TypedValue* tv2) {
|
||||
assert(tvIsPlausible(tv1));
|
||||
assert(tvIsPlausible(tv2));
|
||||
return cellRelOp(op, tvToCell(tv1), tvToCell(tv2));
|
||||
}
|
||||
|
||||
/*
|
||||
* These relative ops helper function objects define operator() for
|
||||
* each primitive type, and for the case of a complex type being
|
||||
@@ -387,39 +370,36 @@ struct Gt {
|
||||
|
||||
}
|
||||
|
||||
bool tvSame(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
assert(tvIsPlausible(tv1));
|
||||
assert(tvIsPlausible(tv2));
|
||||
bool cellSame(const Cell* c1, const Cell* c2) {
|
||||
assert(c1->m_type != KindOfRef);
|
||||
assert(c2->m_type != KindOfRef);
|
||||
|
||||
tv1 = tvToCell(tv1);
|
||||
tv2 = tvToCell(tv2);
|
||||
|
||||
bool const null1 = IS_NULL_TYPE(tv1->m_type);
|
||||
bool const null2 = IS_NULL_TYPE(tv2->m_type);
|
||||
bool const null1 = IS_NULL_TYPE(c1->m_type);
|
||||
bool const null2 = IS_NULL_TYPE(c2->m_type);
|
||||
if (null1 && null2) return true;
|
||||
if (null1 || null2) return false;
|
||||
|
||||
switch (tv1->m_type) {
|
||||
switch (c1->m_type) {
|
||||
case KindOfInt64:
|
||||
case KindOfBoolean:
|
||||
if (tv2->m_type != tv1->m_type) return false;
|
||||
return tv1->m_data.num == tv2->m_data.num;
|
||||
if (c2->m_type != c1->m_type) return false;
|
||||
return c1->m_data.num == c2->m_data.num;
|
||||
case KindOfDouble:
|
||||
if (tv2->m_type != tv1->m_type) return false;
|
||||
return tv1->m_data.dbl == tv2->m_data.dbl;
|
||||
if (c2->m_type != c1->m_type) return false;
|
||||
return c1->m_data.dbl == c2->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);
|
||||
if (!IS_STRING_TYPE(c2->m_type)) return false;
|
||||
return c1->m_data.pstr->same(c2->m_data.pstr);
|
||||
|
||||
case KindOfArray:
|
||||
if (tv2->m_type != KindOfArray) return false;
|
||||
return tv1->m_data.parr->equal(tv2->m_data.parr, true);
|
||||
if (c2->m_type != KindOfArray) return false;
|
||||
return c1->m_data.parr->equal(c2->m_data.parr, true);
|
||||
|
||||
case KindOfObject:
|
||||
return tv2->m_type == KindOfObject &&
|
||||
tv1->m_data.pobj == tv2->m_data.pobj;
|
||||
return c2->m_type == KindOfObject &&
|
||||
c1->m_data.pobj == c2->m_data.pobj;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -427,6 +407,12 @@ bool tvSame(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
not_reached();
|
||||
}
|
||||
|
||||
bool tvSame(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
assert(tvIsPlausible(tv1));
|
||||
assert(tvIsPlausible(tv2));
|
||||
return cellSame(tvToCell(tv1), tvToCell(tv2));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
@@ -459,6 +445,10 @@ bool cellEqual(const Cell* cell, const ObjectData* val) {
|
||||
return cellRelOp(Eq(), cell, val);
|
||||
}
|
||||
|
||||
bool cellEqual(const Cell* c1, const Cell* c2) {
|
||||
return cellRelOp(Eq(), c1, c2);
|
||||
}
|
||||
|
||||
HOT_FUNC
|
||||
bool tvEqual(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
return tvRelOp(Eq(), tv1, tv2);
|
||||
@@ -488,6 +478,10 @@ bool cellLess(const Cell* cell, const ObjectData* val) {
|
||||
return cellRelOp(Lt(), cell, val);
|
||||
}
|
||||
|
||||
bool cellLess(const Cell* c1, const Cell* c2) {
|
||||
return cellRelOp(Lt(), c1, c2);
|
||||
}
|
||||
|
||||
HOT_FUNC
|
||||
bool tvLess(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
return tvRelOp(Lt(), tv1, tv2);
|
||||
@@ -518,11 +512,39 @@ bool cellGreater(const Cell* cell, const ObjectData* val) {
|
||||
return cellRelOp(Gt(), cell, val);
|
||||
}
|
||||
|
||||
bool cellGreater(const Cell* c1, const Cell* c2) {
|
||||
return cellRelOp(Gt(), c1, c2);
|
||||
}
|
||||
|
||||
bool tvGreater(const TypedValue* tv1, const TypedValue* tv2) {
|
||||
return tvRelOp(Gt(), tv1, tv2);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool cellLessOrEqual(const Cell* c1, const Cell* c2) {
|
||||
assert(c1->m_type != KindOfRef);
|
||||
assert(c2->m_type != KindOfRef);
|
||||
|
||||
if ((c1->m_type == KindOfArray && c2->m_type == KindOfArray) ||
|
||||
(c1->m_type == KindOfObject && c2->m_type == KindOfObject)) {
|
||||
return cellLess(c1, c2) || cellEqual(c1, c2);
|
||||
}
|
||||
return !cellGreater(c1, c2);
|
||||
}
|
||||
|
||||
bool cellGreaterOrEqual(const Cell* c1, const Cell* c2) {
|
||||
assert(c1->m_type != KindOfRef);
|
||||
assert(c2->m_type != KindOfRef);
|
||||
|
||||
if ((c1->m_type == KindOfArray && c2->m_type == KindOfArray) ||
|
||||
(c1->m_type == KindOfObject && c2->m_type == KindOfObject)) {
|
||||
return cellGreater(c1, c2) || cellEqual(c1, c2);
|
||||
}
|
||||
return !cellLess(c1, c2);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ namespace HPHP {
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Php's operator ===
|
||||
|
||||
/*
|
||||
* Returns whether two Cells have the same value, in the sense of
|
||||
* php's === operator.
|
||||
*/
|
||||
bool cellSame(const Cell*, const Cell*);
|
||||
|
||||
/*
|
||||
* Returns whether two TypedValues have the same value, in sense of
|
||||
* php's === operator.
|
||||
@@ -44,6 +50,12 @@ bool cellEqual(const Cell*, const StringData*);
|
||||
bool cellEqual(const Cell*, const ArrayData*);
|
||||
bool cellEqual(const Cell*, const ObjectData*);
|
||||
|
||||
/*
|
||||
* Returns whether two Cells have the same value, in the same of php's
|
||||
* == operator.
|
||||
*/
|
||||
bool cellEqual(const Cell*, const Cell*);
|
||||
|
||||
/*
|
||||
* Returns whether two TypedValues have the same value, in the sense
|
||||
* of php's == operator.
|
||||
@@ -65,6 +77,12 @@ bool cellLess(const Cell*, const StringData*);
|
||||
bool cellLess(const Cell*, const ArrayData*);
|
||||
bool cellLess(const Cell*, const ObjectData*);
|
||||
|
||||
/*
|
||||
* Returns whether a Cell is greater than another Cell, in the sense
|
||||
* of php's < operator.
|
||||
*/
|
||||
bool cellLess(const Cell*, const Cell*);
|
||||
|
||||
/*
|
||||
* Returns whether tv1 is less than tv2, as in php's < operator.
|
||||
*/
|
||||
@@ -85,6 +103,12 @@ bool cellGreater(const Cell*, const StringData*);
|
||||
bool cellGreater(const Cell*, const ArrayData*);
|
||||
bool cellGreater(const Cell*, const ObjectData*);
|
||||
|
||||
/*
|
||||
* Returns whether a Cell is greater than another Cell, in the sense
|
||||
* of php's > operator.
|
||||
*/
|
||||
bool cellGreater(const Cell*, const Cell*);
|
||||
|
||||
/*
|
||||
* Returns whether tv1 is greather than tv2, as in php's > operator.
|
||||
*/
|
||||
@@ -92,6 +116,19 @@ bool tvGreater(const TypedValue*, const TypedValue*);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Php operator >= and <=
|
||||
*
|
||||
* Note that in php $x <= $y is not equivalent to !($x > $y) for
|
||||
* objects and arrays.
|
||||
*
|
||||
* These functions are necessary to handle those cases specially.
|
||||
*/
|
||||
bool cellLessOrEqual(const Cell*, const Cell*);
|
||||
bool cellGreaterOrEqual(const Cell*, const Cell*);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
#include "hphp/runtime/base/tv_comparisons-inl.h"
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| 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. |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
namespace HPHP {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool cellToBool(const Cell* cell) {
|
||||
assert(tvIsPlausible(cell));
|
||||
assert(cell->m_type != KindOfRef);
|
||||
|
||||
switch (cell->m_type) {
|
||||
case KindOfUninit:
|
||||
case KindOfNull: return false;
|
||||
case KindOfInt64: return cell->m_data.num != 0;
|
||||
case KindOfBoolean: return cell->m_data.num;
|
||||
case KindOfDouble: return cell->m_data.dbl != 0;
|
||||
case KindOfStaticString:
|
||||
case KindOfString: return cell->m_data.pstr->toBoolean();
|
||||
case KindOfArray: return !cell->m_data.parr->empty();
|
||||
case KindOfObject: // TODO: should handle o_toBoolean?
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
not_reached();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
@@ -29,16 +29,6 @@ namespace HPHP {
|
||||
|
||||
class Variant;
|
||||
|
||||
template<typename Data>
|
||||
inline TypedValue tv(DataType type, Data data) {
|
||||
static_assert(sizeof(Data) == sizeof(int64_t),
|
||||
"Data type in tv() not proper size");
|
||||
TypedValue v;
|
||||
v.m_data.num = (int64_t)data;
|
||||
v.m_type = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
// Assumes 'data' is live
|
||||
// Assumes 'IS_REFCOUNTED_TYPE(type)'
|
||||
void tvDecRefHelper(DataType type, uint64_t datum);
|
||||
@@ -448,6 +438,15 @@ inline bool tvIsString(const TypedValue* tv) {
|
||||
|
||||
void tvUnboxIfNeeded(TypedValue* tv);
|
||||
|
||||
/*
|
||||
* Convert a cell to a boolean, without changing the Cell.
|
||||
*/
|
||||
bool cellToBool(const Cell*);
|
||||
|
||||
/*
|
||||
* TypedValue conversions that update the tv in place (decrefing and
|
||||
* old value, if necessary).
|
||||
*/
|
||||
void tvCastToBooleanInPlace(TypedValue* tv);
|
||||
void tvCastToInt64InPlace(TypedValue* tv, int base = 10);
|
||||
int64_t tvCastToInt64(TypedValue* tv, int base = 10);
|
||||
@@ -471,4 +470,6 @@ extern const RawDestructor g_destructors[kDestrTableSize];
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
#include "hphp/runtime/base/tv_helpers-inl.h"
|
||||
|
||||
#endif // incl_HPHP_TV_HELPERS_H_
|
||||
|
||||
@@ -587,14 +587,6 @@ bool String::operator!=(litstr v) const {
|
||||
return !HPHP::equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>=(litstr v) const {
|
||||
return more_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator<=(litstr v) const {
|
||||
return less_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>(litstr v) const {
|
||||
return HPHP::more(m_px, v);
|
||||
}
|
||||
@@ -611,14 +603,6 @@ bool String::operator!=(CStrRef v) const {
|
||||
return !HPHP::equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>=(CStrRef v) const {
|
||||
return more_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator<=(CStrRef v) const {
|
||||
return less_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>(CStrRef v) const {
|
||||
return HPHP::more(m_px, v);
|
||||
}
|
||||
@@ -635,14 +619,6 @@ bool String::operator!=(CVarRef v) const {
|
||||
return !HPHP::equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>=(CVarRef v) const {
|
||||
return more_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator<=(CVarRef v) const {
|
||||
return less_or_equal(m_px, v);
|
||||
}
|
||||
|
||||
bool String::operator>(CVarRef v) const {
|
||||
return HPHP::more(m_px, v);
|
||||
}
|
||||
|
||||
@@ -332,20 +332,20 @@ public:
|
||||
*/
|
||||
bool operator == (litstr v) const;
|
||||
bool operator != (litstr v) const;
|
||||
bool operator >= (litstr v) const;
|
||||
bool operator <= (litstr v) const;
|
||||
bool operator >= (litstr v) const = delete;
|
||||
bool operator <= (litstr v) const = delete;
|
||||
bool operator > (litstr v) const;
|
||||
bool operator < (litstr v) const;
|
||||
bool operator == (CStrRef v) const;
|
||||
bool operator != (CStrRef v) const;
|
||||
bool operator >= (CStrRef v) const;
|
||||
bool operator <= (CStrRef v) const;
|
||||
bool operator >= (CStrRef v) const = delete;
|
||||
bool operator <= (CStrRef v) const = delete;
|
||||
bool operator > (CStrRef v) const;
|
||||
bool operator < (CStrRef v) const;
|
||||
bool operator == (CVarRef v) const;
|
||||
bool operator != (CVarRef v) const;
|
||||
bool operator >= (CVarRef v) const;
|
||||
bool operator <= (CVarRef v) const;
|
||||
bool operator >= (CVarRef v) const = delete;
|
||||
bool operator <= (CVarRef v) const = delete;
|
||||
bool operator > (CVarRef v) const;
|
||||
bool operator < (CVarRef v) const;
|
||||
|
||||
|
||||
@@ -3780,79 +3780,70 @@ inline void OPTBLD_INLINE VMExecutionContext::iopMod(PC& pc) {
|
||||
#undef MATHOP_DOUBLE
|
||||
#undef MATHOP_DIVCHECK
|
||||
|
||||
#define LOGICOP(OP) do { \
|
||||
NEXT(); \
|
||||
Cell* c1 = m_stack.topC(); \
|
||||
Cell* c2 = m_stack.indC(1); \
|
||||
{ \
|
||||
tvCellAsVariant(c2) = \
|
||||
bool(tvCellAsVariant(c2).toBoolean() OP tvCellAsVariant(c1).toBoolean()); \
|
||||
} \
|
||||
m_stack.popC(); \
|
||||
} while (0)
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopXor(PC& pc) {
|
||||
LOGICOP(^);
|
||||
}
|
||||
#undef LOGICOP
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopNot(PC& pc) {
|
||||
NEXT();
|
||||
Cell* c1 = m_stack.topC();
|
||||
tvCellAsVariant(c1) = !tvCellAsVariant(c1).toBoolean();
|
||||
}
|
||||
|
||||
#define CMPOP(OP, VOP) do { \
|
||||
NEXT(); \
|
||||
Cell* c1 = m_stack.topC(); \
|
||||
Cell* c2 = m_stack.indC(1); \
|
||||
if (c2->m_type == KindOfInt64 && c1->m_type == KindOfInt64) { \
|
||||
int64_t a = c2->m_data.num; \
|
||||
int64_t b = c1->m_data.num; \
|
||||
c2->m_data.num = (a OP b); \
|
||||
c2->m_type = KindOfBoolean; \
|
||||
m_stack.popX(); \
|
||||
} else { \
|
||||
int64_t result = VOP(tvCellAsVariant(c2), tvCellAsCVarRef(c1)); \
|
||||
tvRefcountedDecRefCell(c2); \
|
||||
c2->m_data.num = result; \
|
||||
c2->m_type = KindOfBoolean; \
|
||||
m_stack.popC(); \
|
||||
} \
|
||||
} while (0)
|
||||
template<class Op>
|
||||
void OPTBLD_INLINE VMExecutionContext::implCellBinOpBool(PC& pc, Op op) {
|
||||
NEXT();
|
||||
auto const c1 = m_stack.topC();
|
||||
auto const c2 = m_stack.indC(1);
|
||||
bool const result = op(c2, c1);
|
||||
tvRefcountedDecRefCell(c2);
|
||||
*c2 = make_tv<KindOfBoolean>(result);
|
||||
m_stack.popC();
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopXor(PC& pc) {
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) -> bool {
|
||||
return cellToBool(c1) ^ cellToBool(c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopSame(PC& pc) {
|
||||
CMPOP(==, same);
|
||||
implCellBinOpBool(pc, cellSame);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopNSame(PC& pc) {
|
||||
CMPOP(!=, !same);
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) {
|
||||
return !cellSame(c1, c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopEq(PC& pc) {
|
||||
CMPOP(==, equal);
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) {
|
||||
return cellEqual(c1, c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopNeq(PC& pc) {
|
||||
CMPOP(!=, !equal);
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) {
|
||||
return !cellEqual(c1, c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopLt(PC& pc) {
|
||||
CMPOP(<, less);
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) {
|
||||
return cellLess(c1, c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopLte(PC& pc) {
|
||||
CMPOP(<=, less_or_equal);
|
||||
implCellBinOpBool(pc, cellLessOrEqual);
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopGt(PC& pc) {
|
||||
CMPOP(>, more);
|
||||
implCellBinOpBool(pc, [&] (const Cell* c1, const Cell* c2) {
|
||||
return cellGreater(c1, c2);
|
||||
});
|
||||
}
|
||||
|
||||
inline void OPTBLD_INLINE VMExecutionContext::iopGte(PC& pc) {
|
||||
CMPOP(>=, more_or_equal);
|
||||
implCellBinOpBool(pc, cellGreaterOrEqual);
|
||||
}
|
||||
#undef CMPOP
|
||||
|
||||
#define MATHOP_DOUBLE(OP)
|
||||
#define MATHOP_DIVCHECK(x)
|
||||
|
||||
@@ -31,7 +31,7 @@ class InvalidSetMException : public std::runtime_error {
|
||||
public:
|
||||
InvalidSetMException()
|
||||
: std::runtime_error("Empty InvalidSetMException")
|
||||
, m_tv(HPHP::tv(KindOfNull, 0LL))
|
||||
, m_tv(make_tv<KindOfNull>())
|
||||
{}
|
||||
|
||||
explicit InvalidSetMException(const TypedValue& value)
|
||||
@@ -543,7 +543,7 @@ inline void SetElemNumberish(Cell* value) {
|
||||
tvRefcountedDecRefCell((TypedValue*)value);
|
||||
tvWriteNull((TypedValue*)value);
|
||||
} else {
|
||||
throw InvalidSetMException(tv(KindOfNull, 0LL));
|
||||
throw InvalidSetMException(make_tv<KindOfNull>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ inline void SetElemArray(TypedValue* base, TypedValue* key,
|
||||
tvRefcountedDecRef(value);
|
||||
tvWriteNull(value);
|
||||
} else {
|
||||
throw InvalidSetMException(tv(KindOfNull, 0LL));
|
||||
throw InvalidSetMException(make_tv<KindOfNull>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,7 +788,7 @@ inline void SetNewElemNumberish(Cell* value) {
|
||||
tvRefcountedDecRefCell((TypedValue*)value);
|
||||
tvWriteNull((TypedValue*)value);
|
||||
} else {
|
||||
throw InvalidSetMException(tv(KindOfNull, 0LL));
|
||||
throw InvalidSetMException(make_tv<KindOfNull>());
|
||||
}
|
||||
}
|
||||
template <bool setResult>
|
||||
@@ -1519,7 +1519,7 @@ inline void SetPropNull(Cell* val) {
|
||||
tvRefcountedDecRefCell(val);
|
||||
tvWriteNull(val);
|
||||
} else {
|
||||
throw InvalidSetMException(tv(KindOfNull, 0LL));
|
||||
throw InvalidSetMException(make_tv<KindOfNull>());
|
||||
}
|
||||
}
|
||||
inline void SetPropStdclass(TypedValue* base, TypedValue* key,
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário