diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index 578fbcec5..931cfa59c 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -1699,7 +1699,7 @@ void EmitterVisitor::visit(FileScopePtr file) { } else { assert(!IS_REFCOUNTED_TYPE(v.getType())); } - mainReturn = *v.getTypedAccessor(); + mainReturn = *v.asCell(); m_ue.returnSeen(); } break; diff --git a/hphp/compiler/expression/unary_op_expression.cpp b/hphp/compiler/expression/unary_op_expression.cpp index e9e7facc4..7e6464814 100644 --- a/hphp/compiler/expression/unary_op_expression.cpp +++ b/hphp/compiler/expression/unary_op_expression.cpp @@ -233,7 +233,7 @@ bool UnaryOpExpression::preCompute(CVarRef value, Variant &result) { case '-': result = value.negate(); break; case '~': - result = ~value; break; + result = value.bitNot(); break; case '@': result = value; break; case T_INT_CAST: diff --git a/hphp/runtime/base/array/array_inline.h b/hphp/runtime/base/array/array_inline.h index 08df86e04..2e5ef7b2a 100644 --- a/hphp/runtime/base/array/array_inline.h +++ b/hphp/runtime/base/array/array_inline.h @@ -24,18 +24,18 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// namespace { -typedef Variant::TypedValueAccessor TypedValueAccessor; - -inline bool isIntKey(TypedValueAccessor tva) { - return Variant::GetAccessorType(tva) <= KindOfInt64; +inline bool isIntKey(const Cell* cell) { + return IS_INT_KEY_TYPE(cell->m_type); } -inline int64_t getIntKey(TypedValueAccessor tva) { - return Variant::GetInt64(tva); +inline int64_t getIntKey(const Cell* cell) { + assert(cell->m_type == KindOfInt64); + return cell->m_data.num; } -inline StringData *getStringKey(TypedValueAccessor tva) { - return Variant::GetStringData(tva); +inline StringData* getStringKey(const Cell* cell) { + assert(IS_STRING_TYPE(cell->m_type)); + return cell->m_data.pstr; } } @@ -46,9 +46,9 @@ inline bool ArrayData::exists(CStrRef k) const { inline bool ArrayData::exists(CVarRef k) const { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? exists(getIntKey(tvk)) : - exists(getStringKey(tvk)); + auto const cell = k.asCell(); + return isIntKey(cell) ? exists(getIntKey(cell)) + : exists(getStringKey(cell)); } inline CVarRef ArrayData::get(CStrRef k, bool error) const { @@ -58,9 +58,9 @@ inline CVarRef ArrayData::get(CStrRef k, bool error) const { inline CVarRef ArrayData::get(CVarRef k, bool error) const { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? get(getIntKey(tvk), error) : - get(getStringKey(tvk), error); + auto const cell = k.asCell(); + return isIntKey(cell) ? get(getIntKey(cell), error) + : get(getStringKey(cell), error); } inline ArrayData* ArrayData::lval(CStrRef k, Variant *&ret, bool copy, @@ -72,9 +72,9 @@ inline ArrayData* ArrayData::lval(CStrRef k, Variant *&ret, bool copy, inline ArrayData* ArrayData::lval(CVarRef k, Variant *&ret, bool copy, bool checkExist) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? lval(getIntKey(tvk), ret, copy, checkExist) : - lval(getStringKey(tvk), ret, copy, checkExist); + auto const cell = k.asCell(); + return isIntKey(cell) ? lval(getIntKey(cell), ret, copy, checkExist) + : lval(getStringKey(cell), ret, copy, checkExist); } inline ArrayData *ArrayData::lvalPtr(CStrRef k, Variant *&ret, bool copy, @@ -90,9 +90,9 @@ inline ArrayData* ArrayData::set(CStrRef k, CVarRef v, bool copy) { inline ArrayData* ArrayData::set(CVarRef k, CVarRef v, bool copy) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? set(getIntKey(tvk), v, copy) : - set(getStringKey(tvk), v, copy); + auto const cell = k.asCell(); + return isIntKey(cell) ? set(getIntKey(cell), v, copy) + : set(getStringKey(cell), v, copy); } inline ArrayData* ArrayData::setRef(CStrRef k, CVarRef v, bool copy) { @@ -102,9 +102,9 @@ inline ArrayData* ArrayData::setRef(CStrRef k, CVarRef v, bool copy) { inline ArrayData* ArrayData::setRef(CVarRef k, CVarRef v, bool copy) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? setRef(getIntKey(tvk), v, copy) : - setRef(getStringKey(tvk), v, copy); + auto const cell = k.asCell(); + return isIntKey(cell) ? setRef(getIntKey(cell), v, copy) + : setRef(getStringKey(cell), v, copy); } inline ArrayData* ArrayData::add(CStrRef k, CVarRef v, bool copy) { @@ -114,9 +114,9 @@ inline ArrayData* ArrayData::add(CStrRef k, CVarRef v, bool copy) { inline ArrayData* ArrayData::add(CVarRef k, CVarRef v, bool copy) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? add(getIntKey(tvk), v, copy) : - add(getStringKey(tvk), v, copy); + auto const cell = k.asCell(); + return isIntKey(cell) ? add(getIntKey(cell), v, copy) + : add(getStringKey(cell), v, copy); } inline ArrayData* ArrayData::addLval(CStrRef k, Variant *&ret, bool copy) { @@ -126,9 +126,9 @@ inline ArrayData* ArrayData::addLval(CStrRef k, Variant *&ret, bool copy) { inline ArrayData* ArrayData::addLval(CVarRef k, Variant *&ret, bool copy) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? addLval(getIntKey(tvk), ret, copy) : - addLval(getStringKey(tvk), ret, copy); + auto const cell = k.asCell(); + return isIntKey(cell) ? addLval(getIntKey(cell), ret, copy) + : addLval(getStringKey(cell), ret, copy); } inline ArrayData* ArrayData::remove(CStrRef k, bool copy) { @@ -138,9 +138,9 @@ inline ArrayData* ArrayData::remove(CStrRef k, bool copy) { inline ArrayData* ArrayData::remove(CVarRef k, bool copy) { assert(IsValidKey(k)); - TypedValueAccessor tvk = k.getTypedAccessor(); - return isIntKey(tvk) ? remove(getIntKey(tvk), copy) : - remove(getStringKey(tvk), copy); + auto const cell = k.asCell(); + return isIntKey(cell) ? remove(getIntKey(cell), copy) + : remove(getStringKey(cell), copy); } /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/base/builtin_functions.cpp b/hphp/runtime/base/builtin_functions.cpp index c2ff731e9..5bcbcc921 100644 --- a/hphp/runtime/base/builtin_functions.cpp +++ b/hphp/runtime/base/builtin_functions.cpp @@ -1056,10 +1056,10 @@ AutoloadHandler::Result AutoloadHandler::loadFromMap(CStrRef name, assert(!m_map.isNull()); while (true) { CVarRef &type_map = m_map.get()->get(kind); - Variant::TypedValueAccessor tva = type_map.getTypedAccessor(); - if (Variant::GetAccessorType(tva) != KindOfArray) return Failure; + auto const typeMapCell = type_map.asCell(); + if (typeMapCell->m_type != KindOfArray) return Failure; String canonicalName = toLower ? StringUtil::ToLower(name) : name; - CVarRef &file = Variant::GetArrayData(tva)->get(canonicalName); + CVarRef &file = typeMapCell->m_data.parr->get(canonicalName); bool ok = false; if (file.isString()) { String fName = file.toCStrRef().get(); @@ -1095,9 +1095,9 @@ AutoloadHandler::Result AutoloadHandler::loadFromMap(CStrRef name, // - false means we should stop applying autoloaders (only affects classes) // - anything else means keep going Variant action = vm_call_user_func(func, CREATE_VECTOR2(kind, name)); - tva = action.getTypedAccessor(); - if (Variant::GetAccessorType(tva) == KindOfBoolean) { - if (Variant::GetBoolean(tva)) continue; + auto const actionCell = action.asCell(); + if (actionCell->m_type == KindOfBoolean) { + if (actionCell->m_data.num) continue; return StopAutoloading; } return ContinueAutoloading; diff --git a/hphp/runtime/base/comparisons.cpp b/hphp/runtime/base/comparisons.cpp index 376e0a6df..52527ee30 100644 --- a/hphp/runtime/base/comparisons.cpp +++ b/hphp/runtime/base/comparisons.cpp @@ -28,10 +28,10 @@ bool same(CVarRef v1, bool v2) { } bool same(CVarRef v1, int64_t v2) { - auto const acc = v1.getTypedAccessor(); - switch (acc->m_type) { + auto const cell = v1.asCell(); + switch (cell->m_type) { case KindOfInt64: - return v2 == acc->m_data.num; + return v2 == cell->m_data.num; default: break; } diff --git a/hphp/runtime/base/datatype.h b/hphp/runtime/base/datatype.h index 14ab88b62..69ab41132 100644 --- a/hphp/runtime/base/datatype.h +++ b/hphp/runtime/base/datatype.h @@ -227,6 +227,10 @@ BOOST_STATIC_ASSERT(KindOfString == 0x14); #define IS_REAL_TYPE(t) \ (((t) >= KindOfUninit && (t) < MaxNumDataTypes) || (t) == KindOfClass) +inline bool IS_INT_KEY_TYPE(DataType t) { + return t <= KindOfInt64; +} + // typeReentersOnRelease -- // Returns whether the release helper for a given type can // reenter. diff --git a/hphp/runtime/base/shared/shared_map.cpp b/hphp/runtime/base/shared/shared_map.cpp index 06dcaf941..e5d0228e2 100644 --- a/hphp/runtime/base/shared/shared_map.cpp +++ b/hphp/runtime/base/shared/shared_map.cpp @@ -227,14 +227,14 @@ TypedValue* SharedMap::nvGetValueRef(ssize_t pos) { TypedValue* SharedMap::nvGetCell(int64_t k) const { int index = getIndex(k); - return index != -1 ? getValueRef(index).getTypedAccessor() : - nvGetNotFound(k); + return index != -1 ? const_cast(getValueRef(index).asCell()) + : nvGetNotFound(k); } TypedValue* SharedMap::nvGetCell(const StringData* key) const { int index = getIndex(key); - return index != -1 ? getValueRef(index).getTypedAccessor() : - nvGetNotFound(key); + return index != -1 ? const_cast(getValueRef(index).asCell()) + : nvGetNotFound(key); } ArrayData* SharedMap::escalateForSort() { diff --git a/hphp/runtime/base/type_variant.cpp b/hphp/runtime/base/type_variant.cpp index 23c0e1dbb..5b1c1bc71 100644 --- a/hphp/runtime/base/type_variant.cpp +++ b/hphp/runtime/base/type_variant.cpp @@ -435,9 +435,9 @@ bool Variant::isScalar() const { } bool Variant::isResource() const { - TypedValueAccessor acc = getTypedAccessor(); - if (GetAccessorType(acc) == KindOfObject) { - return GetObjectData(acc)->isResource(); + auto const cell = asCell(); + if (cell->m_type == KindOfObject) { + return cell->m_data.pobj->isResource(); } return false; } @@ -1199,16 +1199,16 @@ Variant &Variant::operator%=(double n) { /////////////////////////////////////////////////////////////////////////////// // bitwise -Variant Variant::operator~() const { - TypedValueAccessor tva = getTypedAccessor(); - switch (GetAccessorType(tva)) { +Variant Variant::bitNot() const { + auto const cell = asCell(); + switch (cell->m_type) { case KindOfInt64: - return ~GetInt64(tva); + return ~cell->m_data.num; case KindOfDouble: - return ~toInt64(GetDouble(tva)); + return ~toInt64(cell->m_data.dbl); case KindOfStaticString: case KindOfString: - return ~GetAsString(tva); + return ~String(cell->m_data.pstr); default: break; } @@ -1377,9 +1377,9 @@ MutableArrayIter Variant::begin(Variant *key, Variant &val, } void Variant::escalate() { - TypedValueAccessor tva = getTypedAccessor(); - if (GetAccessorType(tva) == KindOfArray) { - ArrayData *arr = GetArrayData(tva); + auto const cell = asCell(); + if (cell->m_type == KindOfArray) { + ArrayData *arr = cell->m_data.parr; ArrayData *esc = arr->escalate(); if (arr != esc) set(esc); } @@ -1545,109 +1545,25 @@ Variant::operator Object() const { /////////////////////////////////////////////////////////////////////////////// -#define UNWRAP(reverse) \ - TypedValueAccessor acc = getTypedAccessor(); \ - switch (GetAccessorType(acc)) { \ - case KindOfUninit: \ - case KindOfNull: return HPHP::reverse(v2, false); \ - case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \ - case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \ - case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \ - case KindOfStaticString: \ - case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \ - case KindOfArray: return HPHP::reverse(v2, Array(GetArrayData(acc))); \ - case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\ - default: \ - assert(false); \ - break; \ - } \ - return false; \ - -// "null" needs to convert to "" before comparing with a string -#define UNWRAP_STR(reverse) \ - TypedValueAccessor acc = getTypedAccessor(); \ - switch (GetAccessorType(acc)) { \ - case KindOfUninit: \ - case KindOfNull: return HPHP::reverse(v2, empty_string); \ - case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \ - case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \ - case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \ - case KindOfStaticString: \ - case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \ - case KindOfArray: return HPHP::reverse(v2, Array(GetArrayData(acc))); \ - case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\ - default: \ - assert(false); \ - break; \ - } \ - return false; \ - // Array needs to convert to "Array" and Object to String -#define UNWRAP_STRING(reverse) \ - TypedValueAccessor acc = getTypedAccessor(); \ - switch (GetAccessorType(acc)) { \ - case KindOfUninit: \ - case KindOfNull: return HPHP::reverse(v2, empty_string); \ - case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \ - case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \ - case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \ - case KindOfStaticString: \ - case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \ - case KindOfArray: return HPHP::reverse(v2, s_array); \ - case KindOfObject: \ - return HPHP::reverse(v2, Object(GetObjectData(acc)).toString()); \ - default: \ - assert(false); \ - break; \ - } \ - return false; \ - -// "null" needs to convert to "" before comparing with a string -#define UNWRAP_VAR(forward, reverse) \ - TypedValueAccessor acc = getTypedAccessor(); \ - switch (GetAccessorType(acc)) { \ - case KindOfUninit: \ - case KindOfNull: \ - if (v2.isString()) { \ - return HPHP::reverse(v2.getStringData(), empty_string); \ - } \ - return HPHP::reverse(v2, false); \ - case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \ - case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \ - case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \ - case KindOfStaticString: \ - case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \ - case KindOfArray: \ - if (v2.isArray()) { \ - return Array(GetArrayData(acc)).forward(Array(v2.getArrayData())); \ - } \ - return HPHP::reverse(v2, Array(GetArrayData(acc))); \ - case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\ - default: \ - assert(false); \ - break; \ - } \ - return false; \ - -// array comparison is directional when they are uncomparable -// also, ">" is implemented as "!<=" in Zend -#define UNWRAP_ARR(forward, reverse) \ - TypedValueAccessor acc = getTypedAccessor(); \ - switch (GetAccessorType(acc)) { \ - case KindOfUninit: \ - case KindOfNull: return HPHP::reverse(v2, false); \ - case KindOfBoolean: return HPHP::reverse(v2, GetBoolean(acc)); \ - case KindOfInt64: return HPHP::reverse(v2, GetInt64(acc)); \ - case KindOfDouble: return HPHP::reverse(v2, GetDouble(acc)); \ - case KindOfStaticString: \ - case KindOfString: return HPHP::reverse(v2, GetStringData(acc)); \ - case KindOfArray: return Array(GetArrayData(acc)).forward(v2); \ - case KindOfObject: return HPHP::reverse(v2, Object(GetObjectData(acc)));\ - default: \ - assert(false); \ - break; \ - } \ - return false; \ +#define UNWRAP_STRING(reverse) \ + auto const cell = asCell(); \ + switch (cell->m_type) { \ + case KindOfUninit: \ + case KindOfNull: return HPHP::reverse(v2, empty_string); \ + case KindOfBoolean: return HPHP::reverse(v2, !!cell->m_data.num); \ + case KindOfInt64: return HPHP::reverse(v2, cell->m_data.num); \ + case KindOfDouble: return HPHP::reverse(v2, cell->m_data.dbl); \ + case KindOfStaticString: \ + case KindOfString: return HPHP::reverse(v2, cell->m_data.pstr); \ + case KindOfArray: return HPHP::reverse(v2, s_array); \ + case KindOfObject: \ + return HPHP::reverse(v2, Object(cell->m_data.pobj).toString()); \ + default: \ + assert(false); \ + break; \ + } \ + return false; bool Variant::equalAsStr(bool v2) const { UNWRAP_STRING(equalAsStr);} bool Variant::equalAsStr(int v2) const { UNWRAP_STRING(equalAsStr);} diff --git a/hphp/runtime/base/type_variant.h b/hphp/runtime/base/type_variant.h index 9f44efd0e..68f7295a5 100644 --- a/hphp/runtime/base/type_variant.h +++ b/hphp/runtime/base/type_variant.h @@ -585,7 +585,6 @@ class Variant : private TypedValue { Variant &operator %= (int64_t n); Variant &operator %= (double n); - Variant operator ~ () const; Variant operator | (CVarRef v) const; Variant &operator |= (CVarRef v); Variant operator & (CVarRef v) const; @@ -600,6 +599,10 @@ class Variant : private TypedValue { Variant &operator -- (); Variant operator -- (int); + // 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(). */ @@ -987,65 +990,6 @@ class Variant : private TypedValue { const Cell* asCell() const { return tvToCell(asTypedValue()); } Cell* asCell() { return tvToCell(asTypedValue()); } - /** - * Based on the order in complex_types.h, TypedValue is defined before. - * TypedValue is binary compatible with Variant - */ - typedef struct TypedValue* TypedValueAccessor; - TypedValueAccessor getTypedAccessor() const { - const Variant *value = m_type == KindOfRef ? m_data.pref->var() : this; - return (TypedValueAccessor)value; - } - static DataType GetAccessorType(TypedValueAccessor acc) { - assert(acc); - return acc->m_type; - } - static bool GetBoolean(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfBoolean); - return acc->m_data.num; - } - static int64_t GetInt64(TypedValueAccessor acc) { - assert(acc); - assert(acc->m_type == KindOfInt64); - return acc->m_data.num; - } - static double GetDouble(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfDouble); - return acc->m_data.dbl; - } - static bool IsString(TypedValueAccessor acc) { - return IS_STRING_TYPE(acc->m_type); - } - static StringData *GetStringData(TypedValueAccessor acc) { - assert(acc && IS_STRING_TYPE(acc->m_type)); - return acc->m_data.pstr; - } - static ArrayData *GetArrayData(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfArray); - return acc->m_data.parr; - } - static ObjectData *GetObjectData(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfObject); - return acc->m_data.pobj; - } - static ObjectData *GetArrayAccess(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfObject); - ObjectData *obj = acc->m_data.pobj; - if (!obj->instanceof(SystemLib::s_ArrayAccessClass)) { - throw InvalidOperandException("not ArrayAccess objects"); - } - return obj; - } - static Array& GetAsArray(TypedValueAccessor acc) { - assert(acc && acc->m_type == KindOfArray); - return *reinterpret_cast(&acc->m_data.parr); - } - - static String& GetAsString(TypedValueAccessor acc) { - assert(IsString(acc)); - return *reinterpret_cast(&acc->m_data.pstr); - } - private: bool isPrimitive() const { return !IS_REFCOUNTED_TYPE(m_type); } bool isObjectConvertable() { @@ -1270,9 +1214,11 @@ public: return *const_cast(this); } operator Variant&() const { return m_var; } - Variant *operator&() const { return &m_var; } + Variant *operator&() const { return &m_var; } // FIXME Variant *operator->() const { return &m_var; } + Variant& wrapped() const { return m_var; } + explicit operator bool () const { return m_var.toBoolean();} operator int () const { return m_var.toInt32();} operator int64_t () const { return m_var.toInt64();} @@ -1316,9 +1262,6 @@ public: Variant array_iter_key() const { return m_var.array_iter_key(); } Variant array_iter_each() const { return m_var.array_iter_each(); } - Variant::TypedValueAccessor getTypedAccessor() const { - return m_var.getTypedAccessor(); - } private: mutable Variant m_var; }; diff --git a/hphp/runtime/base/util/string_buffer.cpp b/hphp/runtime/base/util/string_buffer.cpp index 1bf2a0836..a77ede845 100644 --- a/hphp/runtime/base/util/string_buffer.cpp +++ b/hphp/runtime/base/util/string_buffer.cpp @@ -177,12 +177,16 @@ void StringBuffer::append(int64_t n) { } void StringBuffer::append(CVarRef v) { - Variant::TypedValueAccessor tva = v.getTypedAccessor(); - if (Variant::IsString(tva)) { - append(Variant::GetAsString(tva)); - } else if (IS_INT_TYPE(Variant::GetAccessorType(tva))) { - append(Variant::GetInt64(tva)); - } else { + auto const cell = v.asCell(); + switch (cell->m_type) { + case KindOfStaticString: + case KindOfString: + append(cell->m_data.pstr); + break; + case KindOfInt64: + append(cell->m_data.num); + break; + default: append(v.toString()); } } diff --git a/hphp/runtime/base/variable_serializer.cpp b/hphp/runtime/base/variable_serializer.cpp index 9cf46853a..6cf6aa260 100644 --- a/hphp/runtime/base/variable_serializer.cpp +++ b/hphp/runtime/base/variable_serializer.cpp @@ -670,54 +670,60 @@ void VariableSerializer::writePropertyKey(CStrRef prop) { /* key MUST be a non-reference string or int */ void VariableSerializer::writeArrayKey(Variant key) { - Variant::TypedValueAccessor tva = key.getTypedAccessor(); - bool skey = Variant::IsString(tva); + auto const keyCell = key.asCell(); + bool const skey = IS_STRING_TYPE(keyCell->m_type); + if (skey && m_type == APCSerialize) { - write(Variant::GetAsString(tva)); + write(StrNR(keyCell->m_data.pstr).asString()); return; } ArrayInfo &info = m_arrayInfos.back(); + switch (m_type) { case DebuggerDump: case PrintR: { indent(); m_buf->append('['); if (info.is_object && skey) { - writePropertyKey(Variant::GetAsString(tva)); + writePropertyKey(keyCell->m_data.pstr); } else { m_buf->append(key); } m_buf->append("] => "); break; } + case VarExport: case PHPOutput: indent(); write(key, true); m_buf->append(" => "); break; + case VarDump: case DebugDump: indent(); m_buf->append('['); if (!skey) { - m_buf->append(Variant::GetInt64(tva)); + m_buf->append(keyCell->m_data.num); } else { m_buf->append('"'); if (info.is_object) { - writePropertyKey(Variant::GetAsString(tva)); + writePropertyKey(keyCell->m_data.pstr); } else { - m_buf->append(Variant::GetAsString(tva)); + m_buf->append(keyCell->m_data.pstr); m_buf->append('"'); } } m_buf->append("]=>\n"); break; + case APCSerialize: case Serialize: case DebuggerSerialize: write(key); break; + case JSON: if (!info.first_element) { m_buf->append(','); @@ -728,9 +734,9 @@ void VariableSerializer::writeArrayKey(Variant key) { } if (!info.is_vector) { if (skey) { - CStrRef s = Variant::GetAsString(tva); - const char *k = s.data(); - int len = s.size(); + auto const sdata = keyCell->m_data.pstr; + const char *k = sdata->data(); + int len = sdata->size(); if (info.is_object && !*k && len) { while (*++k) len--; k++; @@ -739,7 +745,7 @@ void VariableSerializer::writeArrayKey(Variant key) { write(k, len); } else { m_buf->append('"'); - m_buf->append(Variant::GetInt64(tva)); + m_buf->append(keyCell->m_data.num); m_buf->append('"'); } m_buf->append(':'); @@ -748,6 +754,7 @@ void VariableSerializer::writeArrayKey(Variant key) { } } break; + default: assert(false); break; diff --git a/hphp/runtime/ext/ext_array.cpp b/hphp/runtime/ext/ext_array.cpp index 5674d4723..3bd05977c 100644 --- a/hphp/runtime/ext/ext_array.cpp +++ b/hphp/runtime/ext/ext_array.cpp @@ -65,16 +65,15 @@ const int64_t k_UCOL_NUMERIC_COLLATION = UCOL_NUMERIC_COLLATION; using HPHP::Transl::CallerFrame; using HPHP::Transl::EagerCallerFrame; -#define getCheckedArrayRetType(input, fail, type) \ - Variant::TypedValueAccessor tva_##input = input.getTypedAccessor(); \ - if (UNLIKELY(Variant::GetAccessorType(tva_##input) != KindOfArray)) { \ - throw_bad_array_exception(); \ - return fail; \ - } \ - type arr_##input = Variant::GetAsArray(tva_##input); +#define getCheckedArrayRet(input, fail) \ + auto const cell_##input = static_cast(input).asCell(); \ + if (UNLIKELY(cell_##input->m_type != KindOfArray)) { \ + throw_bad_array_exception(); \ + return fail; \ + } \ + ArrNR arrNR_##input(cell_##input->m_data.parr); \ + CArrRef arr_##input = arrNR_##input.asArray(); -#define getCheckedArrayRet(input, fail) \ - getCheckedArrayRetType(input, fail, CArrRef) #define getCheckedArray(input) getCheckedArrayRet(input, uninit_null()) Variant f_array_change_key_case(CVarRef input, bool upper /* = false */) { @@ -191,12 +190,12 @@ Variant f_array_flip(CVarRef trans) { HOT_FUNC bool f_array_key_exists(CVarRef key, CVarRef search) { const ArrayData *ad; - Variant::TypedValueAccessor sacc = search.getTypedAccessor(); - DataType saccType = Variant::GetAccessorType(sacc); - if (LIKELY(saccType == KindOfArray)) { - ad = Variant::GetArrayData(sacc); - } else if (saccType == KindOfObject) { - ObjectData* obj = Variant::GetObjectData(sacc); + + auto const searchCell = search.asCell(); + if (LIKELY(searchCell->m_type == KindOfArray)) { + ad = searchCell->m_data.parr; + } else if (searchCell->m_type == KindOfObject) { + ObjectData* obj = searchCell->m_data.pobj; if (obj->isCollection()) { return collectionOffsetContains(obj, key); } @@ -206,19 +205,20 @@ bool f_array_key_exists(CVarRef key, CVarRef search) { "false returned."); return false; } - Variant::TypedValueAccessor kacc = key.getTypedAccessor(); - switch (Variant::GetAccessorType(kacc)) { + + auto const cell = key.asCell(); + switch (cell->m_type) { case KindOfString: case KindOfStaticString: { int64_t n = 0; - StringData *sd = Variant::GetStringData(kacc); + StringData *sd = cell->m_data.pstr; if (sd->isStrictlyInteger(n)) { return ad->exists(n); } return ad->exists(StrNR(sd)); } case KindOfInt64: - return ad->exists(Variant::GetInt64(kacc)); + return ad->exists(cell->m_data.num); case KindOfUninit: case KindOfNull: return ad->exists(empty_string); @@ -445,7 +445,18 @@ Variant f_array_product(CVarRef array) { } Variant f_array_push(int _argc, VRefParam array, CVarRef var, CArrRef _argv /* = null_array */) { - getCheckedArrayRetType(array, uninit_null(), Array &); + auto const array_cell = array.wrapped().asCell(); + if (UNLIKELY(array_cell->m_type != KindOfArray)) { + throw_bad_array_exception(); + return uninit_null(); + } + + /* + * Important note: this *must* cast the parr in the inner cell to + * the Array&---we can't copy it to the stack or anything because we + * might escalate. + */ + Array& arr_array = *reinterpret_cast(&array_cell->m_data.parr); arr_array.append(var); for (ArrayIter iter(_argv); iter; ++iter) { arr_array.append(iter.second()); @@ -1086,7 +1097,7 @@ class ArraySortTmp { static bool php_sort(VRefParam array, int sort_flags, bool ascending, bool use_collator) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); if (use_collator && sort_flags != SORT_LOCALE_STRING) { UCollator *coll = s_collator->getCollator(); if (coll) { @@ -1114,7 +1125,7 @@ php_sort(VRefParam array, int sort_flags, bool ascending, bool use_collator) { static bool php_asort(VRefParam array, int sort_flags, bool ascending, bool use_collator) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); if (use_collator && sort_flags != SORT_LOCALE_STRING) { UCollator *coll = s_collator->getCollator(); if (coll) { @@ -1142,7 +1153,7 @@ php_asort(VRefParam array, int sort_flags, bool ascending, bool use_collator) { static bool php_ksort(VRefParam array, int sort_flags, bool ascending) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); ArraySortTmp ast(arr_array); ast->ksort(sort_flags, ascending); return true; @@ -1201,7 +1212,7 @@ Variant f_natcasesort(VRefParam array) { bool f_usort(VRefParam array, CVarRef cmp_function) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); ArraySortTmp ast(arr_array); ast->usort(cmp_function); return true; @@ -1220,7 +1231,7 @@ bool f_usort(VRefParam array, CVarRef cmp_function) { bool f_uasort(VRefParam array, CVarRef cmp_function) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); ArraySortTmp ast(arr_array); ast->uasort(cmp_function); return true; @@ -1239,7 +1250,7 @@ bool f_uasort(VRefParam array, CVarRef cmp_function) { bool f_uksort(VRefParam array, CVarRef cmp_function) { if (array.isArray()) { - Array& arr_array = Variant::GetAsArray(array.getTypedAccessor()); + Array& arr_array = array.wrapped().toArrRef(); ArraySortTmp ast(arr_array); ast->uksort(cmp_function); return true; @@ -1273,8 +1284,8 @@ bool f_array_multisort(int _argc, VRefParam ar1, bool ascending = true; for (int i = 0; i < _argv.size(); i++) { Variant *v = &((Array&)_argv).lvalAt(i); - Variant::TypedValueAccessor tva = v->getTypedAccessor(); - if (Variant::GetAccessorType(tva) == KindOfArray) { + auto const cell = v->asCell(); + if (cell->m_type == KindOfArray) { sd.cmp_func = get_cmp_func(sort_flags, ascending); data.push_back(sd); @@ -1282,7 +1293,7 @@ bool f_array_multisort(int _argc, VRefParam ar1, ascending = true; sd.original = v; - arrays.push_back(Variant::GetAsArray(tva)); + arrays.push_back(Array(cell->m_data.parr)); sd.array = &arrays.back(); } else { int n = v->toInt32(); diff --git a/hphp/runtime/ext/ext_function.cpp b/hphp/runtime/ext/ext_function.cpp index 24959f51a..03e7c2e46 100644 --- a/hphp/runtime/ext/ext_function.cpp +++ b/hphp/runtime/ext/ext_function.cpp @@ -74,14 +74,14 @@ bool f_is_callable(CVarRef v, bool syntax /* = false */, if (!name.isReferenced()) return ret; } - Variant::TypedValueAccessor tv_func = v.getTypedAccessor(); - if (Variant::IsString(tv_func)) { - if (name.isReferenced()) name = Variant::GetStringData(tv_func); + auto const tv_func = v.asCell(); + if (IS_STRING_TYPE(tv_func->m_type)) { + if (name.isReferenced()) name = tv_func->m_data.pstr; return ret; } - if (Variant::GetAccessorType(tv_func) == KindOfArray) { - CArrRef arr = Variant::GetAsArray(tv_func); + if (tv_func->m_type == KindOfArray) { + CArrRef arr = tv_func->m_data.parr; CVarRef clsname = arr.rvalAtRef(int64_t(0)); CVarRef mthname = arr.rvalAtRef(int64_t(1)); if (arr.size() != 2 || @@ -91,28 +91,28 @@ bool f_is_callable(CVarRef v, bool syntax /* = false */, return false; } - Variant::TypedValueAccessor tv_meth = mthname.getTypedAccessor(); - if (!Variant::IsString(tv_meth)) { + auto const tv_meth = mthname.asCell(); + if (!IS_STRING_TYPE(tv_meth->m_type)) { if (name.isReferenced()) name = v.toString(); return false; } - Variant::TypedValueAccessor tv_cls = clsname.getTypedAccessor(); - if (Variant::GetAccessorType(tv_cls) == KindOfObject) { - name = Variant::GetObjectData(tv_cls)->o_getClassName(); - } else if (Variant::IsString(tv_cls)) { - name = Variant::GetStringData(tv_cls); + auto const tv_cls = clsname.asCell(); + if (tv_cls->m_type == KindOfObject) { + name = tv_cls->m_data.pobj->o_getClassName(); + } else if (IS_STRING_TYPE(tv_cls->m_type)) { + name = tv_cls->m_data.pstr; } else { name = v.toString(); return false; } - name = concat3(name, s_colon2, Variant::GetAsString(tv_meth)); + name = concat3(name, s_colon2, tv_meth->m_data.pstr); return ret; } - if (Variant::GetAccessorType(tv_func) == KindOfObject) { - ObjectData *d = Variant::GetObjectData(tv_func); + if (tv_func->m_type == KindOfObject) { + ObjectData *d = tv_func->m_data.pobj; const Func* invoke = d->getVMClass()->lookupMethod(s__invoke.get()); if (name.isReferenced()) { if (d->instanceof(c_Closure::s_cls)) { diff --git a/hphp/runtime/ext/ext_misc.cpp b/hphp/runtime/ext/ext_misc.cpp index 9cac86783..71a73373a 100644 --- a/hphp/runtime/ext/ext_misc.cpp +++ b/hphp/runtime/ext/ext_misc.cpp @@ -136,7 +136,7 @@ bool f_define(CStrRef name, CVarRef value, if (case_insensitive) { raise_warning(Strings::CONSTANTS_CASE_SENSITIVE); } - return Unit::defCns(name.get(), value.getTypedAccessor()); + return Unit::defCns(name.get(), value.asCell()); } bool f_defined(CStrRef name, bool autoload /* = true */) { diff --git a/hphp/runtime/ext/ext_string.cpp b/hphp/runtime/ext/ext_string.cpp index cb386db33..174f7c30e 100644 --- a/hphp/runtime/ext/ext_string.cpp +++ b/hphp/runtime/ext/ext_string.cpp @@ -667,11 +667,11 @@ Variant f_strcspn(CStrRef str1, CStrRef str2, int start /* = 0 */, } Variant f_strlen(CVarRef vstr) { - Variant::TypedValueAccessor tva = vstr.getTypedAccessor(); - switch (Variant::GetAccessorType(tva)) { + auto const cell = vstr.asCell(); + switch (cell->m_type) { case KindOfString: case KindOfStaticString: - return Variant(Variant::GetStringData(tva)->size()); + return Variant(cell->m_data.pstr->size()); case KindOfArray: raise_warning("strlen() expects parameter 1 to be string, array given"); return uninit_null(); diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index abddcdaba..8dd104ba3 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -4185,7 +4185,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopBitNot(PC& pc) { c1->m_type = KindOfInt64; c1->m_data.num = ~int64_t(c1->m_data.dbl); } else if (IS_STRING_TYPE(c1->m_type)) { - tvCellAsVariant(c1) = ~tvCellAsVariant(c1); + tvCellAsVariant(c1) = tvCellAsVariant(c1).bitNot(); } else { raise_error("Unsupported operand type for ~"); }