Implement bitwise negation outside of Variant

Esse commit está contido em:
Jordan DeLong
2013-07-05 13:51:21 -07:00
commit de Sara Golemon
commit e250fd6336
8 arquivos alterados com 62 adições e 50 exclusões
+17 -8
Ver Arquivo
@@ -237,21 +237,30 @@ bool UnaryOpExpression::preCompute(CVarRef value, Variant &result) {
*result.asCell());
break;
case '~':
result = value.bitNot(); break;
tvSet(*value.asCell(), *result.asTypedValue());
cellBitNot(*result.asCell());
break;
case '@':
result = value; break;
result = value;
break;
case T_INT_CAST:
result = value.toInt64(); break;
result = value.toInt64();
break;
case T_DOUBLE_CAST:
result = toDouble(value); break;
result = toDouble(value);
break;
case T_STRING_CAST:
result = toString(value); break;
result = toString(value);
break;
case T_BOOL_CAST:
result = toBoolean(value); break;
result = toBoolean(value);
break;
case T_EMPTY:
result = empty(value); break;
result = empty(value);
break;
case T_ISSET:
result = isset(value); break;
result = isset(value);
break;
case T_INC:
case T_DEC:
assert(false);
+32 -1
Ver Arquivo
@@ -239,7 +239,6 @@ struct MulEq {
}
};
template<class SzOp, class BitOp>
StringData* stringBitOp(BitOp bop, SzOp sop, StringData* s1, StringData* s2) {
auto const s1Size = s1->size();
@@ -489,6 +488,38 @@ void cellDec(Cell& cell) {
cellIncDecOp(Dec(), cell);
}
void cellBitNot(Cell& cell) {
assert(cellIsPlausible(&cell));
switch (cell.m_type) {
case KindOfInt64:
cell.m_data.num = ~cell.m_data.num;
break;
case KindOfDouble:
cell.m_type = KindOfInt64;
cell.m_data.num = ~toInt64(cell.m_data.dbl);
break;
case KindOfString:
if (cell.m_data.pstr->getCount() > 1) {
case KindOfStaticString:
auto const newSd = NEW(StringData)(
cell.m_data.pstr->slice(),
CopyString
);
newSd->incRefCount();
cell.m_data.pstr->decRefCount(); // can't go to zero
cell.m_data.pstr = newSd;
cell.m_type = KindOfString;
}
cell.m_data.pstr->negate();
break;
default:
raise_error("Unsupported operand type for ~");
}
}
//////////////////////////////////////////////////////////////////////
}
+11
Ver Arquivo
@@ -112,6 +112,8 @@ void cellBitAndEq(Cell& c1, Cell);
void cellBitOrEq(Cell& c1, Cell);
void cellBitXorEq(Cell& c1, Cell);
//////////////////////////////////////////////////////////////////////
/*
* PHP operator ++ and --.
*
@@ -121,6 +123,15 @@ void cellBitXorEq(Cell& c1, Cell);
void cellInc(Cell&);
void cellDec(Cell&);
/*
* PHP unary operator ~.
*
* Mutates the argument in place, with the effects of php's unary
* bitwise not operator.
*/
void cellBitNot(Cell&);
//////////////////////////////////////////////////////////////////////
}
-6
Ver Arquivo
@@ -396,12 +396,6 @@ String operator+(const String & lhs, const String & rhs) {
return NEW(StringData)(lhs.slice(), rhs.slice());
}
String String::operator~() const {
String ret(NEW(StringData)(slice(), CopyString));
ret->negate();
return ret;
}
///////////////////////////////////////////////////////////////////////////////
// conversions
+1 -1
Ver Arquivo
@@ -318,7 +318,7 @@ public:
String &operator |= (CStrRef v) = delete;
String &operator &= (CStrRef v) = delete;
String &operator ^= (CStrRef v) = delete;
String operator ~ () const;
String operator ~ () const = delete;
explicit operator std::string () const {
return std::string(c_str(), size());
}
-19
Ver Arquivo
@@ -522,25 +522,6 @@ inline DataType Variant::convertToNumeric(int64_t *lval, double *dval) const {
return s->isNumericWithVal(*lval, *dval, 1);
}
///////////////////////////////////////////////////////////////////////////////
// bitwise
Variant Variant::bitNot() const {
auto const cell = asCell();
switch (cell->m_type) {
case KindOfInt64:
return ~cell->m_data.num;
case KindOfDouble:
return ~toInt64(cell->m_data.dbl);
case KindOfStaticString:
case KindOfString:
return ~String(cell->m_data.pstr);
default:
break;
}
throw InvalidOperandException("only numerics and strings can be negated");
}
///////////////////////////////////////////////////////////////////////////////
// iterator functions
-4
Ver Arquivo
@@ -590,10 +590,6 @@ class Variant : private TypedValue {
Variant &operator -- () = delete;
Variant operator -- (int) = delete;
// Return the result of applying the php bitwise not operator to
// this value.
Variant bitNot() const;
/**
* Iterator functions. See array_iterator.h for end() and next().
*/
+1 -11
Ver Arquivo
@@ -3768,17 +3768,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopShr(PC& pc) {
inline void OPTBLD_INLINE VMExecutionContext::iopBitNot(PC& pc) {
NEXT();
Cell* c1 = m_stack.topC();
if (LIKELY(c1->m_type == KindOfInt64)) {
c1->m_data.num = ~c1->m_data.num;
} else if (c1->m_type == KindOfDouble) {
c1->m_type = KindOfInt64;
c1->m_data.num = ~int64_t(c1->m_data.dbl);
} else if (IS_STRING_TYPE(c1->m_type)) {
cellAsVariant(*c1) = cellAsVariant(*c1).bitNot();
} else {
raise_error("Unsupported operand type for ~");
}
cellBitNot(*m_stack.topC());
}
inline void OPTBLD_INLINE VMExecutionContext::iopCastBool(PC& pc) {