зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1247972 - specialize NS_ProxyRelease for nsISupports to be out-of-line; r=erahm
NS_ProxyRelease's current implementation requires a lot of code. We can reduce the impact of this by providing an out-of-line implementation for classes based on nsISupports. This change reduces codesize by ~60K on a Linux x86-64 build.
This commit is contained in:
Родитель
2ca762b096
Коммит
523608513b
|
@ -458,4 +458,13 @@ RasterImage::GetAnimationMode(uint16_t* aAnimationMode) {
|
|||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Casting RasterImage to nsISupports is ambiguous. This method handles that.
|
||||
*/
|
||||
inline nsISupports*
|
||||
ToSupports(mozilla::image::RasterImage* p)
|
||||
{
|
||||
return NS_ISUPPORTS_CAST(mozilla::image::ImageResource*, p);
|
||||
}
|
||||
|
||||
#endif /* mozilla_image_RasterImage_h */
|
||||
|
|
|
@ -111,4 +111,14 @@ private:
|
|||
} // net namespace
|
||||
} // mozilla namespace
|
||||
|
||||
/**
|
||||
* Casting WebSocketEventService to nsISupports is ambiguous.
|
||||
* This method handles that.
|
||||
*/
|
||||
inline nsISupports*
|
||||
ToSupports(mozilla::net::WebSocketEventService* p)
|
||||
{
|
||||
return NS_ISUPPORTS_CAST(nsIWebSocketEventService*, p);
|
||||
}
|
||||
|
||||
#endif // mozilla_net_WebSocketEventService_h
|
||||
|
|
|
@ -110,4 +110,14 @@ protected:
|
|||
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* Casting nsWyciwygChannel to nsISupports is ambiguous.
|
||||
* This method handles that.
|
||||
*/
|
||||
inline nsISupports*
|
||||
ToSupports(nsWyciwygChannel* p)
|
||||
{
|
||||
return NS_ISUPPORTS_CAST(nsIStreamListener*, p);
|
||||
}
|
||||
|
||||
#endif /* nsWyciwygChannel_h___ */
|
||||
|
|
|
@ -413,4 +413,14 @@ private:
|
|||
} // namespace storage
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Casting Connection to nsISupports is ambiguous.
|
||||
* This method handles that.
|
||||
*/
|
||||
inline nsISupports*
|
||||
ToSupports(mozilla::storage::Connection* p)
|
||||
{
|
||||
return NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, p);
|
||||
}
|
||||
|
||||
#endif // mozilla_storage_Connection_h
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace detail {
|
||||
|
||||
/* static */ void
|
||||
ProxyReleaseChooser<true>::ProxyReleaseISupports(nsIEventTarget* aTarget,
|
||||
nsISupports* aDoomed,
|
||||
bool aAlwaysProxy)
|
||||
{
|
||||
::detail::ProxyRelease<nsISupports>(aTarget, dont_AddRef(aDoomed),
|
||||
aAlwaysProxy);
|
||||
}
|
||||
|
||||
} // namespace detail
|
|
@ -15,17 +15,19 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#ifdef XPCOM_GLUE_AVOID_NSPR
|
||||
#error NS_ProxyRelease implementation depends on NSPR.
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
class nsProxyReleaseEvent : public mozilla::Runnable
|
||||
template<typename T>
|
||||
class ProxyReleaseEvent : public mozilla::Runnable
|
||||
{
|
||||
public:
|
||||
explicit nsProxyReleaseEvent(already_AddRefed<T> aDoomed)
|
||||
explicit ProxyReleaseEvent(already_AddRefed<T> aDoomed)
|
||||
: mDoomed(aDoomed.take()) {}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
|
@ -38,6 +40,68 @@ private:
|
|||
T* MOZ_OWNING_REF mDoomed;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
ProxyRelease(nsIEventTarget* aTarget, already_AddRefed<T> aDoomed, bool aAlwaysProxy)
|
||||
{
|
||||
// Auto-managing release of the pointer.
|
||||
RefPtr<T> doomed = aDoomed;
|
||||
nsresult rv;
|
||||
|
||||
if (!doomed || !aTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aAlwaysProxy) {
|
||||
bool onCurrentThread = false;
|
||||
rv = aTarget->IsOnCurrentThread(&onCurrentThread);
|
||||
if (NS_SUCCEEDED(rv) && onCurrentThread) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new ProxyReleaseEvent<T>(doomed.forget());
|
||||
|
||||
rv = aTarget->Dispatch(ev, NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to post proxy release event, leaking!");
|
||||
// It is better to leak the aDoomed object than risk crashing as
|
||||
// a result of deleting it on the wrong thread.
|
||||
}
|
||||
}
|
||||
|
||||
template<bool nsISupportsBased>
|
||||
struct ProxyReleaseChooser
|
||||
{
|
||||
template<typename T>
|
||||
static void ProxyRelease(nsIEventTarget* aTarget,
|
||||
already_AddRefed<T> aDoomed,
|
||||
bool aAlwaysProxy)
|
||||
{
|
||||
::detail::ProxyRelease(aTarget, mozilla::Move(aDoomed), aAlwaysProxy);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct ProxyReleaseChooser<true>
|
||||
{
|
||||
// We need an intermediate step for handling classes with ambiguous
|
||||
// inheritance to nsISupports.
|
||||
template<typename T>
|
||||
static void ProxyRelease(nsIEventTarget* aTarget,
|
||||
already_AddRefed<T> aDoomed,
|
||||
bool aAlwaysProxy)
|
||||
{
|
||||
ProxyReleaseISupports(aTarget, ToSupports(aDoomed.take()), aAlwaysProxy);
|
||||
}
|
||||
|
||||
static void ProxyReleaseISupports(nsIEventTarget* aTarget,
|
||||
nsISupports* aDoomed,
|
||||
bool aAlwaysProxy);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* Ensures that the delete of a smart pointer occurs on the target thread.
|
||||
*
|
||||
|
@ -56,30 +120,8 @@ inline NS_HIDDEN_(void)
|
|||
NS_ProxyRelease(nsIEventTarget* aTarget, already_AddRefed<T> aDoomed,
|
||||
bool aAlwaysProxy = false)
|
||||
{
|
||||
// Auto-managing release of the pointer.
|
||||
RefPtr<T> doomed = aDoomed;
|
||||
nsresult rv;
|
||||
|
||||
if (!doomed || !aTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aAlwaysProxy) {
|
||||
bool onCurrentThread = false;
|
||||
rv = aTarget->IsOnCurrentThread(&onCurrentThread);
|
||||
if (NS_SUCCEEDED(rv) && onCurrentThread) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new nsProxyReleaseEvent<T>(doomed.forget());
|
||||
|
||||
rv = aTarget->Dispatch(ev, NS_DISPATCH_NORMAL);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to post proxy release event, leaking!");
|
||||
// It is better to leak the aDoomed object than risk crashing as
|
||||
// a result of deleting it on the wrong thread.
|
||||
}
|
||||
::detail::ProxyReleaseChooser<mozilla::IsBaseOf<nsISupports, T>::value>
|
||||
::ProxyRelease(aTarget, mozilla::Move(aDoomed), aAlwaysProxy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@ xpcom_glue_src_cppsrcs = [
|
|||
xpcom_gluens_src_lcppsrcs = [
|
||||
'BlockingResourceBase.cpp',
|
||||
'GenericFactory.cpp',
|
||||
'nsProxyRelease.cpp',
|
||||
'nsTextFormatter.cpp',
|
||||
]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче