void nativeDataInstanceDtor(ObjectData* obj, const Class* cls) { assert(!cls->preClass()->builtinObjSize()); assert(!cls->preClass()->builtinODOffset()); obj->~ObjectData(); auto const nProps = size_t{cls->numDeclProperties()}; auto prop = reinterpret_cast<TypedValue*>(obj + 1); auto const stop = prop + nProps; for (; prop != stop; ++prop) { tvRefcountedDecRef(prop); } auto ndi = cls->getNativeDataInfo(); assert(ndi); if (ndi->destroy) { ndi->destroy(obj); } if (ndi->sweep) { removeSweepNode(getSweepNode(obj)); } size_t nativeDataSize = alignTypedValue(ndi->sz + sizeof(SweepNode)); size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize; void *ptr = obj; ptr = static_cast<char*>(ptr) - nativeDataSize; if (LIKELY(size <= kMaxSmartSize)) { return MM().smartFreeSizeLogged(ptr, size); } MM().smartFreeSizeBigLogged(ptr, size); }
/* Classes with NativeData structs allocate extra memory prior * to the ObjectData. * * [padding][NativeData][SweepNode][ObjectData](prop0)...(propN) * /\ * ObjectData* points here * * padding is added by alignTypedValue() to ensure that ObjectData* * falls on a memory alignment boundary * NativeData is info.sz bytes for the custom class Native Data * SweepNode is a link in the NativeData sweep list for this ND block */ ObjectData* nativeDataInstanceCtor(Class* cls) { Attr attrs = cls->attrs(); if (UNLIKELY(attrs & (AttrAbstract | AttrInterface | AttrTrait | AttrEnum))) { ObjectData::raiseAbstractClassError(cls); } auto ndi = cls->getNativeDataInfo(); size_t nativeDataSize = alignTypedValue(ndi->sz + sizeof(SweepNode)); size_t nProps = cls->numDeclProperties(); size_t size = ObjectData::sizeForNProps(nProps) + nativeDataSize; void *ptr = MM().objMallocLogged(size); auto obj = new (static_cast<char*>(ptr) + nativeDataSize) ObjectData(cls); obj->setAttribute(static_cast<ObjectData::Attribute>(ndi->odattrs)); if (ndi->init) { ndi->init(obj); } if (ndi->sweep) { prependSweepNode(getSweepNode(obj)); } if (UNLIKELY(cls->callsCustomInstanceInit())) { obj->callCustomInstanceInit(); } return obj; }
// return the full native header size, which is also the distance from // the allocated pointer to the ObjectData*. inline size_t ndsize(const NativeDataInfo* ndi) { return alignTypedValue(ndi->sz + sizeof(NativeNode)); }