Bug 1401873 - Remove nsHtml5Atom. r=froydnj,henri. draft
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 21 Sep 2017 14:02:05 +1000
changeset 668169 ab940a6b491f9df162c3a4a322135d0c3ad99cd2
parent 668168 94ddb8d4843f5b5a91ecb72539725b1f74ed62aa
child 732606 706df0344362520563c0a943e785878c8c511a63
push id80945
push usernnethercote@mozilla.com
push dateThu, 21 Sep 2017 07:22:53 +0000
reviewersfroydnj, henri
bugs1401873
milestone57.0a1
Bug 1401873 - Remove nsHtml5Atom. r=froydnj,henri. nsHtml5Atoms are very similar to dynamic nsAtoms. This patch removes the former in favour of the latter, which leaves nsAtom as the only subclass of nsIAtom. nsAtom::mKind is still used to distinguish dynamic atoms from HTML5 atoms, and the HTML5 parser still uses manual memory management to handle its HTML5 atoms. MozReview-Commit-ID: KV6l27jzCKj
parser/html/moz.build
parser/html/nsHtml5Atom.cpp
parser/html/nsHtml5Atom.h
parser/html/nsHtml5AtomTable.cpp
parser/html/nsHtml5AtomTable.h
parser/html/nsHtml5SpeculativeLoad.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsIAtom.h
--- a/parser/html/moz.build
+++ b/parser/html/moz.build
@@ -50,17 +50,16 @@ EXPORTS += [
     'nsHtml5UTF16Buffer.h',
     'nsHtml5UTF16BufferHSupplement.h',
     'nsHtml5ViewSourceUtils.h',
     'nsIContentHandle.h',
     'nsParserUtils.h',
 ]
 
 UNIFIED_SOURCES += [
-    'nsHtml5Atom.cpp',
     'nsHtml5AtomTable.cpp',
     'nsHtml5AttributeName.cpp',
     'nsHtml5DependentUTF16Buffer.cpp',
     'nsHtml5DocumentBuilder.cpp',
     'nsHtml5ElementName.cpp',
     'nsHtml5Highlighter.cpp',
     'nsHtml5HtmlAttributes.cpp',
     'nsHtml5MetaScanner.cpp',
deleted file mode 100644
--- a/parser/html/nsHtml5Atom.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/* 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 "nsHtml5Atom.h"
-#include "nsAutoPtr.h"
-#include "mozilla/Unused.h"
-
-nsHtml5Atom::nsHtml5Atom(const nsAString& aString)
-{
-  mLength = aString.Length();
-  SetKind(AtomKind::HTML5Atom);
-  RefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString);
-  if (buf) {
-    mString = static_cast<char16_t*>(buf->Data());
-  } else {
-    const size_t size = (mLength + 1) * sizeof(char16_t);
-    buf = nsStringBuffer::Alloc(size);
-    if (MOZ_UNLIKELY(!buf)) {
-      // We OOM because atom allocations should be small and it's hard to
-      // handle them more gracefully in a constructor.
-      NS_ABORT_OOM(size);
-    }
-    mString = static_cast<char16_t*>(buf->Data());
-    CopyUnicodeTo(aString, 0, mString, mLength);
-    mString[mLength] = char16_t(0);
-  }
-
-  NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated");
-  NS_ASSERTION(buf && buf->StorageSize() >= (mLength+1) * sizeof(char16_t),
-               "enough storage");
-  NS_ASSERTION(Equals(aString), "correct data");
-
-  // Take ownership of buffer
-  mozilla::Unused << buf.forget();
-}
-
-nsHtml5Atom::~nsHtml5Atom()
-{
-  nsStringBuffer::FromData(mString)->Release();
-}
-
-NS_IMETHODIMP
-nsHtml5Atom::QueryInterface(REFNSIID aIID, void** aInstancePtr)
-{
-  NS_NOTREACHED("Attempt to call QueryInterface an nsHtml5Atom.");
-  return NS_ERROR_UNEXPECTED;
-}
-
-NS_IMETHODIMP
-nsHtml5Atom::ToUTF8String(nsACString& aReturn)
-{
-  NS_NOTREACHED("Should not attempt to convert to an UTF-8 string.");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP_(size_t)
-nsHtml5Atom::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
-{
-  NS_NOTREACHED("Should not call SizeOfIncludingThis.");
-  return 0;
-}
-
deleted file mode 100644
--- a/parser/html/nsHtml5Atom.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 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/. */
-
-#ifndef nsHtml5Atom_h
-#define nsHtml5Atom_h
-
-#include "nsIAtom.h"
-#include "mozilla/Attributes.h"
-
-/**
- * A dynamic atom implementation meant for use within the nsHtml5Tokenizer and 
- * nsHtml5TreeBuilder owned by one nsHtml5Parser or nsHtml5StreamParser 
- * instance.
- *
- * Usage is documented in nsHtml5AtomTable and nsIAtom.
- */
-class nsHtml5Atom final : public nsIAtom
-{
-  public:
-    NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) final;
-    NS_DECL_NSIATOM
-
-    explicit nsHtml5Atom(const nsAString& aString);
-    ~nsHtml5Atom();
-};
-
-#endif // nsHtml5Atom_h
--- a/parser/html/nsHtml5AtomTable.cpp
+++ b/parser/html/nsHtml5AtomTable.cpp
@@ -1,19 +1,24 @@
 /* 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 "nsHtml5AtomTable.h"
-#include "nsHtml5Atom.h"
 #include "nsThreadUtils.h"
 
+nsAtom*
+NewHtml5Atom(const nsAString& aStr)
+{
+  return new nsAtom(nsAtom::AtomKind::HTML5Atom, aStr, 0);
+}
+
 nsHtml5AtomEntry::nsHtml5AtomEntry(KeyTypePointer aStr)
   : nsStringHashKey(aStr)
-  , mAtom(new nsHtml5Atom(*aStr))
+  , mAtom(NewHtml5Atom(*aStr))
 {
 }
 
 nsHtml5AtomEntry::nsHtml5AtomEntry(const nsHtml5AtomEntry& aOther)
   : nsStringHashKey(aOther)
   , mAtom(nullptr)
 {
   NS_NOTREACHED("nsHtml5AtomTable is broken and tried to copy an entry");
--- a/parser/html/nsHtml5AtomTable.h
+++ b/parser/html/nsHtml5AtomTable.h
@@ -8,30 +8,25 @@
 #include "nsHashKeys.h"
 #include "nsTHashtable.h"
 #include "nsAutoPtr.h"
 #include "nsIAtom.h"
 #include "nsISerialEventTarget.h"
 
 #define RECENTLY_USED_PARSER_ATOMS_SIZE 31
 
-class nsHtml5Atom;
-
 class nsHtml5AtomEntry : public nsStringHashKey
 {
   public:
     explicit nsHtml5AtomEntry(KeyTypePointer aStr);
     nsHtml5AtomEntry(const nsHtml5AtomEntry& aOther);
     ~nsHtml5AtomEntry();
-    inline nsHtml5Atom* GetAtom()
-    {
-      return mAtom;
-    }
+    inline nsAtom* GetAtom() { return mAtom; }
   private:
-    nsAutoPtr<nsHtml5Atom> mAtom;
+    nsAutoPtr<nsAtom> mAtom;
 };
 
 /**
  * nsHtml5AtomTable provides non-locking lookup and creation of atoms for 
  * nsHtml5Parser or nsHtml5StreamParser.
  *
  * The hashtable holds dynamically allocated atoms that are private to an 
  * instance of nsHtml5Parser or nsHtml5StreamParser. (Static atoms are used on 
--- a/parser/html/nsHtml5SpeculativeLoad.cpp
+++ b/parser/html/nsHtml5SpeculativeLoad.cpp
@@ -1,14 +1,15 @@
 /* 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 "nsHtml5SpeculativeLoad.h"
 #include "nsHtml5TreeOpExecutor.h"
+#include "mozilla/Encoding.h"
 
 nsHtml5SpeculativeLoad::nsHtml5SpeculativeLoad()
   :
 #ifdef DEBUG
   mOpCode(eSpeculativeLoadUninitialized),
 #endif
   mIsAsync(false),
   mIsDefer(false)
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -104,22 +104,23 @@ public:
 
 private:
   nsStringBuffer* mBuffer;
 };
 
 UniquePtr<nsTArray<FakeBufferRefcountHelper>> gFakeBuffers;
 #endif
 
-// This constructor is for dynamic atoms.
-nsAtom::nsAtom(const nsAString& aString, uint32_t aHash)
+// This constructor is for dynamic atoms and HTML5 atoms.
+nsAtom::nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash)
   : mRefCnt(1)
 {
   mLength = aString.Length();
-  SetKind(AtomKind::DynamicAtom);
+  SetKind(aKind);
+  MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom());
   RefPtr<nsStringBuffer> buf = nsStringBuffer::FromString(aString);
   if (buf) {
     mString = static_cast<char16_t*>(buf->Data());
   } else {
     const size_t size = (mLength + 1) * sizeof(char16_t);
     buf = nsStringBuffer::Alloc(size);
     if (MOZ_UNLIKELY(!buf)) {
       // We OOM because atom allocations should be small and it's hard to
@@ -127,17 +128,17 @@ nsAtom::nsAtom(const nsAString& aString,
       NS_ABORT_OOM(size);
     }
     mString = static_cast<char16_t*>(buf->Data());
     CopyUnicodeTo(aString, 0, mString, mLength);
     mString[mLength] = char16_t(0);
   }
 
   mHash = aHash;
-  MOZ_ASSERT(mHash == HashString(mString, mLength));
+  MOZ_ASSERT_IF(IsDynamicAtom(), mHash == HashString(mString, mLength));
 
   NS_ASSERTION(mString[mLength] == char16_t(0), "null terminated");
   NS_ASSERTION(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t),
                "enough storage");
   NS_ASSERTION(Equals(aString), "correct data");
 
   // Take ownership of buffer
   mozilla::Unused << buf.forget();
@@ -171,35 +172,36 @@ nsAtom::nsAtom(nsStringBuffer* aStringBu
              "correct storage");
 }
 
 // We don't need a virtual destructor because we always delete via an nsAtom*
 // pointer (in AtomTableClearEntry() for static atoms, and in
 // GCAtomTableLocked() for dynamic atoms), not an nsIAtom* pointer.
 nsAtom::~nsAtom()
 {
-  if (IsDynamicAtom()) {
+  if (!IsStaticAtom()) {
+    MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom());
     nsStringBuffer::FromData(mString)->Release();
-  } else {
-    MOZ_ASSERT(IsStaticAtom());
   }
 }
 
 NS_IMPL_QUERY_INTERFACE(nsAtom, nsIAtom);
 
 NS_IMETHODIMP
 nsAtom::ToUTF8String(nsACString& aBuf)
 {
+  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an HTML5 atom");
   CopyUTF16toUTF8(nsDependentString(mString, mLength), aBuf);
   return NS_OK;
 }
 
 NS_IMETHODIMP_(size_t)
 nsAtom::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
 {
+  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an HTML5 atom");
   size_t n = aMallocSizeOf(this);
   // String buffers pointed to by static atoms are in static memory, and so
   // are not measured here.
   if (IsDynamicAtom()) {
     n += nsStringBuffer::FromData(mString)->SizeOfIncludingThisIfUnshared(
            aMallocSizeOf);
   } else {
     MOZ_ASSERT(IsStaticAtom());
@@ -207,28 +209,28 @@ nsAtom::SizeOfIncludingThis(MallocSizeOf
   return n;
 }
 
 //----------------------------------------------------------------------
 
 NS_IMETHODIMP_(MozExternalRefCountType)
 nsIAtom::AddRef()
 {
-  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an nsHtml5Atom");
+  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an HTML5 atom");
   if (!IsDynamicAtom()) {
     MOZ_ASSERT(IsStaticAtom());
     return 2;
   }
   return static_cast<nsAtom*>(this)->DynamicAddRef();
 }
 
 NS_IMETHODIMP_(MozExternalRefCountType)
 nsIAtom::Release()
 {
-  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to Release an nsHtml5Atom");
+  MOZ_ASSERT(!IsHTML5Atom(), "Attempt to Release an HTML5 atom");
   if (!IsDynamicAtom()) {
     MOZ_ASSERT(IsStaticAtom());
     return 1;
   }
   return static_cast<nsAtom*>(this)->DynamicRelease();
 }
 
 //----------------------------------------------------------------------
@@ -688,17 +690,18 @@ NS_Atomize(const nsACString& aUTF8String
     return atom.forget();
   }
 
   // This results in an extra addref/release of the nsStringBuffer.
   // Unfortunately there doesn't seem to be any APIs to avoid that.
   // Actually, now there is, sort of: ForgetSharedBuffer.
   nsString str;
   CopyUTF8toUTF16(aUTF8String, str);
-  RefPtr<nsAtom> atom = dont_AddRef(new nsAtom(str, hash));
+  RefPtr<nsAtom> atom =
+    dont_AddRef(new nsAtom(nsAtom::AtomKind::DynamicAtom, str, hash));
 
   he->mAtom = atom;
 
   return atom.forget();
 }
 
 already_AddRefed<nsIAtom>
 NS_Atomize(const char16_t* aUTF16String)
@@ -716,17 +719,18 @@ NS_Atomize(const nsAString& aUTF16String
                                         &hash);
 
   if (he->mAtom) {
     nsCOMPtr<nsIAtom> atom = he->mAtom;
 
     return atom.forget();
   }
 
-  RefPtr<nsAtom> atom = dont_AddRef(new nsAtom(aUTF16String, hash));
+  RefPtr<nsAtom> atom =
+    dont_AddRef(new nsAtom(nsAtom::AtomKind::DynamicAtom, aUTF16String, hash));
   he->mAtom = atom;
 
   return atom.forget();
 }
 
 already_AddRefed<nsIAtom>
 NS_AtomizeMainThread(const nsAString& aUTF16String)
 {
@@ -747,17 +751,18 @@ NS_AtomizeMainThread(const nsAString& aU
   }
 
   MutexAutoLock lock(*gAtomTableLock);
   AtomTableEntry* he = static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
 
   if (he->mAtom) {
     retVal = he->mAtom;
   } else {
-    RefPtr<nsAtom> newAtom = dont_AddRef(new nsAtom(aUTF16String, hash));
+    RefPtr<nsAtom> newAtom = dont_AddRef(
+      new nsAtom(nsAtom::AtomKind::DynamicAtom, aUTF16String, hash));
     he->mAtom = newAtom;
     retVal = newAtom.forget();
   }
 
   sRecentlyUsedMainThreadAtoms[index] = he->mAtom;
   return retVal.forget();
 }
 
--- a/xpcom/ds/nsIAtom.h
+++ b/xpcom/ds/nsIAtom.h
@@ -76,17 +76,21 @@ public:
     return nsStringBuffer::FromData(mString);
   }
 
   NS_IMETHOD_(MozExternalRefCountType) AddRef() final;
   NS_IMETHOD_(MozExternalRefCountType) Release() final;
 
   // A hashcode that is better distributed than the actual atom pointer, for
   // use in situations that need a well-distributed hashcode.
-  uint32_t hash() const { return mHash; }
+  uint32_t hash() const
+  {
+    MOZ_ASSERT(!IsHTML5Atom());
+    return mHash;
+  }
 
 protected:
   uint32_t mLength: 30;
   uint32_t mKind: 2; // nsIAtom::AtomKind
   uint32_t mHash;
   // WARNING! There is an invisible constraint on |mString|: the chars it
   // points to must belong to an nsStringBuffer. This is so that the
   // nsStringBuffer::FromData() calls above are valid.
@@ -115,18 +119,19 @@ public:
 
 private:
   // nsAtom constructors are private because they must be constructed in very
   // restricted ways. The following functions are those responsible.
   friend void RegisterStaticAtoms(const nsStaticAtom*, uint32_t);
   friend already_AddRefed<nsIAtom> NS_Atomize(const nsACString&);
   friend already_AddRefed<nsIAtom> NS_Atomize(const nsAString&);
   friend already_AddRefed<nsIAtom> NS_AtomizeMainThread(const nsAString&);
+  friend nsAtom* NewHtml5Atom(const nsAString&);
 
-  nsAtom(const nsAString& aString, uint32_t aHash);
+  nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash);
   nsAtom(nsStringBuffer* aStringBuffer, uint32_t aLength, uint32_t aHash);
 
   mozilla::ThreadSafeAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
 
 // The four forms of NS_Atomize (for use with |nsCOMPtr<nsIAtom>|) return the
 // atom for the string given. At any given time there will always be one atom