From 523608513bf8fc8d3c844c0593aa15e13d26ad69 Mon Sep 17 00:00:00 2001 From: Aidin Gharibnavaz Date: Wed, 29 Jun 2016 18:56:41 -0400 Subject: [PATCH] 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. --- image/RasterImage.h | 9 ++ .../websocket/WebSocketEventService.h | 10 ++ netwerk/protocol/wyciwyg/nsWyciwygChannel.h | 10 ++ storage/mozStorageConnection.h | 10 ++ xpcom/glue/nsProxyRelease.cpp | 21 ++++ xpcom/glue/nsProxyRelease.h | 96 +++++++++++++------ xpcom/glue/objs.mozbuild | 1 + 7 files changed, 130 insertions(+), 27 deletions(-) create mode 100644 xpcom/glue/nsProxyRelease.cpp diff --git a/image/RasterImage.h b/image/RasterImage.h index 7705dde83cd3..038ac1105933 100644 --- a/image/RasterImage.h +++ b/image/RasterImage.h @@ -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 */ diff --git a/netwerk/protocol/websocket/WebSocketEventService.h b/netwerk/protocol/websocket/WebSocketEventService.h index 6f9797557621..f23267999861 100644 --- a/netwerk/protocol/websocket/WebSocketEventService.h +++ b/netwerk/protocol/websocket/WebSocketEventService.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 diff --git a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h index 4b77b3ca1465..26c7e699381d 100644 --- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h @@ -110,4 +110,14 @@ protected: nsCOMPtr 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___ */ diff --git a/storage/mozStorageConnection.h b/storage/mozStorageConnection.h index c1a1f0025b21..d38024e6d779 100644 --- a/storage/mozStorageConnection.h +++ b/storage/mozStorageConnection.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 diff --git a/xpcom/glue/nsProxyRelease.cpp b/xpcom/glue/nsProxyRelease.cpp new file mode 100644 index 000000000000..1a8150cc6fee --- /dev/null +++ b/xpcom/glue/nsProxyRelease.cpp @@ -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::ProxyReleaseISupports(nsIEventTarget* aTarget, + nsISupports* aDoomed, + bool aAlwaysProxy) +{ + ::detail::ProxyRelease(aTarget, dont_AddRef(aDoomed), + aAlwaysProxy); +} + +} // namespace detail diff --git a/xpcom/glue/nsProxyRelease.h b/xpcom/glue/nsProxyRelease.h index 8393b22378aa..746542560653 100644 --- a/xpcom/glue/nsProxyRelease.h +++ b/xpcom/glue/nsProxyRelease.h @@ -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 nsProxyReleaseEvent : public mozilla::Runnable +template +class ProxyReleaseEvent : public mozilla::Runnable { public: - explicit nsProxyReleaseEvent(already_AddRefed aDoomed) + explicit ProxyReleaseEvent(already_AddRefed aDoomed) : mDoomed(aDoomed.take()) {} NS_IMETHOD Run() @@ -38,6 +40,68 @@ private: T* MOZ_OWNING_REF mDoomed; }; +template +void +ProxyRelease(nsIEventTarget* aTarget, already_AddRefed aDoomed, bool aAlwaysProxy) +{ + // Auto-managing release of the pointer. + RefPtr doomed = aDoomed; + nsresult rv; + + if (!doomed || !aTarget) { + return; + } + + if (!aAlwaysProxy) { + bool onCurrentThread = false; + rv = aTarget->IsOnCurrentThread(&onCurrentThread); + if (NS_SUCCEEDED(rv) && onCurrentThread) { + return; + } + } + + nsCOMPtr ev = new ProxyReleaseEvent(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 +struct ProxyReleaseChooser +{ + template + static void ProxyRelease(nsIEventTarget* aTarget, + already_AddRefed aDoomed, + bool aAlwaysProxy) + { + ::detail::ProxyRelease(aTarget, mozilla::Move(aDoomed), aAlwaysProxy); + } +}; + +template<> +struct ProxyReleaseChooser +{ + // We need an intermediate step for handling classes with ambiguous + // inheritance to nsISupports. + template + static void ProxyRelease(nsIEventTarget* aTarget, + already_AddRefed 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 aDoomed, bool aAlwaysProxy = false) { - // Auto-managing release of the pointer. - RefPtr doomed = aDoomed; - nsresult rv; - - if (!doomed || !aTarget) { - return; - } - - if (!aAlwaysProxy) { - bool onCurrentThread = false; - rv = aTarget->IsOnCurrentThread(&onCurrentThread); - if (NS_SUCCEEDED(rv) && onCurrentThread) { - return; - } - } - - nsCOMPtr ev = new nsProxyReleaseEvent(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::value> + ::ProxyRelease(aTarget, mozilla::Move(aDoomed), aAlwaysProxy); } /** diff --git a/xpcom/glue/objs.mozbuild b/xpcom/glue/objs.mozbuild index 641ae8aa4564..9c211cc7892f 100644 --- a/xpcom/glue/objs.mozbuild +++ b/xpcom/glue/objs.mozbuild @@ -39,6 +39,7 @@ xpcom_glue_src_cppsrcs = [ xpcom_gluens_src_lcppsrcs = [ 'BlockingResourceBase.cpp', 'GenericFactory.cpp', + 'nsProxyRelease.cpp', 'nsTextFormatter.cpp', ]