Bug 1350729 - Implement fake refcount logging for nsFakeStringBuffer. r=dbaron

Running with XPCOM_MEM_LOG_CLASSES=nsStringBuffer triggers an
assertion in refcount logging for nsFakeStringBuffers. These are given
an initial refcount of 1, without calling NS_LOG_ADDREF. Then,
AddRef() is called on these objects in StaticAtom::StaticAtom(), and
we tell the refcount logging system about the fake buffer, and that it
has a refcount of 0, triggering the assertion.

The first part of the fix is to call NS_LOG_ADDREF for this initial
refcount, in StaticAtom().

This first fix causes refcount logging to start reporting that the
fake string buffers leak, when XPCOM_MEM_LOG_CLASSES is not set. This
is because refcount logging is now getting told about these objects
being AddRefed at 1, which it takes to mean that an object is created.

To work around this issue, I add an array gFakeBuffers that contains
every fake string buffer we create, and tell the refcount logging
system that these objects are all being destroyed, when the atom table
is being shut down. This could result in some bogosity if the fake
buffers are "leaked" but hopefully this is still an improvement over
the current state.

MozReview-Commit-ID: 5AxoBYAlYRU

--HG--
extra : rebase_source : ba0763cb494894918141774025db525cea9f9c75
This commit is contained in:
Andrew McCreight 2017-07-14 10:20:23 -07:00
parent 09cb31cb1a
commit d6f0453414

View File

@ -132,6 +132,39 @@ public:
NS_DECL_NSIATOM
};
#if defined(NS_BUILD_REFCNT_LOGGING)
// nsFakeStringBuffers don't really use the refcounting system, but we
// have to give a coherent series of addrefs and releases to the
// refcount logging system, or we'll hit assertions when running with
// XPCOM_MEM_LOG_CLASSES=nsStringBuffer.
class FakeBufferRefcountHelper
{
public:
explicit FakeBufferRefcountHelper(nsStringBuffer* aBuffer)
: mBuffer(aBuffer)
{
// Account for the initial static refcount of 1, so that we don't
// hit a refcount logging assertion when this object first appears
// with a refcount of 2.
NS_LOG_ADDREF(aBuffer, 1, "nsStringBuffer", sizeof(nsStringBuffer));
}
~FakeBufferRefcountHelper()
{
// We told the refcount logging system in the ctor that this
// object was created, so now we have to tell it that it was
// destroyed, to avoid leak reports. This may cause odd the
// refcount isn't actually 0.
NS_LOG_RELEASE(mBuffer, 0, "nsStringBuffer");
}
private:
nsStringBuffer* mBuffer;
};
UniquePtr<nsTArray<FakeBufferRefcountHelper>> gFakeBuffers;
#endif
class StaticAtom final : public nsIAtom
{
public:
@ -140,6 +173,15 @@ public:
mLength = aLength;
mIsStatic = true;
mString = static_cast<char16_t*>(aStringBuffer->Data());
#if defined(NS_BUILD_REFCNT_LOGGING)
MOZ_ASSERT(NS_IsMainThread());
if (!gFakeBuffers) {
gFakeBuffers = MakeUnique<nsTArray<FakeBufferRefcountHelper>>();
}
gFakeBuffers->AppendElement(aStringBuffer);
#endif
// Technically we could currently avoid doing this addref by instead making
// the static atom buffers have an initial refcount of 2.
aStringBuffer->AddRef();
@ -564,6 +606,10 @@ NS_InitAtomTable()
void
NS_ShutdownAtomTable()
{
#if defined(NS_BUILD_REFCNT_LOGGING)
gFakeBuffers = nullptr;
#endif
delete gStaticAtomTable;
gStaticAtomTable = nullptr;