void tvDecRefHelper(DataType type, uint64_t datum) noexcept { assert(type == KindOfString || type == KindOfArray || type == KindOfObject || type == KindOfResource || type == KindOfRef); TypedValue tmp; tmp.m_type = type; tmp.m_data.num = datum; if (TV_GENERIC_DISPATCH(tmp, decReleaseCheck)) { g_destructors[typeToDestrIdx(type)]((void*)datum); } }
// the version of the high frequency function that is not inlined NEVER_INLINE Variant::Variant(const Variant& v) noexcept { constructValHelper(v); } /* * The destruct functions below all arbitrarily take RefData* as an * example of a refcounted object, then just cast to the proper type. * This is safe because we have compile time assertions that guarantee that * the _count field will always be exactly FAST_REFCOUNT_OFFSET bytes from * the beginning of the object for the StringData, ArrayData, ObjectData, * ResourceHdr, and RefData classes. */ static_assert(typeToDestrIdx(KindOfString) == 2, "String destruct index"); static_assert(typeToDestrIdx(KindOfArray) == 3, "Array destruct index"); static_assert(typeToDestrIdx(KindOfObject) == 4, "Object destruct index"); static_assert(typeToDestrIdx(KindOfResource) == 5, "Resource destruct index"); static_assert(typeToDestrIdx(KindOfRef) == 6, "Ref destruct index"); static_assert(kDestrTableSize == 7, "size of g_destructors[] must be kDestrTableSize"); RawDestructor g_destructors[] = { nullptr, nullptr, (RawDestructor)getMethodPtr(&StringData::release), (RawDestructor)getMethodPtr(&ArrayData::release), (RawDestructor)getMethodPtr(&ObjectData::release), // may replace at runtime
void tweak_variant_dtors() { if (RuntimeOption::EnableObjDestructCall) return; g_destructors[typeToDestrIdx(KindOfObject)] = (RawDestructor)getMethodPtr(&ObjectData::releaseNoObjDestructCheck); }
// the version of the high frequency function that is not inlined NEVER_INLINE Variant::Variant(const Variant& v) noexcept { constructValHelper(v); } /* * The destruct functions below all arbitrarily take RefData* as an * example of a refcounted object, then just cast to the proper type. * This is safe because we have compile time assertions that guarantee that * the _count field will always be exactly FAST_REFCOUNT_OFFSET bytes from * the beginning of the object for the StringData, ArrayData, ObjectData, * ResourceHdr, and RefData classes. */ static_assert(typeToDestrIdx(KindOfObject) == 16, "Object destruct index"); static_assert(typeToDestrIdx(KindOfResource) == 20, "Resource destruct index"); static_assert(typeToDestrIdx(KindOfVec) == 22, "Vec destruct index"); static_assert(typeToDestrIdx(KindOfString) == 24, "String destruct index"); static_assert(typeToDestrIdx(KindOfDict) == 26, "Dict destruct index"); static_assert(typeToDestrIdx(KindOfRef) == 28, "Ref destruct index"); static_assert(typeToDestrIdx(KindOfArray) == 29, "Array destruct index"); static_assert(typeToDestrIdx(KindOfKeyset) == 30, "Keyset destruct index"); static_assert(kDestrTableSize == 31, "size of g_destructors[] must be kDestrTableSize"); RawDestructor g_destructors[] = { nullptr, nullptr, nullptr,