Bug 1390568 - manually de-virtualize do_QueryReferent; r=ehsan

nsQueryReferent is defined as an nsCOMPtr_helper, which implies that
calling its operator() method requires a virtual call.  While
nsQueryReferent is marked `final`, compiler inlining decisions make it
impossible to de-virtualize the call to operator().  However, we have
many other classes returned by do_* functions that nsCOMPtr handles
directly, requiring no extra virtual calls, and we can give
nsQueryReferent the same treatment.
This commit is contained in:
Nathan Froyd 2017-08-24 20:04:31 -04:00
parent 519e4af9fe
commit c5fa35746e
4 changed files with 101 additions and 17 deletions

View File

@ -15,6 +15,7 @@
// template <class T> class RefPtrGetterAddRefs;
class nsQueryReferent;
class nsCOMPtr_helper;
namespace mozilla {
@ -148,6 +149,7 @@ public:
{
}
MOZ_IMPLICIT RefPtr(const nsQueryReferent& aHelper);
MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
// Defined in OwningNonNull.h
@ -210,6 +212,7 @@ public:
return *this;
}
RefPtr<T>& operator=(const nsQueryReferent& aQueryReferent);
RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
RefPtr<T>&

View File

@ -109,6 +109,17 @@ nsCOMPtr_base::assign_from_gs_contractid_with_error(
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
}
void
nsCOMPtr_base::assign_from_query_referent(
const nsQueryReferent& aQueryReferent, const nsIID& aIID)
{
void* newRawPtr;
if (NS_FAILED(aQueryReferent(aIID, &newRawPtr))) {
newRawPtr = nullptr;
}
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
}
void
nsCOMPtr_base::assign_from_helper(const nsCOMPtr_helper& aHelper,
const nsIID& aIID)

View File

@ -273,6 +273,25 @@ private:
nsresult* mErrorPtr;
};
class nsIWeakReference;
// Weak references
class MOZ_STACK_CLASS nsQueryReferent final
{
public:
nsQueryReferent(nsIWeakReference* aWeakPtr, nsresult* aError)
: mWeakPtr(aWeakPtr)
, mErrorPtr(aError)
{
}
nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
private:
nsIWeakReference* MOZ_NON_OWNING_REF mWeakPtr;
nsresult* mErrorPtr;
};
/**
* Factors implementation for all template versions of nsCOMPtr.
*
@ -311,6 +330,8 @@ public:
assign_from_gs_contractid_with_error(const nsGetServiceByContractIDWithError&,
const nsIID&);
void NS_FASTCALL
assign_from_query_referent(const nsQueryReferent&, const nsIID&);
void NS_FASTCALL
assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
void** NS_FASTCALL
begin_assignment();
@ -366,6 +387,7 @@ private:
void assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
void assign_from_gs_contractid_with_error(
const nsGetServiceByContractIDWithError&, const nsIID&);
void assign_from_query_referent(const nsQueryReferent&, const nsIID&);
void assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
void** begin_assignment();
@ -564,6 +586,15 @@ public:
assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
}
// Construct from |do_QueryReferent(ptr)|
MOZ_IMPLICIT nsCOMPtr(const nsQueryReferent& aQueryReferent)
: NSCAP_CTOR_BASE(nullptr)
{
assert_validity();
NSCAP_LOG_ASSIGNMENT(this, nullptr);
assign_from_query_referent(aQueryReferent, NS_GET_TEMPLATE_IID(T));
}
// And finally, anything else we might need to construct from can exploit the
// nsCOMPtr_helper facility.
MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
@ -667,6 +698,13 @@ public:
return *this;
}
// Assign from |do_QueryReferent(ptr)|.
nsCOMPtr<T>& operator=(const nsQueryReferent& aRhs)
{
assign_from_query_referent(aRhs, NS_GET_TEMPLATE_IID(T));
return *this;
}
// And finally, anything else we might need to assign from can exploit the
// nsCOMPtr_helper facility.
nsCOMPtr<T>& operator=(const nsCOMPtr_helper& aRhs)
@ -898,6 +936,14 @@ public:
assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports));
}
// Construct from |do_QueryReferent(ptr)|
MOZ_IMPLICIT nsCOMPtr(const nsQueryReferent& aQueryReferent)
: nsCOMPtr_base(nullptr)
{
NSCAP_LOG_ASSIGNMENT(this, nullptr);
assign_from_query_referent(aQueryReferent, NS_GET_TEMPLATE_IID(nsISupports));
}
// And finally, anything else we might need to construct from can exploit
// the |nsCOMPtr_helper| facility
MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
@ -984,6 +1030,13 @@ public:
return *this;
}
// Assign from |do_QueryReferent(ptr)|.
nsCOMPtr<nsISupports>& operator=(const nsQueryReferent& aRhs)
{
assign_from_query_referent(aRhs, NS_GET_TEMPLATE_IID(nsISupports));
return *this;
}
// And finally, anything else we might need to assign from can exploit the
// nsCOMPtr_helper facility
nsCOMPtr<nsISupports>& operator=(const nsCOMPtr_helper& aRhs)
@ -1177,6 +1230,18 @@ nsCOMPtr<T>::assign_from_gs_contractid_with_error(
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
}
template<class T>
void
nsCOMPtr<T>::assign_from_query_referent(
const nsQueryReferent& aQueryReferent, const nsIID& aIID)
{
void* newRawPtr;
if (NS_FAILED(aQueryReferent(aIID, &newRawPtr))) {
newRawPtr = nullptr;
}
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
}
template<class T>
void
nsCOMPtr<T>::assign_from_helper(const nsCOMPtr_helper& helper, const nsIID& aIID)
@ -1440,6 +1505,16 @@ CallQueryInterface(nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
return CallQueryInterface(aSourcePtr.get(), aDestPtr);
}
template <class T>
RefPtr<T>::RefPtr(const nsQueryReferent& aQueryReferent)
{
void* newRawPtr;
if (NS_FAILED(aQueryReferent(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
newRawPtr = nullptr;
}
mRawPtr = static_cast<T*>(newRawPtr);
}
template <class T>
RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper)
{
@ -1450,6 +1525,18 @@ RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper)
mRawPtr = static_cast<T*>(newRawPtr);
}
template <class T>
RefPtr<T>&
RefPtr<T>::operator=(const nsQueryReferent& aQueryReferent)
{
void* newRawPtr;
if (NS_FAILED(aQueryReferent(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
newRawPtr = nullptr;
}
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
return *this;
}
template <class T>
RefPtr<T>&
RefPtr<T>::operator=(const nsCOMPtr_helper& aHelper)

View File

@ -30,23 +30,6 @@ CallQueryReferent(T* aSource, DestinationType** aDestination)
}
class MOZ_STACK_CLASS nsQueryReferent final : public nsCOMPtr_helper
{
public:
nsQueryReferent(nsIWeakReference* aWeakPtr, nsresult* aError)
: mWeakPtr(aWeakPtr)
, mErrorPtr(aError)
{
}
virtual nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const
override;
private:
nsIWeakReference* MOZ_NON_OWNING_REF mWeakPtr;
nsresult* mErrorPtr;
};
inline const nsQueryReferent
do_QueryReferent(nsIWeakReference* aRawPtr, nsresult* aError = 0)
{