Backed out 2 changesets (bug 1618121, bug 1617993) for assertion failure at nsTArray.h . CLOSED TREE

Backed out changeset e4d228335a49 (bug 1617993)
Backed out changeset b874484bdeb7 (bug 1618121)
This commit is contained in:
Narcis Beleuzu 2020-03-12 11:40:00 +02:00
Родитель 20b5709c6a
Коммит 02dfadf8c9
6 изменённых файлов: 127 добавлений и 193 удалений

Просмотреть файл

@ -20,37 +20,45 @@ enum class CheckingSupport {
Disabled,
};
template <typename T>
class CheckedUnsafePtr;
namespace detail {
class CheckedUnsafePtrBaseCheckingEnabled;
template <CheckingSupport>
class CheckedUnsafePtrBase;
struct CheckedUnsafePtrCheckData {
using Data = nsTArray<CheckedUnsafePtrBaseCheckingEnabled*>;
using Data = nsTArray<CheckedUnsafePtrBase<CheckingSupport::Enabled>*>;
DataMutex<Data> mPtrs{"mozilla::SupportsCheckedUnsafePtr"};
};
class CheckedUnsafePtrBaseCheckingEnabled {
template <>
class CheckedUnsafePtrBase<CheckingSupport::Disabled> {
protected:
template <typename Ptr>
void CopyDanglingFlagIfAvailableFrom(const Ptr&) {}
template <typename Ptr, typename F>
void WithCheckedUnsafePtrsImpl(Ptr, F&&) {}
};
template <>
class CheckedUnsafePtrBase<CheckingSupport::Enabled> {
friend class CheckedUnsafePtrBaseAccess;
protected:
constexpr CheckedUnsafePtrBaseCheckingEnabled() = default;
CheckedUnsafePtrBaseCheckingEnabled(
const CheckedUnsafePtrBaseCheckingEnabled& aOther) = default;
CheckedUnsafePtrBase() = default;
CheckedUnsafePtrBase(const CheckedUnsafePtrBase& aOther) = default;
// When copying an CheckedUnsafePtr, its mIsDangling member must be copied as
// well; otherwise the new copy might try to dereference a dangling pointer
// when destructed.
void CopyDanglingFlagIfAvailableFrom(
const CheckedUnsafePtrBaseCheckingEnabled& aOther) {
const CheckedUnsafePtrBase<CheckingSupport::Enabled>& aOther) {
mIsDangling = aOther.mIsDangling;
}
template <typename Ptr>
using DisableForCheckedUnsafePtr = std::enable_if_t<
!std::is_base_of<CheckedUnsafePtrBaseCheckingEnabled, Ptr>::value>;
using DisableForCheckedUnsafePtr =
std::enable_if_t<!std::is_base_of<CheckedUnsafePtrBase, Ptr>::value>;
// When constructing an CheckedUnsafePtr from a different kind of pointer it's
// not possible to determine whether it's dangling; therefore it's undefined
@ -74,136 +82,11 @@ class CheckedUnsafePtrBaseCheckingEnabled {
class CheckedUnsafePtrBaseAccess {
protected:
static void SetDanglingFlag(CheckedUnsafePtrBaseCheckingEnabled& aBase) {
static void SetDanglingFlag(
CheckedUnsafePtrBase<CheckingSupport::Enabled>& aBase) {
aBase.mIsDangling = true;
}
};
template <typename T, CheckingSupport = T::SupportsChecking::value>
class CheckedUnsafePtrBase;
template <typename T, typename U, typename S = std::nullptr_t>
using EnableIfCompatible =
std::enable_if_t<std::is_base_of<T, std::remove_reference_t<decltype(
*std::declval<U>())>>::value,
S>;
template <typename T>
class CheckedUnsafePtrBase<T, CheckingSupport::Enabled>
: detail::CheckedUnsafePtrBaseCheckingEnabled {
public:
MOZ_IMPLICIT constexpr CheckedUnsafePtrBase(const std::nullptr_t = nullptr)
: mRawPtr(nullptr) {}
template <typename U, typename = EnableIfCompatible<T, U>>
MOZ_IMPLICIT CheckedUnsafePtrBase(const U& aPtr) {
Set(aPtr);
}
CheckedUnsafePtrBase(const CheckedUnsafePtrBase& aOther) {
Set(aOther.Downcast());
}
~CheckedUnsafePtrBase() { Reset(); }
CheckedUnsafePtr<T>& operator=(const std::nullptr_t) {
Reset();
return Downcast();
}
template <typename U>
EnableIfCompatible<T, U, CheckedUnsafePtr<T>&> operator=(const U& aPtr) {
Replace(aPtr);
return Downcast();
}
CheckedUnsafePtr<T>& operator=(const CheckedUnsafePtr<T>& aOther) {
if (&aOther != this) {
Replace(aOther);
}
return Downcast();
}
constexpr T* get() const { return mRawPtr; }
private:
template <typename U, CheckingSupport>
friend class CheckedUnsafePtrBase;
CheckedUnsafePtr<T>& Downcast() {
return static_cast<CheckedUnsafePtr<T>&>(*this);
}
const CheckedUnsafePtr<T>& Downcast() const {
return static_cast<const CheckedUnsafePtr<T>&>(*this);
}
using Base = detail::CheckedUnsafePtrBaseCheckingEnabled;
template <typename U>
void Replace(const U& aPtr) {
Reset();
Set(aPtr);
}
void Reset() {
WithCheckedUnsafePtrs(
[](Base* const aSelf,
detail::CheckedUnsafePtrCheckData::Data& aCheckedUnsafePtrs) {
const auto index = aCheckedUnsafePtrs.IndexOf(aSelf);
aCheckedUnsafePtrs.UnorderedRemoveElementAt(index);
});
mRawPtr = nullptr;
}
template <typename U>
void Set(const U& aPtr) {
this->CopyDanglingFlagIfAvailableFrom(aPtr);
mRawPtr = &*aPtr;
WithCheckedUnsafePtrs(
[](Base* const aSelf,
detail::CheckedUnsafePtrCheckData::Data& aCheckedUnsafePtrs) {
aCheckedUnsafePtrs.AppendElement(aSelf);
});
}
template <typename F>
void WithCheckedUnsafePtrs(F&& aClosure) {
this->WithCheckedUnsafePtrsImpl(mRawPtr, std::forward<F>(aClosure));
}
T* mRawPtr;
};
template <typename T>
class CheckedUnsafePtrBase<T, CheckingSupport::Disabled> {
public:
MOZ_IMPLICIT constexpr CheckedUnsafePtrBase(const std::nullptr_t = nullptr)
: mRawPtr(nullptr) {}
template <typename U, typename = EnableIfCompatible<T, U>>
MOZ_IMPLICIT constexpr CheckedUnsafePtrBase(const U& aPtr) : mRawPtr(aPtr) {}
constexpr CheckedUnsafePtr<T>& operator=(const std::nullptr_t) {
mRawPtr = nullptr;
return Downcast();
}
template <typename U>
constexpr EnableIfCompatible<T, U, CheckedUnsafePtr<T>&> operator=(
const U& aPtr) {
mRawPtr = aPtr;
return Downcast();
}
constexpr T* get() const { return mRawPtr; }
private:
constexpr CheckedUnsafePtr<T>& Downcast() {
return static_cast<CheckedUnsafePtr<T>&>(*this);
}
T* mRawPtr;
};
} // namespace detail
class CheckingPolicyAccess {
@ -335,46 +218,117 @@ class SupportsCheckedUnsafePtr
// can be used, has the same size, and imposes no additional thread-safety
// restrictions.
template <typename T>
class CheckedUnsafePtr : public detail::CheckedUnsafePtrBase<T> {
class CheckedUnsafePtr
: private detail::CheckedUnsafePtrBase<T::SupportsChecking::value> {
static_assert(
std::is_base_of<detail::SupportsCheckedUnsafePtrTag, T>::value,
"type T must be derived from instantiation of SupportsCheckedUnsafePtr");
template <typename U>
friend class CheckedUnsafePtr;
template <typename U, typename S = std::nullptr_t>
using EnableIfCompatible =
std::enable_if_t<std::is_base_of<T, std::remove_reference_t<decltype(
*std::declval<U>())>>::value,
S>;
public:
using detail::CheckedUnsafePtrBase<T>::CheckedUnsafePtrBase;
using detail::CheckedUnsafePtrBase<T>::get;
constexpr T* operator->() const { return get(); }
constexpr T& operator*() const { return *get(); }
MOZ_IMPLICIT constexpr operator T*() const { return get(); }
MOZ_IMPLICIT CheckedUnsafePtr(const std::nullptr_t = nullptr)
: mRawPtr(nullptr){};
template <typename U>
constexpr bool operator==(
detail::EnableIfCompatible<T, U, const U&> aRhs) const {
return get() == aRhs.get();
MOZ_IMPLICIT CheckedUnsafePtr(const U& aPtr,
EnableIfCompatible<U> = nullptr) {
Set(aPtr);
}
CheckedUnsafePtr(const CheckedUnsafePtr& aOther) { Set(aOther); }
~CheckedUnsafePtr() { Reset(); }
CheckedUnsafePtr& operator=(const std::nullptr_t) {
Reset();
return *this;
}
template <typename U>
friend constexpr bool operator==(
detail::EnableIfCompatible<T, U, const U&> aLhs,
const CheckedUnsafePtr& aRhs) {
EnableIfCompatible<U, CheckedUnsafePtr&> operator=(const U& aPtr) {
Replace(aPtr);
return *this;
}
CheckedUnsafePtr& operator=(const CheckedUnsafePtr& aOther) {
if (&aOther != this) {
Replace(aOther);
}
return *this;
}
T* operator->() const { return mRawPtr; }
T& operator*() const { return *operator->(); }
MOZ_IMPLICIT operator T*() const { return operator->(); }
template <typename U>
bool operator==(EnableIfCompatible<U, const U&> aRhs) const {
return mRawPtr == &*aRhs;
}
template <typename U>
friend bool operator==(EnableIfCompatible<U, const U&> aLhs,
const CheckedUnsafePtr& aRhs) {
return aRhs == aLhs;
}
template <typename U>
constexpr bool operator!=(
detail::EnableIfCompatible<T, U, const U&> aRhs) const {
bool operator!=(EnableIfCompatible<U, const U&> aRhs) const {
return !(*this == aRhs);
}
template <typename U>
friend constexpr bool operator!=(
detail::EnableIfCompatible<T, U, const U&> aLhs,
const CheckedUnsafePtr& aRhs) {
friend bool operator!=(EnableIfCompatible<U, const U&> aLhs,
const CheckedUnsafePtr& aRhs) {
return aRhs != aLhs;
}
private:
using Base = detail::CheckedUnsafePtrBase<CheckingSupport::Enabled>;
template <typename U>
void Replace(const U& aPtr) {
Reset();
Set(aPtr);
}
void Reset() {
WithCheckedUnsafePtrs(
[](Base* const aSelf,
detail::CheckedUnsafePtrCheckData::Data& aCheckedUnsafePtrs) {
const auto index = aCheckedUnsafePtrs.IndexOf(aSelf);
aCheckedUnsafePtrs.UnorderedRemoveElementAt(index);
});
mRawPtr = nullptr;
}
template <typename U>
void Set(const U& aPtr) {
this->CopyDanglingFlagIfAvailableFrom(aPtr);
mRawPtr = &*aPtr;
WithCheckedUnsafePtrs(
[](Base* const aSelf,
detail::CheckedUnsafePtrCheckData::Data& aCheckedUnsafePtrs) {
aCheckedUnsafePtrs.AppendElement(aSelf);
});
}
template <typename F>
void WithCheckedUnsafePtrs(F&& aClosure) {
this->WithCheckedUnsafePtrsImpl(mRawPtr, std::forward<F>(aClosure));
}
T* mRawPtr;
};
} // namespace mozilla

Просмотреть файл

@ -8,19 +8,6 @@
using namespace mozilla;
class NoCheckTestType
: public SupportsCheckedUnsafePtr<DoNotCheckCheckedUnsafePtrs> {};
static_assert(std::is_literal_type_v<CheckedUnsafePtr<NoCheckTestType>>);
static_assert(
std::is_trivially_copy_constructible_v<CheckedUnsafePtr<NoCheckTestType>>);
static_assert(
std::is_trivially_copy_assignable_v<CheckedUnsafePtr<NoCheckTestType>>);
static_assert(
std::is_trivially_move_constructible_v<CheckedUnsafePtr<NoCheckTestType>>);
static_assert(
std::is_trivially_move_assignable_v<CheckedUnsafePtr<NoCheckTestType>>);
class TestCheckingPolicy : public CheckCheckedUnsafePtrs<TestCheckingPolicy> {
protected:
explicit TestCheckingPolicy(bool& aPassedCheck)

Просмотреть файл

@ -8,7 +8,6 @@
#define mozilla_dom_SharedWorkerManager_h
#include "mozilla/dom/RemoteWorkerController.h"
#include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
@ -26,8 +25,7 @@ class SharedWorkerParent;
// Main-thread only object that keeps a manager and the service alive.
// When the last SharedWorkerManagerHolder is released, the corresponding
// manager unregisters itself from the service and terminates the worker.
class SharedWorkerManagerHolder final
: public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
class SharedWorkerManagerHolder final {
public:
NS_INLINE_DECL_REFCOUNTING(SharedWorkerManagerHolder);
@ -41,8 +39,8 @@ class SharedWorkerManagerHolder final
private:
~SharedWorkerManagerHolder();
const RefPtr<SharedWorkerManager> mManager;
const RefPtr<SharedWorkerService> mService;
RefPtr<SharedWorkerManager> mManager;
RefPtr<SharedWorkerService> mService;
};
// Thread-safe wrapper for SharedWorkerManagerHolder.
@ -126,23 +124,23 @@ class SharedWorkerManager final : public RemoteWorkerObserver {
nsCOMPtr<nsIEventTarget> mPBackgroundEventTarget;
nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
const nsCString mDomain;
const OriginAttributes mStoragePrincipalAttrs;
const nsCOMPtr<nsIURI> mResolvedScriptURL;
const nsString mName;
const bool mIsSecureContext;
nsCString mDomain;
OriginAttributes mStoragePrincipalAttrs;
nsCOMPtr<nsIURI> mResolvedScriptURL;
nsString mName;
bool mIsSecureContext;
bool mSuspended;
bool mFrozen;
// Raw pointers because SharedWorkerParent unregisters itself in
// ActorDestroy().
nsTArray<CheckedUnsafePtr<SharedWorkerParent>> mActors;
nsTArray<SharedWorkerParent*> mActors;
RefPtr<RemoteWorkerController> mRemoteWorkerController;
// Main-thread only. Raw Pointers because holders keep the manager alive and
// they unregister themselves in their DTOR.
nsTArray<CheckedUnsafePtr<SharedWorkerManagerHolder>> mHolders;
nsTArray<SharedWorkerManagerHolder*> mHolders;
};
} // namespace dom

Просмотреть файл

@ -8,7 +8,6 @@
#define mozilla_dom_dom_SharedWorkerParent_h
#include "mozilla/dom/PSharedWorkerParent.h"
#include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "nsISupportsImpl.h"
@ -19,9 +18,7 @@ class MessagePortIdentifier;
class RemoteWorkerData;
class SharedWorkerManagerWrapper;
class SharedWorkerParent final
: public mozilla::dom::PSharedWorkerParent,
public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
class SharedWorkerParent final : public mozilla::dom::PSharedWorkerParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedWorkerParent)

Просмотреть файл

@ -23,7 +23,7 @@ StaticMutex sSharedWorkerMutex;
// Raw pointer because SharedWorkerParent keeps this object alive, indirectly
// via SharedWorkerManagerHolder.
CheckedUnsafePtr<SharedWorkerService> sSharedWorkerService;
SharedWorkerService* MOZ_NON_OWNING_REF sSharedWorkerService;
class GetOrCreateWorkerManagerRunnable final : public Runnable {
public:
@ -119,7 +119,7 @@ already_AddRefed<SharedWorkerService> SharedWorkerService::GetOrCreate() {
StaticMutexAutoLock lock(sSharedWorkerMutex);
if (sSharedWorkerService) {
RefPtr<SharedWorkerService> instance = sSharedWorkerService.get();
RefPtr<SharedWorkerService> instance = sSharedWorkerService;
return instance.forget();
}

Просмотреть файл

@ -7,7 +7,6 @@
#ifndef mozilla_dom_SharedWorkerService_h
#define mozilla_dom_SharedWorkerService_h
#include "mozilla/dom/quota/CheckedUnsafePtr.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
@ -25,8 +24,7 @@ class SharedWorkerManager;
class SharedWorkerParent;
class UniqueMessagePortId;
class SharedWorkerService final
: public SupportsCheckedUnsafePtr<CheckIf<DiagnosticAssertEnabled>> {
class SharedWorkerService final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedWorkerService);