From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- js/public/RefCounted.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 js/public/RefCounted.h (limited to 'js/public/RefCounted.h') diff --git a/js/public/RefCounted.h b/js/public/RefCounted.h new file mode 100644 index 0000000000..de5a72f2d8 --- /dev/null +++ b/js/public/RefCounted.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef js_RefCounted_h +#define js_RefCounted_h + +#include "mozilla/Atomics.h" +#include "mozilla/RefCountType.h" + +#include "js/Utility.h" + +// These types implement the same interface as mozilla::(Atomic)RefCounted and +// must be used instead of mozilla::(Atomic)RefCounted for everything in +// SpiderMonkey. There are two reasons: +// - Release() needs to call js_delete, not delete +// - SpiderMonkey does not have MOZILLA_INTERNAL_API defined which can lead +// to ODR violations that show up as spurious leak reports when ref-counted +// types are allocated by SpiderMonkey and released by Gecko (or vice versa). + +namespace js { + +template +class RefCounted { + static const MozRefCountType DEAD = 0xffffdead; + + protected: + RefCounted() : mRefCnt(0) {} + ~RefCounted() { MOZ_ASSERT(mRefCnt == DEAD); } + + public: + void AddRef() const { + MOZ_ASSERT(int32_t(mRefCnt) >= 0); + ++mRefCnt; + } + + void Release() const { + MOZ_ASSERT(int32_t(mRefCnt) > 0); + MozRefCountType cnt = --mRefCnt; + if (0 == cnt) { +#ifdef DEBUG + mRefCnt = DEAD; +#endif + js_delete(const_cast(static_cast(this))); + } + } + + private: + mutable MozRefCountType mRefCnt; +}; + +template +class AtomicRefCounted { + // On 64-bit systems, if the refcount type is small (say, 32 bits), there's + // a risk that it could overflow. So require it to be large enough. + + static_assert(sizeof(MozRefCountType) == sizeof(uintptr_t), + "You're at risk for ref count overflow."); + + static const MozRefCountType DEAD = ~MozRefCountType(0xffff) | 0xdead; + + protected: + AtomicRefCounted() = default; + ~AtomicRefCounted() { MOZ_ASSERT(mRefCnt == DEAD); } + + public: + void AddRef() const { + ++mRefCnt; + MOZ_ASSERT(mRefCnt != DEAD); + } + + void Release() const { + MOZ_ASSERT(mRefCnt != 0); + MozRefCountType cnt = --mRefCnt; + if (0 == cnt) { +#ifdef DEBUG + mRefCnt = DEAD; +#endif + js_delete(const_cast(static_cast(this))); + } + } + + bool hasOneRef() const { + MOZ_ASSERT(mRefCnt > 0); + return mRefCnt == 1; + } + + private: + mutable mozilla::Atomic mRefCnt{0}; +}; + +} // namespace js + +#endif /* js_RefCounted_h */ -- cgit v1.2.3