diff --git a/hphp/hhvm/externals_stubs.cpp b/hphp/hhvm/externals_stubs.cpp deleted file mode 100644 index dbff9ad95..000000000 --- a/hphp/hhvm/externals_stubs.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | HipHop for PHP | - +----------------------------------------------------------------------+ - | Copyright (c) 2010- 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 "runtime/eval/eval.h" -#include "runtime/base/externals.h" - -/* - * HHVM's stubs for various hphpc-style externals.h functions. - * - * These exist for legacy reasons---much of the runtime assumed - * generated versions of some of these functions would exist (as - * output from hphpc). - * - * In the VM, we still fake a few of them while phasing this out. - */ - -namespace HPHP { - -////////////////////////////////////////////////////////////////////// - -Object create_object_only(CStrRef s, ObjectData* root /* = NULL*/) { - ObjectData *obj = eval_create_object_only_hook(s, root); - if (UNLIKELY(!obj)) throw_missing_class(s); - Object r = obj; - obj->init(); - return r; -} - -////////////////////////////////////////////////////////////////////// - -} diff --git a/hphp/runtime/base/builtin_functions.cpp b/hphp/runtime/base/builtin_functions.cpp index 4e13d4617..04a000dfb 100644 --- a/hphp/runtime/base/builtin_functions.cpp +++ b/hphp/runtime/base/builtin_functions.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -519,12 +518,12 @@ void check_collection_cast_to_array() { } } -Object create_object(CStrRef s, CArrRef params, bool init /* = true */, - ObjectData *root /* = NULL */) { - assert_not_implemented(root == nullptr); - const StringData* className = StringData::GetStaticString(s.get()); - Object o = g_vmContext->createObject((StringData*)className, params, init); - return o; +Object create_object_only(CStrRef s) { + return g_vmContext->createObjectOnly(s.get()); +} + +Object create_object(CStrRef s, CArrRef params, bool init /* = true */) { + return g_vmContext->createObject(s.get(), params, init); } /* diff --git a/hphp/runtime/base/builtin_functions.h b/hphp/runtime/base/builtin_functions.h index 674c99a6b..0bd60d84b 100644 --- a/hphp/runtime/base/builtin_functions.h +++ b/hphp/runtime/base/builtin_functions.h @@ -405,6 +405,9 @@ void check_collection_compare(ObjectData* obj); void check_collection_compare(ObjectData* obj1, ObjectData* obj2); void check_collection_cast_to_array(); +Object create_object_only(CStrRef s); +Object create_object(CStrRef s, const Array ¶ms, bool init = true); + /** * Argument count handling. * - When level is 2, it's from constructors that turn these into fatals diff --git a/hphp/runtime/base/externals.h b/hphp/runtime/base/externals.h index df3c63058..9b1084bd7 100644 --- a/hphp/runtime/base/externals.h +++ b/hphp/runtime/base/externals.h @@ -52,20 +52,6 @@ extern Variant get_class_var_init(CStrRef s, const char *var); * Class/function meta info entirely encoded here as a const char * array. */ extern const char *g_class_map[]; -#if 0 -extern const char *g_source_root; -extern const char *g_source_info[]; -extern const char *g_source_cls2file[]; -extern const char *g_source_func2file[]; -extern const char *g_paramrtti_map[]; -#endif - -/** - * Dynamically create an object. - */ -Object create_object(CStrRef s, const Array ¶ms, - bool init = true, ObjectData *root = nullptr); -extern Object create_object_only(CStrRef s, ObjectData *root = nullptr); /** * Returns a thread local global variable class pointer. diff --git a/hphp/runtime/base/hphp.h b/hphp/runtime/base/hphp.h index b47aeda9f..0927911c4 100644 --- a/hphp/runtime/base/hphp.h +++ b/hphp/runtime/base/hphp.h @@ -29,7 +29,6 @@ #include #include #include -#include /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/base/object_data.cpp b/hphp/runtime/base/object_data.cpp index 3c1035f8a..a8c4712ed 100644 --- a/hphp/runtime/base/object_data.cpp +++ b/hphp/runtime/base/object_data.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -66,13 +67,26 @@ bool ObjectData::instanceof(const HPHP::VM::Class* c) const { HOT_FUNC void ObjectData::destruct() { + if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) { + assert(RuntimeOption::EnableObjDestructCall); + g_vmContext->m_liveBCObjs.erase(this); + } if (!noDestruct()) { setNoDestruct(); - CountableHelper h(this); - try { - t___destruct(); - } catch (...) { - handle_destructor_exception(); + if (auto meth = m_cls->getDtor()) { + // We raise the refcount around the call to __destruct(). This is to + // prevent the refcount from going to zero when the destructor returns. + CountableHelper h(this); + TypedValue retval; + tvWriteNull(&retval); + try { + // Call the destructor method + g_vmContext->invokeFunc(&retval, meth, null_array, this); + } catch (...) { + // Swallow any exceptions that escape the __destruct method + handle_destructor_exception(); + } + tvRefcountedDecRef(&retval); } } } @@ -405,14 +419,6 @@ Variant ObjectData::o_setPublicRef(CStrRef propName, CVarRef v) { return o_setPublicImpl(propName, strongBind(v), false); } -Variant ObjectData::o_setPublicWithRef(CStrRef propName, CVarRef v) { - return o_setPublicImpl(propName, withRefBind(v), false); -} - -Variant ObjectData::o_i_set(CStrRef propName, CVarRef v) { - return o_setPublicImpl(propName, v, true); -} - Variant ObjectData::o_i_setPublicWithRef(CStrRef propName, CVarRef v) { return o_setPublicImpl(propName, withRefBind(v), true); } @@ -440,15 +446,6 @@ void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const { } } -Variant ObjectData::o_argval(bool byRef, CStrRef s, - bool error /* = true */, CStrRef context /* = null_string */) { - if (byRef) { - return strongBind(o_lval(s, context)); - } else { - return o_get(s, error, context); - } -} - Object ObjectData::FromArray(ArrayData *properties) { ObjectData *ret = SystemLib::AllocStdClassObject(); if (!properties->empty()) { @@ -514,114 +511,81 @@ Array ObjectData::o_toArray() const { Array ObjectData::o_toIterArray(CStrRef context, bool getRef /* = false */) { - CStrRef object_class = o_getClassName(); - const ClassInfo *classInfo = ClassInfo::FindClass(object_class); - const ClassInfo *contextClassInfo = nullptr; - int category; - - if (!classInfo) { - return Array::Create(); + size_t size = m_cls->m_declPropNumAccessible + + (o_properties.get() ? o_properties.get()->size() : 0); + HphpArray* retval = NEW(HphpArray)(size); + VM::Class* ctx = nullptr; + if (!context.empty()) { + ctx = VM::Unit::lookupClass(context.get()); } - Array ret(Array::Create()); + // Get all declared properties first, bottom-to-top in the inheritance + // hierarchy, in declaration order. + const VM::Class* klass = m_cls; + while (klass != nullptr) { + const VM::PreClass::Prop* props = klass->m_preClass->properties(); + const size_t numProps = klass->m_preClass->numProperties(); - // There are 3 cases: - // (1) called from standalone function (this_object == null) or - // the object class is not related to the context class; - // (2) the object class is a subclass of the context class or vice versa. - // (3) the object class is the same as the context class - // For (1), only public properties of the object are accessible. - // For (2) and (3), the public/protected properties of the object are - // accessible; - // any property of the context class is also accessible unless it is - // overriden by the object class. (3) is really just an optimization. - if (context.empty()) { // null_string is also empty - category = 1; - } else { - contextClassInfo = ClassInfo::FindClass(context); - assert(contextClassInfo); - if (object_class->isame(context.get())) { - category = 3; - } else if (classInfo->derivesFrom(context, false) || - contextClassInfo->derivesFrom(object_class, false)) { - category = 2; - } else { - category = 1; - } - } - - ClassInfo::PropertyVec properties; - classInfo->getAllProperties(properties); - ClassInfo::PropertyMap contextProperties; - if (category == 2) { - contextClassInfo->getAllProperties(contextProperties); - } - Array dynamics = o_getDynamicProperties(); - for (unsigned int i = 0; i < properties.size(); i++) { - ClassInfo::PropertyInfo *prop = properties[i]; - if (prop->attribute & ClassInfo::IsStatic) continue; - - bool visible = false; - switch (category) { - case 1: - visible = (prop->attribute & ClassInfo::IsPublic); - break; - case 2: - if ((prop->attribute & ClassInfo::IsPrivate) == 0) { - visible = true; - } else { - ClassInfo::PropertyMap::const_iterator iterProp = - contextProperties.find(prop->name); - if (iterProp != contextProperties.end() && - iterProp->second->owner == contextClassInfo) { - visible = true; + for (size_t i = 0; i < numProps; ++i) { + auto key = const_cast(props[i].name()); + bool visible, accessible, unset; + TypedValue* val = ((VM::Instance*)this)->getProp( + ctx, key, visible, accessible, unset); + if (accessible && val->m_type != KindOfUninit && !unset) { + if (getRef) { + if (val->m_type != KindOfRef) { + tvBox(val); + } + retval->nvBind(key, val); } else { - visible = false; + retval->nvSet(key, val, false); } } - break; - case 3: - if ((prop->attribute & ClassInfo::IsPrivate) == 0 || - prop->owner == classInfo) { - visible = true; - } - break; - default: - assert(false); } - if (visible && o_propForIteration(prop->name, context)) { - if (getRef) { - Variant tmp; - Variant &ov = o_lval(prop->name, tmp, context); - Variant &av = ret.lvalAt(prop->name, AccessFlags::Key); - av.assignRef(ov); - } else { - ret.set(prop->name, o_getUnchecked(prop->name, - prop->owner->getName())); - } - } - dynamics.remove(prop->name); + klass = klass->m_parent.get(); } - if (!dynamics.empty()) { - if (getRef) { - for (ArrayIter iter(o_getDynamicProperties()); iter; ++iter) { - // Object property names are always strings. - String key = iter.first().toString(); - if (dynamics->exists(key)) { - CVarRef value = iter.secondRef(); - Variant &av = ret.lvalAt(key, AccessFlags::Key); - av.assignRef(value); - } - } - } else { - ret += dynamics; - } - } - return ret; -} -Array ObjectData::o_getDynamicProperties() const { - return o_properties; + // Now get dynamic properties. + if (o_properties.get()) { + ssize_t iter = o_properties.get()->iter_begin(); + while (iter != HphpArray::ElmIndEmpty) { + TypedValue key; + static_cast(o_properties.get())->nvGetKey(&key, iter); + iter = o_properties.get()->iter_advance(iter); + + // You can get this if you cast an array to object. These properties must + // be dynamic because you can't declare a property with a non-string name. + if (UNLIKELY(!IS_STRING_TYPE(key.m_type))) { + assert(key.m_type == KindOfInt64); + TypedValue* val = + static_cast(o_properties.get())->nvGet(key.m_data.num); + if (getRef) { + if (val->m_type != KindOfRef) { + tvBox(val); + } + retval->nvBind(key.m_data.num, val); + } else { + retval->nvSet(key.m_data.num, val, false); + } + continue; + } + + StringData* strKey = key.m_data.pstr; + TypedValue* val = + static_cast(o_properties.get())->nvGet(strKey); + if (getRef) { + if (val->m_type != KindOfRef) { + tvBox(val); + } + retval->nvBind(strKey, val); + } else { + retval->nvSet(strKey, val, false); + } + decRefStr(strKey); + } + } + + return Array(retval); } Variant ObjectData::o_invoke(CStrRef s, CArrRef params, @@ -747,11 +711,6 @@ Variant ObjectData::o_invoke_ex(CStrRef clsname, CStrRef s, return ret; } -Variant ObjectData::o_throw_fatal(const char *msg) { - throw_fatal(msg); - return null; -} - bool ObjectData::php_sleep(Variant &ret) { setAttribute(HasSleep); ret = t___sleep(); @@ -900,10 +859,6 @@ ObjectData *ObjectData::clone() { return instance->cloneImpl(); } -void ObjectData::cloneDynamic(ObjectData *orig) { - o_properties.asArray() = orig->o_properties; -} - Variant ObjectData::o_getError(CStrRef prop, CStrRef context) { raise_notice("Undefined property: %s::$%s", o_getClassName().data(), prop.data()); @@ -914,52 +869,6 @@ Variant ObjectData::o_setError(CStrRef prop, CStrRef context) { return null; } -bool ObjectData::o_isset(CStrRef prop, CStrRef context) { - if (Variant *t = o_realProp(prop, 0, context)) { - if (t->isInitialized()) { - return !t->isNull(); - } - } - if (getAttribute(UseIsset)) { - AttributeClearer a(UseIsset, this); - return t___isset(prop); - } - return false; -} - -bool ObjectData::o_empty(CStrRef prop, CStrRef context) { - if (Variant *t = o_realProp(prop, 0, context)) { - if (t->isInitialized()) { - return empty(*t); - } - } - if (getAttribute(UseIsset)) { - { - AttributeClearer a(UseIsset, this); - if (!t___isset(prop) || !getAttribute(UseGet)) { - return true; - } - } - AttributeClearer a(UseGet, this); - return empty(t___get(prop)); - } - return true; -} - -void ObjectData::o_unset(CStrRef prop, CStrRef context) { - if (Variant *t = o_realProp(prop, - RealPropWrite|RealPropNoDynamic, context)) { - unset(*t); - } else if (o_properties.asArray().exists(prop, true)) { - o_properties.asArray().weakRemove(prop, true); - } else if (UNLIKELY(!*prop.data())) { - throw_invalid_property_name(prop); - } else if (getAttribute(UseUnset)) { - AttributeClearer a(UseUnset, this); - t___unset(prop); - } -} - /////////////////////////////////////////////////////////////////////////////// // magic methods that user classes can override, and these are default handlers // or actions to take: @@ -988,17 +897,17 @@ Variant *ObjectData::___lval(Variant v_name) { return nullptr; } -Variant& ObjectData::___offsetget_lval(Variant key) { - if (isCollection()) { - return collectionOffsetGet(this, key); - } else { - if (!instanceof(SystemLib::s_ArrayAccessClass)) { - throw InvalidOperandException("not ArrayAccess objects"); - } - Variant &v = get_system_globals()->__lvalProxy; - v = o_invoke_few_args(s_offsetGet, -1, 1, key); - return v; +Variant ObjectData::offsetGet(Variant key) { + assert(instanceof(SystemLib::s_ArrayAccessClass)); + const VM::Func* method = m_cls->lookupMethod(s_offsetGet.get()); + assert(method); + if (!method) { + return null; } + Variant v; + g_vmContext->invokeFunc((TypedValue*)(&v), method, + CREATE_VECTOR1(key), this); + return v; } bool ObjectData::t___isset(Variant v_name) { @@ -1015,12 +924,6 @@ bool ObjectData::o_propExists(CStrRef s, CStrRef context /* = null_string */) { return t; } -bool ObjectData::o_propForIteration(CStrRef s, - CStrRef context /* = null_string */) { - Variant *t = o_realProp(s, 0, context); - return t && t->isInitialized(); -} - Variant ObjectData::t___sleep() { clearAttribute(HasSleep); return null; diff --git a/hphp/runtime/base/object_data.h b/hphp/runtime/base/object_data.h index 20681a521..a2004daa7 100644 --- a/hphp/runtime/base/object_data.h +++ b/hphp/runtime/base/object_data.h @@ -146,7 +146,6 @@ class ObjectData : public CountableNF { * false for classes that are descendents of ResourceData. */ bool o_instanceof(CStrRef s) const; - virtual ObjectData *getRedeclaredParent() const { return 0; } // class info CStrRef o_getClassName() const; @@ -162,15 +161,16 @@ class ObjectData : public CountableNF { virtual int64_t o_toInt64() const; virtual double o_toDouble() const { return o_toInt64();} - void setDummy(); - - virtual void init() {} - virtual void destruct(); + void destruct(); // properties virtual Array o_toArray() const; - virtual Array o_toIterArray(CStrRef context, bool getRef = false); - virtual Array o_getDynamicProperties() const; + Array o_toIterArray(CStrRef context, bool getRef = false); + + Array o_getDynamicProperties() const { + return o_properties; + } + Variant *o_realProp(CStrRef s, int flags, CStrRef context = null_string) const; void *o_realPropTyped(CStrRef s, int flags, @@ -182,7 +182,6 @@ class ObjectData : public CountableNF { Variant o_getPublic(CStrRef s, bool error = true); Variant o_getUnchecked(CStrRef s, CStrRef context = null_string); - Variant o_i_set(CStrRef s, CVarRef v); Variant o_i_setPublicWithRef(CStrRef s, CVarRef v); Variant o_set(CStrRef s, CVarRef v); @@ -195,24 +194,16 @@ class ObjectData : public CountableNF { Variant o_setPublic(CStrRef s, CVarRef v); Variant o_setPublic(CStrRef s, RefResult v); Variant o_setPublicRef(CStrRef s, CVarRef v); - Variant o_setPublicWithRef(CStrRef s, CVarRef v); Variant &o_lval(CStrRef s, CVarRef tmpForGet, CStrRef context = null_string); - Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet, - CStrRef context = null_string) { - return o_lval(s, tmpForGet, context); - } Variant *o_weakLval(CStrRef s, CStrRef context = null_string); virtual void o_setArray(CArrRef properties); virtual void o_getArray(Array &props, bool pubOnly = false) const; - void o_set(const Array properties); - Variant o_argval(bool byRef, CStrRef s, bool error = true, - CStrRef context = null_string); - virtual Variant o_getError(CStrRef prop, CStrRef context); - virtual Variant o_setError(CStrRef prop, CStrRef context); + Variant o_getError(CStrRef prop, CStrRef context); + Variant o_setError(CStrRef prop, CStrRef context); /** * This is different from o_exists(), which is isset() semantics. This one * is property_exists() semantics. ie, accessibility is ignored, and declared @@ -220,12 +211,6 @@ class ObjectData : public CountableNF { */ bool o_propExists(CStrRef s, CStrRef context = null_string); - /** - * This is different from o_exists(), which is isset() semantics; this one - * returns true even if the property is set to null. - */ - bool o_propForIteration(CStrRef s, CStrRef context = null_string); - static Object FromArray(ArrayData *properties); CVarRef set(CStrRef s, CVarRef v); @@ -241,16 +226,13 @@ class ObjectData : public CountableNF { INVOKE_FEW_ARGS_DECL_ARGS); // misc - Variant o_throw_fatal(const char *msg); void serialize(VariableSerializer *serializer) const; virtual void serializeImpl(VariableSerializer *serializer) const; bool hasInternalReference(PointerSet &vars, bool ds = false) const; virtual void dump() const; virtual ObjectData *clone(); - bool o_isset(CStrRef prop, CStrRef context = null_string); - bool o_empty(CStrRef prop, CStrRef context = null_string); - void o_unset(CStrRef prop, CStrRef context = null_string); + Variant offsetGet(Variant key); // magic methods // __construct is handled in a special way @@ -259,7 +241,6 @@ class ObjectData : public CountableNF { virtual Variant t___set(Variant v_name, Variant v_value); virtual Variant t___get(Variant v_name); virtual Variant *___lval(Variant v_name); - virtual Variant &___offsetget_lval(Variant key); virtual bool t___isset(Variant v_name); virtual Variant t___unset(Variant v_name); virtual Variant t___sleep(); @@ -267,13 +248,10 @@ class ObjectData : public CountableNF { virtual String t___tostring(); virtual Variant t___clone(); - template - T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string); - static int GetMaxId() ATTRIBUTE_COLD; protected: virtual bool php_sleep(Variant &ret); -public: + public: CArrRef getProperties() const { return o_properties; } void initProperties(int nProp); private: @@ -307,9 +285,6 @@ public: ArrNR o_properties; // dynamic properties (VM and hphpc) int o_id; // a numeric identifier of this object - protected: - void cloneDynamic(ObjectData *orig); - private: static void compileTimeAssertions() { static_assert(offsetof(ObjectData, _count) == FAST_REFCOUNT_OFFSET, diff --git a/hphp/runtime/base/resource_data.h b/hphp/runtime/base/resource_data.h index 295534480..157ac481d 100644 --- a/hphp/runtime/base/resource_data.h +++ b/hphp/runtime/base/resource_data.h @@ -35,7 +35,6 @@ public: void operator delete(void* p) { ::operator delete(p); } // implementing ObjectData - virtual bool o_instanceof(CStrRef s) const { return false;} virtual bool isResource() const { return true;} virtual String t___tostring(); virtual int64_t o_toInt64() const { return o_getId();} diff --git a/hphp/runtime/base/shared/immutable_obj.cpp b/hphp/runtime/base/shared/immutable_obj.cpp index c67827d0a..2ccb15f8e 100644 --- a/hphp/runtime/base/shared/immutable_obj.cpp +++ b/hphp/runtime/base/shared/immutable_obj.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include diff --git a/hphp/runtime/base/type_object.cpp b/hphp/runtime/base/type_object.cpp index eedc61212..3bc80bbc0 100644 --- a/hphp/runtime/base/type_object.cpp +++ b/hphp/runtime/base/type_object.cpp @@ -164,40 +164,6 @@ Variant &Object::o_lval(CStrRef propName, CVarRef tmpForGet, return m_px->o_lval(propName, tmpForGet, context); } -Variant &Object::o_unsetLval(CStrRef propName, CVarRef tmpForGet, - CStrRef context /* = null_string */) { - if (!m_px) { - return const_cast(tmpForGet); - } - return m_px->o_lval(propName, tmpForGet, context); -} - -bool Object::o_isset(CStrRef propName, - CStrRef context /* = null_string */) const { - if (!m_px) return false; - return m_px->o_isset(propName, context); -} - -bool Object::o_empty(CStrRef propName, - CStrRef context /* = null_string */) const { - if (!m_px) return true; - return m_px->o_empty(propName, context); -} - -void Object::o_unset(CStrRef propName, - CStrRef context /* = null_string */) const { - if (m_px) m_px->o_unset(propName, context); -} - -Variant Object::o_argval(bool byRef, CStrRef propName, - bool error /* = true */, CStrRef context /* = null_string */) { - if (!byRef) { - return o_get(propName, error, context); - } else { - return strongBind(o_lval(propName, context)); - } -} - /////////////////////////////////////////////////////////////////////////////// // output diff --git a/hphp/runtime/base/type_object.h b/hphp/runtime/base/type_object.h index b3b77fd87..266b2c6f0 100644 --- a/hphp/runtime/base/type_object.h +++ b/hphp/runtime/base/type_object.h @@ -127,21 +127,17 @@ public: } return nullptr; } - while (true) { - T *px = dynamic_cast(cur); - if (!px) { - cur = cur->getRedeclaredParent(); - if (cur) continue; - if (!badTypeOkay) { - throw InvalidObjectTypeException(m_px->o_getClassName()); - } - return nullptr; + T *px = dynamic_cast(cur); + if (!px) { + if (!badTypeOkay) { + throw InvalidObjectTypeException(m_px->o_getClassName()); } - - // Assert that casting does not adjust the 'this' pointer - assert((void*)px == (void*)cur); - return px; + return nullptr; } + + // Assert that casting does not adjust the 'this' pointer + assert((void*)px == (void*)cur); + return px; } template bool is() const { @@ -196,15 +192,6 @@ public: Variant o_setPublicRef(CStrRef s, CVarRef v); Variant &o_lval(CStrRef propName, CVarRef tmpForGet, CStrRef context = null_string); - Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet, - CStrRef context = null_string); - bool o_isset(CStrRef propName, CStrRef context = null_string) const; - bool o_empty(CStrRef propName, CStrRef context = null_string) const; - void o_unset(CStrRef propName, CStrRef context = null_string) const; - template - T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string); - Variant o_argval(bool byRef, CStrRef propName, bool error = true, - CStrRef context = null_string); /** * Input/Output */ diff --git a/hphp/runtime/base/type_variant.cpp b/hphp/runtime/base/type_variant.cpp index d769ff4f6..7a8bcda05 100644 --- a/hphp/runtime/base/type_variant.cpp +++ b/hphp/runtime/base/type_variant.cpp @@ -2262,6 +2262,8 @@ public: static const bool CheckParams = true; }; +DECLARE_THREAD_LOCAL(Variant, __lvalProxy); + template Variant& Variant::LvalAtImpl0( Variant *self, T key, Variant *tmp, bool blackHole, ACCESSPARAMS_IMPL) { @@ -2303,12 +2305,13 @@ head: if (self->m_data.pobj->isCollection()) { return collectionOffsetGet(self->m_data.pobj, Variant(key)); } - Variant *ret = &(self->getArrayAccess()->___offsetget_lval(key)); if (!blackHole) { - *tmp = *ret; - ret = tmp; + *tmp = self->getArrayAccess()->offsetGet(key); + return *tmp; } - return *ret; + Variant& retv = *(__lvalProxy.get()); + retv = self->getArrayAccess()->offsetGet(key); + return retv; } return lvalInvalid(); } @@ -2432,7 +2435,7 @@ Variant &Variant::lvalInvalid() { } Variant &Variant::lvalBlackHole() { - Variant &bh = get_system_globals()->__lvalProxy; + Variant &bh = *(__lvalProxy.get()); bh.unset(); return bh; } @@ -2460,57 +2463,6 @@ Variant Variant::o_getPublic(CStrRef propName, bool error /* = true */) const { return null_variant; } -bool Variant::o_empty(CStrRef propName, - CStrRef context /* = null_string */) const { - if (m_type == KindOfObject) { - return m_data.pobj->o_empty(propName, context); - } - if (m_type == KindOfRef) { - return m_data.pref->var()->o_empty(propName, context); - } - return true; -} - -bool Variant::o_isset(CStrRef propName, - CStrRef context /* = null_string */) const { - if (m_type == KindOfObject) { - return m_data.pobj->o_isset(propName, context); - } - if (m_type == KindOfRef) { - return m_data.pref->var()->o_isset(propName, context); - } - return false; -} - -void Variant::o_unset(CStrRef propName, CStrRef context /* = null_string */) { - if (m_type == KindOfObject) { - m_data.pobj->o_unset(propName, context); - } - if (m_type == KindOfRef) { - m_data.pref->var()->o_unset(propName, context); - } -} - -Variant Variant::o_argval(bool byRef, CStrRef propName, - bool error /* = true */, CStrRef context /* = null_string */) const { - if (m_type == KindOfObject) { - if (byRef) { - return strongBind(m_data.pobj->o_lval(propName, context)); - } else { - return m_data.pobj->o_get(propName, error, context); - } - } else if (m_type == KindOfRef) { - if (byRef) { - return strongBind(m_data.pref->var()->o_lval(propName, context)); - } else { - return m_data.pref->var()->o_get(propName, error, context); - } - } else if (error) { - raise_notice("Trying to get property of non-object"); - } - return null_variant; -} - Variant Variant::o_set(CStrRef propName, CVarRef val, CStrRef context /* = null_string */) { if (m_type == KindOfObject) { @@ -2629,91 +2581,6 @@ Variant &Variant::o_lval(CStrRef propName, CVarRef tmpForGet, } } -Variant &Variant::o_unsetLval(CStrRef propName, CVarRef tmpForGet, - CStrRef context /* = null_string */) { - if (m_type == KindOfObject) { - return m_data.pobj->o_lval(propName, tmpForGet, context); - } else if (m_type == KindOfRef) { - return m_data.pref->var()->o_unsetLval(propName, tmpForGet, context); - } else { - return const_cast(tmpForGet); - } -} - -#define OPEQUAL(op, l, r) \ - switch (op) { \ - case T_CONCAT_EQUAL: concat_assign((l), r); break; \ - case T_PLUS_EQUAL: ((l) += r); break; \ - case T_MINUS_EQUAL: ((l) -= r); break; \ - case T_MUL_EQUAL: ((l) *= r); break; \ - case T_DIV_EQUAL: ((l) /= r); break; \ - case T_MOD_EQUAL: ((l) %= r); break; \ - case T_AND_EQUAL: ((l) &= r); break; \ - case T_OR_EQUAL: ((l) |= r); break; \ - case T_XOR_EQUAL: ((l) ^= r); break; \ - case T_SL_EQUAL: ((l) <<= r); break; \ - case T_SR_EQUAL: ((l) >>= r); break; \ - default: \ - throw FatalErrorException(0, "invalid operator %d", op); \ - } \ - -#define IMPLEMENT_SETAT_OPEQUAL \ -check_array: \ - if (m_type == KindOfArray) { \ - Variant *cv = nullptr; \ - ArrayData *escalated = \ - m_data.parr->lval(ToKey(key), cv, (m_data.parr->getCount() > 1)); \ - if (escalated) { \ - set(escalated); \ - } \ - assert(cv); \ - OPEQUAL(op, *cv, v); \ - return *cv; \ - } \ - switch (m_type) { \ - case KindOfBoolean: \ - if (toBoolean()) { \ - throw_bad_type_exception("not array objects"); \ - break; \ - } \ - /* Fall through */ \ - case KindOfUninit: \ - case KindOfNull: \ - set(ArrayData::Create(ToKey(key), null)); \ - goto check_array; \ - case KindOfRef: \ - m_data.pref->var()->setOpEqual(op, key, v); \ - break; \ - case KindOfStaticString: \ - case KindOfString: { \ - String s = toString(); \ - if (s.empty()) { \ - set(ArrayData::Create(ToKey(key), null)); \ - goto check_array; \ - } \ - throw_bad_type_exception("not array objects"); \ - break; \ - } \ - case KindOfObject: { \ - ObjectData* obj = m_data.pobj; \ - if (obj->isCollection()) { \ - Variant &cv = collectionOffsetGet(obj, key); \ - OPEQUAL(op, cv, v); \ - return cv; \ - } else { \ - ObjectData *aa = getArrayAccess(); \ - Variant &cv = aa->___offsetget_lval(key); \ - OPEQUAL(op, cv, v); \ - aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1); \ - return cv; \ - } \ - } \ - default: \ - throw_bad_type_exception("not array objects"); \ - break; \ - } \ - return v; \ - template inline ALWAYS_INLINE CVarRef Variant::SetImpl(Variant *self, T key, CVarRef v, bool isKey) { @@ -2975,235 +2842,6 @@ CVarRef Variant::appendRef(CVarRef v) { return v; } -CVarRef Variant::setOpEqual(int op, bool key, CVarRef v) { - IMPLEMENT_SETAT_OPEQUAL; -} - -CVarRef Variant::setOpEqual(int op, int64_t key, CVarRef v) { - IMPLEMENT_SETAT_OPEQUAL; -} - -CVarRef Variant::setOpEqual(int op, double key, CVarRef v) { - IMPLEMENT_SETAT_OPEQUAL; -} - -CVarRef Variant::setOpEqual(int op, CStrRef key, CVarRef v, - bool isString /* = false */) { -check_array: - if (m_type == KindOfArray) { - Variant *cv = nullptr; - ArrayData *escalated; - if (isString) { - escalated = - m_data.parr->lval(key, cv, (m_data.parr->getCount() > 1)); - } else { - escalated = - m_data.parr->lval(ToKey(key), cv, (m_data.parr->getCount() > 1)); - } - if (escalated) { - set(escalated); - } - assert(cv); - OPEQUAL(op, *cv, v); - return *cv; - } - switch (m_type) { - case KindOfBoolean: - if (toBoolean()) { - throw_bad_type_exception("not array objects"); - break; - } - /* Fall through */ - case KindOfUninit: - case KindOfNull: - if (isString) { - set(ArrayData::Create(key, null)); - } else { - set(ArrayData::Create(ToKey(key), null)); - } - goto check_array; - case KindOfRef: - return m_data.pref->var()->setOpEqual(op, key, v, isString); - case KindOfStaticString: - case KindOfString: { - String s = toString(); - if (s.empty()) { - if (isString) { - set(ArrayData::Create(key, null)); - } else { - set(ArrayData::Create(ToKey(key), null)); - } - goto check_array; - } - throw_bad_type_exception("not array objects"); - break; - } - case KindOfObject: { - ObjectData* obj = m_data.pobj; - if (obj->isCollection()) { - Variant &cv = collectionOffsetGet(obj, key); - OPEQUAL(op, cv, v); - return cv; - } else { - ObjectData *aa = getArrayAccess(); - Variant &cv = aa->___offsetget_lval(key); - OPEQUAL(op, cv, v); - aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1); - return cv; - } - } - default: - throw_bad_type_exception("not array objects"); - break; - } - return v; -} - -CVarRef Variant::setOpEqual(int op, CVarRef key, CVarRef v) { -check_array: - if (m_type == KindOfArray) { - Variant *cv = nullptr; - VarNR k(ToKey(key)); - if (k.isNull()) return lvalBlackHole(); - ArrayData *escalated = - m_data.parr->lval(k, cv, (m_data.parr->getCount() > 1)); - if (escalated) { - set(escalated); - } - assert(cv); - OPEQUAL(op, *cv, v); - return *cv; - } - switch (m_type) { - case KindOfBoolean: - if (toBoolean()) { - throw_bad_type_exception("not array objects"); - break; - } - /* Fall through */ - case KindOfUninit: - case KindOfNull: { - VarNR k(ToKey(key)); - if (k.isNull()) return lvalBlackHole(); - set(ArrayData::Create(k, null)); - goto check_array; - } - case KindOfRef: - return m_data.pref->var()->setOpEqual(op, key, v); - case KindOfStaticString: - case KindOfString: { - String s = toString(); - if (s.empty()) { - VarNR k(ToKey(key)); - if (k.isNull()) return lvalBlackHole(); - set(ArrayData::Create(k, null)); - goto check_array; - } - throw_bad_type_exception("not array objects"); - break; - } - case KindOfObject: { - ObjectData* obj = m_data.pobj; - if (obj->isCollection()) { - Variant &cv = collectionOffsetGet(obj, key); - OPEQUAL(op, cv, v); - return cv; - } else { - ObjectData *aa = getArrayAccess(); - Variant &cv = aa->___offsetget_lval(key); - OPEQUAL(op, cv, v); - aa->o_invoke(s_offsetSet, CREATE_VECTOR2(key, cv), -1); - return cv; - } - } - default: - throw_bad_type_exception("not array objects"); - break; - } - return v; -} - -CVarRef Variant::appendOpEqual(int op, CVarRef v) { -check_array: - if (m_type == KindOfArray) { - Variant *cv = nullptr; - ArrayData *escalated = - m_data.parr->lvalNew(cv, m_data.parr->getCount() > 1); - if (escalated) { - set(escalated); - } - assert(cv); - switch (op) { - case T_CONCAT_EQUAL: return concat_assign((*cv), v); - case T_PLUS_EQUAL: return ((*cv) += v); - case T_MINUS_EQUAL: return ((*cv) -= v); - case T_MUL_EQUAL: return ((*cv) *= v); - case T_DIV_EQUAL: return ((*cv) /= v); - case T_MOD_EQUAL: return ((*cv) %= v); - case T_AND_EQUAL: return ((*cv) &= v); - case T_OR_EQUAL: return ((*cv) |= v); - case T_XOR_EQUAL: return ((*cv) ^= v); - case T_SL_EQUAL: return ((*cv) <<= v); - case T_SR_EQUAL: return ((*cv) >>= v); - default: - throw FatalErrorException(0, "invalid operator %d", op); - } - return v; - } - switch (m_type) { - case KindOfUninit: - case KindOfNull: - set(ArrayData::Create()); - goto check_array; - case KindOfBoolean: - if (!toBoolean()) { - set(ArrayData::Create()); - goto check_array; - } else { - throw_bad_type_exception("[] operator not supported for this type"); - } - break; - case KindOfRef: - m_data.pref->var()->appendOpEqual(op, v); - break; - case KindOfObject: { - if (m_data.pobj->isCollection()) { - raise_error("Cannot use [] for reading"); - } - ObjectData *aa = getArrayAccess(); - Variant &cv = aa->___offsetget_lval(null_variant); - switch (op) { - case T_CONCAT_EQUAL: concat_assign(cv, v); break; - case T_PLUS_EQUAL: cv += v; break; - case T_MINUS_EQUAL: cv -= v; break; - case T_MUL_EQUAL: cv *= v; break; - case T_DIV_EQUAL: cv /= v; break; - case T_MOD_EQUAL: cv %= v; break; - case T_AND_EQUAL: cv &= v; break; - case T_OR_EQUAL: cv |= v; break; - case T_XOR_EQUAL: cv ^= v; break; - case T_SL_EQUAL: cv <<= v; break; - case T_SR_EQUAL: cv >= v; break; - break; - default: - throw FatalErrorException(0, "invalid operator %d", op); - } - aa->o_invoke(s_offsetSet, CREATE_VECTOR2(null_variant, cv)); - return cv; - } - case KindOfStaticString: - case KindOfString: - if (getStringData()->empty()) { - set(ArrayData::Create()); - goto check_array; - } - // fall through to throw - default: - throw_bad_type_exception("[] operator not supported for this type"); - } - return v; -} - void Variant::removeImpl(double key) { switch (getType()) { case KindOfUninit: @@ -3865,154 +3503,5 @@ VarNR::VarNR(ObjectData *v) { } } -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return concat_assign(var, val); -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var += val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var -= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var *= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var /= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var %= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var &= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var |= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var ^= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var <<= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return var >>= val; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return val.isNull() ? ++var : var++; -} - -template<> -Variant AssignOp::assign(Variant &var, CVarRef val) { - return val.isNull() ? --var : var--; -} - -template -T Variant::o_assign_op(CStrRef propName, CVarRef val, - CStrRef context /* = null_string */) { - if (LIKELY(m_type == KindOfObject)) { - } else if (m_type == KindOfRef) { - return (T)m_data.pref->var()->template o_assign_op(propName, - val, context); - } else if (isObjectConvertable()) { - setToDefaultObject(); - } else { - // Raise a warning - raise_warning("Attempt to assign property of non-object"); - return T(); - } - return (T)m_data.pobj->template o_assign_op(propName, val, context); -} - -template -T Object::o_assign_op(CStrRef propName, CVarRef val, - CStrRef context /* = null_string */) { - if (UNLIKELY(!m_px)) { - setToDefaultObject(); - } - assert(m_px); - return m_px->template o_assign_op(propName, val, context); -} - -template -T ObjectData::o_assign_op(CStrRef propName, CVarRef val, - CStrRef context /* = null_string */) { - if (UNLIKELY(!*propName.data())) { - throw_invalid_property_name(propName); - } - bool useGet = getAttribute(ObjectData::UseGet); - bool useSet = getAttribute(ObjectData::UseSet); - int flags = useSet ? ObjectData::RealPropWrite : - ObjectData::RealPropCreate | ObjectData::RealPropWrite; - - if (Variant *t = o_realProp(propName, flags, context)) { - if (useGet && !t->isInitialized()) { - AttributeClearer a(ObjectData::UseGet, this); - *t = t___get(propName); - } - - return (T)AssignOp::assign(*t, val); - } - - assert(useSet); - Variant var; - if (useGet) { - AttributeClearer a(ObjectData::UseGet, this); - var = t___get(propName); - } - - Variant ret = AssignOp::assign(var, val); - AttributeClearer a(ObjectData::UseSet, this); - t___set(propName, var); - return (T)ret; -} - -#define DECLARE_O_ASSIGN_OP_ONE(C,T,op) \ - template T \ - C::o_assign_op(CStrRef propName, CVarRef val, \ - CStrRef context /* = null_string */) - -#define DECLARE_O_ASSIGN_OP(op) \ - DECLARE_O_ASSIGN_OP_ONE(Object,void,op); \ - DECLARE_O_ASSIGN_OP_ONE(Object,Variant,op); \ - DECLARE_O_ASSIGN_OP_ONE(Variant,void,op); \ - DECLARE_O_ASSIGN_OP_ONE(Variant,Variant,op) - -DECLARE_O_ASSIGN_OP(T_CONCAT_EQUAL); -DECLARE_O_ASSIGN_OP(T_PLUS_EQUAL); -DECLARE_O_ASSIGN_OP(T_MINUS_EQUAL); -DECLARE_O_ASSIGN_OP(T_MUL_EQUAL); -DECLARE_O_ASSIGN_OP(T_DIV_EQUAL); -DECLARE_O_ASSIGN_OP(T_MOD_EQUAL); -DECLARE_O_ASSIGN_OP(T_AND_EQUAL); -DECLARE_O_ASSIGN_OP(T_OR_EQUAL); -DECLARE_O_ASSIGN_OP(T_XOR_EQUAL); -DECLARE_O_ASSIGN_OP(T_SL_EQUAL); -DECLARE_O_ASSIGN_OP(T_SR_EQUAL); -DECLARE_O_ASSIGN_OP(T_INC); -DECLARE_O_ASSIGN_OP(T_DEC); /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/runtime/base/type_variant.h b/hphp/runtime/base/type_variant.h index d438510a9..4a013d902 100644 --- a/hphp/runtime/base/type_variant.h +++ b/hphp/runtime/base/type_variant.h @@ -909,13 +909,6 @@ class Variant : private VariantBase { Variant o_setPublicRef(CStrRef s, CVarRef v); Variant &o_lval(CStrRef propName, CVarRef tmpForGet, CStrRef context = null_string); - Variant &o_unsetLval(CStrRef s, CVarRef tmpForGet, - CStrRef context = null_string); - Variant o_argval(bool byRef, CStrRef propName, bool error = true, - CStrRef context = null_string) const; - bool o_empty(CStrRef propName, CStrRef context = null_string) const; - bool o_isset(CStrRef propName, CStrRef context = null_string) const; - void o_unset(CStrRef propName, CStrRef context = null_string); Variant o_invoke(CStrRef s, CArrRef params, int64_t hash = -1); Variant o_root_invoke(CStrRef s, CArrRef params, int64_t hash = -1); @@ -970,22 +963,6 @@ class Variant : private VariantBase { CVarRef appendRef(CVarRef v); CVarRef append(RefResult v) { return appendRef(variant(v)); } - CVarRef setOpEqual(int op, bool key, CVarRef v); - CVarRef setOpEqual(int op, int key, CVarRef v) { - return setOpEqual(op, (int64_t)key, v); - } - CVarRef setOpEqual(int op, int64_t key, CVarRef v); - CVarRef setOpEqual(int op, double key, CVarRef v); - CVarRef setOpEqual(int op, litstr key, CVarRef v, bool isString = false) { - return setOpEqual(op, String(key), v, isString); - } - CVarRef setOpEqual(int op, CStrRef key, CVarRef v, bool isString = false); - CVarRef setOpEqual(int op, CVarRef key, CVarRef v); - CVarRef appendOpEqual(int op, CVarRef v); - - template - T o_assign_op(CStrRef propName, CVarRef val, CStrRef context = null_string); - void remove(bool key) { removeImpl(key);} void remove(int key) { removeImpl((int64_t)key);} void remove(int64_t key) { removeImpl(key);} @@ -1480,11 +1457,6 @@ inline VRefParam directRef(CVarRef v) { class VariantStrongBind { private: Variant m_var; }; class VariantWithRefBind { private: Variant m_var; }; -template class AssignOp { -public: - static Variant assign(Variant &var, CVarRef val); -}; - /////////////////////////////////////////////////////////////////////////////// // VarNR diff --git a/hphp/runtime/base/util/smart_object.h b/hphp/runtime/base/util/smart_object.h index 90254706f..e227914ff 100644 --- a/hphp/runtime/base/util/smart_object.h +++ b/hphp/runtime/base/util/smart_object.h @@ -91,32 +91,6 @@ public: } }; -template -class SmartInterface : public Object { -public: - SmartInterface() {} - SmartInterface(CObjRef obj) : Object(obj) { intf = init(m_px); } - SmartInterface(ObjectData *obj) : Object(obj) { intf = init(m_px); } - SmartInterface(CVarRef obj) : Object(obj.toObject().get()) { - intf = init(m_px); - } - T* operator->() const { return intf; } - CObjRef object() const { return *this; } -private: - T *init(ObjectData *obj) const { - T *t = dynamic_cast(obj); - if (!t) { - if (ObjectData *parent = obj->getRedeclaredParent()) { - return init(parent); - } - throw InvalidObjectTypeException(m_px->o_getClassName()); - } - return t; - } - - T *intf; -}; - /////////////////////////////////////////////////////////////////////////////// } diff --git a/hphp/runtime/eval/debugger/debugger_proxy.cpp b/hphp/runtime/eval/debugger/debugger_proxy.cpp index 0bc62c63c..84bc0249b 100644 --- a/hphp/runtime/eval/debugger/debugger_proxy.cpp +++ b/hphp/runtime/eval/debugger/debugger_proxy.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/hphp/runtime/eval/eval.cpp b/hphp/runtime/eval/eval.cpp deleted file mode 100644 index 325f9b00b..000000000 --- a/hphp/runtime/eval/eval.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | HipHop for PHP | - +----------------------------------------------------------------------+ - | Copyright (c) 2010- 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 -#include - -namespace HPHP { - -using namespace Eval; - -/////////////////////////////////////////////////////////////////////////////// - -ObjectData *eval_create_object_only_hook(CStrRef s, ObjectData *root) { - assert_not_implemented(root == nullptr); - const StringData* className = StringData::GetStaticString(s.get()); - return g_vmContext->createObjectOnly((StringData*)className); -} - -/////////////////////////////////////////////////////////////////////////////// -} diff --git a/hphp/runtime/eval/eval.h b/hphp/runtime/eval/eval.h deleted file mode 100644 index 2591d7b7a..000000000 --- a/hphp/runtime/eval/eval.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | HipHop for PHP | - +----------------------------------------------------------------------+ - | Copyright (c) 2010- 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 __EVAL_EVAL_H__ -#define __EVAL_EVAL_H__ - -#include - -namespace HPHP { -/////////////////////////////////////////////////////////////////////////////// - -ObjectData *eval_create_object_only_hook(CStrRef s, ObjectData *root); - -/////////////////////////////////////////////////////////////////////////////// -} - -#endif // __EVAL_EVAL_H__ diff --git a/hphp/runtime/ext/ext_array.cpp b/hphp/runtime/ext/ext_array.cpp index 5cd7693f1..834f674ee 100644 --- a/hphp/runtime/ext/ext_array.cpp +++ b/hphp/runtime/ext/ext_array.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/hphp/runtime/ext/ext_pdo.cpp b/hphp/runtime/ext/ext_pdo.cpp index 715521613..e49f2f662 100644 --- a/hphp/runtime/ext/ext_pdo.cpp +++ b/hphp/runtime/ext/ext_pdo.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include diff --git a/hphp/runtime/vm/instance.cpp b/hphp/runtime/vm/instance.cpp index 700e2c75d..7fdfaf505 100644 --- a/hphp/runtime/vm/instance.cpp +++ b/hphp/runtime/vm/instance.cpp @@ -81,26 +81,6 @@ Instance* Instance::newInstanceRaw(Class* cls, int idx) { return obj; } -void Instance::destructHard(const Func* meth) { - static ArrayData* args = - ArrayData::GetScalarArray(HphpArray::GetStaticEmptyArray()); - TypedValue retval; - tvWriteNull(&retval); - try { - // Call the destructor method - g_vmContext->invokeFunc(&retval, meth, CArrRef(args), this); - } catch (...) { - // Swallow any exceptions that escape the __destruct method - handle_destructor_exception(); - } - tvRefcountedDecRef(&retval); -} - -void Instance::forgetSweepable() { - assert(RuntimeOption::EnableObjDestructCall); - g_vmContext->m_liveBCObjs.erase(this); -} - void Instance::invokeUserMethod(TypedValue* retval, const Func* method, CArrRef params) { g_vmContext->invokeFunc(retval, method, params, this); @@ -592,83 +572,6 @@ void Instance::raiseUndefProp(const StringData* key) { m_cls->name()->data(), key->data()); } -Array Instance::o_toIterArray(CStrRef context, bool getRef /* = false */) { - int size = m_cls->m_declPropNumAccessible + - (o_properties.get() != nullptr ? o_properties.get()->size() : 0); - HphpArray* retval = NEW(HphpArray)(size); - Class* ctx = nullptr; - if (!context.empty()) { - ctx = Unit::lookupClass(context.get()); - } - - // Get all declared properties first, bottom-to-top in the inheritance - // hierarchy, in declaration order. - const Class* klass = m_cls; - while (klass != nullptr) { - const PreClass::Prop* props = klass->m_preClass->properties(); - const size_t numProps = klass->m_preClass->numProperties(); - - for (size_t i = 0; i < numProps; ++i) { - StringData* key = const_cast(props[i].name()); - bool visible, accessible, unset; - TypedValue* val = getProp(ctx, key, visible, accessible, unset); - if (accessible && val->m_type != KindOfUninit && !unset) { - if (getRef) { - if (val->m_type != KindOfRef) { - tvBox(val); - } - retval->nvBind(key, val); - } else { - retval->nvSet(key, val, false); - } - } - } - klass = klass->m_parent.get(); - } - - // Now get dynamic properties. - if (o_properties.get() != nullptr) { - ssize_t iter = o_properties.get()->iter_begin(); - while (iter != HphpArray::ElmIndEmpty) { - TypedValue key; - static_cast(o_properties.get())->nvGetKey(&key, iter); - iter = o_properties.get()->iter_advance(iter); - - // You can get this if you cast an array to object. These properties must - // be dynamic because you can't declare a property with a non-string name. - if (UNLIKELY(!IS_STRING_TYPE(key.m_type))) { - assert(key.m_type == KindOfInt64); - TypedValue* val = - static_cast(o_properties.get())->nvGet(key.m_data.num); - if (getRef) { - if (val->m_type != KindOfRef) { - tvBox(val); - } - retval->nvBind(key.m_data.num, val); - } else { - retval->nvSet(key.m_data.num, val, false); - } - continue; - } - - StringData* strKey = key.m_data.pstr; - TypedValue* val = - static_cast(o_properties.get())->nvGet(strKey); - if (getRef) { - if (val->m_type != KindOfRef) { - tvBox(val); - } - retval->nvBind(strKey, val); - } else { - retval->nvSet(strKey, val, false); - } - decRefStr(strKey); - } - } - - return Array(retval); -} - void Instance::o_setArray(CArrRef properties) { for (ArrayIter iter(properties); iter; ++iter) { String k = iter.first().toString(); @@ -839,30 +742,6 @@ Variant Instance::t___unset(Variant v_name) { } } -DECLARE_THREAD_LOCAL(Variant, __lvalProxy); -DECLARE_THREAD_LOCAL(Variant, nullProxy); - -Variant& Instance::___offsetget_lval(Variant key) { - if (isCollection()) { - return collectionOffsetGet(this, key); - } else { - if (!instanceof(SystemLib::s_ArrayAccessClass)) { - throw InvalidOperandException("not ArrayAccess objects"); - } - static StringData* sd__offsetGet = StringData::GetStaticString("offsetGet"); - const Func* method = m_cls->lookupMethod(sd__offsetGet); - assert(method); - if (method) { - Variant *v = __lvalProxy.get(); - g_vmContext->invokeFunc((TypedValue*)v, method, - CREATE_VECTOR1(key), this); - return *v; - } else { - return *nullProxy.get(); - } - } -} - Variant Instance::t___sleep() { static StringData* sd__sleep = StringData::GetStaticString("__sleep"); const Func *method = m_cls->lookupMethod(sd__sleep); diff --git a/hphp/runtime/vm/instance.h b/hphp/runtime/vm/instance.h index 84450a104..ccfcd25da 100644 --- a/hphp/runtime/vm/instance.h +++ b/hphp/runtime/vm/instance.h @@ -152,31 +152,10 @@ class Instance : public ObjectData { DELETEOBJSZ(sizeForNProps(nProps))(this_); } - private: - void destructHard(const Func* meth); - void forgetSweepable(); - //============================================================================ // Virtual ObjectData methods that we need to override public: - virtual void destruct() { - if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) { - forgetSweepable(); - } - if (!noDestruct()) { - setNoDestruct(); - if (const Func* meth = m_cls->getDtor()) { - // We raise the refcount around the call to __destruct(). This is to - // prevent the refcount from going to zero when the destructor returns. - CountableHelper h(this); - destructHard(meth); - } - } - } - - virtual Array o_toIterArray(CStrRef context, bool getRef=false); - virtual void o_setArray(CArrRef properties); virtual void o_getArray(Array& props, bool pubOnly=false) const; @@ -184,7 +163,6 @@ class Instance : public ObjectData { virtual Variant t___call(Variant v_name, Variant v_arguments); virtual Variant t___set(Variant v_name, Variant v_value); virtual Variant t___get(Variant v_name); - virtual Variant& ___offsetget_lval(Variant key); virtual bool t___isset(Variant v_name); virtual Variant t___unset(Variant v_name); virtual Variant t___sleep(); diff --git a/hphp/runtime/vm/name_value_table_wrapper.h b/hphp/runtime/vm/name_value_table_wrapper.h index 8f22c1bb9..03e9530fd 100644 --- a/hphp/runtime/vm/name_value_table_wrapper.h +++ b/hphp/runtime/vm/name_value_table_wrapper.h @@ -165,7 +165,6 @@ class GlobalNameValueTableWrapper : public NameValueTableWrapper { Variant gvm_http_response_header; Variant __realPropProxy; - Variant __lvalProxy; Variant stgv_Variant[1]; #define k_SID stgv_Variant[0] diff --git a/hphp/test/CMakeLists.txt b/hphp/test/CMakeLists.txt index cc39e140d..2313f0465 100644 --- a/hphp/test/CMakeLists.txt +++ b/hphp/test/CMakeLists.txt @@ -10,7 +10,6 @@ auto_sources(files "*.cpp" "") list(APPEND CXX_SOURCES ${files}) list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/genCmpTest.cpp") list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/process_init.cpp") -list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/externals_stubs.cpp") list(APPEND CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../hhvm/global_variables.cpp") add_definitions(-DHPHPI_PATH="hphpi/hphpi")