Implement shift operators outside of Variant

Esse commit está contido em:
Jordan DeLong
2013-07-01 19:15:25 -07:00
commit de Sara Golemon
commit 524cbb5d3e
9 arquivos alterados com 64 adições e 58 exclusões
@@ -584,9 +584,11 @@ ExpressionPtr BinaryOpExpression::foldConst(AnalysisResultConstPtr ar) {
*result.asCell() = cellMod(*v1.asCell(), *v2.asCell());
break;
case T_SL:
result = shift_left(v1.toInt64(), v2.toInt64()); break;
result = v1.toInt64() << v2.toInt64();
break;
case T_SR:
result = shift_right(v1.toInt64(), v2.toInt64()); break;
result = v1.toInt64() >> v2.toInt64();
break;
case T_BOOLEAN_OR:
result = v1.toBoolean() || v2.toBoolean(); break;
case T_BOOLEAN_AND:
+1 -4
Ver Arquivo
@@ -90,10 +90,7 @@ bool empty(CVarRef v, CStrRef, bool = false) = delete;
///////////////////////////////////////////////////////////////////////////////
// operators
inline int64_t shift_left(int64_t v1, int64_t v2) { return v1 << v2; }
inline int64_t shift_right(int64_t v1, int64_t v2) { return v1 >> v2; }
inline String concat(CStrRef s1, CStrRef s2) {
inline String concat(CStrRef s1, CStrRef s2) {
return s1 + s2;
}
+1
Ver Arquivo
@@ -457,6 +457,7 @@ void tvUnboxIfNeeded(TypedValue* tv);
*/
void tvCastToBooleanInPlace(TypedValue* tv);
void tvCastToInt64InPlace(TypedValue* tv);
void cellCastToInt64InPlace(Cell*);
void tvCastToDoubleInPlace(TypedValue* tv);
double tvCastToDouble(TypedValue* tv);
void tvCastToStringInPlace(TypedValue* tv);
-10
Ver Arquivo
@@ -624,16 +624,6 @@ Variant Variant::bitNot() const {
throw InvalidOperandException("only numerics and strings can be negated");
}
Variant &Variant::operator<<=(int64_t n) {
set(toInt64() << n);
return *this;
}
Variant &Variant::operator>>=(int64_t n) {
set(toInt64() >> n);
return *this;
}
///////////////////////////////////////////////////////////////////////////////
// increment/decrement
+2 -2
Ver Arquivo
@@ -581,8 +581,8 @@ class Variant : private TypedValue {
Variant &operator &= (CVarRef v) = delete;
Variant operator ^ (CVarRef v) const = delete;
Variant &operator ^= (CVarRef v) = delete;
Variant &operator <<=(int64_t n);
Variant &operator >>=(int64_t n);
Variant &operator <<=(int64_t n) = delete;
Variant &operator >>=(int64_t n) = delete;
Variant &operator ++ ();
Variant operator ++ (int);
+23 -35
Ver Arquivo
@@ -3688,6 +3688,17 @@ void OPTBLD_INLINE VMExecutionContext::implCellBinOp(PC& pc, Op op) {
m_stack.popC();
}
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::iopAdd(PC& pc) {
implCellBinOp(pc, cellAdd);
}
@@ -3720,17 +3731,6 @@ inline void OPTBLD_INLINE VMExecutionContext::iopBitXor(PC& pc) {
implCellBinOp(pc, cellBitXor);
}
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, [&] (Cell c1, Cell c2) -> bool {
return cellToBool(c1) ^ cellToBool(c2);
@@ -3779,6 +3779,18 @@ inline void OPTBLD_INLINE VMExecutionContext::iopGte(PC& pc) {
implCellBinOpBool(pc, cellGreaterOrEqual);
}
inline void OPTBLD_INLINE VMExecutionContext::iopShl(PC& pc) {
implCellBinOp(pc, [&] (Cell c1, Cell c2) {
return make_tv<KindOfInt64>(cellToInt(c1) << cellToInt(c2));
});
}
inline void OPTBLD_INLINE VMExecutionContext::iopShr(PC& pc) {
implCellBinOp(pc, [&] (Cell c1, Cell c2) {
return make_tv<KindOfInt64>(cellToInt(c1) >> cellToInt(c2));
});
}
inline void OPTBLD_INLINE VMExecutionContext::iopBitNot(PC& pc) {
NEXT();
Cell* c1 = m_stack.topC();
@@ -3794,30 +3806,6 @@ inline void OPTBLD_INLINE VMExecutionContext::iopBitNot(PC& pc) {
}
}
#define SHIFTOP(OP) 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; \
m_stack.popX(); \
} else { \
tvCellAsVariant(c2) = tvCellAsVariant(c2).toInt64() OP \
tvCellAsCVarRef(c1).toInt64(); \
m_stack.popC(); \
} \
} while (0)
inline void OPTBLD_INLINE VMExecutionContext::iopShl(PC& pc) {
SHIFTOP(<<);
}
inline void OPTBLD_INLINE VMExecutionContext::iopShr(PC& pc) {
SHIFTOP(>>);
}
#undef SHIFTOP
inline void OPTBLD_INLINE VMExecutionContext::iopCastBool(PC& pc) {
NEXT();
Cell* c1 = m_stack.topC();
+12 -5
Ver Arquivo
@@ -23,6 +23,7 @@
#include "hphp/util/util.h"
#include "hphp/runtime/base/complex_types.h"
#include "hphp/runtime/base/tv_arith.h"
#include "hphp/runtime/base/tv_conversions.h"
#include "hphp/runtime/base/class_info.h"
#include "hphp/runtime/base/array/array_iterator.h"
#include "hphp/runtime/vm/class.h"
@@ -50,11 +51,17 @@ void SETOP_BODY(TypedValue* lhs, unsigned char op, Cell* rhs) {
case SetOpAndEqual: cellBitAndEq(*lhs, *rhs); break;
case SetOpOrEqual: cellBitOrEq(*lhs, *rhs); break;
case SetOpXorEqual: cellBitXorEq(*lhs, *rhs); break;
case SetOpSlEqual: tvAsVariant(lhs) <<=
tvCellAsCVarRef(rhs).toInt64(); break;
case SetOpSrEqual: tvAsVariant(lhs) >>=
tvCellAsCVarRef(rhs).toInt64(); break;
default: not_reached();
case SetOpSlEqual:
cellCastToInt64InPlace(lhs);
lhs->m_data.num <<= cellToInt(*rhs);
break;
case SetOpSrEqual:
cellCastToInt64InPlace(lhs);
lhs->m_data.num >>= cellToInt(*rhs);
break;
default:
not_reached();
}
}
+16
Ver Arquivo
@@ -0,0 +1,16 @@
<?php
class A {
public function __destruct() { echo "~A\n"; }
}
class B {
public function __destruct() { echo "~B\n"; }
}
function main() {
$k = (new A) << (new B);
var_dump($k);
}
main();
+5
Ver Arquivo
@@ -0,0 +1,5 @@
HipHop Notice: Object of class A could not be converted to int in %s on line 12
HipHop Notice: Object of class B could not be converted to int in %s on line 12
~A
~B
int(2)