Clean up InstanceDtor flags
[hiphop-php.git] / hphp / runtime / base / object-data-inl.h
blob0cce402ffe9a793d953328be3928c2fad77f07e9
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_OBJECT_DATA_INL_H_
18 #error "object-data-inl.h should only be included by object-data.h"
19 #endif
21 #include "hphp/system/systemlib.h"
23 namespace HPHP {
24 ///////////////////////////////////////////////////////////////////////////////
26 inline void ObjectData::resetMaxId() {
27 os_max_id = 0;
30 inline ObjectData::ObjectData(Class* cls)
31 : ObjectData(cls, 0, HeaderKind::Object)
34 inline ObjectData::ObjectData(Class* cls, uint16_t flags, HeaderKind kind)
35 : m_cls(cls)
37 m_hdr.init(flags, kind, 1);
38 assert(m_hdr.aux == flags && hasExactlyOneRef());
39 assert(isObjectKind(kind));
40 assert(!cls->needInitialization() || cls->initialized());
41 o_id = ++os_max_id;
42 if (flags & Attribute::IsCollection) {
43 // Whatever attribute we need to set, do it via flags and void runtime
44 // loading. These assertions guarantee that `instanceInit(cls)' is not
45 // needed for collections.
46 assertx(!(cls->getODAttrs() & ~static_cast<uint16_t>(flags)));
47 assertx(cls->numDeclProperties() == 0);
48 return;
50 instanceInit(cls);
53 inline ObjectData::ObjectData(Class* cls, NoInit) noexcept
54 : m_cls(cls)
56 m_hdr.init(0, HeaderKind::Object, 1);
57 assert(!m_hdr.aux && m_hdr.kind == HeaderKind::Object && hasExactlyOneRef());
58 assert(!cls->needInitialization() || cls->initialized());
59 o_id = ++os_max_id;
62 inline ObjectData::ObjectData(Class* cls,
63 uint16_t flags,
64 HeaderKind kind,
65 NoInit) noexcept
66 : m_cls(cls)
68 m_hdr.init(flags, kind, 1);
69 assert(m_hdr.aux == flags && hasExactlyOneRef());
70 assert(isObjectKind(kind));
71 assert(!cls->needInitialization() || cls->initialized());
72 assert(!(cls->getODAttrs() & ~static_cast<uint16_t>(flags)));
73 assert(cls->numDeclProperties() == 0);
74 o_id = ++os_max_id;
77 inline size_t ObjectData::heapSize() const {
78 return m_cls->builtinODTailSize() + sizeForNProps(m_cls->numDeclProperties());
81 inline ObjectData* ObjectData::newInstance(Class* cls) {
82 if (cls->needInitialization()) {
83 cls->initialize();
85 if (auto const ctor = cls->instanceCtor()) {
86 auto obj = ctor(cls);
87 assert(obj->checkCount());
88 return obj;
90 Attr attrs = cls->attrs();
91 if (UNLIKELY(attrs &
92 (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) {
93 raiseAbstractClassError(cls);
95 size_t nProps = cls->numDeclProperties();
96 size_t size = sizeForNProps(nProps);
97 auto& mm = MM();
98 auto const obj = new (mm.objMalloc(size)) ObjectData(cls);
99 assert(obj->hasExactlyOneRef());
100 if (UNLIKELY(cls->callsCustomInstanceInit())) {
102 This must happen after the constructor finishes,
103 because it can leak references to obj AND it can
104 throw exceptions. If we have this in the ObjectData
105 constructor, and it throws, obj will be partially
106 destroyed (ie ~ObjectData will be called, resetting
107 the vtable pointer) leaving dangling references
108 to the object (eg in backtraces).
110 obj->callCustomInstanceInit();
113 // callCustomInstanceInit may have inc-refd.
114 assert(obj->checkCount());
115 return obj;
118 inline void ObjectData::instanceInit(Class* cls) {
119 m_hdr.aux |= cls->getODAttrs();
121 size_t nProps = cls->numDeclProperties();
122 if (nProps > 0) {
123 if (cls->pinitVec().size() > 0) {
124 const Class::PropInitVec* propInitVec = m_cls->getPropData();
125 assert(propInitVec != nullptr);
126 assert(nProps == propInitVec->size());
127 if (!cls->hasDeepInitProps()) {
128 memcpy(propVec(), &(*propInitVec)[0], nProps * sizeof(TypedValue));
129 } else {
130 deepInitHelper(propVec(), &(*propInitVec)[0], nProps);
132 } else {
133 assert(nProps == cls->declPropInit().size());
134 memcpy(propVec(), &cls->declPropInit()[0], nProps * sizeof(TypedValue));
139 inline Class* ObjectData::getVMClass() const {
140 return m_cls;
143 inline void ObjectData::setVMClass(Class* cls) {
144 m_cls = cls;
147 inline bool ObjectData::instanceof(const Class* c) const {
148 return m_cls->classof(c);
151 inline bool ObjectData::isCollection() const {
152 return getAttribute(Attribute::IsCollection);
155 inline bool ObjectData::isMutableCollection() const {
156 return isCollection() && HPHP::isMutableCollection(collectionType());
159 inline bool ObjectData::isImmutableCollection() const {
160 return isCollection() && HPHP::isImmutableCollection(collectionType());
163 inline CollectionType ObjectData::collectionType() const {
164 assert(isValidCollection(static_cast<CollectionType>(m_hdr.kind)));
165 return static_cast<CollectionType>(m_hdr.kind);
168 inline HeaderKind ObjectData::headerKind() const {
169 return m_hdr.kind;
172 inline bool ObjectData::isIterator() const {
173 return instanceof(SystemLib::s_IteratorClass);
176 inline bool ObjectData::getAttribute(Attribute attr) const {
177 return m_hdr.aux & attr;
180 inline void ObjectData::setAttribute(Attribute attr) {
181 m_hdr.aux |= attr;
184 inline bool ObjectData::noDestruct() const {
185 return getAttribute(NoDestructor);
188 inline void ObjectData::setNoDestruct() {
189 setAttribute(NoDestructor);
192 inline void ObjectData::clearNoDestruct() {
193 m_hdr.aux &= ~NoDestructor;
196 inline bool ObjectData::hasInstanceDtor() const {
197 return m_hdr.aux & (IsCppBuiltin | HasNativeData);
200 inline int ObjectData::getId() const {
201 return o_id;
204 inline bool ObjectData::toBoolean() const {
205 if (UNLIKELY(getAttribute(CallToImpl))) {
206 return toBooleanImpl();
208 return true;
211 inline int64_t ObjectData::toInt64() const {
212 if (UNLIKELY(getAttribute(CallToImpl) && !isCollection())) {
213 return toInt64Impl();
215 raiseObjToIntNotice(classname_cstr());
216 return 1;
219 inline double ObjectData::toDouble() const {
220 if (UNLIKELY(getAttribute(CallToImpl) && !isCollection())) {
221 return toDoubleImpl();
223 return toInt64();
226 inline const Func* ObjectData::methodNamed(const StringData* sd) const {
227 return getVMClass()->lookupMethod(sd);
230 inline size_t ObjectData::sizeForNProps(Slot nProps) {
231 return sizeof(ObjectData) + sizeof(TypedValue) * nProps;
234 ///////////////////////////////////////////////////////////////////////////////