Bug 534136 Part 1: Make atoms keep a pointer to an nsStringBuffer rather than storing the data inline. r=bsmedberg
authorJonas Sicking <jonas@sicking.cc>
Mon, 08 Mar 2010 07:44:59 -0800
changeset 39099 5b152f233117a9a0dcbb962910fcca3effee5ca6
parent 39098 843e68865dea42bc30c3729b2f4e384f47647e70
child 39100 cb17f4d9294251cebc73861239603fc87c4c45fd
push id12012
push usersicking@mozilla.com
push dateMon, 08 Mar 2010 15:47:04 +0000
treeherdermozilla-central@f8dd7b5b02ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs534136
milestone1.9.3a3pre
Bug 534136 Part 1: Make atoms keep a pointer to an nsStringBuffer rather than storing the data inline. r=bsmedberg
accessible/src/base/nsAccessibilityAtoms.cpp
chrome/src/nsChromeRegistry.cpp
content/base/src/nsGkAtoms.cpp
editor/libeditor/html/nsEditProperty.cpp
editor/txtsvc/src/nsTextServicesDocument.cpp
gfx/thebes/src/gfxAtoms.cpp
gfx/thebes/test/gfxFontSelectionTests.h
gfx/thebes/test/gfxTextRunPerfTest.cpp
gfx/thebes/test/gfxWordCacheTest.cpp
layout/inspector/src/inDOMView.cpp
layout/inspector/src/inDOMView.h
layout/inspector/src/inDOMViewAtomList.h
layout/style/nsCSSAnonBoxes.cpp
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSPseudoElements.cpp
parser/html/nsHtml5Atoms.cpp
parser/htmlparser/src/nsHTMLTags.cpp
rdf/base/src/nsRDFContentSink.cpp
rdf/base/src/nsRDFContentSinkAtomList.h
widget/src/xpwidgets/nsWidgetAtoms.cpp
xpcom/ds/nsAtomService.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsAtomTable.h
xpcom/ds/nsIAtom.idl
xpcom/ds/nsStaticAtom.h
xpcom/io/Makefile.in
xpcom/io/nsDirectoryService.cpp
xpcom/io/nsDirectoryService.h
xpcom/io/nsDirectoryServiceAtomList.h
xpcom/string/public/nsStringBuffer.h
xpcom/string/src/nsSubstring.cpp
xpcom/tests/Makefile.in
xpcom/tests/MoreTestingAtoms.cpp
xpcom/tests/TestingAtoms.cpp
--- a/accessible/src/base/nsAccessibilityAtoms.cpp
+++ b/accessible/src/base/nsAccessibilityAtoms.cpp
@@ -40,18 +40,22 @@
 #include "nsStaticAtom.h"
 #include "nsMemory.h"
 
 // define storage for all accessibility atoms
 #define ACCESSIBILITY_ATOM(_name, _value) nsIAtom* nsAccessibilityAtoms::_name;
 #include "nsAccessibilityAtomList.h"
 #undef ACCESSIBILITY_ATOM
 
+#define ACCESSIBILITY_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsAccessibilityAtomList.h"
+#undef ACCESSIBILITY_ATOM
+
 static const nsStaticAtom atomInfo[] = {
-#define ACCESSIBILITY_ATOM(name_, value_) { value_, &nsAccessibilityAtoms::name_ },
+#define ACCESSIBILITY_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsAccessibilityAtoms::name_),
 #include "nsAccessibilityAtomList.h"
 #undef ACCESSIBILITY_ATOM
 };
 
 void nsAccessibilityAtoms::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(atomInfo, NS_ARRAY_LENGTH(atomInfo));
 }
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -60,17 +60,16 @@
 #include "nsCOMPtr.h"
 #include "nsDOMError.h"
 #include "nsEscape.h"
 #include "nsInt64.h"
 #include "nsLayoutCID.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsReadableUtils.h"
-#include "nsStaticAtom.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsWidgetsCID.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsXPIDLString.h"
 #include "nsXULAppAPI.h"
 #include "nsTextFormatter.h"
 
--- a/content/base/src/nsGkAtoms.cpp
+++ b/content/base/src/nsGkAtoms.cpp
@@ -40,22 +40,26 @@
  * set of atoms used by gklayout; the atoms are created when gklayout
  * is loaded and they are destroyed when gklayout is unloaded.
  */
 
 #include "nsGkAtoms.h"
 #include "nsStaticAtom.h"
 
 // define storage for all atoms
-#define GK_ATOM(_name, _value) nsIAtom* nsGkAtoms::_name;
+#define GK_ATOM(name_, value_) nsIAtom* nsGkAtoms::name_;
+#include "nsGkAtomList.h"
+#undef GK_ATOM
+
+#define GK_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 
 static const nsStaticAtom GkAtoms_info[] = {
-#define GK_ATOM(name_, value_) { value_, &nsGkAtoms::name_ },
+#define GK_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsGkAtoms::name_),
 #include "nsGkAtomList.h"
 #undef GK_ATOM
 };
 
 void nsGkAtoms::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(GkAtoms_info, NS_ARRAY_LENGTH(GkAtoms_info));
 }
--- a/editor/libeditor/html/nsEditProperty.cpp
+++ b/editor/libeditor/html/nsEditProperty.cpp
@@ -62,20 +62,25 @@ BLOCK:
 <!ENTITY % block
       "P | %heading (h1-h6); | %list (UL | OL); | %preformatted (PRE); | DL | DIV | NOSCRIPT |
        BLOCKQUOTE | FORM | HR | TABLE | FIELDSET | ADDRESS">
 
 But what about BODY, TR, TD, TH, CAPTION, COL, COLGROUP, THEAD, TFOOT, LI, DT, DD, LEGEND, etc.?
  
 
 */
+
+#define EDITOR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsEditPropertyAtomList.h"
+#undef EDITOR_ATOM
+
 void
 nsEditProperty::RegisterAtoms()
 {
   // inline tags
   static const nsStaticAtom property_atoms[] = {
-#define EDITOR_ATOM(name_, value_) { value_, &name_ },
+#define EDITOR_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &name_),
 #include "nsEditPropertyAtomList.h"
 #undef EDITOR_ATOM
   };
   
   NS_RegisterStaticAtoms(property_atoms, NS_ARRAY_LENGTH(property_atoms));
 }
--- a/editor/txtsvc/src/nsTextServicesDocument.cpp
+++ b/editor/txtsvc/src/nsTextServicesDocument.cpp
@@ -118,22 +118,26 @@ nsTextServicesDocument::~nsTextServicesD
 {
   nsCOMPtr<nsIEditor> editor (do_QueryReferent(mEditor));
   if (editor && mNotifier)
     editor->RemoveEditActionListener(mNotifier);
 
   ClearOffsetTable(&mOffsetTable);
 }
 
+#define TS_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsTSAtomList.h"
+#undef TS_ATOM
+
 /* static */
 void
 nsTextServicesDocument::RegisterAtoms()
 {
   static const nsStaticAtom ts_atoms[] = {
-#define TS_ATOM(name_, value_) { value_, &name_ },
+#define TS_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &name_),
 #include "nsTSAtomList.h"
 #undef TS_ATOM
   };
 
   NS_RegisterStaticAtoms(ts_atoms, NS_ARRAY_LENGTH(ts_atoms));
 }
 
 /* static */
--- a/gfx/thebes/src/gfxAtoms.cpp
+++ b/gfx/thebes/src/gfxAtoms.cpp
@@ -33,22 +33,26 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "gfxAtoms.h"
 #include "nsStaticAtom.h"
 #include "nsMemory.h"
 
-#define GFX_ATOM(_name, _value) nsIAtom* gfxAtoms::_name = 0;
+#define GFX_ATOM(name_, value_) nsIAtom* gfxAtoms::name_ = 0;
+#include "gfxAtomList.h"
+#undef GFX_ATOM
+
+#define GFX_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
 #include "gfxAtomList.h"
 #undef GFX_ATOM
 
 static const nsStaticAtom atoms[] = {
-#define GFX_ATOM(_name, _value) { _value, &gfxAtoms::_name },
+#define GFX_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &gfxAtoms::name_),
 #include "gfxAtomList.h"
 #undef GFX_ATOM
 };
 
 void gfxAtoms::RegisterAtoms()
 {
     NS_RegisterStaticAtoms(atoms, NS_ARRAY_LENGTH(atoms));
 }
--- a/gfx/thebes/test/gfxFontSelectionTests.h
+++ b/gfx/thebes/test/gfxFontSelectionTests.h
@@ -104,25 +104,25 @@ SetupTests()
 {
     TestEntry *t;
 
     /* some common styles */
     gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
                                           NS_FONT_STRETCH_NORMAL,
                                           400,
                                           16.0,
-                                          NS_NewPermanentAtom("en"),
+                                          NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")),
                                           0.0,
                                           PR_FALSE, PR_FALSE, PR_FALSE);
 
     gfxFontStyle style_western_bold_16 (FONT_STYLE_NORMAL,
                                         NS_FONT_STRETCH_NORMAL,
                                         700,
                                         16.0,
-                                        NS_NewPermanentAtom("en"),
+                                        NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")),
                                         0.0,
                                         PR_FALSE, PR_FALSE, PR_FALSE);
 
     /* Test 0 */
     t = AddTest ("sans-serif",
                  style_western_normal_16,
                  S_ASCII,
                  "ABCD");
--- a/gfx/thebes/test/gfxTextRunPerfTest.cpp
+++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp
@@ -88,17 +88,17 @@ const char* lastFamilies = nsnull;
 
 void
 RunTest (TestEntry *test, gfxContext *ctx) {
     if (!lastFamilies || strcmp(lastFamilies, test->mFamilies)) {
         gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
                                               NS_FONT_STRETCH_NORMAL,
                                               400,
                                               16.0,
-                                              NS_NewPermanentAtom("en"),
+                                              NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")),
                                               0.0,
                                               PR_FALSE, PR_FALSE, PR_FALSE);
 
         fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nsnull);
     }
 
     nsAutoPtr<gfxTextRun> textRun;
     PRUint32 i;
--- a/gfx/thebes/test/gfxWordCacheTest.cpp
+++ b/gfx/thebes/test/gfxWordCacheTest.cpp
@@ -154,17 +154,17 @@ main (int argc, char **argv) {
    gTextRuns = new FrameTextRunCache();
 
    nsRefPtr<gfxContext> ctx = MakeContext();
    {
        gfxFontStyle style (FONT_STYLE_NORMAL,
                            NS_FONT_STRETCH_NORMAL,
                            139,
                            10.0,
-                           NS_NewPermanentAtom("en"),
+                           NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")),
                            0.0,
                            PR_FALSE, PR_FALSE, PR_FALSE);
 
        nsRefPtr<gfxFontGroup> fontGroup =
            gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style, nsnull);
 
        gfxTextRunFactory::Parameters params = {
            ctx, nsnull, nsnull, nsnull, 0, 60
--- a/layout/inspector/src/inDOMView.cpp
+++ b/layout/inspector/src/inDOMView.cpp
@@ -101,60 +101,42 @@ inDOMViewNode::inDOMViewNode(nsIDOMNode*
 }
 
 inDOMViewNode::~inDOMViewNode()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////
 
-nsIAtom* inDOMView::kAnonymousAtom = nsnull;
-nsIAtom* inDOMView::kElementNodeAtom = nsnull;
-nsIAtom* inDOMView::kAttributeNodeAtom = nsnull;
-nsIAtom* inDOMView::kTextNodeAtom = nsnull;
-nsIAtom* inDOMView::kCDataSectionNodeAtom = nsnull;
-nsIAtom* inDOMView::kEntityReferenceNodeAtom = nsnull;
-nsIAtom* inDOMView::kEntityNodeAtom = nsnull;
-nsIAtom* inDOMView::kProcessingInstructionNodeAtom = nsnull;
-nsIAtom* inDOMView::kCommentNodeAtom = nsnull;
-nsIAtom* inDOMView::kDocumentNodeAtom = nsnull;
-nsIAtom* inDOMView::kDocumentTypeNodeAtom = nsnull;
-nsIAtom* inDOMView::kDocumentFragmentNodeAtom = nsnull;
-nsIAtom* inDOMView::kNotationNodeAtom = nsnull;
-nsIAtom* inDOMView::kAccessibleNodeAtom = nsnull;
-
 inDOMView::inDOMView() :
   mShowAnonymous(PR_FALSE),
   mShowSubDocuments(PR_FALSE),
   mShowWhitespaceNodes(PR_TRUE),
   mShowAccessibleNodes(PR_FALSE),
   mWhatToShow(nsIDOMNodeFilter::SHOW_ALL)
 {
 }
 
 inDOMView::~inDOMView()
 {
   SetRootNode(nsnull);
 }
 
+#define DOMVIEW_ATOM(name_, value_) nsIAtom* inDOMView::name_ = nsnull;
+#include "inDOMViewAtomList.h"
+#undef DOMVIEW_ATOM
+
+#define DOMVIEW_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "inDOMViewAtomList.h"
+#undef DOMVIEW_ATOM
+
 /* static */ const nsStaticAtom inDOMView::Atoms_info[] = {
-  {"anonymous", &inDOMView::kAnonymousAtom},
-  {"ELEMENT_NODE", &inDOMView::kElementNodeAtom},
-  {"ATTRIBUTE_NODE", &inDOMView::kAttributeNodeAtom},
-  {"TEXT_NODE", &inDOMView::kTextNodeAtom},
-  {"CDATA_SECTION_NODE", &inDOMView::kCDataSectionNodeAtom},
-  {"ENTITY_REFERENCE_NODE", &inDOMView::kEntityReferenceNodeAtom},
-  {"ENTITY_NODE", &inDOMView::kEntityNodeAtom},
-  {"PROCESSING_INSTRUCTION_NODE", &inDOMView::kProcessingInstructionNodeAtom},
-  {"COMMENT_NODE", &inDOMView::kCommentNodeAtom},
-  {"DOCUMENT_NODE", &inDOMView::kDocumentNodeAtom},
-  {"DOCUMENT_TYPE_NODE", &inDOMView::kDocumentTypeNodeAtom},
-  {"DOCUMENT_FRAGMENT_NODE", &inDOMView::kDocumentFragmentNodeAtom},
-  {"NOTATION_NODE", &inDOMView::kNotationNodeAtom},
-  {"ACCESSIBLE_NODE", &inDOMView::kAccessibleNodeAtom}
+#define DOMVIEW_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &inDOMView::name_),
+#include "inDOMViewAtomList.h"
+#undef DOMVIEW_ATOM
 };
 
 /* static */ void
 inDOMView::InitAtoms()
 {
   NS_RegisterStaticAtoms(Atoms_info, NS_ARRAY_LENGTH(Atoms_info));
 }
 
--- a/layout/inspector/src/inDOMView.h
+++ b/layout/inspector/src/inDOMView.h
@@ -69,30 +69,20 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
   static void InitAtoms();
 
 protected:
-  static nsIAtom* kAnonymousAtom;
-  static nsIAtom* kElementNodeAtom;
-  static nsIAtom* kAttributeNodeAtom;
-  static nsIAtom* kTextNodeAtom;
-  static nsIAtom* kCDataSectionNodeAtom;
-  static nsIAtom* kEntityReferenceNodeAtom;
-  static nsIAtom* kEntityNodeAtom;
-  static nsIAtom* kProcessingInstructionNodeAtom;
-  static nsIAtom* kCommentNodeAtom;
-  static nsIAtom* kDocumentNodeAtom;
-  static nsIAtom* kDocumentTypeNodeAtom;
-  static nsIAtom* kDocumentFragmentNodeAtom;
-  static nsIAtom* kNotationNodeAtom;
-  static nsIAtom* kAccessibleNodeAtom;
+
+#define DOMVIEW_ATOM(name_, value_) static nsIAtom* name_;
+#include "inDOMViewAtomList.h"
+#undef DOMVIEW_ATOM
 
   static const nsStaticAtom Atoms_info[]; 
 
   nsCOMPtr<nsITreeBoxObject> mTree;
   nsCOMPtr<nsITreeSelection> mSelection;
   nsCOMPtr<inIDOMUtils> mDOMUtils;
 
   PRPackedBool mShowAnonymous;
new file mode 100644
--- /dev/null
+++ b/layout/inspector/src/inDOMViewAtomList.h
@@ -0,0 +1,51 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2001
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Joe Hewitt <hewitt@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+DOMVIEW_ATOM(kAnonymousAtom, "anonymous")
+DOMVIEW_ATOM(kElementNodeAtom, "ELEMENT_NODE")
+DOMVIEW_ATOM(kAttributeNodeAtom, "ATTRIBUTE_NODE")
+DOMVIEW_ATOM(kTextNodeAtom, "TEXT_NODE")
+DOMVIEW_ATOM(kCDataSectionNodeAtom, "CDATA_SECTION_NODE")
+DOMVIEW_ATOM(kEntityReferenceNodeAtom, "ENTITY_REFERENCE_NODE")
+DOMVIEW_ATOM(kEntityNodeAtom, "ENTITY_NODE")
+DOMVIEW_ATOM(kProcessingInstructionNodeAtom, "PROCESSING_INSTRUCTION_NODE")
+DOMVIEW_ATOM(kCommentNodeAtom, "COMMENT_NODE")
+DOMVIEW_ATOM(kDocumentNodeAtom, "DOCUMENT_NODE")
+DOMVIEW_ATOM(kDocumentTypeNodeAtom, "DOCUMENT_TYPE_NODE")
+DOMVIEW_ATOM(kDocumentFragmentNodeAtom, "DOCUMENT_FRAGMENT_NODE")
+DOMVIEW_ATOM(kNotationNodeAtom, "NOTATION_NODE")
+DOMVIEW_ATOM(kAccessibleNodeAtom, "ACCESSIBLE_NODE")
--- a/layout/style/nsCSSAnonBoxes.cpp
+++ b/layout/style/nsCSSAnonBoxes.cpp
@@ -45,19 +45,24 @@
 #include "nsCRT.h"
 
 // define storage for all atoms
 #define CSS_ANON_BOX(_name, _value) \
   nsICSSAnonBoxPseudo* nsCSSAnonBoxes::_name;
 #include "nsCSSAnonBoxList.h"
 #undef CSS_ANON_BOX
 
+#define CSS_ANON_BOX(name_, value_) \
+  NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsCSSAnonBoxList.h"
+#undef CSS_ANON_BOX
+
 static const nsStaticAtom CSSAnonBoxes_info[] = {
 #define CSS_ANON_BOX(name_, value_) \
-  { value_, (nsIAtom**)&nsCSSAnonBoxes::name_ },
+  NS_STATIC_ATOM(name_##_buffer, (nsIAtom**)&nsCSSAnonBoxes::name_),
 #include "nsCSSAnonBoxList.h"
 #undef CSS_ANON_BOX
 };
 
 void nsCSSAnonBoxes::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(CSSAnonBoxes_info,
                          NS_ARRAY_LENGTH(CSSAnonBoxes_info));
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -44,19 +44,24 @@
 #include "nsMemory.h"
 
 // define storage for all atoms
 #define CSS_PSEUDO_CLASS(_name, _value) \
   nsICSSPseudoClass* nsCSSPseudoClasses::_name;
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 
+#define CSS_PSEUDO_CLASS(name_, value_) \
+  NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsCSSPseudoClassList.h"
+#undef CSS_PSEUDO_CLASS
+
 static const nsStaticAtom CSSPseudoClasses_info[] = {
 #define CSS_PSEUDO_CLASS(name_, value_) \
-  { value_, (nsIAtom**)&nsCSSPseudoClasses::name_ },
+  NS_STATIC_ATOM(name_##_buffer, (nsIAtom**)&nsCSSPseudoClasses::name_),
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 };
 
 void nsCSSPseudoClasses::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(CSSPseudoClasses_info,
                          NS_ARRAY_LENGTH(CSSPseudoClasses_info));
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -45,19 +45,23 @@
 #include "nsCSSAnonBoxes.h"
 
 // define storage for all atoms
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
   nsICSSPseudoElement* nsCSSPseudoElements::name_;
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
+#define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
+  NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsCSSPseudoElementList.h"
+
 static const nsStaticAtom CSSPseudoElements_info[] = {
 #define CSS_PSEUDO_ELEMENT(name_, value_, flags_) \
-    { value_, (nsIAtom**)&nsCSSPseudoElements::name_ },
+  NS_STATIC_ATOM(name_##_buffer, (nsIAtom**)&nsCSSPseudoElements::name_),
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 };
 
 // Separate from the array above so that we can have an array of
 // nsStaticAtom (to pass to NS_RegisterStaticAtoms and
 // nsAtomListUtils::IsMember), but with corresponding indices (so the
 // i-th element of this array is the flags for the i-th pseudo-element
--- a/parser/html/nsHtml5Atoms.cpp
+++ b/parser/html/nsHtml5Atoms.cpp
@@ -45,19 +45,22 @@
 #include "nsHtml5Atoms.h"
 #include "nsStaticAtom.h"
 
 // define storage for all atoms
 #define HTML5_ATOM(_name, _value) nsIAtom* nsHtml5Atoms::_name;
 #include "nsHtml5AtomList.h"
 #undef HTML5_ATOM
 
-static const nsStaticAtom Html5Atoms_info[] = {
+#define HTML5_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsHtml5AtomList.h"
+#undef HTML5_ATOM
 
-#define HTML5_ATOM(name_, value_) { value_, &nsHtml5Atoms::name_ },
+static const nsStaticAtom Html5Atoms_info[] = {
+#define HTML5_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsHtml5Atoms::name_),
 #include "nsHtml5AtomList.h"
 #undef HTML5_ATOM
 };
 
 void nsHtml5Atoms::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(Html5Atoms_info, NS_ARRAY_LENGTH(Html5Atoms_info));
 }
--- a/parser/htmlparser/src/nsHTMLTags.cpp
+++ b/parser/htmlparser/src/nsHTMLTags.cpp
@@ -311,22 +311,29 @@ HTMLTagsKeyCompareUCPtr(const void *key1
 static PLHashNumber
 HTMLTagsHashCodeAtom(const void *key)
 {
   return NS_PTR_TO_INT32(key) >> 2;
 }
 
 #define NS_HTMLTAG_NAME_MAX_LENGTH 10
 
+#define HTML_TAG(_tag, _classname) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
+#define HTML_OTHER(_tag)
+#include "nsHTMLTagList.h"
+#undef HTML_TAG
+#undef HTML_OTHER
+
+
 // static
 nsresult
 nsHTMLTags::AddRefTable(void)
 {
   // static array of tag StaticAtom structs
-#define HTML_TAG(_tag, _classname) { #_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1] },
+#define HTML_TAG(_tag, _classname) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
 #define HTML_OTHER(_tag)
   static const nsStaticAtom sTagAtoms_info[] = {
 #include "nsHTMLTagList.h"
   };
 #undef HTML_TAG
 #undef HTML_OTHER
 
   if (gTableRefCount++ == 0) {
@@ -360,27 +367,27 @@ nsHTMLTags::AddRefTable(void)
     }
 
 
 
 #ifdef DEBUG
     {
       // let's verify that all names in the the table are lowercase...
       for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
-        nsCAutoString temp1(sTagAtoms_info[i].mString);
-        nsCAutoString temp2(sTagAtoms_info[i].mString);
+        nsCAutoString temp1((char*)sTagAtoms_info[i].mStringBuffer->Data());
+        nsCAutoString temp2((char*)sTagAtoms_info[i].mStringBuffer->Data());
         ToLowerCase(temp1);
         NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
       }
 
       // let's verify that all names in the unicode strings above are
       // correct.
       for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
         nsAutoString temp1(sTagUnicodeTable[i]);
-        nsAutoString temp2; temp2.AssignWithConversion(sTagAtoms_info[i].mString);
+        nsAutoString temp2; temp2.AssignWithConversion((char*)sTagAtoms_info[i].mStringBuffer->Data());
         NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!");
       }
 
       // let's verify that NS_HTMLTAG_NAME_MAX_LENGTH is correct
       PRUint32 maxTagNameLength = 0;
       for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
         PRUint32 len = nsCRT::strlen(sTagUnicodeTable[i]);
         maxTagNameLength = NS_MAX(len, maxTagNameLength);        
--- a/rdf/base/src/nsRDFContentSink.cpp
+++ b/rdf/base/src/nsRDFContentSink.cpp
@@ -181,30 +181,19 @@ public:
     static nsIRDFContainerUtils* gRDFContainerUtils;
     static nsIRDFResource* kRDF_type;
     static nsIRDFResource* kRDF_instanceOf; // XXX should be RDF:type
     static nsIRDFResource* kRDF_Alt;
     static nsIRDFResource* kRDF_Bag;
     static nsIRDFResource* kRDF_Seq;
     static nsIRDFResource* kRDF_nextVal;
 
-    static nsIAtom* kAboutAtom;
-    static nsIAtom* kIdAtom;
-    static nsIAtom* kNodeIdAtom;
-    static nsIAtom* kAboutEachAtom;
-    static nsIAtom* kResourceAtom;
-    static nsIAtom* kRDFAtom;
-    static nsIAtom* kDescriptionAtom;
-    static nsIAtom* kBagAtom;
-    static nsIAtom* kSeqAtom;
-    static nsIAtom* kAltAtom;
-    static nsIAtom* kLiAtom;
-    static nsIAtom* kXMLNSAtom;
-    static nsIAtom* kParseTypeAtom;
-
+#define RDF_ATOM(name_, value_) static nsIAtom* name_;
+#include "nsRDFContentSinkAtomList.h"
+#undef RDF_ATOM
 
     typedef struct ContainerInfo {
         nsIRDFResource**  mType;
         nsContainerTestFn mTestFn;
         nsMakeContainerFn mMakeFn;
     } ContainerInfo;
 
 protected:
@@ -292,45 +281,30 @@ nsIRDFService*  RDFContentSinkImpl::gRDF
 nsIRDFContainerUtils* RDFContentSinkImpl::gRDFContainerUtils;
 nsIRDFResource* RDFContentSinkImpl::kRDF_type;
 nsIRDFResource* RDFContentSinkImpl::kRDF_instanceOf;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Alt;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Bag;
 nsIRDFResource* RDFContentSinkImpl::kRDF_Seq;
 nsIRDFResource* RDFContentSinkImpl::kRDF_nextVal;
 
-nsIAtom* RDFContentSinkImpl::kAboutAtom;
-nsIAtom* RDFContentSinkImpl::kIdAtom;
-nsIAtom* RDFContentSinkImpl::kNodeIdAtom;
-nsIAtom* RDFContentSinkImpl::kAboutEachAtom;
-nsIAtom* RDFContentSinkImpl::kResourceAtom;
-nsIAtom* RDFContentSinkImpl::kRDFAtom;
-nsIAtom* RDFContentSinkImpl::kDescriptionAtom;
-nsIAtom* RDFContentSinkImpl::kBagAtom;
-nsIAtom* RDFContentSinkImpl::kSeqAtom;
-nsIAtom* RDFContentSinkImpl::kAltAtom;
-nsIAtom* RDFContentSinkImpl::kLiAtom;
-nsIAtom* RDFContentSinkImpl::kXMLNSAtom;
-nsIAtom* RDFContentSinkImpl::kParseTypeAtom;
+////////////////////////////////////////////////////////////////////////
+
+#define RDF_ATOM(name_, value_) nsIAtom* RDFContentSinkImpl::name_;
+#include "nsRDFContentSinkAtomList.h"
+#undef RDF_ATOM
 
-////////////////////////////////////////////////////////////////////////
+#define RDF_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsRDFContentSinkAtomList.h"
+#undef RDF_ATOM
+
 static const nsStaticAtom rdf_atoms[] = {
-    { "about", &RDFContentSinkImpl::kAboutAtom },
-    { "ID", &RDFContentSinkImpl::kIdAtom },
-    { "nodeID", &RDFContentSinkImpl::kNodeIdAtom },
-    { "aboutEach", &RDFContentSinkImpl::kAboutEachAtom },
-    { "resource", &RDFContentSinkImpl::kResourceAtom },
-    { "RDF", &RDFContentSinkImpl::kRDFAtom },
-    { "Description", &RDFContentSinkImpl::kDescriptionAtom },
-    { "Bag", &RDFContentSinkImpl::kBagAtom },
-    { "Seq", &RDFContentSinkImpl::kSeqAtom },
-    { "Alt", &RDFContentSinkImpl::kAltAtom },
-    { "li", &RDFContentSinkImpl::kLiAtom },
-    { "xmlns", &RDFContentSinkImpl::kXMLNSAtom },
-    { "parseType", &RDFContentSinkImpl::kParseTypeAtom },
+#define RDF_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &RDFContentSinkImpl::name_),
+#include "nsRDFContentSinkAtomList.h"
+#undef RDF_ATOM
 };
 
 RDFContentSinkImpl::RDFContentSinkImpl()
     : mText(nsnull),
       mTextLength(0),
       mTextSize(0),
       mState(eRDFContentSinkState_InProlog),
       mParseMode(eRDFContentSinkParseMode_Literal),
new file mode 100644
--- /dev/null
+++ b/rdf/base/src/nsRDFContentSinkAtomList.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+RDF_ATOM(kAboutAtom, "about")
+RDF_ATOM(kIdAtom, "ID")
+RDF_ATOM(kNodeIdAtom, "nodeID")
+RDF_ATOM(kAboutEachAtom, "aboutEach")
+RDF_ATOM(kResourceAtom, "resource")
+RDF_ATOM(kRDFAtom, "RDF")
+RDF_ATOM(kDescriptionAtom, "Description")
+RDF_ATOM(kBagAtom, "Bag")
+RDF_ATOM(kSeqAtom, "Seq")
+RDF_ATOM(kAltAtom, "Alt")
+RDF_ATOM(kLiAtom, "li")
+RDF_ATOM(kXMLNSAtom, "xmlns")
+RDF_ATOM(kParseTypeAtom, "parseType")
--- a/widget/src/xpwidgets/nsWidgetAtoms.cpp
+++ b/widget/src/xpwidgets/nsWidgetAtoms.cpp
@@ -39,19 +39,23 @@
 #include "nsWidgetAtoms.h"
 #include "nsStaticAtom.h"
 #include "nsMemory.h"
 
 #define WIDGET_ATOM(_name, _value) nsIAtom* nsWidgetAtoms::_name = 0;
 #include "nsWidgetAtomList.h"
 #undef WIDGET_ATOM
 
+#define WIDGET_ATOM(_name, _value) NS_STATIC_ATOM_BUFFER(_name##_buffer, _value)
+#include "nsWidgetAtomList.h"
+#undef WIDGET_ATOM
+
 static const nsStaticAtom widget_atoms[] = {
 // define storage for all atoms
-#define WIDGET_ATOM(_name, _value) { _value, &nsWidgetAtoms::_name },
+#define WIDGET_ATOM(_name, _value) NS_STATIC_ATOM(_name##_buffer, &nsWidgetAtoms::_name),
 #include "nsWidgetAtomList.h"
 #undef WIDGET_ATOM
 };
 
 
 void nsWidgetAtoms::RegisterAtoms() {
 
   NS_RegisterStaticAtoms(widget_atoms, NS_ARRAY_LENGTH(widget_atoms));
--- a/xpcom/ds/nsAtomService.cpp
+++ b/xpcom/ds/nsAtomService.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -54,17 +54,17 @@ nsAtomService::GetAtom(const nsAString& 
     return NS_ERROR_OUT_OF_MEMORY;
   
   return NS_OK;
 }
 
 nsresult
 nsAtomService::GetPermanentAtom(const nsAString& aString, nsIAtom ** aResult)
 {
-  *aResult = NS_NewPermanentAtom(aString);
+  *aResult = NS_NewPermanentAtom(NS_ConvertUTF16toUTF8(aString));
 
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -76,15 +76,15 @@ nsAtomService::GetAtomUTF8(const char *a
         return NS_ERROR_OUT_OF_MEMORY;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAtomService::GetPermanentAtomUTF8(const char *aValue, nsIAtom* *aResult)
 {
-    *aResult = NS_NewPermanentAtom(aValue);
+    *aResult = NS_NewPermanentAtom(nsDependentCString(aValue));
 
     if (!*aResult)
         return NS_ERROR_OUT_OF_MEMORY;
 
     return NS_OK;
 }
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -42,87 +42,43 @@
 #include "nsReadableUtils.h"
 #include "nsUTF8Utils.h"
 #include "nsCRT.h"
 #include "pldhash.h"
 #include "prenv.h"
 #include "nsThreadUtils.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
+#include "nsAutoPtr.h"
 
 #define PL_ARENA_CONST_ALIGN_MASK 3
 #include "plarena.h"
 
-class nsStaticAtomWrapper;
-
 /**
  * The shared hash table for atom lookups.
  *
  * XXX This should be manipulated in a threadsafe way or we should make
  * sure it's only manipulated from the main thread.  Probably the latter
  * is better, since the former would hurt performance.
  *
  * If |gAtomTable.ops| is 0, then the table is uninitialized.
  */
 static PLDHashTable gAtomTable;
 
-// this is where we keep the nsStaticAtomWrapper objects
-
-static PLArenaPool* gStaticAtomArena = 0;
-
 /**
  * A hashtable of static atoms that existed at app startup. This hashtable helps 
  * nsHtml5AtomTable.
  */
 static nsDataHashtable<nsStringHashKey, nsIAtom*>* gStaticAtomTable = 0;
 
 /**
  * Whether it is still OK to add atoms to gStaticAtomTable.
  */
 static PRBool gStaticAtomTableSealed = PR_FALSE;
 
-class nsStaticAtomWrapper : public nsIAtom
-{
-public:
-  nsStaticAtomWrapper(const nsStaticAtom* aAtom, PRUint32 aLength) :
-    mStaticAtom(aAtom), mLength(aLength)
-  {
-    MOZ_COUNT_CTOR(nsStaticAtomWrapper);
-  }
-  ~nsStaticAtomWrapper() {   // no subclasses -> not virtual
-    // this is arena allocated and won't be called except in debug
-    // builds. If this function ever does anything non-debug, be sure
-    // to get rid of the ifdefs in AtomTableClearEntry!
-    MOZ_COUNT_DTOR(nsStaticAtomWrapper);
-  }
-
-  NS_IMETHOD QueryInterface(REFNSIID aIID,
-                            void** aInstancePtr);
-  NS_IMETHOD_(nsrefcnt) AddRef(void);
-  NS_IMETHOD_(nsrefcnt) Release(void);
-
-  NS_DECL_NSIATOM
-
-  const nsStaticAtom* GetStaticAtom() const {
-    return mStaticAtom;
-  }
-
-  PRUint32 getLength() const {
-    return mLength;
-  }
-
-private:
-  const nsStaticAtom* mStaticAtom;
-
-  // The length of the string in the static atom. The static atom
-  // (nsStaticAtom) doesn't hold a length, so we keep it here in the
-  // wrapper instead.
-  PRUint32 mLength;
-};
-
 // The |key| pointer in the various PLDHashTable callbacks we use is an
 // AtomTableClearEntry*.  These pointers can come from two places: either a
 // (probably stack-allocated) string key being passed to PL_DHashTableOperate,
 // or an actual entry in the atom table. PLDHashTable reseves the keyHash
 // values 0 and 1 for internal use, which means that the *PLDHashTable code*
 // will never pass an entry whose keyhash is 0 or 1 to our hooks. That means we
 // can use those values to tell whether an AtomTableEntry is a string key
 // created by a PLDHashTable code caller or an actual live AtomTableEntry used
@@ -156,88 +112,57 @@ struct AtomTableEntry : public PLDHashEn
   }
 
   inline AtomTableEntry(const PRUnichar *aString, PRUint32 aLength)
     : mBits(PtrBits(aString)), mLength(aLength)
   {
     keyHash = 1;
   }
 
-  inline PRBool IsStaticAtom() const {
-    NS_ASSERTION(keyHash > 1,
-                 "IsStaticAtom() called on non-atom AtomTableEntry!");
-    return (mBits & 0x1) != 0;
-  }
-
   inline PRBool IsUTF8String() const {
     return keyHash == 0;
   }
 
   inline PRBool IsUTF16String() const {
     return keyHash == 1;
   }
 
   inline void SetAtomImpl(AtomImpl* aAtom) {
     NS_ASSERTION(keyHash > 1,
                  "SetAtomImpl() called on non-atom AtomTableEntry!");
     NS_ASSERTION(aAtom, "Setting null atom");
     mBits = PtrBits(aAtom);
     mLength = aAtom->mLength;
   }
 
-  inline void SetStaticAtomWrapper(nsStaticAtomWrapper* aAtom) {
-    NS_ASSERTION(keyHash > 1,
-                 "SetStaticAtomWrapper() called on non-atom AtomTableEntry!");
-    NS_ASSERTION(aAtom, "Setting null atom");
-    NS_ASSERTION((PtrBits(aAtom) & ~0x1) == PtrBits(aAtom),
-                 "Pointers must align or this is broken");
-
-    mBits = PtrBits(aAtom) | 0x1;
-    mLength = aAtom->getLength();
-  }
-  
   inline void ClearAtom() {
     mBits = nsnull;
   }
 
   inline PRBool HasValue() const {
     NS_ASSERTION(keyHash > 1,
                  "HasValue() called on non-atom AtomTableEntry!");
     return (mBits & ~0x1) != 0;
   }
 
   // these accessors assume that you already know the type
   inline AtomImpl *GetAtomImpl() const {
     NS_ASSERTION(keyHash > 1,
                  "GetAtomImpl() called on non-atom AtomTableEntry!");
-    NS_ASSERTION(!IsStaticAtom(), "This is a static atom, not an AtomImpl");
     return (AtomImpl*) (mBits & ~0x1);
   }
 
-  inline nsStaticAtomWrapper *GetStaticAtomWrapper() const {
-    NS_ASSERTION(keyHash > 1,
-                 "GetStaticAtomWrapper() called on non-atom AtomTableEntry!");
-    NS_ASSERTION(IsStaticAtom(), "This is an AtomImpl, not a static atom");
-    return (nsStaticAtomWrapper*) (mBits & ~0x1);
-  }
-
-  inline const nsStaticAtom* GetStaticAtom() const {
-    NS_ASSERTION(keyHash > 1,
-                 "GetStaticAtom() called on non-atom AtomTableEntry!");
-    return GetStaticAtomWrapper()->GetStaticAtom();
-  }
-
   // type-agnostic accessors
 
   // get the string buffer
   inline const char* getAtomString() const {
     NS_ASSERTION(keyHash > 1,
                  "getAtomString() called on non-atom AtomTableEntry!");
 
-    return IsStaticAtom() ? GetStaticAtom()->mString : GetAtomImpl()->mString;
+    return GetAtomImpl()->mString;
   }
 
   // get the string buffer
   inline const char* getUTF8String() const {
     NS_ASSERTION(keyHash == 0,
                  "getUTF8String() called on non-UTF8 AtomTableEntry!");
 
     return (char *)mBits;
@@ -259,22 +184,17 @@ struct AtomTableEntry : public PLDHashEn
   // get an addreffed nsIAtom - not using already_AddRef'ed atom
   // because the callers are not (and should not be) using nsCOMPtr
   inline nsIAtom* GetAtom() const {
     NS_ASSERTION(keyHash > 1,
                  "GetAtom() called on non-atom AtomTableEntry!");
 
     nsIAtom* result;
     
-    if (IsStaticAtom())
-      result = GetStaticAtomWrapper();
-    else {
-      result = GetAtomImpl();
-      NS_ADDREF(result);
-    }
+    NS_ADDREF(result = GetAtomImpl());
     
     return result;
   }
 };
 
 static PLDHashNumber
 AtomTableGetHash(PLDHashTable *table, const void *key)
 {
@@ -322,32 +242,27 @@ AtomTableMatchKey(PLDHashTable *table, c
   return memcmp(atomString, str, length * sizeof(char)) == 0;
 }
 
 static void
 AtomTableClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   AtomTableEntry *he = static_cast<AtomTableEntry*>(entry);
   
-  if (!he->IsStaticAtom()) {
-    AtomImpl *atom = he->GetAtomImpl();
-    // Normal |AtomImpl| atoms are deleted when their refcount hits 0, and
-    // they then remove themselves from the table.  In other words, they
-    // are owned by the callers who own references to them.
-    // |PermanentAtomImpl| permanent atoms ignore their refcount and are
-    // deleted when they are removed from the table at table destruction.
-    // In other words, they are owned by the atom table.
-    if (atom->IsPermanent()) {
-      he->keyHash = 0;
+  AtomImpl *atom = he->GetAtomImpl();
+  // Normal |AtomImpl| atoms are deleted when their refcount hits 0, and
+  // they then remove themselves from the table.  In other words, they
+  // are owned by the callers who own references to them.
+  // |PermanentAtomImpl| permanent atoms ignore their refcount and are
+  // deleted when they are removed from the table at table destruction.
+  // In other words, they are owned by the atom table.
+  if (atom->IsPermanent()) {
+    he->keyHash = 0;
 
-      delete static_cast<PermanentAtomImpl*>(atom);
-    }
-  }
-  else {
-    he->GetStaticAtomWrapper()->~nsStaticAtomWrapper();
+    delete static_cast<PermanentAtomImpl*>(atom);
   }
   
   he->ClearAtom();
 }
 
 static PRBool
 AtomTableInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
                    const void *key)
@@ -369,37 +284,32 @@ static const PLDHashTableOps AtomTableOp
   PL_DHashMoveEntryStub,
   AtomTableClearEntry,
   PL_DHashFinalizeStub,
   AtomTableInitEntry
 };
 
 
 #ifdef DEBUG
-
 static PLDHashOperator
 DumpAtomLeaks(PLDHashTable *table, PLDHashEntryHdr *he,
               PRUint32 index, void *arg)
 {
   AtomTableEntry *entry = static_cast<AtomTableEntry*>(he);
   
-  if (entry->IsStaticAtom())
-    return PL_DHASH_NEXT;
-  
   AtomImpl* atom = entry->GetAtomImpl();
   if (!atom->IsPermanent()) {
     ++*static_cast<PRUint32*>(arg);
     const char *str;
     atom->GetUTF8String(&str);
     fputs(str, stdout);
     fputs("\n", stdout);
   }
   return PL_DHASH_NEXT;
 }
-
 #endif
 
 static inline
 void PromoteToPermanent(AtomImpl* aAtom)
 {
 #ifdef NS_BUILD_REFCNT_LOGGING
   {
     nsrefcnt refcount = aAtom->GetRefCount();
@@ -425,27 +335,42 @@ NS_PurgeAtomTable()
              gAtomTable.entryCount);
       PL_DHashTableEnumerate(&gAtomTable, DumpAtomLeaks, &leaked);
       printf("*** %u non-permanent atoms leaked\n", leaked);
     }
 #endif
     PL_DHashTableFinish(&gAtomTable);
     gAtomTable.entryCount = 0;
     gAtomTable.ops = nsnull;
-
-    if (gStaticAtomArena) {
-      PL_FinishArenaPool(gStaticAtomArena);
-      delete gStaticAtomArena;
-      gStaticAtomArena = nsnull;
-    }
   }
 }
 
-AtomImpl::AtomImpl()
+AtomImpl::AtomImpl(const nsACString& aString)
+  : mLength(aString.Length())
 {
+  nsStringBuffer* buf = nsStringBuffer::FromString(aString);
+  if (buf) {
+    buf->AddRef();
+    mString = static_cast<char*>(buf->Data());
+  }
+  else {
+    buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char));
+    mString = static_cast<char*>(buf->Data());
+    memcpy(mString, aString.BeginReading(), mLength * sizeof(char));
+    mString[mLength] = PRUnichar(0);
+  }
+}
+
+AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, PRUint32 aLength)
+  : mLength(aLength),
+    mString(static_cast<char*>(aStringBuffer->Data()))
+{
+  // Technically we could currently avoid doing this addref by instead making
+  // the static atom buffers have an initial refcount of 2.
+  aStringBuffer->AddRef();
 }
 
 AtomImpl::~AtomImpl()
 {
   NS_PRECONDITION(gAtomTable.ops, "uninitialized atom hashtable");
   // Permanent atoms are removed from the hashtable at shutdown, and we
   // don't want to remove them twice.  See comment above in
   // |AtomTableClearEntry|.
@@ -453,25 +378,22 @@ AtomImpl::~AtomImpl()
     AtomTableEntry key(mString, mLength);
     PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_REMOVE);
     if (gAtomTable.entryCount == 0) {
       PL_DHashTableFinish(&gAtomTable);
       NS_ASSERTION(gAtomTable.entryCount == 0,
                    "PL_DHashTableFinish changed the entry count");
     }
   }
+
+  nsStringBuffer::FromData(mString)->Release();
 }
 
 NS_IMPL_ISUPPORTS1(AtomImpl, nsIAtom)
 
-PermanentAtomImpl::PermanentAtomImpl()
-  : AtomImpl()
-{
-}
-
 PermanentAtomImpl::~PermanentAtomImpl()
 {
   // So we can tell if we were permanent while running the base class dtor.
   mRefCnt = REFCNT_PERMANENT_SENTINEL;
 }
 
 NS_IMETHODIMP_(nsrefcnt) PermanentAtomImpl::AddRef()
 {
@@ -492,38 +414,16 @@ AtomImpl::IsPermanent()
 }
 
 /* virtual */ PRBool
 PermanentAtomImpl::IsPermanent()
 {
   return PR_TRUE;
 }
 
-void* AtomImpl::operator new ( size_t size, const nsACString& aString ) CPP_THROW_NEW
-{
-    /*
-      Note: since the |size| will initially also include the |PRUnichar| member
-        |mString|, our size calculation will give us one character too many.
-        We use that extra character for a zero-terminator.
-
-      Note: this construction is not guaranteed to be possible by the C++
-        compiler.  A more reliable scheme is used by |nsShared[C]String|s, see
-        http://lxr.mozilla.org/seamonkey/source/xpcom/ds/nsSharedString.h#174
-     */
-  size += aString.Length() * sizeof(char);
-  AtomImpl* ii = static_cast<AtomImpl*>(::operator new(size));
-  NS_ENSURE_TRUE(ii, nsnull);
-
-  char* toBegin = &ii->mString[0];
-  nsACString::const_iterator fromBegin, fromEnd;
-  *copy_string(aString.BeginReading(fromBegin), aString.EndReading(fromEnd), toBegin) = '\0';
-  ii->mLength = aString.Length();
-  return ii;
-}
-
 void* PermanentAtomImpl::operator new ( size_t size, AtomImpl* aAtom ) CPP_THROW_NEW {
   NS_ASSERTION(!aAtom->IsPermanent(),
                "converting atom that's already permanent");
 
   // Just let the constructor overwrite the vtable pointer.
   return aAtom;
 }
 
@@ -532,17 +432,17 @@ AtomImpl::ToString(nsAString& aBuf)
 {
   CopyUTF8toUTF16(nsDependentCString(mString, mLength), aBuf);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AtomImpl::ToUTF8String(nsACString& aBuf)
 {
-  aBuf.Assign(mString, mLength);
+  nsStringBuffer::FromData(mString)->ToString(mLength, aBuf);
   return NS_OK;
 }
 
 NS_IMETHODIMP 
 AtomImpl::GetUTF8String(const char **aResult)
 {
   NS_PRECONDITION(aResult, "null out param");
   *aResult = mString;
@@ -562,108 +462,21 @@ AtomImpl::Equals(const nsAString& aStrin
   *aResult = CompareUTF8toUTF16(nsDependentCString(mString, mLength),
                                 aString) == 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP_(PRBool)
 AtomImpl::IsStaticAtom()
 {
-  return PR_FALSE;
+  return IsPermanent();
 }
 
 //----------------------------------------------------------------------
 
-// wrapper class for the nsStaticAtom struct
-
-NS_IMETHODIMP_(nsrefcnt)
-nsStaticAtomWrapper::AddRef()
-{
-  NS_ASSERTION(NS_IsMainThread(), "wrong thread");
-  return 2;
-}
-
-NS_IMETHODIMP_(nsrefcnt)
-nsStaticAtomWrapper::Release()
-{
-  NS_ASSERTION(NS_IsMainThread(), "wrong thread");
-  return 1;
-}
-
-NS_IMPL_QUERY_INTERFACE1(nsStaticAtomWrapper, nsIAtom)
-
-NS_IMETHODIMP
-nsStaticAtomWrapper::GetUTF8String(const char** aResult)
-{
-  *aResult = mStaticAtom->mString;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsStaticAtomWrapper::ToString(nsAString& aBuf)
-{
-  // static should always be always ASCII, to allow tools like gperf
-  // to generate the tables, and to avoid unnecessary conversion
-  NS_ASSERTION(nsCRT::IsAscii(mStaticAtom->mString),
-               "Data loss - atom should be ASCII");
-  CopyASCIItoUTF16(nsDependentCString(mStaticAtom->mString, mLength), aBuf);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsStaticAtomWrapper::ToUTF8String(nsACString& aBuf)
-{
-  aBuf.Assign(mStaticAtom->mString);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsStaticAtomWrapper::EqualsUTF8(const nsACString& aString, PRBool* aResult)
-{
-  *aResult = aString.Equals(nsDependentCString(mStaticAtom->mString, mLength));
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsStaticAtomWrapper::Equals(const nsAString& aString, PRBool* aResult)
-{
-  *aResult = CompareUTF8toUTF16(nsDependentCString(mStaticAtom->mString,
-                                                   mLength),
-                                aString) == 0;
-  return NS_OK;
-}
-
-NS_IMETHODIMP_(PRBool)
-nsStaticAtomWrapper::IsStaticAtom()
-{
-  return PR_TRUE;
-}
-
-//----------------------------------------------------------------------
-
-static nsStaticAtomWrapper*
-WrapStaticAtom(const nsStaticAtom* aAtom, PRUint32 aLength)
-{
-  if (!gStaticAtomArena) {
-    gStaticAtomArena = new PLArenaPool;
-    if (!gStaticAtomArena)
-      return nsnull;
-    
-    PL_INIT_ARENA_POOL(gStaticAtomArena, "nsStaticAtomArena", 4096);
-  }
-
-  void* mem;
-  PL_ARENA_ALLOCATE(mem, gStaticAtomArena, sizeof(nsStaticAtomWrapper));
-
-  nsStaticAtomWrapper* wrapper =
-    new (mem) nsStaticAtomWrapper(aAtom, aLength);
-
-  return wrapper;
-}
-
 #define ATOM_HASHTABLE_INITIAL_SIZE  4096
 
 static inline AtomTableEntry*
 GetAtomHashEntry(const char* aString, PRUint32 aLength)
 {
   NS_ASSERTION(NS_IsMainThread(), "wrong thread");
   if (!gAtomTable.ops &&
       !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0,
@@ -688,16 +501,32 @@ GetAtomHashEntry(const PRUnichar* aStrin
     return nsnull;
   }
 
   AtomTableEntry key(aString, aLength);
   return static_cast<AtomTableEntry*>
                     (PL_DHashTableOperate(&gAtomTable, &key, PL_DHASH_ADD));
 }
 
+class CheckStaticAtomSizes
+{
+  CheckStaticAtomSizes() {
+    PR_STATIC_ASSERT((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
+                      sizeof(nsStringBuffer().mRefCount)) &&
+                     (sizeof(nsFakeStringBuffer<1>().mSize) ==
+                      sizeof(nsStringBuffer().mStorageSize)) &&
+                     (offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
+                      offsetof(nsStringBuffer, mRefCount)) &&
+                     (offsetof(nsFakeStringBuffer<1>, mSize) ==
+                      offsetof(nsStringBuffer, mStorageSize)) &&
+                     (offsetof(nsFakeStringBuffer<1>, mStringData) ==
+                      sizeof(nsStringBuffer)));
+  }
+};
+
 NS_COM nsresult
 NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
 {
   // this does three things:
   // 1) wraps each static atom in a wrapper, if necessary
   // 2) initializes the address pointed to by each mBits slot
   // 3) puts the atom into the static atom table as well
   
@@ -706,48 +535,44 @@ NS_RegisterStaticAtoms(const nsStaticAto
     if (!gStaticAtomTable || !gStaticAtomTable->Init()) {
       delete gStaticAtomTable;
       gStaticAtomTable = nsnull;
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
   
   for (PRUint32 i=0; i<aAtomCount; i++) {
-    NS_ASSERTION(nsCRT::IsAscii(aAtoms[i].mString),
+    NS_ASSERTION(nsCRT::IsAscii((char*)aAtoms[i].mStringBuffer->Data()),
                  "Static atoms must be ASCII!");
 
-    PRUint32 stringLen = strlen(aAtoms[i].mString);
+    PRUint32 stringLen =
+      aAtoms[i].mStringBuffer->StorageSize() / sizeof(char) - 1;
 
     AtomTableEntry *he =
-      GetAtomHashEntry(aAtoms[i].mString, stringLen);
+      GetAtomHashEntry((char*)aAtoms[i].mStringBuffer->Data(),
+                       stringLen);
 
-    if (he->HasValue() && aAtoms[i].mAtom) {
+    if (he->HasValue()) {
       // there already is an atom with this name in the table.. but we
       // still have to update mBits
-      if (!he->IsStaticAtom() && !he->GetAtomImpl()->IsPermanent()) {
+      if (!he->GetAtomImpl()->IsPermanent()) {
         // since we wanted to create a static atom but there is
         // already one there, we convert it to a non-refcounting
         // permanent atom
         PromoteToPermanent(he->GetAtomImpl());
       }
       
-      // and now, if the consumer wants to remember this value in a
-      // slot, we do so
-      if (aAtoms[i].mAtom)
-        *aAtoms[i].mAtom = he->GetAtom();
+      *aAtoms[i].mAtom = he->GetAtom();
     }
     else {
-      nsStaticAtomWrapper* atom = WrapStaticAtom(&aAtoms[i], stringLen);
-      NS_ASSERTION(atom, "Failed to wrap static atom");
+      AtomImpl* atom = new PermanentAtomImpl(aAtoms[i].mStringBuffer,
+                                             stringLen);
+      he->SetAtomImpl(atom);
+      *aAtoms[i].mAtom = atom;
 
-      // but even if atom is null, no real difference in code..
-      he->SetStaticAtomWrapper(atom);
-      if (aAtoms[i].mAtom)
-        *aAtoms[i].mAtom = atom;
-        
       if (!gStaticAtomTableSealed) {
         nsAutoString key;
         atom->ToString(key);
         gStaticAtomTable->Put(key, atom);
       }
     }
   }
   return NS_OK;
@@ -770,24 +595,20 @@ NS_NewAtom(const nsACString& aUTF8String
   }
 
   NS_ASSERTION(!he->IsUTF8String() && !he->IsUTF16String(),
                "Atom hash entry is string?  Should be atom!");
 
   if (he->HasValue())
     return he->GetAtom();
 
-  AtomImpl* atom = new (aUTF8String) AtomImpl();
+  AtomImpl* atom = new AtomImpl(aUTF8String);
   he->SetAtomImpl(atom);
-  if (!atom) {
-    PL_DHashTableRawRemove(&gAtomTable, he);
-    return nsnull;
-  }
+  NS_ADDREF(atom);
 
-  NS_ADDREF(atom);
   return atom;
 }
 
 NS_COM nsIAtom*
 NS_NewAtom(const PRUnichar* aUTF16String)
 {
   return NS_NewAtom(nsDependentString(aUTF16String));
 }
@@ -796,80 +617,50 @@ NS_COM nsIAtom*
 NS_NewAtom(const nsAString& aUTF16String)
 {
   AtomTableEntry *he = GetAtomHashEntry(aUTF16String.Data(),
                                         aUTF16String.Length());
 
   if (he->HasValue())
     return he->GetAtom();
 
-  // MSVC.NET doesn't like passing a temporary NS_ConvertUTF16toUTF8() to
-  // operator new, so declare one as a local instead.
-  NS_ConvertUTF16toUTF8 str(aUTF16String);
-  AtomImpl* atom = new (str) AtomImpl();
+  // This results in an extra addref/release of the nsStringBuffer.
+  // Unfortunately there doesn't seem to be any APIs to avoid that.
+  nsCString str;
+  CopyUTF16toUTF8(aUTF16String, str);
+  AtomImpl* atom = new AtomImpl(str);
+
   he->SetAtomImpl(atom);
-  if (!atom) {
-    PL_DHashTableRawRemove(&gAtomTable, he);
-    return nsnull;
-  }
+  NS_ADDREF(atom);
 
-  NS_ADDREF(atom);
   return atom;
 }
 
 NS_COM nsIAtom*
-NS_NewPermanentAtom(const char* aUTF8String)
-{
-  return NS_NewPermanentAtom(nsDependentCString(aUTF8String));
-}
-
-NS_COM nsIAtom*
 NS_NewPermanentAtom(const nsACString& aUTF8String)
 {
   AtomTableEntry *he = GetAtomHashEntry(aUTF8String.Data(),
                                         aUTF8String.Length());
 
-  if (he->HasValue() && he->IsStaticAtom())
-    return he->GetStaticAtomWrapper();
-  
-  // either there is no atom and we'll create an AtomImpl,
-  // or there is an existing AtomImpl
-  AtomImpl* atom = he->GetAtomImpl();
-  
-  if (atom) {
-    // ensure that it's permanent
+  if (he->HasValue()) {
+    AtomImpl* atom = he->GetAtomImpl();
     if (!atom->IsPermanent()) {
       PromoteToPermanent(atom);
     }
-  } else {
-    // otherwise, make a new atom
-    atom = new (aUTF8String) PermanentAtomImpl();
-    he->SetAtomImpl(atom);
-    if ( !atom ) {
-      PL_DHashTableRawRemove(&gAtomTable, he);
-      return nsnull;
-    }
+    return atom;
   }
+  
+  AtomImpl* atom = new PermanentAtomImpl(aUTF8String);
+  he->SetAtomImpl(atom);
 
-  NS_ADDREF(atom);
+  // No need to addref since permanent atoms aren't refcounted anyway
+
   return atom;
 }
 
-NS_COM nsIAtom*
-NS_NewPermanentAtom(const nsAString& aUTF16String)
-{
-  return NS_NewPermanentAtom(NS_ConvertUTF16toUTF8(aUTF16String));
-}
-
-NS_COM nsIAtom*
-NS_NewPermanentAtom(const PRUnichar* aUTF16String)
-{
-  return NS_NewPermanentAtom(NS_ConvertUTF16toUTF8(aUTF16String));
-}
-
 NS_COM nsrefcnt
 NS_GetNumberOfAtoms(void)
 {
   return gAtomTable.entryCount;
 }
 
 NS_COM nsIAtom*
 NS_GetStaticAtom(const nsAString& aUTF16String)
--- a/xpcom/ds/nsAtomTable.h
+++ b/xpcom/ds/nsAtomTable.h
@@ -34,28 +34,43 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsAtomTable_h__
 #define nsAtomTable_h__
 
 #include "nsIAtom.h"
+#include "nsStringBuffer.h"
 
 /**
- * A threadsafely-refcounted implementation of nsIAtom.  Note that
- * AtomImpl objects are sometimes converted into PermanentAtomImpl
+ * Note that AtomImpl objects are sometimes converted into PermanentAtomImpl
  * objects using placement new and just overwriting the vtable pointer.
  */
 
 class AtomImpl : public nsIAtom {
 public:
-  AtomImpl();
+  AtomImpl(const nsACString& aString);
+
+  // This is currently only used during startup when creating a permanent atom
+  // from NS_RegisterStaticAtoms
+  AtomImpl(nsStringBuffer* aData, PRUint32 aLength);
 
 protected:
+  // This is only intended to be used when a normal atom is turned into a
+  // permanent one.
+  AtomImpl() {
+    // We can't really assert that mString is a valid nsStringBuffer string,
+    // so do the best we can do and check for some consistencies.
+    NS_ASSERTION((mLength + 1) * sizeof(char) <=
+                 nsStringBuffer::FromData(mString)->StorageSize() &&
+                 mString[mLength] == 0,
+                 "Not initialized atom");
+  }
+
   // We don't need a virtual destructor here because PermanentAtomImpl
   // deletions aren't handled through Release().
   ~AtomImpl();
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIATOM
 
@@ -63,48 +78,50 @@ public:
 
   virtual PRBool IsPermanent();
 
   // We can't use the virtual function in the base class destructor.
   PRBool IsPermanentInDestructor() {
     return mRefCnt == REFCNT_PERMANENT_SENTINEL;
   }
 
-  void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW;
-
-  void operator delete(void* ptr) {
-    ::operator delete(ptr);
-  }
-
   // for |#ifdef NS_BUILD_REFCNT_LOGGING| access to reference count
   nsrefcnt GetRefCount() { return mRefCnt; }
 
   // The length of the string in the atom.
   PRUint32 mLength;
 
-  // Actually more; 0 terminated. This slot is reserved for the
-  // terminating zero.
-  char mString[1];
+  // This always points to the data owned by a nsStringBuffer
+  char* mString;
 };
 
 /**
  * A non-refcounted implementation of nsIAtom.
  */
 
 class PermanentAtomImpl : public AtomImpl {
 public:
-  PermanentAtomImpl();
+  PermanentAtomImpl(const nsACString& aString)
+    : AtomImpl(aString)
+  {}
+  PermanentAtomImpl(nsStringBuffer* aData, PRUint32 aLength)
+    : AtomImpl(aData, aLength)
+  {}
+  PermanentAtomImpl()
+  {}
+
   ~PermanentAtomImpl();
   NS_IMETHOD_(nsrefcnt) AddRef();
   NS_IMETHOD_(nsrefcnt) Release();
 
   virtual PRBool IsPermanent();
 
-  void* operator new(size_t size, const nsACString& aString) CPP_THROW_NEW {
-    return AtomImpl::operator new(size, aString);
+  void* operator new(size_t size, AtomImpl* aAtom) CPP_THROW_NEW;
+  void* operator new(size_t size) CPP_THROW_NEW
+  {
+    return ::operator new(size);
   }
-  void* operator new(size_t size, AtomImpl* aAtom) CPP_THROW_NEW;
 
 };
 
 void NS_PurgeAtomTable();
 
 #endif // nsAtomTable_h__
--- a/xpcom/ds/nsIAtom.idl
+++ b/xpcom/ds/nsIAtom.idl
@@ -110,56 +110,42 @@ interface nsIAtom : nsISupports
  */
 
 
 /**
  * Find an atom that matches the given UTF-8 string.
  * The string is assumed to be zero terminated.
  */
 extern NS_COM nsIAtom* NS_NewAtom(const char* aUTF8String);
-extern NS_COM nsIAtom* NS_NewPermanentAtom(const char* aUTF8String);
 
 inline already_AddRefed<nsIAtom> do_GetAtom(const char* aUTF8String)
     { return NS_NewAtom(aUTF8String); }
-inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const char* aUTF8String)
-    { return NS_NewPermanentAtom(aUTF8String); }
  
 /**
  * Find an atom that matches the given UTF-8 string.
  */
 extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String);
 extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsACString& aUTF8String);
-
 inline already_AddRefed<nsIAtom> do_GetAtom(const nsACString& aUTF8String)
     { return NS_NewAtom(aUTF8String); }
-inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsACString& aUTF8String)
-    { return NS_NewPermanentAtom(aUTF8String); }
 
 /**
  * Find an atom that matches the given UTF-16 string.
  * The string is assumed to be zero terminated.
  */
 extern NS_COM nsIAtom* NS_NewAtom(const PRUnichar* aUTF16String);
-extern NS_COM nsIAtom* NS_NewPermanentAtom(const PRUnichar* aUTF16String);
-
 inline already_AddRefed<nsIAtom> do_GetAtom(const PRUnichar* aUTF16String)
     { return NS_NewAtom(aUTF16String); }
-inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const PRUnichar* aUTF16String)
-    { return NS_NewPermanentAtom(aUTF16String); }
 
 /**
  * Find an atom that matches the given UTF-16 string.
  */
 extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String);
-extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsAString& aUTF16String);
-
 inline already_AddRefed<nsIAtom> do_GetAtom(const nsAString& aUTF16String)
     { return NS_NewAtom(aUTF16String); }
-inline already_AddRefed<nsIAtom> do_GetPermanentAtom(const nsAString& aUTF16String)
-    { return NS_NewPermanentAtom(aUTF16String); }
 
 /**
  * Return a count of the total number of atoms currently
  * alive in the system.
  */
 extern NS_COM nsrefcnt NS_GetNumberOfAtoms(void);
 
 /**
--- a/xpcom/ds/nsStaticAtom.h
+++ b/xpcom/ds/nsStaticAtom.h
@@ -35,31 +35,40 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsStaticAtom_h__
 #define nsStaticAtom_h__
 
 #include "nsIAtom.h"
+#include "nsStringBuffer.h"
+#include "prlog.h"
 
-// see http://www.mozilla.org/projects/xpcom/atoms.html to use this stuff
+#define NS_STATIC_ATOM(buffer_name, atom_ptr)  { (nsStringBuffer*) &buffer_name, atom_ptr }
+#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) static nsFakeStringBuffer< sizeof(str_data) > buffer_name = { 1, sizeof(str_data), str_data };
 
-// class for declaring a static list of atoms, for use with gperf
-// Keep this VERY simple
-// mString: the value of the atom - the policy is that this is only
-//          ASCII, in order to avoid unnecessary conversions if
-//          someone asks for this in unicode
-// mAtom:   a convienience pointer - if you want to store the value of
-//          the atom created by this structure somewhere, put its
-//          address here
+/**
+ * Holds data used to initialize large number of atoms during startup. Use
+ * the above macros to initialize these structs. They should never be accessed
+ * directly other than from AtomTable.cpp
+ */
 struct nsStaticAtom {
-    const char* mString;
+    nsStringBuffer* mStringBuffer;
     nsIAtom ** mAtom;
 };
 
+/**
+ * This is a struct with the same binary layout as a nsStringBuffer.
+ */
+template <PRUint32 size>
+struct nsFakeStringBuffer {
+    PRInt32 mRefCnt;
+    PRUint32 mSize;
+    char mStringData[size];
+};
 
 // register your lookup function with the atom table. Your function
 // will be called when at atom is not found in the main atom table.
 NS_COM nsresult
 NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount);
 
 #endif
--- a/xpcom/io/Makefile.in
+++ b/xpcom/io/Makefile.in
@@ -96,16 +96,17 @@ else
 CPPSRCS		+= nsLocalFileUnix.cpp
 endif # windows
 endif # mac
 endif # OS2
 
 EXPORTS		= \
 		nsAppDirectoryServiceDefs.h \
 		nsDirectoryService.h \
+		nsDirectoryServiceAtomList.h \
 		nsEscape.h \
 		nsFastLoadService.h \
 		nsLinebreakConverter.h \
 		nsLocalFile.h \
 		nsMultiplexInputStream.h \
 		nsNativeCharsetUtils.h \
 		nsScriptableInputStream.h \
 		nsStorageStream.h \
--- a/xpcom/io/nsDirectoryService.cpp
+++ b/xpcom/io/nsDirectoryService.cpp
@@ -272,110 +272,16 @@ nsDirectoryService::GetCurrentProcessDir
 #endif
     
     NS_RELEASE(localFile);
 
     NS_ERROR("unable to get current process directory");
     return NS_ERROR_FAILURE;
 } // GetCurrentProcessDirectory()
 
-
-nsIAtom*  nsDirectoryService::sCurrentProcess = nsnull;
-nsIAtom*  nsDirectoryService::sComponentRegistry = nsnull;
-nsIAtom*  nsDirectoryService::sXPTIRegistry = nsnull;
-nsIAtom*  nsDirectoryService::sComponentDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sGRE_Directory = nsnull;
-nsIAtom*  nsDirectoryService::sGRE_ComponentDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_DriveDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_TemporaryDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_CurrentProcessDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_CurrentWorkingDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_DesktopDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS_HomeDirectory = nsnull;
-#if defined (XP_MACOSX)
-nsIAtom*  nsDirectoryService::sDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sTrashDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sStartupDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sShutdownDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sAppleMenuDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sControlPanelDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sExtensionDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sFontsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sPreferencesDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sInternetSearchDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserLibDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sDefaultDownloadDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserDesktopDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalDesktopDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserApplicationsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalApplicationsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserInternetPlugInDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalInternetPlugInDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserFrameworksDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalFrameworksDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sUserPreferencesDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLocalPreferencesDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sPictureDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sMovieDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sMusicDocumentsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sInternetSitesDirectory = nsnull;
-#elif defined (XP_WIN) 
-nsIAtom*  nsDirectoryService::sSystemDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sWindowsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sWindowsProgramFiles = nsnull;
-nsIAtom*  nsDirectoryService::sDesktop = nsnull;
-nsIAtom*  nsDirectoryService::sPrograms = nsnull;
-nsIAtom*  nsDirectoryService::sControls = nsnull;
-nsIAtom*  nsDirectoryService::sPrinters = nsnull;
-nsIAtom*  nsDirectoryService::sPersonal = nsnull;
-nsIAtom*  nsDirectoryService::sFavorites = nsnull;
-nsIAtom*  nsDirectoryService::sStartup = nsnull;
-nsIAtom*  nsDirectoryService::sRecent = nsnull;
-nsIAtom*  nsDirectoryService::sSendto = nsnull;
-nsIAtom*  nsDirectoryService::sBitbucket = nsnull;
-nsIAtom*  nsDirectoryService::sStartmenu = nsnull;
-nsIAtom*  nsDirectoryService::sDesktopdirectory = nsnull;
-nsIAtom*  nsDirectoryService::sDrives = nsnull;
-nsIAtom*  nsDirectoryService::sNetwork = nsnull;
-nsIAtom*  nsDirectoryService::sNethood = nsnull;
-nsIAtom*  nsDirectoryService::sFonts = nsnull;
-nsIAtom*  nsDirectoryService::sTemplates = nsnull;
-nsIAtom*  nsDirectoryService::sCommon_Startmenu = nsnull;
-nsIAtom*  nsDirectoryService::sCommon_Programs = nsnull;
-nsIAtom*  nsDirectoryService::sCommon_Startup = nsnull;
-nsIAtom*  nsDirectoryService::sCommon_Desktopdirectory = nsnull;
-nsIAtom*  nsDirectoryService::sAppdata = nsnull;
-nsIAtom*  nsDirectoryService::sLocalAppdata = nsnull;
-nsIAtom*  nsDirectoryService::sPrinthood = nsnull;
-nsIAtom*  nsDirectoryService::sWinCookiesDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sDefaultDownloadDirectory = nsnull;
-#elif defined (XP_UNIX)
-nsIAtom*  nsDirectoryService::sLocalDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sLibDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sDefaultDownloadDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sXDGDesktop = nsnull;
-nsIAtom*  nsDirectoryService::sXDGDocuments = nsnull;
-nsIAtom*  nsDirectoryService::sXDGDownload = nsnull;
-nsIAtom*  nsDirectoryService::sXDGMusic = nsnull;
-nsIAtom*  nsDirectoryService::sXDGPictures = nsnull;
-nsIAtom*  nsDirectoryService::sXDGPublicShare = nsnull;
-nsIAtom*  nsDirectoryService::sXDGTemplates = nsnull;
-nsIAtom*  nsDirectoryService::sXDGVideos = nsnull;
-#elif defined (XP_OS2)
-nsIAtom*  nsDirectoryService::sSystemDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sOS2Directory = nsnull;
-#elif defined (XP_BEOS)
-nsIAtom*  nsDirectoryService::sSettingsDirectory = nsnull;
-nsIAtom*  nsDirectoryService::sSystemDirectory = nsnull;
-#endif
-
-
 nsDirectoryService* nsDirectoryService::gService = nsnull;
 
 nsDirectoryService::nsDirectoryService() :
     mHashtable(256, PR_TRUE)
 {
 }
 
 NS_METHOD
@@ -387,109 +293,28 @@ nsDirectoryService::Create(nsISupports *
     if (!gService)
     {
         return NS_ERROR_NOT_INITIALIZED;
     }
 
     return gService->QueryInterface(aIID, aResult);
 }
 
+#define DIR_ATOM(name_, value_) nsIAtom* nsDirectoryService::name_ = nsnull;
+#include "nsDirectoryServiceAtomList.h"
+#undef DIR_ATOM
+
+#define DIR_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "nsDirectoryServiceAtomList.h"
+#undef DIR_ATOM
+
 static const nsStaticAtom directory_atoms[] = {
-    { NS_XPCOM_CURRENT_PROCESS_DIR,     &nsDirectoryService::sCurrentProcess },
-    { NS_XPCOM_COMPONENT_REGISTRY_FILE, &nsDirectoryService::sComponentRegistry },
-    { NS_XPCOM_COMPONENT_DIR,         &nsDirectoryService::sComponentDirectory },
-    { NS_XPCOM_XPTI_REGISTRY_FILE, &nsDirectoryService::sXPTIRegistry },
-    { NS_GRE_DIR,                  &nsDirectoryService::sGRE_Directory },
-    { NS_GRE_COMPONENT_DIR,        &nsDirectoryService::sGRE_ComponentDirectory },
-    { NS_OS_DRIVE_DIR,             &nsDirectoryService::sOS_DriveDirectory },
-    { NS_OS_TEMP_DIR,              &nsDirectoryService::sOS_TemporaryDirectory },
-    { NS_OS_CURRENT_PROCESS_DIR,   &nsDirectoryService::sOS_CurrentProcessDirectory },
-    { NS_OS_CURRENT_WORKING_DIR,   &nsDirectoryService::sOS_CurrentWorkingDirectory },
-    { NS_OS_HOME_DIR,              &nsDirectoryService::sOS_HomeDirectory },
-    { NS_OS_DESKTOP_DIR,           &nsDirectoryService::sOS_DesktopDirectory },
-    { NS_XPCOM_INIT_CURRENT_PROCESS_DIR, nsnull },
-#if defined (XP_MACOSX)
-    { NS_OS_SYSTEM_DIR,                   &nsDirectoryService::sDirectory },
-    { NS_MAC_TRASH_DIR,                   &nsDirectoryService::sTrashDirectory },
-    { NS_MAC_STARTUP_DIR,                 &nsDirectoryService::sStartupDirectory },
-    { NS_MAC_SHUTDOWN_DIR,                &nsDirectoryService::sShutdownDirectory },
-    { NS_MAC_APPLE_MENU_DIR,              &nsDirectoryService::sAppleMenuDirectory },
-    { NS_MAC_CONTROL_PANELS_DIR,          &nsDirectoryService::sControlPanelDirectory },
-    { NS_MAC_EXTENSIONS_DIR,              &nsDirectoryService::sExtensionDirectory },
-    { NS_MAC_FONTS_DIR,                   &nsDirectoryService::sFontsDirectory },
-    { NS_MAC_PREFS_DIR,                   &nsDirectoryService::sPreferencesDirectory },
-    { NS_MAC_DOCUMENTS_DIR,               &nsDirectoryService::sDocumentsDirectory },
-    { NS_MAC_INTERNET_SEARCH_DIR,         &nsDirectoryService::sInternetSearchDirectory },
-    { NS_MAC_USER_LIB_DIR,                &nsDirectoryService::sUserLibDirectory },
-    { NS_OSX_DEFAULT_DOWNLOAD_DIR,        &nsDirectoryService::sDefaultDownloadDirectory },
-    { NS_OSX_USER_DESKTOP_DIR,            &nsDirectoryService::sUserDesktopDirectory },
-    { NS_OSX_LOCAL_DESKTOP_DIR,           &nsDirectoryService::sLocalDesktopDirectory },
-    { NS_OSX_USER_APPLICATIONS_DIR,       &nsDirectoryService::sUserApplicationsDirectory },
-    { NS_OSX_LOCAL_APPLICATIONS_DIR,      &nsDirectoryService::sLocalApplicationsDirectory },
-    { NS_OSX_USER_DOCUMENTS_DIR,          &nsDirectoryService::sUserDocumentsDirectory },
-    { NS_OSX_LOCAL_DOCUMENTS_DIR,         &nsDirectoryService::sLocalDocumentsDirectory },
-    { NS_OSX_USER_INTERNET_PLUGIN_DIR,    &nsDirectoryService::sUserInternetPlugInDirectory },
-    { NS_OSX_LOCAL_INTERNET_PLUGIN_DIR,   &nsDirectoryService::sLocalInternetPlugInDirectory },
-    { NS_OSX_USER_FRAMEWORKS_DIR,         &nsDirectoryService::sUserFrameworksDirectory },
-    { NS_OSX_LOCAL_FRAMEWORKS_DIR,        &nsDirectoryService::sLocalFrameworksDirectory },
-    { NS_OSX_USER_PREFERENCES_DIR,        &nsDirectoryService::sUserPreferencesDirectory },
-    { NS_OSX_LOCAL_PREFERENCES_DIR,       &nsDirectoryService::sLocalPreferencesDirectory },
-    { NS_OSX_PICTURE_DOCUMENTS_DIR,       &nsDirectoryService::sPictureDocumentsDirectory },
-    { NS_OSX_MOVIE_DOCUMENTS_DIR,         &nsDirectoryService::sMovieDocumentsDirectory },
-    { NS_OSX_MUSIC_DOCUMENTS_DIR,         &nsDirectoryService::sMusicDocumentsDirectory },
-    { NS_OSX_INTERNET_SITES_DIR,          &nsDirectoryService::sInternetSitesDirectory },
-#elif defined (XP_WIN) 
-    { NS_OS_SYSTEM_DIR,            &nsDirectoryService::sSystemDirectory },
-    { NS_WIN_WINDOWS_DIR,          &nsDirectoryService::sWindowsDirectory },
-    { NS_WIN_PROGRAM_FILES_DIR,    &nsDirectoryService::sWindowsProgramFiles },
-    { NS_WIN_DESKTOP_DIR,          &nsDirectoryService::sDesktop },
-    { NS_WIN_PROGRAMS_DIR,         &nsDirectoryService::sPrograms },
-    { NS_WIN_CONTROLS_DIR,         &nsDirectoryService::sControls },
-    { NS_WIN_PRINTERS_DIR,         &nsDirectoryService::sPrinters },
-    { NS_WIN_PERSONAL_DIR,         &nsDirectoryService::sPersonal },
-    { NS_WIN_FAVORITES_DIR,        &nsDirectoryService::sFavorites },
-    { NS_WIN_STARTUP_DIR,          &nsDirectoryService::sStartup },
-    { NS_WIN_RECENT_DIR,           &nsDirectoryService::sRecent },
-    { NS_WIN_SEND_TO_DIR,          &nsDirectoryService::sSendto },
-    { NS_WIN_BITBUCKET_DIR,        &nsDirectoryService::sBitbucket },
-    { NS_WIN_STARTMENU_DIR,        &nsDirectoryService::sStartmenu },
-    { NS_WIN_DESKTOP_DIRECTORY,    &nsDirectoryService::sDesktopdirectory },
-    { NS_WIN_DRIVES_DIR,           &nsDirectoryService::sDrives },
-    { NS_WIN_NETWORK_DIR,          &nsDirectoryService::sNetwork },
-    { NS_WIN_NETHOOD_DIR,          &nsDirectoryService::sNethood },
-    { NS_WIN_FONTS_DIR,            &nsDirectoryService::sFonts },
-    { NS_WIN_TEMPLATES_DIR,        &nsDirectoryService::sTemplates },
-    { NS_WIN_COMMON_STARTMENU_DIR, &nsDirectoryService::sCommon_Startmenu },
-    { NS_WIN_COMMON_PROGRAMS_DIR,  &nsDirectoryService::sCommon_Programs },
-    { NS_WIN_COMMON_STARTUP_DIR,   &nsDirectoryService::sCommon_Startup },
-    { NS_WIN_COMMON_DESKTOP_DIRECTORY, &nsDirectoryService::sCommon_Desktopdirectory },
-    { NS_WIN_APPDATA_DIR,          &nsDirectoryService::sAppdata },
-    { NS_WIN_LOCAL_APPDATA_DIR,    &nsDirectoryService::sLocalAppdata },
-    { NS_WIN_PRINTHOOD,            &nsDirectoryService::sPrinthood },
-    { NS_WIN_COOKIES_DIR,          &nsDirectoryService::sWinCookiesDirectory },
-    { NS_WIN_DEFAULT_DOWNLOAD_DIR, &nsDirectoryService::sDefaultDownloadDirectory },
-#elif defined (XP_UNIX)
-    { NS_UNIX_LOCAL_DIR,           &nsDirectoryService::sLocalDirectory },
-    { NS_UNIX_LIB_DIR,             &nsDirectoryService::sLibDirectory },
-    { NS_UNIX_DEFAULT_DOWNLOAD_DIR, &nsDirectoryService::sDefaultDownloadDirectory },
-    { NS_UNIX_XDG_DESKTOP_DIR,     &nsDirectoryService::sXDGDesktop },
-    { NS_UNIX_XDG_DOCUMENTS_DIR,   &nsDirectoryService::sXDGDocuments },
-    { NS_UNIX_XDG_DOWNLOAD_DIR,    &nsDirectoryService::sXDGDownload },
-    { NS_UNIX_XDG_MUSIC_DIR,       &nsDirectoryService::sXDGMusic },
-    { NS_UNIX_XDG_PICTURES_DIR,    &nsDirectoryService::sXDGPictures },
-    { NS_UNIX_XDG_PUBLIC_SHARE_DIR, &nsDirectoryService::sXDGPublicShare },
-    { NS_UNIX_XDG_TEMPLATES_DIR,   &nsDirectoryService::sXDGTemplates },
-    { NS_UNIX_XDG_VIDEOS_DIR,      &nsDirectoryService::sXDGVideos },
-#elif defined (XP_OS2)
-    { NS_OS_SYSTEM_DIR,            &nsDirectoryService::sSystemDirectory },
-    { NS_OS2_DIR,                  &nsDirectoryService::sOS2Directory },
-#elif defined (XP_BEOS)
-    { NS_OS_SYSTEM_DIR,            &nsDirectoryService::sSystemDirectory },
-    { NS_BEOS_SETTINGS_DIR,        &nsDirectoryService::sSettingsDirectory },
-#endif
+#define DIR_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &nsDirectoryService::name_),
+#include "nsDirectoryServiceAtomList.h"
+#undef DIR_ATOM
 };    
 
 NS_IMETHODIMP
 nsDirectoryService::Init()
 {
     NS_NOTREACHED("nsDirectoryService::Init() for internal use only!");
     return NS_OK;
 }
--- a/xpcom/io/nsDirectoryService.h
+++ b/xpcom/io/nsDirectoryService.h
@@ -80,106 +80,18 @@ class nsDirectoryService : public nsIDir
 private:
     nsresult GetCurrentProcessDirectory(nsILocalFile** aFile);
     
     static PRBool ReleaseValues(nsHashKey* key, void* data, void* closure);
     nsSupportsHashtable mHashtable;
     nsCOMPtr<nsISupportsArray> mProviders;
 
 public:
-    static nsIAtom *sCurrentProcess;
-    static nsIAtom *sComponentRegistry;
-    static nsIAtom *sComponentDirectory;
-    static nsIAtom *sXPTIRegistry;
-    static nsIAtom *sGRE_Directory;
-    static nsIAtom *sGRE_ComponentDirectory;
-    static nsIAtom *sOS_DriveDirectory;
-    static nsIAtom *sOS_TemporaryDirectory;
-    static nsIAtom *sOS_CurrentProcessDirectory;
-    static nsIAtom *sOS_CurrentWorkingDirectory;
-    static nsIAtom *sOS_DesktopDirectory;
-    static nsIAtom *sOS_HomeDirectory;
-#if defined (XP_MACOSX)
-    static nsIAtom *sDirectory;
-    static nsIAtom *sTrashDirectory;
-    static nsIAtom *sStartupDirectory;
-    static nsIAtom *sShutdownDirectory;
-    static nsIAtom *sAppleMenuDirectory;
-    static nsIAtom *sControlPanelDirectory;
-    static nsIAtom *sExtensionDirectory;
-    static nsIAtom *sFontsDirectory;
-    static nsIAtom *sPreferencesDirectory;
-    static nsIAtom *sDocumentsDirectory;
-    static nsIAtom *sInternetSearchDirectory;
-    static nsIAtom *sUserLibDirectory;
-    static nsIAtom *sDefaultDownloadDirectory;
-    static nsIAtom *sUserDesktopDirectory;
-    static nsIAtom *sLocalDesktopDirectory;
-    static nsIAtom *sUserApplicationsDirectory;
-    static nsIAtom *sLocalApplicationsDirectory;
-    static nsIAtom *sUserDocumentsDirectory;
-    static nsIAtom *sLocalDocumentsDirectory;
-    static nsIAtom *sUserInternetPlugInDirectory;
-    static nsIAtom *sLocalInternetPlugInDirectory;
-    static nsIAtom *sUserFrameworksDirectory;
-    static nsIAtom *sLocalFrameworksDirectory;
-    static nsIAtom *sUserPreferencesDirectory;
-    static nsIAtom *sLocalPreferencesDirectory;
-    static nsIAtom *sPictureDocumentsDirectory;
-    static nsIAtom *sMovieDocumentsDirectory;
-    static nsIAtom *sMusicDocumentsDirectory;
-    static nsIAtom *sInternetSitesDirectory;
-#elif defined (XP_WIN) 
-    static nsIAtom *sSystemDirectory;
-    static nsIAtom *sWindowsDirectory;
-    static nsIAtom *sWindowsProgramFiles;
-    static nsIAtom *sDesktop;
-    static nsIAtom *sPrograms;
-    static nsIAtom *sControls;
-    static nsIAtom *sPrinters;
-    static nsIAtom *sPersonal;
-    static nsIAtom *sFavorites;
-    static nsIAtom *sStartup;
-    static nsIAtom *sRecent;
-    static nsIAtom *sSendto;
-    static nsIAtom *sBitbucket;
-    static nsIAtom *sStartmenu;
-    static nsIAtom *sDesktopdirectory;
-    static nsIAtom *sDrives;
-    static nsIAtom *sNetwork;
-    static nsIAtom *sNethood;
-    static nsIAtom *sFonts;
-    static nsIAtom *sTemplates;
-    static nsIAtom *sCommon_Startmenu;
-    static nsIAtom *sCommon_Programs;
-    static nsIAtom *sCommon_Startup;
-    static nsIAtom *sCommon_Desktopdirectory;
-    static nsIAtom *sAppdata;
-    static nsIAtom *sLocalAppdata;
-    static nsIAtom *sPrinthood;
-    static nsIAtom *sWinCookiesDirectory;
-    static nsIAtom *sDefaultDownloadDirectory;
-#elif defined (XP_UNIX)
-    static nsIAtom *sLocalDirectory;
-    static nsIAtom *sLibDirectory;
-    static nsIAtom *sXDGDesktop;
-    static nsIAtom *sXDGDocuments;
-    static nsIAtom *sXDGDownload;
-    static nsIAtom *sXDGMusic;
-    static nsIAtom *sXDGPictures;
-    static nsIAtom *sXDGPublicShare;
-    static nsIAtom *sXDGTemplates;
-    static nsIAtom *sXDGVideos;
-    static nsIAtom *sDefaultDownloadDirectory;
-#elif defined (XP_OS2)
-    static nsIAtom *sSystemDirectory;
-    static nsIAtom *sOS2Directory;
-#elif defined (XP_BEOS)
-    static nsIAtom *sSettingsDirectory;
-    static nsIAtom *sSystemDirectory;
-#endif
 
+#define DIR_ATOM(name_, value_) static nsIAtom* name_;
+#include "nsDirectoryServiceAtomList.h"
+#undef DIR_ATOM
 
 };
 
 
 #endif
 
new file mode 100644
--- /dev/null
+++ b/xpcom/io/nsDirectoryServiceAtomList.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   IBM Corp.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+DIR_ATOM(sCurrentProcess, NS_XPCOM_CURRENT_PROCESS_DIR)
+DIR_ATOM(sComponentRegistry, NS_XPCOM_COMPONENT_REGISTRY_FILE)
+DIR_ATOM(sComponentDirectory, NS_XPCOM_COMPONENT_DIR)
+DIR_ATOM(sXPTIRegistry, NS_XPCOM_XPTI_REGISTRY_FILE)
+DIR_ATOM(sGRE_Directory, NS_GRE_DIR)
+DIR_ATOM(sGRE_ComponentDirectory, NS_GRE_COMPONENT_DIR)
+DIR_ATOM(sOS_DriveDirectory, NS_OS_DRIVE_DIR)
+DIR_ATOM(sOS_TemporaryDirectory, NS_OS_TEMP_DIR)
+DIR_ATOM(sOS_CurrentProcessDirectory, NS_OS_CURRENT_PROCESS_DIR)
+DIR_ATOM(sOS_CurrentWorkingDirectory, NS_OS_CURRENT_WORKING_DIR)
+DIR_ATOM(sOS_HomeDirectory, NS_OS_HOME_DIR)
+DIR_ATOM(sOS_DesktopDirectory, NS_OS_DESKTOP_DIR)
+DIR_ATOM(sInitCurrentProcess_dummy, NS_XPCOM_INIT_CURRENT_PROCESS_DIR)
+#if defined (XP_MACOSX)
+DIR_ATOM(sDirectory, NS_OS_SYSTEM_DIR)
+DIR_ATOM(sTrashDirectory, NS_MAC_TRASH_DIR)
+DIR_ATOM(sStartupDirectory, NS_MAC_STARTUP_DIR)
+DIR_ATOM(sShutdownDirectory, NS_MAC_SHUTDOWN_DIR)
+DIR_ATOM(sAppleMenuDirectory, NS_MAC_APPLE_MENU_DIR)
+DIR_ATOM(sControlPanelDirectory, NS_MAC_CONTROL_PANELS_DIR)
+DIR_ATOM(sExtensionDirectory, NS_MAC_EXTENSIONS_DIR)
+DIR_ATOM(sFontsDirectory, NS_MAC_FONTS_DIR)
+DIR_ATOM(sPreferencesDirectory, NS_MAC_PREFS_DIR)
+DIR_ATOM(sDocumentsDirectory, NS_MAC_DOCUMENTS_DIR)
+DIR_ATOM(sInternetSearchDirectory, NS_MAC_INTERNET_SEARCH_DIR)
+DIR_ATOM(sUserLibDirectory, NS_MAC_USER_LIB_DIR)
+DIR_ATOM(sDefaultDownloadDirectory, NS_OSX_DEFAULT_DOWNLOAD_DIR)
+DIR_ATOM(sUserDesktopDirectory, NS_OSX_USER_DESKTOP_DIR)
+DIR_ATOM(sLocalDesktopDirectory, NS_OSX_LOCAL_DESKTOP_DIR)
+DIR_ATOM(sUserApplicationsDirectory, NS_OSX_USER_APPLICATIONS_DIR)
+DIR_ATOM(sLocalApplicationsDirectory, NS_OSX_LOCAL_APPLICATIONS_DIR)
+DIR_ATOM(sUserDocumentsDirectory, NS_OSX_USER_DOCUMENTS_DIR)
+DIR_ATOM(sLocalDocumentsDirectory, NS_OSX_LOCAL_DOCUMENTS_DIR)
+DIR_ATOM(sUserInternetPlugInDirectory, NS_OSX_USER_INTERNET_PLUGIN_DIR)
+DIR_ATOM(sLocalInternetPlugInDirectory, NS_OSX_LOCAL_INTERNET_PLUGIN_DIR)
+DIR_ATOM(sUserFrameworksDirectory, NS_OSX_USER_FRAMEWORKS_DIR)
+DIR_ATOM(sLocalFrameworksDirectory, NS_OSX_LOCAL_FRAMEWORKS_DIR)
+DIR_ATOM(sUserPreferencesDirectory, NS_OSX_USER_PREFERENCES_DIR)
+DIR_ATOM(sLocalPreferencesDirectory, NS_OSX_LOCAL_PREFERENCES_DIR)
+DIR_ATOM(sPictureDocumentsDirectory, NS_OSX_PICTURE_DOCUMENTS_DIR)
+DIR_ATOM(sMovieDocumentsDirectory, NS_OSX_MOVIE_DOCUMENTS_DIR)
+DIR_ATOM(sMusicDocumentsDirectory, NS_OSX_MUSIC_DOCUMENTS_DIR)
+DIR_ATOM(sInternetSitesDirectory, NS_OSX_INTERNET_SITES_DIR)
+#elif defined (XP_WIN) 
+DIR_ATOM(sSystemDirectory, NS_OS_SYSTEM_DIR)
+DIR_ATOM(sWindowsDirectory, NS_WIN_WINDOWS_DIR)
+DIR_ATOM(sWindowsProgramFiles, NS_WIN_PROGRAM_FILES_DIR)
+DIR_ATOM(sDesktop, NS_WIN_DESKTOP_DIR)
+DIR_ATOM(sPrograms, NS_WIN_PROGRAMS_DIR)
+DIR_ATOM(sControls, NS_WIN_CONTROLS_DIR)
+DIR_ATOM(sPrinters, NS_WIN_PRINTERS_DIR)
+DIR_ATOM(sPersonal, NS_WIN_PERSONAL_DIR)
+DIR_ATOM(sFavorites, NS_WIN_FAVORITES_DIR)
+DIR_ATOM(sStartup, NS_WIN_STARTUP_DIR)
+DIR_ATOM(sRecent, NS_WIN_RECENT_DIR)
+DIR_ATOM(sSendto, NS_WIN_SEND_TO_DIR)
+DIR_ATOM(sBitbucket, NS_WIN_BITBUCKET_DIR)
+DIR_ATOM(sStartmenu, NS_WIN_STARTMENU_DIR)
+DIR_ATOM(sDesktopdirectory, NS_WIN_DESKTOP_DIRECTORY)
+DIR_ATOM(sDrives, NS_WIN_DRIVES_DIR)
+DIR_ATOM(sNetwork, NS_WIN_NETWORK_DIR)
+DIR_ATOM(sNethood, NS_WIN_NETHOOD_DIR)
+DIR_ATOM(sFonts, NS_WIN_FONTS_DIR)
+DIR_ATOM(sTemplates, NS_WIN_TEMPLATES_DIR)
+DIR_ATOM(sCommon_Startmenu, NS_WIN_COMMON_STARTMENU_DIR)
+DIR_ATOM(sCommon_Programs, NS_WIN_COMMON_PROGRAMS_DIR)
+DIR_ATOM(sCommon_Startup, NS_WIN_COMMON_STARTUP_DIR)
+DIR_ATOM(sCommon_Desktopdirectory, NS_WIN_COMMON_DESKTOP_DIRECTORY)
+DIR_ATOM(sAppdata, NS_WIN_APPDATA_DIR)
+DIR_ATOM(sLocalAppdata, NS_WIN_LOCAL_APPDATA_DIR)
+DIR_ATOM(sPrinthood, NS_WIN_PRINTHOOD)
+DIR_ATOM(sWinCookiesDirectory, NS_WIN_COOKIES_DIR)
+DIR_ATOM(sDefaultDownloadDirectory, NS_WIN_DEFAULT_DOWNLOAD_DIR)
+#elif defined (XP_UNIX)
+DIR_ATOM(sLocalDirectory, NS_UNIX_LOCAL_DIR)
+DIR_ATOM(sLibDirectory, NS_UNIX_LIB_DIR)
+DIR_ATOM(sDefaultDownloadDirectory, NS_UNIX_DEFAULT_DOWNLOAD_DIR)
+DIR_ATOM(sXDGDesktop, NS_UNIX_XDG_DESKTOP_DIR)
+DIR_ATOM(sXDGDocuments, NS_UNIX_XDG_DOCUMENTS_DIR)
+DIR_ATOM(sXDGDownload, NS_UNIX_XDG_DOWNLOAD_DIR)
+DIR_ATOM(sXDGMusic, NS_UNIX_XDG_MUSIC_DIR)
+DIR_ATOM(sXDGPictures, NS_UNIX_XDG_PICTURES_DIR)
+DIR_ATOM(sXDGPublicShare, NS_UNIX_XDG_PUBLIC_SHARE_DIR)
+DIR_ATOM(sXDGTemplates, NS_UNIX_XDG_TEMPLATES_DIR)
+DIR_ATOM(sXDGVideos, NS_UNIX_XDG_VIDEOS_DIR)
+#elif defined (XP_OS2)
+DIR_ATOM(sSystemDirectory, NS_OS_SYSTEM_DIR)
+DIR_ATOM(sOS2Directory, NS_OS2_DIR)
+#elif defined (XP_BEOS)
+DIR_ATOM(sSystemDirectory, NS_OS_SYSTEM_DIR)
+DIR_ATOM(sSettingsDirectory, NS_BEOS_SETTINGS_DIR)
+#endif
--- a/xpcom/string/public/nsStringBuffer.h
+++ b/xpcom/string/public/nsStringBuffer.h
@@ -34,28 +34,30 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsStringBuffer_h__
 #define nsStringBuffer_h__
 
+
 /**
  * This structure precedes the string buffers "we" allocate.  It may be the
  * case that nsTAString::mData does not point to one of these special
  * buffers.  The mFlags member variable distinguishes the buffer type.
  *
  * When this header is in use, it enables reference counting, and capacity
  * tracking.  NOTE: A string buffer can be modified only if its reference
  * count is 1.
  */
 class nsStringBuffer
   {
     private:
+      friend class CheckStaticAtomSizes;
 
       PRInt32  mRefCount;
       PRUint32 mStorageSize;
 
     public:
       
       /**
        * Allocates a new string buffer, with given size in bytes and a
--- a/xpcom/string/src/nsSubstring.cpp
+++ b/xpcom/string/src/nsSubstring.cpp
@@ -47,16 +47,17 @@
 #include <stdlib.h>
 #include "nsSubstring.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsDependentString.h"
 #include "nsMemory.h"
 #include "pratom.h"
 #include "prprf.h"
+#include "nsStaticAtom.h"
 
 // ---------------------------------------------------------------------------
 
 static PRUnichar gNullChar = 0;
 
 char*      nsCharTraits<char>     ::sEmptyBuffer = (char*) &gNullChar;
 PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer =         &gNullChar;
 
--- a/xpcom/tests/Makefile.in
+++ b/xpcom/tests/Makefile.in
@@ -67,23 +67,16 @@ CPPSRCS		= \
 		TestThreadPoolListener.cpp \
 		TestTimers.cpp \
 		TestOOM.cpp \
 		TestBlockingProcess.cpp \
 		TestQuickReturn.cpp \
 		TestArguments.cpp \
 		$(NULL)
 
-ifndef MOZ_ENABLE_LIBXUL
-CPPSRCS += \
-		TestAtoms.cpp \
-		TestPermanentAtoms.cpp \
-		$(NULL)
-endif
-
 SIMPLE_PROGRAMS	:= $(CPPSRCS:.cpp=$(BIN_SUFFIX))
 
 CPP_UNIT_TESTS = \
                  ShowSSEConfig.cpp \
                  TestAutoPtr.cpp \
                  TestCOMPtr.cpp \
                  TestCOMPtrEq.cpp \
                  TestFactory.cpp \
--- a/xpcom/tests/MoreTestingAtoms.cpp
+++ b/xpcom/tests/MoreTestingAtoms.cpp
@@ -41,17 +41,17 @@
 
 // define storage for all atoms
 #define MORE_TESTING_ATOM(_name, _value) nsIAtom* MoreTestingAtoms::_name;
 #include "MoreTestingAtomList.h"
 #undef MORE_TESTING_ATOM
 
 static const nsStaticAtom MoreTestingAtoms_info[] = {
 
-#define MORE_TESTING_ATOM(name_, value_) { value_, &MoreTestingAtoms::name_ },
+#define MORE_TESTING_ATOM(name_, value_) NS_STATIC_ATOM(value_, &MoreTestingAtoms::name_),
 #include "MoreTestingAtomList.h"
 #undef MORE_TESTING_ATOM
 };
 
 void MoreTestingAtoms::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(MoreTestingAtoms_info, 
                          NS_ARRAY_LENGTH(MoreTestingAtoms_info));
--- a/xpcom/tests/TestingAtoms.cpp
+++ b/xpcom/tests/TestingAtoms.cpp
@@ -39,19 +39,22 @@
 #include "nsStaticAtom.h"
 #include "nsMemory.h"
 
 // define storage for all atoms
 #define TESTING_ATOM(_name, _value) nsIAtom* TestingAtoms::_name;
 #include "TestingAtomList.h"
 #undef TESTING_ATOM
 
-static const nsStaticAtom TestingAtoms_info[] = {
+#define TESTING_ATOM(name_, value_) NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
+#include "TestingAtomList.h"
+#undef TESTING_ATOM
 
-#define TESTING_ATOM(name_, value_) { value_, &TestingAtoms::name_ },
+static const nsStaticAtom TestingAtoms_info[] = {
+#define TESTING_ATOM(name_, value_) NS_STATIC_ATOM(name_##_buffer, &TestingAtoms::name_),
 #include "TestingAtomList.h"
 #undef TESTING_ATOM
 };
 
 void TestingAtoms::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(TestingAtoms_info, NS_ARRAY_LENGTH(TestingAtoms_info));
 }