diff --git a/hphp/compiler/analysis/emitter.cpp b/hphp/compiler/analysis/emitter.cpp index ee0cb343e..28b39427b 100644 --- a/hphp/compiler/analysis/emitter.cpp +++ b/hphp/compiler/analysis/emitter.cpp @@ -3925,7 +3925,7 @@ bool EmitterVisitor::visitImpl(ConstructPtr node) { pce->init(sLoc->line0, sLoc->line1, m_ue.bcPos(), AttrUnique | AttrPersistent, parentName, nullptr); - // Instance variables. + // Instance properties. TypedValue uninit; tvWriteUninit(&uninit); for (auto& useVar : useVars) { diff --git a/hphp/runtime/base/array/array_data.cpp b/hphp/runtime/base/array/array_data.cpp index 2ea869e7b..2f9508b35 100644 --- a/hphp/runtime/base/array/array_data.cpp +++ b/hphp/runtime/base/array/array_data.cpp @@ -136,7 +136,7 @@ void ArrayData::release() { // reads Object ArrayData::toObject() const { - return Instance::FromArray(const_cast(this)); + return ObjectData::FromArray(const_cast(this)); } int ArrayData::compare(const ArrayData *v2) const { diff --git a/hphp/runtime/base/builtin_functions.cpp b/hphp/runtime/base/builtin_functions.cpp index f6127a58d..04c7eb220 100644 --- a/hphp/runtime/base/builtin_functions.cpp +++ b/hphp/runtime/base/builtin_functions.cpp @@ -339,7 +339,7 @@ Variant vm_call_user_func(CVarRef function, CArrRef params, HPHP::Transl::CallerFrame cf; StringData* invName = nullptr; const HPHP::Func* f = vm_decode_function(function, cf(), forwarding, - obj, cls, invName); + obj, cls, invName); if (f == nullptr) { return uninit_null(); } @@ -681,16 +681,6 @@ void throw_call_non_object(const char *methodName) { throw FatalErrorException(msg.c_str()); } -Object f_clone(CVarRef v) { - if (v.isObject()) { - Object clone = Object(v.toObject()->clone()); - clone->t___clone(); - return clone; - } - raise_error("Cannot clone non-object"); - return Object(); -} - String f_serialize(CVarRef value) { switch (value.getType()) { case KindOfUninit: diff --git a/hphp/runtime/base/builtin_functions.h b/hphp/runtime/base/builtin_functions.h index e18d886d3..295677c43 100644 --- a/hphp/runtime/base/builtin_functions.h +++ b/hphp/runtime/base/builtin_functions.h @@ -360,11 +360,6 @@ void throw_call_non_object() ATTRIBUTE_COLD ATTRIBUTE_NORETURN; void throw_call_non_object(const char *methodName) ATTRIBUTE_COLD ATTRIBUTE_NORETURN; -/** - * Cloning an object. - */ -Object f_clone(CVarRef v); - // unserializable default value arguments such as TimeStamp::Current() // are serialized as "\x01" char const kUnserializableString[] = "\x01"; diff --git a/hphp/runtime/base/execution_context.h b/hphp/runtime/base/execution_context.h index 620fcf9e9..9c67af1b6 100644 --- a/hphp/runtime/base/execution_context.h +++ b/hphp/runtime/base/execution_context.h @@ -417,7 +417,7 @@ public: VMExecutionContext(); ~VMExecutionContext(); - typedef std::set LiveObjSet; + typedef std::set LiveObjSet; LiveObjSet m_liveBCObjs; // pcre ini_settings @@ -535,10 +535,10 @@ public: MethodLookup::LookupResult lookupCtorMethod(const HPHP::Func*& f, const HPHP::Class* cls, bool raise = false); - HPHP::ObjectData* createObject(StringData* clsName, - CArrRef params, - bool init = true); - HPHP::ObjectData* createObjectOnly(StringData* clsName); + ObjectData* createObject(StringData* clsName, + CArrRef params, + bool init = true); + ObjectData* createObjectOnly(StringData* clsName); HphpArray* getFuncStaticCtx(const HPHP::Func* f) { FuncStaticCtxMap::iterator it = m_funcStaticCtx.find(f); diff --git a/hphp/runtime/base/file/user_file.cpp b/hphp/runtime/base/file/user_file.cpp index 2cb81c715..49c06893d 100644 --- a/hphp/runtime/base/file/user_file.cpp +++ b/hphp/runtime/base/file/user_file.cpp @@ -49,7 +49,7 @@ UserFile::UserFile(Class *cls, int options /*= 0 */, cls->name()->data()); } - m_obj = Instance::newInstance(cls); + m_obj = ObjectData::newInstance(cls); m_obj.o_set("context", context); Variant ret; g_vmContext->invokeFuncFew(ret.asTypedValue(), ctor, m_obj.get()); diff --git a/hphp/runtime/base/memory/smart_allocator.h b/hphp/runtime/base/memory/smart_allocator.h index cc5ec8297..0a75cec48 100644 --- a/hphp/runtime/base/memory/smart_allocator.h +++ b/hphp/runtime/base/memory/smart_allocator.h @@ -253,12 +253,12 @@ void *SmartAllocatorInitSetup() { public: \ /* static void *ObjAllocatorInitSetup; */ \ inline ALWAYS_INLINE void operator delete(void *p) { \ - if (T::IsResourceClass) { \ + if (T::IsResourceClass) { \ RELEASEOBJ(NS, T, p); \ return; \ } \ - HPHP::Instance* this_ = (HPHP::Instance*)p; \ - HPHP::Class* cls = this_->getVMClass(); \ + ObjectData* this_ = (ObjectData*)p; \ + Class* cls = this_->getVMClass(); \ size_t nProps = cls->numDeclProperties(); \ size_t builtinPropSize = cls->builtinPropSize(); \ TypedValue* propVec = \ @@ -268,7 +268,7 @@ void *SmartAllocatorInitSetup() { TypedValue* prop = &propVec[i]; \ tvRefcountedDecRef(prop); \ } \ - DELETEOBJSZ(HPHP::Instance::sizeForNProps(nProps) + \ + DELETEOBJSZ(ObjectData::sizeForNProps(nProps) + \ builtinPropSize)(this_); \ } diff --git a/hphp/runtime/base/object_data.cpp b/hphp/runtime/base/object_data.cpp index 542b449fd..6af8c08da 100644 --- a/hphp/runtime/base/object_data.cpp +++ b/hphp/runtime/base/object_data.cpp @@ -54,7 +54,7 @@ static StaticString s_serialize("serialize"); ObjectData::~ObjectData() { if (ArrayData* a = o_properties.get()) decRefArr(a); - int &pmax = *os_max_id; + int& pmax = *os_max_id; if (o_id && o_id == pmax) { --pmax; } @@ -123,10 +123,6 @@ bool ObjectData::o_instanceof(CStrRef s) const { return m_cls->classof(cls); } -void ObjectData::raiseObjToIntNotice(const char* clsName) { - raise_notice("Object of class %s could not be converted to int", clsName); -} - bool ObjectData::o_toBooleanImpl() const noexcept { not_reached(); } @@ -177,7 +173,7 @@ ArrayIter ObjectData::begin(CStrRef context /* = null_string */) { } } -MutableArrayIter ObjectData::begin(Variant *key, Variant &val, +MutableArrayIter ObjectData::begin(Variant* key, Variant& val, CStrRef context /* = null_string */) { bool isIterable; if (isCollection()) { @@ -189,12 +185,12 @@ MutableArrayIter ObjectData::begin(Variant *key, Variant &val, "foreach by reference"); } Array properties = iterable->o_toIterArray(context, true); - ArrayData *arr = properties.detach(); + ArrayData* arr = properties.detach(); return MutableArrayIter(arr, key, val); } void ObjectData::initProperties(int nProp) { - if (!o_properties.get()) ((Instance*)this)->initDynProps(nProp); + if (!o_properties.get()) initDynProps(nProp); } Variant* ObjectData::o_realProp(CStrRef propName, int flags, @@ -210,7 +206,7 @@ Variant* ObjectData::o_realProp(CStrRef propName, int flags, ctx = Unit::lookupClass(context.get()); } - Instance* thiz = (Instance*)this; // sigh + auto thiz = const_cast(this); bool visible, accessible, unset; TypedValue* ret = (flags & RealPropNoDynamic) ? thiz->getDeclProp(ctx, propName.get(), visible, @@ -247,14 +243,16 @@ inline Variant ObjectData::o_getImpl(CStrRef propName, int flags, throw_invalid_property_name(propName); } - if (Variant *t = o_realProp(propName, flags, context)) { + if (Variant* t = o_realProp(propName, flags, context)) { if (t->isInitialized()) return *t; } if (getAttribute(UseGet)) { - AttributeClearer a(UseGet, this); - return t___get(propName); + TypedValue tvResult; + tvWriteNull(&tvResult); + invokeGet(&tvResult, propName.get()); + return tvAsCVarRef(&tvResult); } if (error) { @@ -282,7 +280,7 @@ inline ALWAYS_INLINE Variant ObjectData::o_setImpl(CStrRef propName, T v, auto flags = useSet ? 0 : RealPropCreate; if (forInit) flags |= RealPropUnchecked; - if (Variant *t = o_realProp(propName, flags, context)) { + if (Variant* t = o_realProp(propName, flags, context)) { if (!useSet || t->isInitialized()) { *t = v; return variant(v); @@ -290,8 +288,9 @@ inline ALWAYS_INLINE Variant ObjectData::o_setImpl(CStrRef propName, T v, } if (useSet) { - AttributeClearer a(UseSet, this); - t___set(propName, variant(v)); + TypedValue ignored; + invokeSet(&ignored, propName.get(), (TypedValue*)(&variant(v))); + tvRefcountedDecRef(&ignored); return variant(v); } @@ -324,7 +323,6 @@ Variant ObjectData::o_setRef(CStrRef propName, CVarRef v, CStrRef context) { HOT_FUNC void ObjectData::o_setArray(CArrRef properties) { - auto thiz = static_cast(this); for (ArrayIter iter(properties); iter; ++iter) { String k = iter.first().toString(); Class* ctx = nullptr; @@ -345,12 +343,12 @@ void ObjectData::o_setArray(CArrRef properties) { } CVarRef secondRef = iter.secondRef(); - thiz->setProp(ctx, k.get(), (TypedValue*)(&secondRef), - secondRef.isReferenced()); + setProp(ctx, k.get(), (TypedValue*)(&secondRef), + secondRef.isReferenced()); } } -void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const { +void ObjectData::o_getArray(Array& props, bool pubOnly /* = false */) const { // The declared properties in the resultant array should be a permutation of // propVec. They appear in the following order: go most-to-least-derived in // the inheritance hierarchy, inserting properties in declaration order (with @@ -363,13 +361,12 @@ void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const { // Iterate over declared properties and insert {mangled name --> prop} pairs. const Class* cls = m_cls; - auto thiz = static_cast(this); do { - thiz->getProps(cls, pubOnly, cls->m_preClass.get(), props, inserted); + getProps(cls, pubOnly, cls->m_preClass.get(), props, inserted); auto& usedTraits = cls->m_usedTraits; for (unsigned t = 0; t < usedTraits.size(); t++) { const ClassPtr& trait = usedTraits[t]; - thiz->getProps(cls, pubOnly, trait->m_preClass.get(), props, inserted); + getProps(cls, pubOnly, trait->m_preClass.get(), props, inserted); } cls = cls->m_parent.get(); } while (cls); @@ -384,14 +381,6 @@ void ObjectData::o_getArray(Array &props, bool pubOnly /* = false */) const { } } -Object ObjectData::FromArray(ArrayData *properties) { - ObjectData *ret = SystemLib::AllocStdClassObject(); - if (!properties->empty()) { - ret->o_properties.asArray() = properties; - } - return ret; -} - Array ObjectData::o_toArray() const { Array ret(ArrayData::Create()); o_getArray(ret, false); @@ -418,8 +407,7 @@ Array ObjectData::o_toIterArray(CStrRef context, for (size_t i = 0; i < numProps; ++i) { auto key = const_cast(props[i].name()); bool visible, accessible, unset; - TypedValue* val = ((Instance*)this)->getProp( - ctx, key, 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) { @@ -479,15 +467,10 @@ Array ObjectData::o_toIterArray(CStrRef context, static bool decode_invoke(CStrRef s, ObjectData* obj, bool fatal, CallCtx& ctx) { - // TODO This duplicates some logic from vm_decode_function and - // vm_call_user_func, we should refactor this in the near future ctx.this_ = obj; ctx.cls = obj->getVMClass(); ctx.invName = nullptr; - // XXX The lookup below doesn't take context into account, so it will lead - // to incorrect behavior in some corner cases. o_invoke is gradually being - // removed from the HPHP runtime this should be ok for the short term. ctx.func = ctx.cls->lookupMethod(s.get()); if (ctx.func) { if (ctx.func->attrs() & AttrStatic) { @@ -556,7 +539,7 @@ Variant ObjectData::o_invoke_few_args(CStrRef s, int count, return ret; } -bool ObjectData::php_sleep(Variant &ret) { +bool ObjectData::php_sleep(Variant& ret) { setAttribute(HasSleep); ret = t___sleep(); return getAttribute(HasSleep); @@ -564,7 +547,7 @@ bool ObjectData::php_sleep(Variant &ret) { StaticString s_zero("\0", 1); -void ObjectData::serialize(VariableSerializer *serializer) const { +void ObjectData::serialize(VariableSerializer* serializer) const { if (UNLIKELY(serializer->incNestedLevel((void*)this, true))) { serializer->writeOverflow((void*)this, true); } else { @@ -576,7 +559,7 @@ void ObjectData::serialize(VariableSerializer *serializer) const { static StaticString s_PHP_Incomplete_Class("__PHP_Incomplete_Class"); static StaticString s_PHP_Incomplete_Class_Name("__PHP_Incomplete_Class_Name"); -void ObjectData::serializeImpl(VariableSerializer *serializer) const { +void ObjectData::serializeImpl(VariableSerializer* serializer) const { bool handleSleep = false; Variant ret; if (LIKELY(serializer->getType() == VariableSerializer::Type::Serialize || @@ -631,7 +614,7 @@ void ObjectData::serializeImpl(VariableSerializer *serializer) const { if (UNLIKELY(handleSleep)) { assert(!isCollection()); if (ret.isArray()) { - auto thiz = (Instance*)this; + auto thiz = const_cast(this); Array wanted = Array::Create(); Array props = ret.toArray(); for (ArrayIter iter(props); iter; ++iter) { @@ -706,7 +689,7 @@ void ObjectData::serializeImpl(VariableSerializer *serializer) const { } } -bool ObjectData::hasInternalReference(PointerSet &vars, +bool ObjectData::hasInternalReference(PointerSet& vars, bool ds /* = false */) const { if (isCollection()) { return true; @@ -718,33 +701,8 @@ void ObjectData::dump() const { o_toArray().dump(); } -ObjectData *ObjectData::clone() { - Instance* instance = static_cast(this); - return instance->cloneImpl(); -} - -/////////////////////////////////////////////////////////////////////////////// -// magic methods that user classes can override, and these are default handlers -// or actions to take: - -Variant ObjectData::t___destruct() { - // do nothing - return uninit_null(); -} - -Variant ObjectData::t___call(Variant v_name, Variant v_arguments) { - // do nothing - return uninit_null(); -} - -Variant ObjectData::t___set(Variant v_name, Variant v_value) { - // not called - return uninit_null(); -} - -Variant ObjectData::t___get(Variant v_name) { - // not called - return uninit_null(); +ObjectData* ObjectData::clone() { + return cloneImpl(); } Variant ObjectData::offsetGet(Variant key) { @@ -762,36 +720,6 @@ Variant ObjectData::offsetGet(Variant key) { return v; } -bool ObjectData::t___isset(Variant v_name) { - return false; -} - -Variant ObjectData::t___unset(Variant v_name) { - // not called - return uninit_null(); -} - -Variant ObjectData::t___sleep() { - clearAttribute(HasSleep); - return uninit_null(); -} - -Variant ObjectData::t___wakeup() { - // do nothing - return uninit_null(); -} - -String ObjectData::t___tostring() { - string msg = o_getClassName().data(); - msg += "::__toString() was not defined"; - throw BadTypeConversionException(msg.c_str()); -} - -Variant ObjectData::t___clone() { - // do nothing - return uninit_null(); -} - /////////////////////////////////////////////////////////////////////////////// namespace { @@ -850,8 +778,7 @@ static StaticString s___unset(LITSTR_INIT("__unset")); TRACE_SET_MOD(runtime); -int HPHP::Instance::ObjAllocatorSizeClassCount = - HPHP::InitializeAllocators(); +int ObjectData::ObjAllocatorSizeClassCount = InitializeAllocators(); void deepInitHelper(TypedValue* propVec, const TypedValueAux* propData, size_t nProps) { @@ -867,26 +794,18 @@ void deepInitHelper(TypedValue* propVec, const TypedValueAux* propData, } } -void Instance::raiseAbstractClassError(Class* cls) { - Attr attrs = cls->attrs(); - raise_error("Cannot instantiate %s %s", - (attrs & AttrInterface) ? "interface" : - (attrs & AttrTrait) ? "trait" : "abstract class", - cls->preClass()->name()->data()); -} - -TypedValue* Instance::propVec() { +TypedValue* ObjectData::propVec() { uintptr_t ret = (uintptr_t)this + sizeof(ObjectData) + builtinPropSize(); // TODO(#1432007): some builtins still do not have TypedValue-aligned sizes. assert(ret % sizeof(TypedValue) == builtinPropSize() % sizeof(TypedValue)); return (TypedValue*) ret; } -const TypedValue* Instance::propVec() const { - return const_cast(this)->propVec(); +const TypedValue* ObjectData::propVec() const { + return const_cast(this)->propVec(); } -Instance* Instance::callCustomInstanceInit() { +ObjectData* ObjectData::callCustomInstanceInit() { static StringData* sd_init = StringData::GetStaticString("__init__"); const Func* init = m_cls->lookupMethod(sd_init); if (init != nullptr) { @@ -908,13 +827,20 @@ Instance* Instance::callCustomInstanceInit() { return this; } -void Instance::operator delete(void* p) { - Instance* this_ = (Instance*)p; +HOT_FUNC_VM +ObjectData* ObjectData::newInstanceRaw(Class* cls, int idx) { + ObjectData* obj = (ObjectData*)ALLOCOBJIDX(idx); + new (obj) ObjectData(cls, NoInit::noinit); + return obj; +} + +void ObjectData::operator delete(void* p) { + ObjectData* this_ = (ObjectData*)p; Class* cls = this_->getVMClass(); size_t nProps = cls->numDeclProperties(); // cppext classes have their own implementation of delete assert(this_->builtinPropSize() == 0); - TypedValue* propVec = (TypedValue *)((uintptr_t)this_ + sizeof(ObjectData)); + TypedValue* propVec = (TypedValue*)((uintptr_t)this_ + sizeof(ObjectData)); for (unsigned i = 0; i < nProps; ++i) { TypedValue* prop = &propVec[i]; tvRefcountedDecRef(prop); @@ -922,20 +848,13 @@ void Instance::operator delete(void* p) { DELETEOBJSZ(sizeForNProps(nProps))(this_); } -HOT_FUNC_VM -Instance* Instance::newInstanceRaw(Class* cls, int idx) { - Instance* obj = (Instance*)ALLOCOBJIDX(idx); - new (obj) Instance(cls, NoInit::noinit); - return obj; -} - -void Instance::invokeUserMethod(TypedValue* retval, const Func* method, - CArrRef params) { +void ObjectData::invokeUserMethod(TypedValue* retval, const Func* method, + CArrRef params) { g_vmContext->invokeFunc(retval, method, params, this); } -Object Instance::FromArray(ArrayData *properties) { - Instance* retval = Instance::newInstance(SystemLib::s_stdclassClass); +Object ObjectData::FromArray(ArrayData* properties) { + ObjectData* retval = ObjectData::newInstance(SystemLib::s_stdclassClass); retval->initDynProps(); HphpArray* props = static_cast(retval->o_properties.get()); for (ssize_t pos = properties->iter_begin(); pos != ArrayData::invalid_index; @@ -955,12 +874,12 @@ Object Instance::FromArray(ArrayData *properties) { return retval; } -void Instance::initDynProps(int numDynamic /* = 0 */) { +void ObjectData::initDynProps(int numDynamic /* = 0 */) { // Create o_properties with room for numDynamic o_properties.asArray() = ArrayData::Make(numDynamic); } -Slot Instance::declPropInd(TypedValue* prop) const { +Slot ObjectData::declPropInd(TypedValue* prop) const { // Do an address range check to determine whether prop physically resides // in propVec. const TypedValue* pv = propVec(); @@ -972,9 +891,9 @@ Slot Instance::declPropInd(TypedValue* prop) const { } template -TypedValue* Instance::getPropImpl(Class* ctx, const StringData* key, - bool& visible, bool& accessible, - bool& unset) { +TypedValue* ObjectData::getPropImpl(Class* ctx, const StringData* key, + bool& visible, bool& accessible, + bool& unset) { TypedValue* prop = nullptr; unset = false; Slot propInd = m_cls->getDeclPropIndex(ctx, key, accessible); @@ -1005,19 +924,19 @@ TypedValue* Instance::getPropImpl(Class* ctx, const StringData* key, return prop; } -TypedValue* Instance::getProp(Class* ctx, const StringData* key, - bool& visible, bool& accessible, bool& unset) { +TypedValue* ObjectData::getProp(Class* ctx, const StringData* key, + bool& visible, bool& accessible, bool& unset) { return getPropImpl(ctx, key, visible, accessible, unset); } -TypedValue* Instance::getDeclProp(Class* ctx, const StringData* key, - bool& visible, bool& accessible, - bool& unset) { +TypedValue* ObjectData::getDeclProp(Class* ctx, const StringData* key, + bool& visible, bool& accessible, + bool& unset) { return getPropImpl(ctx, key, visible, accessible, unset); } -void Instance::invokeSet(TypedValue* retval, const StringData* key, - TypedValue* val) { +void ObjectData::invokeSet(TypedValue* retval, const StringData* key, + TypedValue* val) { AttributeClearer a(UseSet, this); const Func* meth = m_cls->lookupMethod(s___set.get()); assert(meth); @@ -1031,28 +950,28 @@ void Instance::invokeSet(TypedValue* retval, const StringData* key, assert(meth); \ invokeUserMethod(retval, meth, CREATE_VECTOR1(CStrRef(key))); \ -void Instance::invokeGet(TypedValue* retval, const StringData* key) { +void ObjectData::invokeGet(TypedValue* retval, const StringData* key) { MAGIC_PROP_BODY(s___get.get(), UseGet); } -void Instance::invokeIsset(TypedValue* retval, const StringData* key) { +void ObjectData::invokeIsset(TypedValue* retval, const StringData* key) { MAGIC_PROP_BODY(s___isset.get(), UseIsset); } -void Instance::invokeUnset(TypedValue* retval, const StringData* key) { +void ObjectData::invokeUnset(TypedValue* retval, const StringData* key) { MAGIC_PROP_BODY(s___unset.get(), UseUnset); } -void Instance::invokeGetProp(TypedValue*& retval, TypedValue& tvRef, - const StringData* key) { +void ObjectData::invokeGetProp(TypedValue*& retval, TypedValue& tvRef, + const StringData* key) { invokeGet(&tvRef, key); retval = &tvRef; } template -void Instance::propImpl(TypedValue*& retval, TypedValue& tvRef, - Class* ctx, - const StringData* key) { +void ObjectData::propImpl(TypedValue*& retval, TypedValue& tvRef, + Class* ctx, + const StringData* key) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); @@ -1111,27 +1030,27 @@ void Instance::propImpl(TypedValue*& retval, TypedValue& tvRef, } } -void Instance::prop(TypedValue*& retval, TypedValue& tvRef, - Class* ctx, const StringData* key) { +void ObjectData::prop(TypedValue*& retval, TypedValue& tvRef, + Class* ctx, const StringData* key) { propImpl(retval, tvRef, ctx, key); } -void Instance::propD(TypedValue*& retval, TypedValue& tvRef, - Class* ctx, const StringData* key) { +void ObjectData::propD(TypedValue*& retval, TypedValue& tvRef, + Class* ctx, const StringData* key) { propImpl(retval, tvRef, ctx, key); } -void Instance::propW(TypedValue*& retval, TypedValue& tvRef, - Class* ctx, const StringData* key) { +void ObjectData::propW(TypedValue*& retval, TypedValue& tvRef, + Class* ctx, const StringData* key) { propImpl(retval, tvRef, ctx, key); } -void Instance::propWD(TypedValue*& retval, TypedValue& tvRef, - Class* ctx, const StringData* key) { +void ObjectData::propWD(TypedValue*& retval, TypedValue& tvRef, + Class* ctx, const StringData* key) { propImpl(retval, tvRef, ctx, key); } -bool Instance::propIsset(Class* ctx, const StringData* key) { +bool ObjectData::propIsset(Class* ctx, const StringData* key) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible && !unset) { @@ -1147,7 +1066,7 @@ bool Instance::propIsset(Class* ctx, const StringData* key) { return tv.m_data.num; } -bool Instance::propEmpty(Class* ctx, const StringData* key) { +bool ObjectData::propEmpty(Class* ctx, const StringData* key) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible && !unset) { @@ -1172,9 +1091,9 @@ bool Instance::propEmpty(Class* ctx, const StringData* key) { return false; } -TypedValue* Instance::setProp(Class* ctx, const StringData* key, - TypedValue* val, - bool bindingAssignment /* = false */) { +TypedValue* ObjectData::setProp(Class* ctx, const StringData* key, + TypedValue* val, + bool bindingAssignment /* = false */) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible) { @@ -1228,9 +1147,9 @@ TypedValue* Instance::setProp(Class* ctx, const StringData* key, return nullptr; } -TypedValue* Instance::setOpProp(TypedValue& tvRef, Class* ctx, - unsigned char op, const StringData* key, - Cell* val) { +TypedValue* ObjectData::setOpProp(TypedValue& tvRef, Class* ctx, + unsigned char op, const StringData* key, + Cell* val) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible) { @@ -1303,9 +1222,9 @@ TypedValue* Instance::setOpProp(TypedValue& tvRef, Class* ctx, } template -void Instance::incDecPropImpl(TypedValue& tvRef, Class* ctx, - unsigned char op, const StringData* key, - TypedValue& dest) { +void ObjectData::incDecPropImpl(TypedValue& tvRef, Class* ctx, + unsigned char op, const StringData* key, + TypedValue& dest) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible) { @@ -1321,7 +1240,7 @@ void Instance::incDecPropImpl(TypedValue& tvRef, Class* ctx, tvRefcountedDecRef(&ignored); propVal = &tvResult; } else { - memcpy((void *)propVal, (void *)&tvResult, sizeof(TypedValue)); + memcpy((void*)propVal, (void*)&tvResult, sizeof(TypedValue)); } } else { IncDecBody(op, propVal, &dest); @@ -1375,20 +1294,20 @@ void Instance::incDecPropImpl(TypedValue& tvRef, Class* ctx, } template <> -void Instance::incDecProp(TypedValue& tvRef, Class* ctx, - unsigned char op, const StringData* key, - TypedValue& dest) { +void ObjectData::incDecProp(TypedValue& tvRef, Class* ctx, + unsigned char op, const StringData* key, + TypedValue& dest) { incDecPropImpl(tvRef, ctx, op, key, dest); } template <> -void Instance::incDecProp(TypedValue& tvRef, Class* ctx, - unsigned char op, const StringData* key, - TypedValue& dest) { +void ObjectData::incDecProp(TypedValue& tvRef, Class* ctx, + unsigned char op, const StringData* key, + TypedValue& dest) { incDecPropImpl(tvRef, ctx, op, key, dest); } -void Instance::unsetProp(Class* ctx, const StringData* key) { +void ObjectData::unsetProp(Class* ctx, const StringData* key) { bool visible, accessible, unset; TypedValue* propVal = getProp(ctx, key, visible, accessible, unset); if (visible && accessible) { @@ -1415,15 +1334,27 @@ void Instance::unsetProp(Class* ctx, const StringData* key) { } } -void Instance::raiseUndefProp(const StringData* key) { +void ObjectData::raiseObjToIntNotice(const char* clsName) { + raise_notice("Object of class %s could not be converted to int", clsName); +} + +void ObjectData::raiseAbstractClassError(Class* cls) { + Attr attrs = cls->attrs(); + raise_error("Cannot instantiate %s %s", + (attrs & AttrInterface) ? "interface" : + (attrs & AttrTrait) ? "trait" : "abstract class", + cls->preClass()->name()->data()); +} + +void ObjectData::raiseUndefProp(const StringData* key) { raise_notice("Undefined property: %s::$%s", m_cls->name()->data(), key->data()); } -void Instance::getProp(const Class* klass, bool pubOnly, - const PreClass::Prop* prop, - Array& props, - std::vector& inserted) const { +void ObjectData::getProp(const Class* klass, bool pubOnly, + const PreClass::Prop* prop, + Array& props, + std::vector& inserted) const { if (prop->attrs() & AttrStatic) { return; } @@ -1441,10 +1372,10 @@ void Instance::getProp(const Class* klass, bool pubOnly, } } -void Instance::getProps(const Class* klass, bool pubOnly, - const PreClass* pc, - Array& props, - std::vector& inserted) const { +void ObjectData::getProps(const Class* klass, bool pubOnly, + const PreClass* pc, + Array& props, + std::vector& inserted) const { PreClass::Prop const* propVec = pc->properties(); size_t count = pc->numProperties(); for (size_t i = 0; i < count; ++i) { @@ -1452,92 +1383,9 @@ void Instance::getProps(const Class* klass, bool pubOnly, } } -Variant Instance::t___destruct() { - static StringData* sd__destruct = StringData::GetStaticString("__destruct"); - const Func* method = m_cls->lookupMethod(sd__destruct); - if (method) { - Variant v; - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this); - return v; - } else { - return uninit_null(); - } -} - -Variant Instance::t___call(Variant v_name, Variant v_arguments) { - static StringData* sd__call = StringData::GetStaticString("__call"); - const Func* method = m_cls->lookupMethod(sd__call); - if (method) { - Variant v; - TypedValue args[2]; - tvDup(*v_name.asTypedValue(), args[0]); - tvDup(*v_arguments.asTypedValue(), args[1]); - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this, nullptr, 2, - args); - return v; - } else { - return uninit_null(); - } -} - -Variant Instance::t___set(Variant v_name, Variant v_value) { - const Func* method = m_cls->lookupMethod(s___set.get()); - if (method) { - Variant v; - g_vmContext->invokeFunc(v.asTypedValue(), method, - Array(ArrayInit(2).set(v_name).set(withRefBind(v_value)).create()), - this); - return v; - } else { - return uninit_null(); - } -} - -Variant Instance::t___get(Variant v_name) { - const Func* method = m_cls->lookupMethod(s___get.get()); - if (method) { - Variant v; - TypedValue args[1]; - tvDup(*v_name.asTypedValue(), args[0]); - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this, nullptr, 1, - args); - return v; - } else { - return uninit_null(); - } -} - -bool Instance::t___isset(Variant v_name) { - const Func* method = m_cls->lookupMethod(s___isset.get()); - if (method) { - Variant v; - TypedValue args[1]; - tvDup(*v_name.asTypedValue(), args[0]); - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this, nullptr, 1, - args); - return v.toBoolean(); - } else { - return false; - } -} - -Variant Instance::t___unset(Variant v_name) { - const Func* method = m_cls->lookupMethod(s___unset.get()); - if (method) { - Variant v; - TypedValue args[1]; - tvDup(*v_name.asTypedValue(), args[0]); - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this, nullptr, 1, - args); - return v; - } else { - return uninit_null(); - } -} - -Variant Instance::t___sleep() { +Variant ObjectData::t___sleep() { static StringData* sd__sleep = StringData::GetStaticString("__sleep"); - const Func *method = m_cls->lookupMethod(sd__sleep); + const Func* method = m_cls->lookupMethod(sd__sleep); if (method) { TypedValue tv; g_vmContext->invokeFuncFew(&tv, method, this); @@ -1548,9 +1396,9 @@ Variant Instance::t___sleep() { } } -Variant Instance::t___wakeup() { +Variant ObjectData::t___wakeup() { static StringData* sd__wakeup = StringData::GetStaticString("__wakeup"); - const Func *method = m_cls->lookupMethod(sd__wakeup); + const Func* method = m_cls->lookupMethod(sd__wakeup); if (method) { TypedValue tv; g_vmContext->invokeFuncFew(&tv, method, this); @@ -1560,28 +1408,13 @@ Variant Instance::t___wakeup() { } } -Variant Instance::t___set_state(Variant v_properties) { - static StringData* sd__set_state = StringData::GetStaticString("__set_state"); - const Func* method = m_cls->lookupMethod(sd__set_state); - if (method) { - Variant v; - TypedValue args[1]; - tvDup(*v_properties.asTypedValue(), args[0]); - g_vmContext->invokeFuncFew(v.asTypedValue(), method, this, nullptr, 1, - args); - return v; - } else { - return false; - } -} - -String Instance::t___tostring() { - const Func *method = m_cls->getToString(); +String ObjectData::t___tostring() { + const Func* method = m_cls->getToString(); if (method) { TypedValue tv; g_vmContext->invokeFuncFew(&tv, method, this); if (!IS_STRING_TYPE(tv.m_type)) { - void (*notify_user)(const char *, ...) = &raise_error; + void (*notify_user)(const char*, ...) = &raise_error; if (hphpiCompat) { tvCastToStringInPlace(&tv); notify_user = &raise_warning; @@ -1597,29 +1430,16 @@ String Instance::t___tostring() { } } -Variant Instance::t___clone() { - static StringData* sd__clone = StringData::GetStaticString("__clone"); - const Func *method = m_cls->lookupMethod(sd__clone); - if (method) { - TypedValue tv; - g_vmContext->invokeFuncFew(&tv, method, this); - return false; - } else { - return false; - } -} - -void Instance::cloneSet(ObjectData* clone) { - Instance* iclone = static_cast(clone); +void ObjectData::cloneSet(ObjectData* clone) { Slot nProps = m_cls->numDeclProperties(); - TypedValue* iclonePropVec = (TypedValue *)((uintptr_t)iclone + + TypedValue* clonePropVec = (TypedValue*)((uintptr_t)clone + sizeof(ObjectData) + builtinPropSize()); for (Slot i = 0; i < nProps; i++) { - tvRefcountedDecRef(&iclonePropVec[i]); - tvDupFlattenVars(&propVec()[i], &iclonePropVec[i], nullptr); + tvRefcountedDecRef(&clonePropVec[i]); + tvDupFlattenVars(&propVec()[i], &clonePropVec[i], nullptr); } if (o_properties.get()) { - iclone->initDynProps(); + clone->initDynProps(); ssize_t iter = o_properties.get()->iter_begin(); while (iter != HphpArray::ElmIndEmpty) { auto props = static_cast(o_properties.get()); @@ -1627,9 +1447,9 @@ void Instance::cloneSet(ObjectData* clone) { props->nvGetKey(&key, iter); assert(tvIsString(&key)); StringData* strKey = key.m_data.pstr; - TypedValue *val = props->nvGet(strKey); - TypedValue *retval; - auto cloneProps = iclone->o_properties.get(); + TypedValue* val = props->nvGet(strKey); + TypedValue* retval; + auto cloneProps = clone->o_properties.get(); cloneProps->createLvalPtr(strKey, *(Variant**)&retval, false); tvDupFlattenVars(val, retval, cloneProps); iter = o_properties.get()->iter_advance(iter); @@ -1638,14 +1458,21 @@ void Instance::cloneSet(ObjectData* clone) { } } -ObjectData* Instance::cloneImpl() { - Instance* obj = Instance::newInstance(m_cls); +ObjectData* ObjectData::cloneImpl() { + ObjectData* obj; + Object o = obj = ObjectData::newInstance(m_cls); cloneSet(obj); - obj->incRefCount(); - obj->t___clone(); - return obj; + static StringData* sd__clone = StringData::GetStaticString("__clone"); + const Func* method = obj->m_cls->lookupMethod(sd__clone); + if (method) { + TypedValue tv; + tvWriteNull(&tv); + g_vmContext->invokeFuncFew(&tv, method, obj); + tvRefcountedDecRef(&tv); + } + return o.detach(); } - } // HPHP::VM +} // HPHP diff --git a/hphp/runtime/base/object_data.h b/hphp/runtime/base/object_data.h index cb1e25bec..6d03ba5d4 100644 --- a/hphp/runtime/base/object_data.h +++ b/hphp/runtime/base/object_data.h @@ -37,16 +37,11 @@ class TypedValue; class PreClass; class Class; -extern StaticString ssIterator; +void deepInitHelper(TypedValue* propVec, const TypedValueAux* propData, + size_t nProps); /** * Base class of all PHP objects and PHP resources. - * - * 1. Properties: - * o_get() -> t___get() as fallback - * o_set() -> t___set() as fallback - * 2. Methods: - * o_invoke() -> t___call() as fallback */ class ObjectData : public CountableNF { public: @@ -77,375 +72,49 @@ class ObjectData : public CountableNF { RealPropExist = 16, // For property_exists }; - ObjectData(bool noId, Class* type) - : o_attribute(0), m_cls(type) { - assert(uintptr_t(this) % sizeof(TypedValue) == 0); - if (!noId) { - o_id = ++(*os_max_id); - } - } - - void setId(const ObjectData *r) { if (r) o_id = r->o_id; } - - virtual ~ObjectData(); // all PHP classes need virtual tables - - Class* getVMClass() const { - return m_cls; - } - static size_t getVMClassOffset() { - // For assembly linkage. - return offsetof(ObjectData, m_cls); - } - static size_t attributeOff() { return offsetof(ObjectData, o_attribute); } - bool instanceof(const Class* c) const; - - bool isCollection() const { - return getCollectionType() != Collection::InvalidType; - } - Collection::Type getCollectionType() const { - // Return the upper 3 bits of o_attribute - return (Collection::Type)((uint16_t)(o_attribute >> 13) & 7); - } - - bool implementsIterator() { - return (instanceof(SystemLib::s_IteratorClass)); - } - - void setAttributes(int attrs) { o_attribute |= attrs; } - void setAttributes(const ObjectData *o) { o_attribute |= o->o_attribute; } - bool getAttribute(Attribute attr) const { return o_attribute & attr; } - void setAttribute(Attribute attr) const { o_attribute |= attr;} - void clearAttribute(Attribute attr) const { o_attribute &= ~attr;} - bool noDestruct() const { return getAttribute(NoDestructor); } - void setNoDestruct() { setAttribute(NoDestructor); } - ObjectData *clearNoDestruct() { clearAttribute(NoDestructor); return this; } - - Object iterableObject(bool& isIterable, bool mayImplementIterator = true); - ArrayIter begin(CStrRef context = null_string); - MutableArrayIter begin(Variant *key, Variant &val, - CStrRef context = null_string); - - /** - * o_instanceof() can be used for both classes and interfaces. - * It is also worth noting that o_instanceof will always return - * false for classes that are descendents of ResourceData. - */ - bool o_instanceof(CStrRef s) const; - - // class info - CStrRef o_getClassName() const; - CStrRef o_getParentName() const; - virtual CStrRef o_getClassNameHook() const; - virtual bool isResource() const { return false; } - int o_getId() const { return o_id;} - - bool o_toBoolean() const { - if (getAttribute(CallToImpl)) { - return o_toBooleanImpl(); - } - return true; - } - - static void raiseObjToIntNotice(const char*); - - int64_t o_toInt64() const { - if (getAttribute(CallToImpl)) { - return o_toInt64Impl(); - } - raiseObjToIntNotice(o_getClassName().data()); - return 1; - } - - double o_toDouble() const { - if (getAttribute(CallToImpl)) { - return o_toDoubleImpl(); - } - return o_toInt64(); - } - - // overridable casting - virtual bool o_toBooleanImpl() const noexcept; - virtual int64_t o_toInt64Impl() const noexcept; - virtual double o_toDoubleImpl() const noexcept; - - void destruct(); - - // properties - virtual Array o_toArray() 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; - - Variant o_get(CStrRef s, bool error = true, - CStrRef context = null_string); - - Variant o_set(CStrRef s, CVarRef v); - Variant o_set(CStrRef s, RefResult v); - Variant o_setRef(CStrRef s, CVarRef v); - - Variant o_set(CStrRef s, CVarRef v, CStrRef context); - Variant o_set(CStrRef s, RefResult v, CStrRef context); - Variant o_setRef(CStrRef s, CVarRef v, CStrRef context); - - void o_setArray(CArrRef properties); - void o_getArray(Array &props, bool pubOnly = false) const; - - static Object FromArray(ArrayData *properties); - - // method invocation with CStrRef - Variant o_invoke(CStrRef s, CArrRef params, bool fatal = true); - Variant o_invoke_few_args(CStrRef s, int count, - INVOKE_FEW_ARGS_DECL_ARGS); - - // misc - 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(); - - Variant offsetGet(Variant key); - - // magic methods - // __construct is handled in a special way - virtual Variant t___destruct(); - 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 bool t___isset(Variant v_name); - virtual Variant t___unset(Variant v_name); - virtual Variant t___sleep(); - virtual Variant t___wakeup(); - virtual String t___tostring(); - virtual Variant t___clone(); - - static int GetMaxId() ATTRIBUTE_COLD; - protected: - virtual bool php_sleep(Variant &ret); - public: - CArrRef getProperties() const { return o_properties; } - void initProperties(int nProp); - private: - static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_id); - ObjectData(const ObjectData &) { assert(false);} - inline Variant o_getImpl(CStrRef propName, int flags, - bool error = true, CStrRef context = null_string); - template - inline Variant o_setImpl(CStrRef propName, T v, - bool forInit, CStrRef context); - public: + // ResourceData overrides this setting IsResourceClass to true; + // various macros check whether type T is a resource type by + // inspecting "T::IsResourceClass". static const bool IsResourceClass = false; - // this will be hopefully packed together with _count from parent class + static int ObjAllocatorSizeClassCount; private: - mutable int16_t o_attribute; // various flags - protected: - // 16 bits of unused memory that can be reused by subclasses - union { - uint16_t u16; - uint8_t u8[2]; - } o_subclassData; - - protected: - Class* m_cls; - - protected: - ArrNR o_properties; // dynamic properties (VM and hphpc) - int o_id; // a numeric identifier of this object - - private: - static void compileTimeAssertions() { - static_assert(offsetof(ObjectData, _count) == FAST_REFCOUNT_OFFSET, - "Offset of ObjectData._count must be FAST_REFCOUNT_OFFSET"); - } - - public: - void release() { - assert(getCount() == 0); - destruct(); - if (UNLIKELY(getCount() != 0)) { - // Object was resurrected. - return; - } - delete this; - } - - public: - void getChildren(std::vector &out) { - ArrayData *props = o_properties.get(); - if (props) { - props->getChildren(out); - } - } -} __attribute__((aligned(16))); - -template<> inline SmartPtr::~SmartPtr() {} - -typedef GlobalNameValueTableWrapper GlobalVariables; - -/////////////////////////////////////////////////////////////////////////////// -// Calculate item sizes for object allocators - -#define WORD_SIZE sizeof(TypedValue) -#define ALIGN_WORD(n) ((n) + (WORD_SIZE - (n) % WORD_SIZE) % WORD_SIZE) - -// Mapping from index to size class for objects. Mapping in the other -// direction is available from ObjectSizeClass<> below. -template class ObjectSizeTable { - enum { prevSize = ObjectSizeTable::value }; -public: - enum { - value = ALIGN_WORD(prevSize + (prevSize >> 1)) - }; -}; - -template<> struct ObjectSizeTable<0> { - enum { value = sizeof(ObjectData) }; -}; - -#undef WORD_SIZE -#undef ALIGN_WORD - -/* - * This determines the highest size class we can have by looking for - * the first entry in our table that is larger than the hard coded - * SmartAllocator SLAB_SIZE. This is because you can't (currently) - * SmartAllocate chunks that are potentially bigger than a slab. If - * you introduce a bigger size class, SmartAllocator will hit an - * assertion at runtime. The last size class currently goes up to - * 97096 bytes -- enough room for 6064 TypedValues. Hopefully that's - * enough. - */ -template -struct DetermineLargestSizeClass { - typedef typename boost::mpl::eval_if_c< - (ObjectSizeTable::value > SLAB_SIZE), - boost::mpl::int_, - DetermineLargestSizeClass - >::type type; -}; -const int NumObjectSizeClasses = DetermineLargestSizeClass<0>::type::value; - -template struct LookupObjSizeIndex { - enum { index = - Sz <= ObjectSizeTable::value - ? Index : LookupObjSizeIndex::index }; -}; -template struct LookupObjSizeIndex { - enum { index = NumObjectSizeClasses }; -}; - -template -struct ObjectSizeClass { - enum { - index = LookupObjSizeIndex::index, - value = ObjectSizeTable::value - }; -}; - -typedef ObjectAllocatorBase *(*ObjectAllocatorBaseGetter)(void); - -class ObjectAllocatorCollector { -public: - static std::map &getWrappers() { - static std::map wrappers; - return wrappers; - } -}; - -template -void *ObjectAllocatorInitSetup() { - ThreadLocalSingleton::value> > tls; - int index = ObjectSizeClass::index; - ObjectAllocatorCollector::getWrappers()[index] = - (ObjectAllocatorBaseGetter)tls.getCheck; - GetAllocatorInitList().insert((AllocatorThreadLocalInit)(tls.getCheck)); - return (void*)tls.getNoCheck; -} - -/* - * Return the index in ThreadInfo::m_allocators for the allocator - * responsible for a given object size. - * - * There is a maximum limit on the size of allocatable objects. If - * this is reached, this function returns -1. - */ -int object_alloc_size_to_index(size_t size); - -/////////////////////////////////////////////////////////////////////////////// -// Attribute helpers -class AttributeSetter { -public: - AttributeSetter(ObjectData::Attribute a, ObjectData *o) : m_a(a), m_o(o) { - o->setAttribute(a); - } - ~AttributeSetter() { - m_o->clearAttribute(m_a); - } -private: - ObjectData::Attribute m_a; - ObjectData *m_o; -}; - -class AttributeClearer { -public: - AttributeClearer(ObjectData::Attribute a, ObjectData *o) : m_a(a), m_o(o) { - o->clearAttribute(a); - } - ~AttributeClearer() { - m_o->setAttribute(m_a); - } -private: - ObjectData::Attribute m_a; - ObjectData *m_o; -}; - -ALWAYS_INLINE inline void decRefObj(ObjectData* obj) { - if (obj->decRefCount() == 0) obj->release(); -} - -/////////////////////////////////////////////////////////////////////////////// - -void deepInitHelper(TypedValue* propVec, const TypedValueAux* propData, - size_t nProps); - -class Instance : public ObjectData { - // Do not declare any fields directly in Instance; instead embed them in - // ObjectData, so that a property vector can always reside immediately past - // the end of an object. - - private: - // This constructor is used for all pure classes that are not - // descendents of cppext classes - explicit Instance(Class* cls) : ObjectData(false, cls) { - instanceInit(cls); - } - - enum class NoInit { noinit }; - explicit Instance(Class* cls, NoInit) : ObjectData(false, cls) {} + static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_id); public: // This constructor is used for all cppext classes (including resources) // and their descendents. - Instance(Class* cls, bool isResource) - : ObjectData(isResource, cls) { + ObjectData(Class* cls, bool isResource) : o_attribute(0), m_cls(cls) { + assert(uintptr_t(this) % sizeof(TypedValue) == 0); + if (!isResource) { + o_id = ++(*os_max_id); + } instanceInit(cls); } - virtual ~Instance() {} + private: + // The two constructors below are used for all pure classes that are not + // descendents of cppext classes + explicit ObjectData(Class* cls) : o_attribute(0), m_cls(cls) { + assert(uintptr_t(this) % sizeof(TypedValue) == 0); + o_id = ++(*os_max_id); + instanceInit(cls); + } - static int ObjAllocatorSizeClassCount; + enum class NoInit { noinit }; + explicit ObjectData(Class* cls, NoInit) : o_attribute(0), m_cls(cls) { + assert(uintptr_t(this) % sizeof(TypedValue) == 0); + o_id = ++(*os_max_id); + } - static void raiseAbstractClassError(Class* cls); + // Disallow copy construction + ObjectData(const ObjectData&) = delete; - // Call newInstance() to instantiate an Instance - static Instance* newInstance(Class* cls) { + public: + virtual ~ObjectData(); // all PHP classes need virtual tables + + // Call newInstance() to instantiate a PHP object + static ObjectData* newInstance(Class* cls) { if (cls->m_InstanceCtor) { return cls->m_InstanceCtor(cls); } @@ -455,13 +124,13 @@ class Instance : public ObjectData { } size_t nProps = cls->numDeclProperties(); size_t size = sizeForNProps(nProps); - Instance* obj = (Instance*)ALLOCOBJSZ(size); - new (obj) Instance(cls); + ObjectData* obj = (ObjectData*)ALLOCOBJSZ(size); + new (obj) ObjectData(cls); if (UNLIKELY(cls->callsCustomInstanceInit())) { /* This must happen after the constructor finishes, because it can leak references to obj AND it can - throw exceptions. If we have this in the Instance + throw exceptions. If we have this in the ObjectData constructor, and it throws, obj will be partially destroyed (ie ~ObjectData will be called, resetting the vtable pointer) leaving dangling references @@ -475,7 +144,7 @@ class Instance : public ObjectData { // Given a Class that is assumed to be a concrete, regular (not a // trait or interface), pure PHP class, and an allocator index, // return a new, uninitialized object of that class. - static Instance* newInstanceRaw(Class* cls, int idx); + static ObjectData* newInstanceRaw(Class* cls, int idx); private: void instanceInit(Class* cls) { @@ -501,30 +170,166 @@ class Instance : public ObjectData { } } + public: + void operator delete(void* p); + + void release() { + assert(getCount() == 0); + destruct(); + if (UNLIKELY(getCount() != 0)) { + // Object was resurrected. + return; + } + delete this; + } + + void setId(const ObjectData* r) { if (r) o_id = r->o_id; } + + Class* getVMClass() const { + return m_cls; + } + static size_t getVMClassOffset() { + // For assembly linkage. + return offsetof(ObjectData, m_cls); + } + static size_t attributeOff() { return offsetof(ObjectData, o_attribute); } + bool instanceof(const Class* c) const; + + bool isCollection() const { + return getCollectionType() != Collection::InvalidType; + } + Collection::Type getCollectionType() const { + // Return the upper 3 bits of o_attribute + return (Collection::Type)((uint16_t)(o_attribute >> 13) & 7); + } + + bool implementsIterator() { + return (instanceof(SystemLib::s_IteratorClass)); + } + + void setAttributes(int attrs) { o_attribute |= attrs; } + void setAttributes(const ObjectData* o) { o_attribute |= o->o_attribute; } + bool getAttribute(Attribute attr) const { return o_attribute & attr; } + void setAttribute(Attribute attr) const { o_attribute |= attr;} + void clearAttribute(Attribute attr) const { o_attribute &= ~attr;} + bool noDestruct() const { return getAttribute(NoDestructor); } + void setNoDestruct() { setAttribute(NoDestructor); } + ObjectData* clearNoDestruct() { clearAttribute(NoDestructor); return this; } + + Object iterableObject(bool& isIterable, bool mayImplementIterator = true); + ArrayIter begin(CStrRef context = null_string); + MutableArrayIter begin(Variant* key, Variant& val, + CStrRef context = null_string); + + /** + * o_instanceof() can be used for both classes and interfaces. + * It is also worth noting that o_instanceof will always return + * false for classes that are descendents of ResourceData. + */ + bool o_instanceof(CStrRef s) const; + + // class info + CStrRef o_getClassName() const; + CStrRef o_getParentName() const; + virtual CStrRef o_getClassNameHook() const; + virtual bool isResource() const { return false; } + int o_getId() const { return o_id;} + + bool o_toBoolean() const { + if (getAttribute(CallToImpl)) { + return o_toBooleanImpl(); + } + return true; + } + + int64_t o_toInt64() const { + if (getAttribute(CallToImpl)) { + return o_toInt64Impl(); + } + raiseObjToIntNotice(o_getClassName().data()); + return 1; + } + + double o_toDouble() const { + if (getAttribute(CallToImpl)) { + return o_toDoubleImpl(); + } + return o_toInt64(); + } + + // overridable casting + virtual bool o_toBooleanImpl() const noexcept; + virtual int64_t o_toInt64Impl() const noexcept; + virtual double o_toDoubleImpl() const noexcept; + virtual Array o_toArray() const; + + void destruct(); + + Array o_toIterArray(CStrRef context, bool getRef = false); + + Variant* o_realProp(CStrRef s, int flags, + CStrRef context = null_string) const; + + Variant o_get(CStrRef s, bool error = true, + CStrRef context = null_string); + + Variant o_set(CStrRef s, CVarRef v); + Variant o_set(CStrRef s, RefResult v); + Variant o_setRef(CStrRef s, CVarRef v); + + Variant o_set(CStrRef s, CVarRef v, CStrRef context); + Variant o_set(CStrRef s, RefResult v, CStrRef context); + Variant o_setRef(CStrRef s, CVarRef v, CStrRef context); + + void o_setArray(CArrRef properties); + void o_getArray(Array& props, bool pubOnly = false) const; + + static Object FromArray(ArrayData* properties); + + // TODO Task #2584896: o_invoke and o_invoke_few_args are deprecated. These + // APIs don't properly take class context into account when looking up the + // method, and they duplicate some of the functionality from invokeFunc(), + // invokeFuncFew(), and vm_decode_function(). We should remove these APIs + // and migrate all callers to use invokeFunc(), invokeFuncFew(), and + // vm_decode_function() instead. + Variant o_invoke(CStrRef s, CArrRef params, bool fatal = true); + Variant o_invoke_few_args(CStrRef s, int count, + INVOKE_FEW_ARGS_DECL_ARGS); + + 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(); + + Variant offsetGet(Variant key); + + virtual Variant t___sleep(); + virtual Variant t___wakeup(); + virtual String t___tostring(); + + static int GetMaxId() ATTRIBUTE_COLD; + + protected: + virtual bool php_sleep(Variant& ret); + + public: + CArrRef getDynProps() const { return o_properties; } + void initProperties(int nProp); + + void getChildren(std::vector &out) { + ArrayData* props = o_properties.get(); + if (props) { + props->getChildren(out); + } + } + protected: TypedValue* propVec(); const TypedValue* propVec() const; public: - Instance* callCustomInstanceInit(); - - void operator delete(void* p); - - //============================================================================ - // Virtual ObjectData methods that we need to override - - public: - virtual Variant t___destruct(); - 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 bool t___isset(Variant v_name); - virtual Variant t___unset(Variant v_name); - virtual Variant t___sleep(); - virtual Variant t___wakeup(); - virtual Variant t___set_state(Variant v_properties); - virtual String t___tostring(); - virtual Variant t___clone(); + ObjectData* callCustomInstanceInit(); //============================================================================ // Miscellaneous. @@ -540,24 +345,25 @@ class Instance : public ObjectData { } static size_t sizeForNProps(Slot nProps) { - size_t sz = sizeof(Instance) + (sizeof(TypedValue) * nProps); + size_t sz = sizeof(ObjectData) + (sizeof(TypedValue) * nProps); assert((sz & (sizeof(TypedValue) - 1)) == 0); return sz; } - static Object FromArray(ArrayData *properties); - //============================================================================ // Properties. public: - int builtinPropSize() const { - return m_cls->builtinPropSize(); - } + int builtinPropSize() const { return m_cls->builtinPropSize(); } - // public for ObjectData access + private: void initDynProps(int numDynamic = 0); Slot declPropInd(TypedValue* prop) const; - private: + + inline Variant o_getImpl(CStrRef propName, int flags, + bool error = true, CStrRef context = null_string); + template + inline Variant o_setImpl(CStrRef propName, T v, + bool forInit, CStrRef context); template TypedValue* getPropImpl(Class* ctx, const StringData* key, bool& visible, bool& accessible, bool& unset); @@ -606,20 +412,176 @@ class Instance : public ObjectData { const StringData* key, TypedValue& dest); void unsetProp(Class* ctx, const StringData* key); + static void raiseObjToIntNotice(const char*); + static void raiseAbstractClassError(Class* cls); void raiseUndefProp(const StringData* name); - friend class ObjectData; + private: + static void compileTimeAssertions() { + static_assert(offsetof(ObjectData, _count) == FAST_REFCOUNT_OFFSET, + "Offset of ObjectData._count must be FAST_REFCOUNT_OFFSET"); + } + + //============================================================================ + // ObjectData fields + + // o_attribute and o_subclassData will hopefully be packed together + // with _count from parent class + private: + // Various per-instance flags + mutable int16_t o_attribute; + protected: + // 16 bits of memory that can be reused by subclasses + union { + uint16_t u16; + uint8_t u8[2]; + } o_subclassData; + // Pointer to this object's class + Class* m_cls; + // Storage for dynamic properties + ArrNR o_properties; + // Numeric identifier of this object (used for var_dump()) + int o_id; + +} __attribute__((aligned(16))); + +template<> inline SmartPtr::~SmartPtr() {} + +typedef GlobalNameValueTableWrapper GlobalVariables; + +/////////////////////////////////////////////////////////////////////////////// +// Calculate item sizes for object allocators + +#define WORD_SIZE sizeof(TypedValue) +#define ALIGN_WORD(n) ((n) + (WORD_SIZE - (n) % WORD_SIZE) % WORD_SIZE) + +// Mapping from index to size class for objects. Mapping in the other +// direction is available from ObjectSizeClass<> below. +template class ObjectSizeTable { + enum { prevSize = ObjectSizeTable::value }; +public: + enum { + value = ALIGN_WORD(prevSize + (prevSize >> 1)) + }; }; -inline Instance* instanceFromTv(TypedValue* tv) { - assert(dynamic_cast(tv->m_data.pobj)); - return static_cast(tv->m_data.pobj); +template<> struct ObjectSizeTable<0> { + enum { value = sizeof(ObjectData) }; +}; + +#undef WORD_SIZE +#undef ALIGN_WORD + +/* + * This determines the highest size class we can have by looking for + * the first entry in our table that is larger than the hard coded + * SmartAllocator SLAB_SIZE. This is because you can't (currently) + * SmartAllocate chunks that are potentially bigger than a slab. If + * you introduce a bigger size class, SmartAllocator will hit an + * assertion at runtime. The last size class currently goes up to + * 97096 bytes -- enough room for 6064 TypedValues. Hopefully that's + * enough. + */ +template +struct DetermineLargestSizeClass { + typedef typename boost::mpl::eval_if_c< + (ObjectSizeTable::value > SLAB_SIZE), + boost::mpl::int_, + DetermineLargestSizeClass + >::type type; +}; +const int NumObjectSizeClasses = DetermineLargestSizeClass<0>::type::value; + +template struct LookupObjSizeIndex { + enum { index = + Sz <= ObjectSizeTable::value + ? Index : LookupObjSizeIndex::index }; +}; +template struct LookupObjSizeIndex { + enum { index = NumObjectSizeClasses }; +}; + +template +struct ObjectSizeClass { + enum { + index = LookupObjSizeIndex::index, + value = ObjectSizeTable::value + }; +}; + +typedef ObjectAllocatorBase*(*ObjectAllocatorBaseGetter)(void); + +class ObjectAllocatorCollector { +public: + static std::map &getWrappers() { + static std::map wrappers; + return wrappers; + } +}; + +template +void* ObjectAllocatorInitSetup() { + ThreadLocalSingleton::value> > tls; + int index = ObjectSizeClass::index; + ObjectAllocatorCollector::getWrappers()[index] = + (ObjectAllocatorBaseGetter)tls.getCheck; + GetAllocatorInitList().insert((AllocatorThreadLocalInit)(tls.getCheck)); + return (void*)tls.getNoCheck; } -class ExtObjectData : public HPHP::Instance { +/* + * Return the index in ThreadInfo::m_allocators for the allocator + * responsible for a given object size. + * + * There is a maximum limit on the size of allocatable objects. If + * this is reached, this function returns -1. + */ +int object_alloc_size_to_index(size_t size); + +/////////////////////////////////////////////////////////////////////////////// +// Attribute helpers +class AttributeSetter { +public: + AttributeSetter(ObjectData::Attribute a, ObjectData* o) : m_a(a), m_o(o) { + o->setAttribute(a); + } + ~AttributeSetter() { + m_o->clearAttribute(m_a); + } +private: + ObjectData::Attribute m_a; + ObjectData* m_o; +}; + +class AttributeClearer { +public: + AttributeClearer(ObjectData::Attribute a, ObjectData* o) : m_a(a), m_o(o) { + o->clearAttribute(a); + } + ~AttributeClearer() { + m_o->setAttribute(m_a); + } +private: + ObjectData::Attribute m_a; + ObjectData* m_o; +}; + +ALWAYS_INLINE inline void decRefObj(ObjectData* obj) { + if (obj->decRefCount() == 0) obj->release(); +} + +/////////////////////////////////////////////////////////////////////////////// + +inline ObjectData* instanceFromTv(TypedValue* tv) { + assert(tv->m_type == KindOfObject); + assert(dynamic_cast(tv->m_data.pobj)); + return tv->m_data.pobj; +} + +class ExtObjectData : public ObjectData { public: - explicit ExtObjectData(HPHP::Class* cls) - : HPHP::Instance(cls, false) { + explicit ExtObjectData(HPHP::Class* cls) : ObjectData(cls, false) { assert(!m_cls->callsCustomInstanceInit()); } }; diff --git a/hphp/runtime/base/resource_data.cpp b/hphp/runtime/base/resource_data.cpp index 9f1ff4a81..402c43651 100644 --- a/hphp/runtime/base/resource_data.cpp +++ b/hphp/runtime/base/resource_data.cpp @@ -31,7 +31,7 @@ int ResourceData::GetMaxResourceId() { } ResourceData::ResourceData() - : Instance(SystemLib::s_resourceClass, true) { + : ObjectData(SystemLib::s_resourceClass, true) { assert(!m_cls->callsCustomInstanceInit()); ObjectData::setAttributes(ObjectData::CallToImpl); int &pmax = *os_max_resource_id; diff --git a/hphp/runtime/base/resource_data.h b/hphp/runtime/base/resource_data.h index b1e62bfba..ba4459193 100644 --- a/hphp/runtime/base/resource_data.h +++ b/hphp/runtime/base/resource_data.h @@ -27,7 +27,7 @@ namespace HPHP { * Base class of all resources used by extensions for opaquely passing object * pointers. */ -class ResourceData : public Instance { +class ResourceData : public ObjectData { public: ResourceData(); virtual ~ResourceData(); diff --git a/hphp/runtime/base/type_variant.cpp b/hphp/runtime/base/type_variant.cpp index c4fcb7cb2..3daf6bb7c 100644 --- a/hphp/runtime/base/type_variant.cpp +++ b/hphp/runtime/base/type_variant.cpp @@ -2455,12 +2455,12 @@ void Variant::unserialize(VariableUnserializer *uns, } } if (cls) { - obj = Instance::newInstance(cls); + obj = ObjectData::newInstance(cls); if (UNLIKELY(cls == c_Pair::s_cls && size != 2)) { throw Exception("Pair objects must have exactly 2 elements"); } } else { - obj = Instance::newInstance( + obj = ObjectData::newInstance( SystemLib::s___PHP_Incomplete_ClassClass); obj->o_set(s_PHP_Incomplete_Class_Name, clsName); } diff --git a/hphp/runtime/ext/ext_continuation.cpp b/hphp/runtime/ext/ext_continuation.cpp index a5b734be2..1cd10b103 100644 --- a/hphp/runtime/ext/ext_continuation.cpp +++ b/hphp/runtime/ext/ext_continuation.cpp @@ -217,11 +217,6 @@ void c_Continuation::copyContinuationVars(ActRec* fp) { } } -// unused -Variant c_Continuation::t___clone() { - not_reached(); -} - c_Continuation *c_Continuation::clone() { const Func *origFunc = m_origFunc; const Func *genFunc = actRec()->m_func; diff --git a/hphp/runtime/ext/ext_continuation.h b/hphp/runtime/ext/ext_continuation.h index 3fc9f21ea..d0dee7789 100644 --- a/hphp/runtime/ext/ext_continuation.h +++ b/hphp/runtime/ext/ext_continuation.h @@ -79,7 +79,6 @@ public: void t_raise(CVarRef v); String t_getorigfuncname(); String t_getcalledclass(); - Variant t___clone(); c_Continuation* clone(); diff --git a/hphp/runtime/ext/ext_pdo.cpp b/hphp/runtime/ext/ext_pdo.cpp index 79c8b24aa..f6c965869 100644 --- a/hphp/runtime/ext/ext_pdo.cpp +++ b/hphp/runtime/ext/ext_pdo.cpp @@ -574,7 +574,7 @@ static Object pdo_stmt_instantiate(sp_PDOConnection dbh, CStrRef clsname, if (!cls) { return Object(); } - return HPHP::Instance::newInstance(cls); + return ObjectData::newInstance(cls); } static void pdo_stmt_construct(sp_PDOStatement stmt, Object object, @@ -588,7 +588,7 @@ static void pdo_stmt_construct(sp_PDOStatement stmt, Object object, } object->o_set("queryString", stmt->query_string); TypedValue ret; - Instance* inst = static_cast(object.get()); + ObjectData* inst = object.get(); inst->invokeUserMethod(&ret, cls->getCtor(), ctor_args.toArray()); tvRefcountedDecRef(&ret); } diff --git a/hphp/runtime/ext/ext_simplexml.cpp b/hphp/runtime/ext/ext_simplexml.cpp index ccac28044..69a93250f 100644 --- a/hphp/runtime/ext/ext_simplexml.cpp +++ b/hphp/runtime/ext/ext_simplexml.cpp @@ -870,7 +870,7 @@ Variant c_SimpleXMLElement::t___set(Variant name, Variant value) { } bool c_SimpleXMLElement::o_toBooleanImpl() const noexcept { - return m_node != NULL || getProperties().size(); + return (m_node || getDynProps().size()); } int64_t c_SimpleXMLElement::o_toInt64Impl() const noexcept { diff --git a/hphp/runtime/ext_hhvm/ext_hhvm.h b/hphp/runtime/ext_hhvm/ext_hhvm.h index afc5452af..0717f834d 100644 --- a/hphp/runtime/ext_hhvm/ext_hhvm.h +++ b/hphp/runtime/ext_hhvm/ext_hhvm.h @@ -24,8 +24,7 @@ namespace HPHP { struct ActRec; - class Instance; -; +class ObjectData; struct HhbcExtFuncInfo { const char* m_name; @@ -40,7 +39,7 @@ struct HhbcExtMethodInfo { struct HhbcExtClassInfo { const char* m_name; - HPHP::Instance* (*m_InstanceCtor)(HPHP::Class*); + ObjectData* (*m_InstanceCtor)(HPHP::Class*); int m_sizeof; long long m_methodCount; const HhbcExtMethodInfo* m_methods; diff --git a/hphp/runtime/vm/backup_gc.cpp b/hphp/runtime/vm/backup_gc.cpp index 9a88f422c..04b7d0539 100644 --- a/hphp/runtime/vm/backup_gc.cpp +++ b/hphp/runtime/vm/backup_gc.cpp @@ -246,12 +246,12 @@ void traceImpl(const Visitor& visit, ObjectData* obj) { // Dynamic properties. We have to visit the dynamic property array // itself, since it is an object living in the smart heap (all the // top-level walks visit it anyway). - if (ArrayData* dyn = obj->getProperties().get()) { + if (ArrayData* dyn = obj->getDynProps().get()) { visit(dyn); } - // Declared properties. We need to indirect through the TypedValue - // before visiting, since these are in-situ in the Instance. + // Declared properties. We need to indirect through the TypedValue + // before visiting, since these are in-situ in the ObjectData. void* vpObj = obj; unsigned char* address = static_cast(vpObj); diff --git a/hphp/runtime/vm/bytecode.cpp b/hphp/runtime/vm/bytecode.cpp index 76b535cbd..d153fcdb3 100644 --- a/hphp/runtime/vm/bytecode.cpp +++ b/hphp/runtime/vm/bytecode.cpp @@ -2531,9 +2531,8 @@ void VMExecutionContext::treadmillSharedVars() { void VMExecutionContext::destructObjects() { if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) { while (!m_liveBCObjs.empty()) { - ObjectData* o = *m_liveBCObjs.begin(); - Instance* instance = static_cast(o); - instance->destruct(); // Let the instance remove the node. + ObjectData* obj = *m_liveBCObjs.begin(); + obj->destruct(); // Let the instance remove the node. } m_liveBCObjs.clear(); } @@ -4270,8 +4269,7 @@ inline void OPTBLD_INLINE VMExecutionContext::iopUnwind(PC& pc) { inline void OPTBLD_INLINE VMExecutionContext::iopThrow(PC& pc) { Cell* c1 = m_stack.topC(); if (c1->m_type != KindOfObject || - !static_cast(c1->m_data.pobj)-> - instanceof(SystemLib::s_ExceptionClass)) { + !c1->m_data.pobj->instanceof(SystemLib::s_ExceptionClass)) { raise_error("Exceptions must be valid objects derived from the " "Exception base class"); } diff --git a/hphp/runtime/vm/class.h b/hphp/runtime/vm/class.h index 5419b5a9e..16dd0cd06 100644 --- a/hphp/runtime/vm/class.h +++ b/hphp/runtime/vm/class.h @@ -43,7 +43,6 @@ class FuncEmitter; class Unit; class UnitEmitter; class Class; -class Instance; class NamedEntity; class PreClass; @@ -51,7 +50,7 @@ typedef hphp_hash_set TraitNameSet; typedef hphp_hash_set > ClassSet; -typedef Instance*(*BuiltinCtorFunction)(Class*); +typedef ObjectData*(*BuiltinCtorFunction)(Class*); /* * A PreClass represents the source-level definition of a php class, @@ -364,8 +363,7 @@ typedef AtomicSmartPtr ClassPtr; class Class : public AtomicCountable { public: friend class ExecutionContext; - friend class HPHP::ObjectData; - friend class Instance; + friend class ObjectData; friend class Unit; enum class Avail { @@ -540,7 +538,7 @@ public: const InitVec& pinitVec() const { return m_pinitVec; } const PropInitVec& declPropInit() const { return m_declPropInit; } - // ObjectData attributes, to be set during Instance initialization. + // ObjectData attributes, to be set during instance initialization. int getODAttrs() const { return m_ODAttrs; } int builtinPropSize() const { return m_builtinPropSize; } @@ -819,14 +817,14 @@ private: // Properties. // - // Each Instance is created with enough trailing space to directly store the - // vector of declared properties. To look up a property by name and - // determine whether it is declared, use m_declPropMap. If the declared - // property index is already known (as may be the case when executing via the - // TC), property metadata in m_declPropInfo can be directly accessed. + // Each ObjectData is created with enough trailing space to directly store + // the vector of declared properties. To look up a property by name and + // determine whether it is declared, use m_declPropMap. If the declared + // property index is already known (as may be the case when executing via + // the TC), property metadata in m_declPropInfo can be directly accessed. // - // m_declPropInit is indexed by the Slot values from - // m_declProperties, and contains initialization information. + // m_declPropInit is indexed by the Slot values from m_declProperties, and + // contains initialization information. PropMap m_declProperties; PropInitVec m_declPropInit; @@ -866,6 +864,6 @@ struct class_same { } }; - } // HPHP::VM +} // HPHP #endif diff --git a/hphp/runtime/vm/jit/codegen.cpp b/hphp/runtime/vm/jit/codegen.cpp index 7253c01c2..a71fd1f0f 100644 --- a/hphp/runtime/vm/jit/codegen.cpp +++ b/hphp/runtime/vm/jit/codegen.cpp @@ -3402,8 +3402,9 @@ const Func* loadClassCtor(Class* cls) { return f; } -Instance* createClHelper(Class* cls, int numArgs, ActRec* ar, TypedValue* sp) { - Instance* newObj = newInstance(cls); +ObjectData* createClHelper(Class* cls, int numArgs, ActRec* ar, + TypedValue* sp) { + ObjectData* newObj = newInstance(cls); newObj->incRefCount(); return static_cast(newObj)->init(numArgs, ar, sp); } @@ -3449,11 +3450,11 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) { SyncOptions::kSyncPoint, ArgGroup(m_regs).imm((uint64_t)cls)); } else { - size_t size = Instance::sizeForNProps(cls->numDeclProperties()); + size_t size = ObjectData::sizeForNProps(cls->numDeclProperties()); int allocator = object_alloc_size_to_index(size); assert(allocator != -1); cgCallHelper(m_as, - (TCA)getMethodPtr(&Instance::newInstanceRaw), + (TCA)getMethodPtr(&ObjectData::newInstanceRaw), dstReg, SyncOptions::kSyncPoint, ArgGroup(m_regs).imm((uint64_t)cls).imm(allocator)); @@ -3518,7 +3519,7 @@ void CodeGenerator::cgAllocObjFast(IRInstruction* inst) { if (cls->callsCustomInstanceInit()) { // callCustomInstanceInit returns the instance in rax cgCallHelper(m_as, - (TCA)getMethodPtr(&Instance::callCustomInstanceInit), + (TCA)getMethodPtr(&ObjectData::callCustomInstanceInit), dstReg, SyncOptions::kSyncPoint, ArgGroup(m_regs).reg(dstReg)); diff --git a/hphp/runtime/vm/jit/codegen.h b/hphp/runtime/vm/jit/codegen.h index e8651a1b3..b69e6be69 100644 --- a/hphp/runtime/vm/jit/codegen.h +++ b/hphp/runtime/vm/jit/codegen.h @@ -547,7 +547,7 @@ private: const Func* loadClassCtor(Class* cls); -Instance* createClHelper(Class*, int, ActRec*, TypedValue*); +ObjectData* createClHelper(Class*, int, ActRec*, TypedValue*); void genCodeForTrace(IRTrace* trace, CodeGenerator::Asm& a, diff --git a/hphp/runtime/vm/jit/translator-runtime.cpp b/hphp/runtime/vm/jit/translator-runtime.cpp index bc4828bbd..a7868375c 100644 --- a/hphp/runtime/vm/jit/translator-runtime.cpp +++ b/hphp/runtime/vm/jit/translator-runtime.cpp @@ -226,7 +226,7 @@ void raisePropertyOnNonObject() { } void raiseUndefProp(ObjectData* base, const StringData* name) { - static_cast(base)->raiseUndefProp(name); + base->raiseUndefProp(name); } void raise_error_sd(const StringData *msg) { diff --git a/hphp/runtime/vm/jit/translator-x64.cpp b/hphp/runtime/vm/jit/translator-x64.cpp index 425b0c6c3..9096ef0b2 100644 --- a/hphp/runtime/vm/jit/translator-x64.cpp +++ b/hphp/runtime/vm/jit/translator-x64.cpp @@ -2893,11 +2893,11 @@ bool TranslatorX64::eagerRecord(const Func* func) { return false; } -Instance* +ObjectData* HOT_FUNC_VM newInstanceHelper(Class* cls, int numArgs, ActRec* ar, ActRec* prevAr) { const Func* f = cls->getCtor(); - Instance* ret = nullptr; + ObjectData* ret = nullptr; if (UNLIKELY(!(f->attrs() & AttrPublic))) { VMRegAnchor _; UNUSED MethodLookup::LookupResult res = diff --git a/hphp/runtime/vm/jit/translator-x64.h b/hphp/runtime/vm/jit/translator-x64.h index a11c1d3b0..914197a2a 100644 --- a/hphp/runtime/vm/jit/translator-x64.h +++ b/hphp/runtime/vm/jit/translator-x64.h @@ -637,13 +637,13 @@ int64_t decodeCufIterHelper(Iter* it, TypedValue func); // These could be static but are used in hopt/codegen.cpp void raiseUndefVariable(StringData* nm); void defFuncHelper(Func *f); -Instance* newInstanceHelper(Class* cls, int numArgs, ActRec* ar, - ActRec* prevAr); -Instance* newInstanceHelperCached(Class** classCache, - const StringData* clsName, int numArgs, - ActRec* ar, ActRec* prevAr); -Instance* newInstanceHelperNoCtorCached(Class** classCache, - const StringData* clsName); +ObjectData* newInstanceHelper(Class* cls, int numArgs, ActRec* ar, + ActRec* prevAr); +ObjectData* newInstanceHelperCached(Class** classCache, + const StringData* clsName, int numArgs, + ActRec* ar, ActRec* prevAr); +ObjectData* newInstanceHelperNoCtorCached(Class** classCache, + const StringData* clsName); bool isNormalPropertyAccess(const NormalizedInstruction& i, int propInput, diff --git a/hphp/runtime/vm/member_operations.cpp b/hphp/runtime/vm/member_operations.cpp index 35ed153a3..259c13fac 100644 --- a/hphp/runtime/vm/member_operations.cpp +++ b/hphp/runtime/vm/member_operations.cpp @@ -29,14 +29,14 @@ StringData* prepareAnyKey(TypedValue* tv) { } } -void objArrayAccess(Instance* base) { +void objArrayAccess(ObjectData* base) { assert(!base->isCollection()); if (!base->getVMClass()->classof(SystemLib::s_ArrayAccessClass)) { raise_error("Object does not implement ArrayAccess"); } } -TypedValue* objOffsetGet(TypedValue& tvRef, Instance* base, +TypedValue* objOffsetGet(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate /* = true */) { if (validate) { objArrayAccess(base); @@ -51,7 +51,7 @@ TypedValue* objOffsetGet(TypedValue& tvRef, Instance* base, return result; } -static bool objOffsetExists(Instance* base, CVarRef offset) { +static bool objOffsetExists(ObjectData* base, CVarRef offset) { objArrayAccess(base); TypedValue tvResult; tvWriteUninit(&tvResult); @@ -65,12 +65,12 @@ static bool objOffsetExists(Instance* base, CVarRef offset) { return bool(tvResult.m_data.num); } -bool objOffsetIsset(TypedValue& tvRef, Instance* base, CVarRef offset, +bool objOffsetIsset(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate /* = true */) { return objOffsetExists(base, offset); } -bool objOffsetEmpty(TypedValue& tvRef, Instance* base, CVarRef offset, +bool objOffsetEmpty(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate /* = true */) { if (!objOffsetExists(base, offset)) { return true; @@ -80,7 +80,7 @@ bool objOffsetEmpty(TypedValue& tvRef, Instance* base, CVarRef offset, return empty(tvAsCVarRef(result)); } -void objOffsetAppend(Instance* base, TypedValue* val, +void objOffsetAppend(ObjectData* base, TypedValue* val, bool validate /* = true */) { assert(!base->isCollection()); if (validate) { @@ -89,7 +89,7 @@ void objOffsetAppend(Instance* base, TypedValue* val, objOffsetSet(base, init_null_variant, val, false); } -void objOffsetSet(Instance* base, CVarRef offset, TypedValue* val, +void objOffsetSet(ObjectData* base, CVarRef offset, TypedValue* val, bool validate /* = true */) { if (validate) { objArrayAccess(base); @@ -105,7 +105,7 @@ void objOffsetSet(Instance* base, CVarRef offset, TypedValue* val, tvRefcountedDecRef(&tvResult); } -void objOffsetUnset(Instance* base, CVarRef offset) { +void objOffsetUnset(ObjectData* base, CVarRef offset) { objArrayAccess(base); static StringData* sd__offsetUnset = StringData::GetStaticString("offsetUnset"); diff --git a/hphp/runtime/vm/member_operations.h b/hphp/runtime/vm/member_operations.h index c949f596e..006f6984f 100644 --- a/hphp/runtime/vm/member_operations.h +++ b/hphp/runtime/vm/member_operations.h @@ -126,17 +126,17 @@ inline void initScratchKey(TypedValue& tv, TypedValue*& key) { } } -void objArrayAccess(Instance* base); -TypedValue* objOffsetGet(TypedValue& tvRef, Instance* base, +void objArrayAccess(ObjectData* base); +TypedValue* objOffsetGet(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate=true); -bool objOffsetIsset(TypedValue& tvRef, Instance* base, CVarRef offset, +bool objOffsetIsset(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate=true); -bool objOffsetEmpty(TypedValue& tvRef, Instance* base, CVarRef offset, +bool objOffsetEmpty(TypedValue& tvRef, ObjectData* base, CVarRef offset, bool validate=true); -void objOffsetSet(Instance* base, CVarRef offset, TypedValue* val, +void objOffsetSet(ObjectData* base, CVarRef offset, TypedValue* val, bool validate=true); -void objOffsetAppend(Instance* base, TypedValue* val, bool validate=true); -void objOffsetUnset(Instance* base, CVarRef offset); +void objOffsetAppend(ObjectData* base, TypedValue* val, bool validate=true); +void objOffsetUnset(ObjectData* base, CVarRef offset); StringData* prepareAnyKey(TypedValue* tv); @@ -169,14 +169,12 @@ inline ALWAYS_INLINE void opPre(TypedValue*& base, DataType& type) { } } -inline TypedValue* ElemArrayRawKey(ArrayData* base, - int64_t key) { +inline TypedValue* ElemArrayRawKey(ArrayData* base, int64_t key) { TypedValue* result = base->nvGet(key); return result ? result : (TypedValue*)&null_variant; } -inline TypedValue* ElemArrayRawKey(ArrayData* base, - StringData* key) { +inline TypedValue* ElemArrayRawKey(ArrayData* base, StringData* key) { int64_t n; TypedValue* result = !key->isStrictlyInteger(n) ? base->nvGet(key) : base->nvGet(n); @@ -184,8 +182,7 @@ inline TypedValue* ElemArrayRawKey(ArrayData* base, } template -inline TypedValue* ElemArray(ArrayData* base, - TypedValue* key) { +inline TypedValue* ElemArray(ArrayData* base, TypedValue* key) { TypedValue* result; if (keyType == KeyType::Any) { DataType rtt = key->m_type; @@ -323,7 +320,7 @@ inline TypedValue* ElemDArray(TypedValue* base, TypedValue* key) { // $result template inline TypedValue* ElemD(TypedValue& tvScratch, TypedValue& tvRef, - TypedValue* base, TypedValue* key) { + TypedValue* base, TypedValue* key) { TypedValue scratch; TypedValue* result; DataType type; @@ -414,7 +411,7 @@ inline TypedValue* ElemD(TypedValue& tvScratch, TypedValue& tvRef, // $result template inline TypedValue* ElemU(TypedValue& tvScratch, TypedValue& tvRef, - TypedValue* base, TypedValue* key) { + TypedValue* base, TypedValue* key) { TypedValue* result = nullptr; DataType type; opPre(base, type); @@ -589,16 +586,16 @@ arrayRefShuffle(ArrayData* oldData, ArrayData* newData, TypedValue* base) { } inline ArrayData* SetElemArrayRawKey(ArrayData* a, - int64_t key, - Cell* value, - bool copy) { + int64_t key, + Cell* value, + bool copy) { return a->set(key, tvCellAsCVarRef(value), copy); } inline ArrayData* SetElemArrayRawKey(ArrayData* a, - StringData* key, - Cell* value, - bool copy) { + StringData* key, + Cell* value, + bool copy) { int64_t n; if (key->isStrictlyInteger(n)) { return a->set(n, tvCellAsCVarRef(value), copy); @@ -609,7 +606,7 @@ inline ArrayData* SetElemArrayRawKey(ArrayData* a, template inline void SetElemArray(TypedValue* base, TypedValue* key, - Cell* value) { + Cell* value) { ArrayData* a = base->m_data.parr; ArrayData* newData = a; bool copy = (a->getCount() > 1) @@ -849,7 +846,7 @@ inline void SetNewElem(TypedValue* base, Cell* value) { } inline TypedValue* SetOpElemEmptyish(unsigned char op, TypedValue* base, - TypedValue* key, Cell* rhs) { + TypedValue* key, Cell* rhs) { Array a = Array::Create(); TypedValue* result = (TypedValue*)&a.lvalAt(tvAsCVarRef(key)); tvAsVariant(base) = a; @@ -868,8 +865,8 @@ inline TypedValue* SetOpElemNumberish(TypedValue& tvScratch) { template inline TypedValue* SetOpElem(TypedValue& tvScratch, TypedValue& tvRef, - unsigned char op, TypedValue* base, - TypedValue* key, Cell* rhs) { + unsigned char op, TypedValue* base, + TypedValue* key, Cell* rhs) { TypedValue scratch; TypedValue* result; DataType type; @@ -930,7 +927,7 @@ inline TypedValue* SetOpElem(TypedValue& tvScratch, TypedValue& tvRef, } inline TypedValue* SetOpNewElemEmptyish(unsigned char op, - TypedValue* base, Cell* rhs) { + TypedValue* base, Cell* rhs) { Array a = Array::Create(); TypedValue* result = (TypedValue*)&a.lvalAt(); tvAsVariant(base) = a; @@ -943,8 +940,8 @@ inline TypedValue* SetOpNewElemNumberish(TypedValue& tvScratch) { return &tvScratch; } inline TypedValue* SetOpNewElem(TypedValue& tvScratch, TypedValue& tvRef, - unsigned char op, TypedValue* base, - Cell* rhs) { + unsigned char op, TypedValue* base, + Cell* rhs) { TypedValue* result; DataType type; opPre(base, type); @@ -1001,7 +998,7 @@ inline TypedValue* SetOpNewElem(TypedValue& tvScratch, TypedValue& tvRef, template inline void IncDecBody(unsigned char op, TypedValue* fr, - TypedValue* to) { + TypedValue* to) { if (fr->m_type == KindOfInt64) { switch ((IncDecOp)op) { case PreInc: { @@ -1083,7 +1080,7 @@ inline void IncDecBody(unsigned char op, TypedValue* fr, template inline void IncDecElemEmptyish(unsigned char op, TypedValue* base, - TypedValue* key, TypedValue& dest) { + TypedValue* key, TypedValue& dest) { Array a = Array::Create(); TypedValue* result = (TypedValue*)&a.lvalAt(tvAsCVarRef(key)); tvAsVariant(base) = a; @@ -1102,8 +1099,8 @@ inline void IncDecElemNumberish(TypedValue& dest) { } template inline void IncDecElem(TypedValue& tvScratch, TypedValue& tvRef, - unsigned char op, TypedValue* base, - TypedValue* key, TypedValue& dest) { + unsigned char op, TypedValue* base, + TypedValue* key, TypedValue& dest) { TypedValue scratch; DataType type; opPre(base, type); @@ -1159,7 +1156,7 @@ inline void IncDecElem(TypedValue& tvScratch, TypedValue& tvRef, template inline void IncDecNewElemEmptyish(unsigned char op, TypedValue* base, - TypedValue& dest) { + TypedValue& dest) { Array a = Array::Create(); TypedValue* result = (TypedValue*)&a.lvalAt(); tvAsVariant(base) = a; @@ -1174,8 +1171,8 @@ inline void IncDecNewElemNumberish(TypedValue& dest) { } template inline void IncDecNewElem(TypedValue& tvScratch, TypedValue& tvRef, - unsigned char op, TypedValue* base, - TypedValue& dest) { + unsigned char op, TypedValue* base, + TypedValue& dest) { DataType type; opPre(base, type); switch (type) { @@ -1226,12 +1223,12 @@ inline void IncDecNewElem(TypedValue& tvScratch, TypedValue& tvRef, } inline ArrayData* UnsetElemArrayRawKey(ArrayData* a, int64_t key, - bool copy) { + bool copy) { return a->remove(key, copy); } inline ArrayData* UnsetElemArrayRawKey(ArrayData* a, StringData* key, - bool copy) { + bool copy) { int64_t n; if (!key->isStrictlyInteger(n)) { return a->remove(StrNR(key), copy); @@ -1303,19 +1300,19 @@ inline DataType propPreNull(TypedValue& tvScratch, TypedValue*& result) { } return KindOfNull; } -inline Instance* createDefaultObject() { +inline ObjectData* createDefaultObject() { raise_warning(Strings::CREATING_DEFAULT_OBJECT); - Instance* obj = newInstance(SystemLib::s_stdclassClass); + ObjectData* obj = newInstance(SystemLib::s_stdclassClass); return obj; } template inline DataType propPreStdclass(TypedValue& tvScratch, - TypedValue*& result, TypedValue* base) { + TypedValue*& result, TypedValue* base) { if (!define) { return propPreNull(tvScratch, result); } // TODO(#1124706): We don't want to do this anymore. - Instance* obj = createDefaultObject(); + ObjectData* obj = createDefaultObject(); tvRefcountedDecRef(base); base->m_type = KindOfObject; base->m_data.pobj = obj; @@ -1326,7 +1323,7 @@ inline DataType propPreStdclass(TypedValue& tvScratch, template inline DataType propPre(TypedValue& tvScratch, TypedValue*& result, - TypedValue*& base) { + TypedValue*& base) { DataType type; opPre(base, type); switch (type) { @@ -1378,9 +1375,9 @@ inline TypedValue* Prop(TypedValue& tvScratch, TypedValue& tvRef, assert(!warn || !unset); TypedValue* result = nullptr; StringData* keySD = nullptr; - Instance* instance; + ObjectData* instance; if (baseIsObj) { - instance = reinterpret_cast(base); + instance = reinterpret_cast(base); } else { DataType t = propPre(tvScratch, result, base); if (t == KindOfNull) { @@ -1404,7 +1401,7 @@ inline TypedValue* Prop(TypedValue& tvScratch, TypedValue& tvRef, } template -inline bool IssetEmptyElemObj(TypedValue& tvRef, Instance* instance, +inline bool IssetEmptyElemObj(TypedValue& tvRef, ObjectData* instance, TypedValue* key) { if (useEmpty) { if (LIKELY(instance->isCollection())) { @@ -1423,13 +1420,12 @@ inline bool IssetEmptyElemObj(TypedValue& tvRef, Instance* instance, template inline bool IssetEmptyElem(TypedValue& tvScratch, TypedValue& tvRef, - TypedValue* base, - TypedValue* key) { + TypedValue* base, TypedValue* key) { TypedValue scratch; if (isObj) { initScratchKey(scratch, key); return IssetEmptyElemObj( - tvRef, reinterpret_cast(base), key); + tvRef, reinterpret_cast(base), key); } TypedValue* result; @@ -1461,8 +1457,7 @@ inline bool IssetEmptyElem(TypedValue& tvScratch, TypedValue& tvRef, } case KindOfObject: { initScratchKey(scratch, key); - return IssetEmptyElemObj( - tvRef, static_cast(base->m_data.pobj), key); + return IssetEmptyElemObj(tvRef, base->m_data.pobj, key); break; } default: { @@ -1478,8 +1473,8 @@ inline bool IssetEmptyElem(TypedValue& tvScratch, TypedValue& tvRef, } template -inline bool IssetEmptyPropObj(Class* ctx, Instance* instance, - TypedValue* key) { +inline bool IssetEmptyPropObj(Class* ctx, ObjectData* instance, + TypedValue* key) { StringData* keySD; bool issetEmptyResult; keySD = prepareKey(key); @@ -1491,11 +1486,10 @@ inline bool IssetEmptyPropObj(Class* ctx, Instance* instance, } template -inline bool IssetEmptyProp(Class* ctx, TypedValue* base, - TypedValue* key) { +inline bool IssetEmptyProp(Class* ctx, TypedValue* base, TypedValue* key) { if (isObj) { return IssetEmptyPropObj( - ctx, reinterpret_cast(base), key); + ctx, reinterpret_cast(base), key); } TypedValue tvScratch; @@ -1523,8 +1517,8 @@ inline void SetPropNull(Cell* val) { } } inline void SetPropStdclass(TypedValue* base, TypedValue* key, - Cell* val) { - Instance* obj = createDefaultObject(); + Cell* val) { + ObjectData* obj = createDefaultObject(); obj->incRefCount(); StringData* keySD = prepareKey(key); obj->setProp(nullptr, keySD, (TypedValue*)val); @@ -1535,8 +1529,8 @@ inline void SetPropStdclass(TypedValue* base, TypedValue* key, } template -inline void SetPropObj(Class* ctx, Instance* instance, - TypedValue* key, Cell* val) { +inline void SetPropObj(Class* ctx, ObjectData* instance, + TypedValue* key, Cell* val) { StringData* keySD = prepareKey(key); // Set property. instance->setProp(ctx, keySD, val); @@ -1545,11 +1539,9 @@ inline void SetPropObj(Class* ctx, Instance* instance, // $base->$key = $val template -inline void SetProp(Class* ctx, TypedValue* base, TypedValue* key, - Cell* val) { +inline void SetProp(Class* ctx, TypedValue* base, TypedValue* key, Cell* val) { if (isObj) { - SetPropObj(ctx, reinterpret_cast(base), - key, val); + SetPropObj(ctx, reinterpret_cast(base), key, val); return; } @@ -1583,8 +1575,7 @@ inline void SetProp(Class* ctx, TypedValue* base, TypedValue* key, break; } case KindOfObject: { - SetPropObj(ctx, static_cast(base->m_data.pobj), - key, val); + SetPropObj(ctx, base->m_data.pobj, key, val); break; } default: { @@ -1600,9 +1591,9 @@ inline TypedValue* SetOpPropNull(TypedValue& tvScratch) { return &tvScratch; } inline TypedValue* SetOpPropStdclass(TypedValue& tvRef, unsigned char op, - TypedValue* base, TypedValue* key, - Cell* rhs) { - Instance* obj = createDefaultObject(); + TypedValue* base, TypedValue* key, + Cell* rhs) { + ObjectData* obj = createDefaultObject(); obj->incRefCount(); tvRefcountedDecRef(base); base->m_type = KindOfObject; @@ -1618,8 +1609,8 @@ inline TypedValue* SetOpPropStdclass(TypedValue& tvRef, unsigned char op, template inline TypedValue* SetOpPropObj(TypedValue& tvRef, Class* ctx, - unsigned char op, Instance* instance, - TypedValue* key, Cell* rhs) { + unsigned char op, ObjectData* instance, + TypedValue* key, Cell* rhs) { StringData* keySD = prepareKey(key); TypedValue* result = instance->setOpProp(tvRef, ctx, op, keySD, rhs); releaseKey(keySD); @@ -1629,13 +1620,14 @@ inline TypedValue* SetOpPropObj(TypedValue& tvRef, Class* ctx, // $base->$key = $rhs template inline TypedValue* SetOpProp(TypedValue& tvScratch, TypedValue& tvRef, - Class* ctx, unsigned char op, - TypedValue* base, TypedValue* key, - Cell* rhs) { + Class* ctx, unsigned char op, + TypedValue* base, TypedValue* key, + Cell* rhs) { TypedValue scratch; if (isObj) { return SetOpPropObj(tvRef, ctx, op, - reinterpret_cast(base), key, rhs); + reinterpret_cast(base), + key, rhs); } TypedValue* result; @@ -1689,8 +1681,8 @@ inline void IncDecPropNull(TypedValue& dest) { } template inline void IncDecPropStdclass(unsigned char op, TypedValue* base, - TypedValue* key, TypedValue& dest) { - Instance* obj = createDefaultObject(); + TypedValue* key, TypedValue& dest) { + ObjectData* obj = createDefaultObject(); obj->incRefCount(); tvRefcountedDecRef(base); base->m_type = KindOfObject; @@ -1717,8 +1709,8 @@ inline void IncDecPropStdclass(unsigned char op, TypedValue* base, template inline void IncDecPropObj(TypedValue& tvRef, Class* ctx, - unsigned char op, Instance* base, - TypedValue* key, TypedValue& dest) { + unsigned char op, ObjectData* base, + TypedValue* key, TypedValue& dest) { StringData* keySD = prepareKey(key); base->incDecProp(tvRef, ctx, op, keySD, dest); releaseKey(keySD); @@ -1726,13 +1718,13 @@ inline void IncDecPropObj(TypedValue& tvRef, Class* ctx, template inline void IncDecProp(TypedValue& tvScratch, TypedValue& tvRef, - Class* ctx, unsigned char op, - TypedValue* base, TypedValue* key, - TypedValue& dest) { + Class* ctx, unsigned char op, + TypedValue* base, TypedValue* key, + TypedValue& dest) { TypedValue scratch; if (isObj) { IncDecPropObj(tvRef, ctx, op, - reinterpret_cast(base), + reinterpret_cast(base), key, dest); return; } @@ -1778,9 +1770,8 @@ inline void IncDecProp(TypedValue& tvScratch, TypedValue& tvRef, } template -inline void UnsetProp(Class* ctx, TypedValue* base, - TypedValue* key) { - Instance* instance; +inline void UnsetProp(Class* ctx, TypedValue* base, TypedValue* key) { + ObjectData* instance; if (!isObj) { DataType type; opPre(base, type); @@ -1791,7 +1782,7 @@ inline void UnsetProp(Class* ctx, TypedValue* base, } instance = instanceFromTv(base); } else { - instance = reinterpret_cast(base); + instance = reinterpret_cast(base); } // Prepare key. StringData* keySD = prepareKey(key); diff --git a/hphp/runtime/vm/object_allocator_sizes.h b/hphp/runtime/vm/object_allocator_sizes.h index 62f83d898..8e6215db0 100644 --- a/hphp/runtime/vm/object_allocator_sizes.h +++ b/hphp/runtime/vm/object_allocator_sizes.h @@ -19,16 +19,16 @@ namespace HPHP { -// SmartAllocator (or, to be more specific, ObjectAllocator) is templatized by -// the size of the chunks it allocates. This works fine when we're only -// allocating objects of fixed sizes, known at compile time. However, the VM -// class "Instance" is of variable size (having room for a property vector at -// the end), and the range of sizes it will take on is unknowable at compile -// time. +// SmartAllocator (or, to be more specific, ObjectAllocator) is templatized +// by the size of the chunks it allocates. This works fine when we're only +// allocating objects of fixed sizes, known at compile time. However, the +// ObjectData class is of variable size (having room for a property vector +// at the end), and the range of sizes it will take on is unknowable at +// compile time. // // To work around this, we instantiate the ObjectAllocator template with a size -// from every possible size class. This way, any size class that Instance might -// end up falling into will have an ObjectAllocator. +// from every possible size class. This way, any size class that ObjectData +// might end up falling into will have an ObjectAllocator. int InitializeAllocators(); } diff --git a/hphp/runtime/vm/runtime.h b/hphp/runtime/vm/runtime.h index 0b6164f14..268af715b 100644 --- a/hphp/runtime/vm/runtime.h +++ b/hphp/runtime/vm/runtime.h @@ -182,10 +182,10 @@ Unit* build_native_class_unit(const HhbcExtClassInfo* builtinClasses, HphpArray* pack_args_into_array(ActRec* ar, int nargs); -inline Instance* +inline ObjectData* newInstance(Class* cls) { assert(cls); - auto* inst = Instance::newInstance(cls); + auto* inst = ObjectData::newInstance(cls); if (UNLIKELY(RuntimeOption::EnableObjDestructCall)) { g_vmContext->m_liveBCObjs.insert(inst); } diff --git a/hphp/system/idl/continuation.idl.json b/hphp/system/idl/continuation.idl.json index 411ca64bc..cf4a4c96e 100644 --- a/hphp/system/idl/continuation.idl.json +++ b/hphp/system/idl/continuation.idl.json @@ -190,16 +190,6 @@ ], "args": [ ] - }, - { - "name": "__clone", - "return": { - "type": "Variant" - }, - "flags": [ - ], - "args": [ - ] } ], "consts": [ diff --git a/hphp/system/systemlib.cpp b/hphp/system/systemlib.cpp index 64524210e..496cb7e2e 100644 --- a/hphp/system/systemlib.cpp +++ b/hphp/system/systemlib.cpp @@ -24,7 +24,7 @@ namespace HPHP { /////////////////////////////////////////////////////////////////////////////// #define ALLOC_OBJECT_STUB_RETURN(name) \ - HPHP::Instance::newInstance(SystemLib::s_##name##Class) + ObjectData::newInstance(SystemLib::s_##name##Class) #define ALLOC_OBJECT_STUB(name) \ ObjectData* SystemLib::Alloc##name##Object() { \ @@ -45,16 +45,16 @@ SYSTEMLIB_CLASSES(DEFINE_SYSTEMLIB_CLASS) #undef DEFINE_SYSTEMLIB_CLASS ObjectData* SystemLib::AllocStdClassObject() { - return HPHP::Instance::newInstance(SystemLib::s_stdclassClass); + return ObjectData::newInstance(SystemLib::s_stdclassClass); } ObjectData* SystemLib::AllocPinitSentinel() { - return HPHP::Instance::newInstance(SystemLib::s_pinitSentinelClass); + return ObjectData::newInstance(SystemLib::s_pinitSentinelClass); } #define CREATE_AND_CONSTRUCT(clsname, params) \ - HPHP::Instance* inst = \ - HPHP::Instance::newInstance(SystemLib::s_##clsname##Class); \ + ObjectData* inst = \ + ObjectData::newInstance(SystemLib::s_##clsname##Class); \ TypedValue ret; \ { \ /* Increment refcount across call to ctor, so the object doesn't */ \ diff --git a/hphp/tools/bootstrap/gen-ext-hhvm.cpp b/hphp/tools/bootstrap/gen-ext-hhvm.cpp index 2ade5d85b..6d382b31b 100644 --- a/hphp/tools/bootstrap/gen-ext-hhvm.cpp +++ b/hphp/tools/bootstrap/gen-ext-hhvm.cpp @@ -58,11 +58,11 @@ constexpr char* g_allIncludes = R"( void emitCtorHelper(const fbstring& className, std::ostream& out) { out << folly::format( R"( -HPHP::Instance* new_{0:s}_Instance(HPHP::Class* cls) {{ +ObjectData* new_{0:s}_Instance(HPHP::Class* cls) {{ size_t nProps = cls->numDeclProperties(); size_t builtinPropSize = sizeof(c_{0:s}) - sizeof(ObjectData); - size_t size = HPHP::Instance::sizeForNProps(nProps) + builtinPropSize; - HPHP::Instance *inst = (HPHP::Instance*)ALLOCOBJSZ(size); + size_t size = ObjectData::sizeForNProps(nProps) + builtinPropSize; + ObjectData *inst = (ObjectData*)ALLOCOBJSZ(size); new ((void *)inst) c_{0:s}(cls); return inst; }})", diff --git a/hphp/tools/bootstrap/gen-infotabs.cpp b/hphp/tools/bootstrap/gen-infotabs.cpp index 491854c56..ab69b684e 100644 --- a/hphp/tools/bootstrap/gen-infotabs.cpp +++ b/hphp/tools/bootstrap/gen-infotabs.cpp @@ -69,7 +69,7 @@ int main(int argc, const char* argv[]) { for (auto const& klass : classes) { if (!(klass.flags() & IsCppAbstract)) { - cpp << "Instance* new_" << klass.name() << "_Instance(Class*);\n"; + cpp << "ObjectData* new_" << klass.name() << "_Instance(Class*);\n"; classesWithCtors.insert(klass.name()); } for (auto const& func : klass.methods()) {