Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 23 Jul 2013 20:53:32 -0400
changeset 152058 ff08148799106414402b71ea87c13c274b2a9489
parent 152057 a47c4711bcd9faa81fc06818cf25fd49f5064c53 (current diff)
parent 151931 2983ca6d4d1aa0b425db2bfbd49e9efe338685da (diff)
child 152059 b661851684160176cf4cf701f45ca6b8fb47922d
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team.
js/src/jit-test/tests/collections/Array-iterator-surfaces.js
xpcom/base/nsAtomicRefcnt.h
--- a/accessible/src/base/DocManager.cpp
+++ b/accessible/src/base/DocManager.cpp
@@ -112,20 +112,20 @@ DocManager::Shutdown()
     progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
 
   ClearDocCache();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(DocManager,
-                              nsIWebProgressListener,
-                              nsIDOMEventListener,
-                              nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS3(DocManager,
+                   nsIWebProgressListener,
+                   nsIDOMEventListener,
+                   nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIWebProgressListener
 
 NS_IMETHODIMP
 DocManager::OnStateChange(nsIWebProgress* aWebProgress,
                           nsIRequest* aRequest, uint32_t aStateFlags,
                           nsresult aStatus)
--- a/accessible/src/base/DocManager.h
+++ b/accessible/src/base/DocManager.h
@@ -24,17 +24,17 @@ class DocAccessible;
  */
 class DocManager : public nsIWebProgressListener,
                    public nsIDOMEventListener,
                    public nsSupportsWeakReference
 {
 public:
   virtual ~DocManager() { }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIWEBPROGRESSLISTENER
   NS_DECL_NSIDOMEVENTLISTENER
 
   /**
    * Return document accessible for the given DOM node.
    */
   DocAccessible* GetDocAccessible(nsIDocument* aDocument);
 
--- a/accessible/src/base/nsTextEquivUtils.cpp
+++ b/accessible/src/base/nsTextEquivUtils.cpp
@@ -50,29 +50,16 @@ nsTextEquivUtils::GetNameFromSubtree(Acc
     }
   }
 
   sInitiatorAcc = nullptr;
 
   return NS_OK;
 }
 
-void
-nsTextEquivUtils::GetTextEquivFromSubtree(Accessible* aAccessible,
-                                          nsString& aTextEquiv)
-{
-  aTextEquiv.Truncate();
-
-  uint32_t nameRule = GetRoleRule(aAccessible->Role());
-  if (nameRule & eNameFromSubtreeIfReqRule) {
-    AppendFromAccessibleChildren(aAccessible, &aTextEquiv);
-    aTextEquiv.CompressWhitespace();
-  }
-}
-
 nsresult
 nsTextEquivUtils::GetTextEquivFromIDRefs(Accessible* aAccessible,
                                          nsIAtom *aIDRefsAttr,
                                          nsAString& aTextEquiv)
 {
   aTextEquiv.Truncate();
 
   nsIContent* content = aAccessible->GetContent();
--- a/accessible/src/base/nsTextEquivUtils.h
+++ b/accessible/src/base/nsTextEquivUtils.h
@@ -50,21 +50,26 @@ public:
    * @param aAccessible [in] the given accessible
    * @param aName       [out] accessible name
    */
   static nsresult GetNameFromSubtree(Accessible* aAccessible,
                                      nsAString& aName);
 
   /**
    * Calculates text equivalent from the subtree. Similar to GetNameFromSubtree.
-   * The difference it returns not empty result for things like HTML p, i.e.
-   * if the role has eNameFromSubtreeIfReq rule.
+   * However it returns not empty result for things like HTML p.
    */
   static void GetTextEquivFromSubtree(Accessible* aAccessible,
-                                      nsString& aTextEquiv);
+                                      nsString& aTextEquiv)
+  {
+    aTextEquiv.Truncate();
+
+    AppendFromAccessibleChildren(aAccessible, &aTextEquiv);
+    aTextEquiv.CompressWhitespace();
+  }
 
   /**
    * Calculates text equivalent for the given accessible from its IDRefs
    * attribute (like aria-labelledby or aria-describedby).
    *
    * @param aAccessible  [in] the accessible text equivalent is computed for
    * @param aIDRefsAttr  [in] IDRefs attribute on DOM node of the accessible
    * @param aTextEquiv   [out] result text equivalent
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -1676,16 +1676,22 @@ Accessible::Value(nsString& aValue)
     if (!mContent->GetAttr(kNameSpaceID_None,
                            nsGkAtoms::aria_valuetext, aValue)) {
       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
                         aValue);
     }
     return;
   }
 
+  // Value of textbox is a textified subtree.
+  if (mRoleMapEntry->Is(nsGkAtoms::textbox)) {
+    nsTextEquivUtils::GetTextEquivFromSubtree(this, aValue);
+    return;
+  }
+
   // Value of combobox is a text of current or selected item.
   if (mRoleMapEntry->Is(nsGkAtoms::combobox)) {
     Accessible* option = CurrentItem();
     if (!option) {
       Accessible* listbox = nullptr;
       IDRefsIterator iter(mDoc, mContent, nsGkAtoms::aria_owns);
       while ((listbox = iter.Next()) && !listbox->IsListControl());
 
--- a/accessible/tests/mochitest/value/test_general.html
+++ b/accessible/tests/mochitest/value/test_general.html
@@ -46,16 +46,21 @@
       testValue("aria_application_link", "");
 
       // roles that can live as HTMLLinkAccessibles
       testValue("aria_link_link", href);
       testValue("aria_main_link", href);
       testValue("aria_navigation_link", href);
 
       //////////////////////////////////////////////////////////////////////////
+      // ARIA textboxes
+
+      testValue("aria_textbox1", "helo");
+
+      //////////////////////////////////////////////////////////////////////////
       // ARIA comboboxes
 
       // aria-activedescendant defines a current item the value is computed from
       testValue("aria_combobox1", kDiscBulletText + "Zoom");
 
       // aria-selected defines a selected item the value is computed from,
       // list control is pointed by aria-owns relation.
       testValue("aria_combobox2", kDiscBulletText + "Zoom");
@@ -78,22 +83,27 @@
 
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=494807"
      title="Do not expose a11y info specific to hyperlinks when role is overridden using ARIA">
-    Mozilla Bug 494807
+    Bug 494807
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=819273"
-     title=" ARIA combobox should have accessible value">
-    Mozilla Bug 819273
+     title="ARIA combobox should have accessible value">
+    Bug 819273
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=887250"
+     title="ARIA textbox role doesn't expose value">
+    Bug 887250
   </a>
   <p id="display"></p>
   <div id="content" style="display: none">
   </div>
   <pre id="test">
   </pre>
 
   <a id="aria_menuitem_link" role="menuitem" href="foo">menuitem</a>
@@ -103,16 +113,18 @@
   <!-- landmark links -->
   <a id="aria_application_link" role="application" href="foo">app</a>
   <a id="aria_main_link" role="main" href="foo">main</a>
   <a id="aria_navigation_link" role="navigation" href="foo">nav</a>
 
   <!-- strange edge case: please don't do this in the wild -->
   <a id="aria_link_link" role="link" href="foo">link</a>
 
+  <div id="aria_textbox1" role="textbox">helo</div>
+
   <div id="aria_combobox1" role="combobox"
        aria-owns="aria_combobox1_owned_listbox"
        aria-activedescendant="aria_combobox1_selected_option">
   </div>
   <ul role="listbox" id="aria_combobox1_owned_listbox">
     <li role="option">Zebra</li>
     <li role="option" id="aria_combobox1_selected_option">Zoom</li>
   </ul>
@@ -137,10 +149,11 @@
   <select id="combobox1">
     <option id="cb1_item1">item1</option>
     <option id="cb1_item2">item2</option>
   </select>
   <select id="combobox2">
     <option id="cb2_item1">item1</option>
     <option id="cb2_item2" selected="true">item2</option>
   </select>
+
 </body>
 </html>
--- a/browser/base/content/baseMenuOverlay.xul
+++ b/browser/base/content/baseMenuOverlay.xul
@@ -47,16 +47,21 @@
                   onclick="checkForMiddleClick(this, event);"
                   label="&productHelp.label;"
                   accesskey="&productHelp.accesskey;"
 #ifdef XP_MACOSX
                   key="key_openHelpMac"/>
 #else
                   />
 #endif
+        <menuitem id="menu_keyboardShortcuts"
+                  oncommand="openHelpLink('keyboard-shortcuts')"
+                  onclick="checkForMiddleClick(this, event);"
+                  label="&helpKeyboardShortcuts.label;"
+                  accesskey="&helpKeyboardShortcuts.accesskey;"/>
 #ifdef MOZ_SERVICES_HEALTHREPORT
         <menuitem id="healthReport"
                   label="&healthReport.label;"
                   accesskey="&healthReport.accesskey;"
                   oncommand="openHealthReport()"
                   onclick="checkForMiddleClick(this, event);"/>
 #endif
         <menuitem id="troubleShooting"
--- a/browser/base/content/browser-appmenu.inc
+++ b/browser/base/content/browser-appmenu.inc
@@ -366,16 +366,20 @@
             <menuitem id="appmenu_openHelp"
                       label="&helpMenu.label;"
                       oncommand="openHelpLink('firefox-help')"
                       onclick="checkForMiddleClick(this, event);"/>
             <menuitem id="appmenu_gettingStarted"
                       label="&appMenuGettingStarted.label;"
                       oncommand="gBrowser.loadOneTab('https://www.mozilla.org/firefox/central/', {inBackground: false});"
                       onclick="checkForMiddleClick(this, event);"/>
+            <menuitem id="appmenu_keyboardShortcuts"
+                      label="&helpKeyboardShortcuts.label;"
+                      oncommand="openHelpLink('keyboard-shortcuts')"
+                      onclick="checkForMiddleClick(this, event);"/>
 #ifdef MOZ_SERVICES_HEALTHREPORT
             <menuitem id="appmenu_healthReport"
                       label="&healthReport.label;"
                       oncommand="openHealthReport()"
                       onclick="checkForMiddleClick(this, event);"/>
 #endif
             <menuitem id="appmenu_troubleshootingInfo"
                       label="&helpTroubleshootingInfo.label;"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -483,24 +483,16 @@
             <menu id="tools-menu"
                   label="&toolsMenu.label;"
                   accesskey="&toolsMenu.accesskey;">
               <menupopup id="menu_ToolsPopup"
 #ifdef MOZ_SERVICES_SYNC
                          onpopupshowing="gSyncUI.updateUI();"
 #endif
                          >
-              <menuitem id="menu_search"
-                        class="show-only-for-keyboard"
-                        label="&search.label;"
-                        accesskey="&search.accesskey;"
-                        key="key_search"
-                        command="Tools:Search"/>
-              <menuseparator id="browserToolsSeparator"
-                             class="show-only-for-keyboard"/>
               <menuitem id="menu_openDownloads"
                         label="&downloads.label;"
                         accesskey="&downloads.accesskey;"
                         key="key_openDownloads"
                         command="Tools:Downloads"/>
               <menuitem id="menu_openAddons"
                         label="&addons.label;"
                         accesskey="&addons.accesskey;"
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -13,17 +13,18 @@ XPCOMUtils.defineLazyGetter(this, "BROWS
   const PREF = "browser.newtab.url";
 
   function getNewTabPageURL() {
     if (!Services.prefs.prefHasUserValue(PREF)) {
       if (PrivateBrowsingUtils.isWindowPrivate(window) &&
           !PrivateBrowsingUtils.permanentPrivateBrowsing)
         return "about:privatebrowsing";
     }
-    return Services.prefs.getCharPref(PREF) || "about:blank";
+    let url = Services.prefs.getComplexValue(PREF, Ci.nsISupportsString).data;
+    return url || "about:blank";
   }
 
   function update() {
     BROWSER_NEW_TAB_URL = getNewTabPageURL();
   }
 
   Services.prefs.addObserver(PREF, update, false);
 
--- a/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
+++ b/browser/locales/en-US/chrome/browser/baseMenuOverlay.dtd
@@ -14,16 +14,20 @@
                        for the help button in the menubar but Gnome does not.   -->
 <!ENTITY helpMenuWin.label        "Help"> 
 <!ENTITY helpMenuWin.accesskey    "H">
 <!ENTITY aboutProduct.label       "About &brandShortName;">
 <!ENTITY aboutProduct.accesskey   "A">
 <!ENTITY productHelp.label        "&brandShortName; Help">
 <!ENTITY productHelp.accesskey    "H">
 <!ENTITY helpMac.commandkey       "?">
+
+<!ENTITY helpKeyboardShortcuts.label     "Keyboard Shortcuts">
+<!ENTITY helpKeyboardShortcuts.accesskey "K">
+
 <!ENTITY helpSafeMode.label       "Restart with Add-ons Disabled…">
 <!ENTITY helpSafeMode.accesskey   "R">
 
 <!ENTITY healthReport.label       "&brandShortName; Health Report">
 <!ENTITY healthReport.accesskey   "e">
 
 <!ENTITY helpTroubleshootingInfo.label      "Troubleshooting Information">
 <!ENTITY helpTroubleshootingInfo.accesskey  "T">
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -189,18 +189,17 @@ These should match what Safari and other
 <!ENTITY historyButton.label            "History">
 <!ENTITY historySidebarCmd.commandKey   "h">
 
 <!ENTITY toolsMenu.label              "Tools">
 <!ENTITY toolsMenu.accesskey          "T"> 
 
 <!ENTITY keywordfield.label           "Add a Keyword for this Search…">
 <!ENTITY keywordfield.accesskey       "K">
-<!ENTITY search.label                 "Web Search">
-<!ENTITY search.accesskey             "S">
+
 <!ENTITY downloads.label              "Downloads">
 <!ENTITY downloads.tooltip            "Display the progress of ongoing downloads">
 <!ENTITY downloads.accesskey          "D">
 <!ENTITY downloads.commandkey         "j">
 <!ENTITY downloadsUnix.commandkey     "y">
 <!ENTITY addons.label                 "Add-ons">
 <!ENTITY addons.accesskey             "A">
 <!ENTITY addons.commandkey            "A">
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -17,16 +17,17 @@
 #include "nsIUUIDGenerator.h"
 #include "nsID.h"
 #include "nsNetUtil.h"
 #include "nsIClassInfoImpl.h"
 #include "nsNetCID.h"
 #include "nsError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsScriptSecurityManager.h"
+#include "pratom.h"
 
 using namespace mozilla;
 
 NS_IMPL_CLASSINFO(nsNullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_NULLPRINCIPAL_CID)
 NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
--- a/caps/src/nsNullPrincipalURI.cpp
+++ b/caps/src/nsNullPrincipalURI.cpp
@@ -28,18 +28,18 @@ nsNullPrincipalURI::nsNullPrincipalURI(c
   NS_ASSERTION(n == count, "Storing the path failed!");
 
   ToLowerCase(mScheme);
 }
 
 static NS_DEFINE_CID(kNullPrincipalURIImplementationCID,
                      NS_NULLPRINCIPALURI_IMPLEMENTATION_CID);
 
-NS_IMPL_THREADSAFE_ADDREF(nsNullPrincipalURI)
-NS_IMPL_THREADSAFE_RELEASE(nsNullPrincipalURI)
+NS_IMPL_ADDREF(nsNullPrincipalURI)
+NS_IMPL_RELEASE(nsNullPrincipalURI)
 
 NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI)
   if (aIID.Equals(kNullPrincipalURIImplementationCID))
     foundInterface = static_cast<nsIURI *>(this);
   else
   NS_INTERFACE_MAP_ENTRY(nsIURI)
   NS_INTERFACE_MAP_ENTRY(nsISizeOf)
--- a/caps/src/nsNullPrincipalURI.h
+++ b/caps/src/nsNullPrincipalURI.h
@@ -22,17 +22,17 @@
 #define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \
   {0x51fcd543, 0x3b52, 0x41f7, \
     {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
 
 class nsNullPrincipalURI MOZ_FINAL : public nsIURI
                                    , public nsISizeOf
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
 
   // nsISizeOf
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   nsNullPrincipalURI(const nsCString &aSpec);
 
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozIThirdPartyUtil.h"
 #include "nscore.h"
 #include "nsScriptSecurityManager.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "plstr.h"
+#include "pratom.h"
 #include "nsCRT.h"
 #include "nsIURI.h"
 #include "nsIFileURL.h"
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "nsJSPrincipals.h"
 #include "nsVoidArray.h"
 #include "nsIObjectInputStream.h"
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -12,16 +12,17 @@
 #include "nsIURL.h"
 #include "nsCOMPtr.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIScriptSecurityManager.h"
+#include "pratom.h"
 
 NS_IMPL_CLASSINFO(nsSystemPrincipal, nullptr,
                   nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_SYSTEMPRINCIPAL_CID)
 NS_IMPL_QUERY_INTERFACE2_CI(nsSystemPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER2(nsSystemPrincipal,
--- a/chrome/src/nsChromeProtocolHandler.cpp
+++ b/chrome/src/nsChromeProtocolHandler.cpp
@@ -34,19 +34,19 @@
 #include "nsIStreamListener.h"
 #include "nsNetUtil.h"
 #include "nsXPIDLString.h"
 #include "nsString.h"
 #include "prlog.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsChromeProtocolHandler,
-                              nsIProtocolHandler,
-                              nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS2(nsChromeProtocolHandler,
+                   nsIProtocolHandler,
+                   nsISupportsWeakReference)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIProtocolHandler methods:
 
 NS_IMETHODIMP
 nsChromeProtocolHandler::GetScheme(nsACString &result)
 {
     result.AssignLiteral("chrome");
--- a/chrome/src/nsChromeProtocolHandler.h
+++ b/chrome/src/nsChromeProtocolHandler.h
@@ -17,17 +17,17 @@
     0x11d3,                                          \
     {0x8c, 0xd0, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \
 }
 
 class nsChromeProtocolHandler MOZ_FINAL : public nsIProtocolHandler,
                                           public nsSupportsWeakReference
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
 
     // nsIProtocolHandler methods:
     NS_DECL_NSIPROTOCOLHANDLER
 
     // nsChromeProtocolHandler methods:
     nsChromeProtocolHandler() {}
     ~nsChromeProtocolHandler() {}
 };
--- a/config/config.mk
+++ b/config/config.mk
@@ -235,16 +235,19 @@ endif
 
 ifdef LIBXUL_LIBRARY
 ifdef IS_COMPONENT
 $(error IS_COMPONENT is set, but is not compatible with LIBXUL_LIBRARY)
 endif
 ifdef MODULE_NAME
 $(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
 endif
+ifdef FORCE_STATIC_LIB
+$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
+endif
 FORCE_STATIC_LIB=1
 ifneq ($(SHORT_LIBNAME),)
 $(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY)
 endif
 endif
 
 # If we are building this component into an extension/xulapp, it cannot be
 # statically linked. In the future we may want to add a xulapp meta-component
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -33,17 +33,16 @@
 #include "nsContentUtils.h"
 #include "nsIScrollableFrame.h"
 #include "mozilla/dom/Attr.h"
 #include "nsISMILAttr.h"
 #include "nsClientRect.h"
 #include "nsEvent.h"
 #include "nsAttrValue.h"
 #include "mozilla/dom/BindingDeclarations.h"
-#include "nsIHTMLCollection.h"
 #include "Units.h"
 
 class nsIDOMEventListener;
 class nsIFrame;
 class nsIDOMMozNamedAttrMap;
 class nsIDOMCSSStyleDeclaration;
 class nsIURI;
 class nsINodeInfo;
@@ -595,46 +594,16 @@ public:
   already_AddRefed<nsIHTMLCollection>
     GetElementsByTagName(const nsAString& aQualifiedName);
   already_AddRefed<nsIHTMLCollection>
     GetElementsByTagNameNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName,
                            ErrorResult& aError);
   already_AddRefed<nsIHTMLCollection>
     GetElementsByClassName(const nsAString& aClassNames);
-  Element* GetFirstElementChild() const;
-  Element* GetLastElementChild() const;
-  Element* GetPreviousElementSibling() const
-  {
-    nsIContent* previousSibling = GetPreviousSibling();
-    while (previousSibling) {
-      if (previousSibling->IsElement()) {
-        return previousSibling->AsElement();
-      }
-      previousSibling = previousSibling->GetPreviousSibling();
-    }
-
-    return nullptr;
-  }
-  Element* GetNextElementSibling() const
-  {
-    nsIContent* nextSibling = GetNextSibling();
-    while (nextSibling) {
-      if (nextSibling->IsElement()) {
-        return nextSibling->AsElement();
-      }
-      nextSibling = nextSibling->GetNextSibling();
-    }
-
-    return nullptr;
-  }
-  uint32_t ChildElementCount()
-  {
-    return Children()->Length();
-  }
   bool MozMatchesSelector(const nsAString& aSelector,
                           ErrorResult& aError);
   void SetCapture(bool aRetargetToElement)
   {
     // If there is already an active capture, ignore this request. This would
     // occur if a splitter, frame resizer, etc had already captured and we don't
     // want to override those.
     if (!nsIPresShell::GetCapturingContent()) {
--- a/content/base/public/FragmentOrElement.h
+++ b/content/base/public/FragmentOrElement.h
@@ -18,26 +18,26 @@
 #include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
 #include "nsIContent.h"                   // base class
 #include "nsIDOMTouchEvent.h"             // base class (nsITouchEventReceiver)
 #include "nsIDOMXPathNSResolver.h"        // base class
 #include "nsIInlineEventHandlers.h"       // base class
 #include "nsINodeList.h"                  // base class
 #include "nsIWeakReference.h"             // base class
 #include "nsNodeUtils.h"                  // class member nsNodeUtils::CloneNodeImpl
+#include "nsIHTMLCollection.h"
 
 class ContentUnbinder;
 class nsContentList;
 class nsDOMAttributeMap;
 class nsDOMTokenList;
 class nsIControllers;
 class nsICSSDeclaration;
 class nsIDocument;
 class nsDOMStringMap;
-class nsIHTMLCollection;
 class nsINodeInfo;
 class nsIURI;
 
 /**
  * Class that implements the nsIDOMNodeList interface (a list of children of
  * the content), by holding a reference to the content and delegating GetLength
  * and Item to its existing child list.
  * @see nsIDOMNodeList
@@ -224,16 +224,20 @@ public:
 
   virtual void DestroyContent() MOZ_OVERRIDE;
   virtual void SaveSubtreeState() MOZ_OVERRIDE;
 
   virtual const nsAttrValue* DoGetClasses() const MOZ_OVERRIDE;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) MOZ_OVERRIDE;
 
   nsIHTMLCollection* Children();
+  uint32_t ChildElementCount()
+  {
+    return Children()->Length();
+  }
 
 public:
   /**
    * If there are listeners for DOMNodeInserted event, fires the event on all
    * aNodes
    */
   static void FireNodeInserted(nsIDocument* aDoc,
                                nsINode* aParent,
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -175,17 +175,17 @@ public:
   nsDOMFile(const nsAString& aContentType, uint64_t aLength)
   : nsDOMFileBase(aContentType, aLength)
   { }
 
   nsDOMFile(const nsAString& aContentType, uint64_t aStart, uint64_t aLength)
   : nsDOMFileBase(aContentType, aStart, aLength)
   { }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 };
 
 class nsDOMFileCC : public nsDOMFileBase
 {
 public:
   nsDOMFileCC(const nsAString& aName, const nsAString& aContentType,
               uint64_t aLength)
   : nsDOMFileBase(aName, aContentType, aLength)
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -48,16 +48,17 @@ class nsIDocShell;
 class nsIDocumentObserver;
 class nsIDOMDocument;
 class nsIDOMDocumentFragment;
 class nsIDOMDocumentType;
 class nsIDOMElement;
 class nsIDOMNodeList;
 class nsIDOMXPathExpression;
 class nsIDOMXPathNSResolver;
+class nsIHTMLCollection;
 class nsILayoutHistoryState;
 class nsIObjectLoadingContent;
 class nsIObserver;
 class nsIPresShell;
 class nsIPrincipal;
 class nsIRequest;
 class nsIStreamListener;
 class nsIStyleRule;
@@ -2115,16 +2116,20 @@ public:
   {
     return mStyleSheetChangeEventsEnabled;
   }
 
   void ObsoleteSheet(nsIURI *aSheetURI, mozilla::ErrorResult& rv);
 
   void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv);
 
+  // ParentNode
+  nsIHTMLCollection* Children();
+  uint32_t ChildElementCount();
+
   virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
 
   virtual JSObject* WrapObject(JSContext *aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
 private:
   uint64_t mWarnedAbout;
 
@@ -2206,16 +2211,19 @@ protected:
 
   // SMIL Animation Controller, lazily-initialized in GetAnimationController
   nsRefPtr<nsSMILAnimationController> mAnimationController;
 
   // Table of element properties for this document.
   nsPropertyTable mPropertyTable;
   nsTArray<nsAutoPtr<nsPropertyTable> > mExtraPropertyTables;
 
+  // Our cached .children collection
+  nsCOMPtr<nsIHTMLCollection> mChildrenCollection;
+
   // Compatibility mode
   nsCompatibility mCompatMode;
 
   // Our readyState
   ReadyState mReadyState;
 
   // Our visibility state
   mozilla::dom::VisibilityState mVisibilityState;
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1585,21 +1585,28 @@ public:
   nsresult RemoveFromParent()
   {
     nsINode* parent = GetParentNode();
     mozilla::ErrorResult rv;
     parent->RemoveChild(*this, rv);
     return rv.ErrorCode();
   }
 
+  // ChildNode methods
+  mozilla::dom::Element* GetPreviousElementSibling() const;
+  mozilla::dom::Element* GetNextElementSibling() const;
   /**
    * Remove this node from its parent, if any.
    */
   void Remove();
 
+  // ParentNode methods
+  mozilla::dom::Element* GetFirstElementChild() const;
+  mozilla::dom::Element* GetLastElementChild() const;
+
 protected:
 
   // Override this function to create a custom slots class.
   // Must not return null.
   virtual nsINode::nsSlots* CreateSlots();
 
   bool HasSlots() const
   {
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -411,44 +411,16 @@ Element::WrapObject(JSContext *aCx, JS::
       nsContentUtils::AddScriptRunner(
         NS_NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
     }
   }
 
   return obj;
 }
 
-Element*
-Element::GetFirstElementChild() const
-{
-  uint32_t i, count = mAttrsAndChildren.ChildCount();
-  for (i = 0; i < count; ++i) {
-    nsIContent* child = mAttrsAndChildren.ChildAt(i);
-    if (child->IsElement()) {
-      return child->AsElement();
-    }
-  }
-  
-  return nullptr;
-}
-
-Element*
-Element::GetLastElementChild() const
-{
-  uint32_t i = mAttrsAndChildren.ChildCount();
-  while (i > 0) {
-    nsIContent* child = mAttrsAndChildren.ChildAt(--i);
-    if (child->IsElement()) {
-      return child->AsElement();
-    }
-  }
-  
-  return nullptr;
-}
-
 nsDOMTokenList*
 Element::GetClassList()
 {
   Element::nsDOMSlots *slots = DOMSlots();
 
   if (!slots->mClassList) {
     nsIAtom* classAttr = GetClassAttributeName();
     if (classAttr) {
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -334,40 +334,40 @@ nsIContent::GetBaseURI() const
 
 static inline JSObject*
 GetJSObjectChild(nsWrapperCache* aCache)
 {
   return aCache->PreservingWrapper() ? aCache->GetWrapperPreserveColor() : nullptr;
 }
 
 static bool
-NeedsScriptTraverse(nsWrapperCache* aCache)
+NeedsScriptTraverse(nsINode* aNode)
 {
-  JSObject* o = GetJSObjectChild(aCache);
-  return o && xpc_IsGrayGCThing(o);
+  return aNode->PreservingWrapper() && aNode->GetWrapperPreserveColor() &&
+         !aNode->IsBlackAndDoesNotNeedTracing(aNode);
 }
 
 //----------------------------------------------------------------------
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsChildContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsChildContentList)
 
 // If nsChildContentList is changed so that any additional fields are
 // traversed by the cycle collector, then CAN_SKIP must be updated to
 // check that the additional fields are null.
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(nsChildContentList)
 
 // nsChildContentList only ever has a single child, its wrapper, so if
 // the wrapper is black, the list can't be part of a garbage cycle.
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsChildContentList)
-  return !NeedsScriptTraverse(tmp);
+  return tmp->IsBlack();
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsChildContentList)
-  return !NeedsScriptTraverse(tmp);
+  return tmp->IsBlackAndDoesNotNeedTracing(tmp);
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
 
 // CanSkipThis returns false to avoid problems with incomplete unlinking.
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsChildContentList)
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
 
 NS_INTERFACE_TABLE_HEAD(nsChildContentList)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1645,16 +1645,17 @@ nsContentUtils::GetContextFromDocument(n
 void
 nsContentUtils::TraceSafeJSContext(JSTracer* aTrc)
 {
   JSContext* cx = GetSafeJSContext();
   if (!cx) {
     return;
   }
   if (JSObject* global = js::GetDefaultGlobalForContext(cx)) {
+    JS::AssertGCThingMustBeTenured(global);
     JS_CallObjectTracer(aTrc, &global, "safe context");
     MOZ_ASSERT(global == js::GetDefaultGlobalForContext(cx));
   }
 }
 
 nsPIDOMWindow *
 nsContentUtils::GetWindowFromCaller()
 {
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -51,17 +51,17 @@ class DataOwnerAdapter MOZ_FINAL : publi
 {
   typedef nsDOMMemoryFile::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          uint32_t aStart,
                          uint32_t aLength,
                          nsIInputStream** _retval);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   // These are mandatory.
   NS_FORWARD_NSIINPUTSTREAM(mStream->)
   NS_FORWARD_NSISEEKABLESTREAM(mSeekableStream->)
 
   // This is optional. We use a conditional QI to keep it from being called
   // if the underlying stream doesn't support it.
   NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(mSerializableInputStream->)
@@ -77,18 +77,18 @@ private:
   }
 
   nsRefPtr<DataOwner> mDataOwner;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
   nsCOMPtr<nsIIPCSerializableInputStream> mSerializableInputStream;
 };
 
-NS_IMPL_THREADSAFE_ADDREF(DataOwnerAdapter)
-NS_IMPL_THREADSAFE_RELEASE(DataOwnerAdapter)
+NS_IMPL_ADDREF(DataOwnerAdapter)
+NS_IMPL_RELEASE(DataOwnerAdapter)
 
 NS_INTERFACE_MAP_BEGIN(DataOwnerAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsISeekableStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIPCSerializableInputStream,
                                      mSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
 NS_INTERFACE_MAP_END
@@ -440,18 +440,18 @@ NS_INTERFACE_MAP_BEGIN(nsDOMFile)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFile)
   NS_INTERFACE_MAP_ENTRY(nsIXHRSendable)
   NS_INTERFACE_MAP_ENTRY(nsIMutable)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, mIsFile)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !mIsFile)
 NS_INTERFACE_MAP_END
 
 // Threadsafe when GetMutable() == false
-NS_IMPL_THREADSAFE_ADDREF(nsDOMFile)
-NS_IMPL_THREADSAFE_RELEASE(nsDOMFile)
+NS_IMPL_ADDREF(nsDOMFile)
+NS_IMPL_RELEASE(nsDOMFile)
 
 ////////////////////////////////////////////////////////////////////////////
 // nsDOMFileCC implementation
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsDOMFileCC)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMFileCC)
   // We don't have anything to traverse, but some of our subclasses do.
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -619,17 +619,17 @@ nsDOMMemoryFile::DataOwner::sDataOwners;
 /* static */ bool
 nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered;
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf)
 
 class nsDOMMemoryFileDataOwnerMemoryReporter MOZ_FINAL
   : public nsIMemoryMultiReporter
 {
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   NS_IMETHOD GetName(nsACString& aName)
   {
     aName.AssignASCII("dom-memory-file-data-owner");
     return NS_OK;
   }
 
   NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback,
@@ -700,17 +700,17 @@ class nsDOMMemoryFileDataOwnerMemoryRepo
         aClosure);
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return NS_OK;
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter,
+NS_IMPL_ISUPPORTS1(nsDOMMemoryFileDataOwnerMemoryReporter,
                    nsIMemoryMultiReporter)
 
 /* static */ void
 nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered()
 {
   sDataOwnerMutex.AssertCurrentThreadOwns();
   if (sMemoryReporterRegistered) {
     return;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1788,16 +1788,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection)
 
   // Traverse all our nsCOMArrays.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCatalogSheets)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPreloadingImages)
 
   for (uint32_t i = 0; i < tmp->mFrameRequestCallbacks.Length(); ++i) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mFrameRequestCallbacks[i]");
@@ -1872,16 +1873,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDisplayDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mFirstBaseNodeWithHref)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMImplementation)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mImageMaps)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalDocument)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
 
   tmp->mParentDocument = nullptr;
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPreloadingImages)
 
 
   if (tmp->mBoxObjectTable) {
    tmp->mBoxObjectTable->EnumerateRead(ClearAllBoxObjects, nullptr);
@@ -9470,16 +9472,35 @@ nsIDocument::ObsoleteSheet(const nsAStri
     return;
   }
   res = CSSLoader()->ObsoleteSheet(uri);
   if (NS_FAILED(res)) {
     rv.Throw(res);
   }
 }
 
+nsIHTMLCollection*
+nsIDocument::Children()
+{
+  if (!mChildrenCollection) {
+    mChildrenCollection = new nsContentList(this, kNameSpaceID_Wildcard,
+                                            nsGkAtoms::_asterix,
+                                            nsGkAtoms::_asterix,
+                                            false);
+  }
+
+  return mChildrenCollection;
+}
+
+uint32_t
+nsIDocument::ChildElementCount()
+{
+  return Children()->Length();
+}
+
 namespace mozilla {
 
 // Singleton class to manage the list of fullscreen documents which are the
 // root of a branch which contains fullscreen documents. We maintain this list
 // so that we can easily exit all windows from fullscreen when the user
 // presses the escape key.
 class FullscreenRoots {
 public:
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -1399,31 +1399,87 @@ nsINode::doInsertChildAt(nsIContent* aKi
       mozAutoSubtreeModified subtree(OwnerDoc(), this);
       (new nsAsyncDOMEvent(aKid, mutation))->RunDOMEventWhenSafe();
     }
   }
 
   return NS_OK;
 }
 
+Element*
+nsINode::GetPreviousElementSibling() const
+{
+  nsIContent* previousSibling = GetPreviousSibling();
+  while (previousSibling) {
+    if (previousSibling->IsElement()) {
+      return previousSibling->AsElement();
+    }
+    previousSibling = previousSibling->GetPreviousSibling();
+  }
+
+  return nullptr;
+}
+
+Element*
+nsINode::GetNextElementSibling() const
+{
+  nsIContent* nextSibling = GetNextSibling();
+  while (nextSibling) {
+    if (nextSibling->IsElement()) {
+      return nextSibling->AsElement();
+    }
+    nextSibling = nextSibling->GetNextSibling();
+  }
+
+  return nullptr;
+}
+
 void
 nsINode::Remove()
 {
   nsCOMPtr<nsINode> parent = GetParentNode();
   if (!parent) {
     return;
   }
   int32_t index = parent->IndexOf(this);
   if (index < 0) {
     NS_WARNING("Ignoring call to nsINode::Remove on anonymous child.");
     return;
   }
   parent->RemoveChildAt(uint32_t(index), true);
 }
 
+Element*
+nsINode::GetFirstElementChild() const
+{
+  for (nsIContent* child = GetFirstChild();
+       child;
+       child = child->GetNextSibling()) {
+    if (child->IsElement()) {
+      return child->AsElement();
+    }
+  }
+
+  return nullptr;
+}
+
+Element*
+nsINode::GetLastElementChild() const
+{
+  for (nsIContent* child = GetLastChild();
+       child;
+       child = child->GetPreviousSibling()) {
+    if (child->IsElement()) {
+      return child->AsElement();
+    }
+  }
+
+  return nullptr;
+}
+
 void
 nsINode::doRemoveChildAt(uint32_t aIndex, bool aNotify,
                          nsIContent* aKid, nsAttrAndChildArray& aChildArray)
 {
   NS_PRECONDITION(aKid && aKid->GetParentNode() == this &&
                   aKid == GetChildAt(aIndex) &&
                   IndexOf(aKid) == (int32_t)aIndex, "Bogus aKid");
 
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -70,17 +70,17 @@ public:
       mLoading(true),
       mIsInline(true),
       mJSVersion(aVersion),
       mLineNo(1),
       mCORSMode(aCORSMode)
   {
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   void FireScriptAvailable(nsresult aResult)
   {
     mElement->ScriptAvailable(aResult, mElement, mIsInline, mURI, mLineNo);
   }
   void FireScriptEvaluated(nsresult aResult)
   {
     mElement->ScriptEvaluated(aResult, mElement, mIsInline);
@@ -100,17 +100,17 @@ public:
   nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   int32_t mLineNo;
   const CORSMode mCORSMode;
 };
 
 // The nsScriptLoadRequest is passed as the context to necko, and thus
 // it needs to be threadsafe. Necko won't do anything with this
 // context, but it will AddRef and Release it on other threads.
-NS_IMPL_THREADSAFE_ISUPPORTS0(nsScriptLoadRequest)
+NS_IMPL_ISUPPORTS0(nsScriptLoadRequest)
 
 //////////////////////////////////////////////////////////////
 //
 //////////////////////////////////////////////////////////////
 
 nsScriptLoader::nsScriptLoader(nsIDocument *aDocument)
   : mDocument(aDocument),
     mBlockerCount(0),
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -244,16 +244,17 @@ MOCHITEST_FILES_A = \
 		test_bug282547.html \
 		bug282547.sjs \
 		test_domparser_null_char.html \
 		test_bug811701.html \
 		test_bug811701.xhtml \
 		test_bug820909.html \
 		test_bug704063.html \
 		test_bug894874.html \
+		test_bug895974.html \
 		$(NULL)
 
 MOCHITEST_FILES_B = \
 		test_bug459424.html \
 		bug461735-redirect1.sjs \
 		bug461735-redirect2.sjs \
 		bug461735-post-redirect.js \
 		test_bug513194.html \
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug895974.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=895974
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 895974</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 895974 **/
+  SimpleTest.waitForExplicitFinish();
+
+  addLoadEvent(function() {
+  var frag = document.createDocumentFragment();
+  var span = document.createElement("span");
+  var div = document.createElement("div");
+  var text = document.createTextNode("help");
+  frag.appendChild(document.createTextNode("fail"));
+  frag.appendChild(span);
+  frag.appendChild(text);
+  frag.appendChild(div);
+  frag.appendChild(document.createTextNode("fail"));
+
+  is(text.nextElementSibling, div, "nextElementSibling should work on text");
+  is(text.previousElementSibling, span,
+    "previousElementSibling should work on text");
+
+  is(document.firstElementChild, document.documentElement,
+     "firstElementChild should work on document");
+  is(document.lastElementChild, document.documentElement,
+     "lastElementChild should work on document");
+  is(document.children.length, 1, "Document has one element kid");
+  is(document.children[0], document.documentElement,
+     "Document only element child is <html>");
+
+  is(frag.firstElementChild, span,
+     "firstElementChild should work on document fragment");
+  is(frag.lastElementChild, div,
+     "lastElementChild should work on document fragment");
+  is(frag.children.length, 2, "Document fragment has two element kids");
+  is(frag.children[0], span, "Document fragment first element child is span");
+  is(frag.children[1], div, "Document fragment second element child is div");
+
+  is(document.documentElement.firstElementChild, document.head,
+     "firstElementChild should work on element");
+  is(document.documentElement.lastElementChild, document.body,
+     "lastElementChild should work on element");
+  is(document.documentElement.children.length, 2, "<html> has two element kids");
+  is(document.documentElement.children[0], document.head,
+     "<html> first element child is head");
+  is(document.documentElement.children[1], document.body,
+     "<html>  second element child is body");
+  SimpleTest.finish();
+  });
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=895974">Mozilla Bug 895974</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -517,17 +517,18 @@ public:
     void TexImage2D(WebGLenum target, WebGLint level,
                     WebGLenum internalformat, WebGLenum format, WebGLenum type,
                     dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexImage2D
     template<class ElementType>
     void TexImage2D(WebGLenum target, WebGLint level,
                     WebGLenum internalformat, WebGLenum format, WebGLenum type,
-                    const ElementType& elt, ErrorResult& rv) {
+                    ElementType& elt, ErrorResult& rv)
+    {
         if (!IsContextStable())
             return;
         nsRefPtr<gfxImageSurface> isurf;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
         rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
                                                     &srcFormat);
         if (rv.Failed())
@@ -554,17 +555,18 @@ public:
     void TexSubImage2D(WebGLenum target, WebGLint level,
                        WebGLint xoffset, WebGLint yoffset, WebGLenum format,
                        WebGLenum type, dom::ImageData* pixels, ErrorResult& rv);
     // Allow whatever element types the bindings are willing to pass
     // us in TexSubImage2D
     template<class ElementType>
     void TexSubImage2D(WebGLenum target, WebGLint level,
                        WebGLint xoffset, WebGLint yoffset, WebGLenum format,
-                       WebGLenum type, const ElementType& elt, ErrorResult& rv) {
+                       WebGLenum type, ElementType& elt, ErrorResult& rv)
+    {
         if (!IsContextStable())
             return;
         nsRefPtr<gfxImageSurface> isurf;
         WebGLTexelFormat srcFormat;
         nsLayoutUtils::SurfaceFromElementResult res = SurfaceFromElement(elt);
         rv = SurfaceFromElementResultToImageSurface(res, getter_AddRefs(isurf),
                                                     &srcFormat);
         if (rv.Failed())
@@ -971,18 +973,19 @@ protected:
 
         if (mPixelStoreColorspaceConversion == LOCAL_GL_NONE)
             flags |= nsLayoutUtils::SFE_NO_COLORSPACE_CONVERSION;
         if (!mPixelStorePremultiplyAlpha)
             flags |= nsLayoutUtils::SFE_NO_PREMULTIPLY_ALPHA;
         return nsLayoutUtils::SurfaceFromElement(aElement, flags);
     }
     template<class ElementType>
-    nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(const dom::NonNull<ElementType>& aElement) {
-      return SurfaceFromElement(aElement.get());
+    nsLayoutUtils::SurfaceFromElementResult SurfaceFromElement(ElementType& aElement)
+    {
+      return SurfaceFromElement(&aElement);
     }
 
     nsresult SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromElementResult& res,
                                                     gfxImageSurface **imageOut,
                                                     WebGLTexelFormat *format);
 
     void CopyTexSubImage2D_base(WebGLenum target,
                                 WebGLint level,
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -37,8 +37,12 @@ INCLUDES	+= \
 		-I$(srcdir) \
 		-I$(topsrcdir)/xpcom/ds \
 		-I$(topsrcdir)/content/media/ \
 		$(NULL)
 
 DEFINES		+= \
 		-D_IMPL_NS_LAYOUT \
 		$(NULL)
+
+ifdef MOZ_WEBGL
+DEFINES += -DMOZ_WEBGL
+endif
--- a/content/html/content/src/nsHTMLDNSPrefetch.cpp
+++ b/content/html/content/src/nsHTMLDNSPrefetch.cpp
@@ -224,18 +224,18 @@ nsHTMLDNSPrefetch::CancelPrefetchLow(con
 {
   return CancelPrefetch(hostname, nsIDNSService::RESOLVE_PRIORITY_LOW,
                         aReason);
 }
 
 
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsHTMLDNSPrefetch::nsListener,
-                              nsIDNSListener)
+NS_IMPL_ISUPPORTS1(nsHTMLDNSPrefetch::nsListener,
+                   nsIDNSListener)
 
 NS_IMETHODIMP
 nsHTMLDNSPrefetch::nsListener::OnLookupComplete(nsICancelable *request,
                                               nsIDNSRecord  *rec,
                                               nsresult       status)
 {
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLDNSPrefetch.h
+++ b/content/html/content/src/nsHTMLDNSPrefetch.h
@@ -68,17 +68,17 @@ private:
                                  uint16_t flags,
                                  nsresult aReason);
   
 public:
   class nsListener MOZ_FINAL : public nsIDNSListener
   {
     // This class exists to give a safe callback no-op DNSListener
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIDNSLISTENER
 
     nsListener()  {}
   private:
     ~nsListener() {}
   };
   
   class nsDeferrals MOZ_FINAL: public nsIWebProgressListener
--- a/content/html/document/src/MediaDocument.cpp
+++ b/content/html/document/src/MediaDocument.cpp
@@ -30,19 +30,19 @@ MediaDocumentStreamListener::MediaDocume
   mDocument = aDocument;
 }
 
 MediaDocumentStreamListener::~MediaDocumentStreamListener()
 {
 }
 
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(MediaDocumentStreamListener,
-                              nsIRequestObserver,
-                              nsIStreamListener)
+NS_IMPL_ISUPPORTS2(MediaDocumentStreamListener,
+                   nsIRequestObserver,
+                   nsIStreamListener)
 
 
 void
 MediaDocumentStreamListener::SetStreamListener(nsIStreamListener *aListener)
 {
   mNextStream = aListener;
 }
 
--- a/content/html/document/src/MediaDocument.h
+++ b/content/html/document/src/MediaDocument.h
@@ -75,17 +75,17 @@ private:
 
 class MediaDocumentStreamListener: public nsIStreamListener
 {
 public:
   MediaDocumentStreamListener(MediaDocument *aDocument);
   virtual ~MediaDocumentStreamListener();
   void SetStreamListener(nsIStreamListener *aListener);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   NS_DECL_NSIREQUESTOBSERVER
 
   NS_DECL_NSISTREAMLISTENER
 
   nsRefPtr<MediaDocument>      mDocument;
   nsCOMPtr<nsIStreamListener>  mNextStream;
 };
--- a/content/media/MediaDecoder.cpp
+++ b/content/media/MediaDecoder.cpp
@@ -105,17 +105,17 @@ public:
     int64_t result = 0;
     for (size_t i = 0; i < decoders.Length(); ++i) {
       result += decoders[i]->AudioQueueMemoryInUse();
     }
     return result;
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(MediaDecoder, nsIObserver)
+NS_IMPL_ISUPPORTS1(MediaDecoder, nsIObserver)
 
 void MediaDecoder::SetDormantIfNecessary(bool aDormant)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
 
   if (!mDecoderStateMachine || !mDecoderStateMachine->IsDormantNeeded() || (mPlayState == PLAY_STATE_SHUTDOWN)) {
     return;
--- a/content/media/MediaDecoder.h
+++ b/content/media/MediaDecoder.h
@@ -236,17 +236,17 @@ static const uint32_t FRAMEBUFFER_LENGTH
 #endif
 
 class MediaDecoder : public nsIObserver,
                      public AbstractMediaDecoder
 {
 public:
   typedef mozilla::layers::Image Image;
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   // Enumeration for the valid play states (see mPlayState)
   enum PlayState {
     PLAY_STATE_START,
     PLAY_STATE_LOADING,
     PLAY_STATE_PAUSED,
     PLAY_STATE_PLAYING,
--- a/content/media/MediaResource.h
+++ b/content/media/MediaResource.h
@@ -50,17 +50,20 @@ class MediaDecoder;
  */
 class MediaChannelStatistics {
 public:
   MediaChannelStatistics() { Reset(); }
 
   MediaChannelStatistics(MediaChannelStatistics * aCopyFrom)
   {
     MOZ_ASSERT(aCopyFrom);
-    *this = *aCopyFrom;
+    mAccumulatedBytes = aCopyFrom->mAccumulatedBytes;
+    mAccumulatedTime = aCopyFrom->mAccumulatedTime;
+    mLastStartTime = aCopyFrom->mLastStartTime;
+    mIsStarted = aCopyFrom->mIsStarted;
   }
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaChannelStatistics)
 
   void Reset() {
     mLastStartTime = TimeStamp();
     mAccumulatedTime = TimeDuration(0);
     mAccumulatedBytes = 0;
--- a/content/media/test/test_playback_rate_playpause.html
+++ b/content/media/test/test_playback_rate_playpause.html
@@ -9,16 +9,19 @@
 <body>
 <pre id="test">
 <script class="testbody" type='application/javascript;version=1.8'>
 
 if (navigator.platform.startsWith("Win")) {
   SimpleTest.expectAssertions(0, 1);
 } else if (navigator.platform.startsWith("Mac")) {
   SimpleTest.expectAssertions(0, 2);
+} else if (navigator.platform.startsWith("Linux")) {
+  // Bug 897024
+  SimpleTest.expectAssertions(0, 2);
 }
 
 let manager = new MediaTestManager;
 
 function ontimeupdate(e) {
   var t = e.target;
   if (t.currentTime != 0.0) {
     dump(t.token + " t.currentTime != 0.0.\n");
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -61,17 +61,17 @@ extern PRLogModuleInfo* gMediaDecoderLog
 class BufferDecoder : public AbstractMediaDecoder
 {
 public:
   // This class holds a weak pointer to MediaResouce.  It's the responsibility
   // of the caller to manage the memory of the MediaResource object.
   explicit BufferDecoder(MediaResource* aResource);
   virtual ~BufferDecoder();
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   // This has to be called before decoding begins
   void BeginDecoding(nsIThread* aDecodeThread)
   {
     MOZ_ASSERT(!mDecodeThread && aDecodeThread);
     mDecodeThread = aDecodeThread;
   }
 
@@ -121,17 +121,17 @@ private:
   // This monitor object is not really used to synchronize access to anything.
   // It's just there in order for us to be able to override
   // GetReentrantMonitor correctly.
   ReentrantMonitor mReentrantMonitor;
   nsCOMPtr<nsIThread> mDecodeThread;
   nsRefPtr<MediaResource> mResource;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS0(BufferDecoder)
+NS_IMPL_ISUPPORTS0(BufferDecoder)
 
 BufferDecoder::BufferDecoder(MediaResource* aResource)
   : mReentrantMonitor("BufferDecoder")
   , mResource(aResource)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_COUNT_CTOR(BufferDecoder);
 #ifdef PR_LOGGING
--- a/content/media/webrtc/MediaEngineDefault.cpp
+++ b/content/media/webrtc/MediaEngineDefault.cpp
@@ -20,17 +20,17 @@
 #include "nsISupportsUtils.h"
 #endif
 
 #define VIDEO_RATE USECS_PER_S
 #define AUDIO_RATE 16000
 
 namespace mozilla {
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultVideoSource, nsITimerCallback)
+NS_IMPL_ISUPPORTS1(MediaEngineDefaultVideoSource, nsITimerCallback)
 /**
  * Default video source.
  */
 
 MediaEngineDefaultVideoSource::MediaEngineDefaultVideoSource()
   : mTimer(nullptr)
 {
   mState = kReleased;
@@ -253,17 +253,17 @@ MediaEngineDefaultVideoSource::NotifyPul
 {
   // Ignore - we push video data
 }
 
 
 /**
  * Default audio source.
  */
-NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineDefaultAudioSource, nsITimerCallback)
+NS_IMPL_ISUPPORTS1(MediaEngineDefaultAudioSource, nsITimerCallback)
 
 MediaEngineDefaultAudioSource::MediaEngineDefaultAudioSource()
   : mTimer(nullptr)
 {
   mState = kReleased;
 }
 
 MediaEngineDefaultAudioSource::~MediaEngineDefaultAudioSource()
--- a/content/media/webrtc/MediaEngineDefault.h
+++ b/content/media/webrtc/MediaEngineDefault.h
@@ -54,17 +54,17 @@ public:
                           TrackID aId,
                           StreamTime aDesiredTime,
                           TrackTicks &aLastEndTime) {}
 
   virtual bool IsFake() {
     return true;
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 protected:
   friend class MediaEngineDefault;
 
   TrackID mTrackID;
   nsCOMPtr<nsITimer> mTimer;
   nsRefPtr<layers::ImageContainer> mImageContainer;
@@ -100,26 +100,27 @@ public:
                           TrackID aId,
                           StreamTime aDesiredTime,
                           TrackTicks &aLastEndTime) {}
 
   virtual bool IsFake() {
     return true;
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 protected:
   TrackID mTrackID;
   nsCOMPtr<nsITimer> mTimer;
 
   SourceMediaStream* mSource;
 };
 
+
 class MediaEngineDefault : public MediaEngine
 {
 public:
   MediaEngineDefault()
   : mMutex("mozilla::MediaEngineDefault")
   {}
   ~MediaEngineDefault() {}
 
--- a/content/media/webrtc/MediaEngineWebRTC.h
+++ b/content/media/webrtc/MediaEngineWebRTC.h
@@ -153,17 +153,17 @@ public:
                           TrackID aId,
                           StreamTime aDesiredTime,
                           TrackTicks &aLastEndTime);
 
   virtual bool IsFake() {
     return false;
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 #ifdef MOZ_B2G_CAMERA
   NS_DECL_NSICAMERAGETCAMERACALLBACK
   NS_DECL_NSICAMERAPREVIEWSTREAMCALLBACK
   NS_DECL_NSICAMERATAKEPICTURECALLBACK
   NS_DECL_NSICAMERARELEASECALLBACK
   NS_DECL_NSICAMERAERRORCALLBACK
 
   void AllocImpl();
@@ -300,17 +300,17 @@ public:
     return false;
   }
 
   // VoEMediaProcess.
   void Process(const int channel, const webrtc::ProcessingTypes type,
                WebRtc_Word16 audio10ms[], const int length,
                const int samplingFreq, const bool isStereo);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
 private:
   static const unsigned int KMaxDeviceNameLength = 128;
   static const unsigned int KMaxUniqueIdLength = 256;
 
   void Init();
   void Shutdown();
 
--- a/content/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -19,17 +19,17 @@ extern PRLogModuleInfo* GetMediaManagerL
 #define LOG(msg) PR_LOG(GetMediaManagerLog(), PR_LOG_DEBUG, msg)
 #else
 #define LOG(msg)
 #endif
 
 /**
  * Webrtc audio source.
  */
-NS_IMPL_THREADSAFE_ISUPPORTS0(MediaEngineWebRTCAudioSource)
+NS_IMPL_ISUPPORTS0(MediaEngineWebRTCAudioSource)
 
 void
 MediaEngineWebRTCAudioSource::GetName(nsAString& aName)
 {
   if (mInitDone) {
     aName.Assign(mDeviceName);
   }
 
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -17,17 +17,17 @@ extern PRLogModuleInfo* GetMediaManagerL
 #else
 #define LOG(msg)
 #define LOGFRAME(msg)
 #endif
 
 /**
  * Webrtc video source.
  */
-NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
+NS_IMPL_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
 
 // ViEExternalRenderer Callback.
 #ifndef MOZ_B2G_CAMERA
 int
 MediaEngineWebRTCVideoSource::FrameSizeChange(
    unsigned int w, unsigned int h, unsigned int streams)
 {
   mWidth = w;
--- a/content/media/wmf/WMFByteStream.cpp
+++ b/content/media/wmf/WMFByteStream.cpp
@@ -31,21 +31,21 @@ PRLogModuleInfo* gWMFByteStreamLog = nul
 // Limit the number of threads that we use for IO.
 static const uint32_t NumWMFIoThreads = 4;
 
 // Thread pool listener which ensures that MSCOM is initialized and
 // deinitialized on the thread pool thread. We can call back into WMF
 // on this thread, so we need MSCOM working.
 class ThreadPoolListener MOZ_FINAL : public nsIThreadPoolListener {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITHREADPOOLLISTENER
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(ThreadPoolListener, nsIThreadPoolListener)
+NS_IMPL_ISUPPORTS1(ThreadPoolListener, nsIThreadPoolListener)
 
 NS_IMETHODIMP
 ThreadPoolListener::OnThreadCreated()
 {
   HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
   if (FAILED(hr)) {
     NS_WARNING("Failed to initialize MSCOM on WMFByteStream thread.");
   }
@@ -209,18 +209,18 @@ WMFByteStream::QueryInterface(REFIID aII
   if (aIId == IID_IMFAttributes) {
     return DoGetInterface(static_cast<IMFAttributes*>(this), aInterface);
   }
 
   *aInterface = NULL;
   return E_NOINTERFACE;
 }
 
-NS_IMPL_THREADSAFE_ADDREF(WMFByteStream)
-NS_IMPL_THREADSAFE_RELEASE(WMFByteStream)
+NS_IMPL_ADDREF(WMFByteStream)
+NS_IMPL_RELEASE(WMFByteStream)
 
 
 // Stores data regarding an async read opreation.
 class ReadRequest MOZ_FINAL : public IUnknown {
 public:
   ReadRequest(int64_t aOffset, BYTE* aBuffer, ULONG aLength)
     : mOffset(aOffset),
       mBuffer(aBuffer),
@@ -234,22 +234,22 @@ public:
   STDMETHODIMP_(ULONG) Release();
 
   int64_t mOffset;
   BYTE* mBuffer;
   ULONG mBufferLength;
   ULONG mBytesRead;
 
   // IUnknown ref counting.
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
 
-NS_IMPL_THREADSAFE_ADDREF(ReadRequest)
-NS_IMPL_THREADSAFE_RELEASE(ReadRequest)
+NS_IMPL_ADDREF(ReadRequest)
+NS_IMPL_RELEASE(ReadRequest)
 
 // IUnknown Methods
 STDMETHODIMP
 ReadRequest::QueryInterface(REFIID aIId, void **aInterface)
 {
   LOG("ReadRequest::QueryInterface %s", GetGUIDName(aIId).get());
 
   if (aIId == IID_IUnknown) {
--- a/content/media/wmf/WMFByteStream.h
+++ b/content/media/wmf/WMFByteStream.h
@@ -157,15 +157,15 @@ private:
   // called.
   uint32_t mBytesConsumed;
 
   // True if the resource has been shutdown, either because the WMFReader is
   // shutting down, or because the underlying MediaResource has closed.
   bool mIsShutdown;
 
   // IUnknown ref counting.
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/wmf/WMFSourceReaderCallback.cpp
+++ b/content/media/wmf/WMFSourceReaderCallback.cpp
@@ -28,18 +28,18 @@ WMFSourceReaderCallback::QueryInterface(
   if (aIId == IID_IUnknown) {
     return DoGetInterface(static_cast<WMFSourceReaderCallback*>(this), aInterface);
   }
 
   *aInterface = NULL;
   return E_NOINTERFACE;
 }
 
-NS_IMPL_THREADSAFE_ADDREF(WMFSourceReaderCallback)
-NS_IMPL_THREADSAFE_RELEASE(WMFSourceReaderCallback)
+NS_IMPL_ADDREF(WMFSourceReaderCallback)
+NS_IMPL_RELEASE(WMFSourceReaderCallback)
 
 WMFSourceReaderCallback::WMFSourceReaderCallback()
   : mMonitor("WMFSourceReaderCallback")
   , mResultStatus(S_OK)
   , mStreamFlags(0)
   , mTimestamp(0)
   , mSample(nullptr)
   , mReadFinished(false)
--- a/content/media/wmf/WMFSourceReaderCallback.h
+++ b/content/media/wmf/WMFSourceReaderCallback.h
@@ -68,16 +68,16 @@ private:
   LONGLONG mTimestamp;
   IMFSample* mSample;
 
   // Sentinal. Set to true when a read result is returned. Wait() won't exit
   // until this is set to true.
   bool mReadFinished;
 
   // IUnknown ref counting.
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 
 };
 
 } // namespace mozilla
 
 #endif // WMFSourceReaderCallback_h_
--- a/content/xbl/src/nsXBLProtoImplMethod.cpp
+++ b/content/xbl/src/nsXBLProtoImplMethod.cpp
@@ -232,16 +232,18 @@ nsXBLProtoImplMethod::Trace(const TraceC
     aCallbacks.Trace(&mMethod.AsHeapObject(), "mMethod", aClosure);
   }
 }
 
 nsresult
 nsXBLProtoImplMethod::Read(nsIScriptContext* aContext,
                            nsIObjectInputStream* aStream)
 {
+  MOZ_ASSERT(!IsCompiled() && !GetUncompiledMethod());
+
   JS::Rooted<JSObject*> methodObject(aContext->GetNativeContext());
   nsresult rv = XBL_DeserializeFunction(aContext, aStream, &methodObject);
   if (NS_FAILED(rv)) {
     SetUncompiledMethod(nullptr);
     return rv;
   }
 
   SetCompiledMethod(methodObject);
@@ -256,27 +258,32 @@ nsXBLProtoImplMethod::Write(nsIScriptCon
   MOZ_ASSERT(IsCompiled());
   if (GetCompiledMethod()) {
     nsresult rv = aStream->Write8(XBLBinding_Serialize_Method);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = aStream->WriteWStringZ(mName);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    return XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject());
+    // Calling fromMarkedLocation() is safe because mMethod is traced by the
+    // Trace() method above, and because its value is never changed after it has
+    // been set to a compiled method.
+    JS::Handle<JSObject*> method =
+      JS::Handle<JSObject*>::fromMarkedLocation(mMethod.AsHeapObject().address());
+    return XBL_SerializeFunction(aContext, aStream, method);
   }
 
   return NS_OK;
 }
 
 nsresult
 nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement)
 {
   NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
-  
+
   if (!GetCompiledMethod()) {
     // Nothing to do here
     return NS_OK;
   }
 
   // Get the script context the same way
   // nsXBLProtoImpl::InstallImplementation does.
   nsIDocument* document = aBoundElement->OwnerDoc();
@@ -359,14 +366,19 @@ nsXBLProtoImplAnonymousMethod::Write(nsI
                                      nsIObjectOutputStream* aStream,
                                      XBLBindingSerializeDetails aType)
 {
   MOZ_ASSERT(IsCompiled());
   if (GetCompiledMethod()) {
     nsresult rv = aStream->Write8(aType);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = XBL_SerializeFunction(aContext, aStream, mMethod.AsHeapObject());
+    // Calling fromMarkedLocation() is safe because mMethod is traced by the
+    // Trace() method above, and because its value is never changed after it has
+    // been set to a compiled method.
+    JS::Handle<JSObject*> method =
+      JS::Handle<JSObject*>::fromMarkedLocation(mMethod.AsHeapObject().address());
+    rv = XBL_SerializeFunction(aContext, aStream, method);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
--- a/content/xbl/src/nsXBLProtoImplProperty.cpp
+++ b/content/xbl/src/nsXBLProtoImplProperty.cpp
@@ -352,20 +352,29 @@ nsXBLProtoImplProperty::Write(nsIScriptC
     type |= XBLBinding_Serialize_ReadOnly;
   }
 
   nsresult rv = aStream->Write8(type);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aStream->WriteWStringZ(mName);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // The calls to fromMarkedLocation() below are safe because mSetter and
+  // mGetter are traced by the Trace() method above, and because their values
+  // are never changed after they have been set to a compiled function.
+  MOZ_ASSERT_IF(mJSAttributes & (JSPROP_GETTER | JSPROP_SETTER), mIsCompiled);
+
   if (mJSAttributes & JSPROP_GETTER) {
-    rv = XBL_SerializeFunction(aContext, aStream, mGetter.AsHeapObject());
+    JS::Handle<JSObject*> function =
+      JS::Handle<JSObject*>::fromMarkedLocation(mGetter.AsHeapObject().address());
+    rv = XBL_SerializeFunction(aContext, aStream, function);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (mJSAttributes & JSPROP_SETTER) {
-    rv = XBL_SerializeFunction(aContext, aStream, mSetter.AsHeapObject());
+     JS::Handle<JSObject*> function =
+      JS::Handle<JSObject*>::fromMarkedLocation(mSetter.AsHeapObject().address());
+    rv = XBL_SerializeFunction(aContext, aStream, function);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2375,18 +2375,25 @@ nsXULPrototypeScript::Serialize(nsIObjec
         return NS_ERROR_FAILURE;
 
     // Write basic prototype data
     nsresult rv;
     rv = aStream->Write32(mLineNo);
     if (NS_FAILED(rv)) return rv;
     rv = aStream->Write32(mLangVersion);
     if (NS_FAILED(rv)) return rv;
-    // And delegate the writing to the nsIScriptContext
-    rv = context->Serialize(aStream, mScriptObject);
+
+    // And delegate the writing to the nsIScriptContext.
+    //
+    // Calling fromMarkedLocation() is safe because we trace mScriptObject in
+    // TraceScriptObject() and because its value is never changed after it has
+    // been set.
+    JS::Handle<JSScript*> script =
+        JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
+    rv = context->Serialize(aStream, script);
     if (NS_FAILED(rv)) return rv;
 
     return NS_OK;
 }
 
 nsresult
 nsXULPrototypeScript::SerializeOutOfLine(nsIObjectOutputStream* aStream,
                                          nsIScriptGlobalObject* aGlobal)
@@ -2401,18 +2408,17 @@ nsXULPrototypeScript::SerializeOutOfLine
     nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
     if (!cache)
         return NS_ERROR_OUT_OF_MEMORY;
 
     NS_ASSERTION(cache->IsEnabled(),
                  "writing to the cache file, but the XUL cache is off?");
     bool exists;
     cache->HasData(mSrcURI, &exists);
-    
-    
+
     /* return will be NS_OK from GetAsciiSpec.
      * that makes no sense.
      * nor does returning NS_OK from HasMuxedDocument.
      * XXX return something meaningful.
      */
     if (exists)
         return NS_OK;
 
--- a/content/xul/content/src/nsXULElement.h
+++ b/content/xul/content/src/nsXULElement.h
@@ -238,17 +238,20 @@ public:
     void Set(JSScript* aObject);
 
     // It's safe to return a handle because we trace mScriptObject, no one ever
     // uses the handle (or the script object) past the point at which the
     // nsXULPrototypeScript dies, and we can't get memmoved so the
     // &mScriptObject pointer can't go stale.
     JS::Handle<JSScript*> GetScriptObject()
     {
-        return JS::Handle<JSScript*>(mScriptObject);
+        // Calling fromMarkedLocation() is safe because we trace mScriptObject in
+        // TraceScriptObject() and because its value is never changed after it has
+        // been set.
+        return JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
     }
 
     void TraceScriptObject(JSTracer* aTrc)
     {
         if (mScriptObject) {
             JS_CallHeapScriptTracer(aTrc, &mScriptObject, "active window XUL prototype script");
         }
     }
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -78,17 +78,17 @@ nsXULPrototypeCache::nsXULPrototypeCache
 
 
 nsXULPrototypeCache::~nsXULPrototypeCache()
 {
     FlushScripts();
 }
 
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsXULPrototypeCache, nsIObserver)
+NS_IMPL_ISUPPORTS1(nsXULPrototypeCache, nsIObserver)
 
 /* static */ nsXULPrototypeCache*
 nsXULPrototypeCache::GetInstance()
 {
     if (!sInstance) {
         NS_ADDREF(sInstance = new nsXULPrototypeCache());
 
         sInstance->mPrototypeTable.Init();
@@ -192,30 +192,25 @@ nsXULPrototypeCache::PutStyleSheet(nsCSS
 
     return NS_OK;
 }
 
 
 JSScript*
 nsXULPrototypeCache::GetScript(nsIURI* aURI)
 {
-    JSScript* script;
-    if (!mScriptTable.Get(aURI, &script)) {
-        return nullptr;
-    }
-    return script;
+    return mScriptTable.Get(aURI);
 }
 
 nsresult
 nsXULPrototypeCache::PutScript(nsIURI* aURI,
                                JS::Handle<JSScript*> aScriptObject)
 {
 #ifdef DEBUG
-    JSScript* existingScript;
-    if (mScriptTable.Get(aURI, &existingScript)) {
+    if (JSScript* existingScript = mScriptTable.Get(aURI)) {
         nsAutoCString scriptName;
         aURI->GetSpec(scriptName);
         nsAutoCString message("Loaded script ");
         message += scriptName;
         message += " twice (bug 392650)";
         NS_WARNING(message.get());
     }
 #endif
@@ -651,20 +646,20 @@ MarkXULInCCGeneration(nsIURI* aKey, nsRe
 void
 nsXULPrototypeCache::MarkInCCGeneration(uint32_t aGeneration)
 {
     mXBLDocTable.Enumerate(MarkXBLInCCGeneration, &aGeneration);
     mPrototypeTable.Enumerate(MarkXULInCCGeneration, &aGeneration);
 }
 
 static PLDHashOperator
-MarkScriptsInGC(nsIURI* aKey, JSScript*& aScript, void* aClosure)
+MarkScriptsInGC(nsIURI* aKey, JS::Heap<JSScript*>& aScript, void* aClosure)
 {
     JSTracer* trc = static_cast<JSTracer*>(aClosure);
-    JS_CallScriptTracer(trc, &aScript, "nsXULPrototypeCache script");
+    JS_CallHeapScriptTracer(trc, &aScript, "nsXULPrototypeCache script");
     return PL_DHASH_NEXT;
 }
 
 void
 nsXULPrototypeCache::MarkInGC(JSTracer* aTrc)
 {
     mScriptTable.Enumerate(MarkScriptsInGC, aTrc);
 }
--- a/content/xul/document/src/nsXULPrototypeCache.h
+++ b/content/xul/document/src/nsXULPrototypeCache.h
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXULPrototypeCache_h__
 #define nsXULPrototypeCache_h__
 
 #include "nsCOMPtr.h"
 #include "nsIObserver.h"
 #include "nsXBLDocumentInfo.h"
-#include "nsDataHashtable.h"
+#include "nsJSThingHashtable.h"
 #include "nsInterfaceHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsXULPrototypeDocument.h"
 #include "nsIInputStream.h"
 #include "nsIStorageStream.h"
 
 #include "jspubtd.h"
@@ -31,17 +31,17 @@ class nsCSSStyleSheet;
  * The cache has two levels:
  *  1. In-memory hashtables
  *  2. The on-disk cache file.
  */
 class nsXULPrototypeCache : public nsIObserver
 {
 public:
     // nsISupports
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIOBSERVER
 
     bool IsCached(nsIURI* aURI) {
         return GetPrototype(aURI) != nullptr;
     }
     void AbortCaching();
 
 
@@ -118,23 +118,23 @@ protected:
 
     nsXULPrototypeCache();
     virtual ~nsXULPrototypeCache();
 
     static nsXULPrototypeCache* sInstance;
 
     void FlushSkinFiles();
 
-    nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument>  mPrototypeTable; // owns the prototypes
-    nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet>        mStyleSheetTable;
-    nsDataHashtable<nsURIHashKey, JSScript*>               mScriptTable;
-    nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo>  mXBLDocTable;
+    nsRefPtrHashtable<nsURIHashKey,nsXULPrototypeDocument>   mPrototypeTable; // owns the prototypes
+    nsRefPtrHashtable<nsURIHashKey,nsCSSStyleSheet>          mStyleSheetTable;
+    nsJSThingHashtable<nsURIHashKey, JSScript*>              mScriptTable;
+    nsRefPtrHashtable<nsURIHashKey,nsXBLDocumentInfo>        mXBLDocTable;
 
-    nsTHashtable<nsURIHashKey> mCacheURITable;
+    nsTHashtable<nsURIHashKey>                               mCacheURITable;
 
-    nsInterfaceHashtable<nsURIHashKey, nsIStorageStream> mOutputStreamTable;
+    nsInterfaceHashtable<nsURIHashKey, nsIStorageStream>     mOutputStreamTable;
     nsInterfaceHashtable<nsURIHashKey, nsIObjectInputStream> mInputStreamTable;
 
     // Bootstrap caching service
     nsresult BeginCaching(nsIURI* aDocumentURI);
 };
 
 #endif // nsXULPrototypeCache_h__
--- a/content/xul/document/src/nsXULPrototypeDocument.cpp
+++ b/content/xul/document/src/nsXULPrototypeDocument.cpp
@@ -84,23 +84,18 @@ protected:
 nsIPrincipal* nsXULPrototypeDocument::gSystemPrincipal;
 nsXULPDGlobalObject* nsXULPrototypeDocument::gSystemGlobal;
 uint32_t nsXULPrototypeDocument::gRefCnt;
 
 
 void
 nsXULPDGlobalObject_finalize(JSFreeOp *fop, JSObject *obj)
 {
-    nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(obj);
-
-    nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeThis));
-
-    if (sgo) {
-        sgo->OnFinalize(obj);
-    }
+    nsXULPDGlobalObject* nativeThis = static_cast<nsXULPDGlobalObject*>(JS_GetPrivate(obj));
+    nativeThis->OnFinalize(obj);
 
     // The addref was part of JSObject construction
     NS_RELEASE(nativeThis);
 }
 
 
 JSBool
 nsXULPDGlobalObject_resolve(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id)
--- a/docshell/base/nsDSURIContentListener.cpp
+++ b/docshell/base/nsDSURIContentListener.cpp
@@ -47,18 +47,18 @@ nsDSURIContentListener::Init()
     return rv;
 }
 
 
 //*****************************************************************************
 // nsDSURIContentListener::nsISupports
 //*****************************************************************************   
 
-NS_IMPL_THREADSAFE_ADDREF(nsDSURIContentListener)
-NS_IMPL_THREADSAFE_RELEASE(nsDSURIContentListener)
+NS_IMPL_ADDREF(nsDSURIContentListener)
+NS_IMPL_RELEASE(nsDSURIContentListener)
 
 NS_INTERFACE_MAP_BEGIN(nsDSURIContentListener)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIContentListener)
     NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
 //*****************************************************************************
--- a/docshell/base/nsDSURIContentListener.h
+++ b/docshell/base/nsDSURIContentListener.h
@@ -18,17 +18,17 @@ class nsIHttpChannel;
 
 class nsDSURIContentListener :
     public nsIURIContentListener,
     public nsSupportsWeakReference
 
 {
 friend class nsDocShell;
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIURICONTENTLISTENER
 
     nsresult Init();
 
 protected:
     nsDSURIContentListener(nsDocShell* aDocShell);
     virtual ~nsDSURIContentListener();
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -11725,18 +11725,18 @@ nsRefreshTimer::nsRefreshTimer()
 nsRefreshTimer::~nsRefreshTimer()
 {
 }
 
 //*****************************************************************************
 // nsRefreshTimer::nsISupports
 //*****************************************************************************   
 
-NS_IMPL_THREADSAFE_ADDREF(nsRefreshTimer)
-NS_IMPL_THREADSAFE_RELEASE(nsRefreshTimer)
+NS_IMPL_ADDREF(nsRefreshTimer)
+NS_IMPL_RELEASE(nsRefreshTimer)
 
 NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
     NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
 NS_INTERFACE_MAP_END_THREADSAFE
 
 ///*****************************************************************************
 // nsRefreshTimer::nsITimerCallback
@@ -11765,17 +11765,17 @@ nsDocShell::InterfaceRequestorProxy::Int
     }
 }
  
 nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy()
 {
     mWeakPtr = nullptr;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor) 
+NS_IMPL_ISUPPORTS1(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor) 
   
 NS_IMETHODIMP 
 nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID & aIID, void **aSink)
 {
     NS_ENSURE_ARG_POINTER(aSink);
     nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
     if (ifReq) {
         return ifReq->GetInterface(aIID, aSink);
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -104,17 +104,17 @@ enum ViewMode {
 //***    nsRefreshTimer
 //*****************************************************************************
 
 class nsRefreshTimer : public nsITimerCallback
 {
 public:
     nsRefreshTimer();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSITIMERCALLBACK
 
     int32_t GetDelay() { return mDelay ;}
 
     nsRefPtr<nsDocShell>  mDocShell;
     nsCOMPtr<nsIURI>      mURI;
     int32_t               mDelay;
     bool                  mRepeat;
@@ -894,17 +894,17 @@ private:
     static unsigned long gNumberOfDocShells;
 #endif /* DEBUG */
 
 public:
     class InterfaceRequestorProxy : public nsIInterfaceRequestor {
     public:
         InterfaceRequestorProxy(nsIInterfaceRequestor* p);
         virtual ~InterfaceRequestorProxy();
-        NS_DECL_ISUPPORTS
+        NS_DECL_THREADSAFE_ISUPPORTS
         NS_DECL_NSIINTERFACEREQUESTOR
  
     protected:
         InterfaceRequestorProxy() {}
         nsWeakPtr mWeakPtr;
     };
 };
 
--- a/dom/base/nsDOMScriptObjectFactory.cpp
+++ b/dom/base/nsDOMScriptObjectFactory.cpp
@@ -204,17 +204,17 @@ nsresult NS_GetScriptRuntimeByID(uint32_
 
   NS_ENSURE_TRUE(aScriptTypeID == nsIProgrammingLanguage::JAVASCRIPT,
                  NS_ERROR_FAILURE);
 
   return NS_GetJSRuntime(aLanguage);
 }
 
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMExceptionProvider, nsIExceptionProvider)
+NS_IMPL_ISUPPORTS1(nsDOMExceptionProvider, nsIExceptionProvider)
 
 NS_IMETHODIMP
 nsDOMExceptionProvider::GetException(nsresult result,
                                      nsIException *aDefaultException,
                                      nsIException **_retval)
 {
   if (!NS_IsMainThread()) {
     return NS_ERROR_NOT_IMPLEMENTED;
--- a/dom/base/nsDOMScriptObjectFactory.h
+++ b/dom/base/nsDOMScriptObjectFactory.h
@@ -46,11 +46,11 @@ public:
                                   uint32_t aScriptableFlags,
                                   bool aHasClassInterface,
                                   const nsCID *aConstructorCID) MOZ_OVERRIDE;
 };
 
 class nsDOMExceptionProvider MOZ_FINAL : public nsIExceptionProvider
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIEXCEPTIONPROVIDER
 };
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3342,17 +3342,17 @@ nsDOMWindowUtils::IsNodeDisabledForEvent
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SetPaintFlashing(bool aPaintFlashing)
 {
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
-    presContext->RefreshDriver()->SetPaintFlashing(aPaintFlashing);
+    presContext->SetPaintFlashing(aPaintFlashing);
     // Clear paint flashing colors
     nsIPresShell* presShell = GetPresShell();
     if (!aPaintFlashing && presShell) {
       nsIFrame* rootFrame = presShell->GetRootFrame();
       if (rootFrame) {
         rootFrame->InvalidateFrameSubtree();
       }
     }
@@ -3361,17 +3361,17 @@ nsDOMWindowUtils::SetPaintFlashing(bool 
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPaintFlashing(bool* aRetVal)
 {
   *aRetVal = false;
   nsPresContext* presContext = GetPresContext();
   if (presContext) {
-    *aRetVal = presContext->RefreshDriver()->GetPaintFlashing();
+    *aRetVal = presContext->GetPaintFlashing();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::DispatchEventToChromeOnly(nsIDOMEventTarget* aTarget,
                                             nsIDOMEvent* aEvent,
                                             bool* aRetVal)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1022,17 +1022,16 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
 #ifdef MOZ_GAMEPAD
     mHasSeenGamepadInput(false),
 #endif
     mNotifiedIDDestroyed(false),
     mAllowScriptsToClose(false),
     mTimeoutInsertionPoint(nullptr),
     mTimeoutPublicIdCounter(1),
     mTimeoutFiringDepth(0),
-    mJSObject(nullptr),
     mTimeoutsSuspendDepth(0),
     mFocusMethod(0),
     mSerial(0),
 #ifdef DEBUG
     mSetOpenerWindowCalled(false),
 #endif
     mCleanedUp(false),
     mCallCleanUpAfterModalDialogCloses(false),
@@ -1860,17 +1859,17 @@ nsGlobalWindow::GetGlobalJSObject()
 {
   return FastGetGlobalJSObject();
 }
 
 void
 nsGlobalWindow::TraceGlobalJSObject(JSTracer* aTrc)
 {
   if (mJSObject) {
-    JS_CallObjectTracer(aTrc, &mJSObject, "active window global");
+    JS_CallTenuredObjectTracer(aTrc, &mJSObject, "active window global");
   }
 }
 
 bool
 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
 {
   // We reuse the inner window when:
   // a. We are currently at our original document.
@@ -2112,24 +2111,23 @@ TreatAsRemoteXUL(nsIPrincipal* aPrincipa
  * Return the native global and an nsISupports 'holder' that can be used
  * to manage the lifetime of it.
  */
 static nsresult
 CreateNativeGlobalForInner(JSContext* aCx,
                            nsGlobalWindow* aNewInner,
                            nsIURI* aURI,
                            nsIPrincipal* aPrincipal,
-                           JSObject** aNativeGlobal,
+                           JS::TenuredHeap<JSObject*>& aNativeGlobal,
                            nsIXPConnectJSObjectHolder** aHolder)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aNewInner);
   MOZ_ASSERT(aNewInner->IsInnerWindow());
   MOZ_ASSERT(aPrincipal);
-  MOZ_ASSERT(aNativeGlobal);
   MOZ_ASSERT(aHolder);
 
   nsGlobalWindow *top = NULL;
   if (aNewInner->GetOuterWindow()) {
     top = aNewInner->GetTop();
   }
   JS::CompartmentOptions options;
   if (top) {
@@ -2149,23 +2147,23 @@ CreateNativeGlobalForInner(JSContext* aC
 
   nsRefPtr<nsIXPConnectJSObjectHolder> jsholder;
   nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
     aCx, ToSupports(aNewInner),
     aPrincipal, flags, options, getter_AddRefs(jsholder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   MOZ_ASSERT(jsholder);
-  *aNativeGlobal = jsholder->GetJSObject();
+  aNativeGlobal = jsholder->GetJSObject();
   jsholder.forget(aHolder);
 
   // Set the location information for the new global, so that tools like
   // about:memory may use that information
-  MOZ_ASSERT(*aNativeGlobal);
-  xpc::SetLocationForGlobal(*aNativeGlobal, aURI);
+  MOZ_ASSERT(aNativeGlobal.getPtr());
+  xpc::SetLocationForGlobal(aNativeGlobal, aURI);
 
   return NS_OK;
 }
 
 nsresult
 nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
                                nsISupports* aState,
                                bool aForceReuseInnerWindow)
@@ -2348,17 +2346,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
 
       Freeze();
       mCreatingInnerWindow = true;
       // Every script context we are initialized with must create a
       // new global.
       rv = CreateNativeGlobalForInner(cx, newInnerWindow,
                                       aDocument->GetDocumentURI(),
                                       aDocument->NodePrincipal(),
-                                      &newInnerWindow->mJSObject,
+                                      newInnerWindow->mJSObject,
                                       getter_AddRefs(mInnerWindowHolder));
       NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && mInnerWindowHolder,
                    "Failed to get script global and holder");
 
       mCreatingInnerWindow = false;
       createdInnerWindow = true;
       Thaw();
 
@@ -3148,17 +3146,17 @@ nsGlobalWindow::OnFinalize(JSObject* aOb
   }
 }
 
 void
 nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
 {
   MOZ_ASSERT(IsOuterWindow());
   if (aObject == mJSObject) {
-    mJSObject = reinterpret_cast<JSObject*>(0x1);
+    mJSObject.setToCrashOnTouch();
   }
 }
 
 void
 nsGlobalWindow::SetScriptsEnabled(bool aEnabled, bool aFireTimeouts)
 {
   FORWARD_TO_INNER_VOID(SetScriptsEnabled, (aEnabled, aFireTimeouts));
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1220,17 +1220,19 @@ protected:
   nsTimeout*                    mTimeoutInsertionPoint;
   uint32_t                      mTimeoutPublicIdCounter;
   uint32_t                      mTimeoutFiringDepth;
   nsRefPtr<nsLocation>          mLocation;
   nsRefPtr<nsHistory>           mHistory;
 
   // These member variables are used on both inner and the outer windows.
   nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
-  JSObject* mJSObject;
+
+  // The JS global object.  Global objects are always allocated tenured.
+  JS::TenuredHeap<JSObject*> mJSObject;
 
   typedef nsCOMArray<nsIDOMStorageEvent> nsDOMStorageEventArray;
   nsDOMStorageEventArray mPendingStorageEvents;
 
   uint32_t mTimeoutsSuspendDepth;
 
   // the method that was used to focus mFocusedNode
   uint32_t mFocusMethod;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -464,30 +464,32 @@ bool ScriptErrorEvent::sHandlingScriptEr
 void
 NS_ScriptErrorReporter(JSContext *cx,
                        const char *message,
                        JSErrorReport *report)
 {
   // We don't want to report exceptions too eagerly, but warnings in the
   // absence of werror are swallowed whole, so report those now.
   if (!JSREPORT_IS_WARNING(report->flags)) {
+    nsIXPConnect* xpc = nsContentUtils::XPConnect();
     if (JS_DescribeScriptedCaller(cx, nullptr, nullptr)) {
+      xpc->MarkErrorUnreported(cx);
       return;
     }
 
-    nsIXPConnect* xpc = nsContentUtils::XPConnect();
     if (xpc) {
       nsAXPCNativeCallContext *cc = nullptr;
       xpc->GetCurrentNativeCallContext(&cc);
       if (cc) {
         nsAXPCNativeCallContext *prev = cc;
         while (NS_SUCCEEDED(prev->GetPreviousCallContext(&prev)) && prev) {
           uint16_t lang;
           if (NS_SUCCEEDED(prev->GetLanguage(&lang)) &&
             lang == nsAXPCNativeCallContext::LANG_JS) {
+            xpc->MarkErrorUnreported(cx);
             return;
           }
         }
       }
     }
   }
 
   // XXX this means we are not going to get error reports on non DOM contexts
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -548,21 +548,21 @@ CreateInterfacePrototypeObject(JSContext
   }
 
   return ourProto;
 }
 
 void
 CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
                        JS::Handle<JSObject*> protoProto,
-                       JSClass* protoClass, JSObject** protoCache,
+                       JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
                        JS::Handle<JSObject*> constructorProto,
                        JSClass* constructorClass, const JSNativeHolder* constructor,
                        unsigned ctorNargs, const NamedConstructor* namedConstructors,
-                       JSObject** constructorCache, const DOMClass* domClass,
+                       JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
                        const NativeProperties* properties,
                        const NativeProperties* chromeOnlyProperties,
                        const char* name)
 {
   MOZ_ASSERT(protoClass || constructorClass || constructor,
              "Need at least one class or a constructor!");
   MOZ_ASSERT(!((properties &&
                 (properties->methods || properties->attributes)) ||
@@ -985,17 +985,17 @@ static bool
 ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
                               JS::Handle<JSObject*> obj,
                               size_t protoAndIfaceArrayIndex, unsigned attrs,
                               JSPropertyDescriptor* desc)
 {
   JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
   {
     JSAutoCompartment ac(cx, global);
-    JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(global);
+    JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(global);
     JSObject* protoOrIface = protoAndIfaceArray[protoAndIfaceArrayIndex];
     if (!protoOrIface) {
       return false;
     }
     desc->obj = wrapper;
     desc->shortid = 0;
     desc->attrs = attrs;
     desc->getter = JS_PropertyStub;
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -272,44 +272,43 @@ MOZ_STATIC_ASSERT((size_t)constructors::
 const size_t kProtoAndIfaceCacheCount = constructors::id::_ID_Count;
 
 inline void
 AllocateProtoAndIfaceCache(JSObject* obj)
 {
   MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
   MOZ_ASSERT(js::GetReservedSlot(obj, DOM_PROTOTYPE_SLOT).isUndefined());
 
-  // Important: The () at the end ensure zero-initialization
-  JSObject** protoAndIfaceArray = new JSObject*[kProtoAndIfaceCacheCount]();
+  JS::Heap<JSObject*>* protoAndIfaceArray = new JS::Heap<JSObject*>[kProtoAndIfaceCacheCount];
 
   js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
                       JS::PrivateValue(protoAndIfaceArray));
 }
 
 inline void
 TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
 {
   MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
 
   if (!HasProtoAndIfaceArray(obj))
     return;
-  JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj);
+  JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
   for (size_t i = 0; i < kProtoAndIfaceCacheCount; ++i) {
     if (protoAndIfaceArray[i]) {
-      JS_CallObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]");
+      JS_CallHeapObjectTracer(trc, &protoAndIfaceArray[i], "protoAndIfaceArray[i]");
     }
   }
 }
 
 inline void
 DestroyProtoAndIfaceCache(JSObject* obj)
 {
   MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
 
-  JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(obj);
+  JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(obj);
 
   delete [] protoAndIfaceArray;
 }
 
 /**
  * Add constants to an object.
  */
 bool
@@ -366,21 +365,21 @@ struct NamedConstructor
  * At least one of protoClass, constructorClass or constructor should be
  * non-null. If constructorClass or constructor are non-null, the resulting
  * interface object will be defined on the given global with property name
  * |name|, which must also be non-null.
  */
 void
 CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
                        JS::Handle<JSObject*> protoProto,
-                       JSClass* protoClass, JSObject** protoCache,
+                       JSClass* protoClass, JS::Heap<JSObject*>* protoCache,
                        JS::Handle<JSObject*> interfaceProto,
                        JSClass* constructorClass, const JSNativeHolder* constructor,
                        unsigned ctorNargs, const NamedConstructor* namedConstructors,
-                       JSObject** constructorCache, const DOMClass* domClass,
+                       JS::Heap<JSObject*>* constructorCache, const DOMClass* domClass,
                        const NativeProperties* regularProperties,
                        const NativeProperties* chromeOnlyProperties,
                        const char* name);
 
 /*
  * Define the unforgeable attributes on an object.
  */
 bool
@@ -2017,16 +2016,47 @@ struct JSBindingFinalized<T, true>
 
 // Helpers for creating a const version of a type.
 template<typename T>
 const T& Constify(T& arg)
 {
   return arg;
 }
 
+// Helper for turning (Owning)NonNull<T> into T&
+template<typename T>
+T& NonNullHelper(T& aArg)
+{
+  return aArg;
+}
+
+template<typename T>
+T& NonNullHelper(NonNull<T>& aArg)
+{
+  return aArg;
+}
+
+template<typename T>
+const T& NonNullHelper(const NonNull<T>& aArg)
+{
+  return aArg;
+}
+
+template<typename T>
+T& NonNullHelper(OwningNonNull<T>& aArg)
+{
+  return aArg;
+}
+
+template<typename T>
+const T& NonNullHelper(const OwningNonNull<T>& aArg)
+{
+  return aArg;
+}
+
 // Reparent the wrapper of aObj to whatever its native now thinks its
 // parent should be.
 nsresult
 ReparentWrapper(JSContext* aCx, JS::HandleObject aObj);
 
 /**
  * Used to implement the hasInstance hook of an interface object.
  *
@@ -2043,17 +2073,17 @@ InterfaceHasInstance(JSContext* cx, JS::
 // Helper for lenient getters/setters to report to console.  If this
 // returns false, we couldn't even get a global.
 bool
 ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
 
 inline JSObject*
 GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
 {
-  JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
+  JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
   JSObject* interfaceProto = protoAndIfaceArray[aId];
   return &js::GetReservedSlot(interfaceProto,
                               DOM_INTERFACE_PROTO_SLOTS_BASE).toObject();
 }
 
 // Given a JSObject* that represents the chrome side of a JS-implemented WebIDL
 // interface, get the nsPIDOMWindow corresponding to the content side, if any.
 // A false return means an exception was thrown.
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -66,38 +66,39 @@ public:
 
   /*
    * This getter does not change the color of the JSObject meaning that the
    * object returned is not guaranteed to be kept alive past the next CC.
    *
    * This should only be called if you are certain that the return value won't
    * be passed into a JS API function and that it won't be stored without being
    * rooted (or otherwise signaling the stored value to the CC).
-   *
-   * This can return a handle because we trace our mCallback.
    */
   JS::Handle<JSObject*> CallbackPreserveColor() const
   {
-    return mCallback;
+    // Calling fromMarkedLocation() is safe because we trace our mCallback, and
+    // because the value of mCallback cannot change after if has been set.
+    return JS::Handle<JSObject*>::fromMarkedLocation(mCallback.address());
   }
 
   enum ExceptionHandling {
     eReportExceptions,
     eRethrowExceptions
   };
 
 protected:
   explicit CallbackObject(CallbackObject* aCallbackObject)
   {
     Init(aCallbackObject->mCallback);
   }
 
 private:
   inline void Init(JSObject* aCallback)
   {
+    MOZ_ASSERT(aCallback && !mCallback);
     // Set mCallback before we hold, on the off chance that a GC could somehow
     // happen in there... (which would be pretty odd, granted).
     mCallback = aCallback;
     // Make sure we'll be able to drop as needed
     nsLayoutStatics::AddRef();
     NS_HOLD_JS_OBJECTS(this, CallbackObject);
   }
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -1063,17 +1063,17 @@ class CGClassConstructor(CGAbstractStati
         return CGAbstractStaticMethod.define(self)
 
     def definition_body(self):
         return self.generate_code()
 
     def generate_code(self):
         preamble = """
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  JS::Rooted<JSObject*> obj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
+  JS::Rooted<JSObject*> obj(cx, &args.callee());
 """
         name = self._ctor.identifier.name
         nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
         callGenerator = CGMethodCall(nativeName, True, self.descriptor,
                                      self._ctor, isConstructor=True)
         return preamble + callGenerator.define();
 
 # Encapsulate the constructor in a helper method to share genConstructorBody with CGJSImplMethod.
@@ -1085,17 +1085,17 @@ class CGConstructNavigatorObjectHelper(C
         name = "ConstructNavigatorObjectHelper"
         args = [Argument('JSContext*', 'cx'),
                 Argument('GlobalObject&', 'global'),
                 Argument('ErrorResult&', 'aRv')]
         rtype = 'already_AddRefed<%s>' % descriptor.name
         CGAbstractStaticMethod.__init__(self, descriptor, name, rtype, args)
 
     def definition_body(self):
-        return genConstructorBody(self.descriptor)
+        return CGIndenter(CGGeneric(genConstructorBody(self.descriptor))).define()
 
 class CGConstructNavigatorObject(CGAbstractMethod):
     """
     Wrap a JS-implemented WebIDL object into a JS value, for use on navigator.
     """
     def __init__(self, descriptor):
         name = 'ConstructNavigatorObject'
         args = [Argument('JSContext*', 'aCx'), Argument('JS::Handle<JSObject*>', 'aObj')]
@@ -1480,16 +1480,25 @@ class MethodDefiner(PropertyDefiner):
                                  "nativeName": stringifier.identifier.name,
                                  "length": 0,
                                  "flags": "JSPROP_ENUMERATE",
                                  "condition": PropertyDefiner.getControllingCondition(stringifier) }
                 if isChromeOnly(stringifier):
                     self.chrome.append(toStringDesc)
                 else:
                     self.regular.append(toStringDesc)
+        elif (descriptor.interface.isJSImplemented() and
+              descriptor.interface.hasInterfaceObject()):
+            self.chrome.append({"name": '_create',
+                                "nativeName": ("%s::_Create" %
+                                               descriptor.name),
+                                "methodInfo": False,
+                                "length": 2,
+                                "flags": "0",
+                                "condition": MemberCondition(None, None) })
 
         if static:
             if not descriptor.interface.hasInterfaceObject():
                 # static methods go on the interface object
                 assert not self.hasChromeOnly() and not self.hasNonChromeOnly()
         else:
             if not descriptor.interface.hasInterfacePrototypeObject():
                 # non-static methods go on the interface prototype object
@@ -1679,17 +1688,17 @@ class CGCreateInterfaceObjectsMethod(CGA
     """
     Generate the CreateInterfaceObjects method for an interface descriptor.
 
     properties should be a PropertyArrays instance.
     """
     def __init__(self, descriptor, properties):
         args = [Argument('JSContext*', 'aCx'),
                 Argument('JS::Handle<JSObject*>', 'aGlobal'),
-                Argument('JSObject**', 'protoAndIfaceArray')]
+                Argument('JS::Heap<JSObject*>*', 'protoAndIfaceArray')]
         CGAbstractMethod.__init__(self, descriptor, 'CreateInterfaceObjects', 'void', args)
         self.properties = properties
     def definition_body(self):
         protoChain = self.descriptor.prototypeChain
         if len(protoChain) == 1:
             getParentProto = "aCx, JS_GetObjectPrototype(aCx, aGlobal)"
             parentProtoType = "Rooted"
         else:
@@ -1882,23 +1891,29 @@ class CGGetPerInterfaceObject(CGAbstract
     def definition_body(self):
         return ("""
 
   /* Make sure our global is sane.  Hopefully we can remove this sometime */
   if (!(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL)) {
     return JS::NullPtr();
   }
   /* Check to see whether the interface objects are already installed */
-  JSObject** protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
+  JS::Heap<JSObject*>* protoAndIfaceArray = GetProtoAndIfaceArray(aGlobal);
   if (!protoAndIfaceArray[%s]) {
     CreateInterfaceObjects(aCx, aGlobal, protoAndIfaceArray);
   }
 
-  /* The object might _still_ be null, but that's OK */
-  return JS::Handle<JSObject*>::fromMarkedLocation(&protoAndIfaceArray[%s]);""" %
+  /* 
+   * The object might _still_ be null, but that's OK.
+   *
+   * Calling fromMarkedLocation() is safe because protoAndIfaceArray is
+   * traced by TraceProtoAndIfaceCache() and its contents are never
+   * changed after they have been set.
+   */
+  return JS::Handle<JSObject*>::fromMarkedLocation(protoAndIfaceArray[%s].address());""" %
                 (self.id, self.id))
 
 class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
     """
     A method for getting the interface prototype object.
     """
     def __init__(self, descriptor):
         CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
@@ -4415,16 +4430,21 @@ class CGCallGenerator(CGThing):
                     # so doesn't need to be const just due to being optional.
                     # This also covers variadic arguments.
                     return True
                 if a.type.isUnion():
                     return True
                 return False
             if needsConst(a):
                 arg = CGWrapper(arg, pre="Constify(", post=")")
+            # And convert NonNull<T> to T&
+            if (((a.type.isInterface() or a.type.isCallback()) and
+                 not a.type.nullable()) or
+                a.type.isDOMString()):
+                arg = CGWrapper(arg, pre="NonNullHelper(", post=")")
             args.append(arg)
 
         # Return values that go in outparams go here
         if resultOutParam:
             args.append(CGGeneric("result"))
         if isFallible:
             args.append(CGGeneric("rv"))
 
@@ -8422,17 +8442,21 @@ class CGBindingRoot(CGThing):
         def descriptorRequiresPreferences(desc):
             iface = desc.interface
             return any(m.getExtendedAttribute("Pref") for m in iface.members + [iface]);
         requiresPreferences = any(descriptorRequiresPreferences(d) for d in descriptors)
         hasOwnedDescriptors = any(d.nativeOwnership == 'owned' for d in descriptors)
         requiresContentUtils = any(d.interface.hasInterfaceObject() for d in descriptors)
         def descriptorHasChromeOnly(desc):
             return (any(isChromeOnly(a) for a in desc.interface.members) or
-                    desc.interface.getExtendedAttribute("ChromeOnly") is not None)
+                    desc.interface.getExtendedAttribute("ChromeOnly") is not None or
+                    # JS-implemented interfaces with an interface object get a
+                    # chromeonly _create method.
+                    (desc.interface.isJSImplemented() and
+                     desc.interface.hasInterfaceObject()))
         hasChromeOnly = any(descriptorHasChromeOnly(d) for d in descriptors)
         # XXXkhuey ugly hack but this is going away soon.
         isEventTarget = webIDLFile.endswith("EventTarget.webidl")
         hasWorkerStuff = len(config.getDescriptors(webIDLFile=webIDLFile,
                                                    workers=True)) != 0
         mainDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
                                                   workers=False)
         workerDictionaries = config.getDictionaries(webIDLFile=webIDLFile,
@@ -9224,30 +9248,30 @@ class CGJSImplMethod(CGNativeMember):
             args = self.getArgs(self.signature[0], self.signature[1])
             # The first two arguments to the constructor implementation are not
             # arguments to the WebIDL constructor, so don't pass them to __Init()
             assert args[0].argType == 'const GlobalObject&'
             assert args[1].argType == 'JSContext*'
             args = args[2:]
             constructorArgs = [arg.name for arg in args]
             initCall = """
-  // Wrap the object before calling __Init so that __DOM_IMPL__ is available.
-  nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
-  JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
-  JS::Rooted<JS::Value> wrappedVal(cx);
-  if (!WrapNewBindingObject(cx, scopeObj, impl, &wrappedVal)) {
-    MOZ_ASSERT(JS_IsExceptionPending(cx));
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-  // Initialize the object with the constructor arguments.
-  impl->mImpl->__Init(%s);
-  if (aRv.Failed()) {
-    return nullptr;
-  }""" % (", ".join(constructorArgs))
+// Wrap the object before calling __Init so that __DOM_IMPL__ is available.
+nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
+JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
+JS::Rooted<JS::Value> wrappedVal(cx);
+if (!WrapNewBindingObject(cx, scopeObj, impl, &wrappedVal)) {
+  MOZ_ASSERT(JS_IsExceptionPending(cx));
+  aRv.Throw(NS_ERROR_UNEXPECTED);
+  return nullptr;
+}
+// Initialize the object with the constructor arguments.
+impl->mImpl->__Init(%s);
+if (aRv.Failed()) {
+  return nullptr;
+}""" % (", ".join(constructorArgs))
         else:
             initCall = ""
         return genConstructorBody(self.descriptor, initCall)
 
 def genConstructorBody(descriptor, initCall=""):
     template = (
         "JS::Rooted<JSObject*> jsImplObj(cx);\n"
         "nsCOMPtr<nsPIDOMWindow> window =\n"
@@ -9380,16 +9404,25 @@ class CGJSImplClass(CGBindingImplClass):
 
         constructor = ClassConstructor(
             [Argument("JS::Handle<JSObject*>", "aJSImplObject"),
              Argument("nsPIDOMWindow*", "aParent")],
             visibility="public",
             baseConstructors=baseConstructors,
             body=constructorBody)
 
+        self.methodDecls.append(
+            ClassMethod("_Create",
+                        "JSBool",
+                        [Argument("JSContext*", "cx"),
+                         Argument("unsigned", "argc"),
+                         Argument("JS::Value*", "vp")],
+                        static=True,
+                        body=self.getCreateFromExistingBody()))
+
         CGClass.__init__(self, descriptor.name,
                          bases=baseClasses,
                          constructors=[constructor],
                          destructor=destructor,
                          methods=self.methodDecls,
                          decorators=decorators,
                          extradeclarations=extradeclarations,
                          extradefinitions=extradefinitions)
@@ -9411,16 +9444,51 @@ class CGJSImplClass(CGBindingImplClass):
                 "return obj;" % self.descriptor.name)
 
     def getGetParentObjectReturnType(self):
         return "nsISupports*"
 
     def getGetParentObjectBody(self):
         return "return mParent;"
 
+    def getCreateFromExistingBody(self):
+        # XXXbz we could try to get parts of this (e.g. the argument
+        # conversions) auto-generated by somehow creating an IDLMethod and
+        # adding it to our interface, but we'd still need to special-case the
+        # implementation slightly to have it not try to forward to the JS
+        # object...
+        return string.Template(
+            "JS::CallArgs args = JS::CallArgsFromVp(argc, vp);\n"
+            "if (args.length() < 2) {\n"
+            '  return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "${ifaceName}._create");\n'
+            "}\n"
+            "if (!args[0].isObject()) {\n"
+            '  return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of ${ifaceName}._create");\n'
+            "}\n"
+            "if (!args[1].isObject()) {\n"
+            '  return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of ${ifaceName}._create");\n'
+            "}\n"
+            "\n"
+            "// GlobalObject will go through wrappers as needed for us, and\n"
+            "// is simpler than the right UnwrapArg incantation.\n"
+            "GlobalObject global(cx, &args[0].toObject());\n"
+            "if (global.Failed()) {\n"
+            "  return false;\n"
+            "}\n"
+            "nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global.Get());\n"
+            "if (!window) {\n"
+            '  return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of ${ifaceName}._create");\n'
+            "}\n"
+            "JS::Rooted<JSObject*> arg(cx, &args[1].toObject());\n"
+            "nsRefPtr<${implName}> impl = new ${implName}(arg, window);\n"
+            "return WrapNewBindingObject(cx, arg, impl, args.rval());").substitute({
+                "ifaceName": self.descriptor.interface.identifier.name,
+                "implName": self.descriptor.name
+                })
+
 def isJSImplementedDescriptor(descriptorProvider):
     return (isinstance(descriptorProvider, Descriptor) and
             descriptorProvider.interface.isJSImplemented())
 
 class CGCallback(CGClass):
     def __init__(self, idlObject, descriptorProvider, baseName, methods,
                  getters=[], setters=[]):
         self.baseName = baseName
@@ -9837,17 +9905,17 @@ class CallbackOperationBase(CallbackMeth
         CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation)
 
     def getThisObj(self):
         if not self.singleOperation:
             return "mCallback"
         # This relies on getCallableDecl declaring a boolean
         # isCallable in the case when we're a single-operation
         # interface.
-        return "isCallable ? aThisObj : mCallback"
+        return "isCallable ? aThisObj.get() : mCallback"
 
     def getCallableDecl(self):
         replacements = {
             "errorReturn" : self.getDefaultRetval(),
             "methodName": self.methodName
             }
         getCallableFromProp = string.Template(
                 'if (!GetCallableProperty(cx, "${methodName}", &callable)) {\n'
--- a/dom/bindings/DOMJSClass.h
+++ b/dom/bindings/DOMJSClass.h
@@ -255,20 +255,20 @@ struct DOMIfaceAndProtoJSClass
 inline bool
 HasProtoAndIfaceArray(JSObject* global)
 {
   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
   // This can be undefined if we GC while creating the global
   return !js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).isUndefined();
 }
 
-inline JSObject**
+inline JS::Heap<JSObject*>*
 GetProtoAndIfaceArray(JSObject* global)
 {
   MOZ_ASSERT(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL);
-  return static_cast<JSObject**>(
+  return static_cast<JS::Heap<JSObject*>*>(
     js::GetReservedSlot(global, DOM_PROTOTYPE_SLOT).toPrivate());
 }
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_DOMJSClass_h */
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -270,17 +270,16 @@ public:
                         double arg8);
 
   // Interface types
   already_AddRefed<TestInterface> ReceiveSelf();
   already_AddRefed<TestInterface> ReceiveNullableSelf();
   TestInterface* ReceiveWeakSelf();
   TestInterface* ReceiveWeakNullableSelf();
   void PassSelf(TestInterface&);
-  void PassSelf2(NonNull<TestInterface>&);
   void PassNullableSelf(TestInterface*);
   already_AddRefed<TestInterface> NonNullSelf();
   void SetNonNullSelf(TestInterface&);
   already_AddRefed<TestInterface> GetNullableSelf();
   void SetNullableSelf(TestInterface*);
   void PassOptionalSelf(const Optional<TestInterface*> &);
   void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&);
   void PassOptionalSelfWithDefault(TestInterface*);
@@ -292,47 +291,44 @@ public:
   void ReceiveNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&);
   void ReceiveNullableNonWrapperCacheInterfaceNullableSequence(Nullable<nsTArray<nsRefPtr<TestNonWrapperCacheInterface> > >&);
 
   already_AddRefed<IndirectlyImplementedInterface> ReceiveOther();
   already_AddRefed<IndirectlyImplementedInterface> ReceiveNullableOther();
   IndirectlyImplementedInterface* ReceiveWeakOther();
   IndirectlyImplementedInterface* ReceiveWeakNullableOther();
   void PassOther(IndirectlyImplementedInterface&);
-  void PassOther2(NonNull<IndirectlyImplementedInterface>&);
   void PassNullableOther(IndirectlyImplementedInterface*);
   already_AddRefed<IndirectlyImplementedInterface> NonNullOther();
   void SetNonNullOther(IndirectlyImplementedInterface&);
   already_AddRefed<IndirectlyImplementedInterface> GetNullableOther();
   void SetNullableOther(IndirectlyImplementedInterface*);
   void PassOptionalOther(const Optional<IndirectlyImplementedInterface*>&);
   void PassOptionalNonNullOther(const Optional<NonNull<IndirectlyImplementedInterface> >&);
   void PassOptionalOtherWithDefault(IndirectlyImplementedInterface*);
 
   already_AddRefed<TestExternalInterface> ReceiveExternal();
   already_AddRefed<TestExternalInterface> ReceiveNullableExternal();
   TestExternalInterface* ReceiveWeakExternal();
   TestExternalInterface* ReceiveWeakNullableExternal();
   void PassExternal(TestExternalInterface*);
-  void PassExternal2(TestExternalInterface*);
   void PassNullableExternal(TestExternalInterface*);
   already_AddRefed<TestExternalInterface> NonNullExternal();
   void SetNonNullExternal(TestExternalInterface*);
   already_AddRefed<TestExternalInterface> GetNullableExternal();
   void SetNullableExternal(TestExternalInterface*);
   void PassOptionalExternal(const Optional<TestExternalInterface*>&);
   void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&);
   void PassOptionalExternalWithDefault(TestExternalInterface*);
 
   already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface();
   already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface();
   TestCallbackInterface* ReceiveWeakCallbackInterface();
   TestCallbackInterface* ReceiveWeakNullableCallbackInterface();
   void PassCallbackInterface(TestCallbackInterface&);
-  void PassCallbackInterface2(OwningNonNull<TestCallbackInterface>);
   void PassNullableCallbackInterface(TestCallbackInterface*);
   already_AddRefed<TestCallbackInterface> NonNullCallbackInterface();
   void SetNonNullCallbackInterface(TestCallbackInterface&);
   already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface();
   void SetNullableCallbackInterface(TestCallbackInterface*);
   void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterface> >&);
   void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&);
   void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*);
@@ -803,16 +799,38 @@ private:
   void PassOptionalNullableDateWithDefaultValue(Nullable<Date>&) MOZ_DELETE;
   void PassDateSequence(Sequence<Date>&) MOZ_DELETE;
   void PassNullableDateSequence(Sequence<Nullable<Date> >&) MOZ_DELETE;
 
   // Make sure variadics are const as needed
   void PassVariadicAny(JSContext*, Sequence<JS::Value>&) MOZ_DELETE;
   void PassVariadicObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
   void PassVariadicNullableObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
+
+  // Ensure NonNull does not leak in
+  void PassSelf(NonNull<TestInterface>&) MOZ_DELETE;
+  void PassSelf(OwningNonNull<TestInterface>&) MOZ_DELETE;
+  void PassSelf(const NonNull<TestInterface>&) MOZ_DELETE;
+  void PassSelf(const OwningNonNull<TestInterface>&) MOZ_DELETE;
+  void PassOther(NonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
+  void PassOther(const NonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
+  void PassOther(OwningNonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
+  void PassOther(const OwningNonNull<IndirectlyImplementedInterface>&) MOZ_DELETE;
+  void PassCallbackInterface(OwningNonNull<TestCallbackInterface>&) MOZ_DELETE;
+  void PassCallbackInterface(const OwningNonNull<TestCallbackInterface>&) MOZ_DELETE;
+  void PassCallbackInterface(NonNull<TestCallbackInterface>&) MOZ_DELETE;
+  void PassCallbackInterface(const NonNull<TestCallbackInterface>&) MOZ_DELETE;
+  void PassCallback(OwningNonNull<TestCallback>&) MOZ_DELETE;
+  void PassCallback(const OwningNonNull<TestCallback>&) MOZ_DELETE;
+  void PassCallback(NonNull<TestCallback>&) MOZ_DELETE;
+  void PassCallback(const NonNull<TestCallback>&) MOZ_DELETE;
+  void PassString(const NonNull<nsAString>&) MOZ_DELETE;
+  void PassString(NonNull<nsAString>&) MOZ_DELETE;
+  void PassString(const OwningNonNull<nsAString>&) MOZ_DELETE;
+  void PassString(OwningNonNull<nsAString>&) MOZ_DELETE;
 };
 
 class TestIndexedGetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -218,20 +218,17 @@ interface TestInterface {
                         optional unrestricted double arg8 = NaN);
 
   // Castable interface types
   // XXXbz add tests for throwing versions of all the castable interface stuff
   TestInterface receiveSelf();
   TestInterface? receiveNullableSelf();
   TestInterface receiveWeakSelf();
   TestInterface? receiveWeakNullableSelf();
-  // A verstion to test for casting to TestInterface&
   void passSelf(TestInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passSelf2(TestInterface arg);
   void passNullableSelf(TestInterface? arg);
   attribute TestInterface nonNullSelf;
   attribute TestInterface? nullableSelf;
   // Optional arguments
   void passOptionalSelf(optional TestInterface? arg);
   void passOptionalNonNullSelf(optional TestInterface arg);
   void passOptionalSelfWithDefault(optional TestInterface? arg = null);
 
@@ -249,54 +246,45 @@ interface TestInterface {
   [Creator]
   sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence();
 
   // Non-castable interface types
   IndirectlyImplementedInterface receiveOther();
   IndirectlyImplementedInterface? receiveNullableOther();
   IndirectlyImplementedInterface receiveWeakOther();
   IndirectlyImplementedInterface? receiveWeakNullableOther();
-  // A verstion to test for casting to IndirectlyImplementedInterface&
   void passOther(IndirectlyImplementedInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passOther2(IndirectlyImplementedInterface arg);
   void passNullableOther(IndirectlyImplementedInterface? arg);
   attribute IndirectlyImplementedInterface nonNullOther;
   attribute IndirectlyImplementedInterface? nullableOther;
   // Optional arguments
   void passOptionalOther(optional IndirectlyImplementedInterface? arg);
   void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg);
   void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null);
 
   // External interface types
   TestExternalInterface receiveExternal();
   TestExternalInterface? receiveNullableExternal();
   TestExternalInterface receiveWeakExternal();
   TestExternalInterface? receiveWeakNullableExternal();
-  // A verstion to test for casting to TestExternalInterface&
   void passExternal(TestExternalInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passExternal2(TestExternalInterface arg);
   void passNullableExternal(TestExternalInterface? arg);
   attribute TestExternalInterface nonNullExternal;
   attribute TestExternalInterface? nullableExternal;
   // Optional arguments
   void passOptionalExternal(optional TestExternalInterface? arg);
   void passOptionalNonNullExternal(optional TestExternalInterface arg);
   void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
 
   // Callback interface types
   TestCallbackInterface receiveCallbackInterface();
   TestCallbackInterface? receiveNullableCallbackInterface();
   TestCallbackInterface receiveWeakCallbackInterface();
   TestCallbackInterface? receiveWeakNullableCallbackInterface();
-  // A verstion to test for casting to TestCallbackInterface&
   void passCallbackInterface(TestCallbackInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passCallbackInterface2(TestCallbackInterface arg);
   void passNullableCallbackInterface(TestCallbackInterface? arg);
   attribute TestCallbackInterface nonNullCallbackInterface;
   attribute TestCallbackInterface? nullableCallbackInterface;
   // Optional arguments
   void passOptionalCallbackInterface(optional TestCallbackInterface? arg);
   void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg);
   void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null);
 
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -114,20 +114,17 @@ interface TestExampleInterface {
   attribute double lenientDoubleAttr;
 
   // Castable interface types
   // XXXbz add tests for throwing versions of all the castable interface stuff
   TestInterface receiveSelf();
   TestInterface? receiveNullableSelf();
   TestInterface receiveWeakSelf();
   TestInterface? receiveWeakNullableSelf();
-  // A verstion to test for casting to TestInterface&
   void passSelf(TestInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passSelf2(TestInterface arg);
   void passNullableSelf(TestInterface? arg);
   attribute TestInterface nonNullSelf;
   attribute TestInterface? nullableSelf;
   // Optional arguments
   void passOptionalSelf(optional TestInterface? arg);
   void passOptionalNonNullSelf(optional TestInterface arg);
   void passOptionalSelfWithDefault(optional TestInterface? arg = null);
 
@@ -145,54 +142,45 @@ interface TestExampleInterface {
   [Creator]
   sequence<TestNonWrapperCacheInterface?>? receiveNullableNonWrapperCacheInterfaceNullableSequence();
 
   // Non-castable interface types
   IndirectlyImplementedInterface receiveOther();
   IndirectlyImplementedInterface? receiveNullableOther();
   IndirectlyImplementedInterface receiveWeakOther();
   IndirectlyImplementedInterface? receiveWeakNullableOther();
-  // A verstion to test for casting to IndirectlyImplementedInterface&
   void passOther(IndirectlyImplementedInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passOther2(IndirectlyImplementedInterface arg);
   void passNullableOther(IndirectlyImplementedInterface? arg);
   attribute IndirectlyImplementedInterface nonNullOther;
   attribute IndirectlyImplementedInterface? nullableOther;
   // Optional arguments
   void passOptionalOther(optional IndirectlyImplementedInterface? arg);
   void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg);
   void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null);
 
   // External interface types
   TestExternalInterface receiveExternal();
   TestExternalInterface? receiveNullableExternal();
   TestExternalInterface receiveWeakExternal();
   TestExternalInterface? receiveWeakNullableExternal();
-  // A verstion to test for casting to TestExternalInterface&
   void passExternal(TestExternalInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passExternal2(TestExternalInterface arg);
   void passNullableExternal(TestExternalInterface? arg);
   attribute TestExternalInterface nonNullExternal;
   attribute TestExternalInterface? nullableExternal;
   // Optional arguments
   void passOptionalExternal(optional TestExternalInterface? arg);
   void passOptionalNonNullExternal(optional TestExternalInterface arg);
   void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
 
   // Callback interface types
   TestCallbackInterface receiveCallbackInterface();
   TestCallbackInterface? receiveNullableCallbackInterface();
   TestCallbackInterface receiveWeakCallbackInterface();
   TestCallbackInterface? receiveWeakNullableCallbackInterface();
-  // A verstion to test for casting to TestCallbackInterface&
   void passCallbackInterface(TestCallbackInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passCallbackInterface2(TestCallbackInterface arg);
   void passNullableCallbackInterface(TestCallbackInterface? arg);
   attribute TestCallbackInterface nonNullCallbackInterface;
   attribute TestCallbackInterface? nullableCallbackInterface;
   // Optional arguments
   void passOptionalCallbackInterface(optional TestCallbackInterface? arg);
   void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg);
   void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null);
 
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -131,18 +131,16 @@ interface TestJSImplInterface {
   TestJSImplInterface? receiveNullableSelf();
 
   // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
   //TestJSImplInterface receiveWeakSelf();
   //TestJSImplInterface? receiveWeakNullableSelf();
 
   // A version to test for casting to TestJSImplInterface&
   void passSelf(TestJSImplInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passSelf2(TestJSImplInterface arg);
   void passNullableSelf(TestJSImplInterface? arg);
   attribute TestJSImplInterface nonNullSelf;
   attribute TestJSImplInterface? nullableSelf;
   // Optional arguments
   void passOptionalSelf(optional TestJSImplInterface? arg);
   void passOptionalNonNullSelf(optional TestJSImplInterface arg);
   void passOptionalSelfWithDefault(optional TestJSImplInterface? arg = null);
 
@@ -163,56 +161,47 @@ interface TestJSImplInterface {
 
   // Non-castable interface types
   IndirectlyImplementedInterface receiveOther();
   IndirectlyImplementedInterface? receiveNullableOther();
   // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
   //IndirectlyImplementedInterface receiveWeakOther();
   //IndirectlyImplementedInterface? receiveWeakNullableOther();
 
-  // A verstion to test for casting to IndirectlyImplementedInterface&
   void passOther(IndirectlyImplementedInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passOther2(IndirectlyImplementedInterface arg);
   void passNullableOther(IndirectlyImplementedInterface? arg);
   attribute IndirectlyImplementedInterface nonNullOther;
   attribute IndirectlyImplementedInterface? nullableOther;
   // Optional arguments
   void passOptionalOther(optional IndirectlyImplementedInterface? arg);
   void passOptionalNonNullOther(optional IndirectlyImplementedInterface arg);
   void passOptionalOtherWithDefault(optional IndirectlyImplementedInterface? arg = null);
 
   // External interface types
   TestExternalInterface receiveExternal();
   TestExternalInterface? receiveNullableExternal();
   // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
   //TestExternalInterface receiveWeakExternal();
   //TestExternalInterface? receiveWeakNullableExternal();
-  // A verstion to test for casting to TestExternalInterface&
   void passExternal(TestExternalInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passExternal2(TestExternalInterface arg);
   void passNullableExternal(TestExternalInterface? arg);
   attribute TestExternalInterface nonNullExternal;
   attribute TestExternalInterface? nullableExternal;
   // Optional arguments
   void passOptionalExternal(optional TestExternalInterface? arg);
   void passOptionalNonNullExternal(optional TestExternalInterface arg);
   void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
 
   // Callback interface types
   TestCallbackInterface receiveCallbackInterface();
   TestCallbackInterface? receiveNullableCallbackInterface();
   // Callback interface ignores 'resultNotAddRefed'. See bug 843272.
   //TestCallbackInterface receiveWeakCallbackInterface();
   //TestCallbackInterface? receiveWeakNullableCallbackInterface();
-  // A verstion to test for casting to TestCallbackInterface&
   void passCallbackInterface(TestCallbackInterface arg);
-  // A version we can use to test for the exact type passed in
-  void passCallbackInterface2(TestCallbackInterface arg);
   void passNullableCallbackInterface(TestCallbackInterface? arg);
   attribute TestCallbackInterface nonNullCallbackInterface;
   attribute TestCallbackInterface? nullableCallbackInterface;
   // Optional arguments
   void passOptionalCallbackInterface(optional TestCallbackInterface? arg);
   void passOptionalNonNullCallbackInterface(optional TestCallbackInterface arg);
   void passOptionalCallbackInterfaceWithDefault(optional TestCallbackInterface? arg = null);
 
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -60,17 +60,17 @@ public:
 
   void SetPath(const nsAString& aPath);
   void SetEditable(bool aEditable);
 
   static already_AddRefed<DeviceStorageFile> CreateUnique(nsAString& aFileName,
                                                           uint32_t aFileType,
                                                           uint32_t aFileAttributes);
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   bool IsAvailable();
   bool IsComposite();
   void GetCompositePath(nsAString& aCompositePath);
 
   // we want to make sure that the names of file can't reach
   // outside of the type of storage the user asked for.
   bool IsSafePath();
--- a/dom/devicestorage/DeviceStorageRequestParent.cpp
+++ b/dom/devicestorage/DeviceStorageRequestParent.cpp
@@ -245,18 +245,18 @@ DeviceStorageRequestParent::EnsureRequir
   return true;
 }
 
 DeviceStorageRequestParent::~DeviceStorageRequestParent()
 {
   MOZ_COUNT_DTOR(DeviceStorageRequestParent);
 }
 
-NS_IMPL_THREADSAFE_ADDREF(DeviceStorageRequestParent)
-NS_IMPL_THREADSAFE_RELEASE(DeviceStorageRequestParent)
+NS_IMPL_ADDREF(DeviceStorageRequestParent)
+NS_IMPL_RELEASE(DeviceStorageRequestParent)
 
 void
 DeviceStorageRequestParent::ActorDestroy(ActorDestroyReason)
 {
   MutexAutoLock lock(mMutex);
   mActorDestoryed = true;
   int32_t count = mRunnables.Length();
   for (int32_t index = 0; index < count; index++) {
--- a/dom/devicestorage/DeviceStorageRequestParent.h
+++ b/dom/devicestorage/DeviceStorageRequestParent.h
@@ -31,17 +31,18 @@ public:
   void Dispatch();
 
   virtual void ActorDestroy(ActorDestroyReason);
 
 protected:
   ~DeviceStorageRequestParent();
 
 private:
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
   DeviceStorageParams mParams;
 
   class CancelableRunnable : public nsRunnable
   {
   public:
     CancelableRunnable(DeviceStorageRequestParent* aParent)
       : mParent(aParent)
     {
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -1295,17 +1295,17 @@ DeviceStorageFile::GetStatusInternal(nsA
   if (volState == nsIVolume::STATE_MOUNTED) {
     aStatus.AssignLiteral("available");
   } else if (volState == nsIVolume::STATE_SHARED || volState == nsIVolume::STATE_SHAREDMNT) {
     aStatus.AssignLiteral("shared");
   }
 #endif
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS0(DeviceStorageFile)
+NS_IMPL_ISUPPORTS0(DeviceStorageFile)
 
 static void
 RegisterForSDCardChanges(nsIObserver* aObserver)
 {
 #ifdef MOZ_WIDGET_GONK
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   obs->AddObserver(aObserver, NS_VOLUME_STATE_CHANGED, false);
 #endif
--- a/dom/file/ArchiveEvent.cpp
+++ b/dom/file/ArchiveEvent.cpp
@@ -7,17 +7,17 @@
 #include "ArchiveEvent.h"
 
 #include "nsContentUtils.h"
 #include "nsCExternalHandlerService.h"
 #include "nsProxyRelease.h"
 
 USING_FILE_NAMESPACE
 
-NS_IMPL_THREADSAFE_ISUPPORTS0(ArchiveItem)
+NS_IMPL_ISUPPORTS0(ArchiveItem)
 
 ArchiveItem::ArchiveItem()
 {
   MOZ_COUNT_CTOR(ArchiveItem);
 }
 
 ArchiveItem::~ArchiveItem()
 {
--- a/dom/file/ArchiveEvent.h
+++ b/dom/file/ArchiveEvent.h
@@ -19,17 +19,17 @@ BEGIN_FILE_NAMESPACE
 
 /**
  * This class contains all the info needed for a single item
  * It must contain the implementation of the File() method.
  */
 class ArchiveItem : public nsISupports
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   ArchiveItem();
   virtual ~ArchiveItem();
 
   // Getter/Setter for the type
   nsCString GetType();
   void SetType(const nsCString& aType);
 
--- a/dom/file/ArchiveZipFile.cpp
+++ b/dom/file/ArchiveZipFile.cpp
@@ -44,17 +44,17 @@ public:
   }
 
   virtual ~ArchiveInputStream()
   {
     MOZ_COUNT_DTOR(ArchiveInputStream);
     Close();
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSISEEKABLESTREAM
 
 private:
   nsresult Init();
 
 private: // data
   ZipCentral mCentral;
@@ -77,19 +77,19 @@ private: // data
     unsigned char input[ZIP_CHUNK];
     uint32_t sizeToBeRead;
     uint32_t cursor;
 
     bool compressed; // a zip file can contain stored or compressed files
   } mData;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(ArchiveInputStream,
-                              nsIInputStream,
-                              nsISeekableStream)
+NS_IMPL_ISUPPORTS2(ArchiveInputStream,
+                   nsIInputStream,
+                   nsISeekableStream)
 
 nsresult
 ArchiveInputStream::Init()
 {
   nsresult rv;
 
   memset(&mZs, 0, sizeof(z_stream));
   int zerr = inflateInit2(&mZs, -MAX_WBITS);
--- a/dom/file/AsyncHelper.cpp
+++ b/dom/file/AsyncHelper.cpp
@@ -9,17 +9,17 @@
 #include "nsIRequestObserver.h"
 
 #include "nsNetUtil.h"
 
 #include "FileService.h"
 
 USING_FILE_NAMESPACE
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(AsyncHelper, nsIRunnable, nsIRequest)
+NS_IMPL_ISUPPORTS2(AsyncHelper, nsIRunnable, nsIRequest)
 
 nsresult
 AsyncHelper::AsyncWork(nsIRequestObserver* aObserver, nsISupports* aCtxt)
 {
   nsresult rv;
 
   if (aObserver) {
     // build proxy for observer events
--- a/dom/file/AsyncHelper.h
+++ b/dom/file/AsyncHelper.h
@@ -20,17 +20,17 @@ BEGIN_FILE_NAMESPACE
  * Must be subclassed. The subclass must implement DoStreamWork.
  * Async operations that are not supported in necko (truncate, flush, etc.)
  * should use this helper. Call AsyncWork to invoke the operation.
  */
 class AsyncHelper : public nsIRunnable,
                     public nsIRequest
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIREQUEST
 
   nsresult
   AsyncWork(nsIRequestObserver* aObserver, nsISupports* aCtxt);
 
 protected:
   AsyncHelper(nsISupports* aStream)
--- a/dom/file/FileHelper.cpp
+++ b/dom/file/FileHelper.cpp
@@ -36,17 +36,17 @@ FileHelper::FileHelper(LockedFile* aLock
 }
 
 FileHelper::~FileHelper()
 {
   NS_ASSERTION(!mFileStorage && !mLockedFile && !mFileRequest && !mListener &&
                !mRequest, "Should have cleared this!");
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(FileHelper, nsIRequestObserver)
+NS_IMPL_ISUPPORTS1(FileHelper, nsIRequestObserver)
 
 nsresult
 FileHelper::Enqueue()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   FileService* service = FileService::GetOrCreate();
   NS_ENSURE_TRUE(service, NS_ERROR_FAILURE);
--- a/dom/file/FileHelper.h
+++ b/dom/file/FileHelper.h
@@ -40,17 +40,17 @@ public:
  * success event. Call Enqueue to start the file operation.
  */
 class FileHelper : public nsIRequestObserver
 {
   friend class FileRequest;
   friend class FileOutputStreamWrapper;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
 
   nsresult
   Enqueue();
 
   nsresult
   AsyncRun(FileHelperListener* aListener);
 
--- a/dom/file/FileService.cpp
+++ b/dom/file/FileService.cpp
@@ -338,18 +338,18 @@ FileService::MaybeFireCallback(StoragesC
 }
 
 FileService::LockedFileQueue::LockedFileQueue(LockedFile* aLockedFile)
 : mLockedFile(aLockedFile)
 {
   NS_ASSERTION(aLockedFile, "Null pointer!");
 }
 
-NS_IMPL_THREADSAFE_ADDREF(FileService::LockedFileQueue)
-NS_IMPL_THREADSAFE_RELEASE(FileService::LockedFileQueue)
+NS_IMPL_ADDREF(FileService::LockedFileQueue)
+NS_IMPL_RELEASE(FileService::LockedFileQueue)
 
 nsresult
 FileService::LockedFileQueue::Enqueue(FileHelper* aFileHelper)
 {
   mQueue.AppendElement(aFileHelper);
 
   nsresult rv;
   if (mLockedFile->mRequestMode == LockedFile::PARALLEL) {
--- a/dom/file/FileService.h
+++ b/dom/file/FileService.h
@@ -83,17 +83,17 @@ private:
 
   private:
     inline
     LockedFileQueue(LockedFile* aLockedFile);
 
     nsresult
     ProcessQueue();
 
-    nsAutoRefCnt mRefCnt;
+    ThreadSafeAutoRefCnt mRefCnt;
     NS_DECL_OWNINGTHREAD
     nsRefPtr<LockedFile> mLockedFile;
     nsTArray<nsRefPtr<FileHelper> > mQueue;
     nsRefPtr<FileHelper> mCurrentHelper;
   };
 
   struct DelayedEnqueueInfo
   {
--- a/dom/file/FileStreamWrappers.cpp
+++ b/dom/file/FileStreamWrappers.cpp
@@ -14,17 +14,17 @@
 
 USING_FILE_NAMESPACE
 
 namespace {
 
 class ProgressRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   ProgressRunnable(FileHelper* aFileHelper,
                    uint64_t aProgress,
                    uint64_t aProgressMax)
   : mFileHelper(aFileHelper),
     mProgress(aProgress),
     mProgressMax(aProgressMax)
@@ -35,31 +35,31 @@ private:
   nsRefPtr<FileHelper> mFileHelper;
   uint64_t mProgress;
   uint64_t mProgressMax;
 };
 
 class CloseRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   CloseRunnable(FileHelper* aFileHelper)
   : mFileHelper(aFileHelper)
   { }
 
 private:
   nsRefPtr<FileHelper> mFileHelper;
 };
 
 class DestroyRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   DestroyRunnable(FileHelper* aFileHelper)
   : mFileHelper(aFileHelper)
   { }
 
 private:
   nsRefPtr<FileHelper> mFileHelper;
@@ -96,17 +96,17 @@ FileStreamWrapper::~FileStreamWrapper()
       nsresult rv = NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
       if (NS_FAILED(rv)) {
         NS_WARNING("Failed to dispatch to the main thread!");
       }
     }
   }
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS0(FileStreamWrapper)
+NS_IMPL_ISUPPORTS0(FileStreamWrapper)
 
 FileInputStreamWrapper::FileInputStreamWrapper(nsISupports* aFileStream,
                                                FileHelper* aFileHelper,
                                                uint64_t aOffset,
                                                uint64_t aLimit,
                                                uint32_t aFlags)
 : FileStreamWrapper(aFileStream, aFileHelper, aOffset, aLimit, aFlags)
 {
@@ -342,43 +342,43 @@ FileOutputStreamWrapper::WriteSegments(n
 
 NS_IMETHODIMP
 FileOutputStreamWrapper::IsNonBlocking(bool* _retval)
 {
   *_retval = false;
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(ProgressRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(ProgressRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 ProgressRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mFileHelper->OnStreamProgress(mProgress, mProgressMax);
   mFileHelper = nullptr;
 
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(CloseRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(CloseRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 CloseRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mFileHelper->OnStreamClose();
   mFileHelper = nullptr;
 
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(DestroyRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(DestroyRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 DestroyRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mFileHelper->OnStreamDestroy();
   mFileHelper = nullptr;
--- a/dom/file/FileStreamWrappers.h
+++ b/dom/file/FileStreamWrappers.h
@@ -14,17 +14,17 @@
 
 BEGIN_FILE_NAMESPACE
 
 class FileHelper;
 
 class FileStreamWrapper : public nsISupports
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   FileStreamWrapper(nsISupports* aFileStream,
                     FileHelper* aFileHelper,
                     uint64_t aOffset,
                     uint64_t aLimit,
                     uint32_t aFlags);
 
   virtual ~FileStreamWrapper();
--- a/dom/file/LockedFile.cpp
+++ b/dom/file/LockedFile.cpp
@@ -918,17 +918,17 @@ LockedFile::Finish()
 FinishHelper::FinishHelper(LockedFile* aLockedFile)
 : mLockedFile(aLockedFile),
   mAborted(aLockedFile->mAborted)
 {
   mParallelStreams.SwapElements(aLockedFile->mParallelStreams);
   mStream.swap(aLockedFile->mStream);
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(FinishHelper, nsIRunnable)
+NS_IMPL_ISUPPORTS1(FinishHelper, nsIRunnable)
 
 NS_IMETHODIMP
 FinishHelper::Run()
 {
   if (NS_IsMainThread()) {
     mLockedFile->mReadyState = LockedFile::DONE;
 
     FileService* service = FileService::Get();
--- a/dom/file/LockedFile.h
+++ b/dom/file/LockedFile.h
@@ -121,17 +121,17 @@ private:
   bool mCreating;
 };
 
 class FinishHelper MOZ_FINAL : public nsIRunnable
 {
   friend class LockedFile;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
 private:
   FinishHelper(LockedFile* aLockedFile);
   ~FinishHelper()
   { }
 
   nsRefPtr<LockedFile> mLockedFile;
--- a/dom/file/MemoryStreams.cpp
+++ b/dom/file/MemoryStreams.cpp
@@ -22,17 +22,17 @@ MemoryOutputStream::Create(uint64_t aSiz
 
   char* dummy;
   uint32_t length = stream->mData.GetMutableData(&dummy, aSize, fallible_t());
   NS_ENSURE_TRUE(length == aSize, nullptr);
 
   return stream.forget();
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryOutputStream, nsIOutputStream)
+NS_IMPL_ISUPPORTS1(MemoryOutputStream, nsIOutputStream)
 
 NS_IMETHODIMP
 MemoryOutputStream::Close()
 {
   mData.Truncate(mOffset);
   return NS_OK;
 }
 
--- a/dom/file/MemoryStreams.h
+++ b/dom/file/MemoryStreams.h
@@ -11,17 +11,17 @@
 
 #include "nsIOutputStream.h"
 
 BEGIN_FILE_NAMESPACE
 
 class MemoryOutputStream : public nsIOutputStream
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOUTPUTSTREAM
 
   static already_AddRefed<MemoryOutputStream>
   Create(uint64_t aSize);
 
 
   const nsCString&
   Data() const
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -180,18 +180,18 @@ AsyncConnectionHelper::~AsyncConnectionH
                         static_cast<nsIIDBTransaction*>(transaction));
       }
     }
   }
 
   NS_ASSERTION(!mOldProgressHandler, "Should not have anything here!");
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(AsyncConnectionHelper, nsIRunnable,
-                                                     mozIStorageProgressHandler)
+NS_IMPL_ISUPPORTS2(AsyncConnectionHelper, nsIRunnable,
+                   mozIStorageProgressHandler)
 
 NS_IMETHODIMP
 AsyncConnectionHelper::Run()
 {
   if (NS_IsMainThread()) {
     PROFILER_MAIN_THREAD_LABEL("IndexedDB", "AsyncConnectionHelper::Run");
 
     if (mTransaction &&
--- a/dom/indexedDB/AsyncConnectionHelper.h
+++ b/dom/indexedDB/AsyncConnectionHelper.h
@@ -85,17 +85,17 @@ protected:
 class AsyncConnectionHelper : public HelperBase,
                               public mozIStorageProgressHandler
 {
   friend class AutoSetCurrentTransaction;
 
 public:
   typedef ipc::ResponseValue ResponseValue;
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_MOZISTORAGEPROGRESSHANDLER
 
   virtual nsresult Dispatch(nsIEventTarget* aDatabaseThread);
 
   // Only for transactions!
   nsresult DispatchToTransactionPool();
 
--- a/dom/indexedDB/CheckPermissionsHelper.cpp
+++ b/dom/indexedDB/CheckPermissionsHelper.cpp
@@ -86,19 +86,19 @@ GetIndexedDBPermissions(nsIDOMWindow* aW
                                                    &permission);
   NS_ENSURE_SUCCESS(rv, PERMISSION_DENIED);
 
   return permission;
 }
 
 } // anonymous namespace
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(CheckPermissionsHelper, nsIRunnable,
-                                                      nsIInterfaceRequestor,
-                                                      nsIObserver)
+NS_IMPL_ISUPPORTS3(CheckPermissionsHelper, nsIRunnable,
+                   nsIInterfaceRequestor,
+                   nsIObserver)
 
 NS_IMETHODIMP
 CheckPermissionsHelper::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   uint32_t permission = mHasPrompted ?
                         mPromptResult :
--- a/dom/indexedDB/CheckPermissionsHelper.h
+++ b/dom/indexedDB/CheckPermissionsHelper.h
@@ -19,17 +19,17 @@ class nsIThread;
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class CheckPermissionsHelper MOZ_FINAL : public nsIRunnable,
                                          public nsIInterfaceRequestor,
                                          public nsIObserver
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIOBSERVER
 
   CheckPermissionsHelper(OpenDatabaseHelper* aHelper,
                          nsIDOMWindow* aWindow,
                          bool aForDeletion)
   : mHelper(aHelper),
--- a/dom/indexedDB/FileInfo.cpp
+++ b/dom/indexedDB/FileInfo.cpp
@@ -60,18 +60,18 @@ FileInfo::GetReferences(int32_t* aRefCnt
   }
 
   if (aSliceRefCnt) {
     *aSliceRefCnt = mSliceRefCnt;
   }
 }
 
 void
-FileInfo::UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta,
-                           bool aClear)
+FileInfo::UpdateReferences(mozilla::ThreadSafeAutoRefCnt& aRefCount,
+                           int32_t aDelta, bool aClear)
 {
   if (IndexedDatabaseManager::IsClosed()) {
     NS_ERROR("Shouldn't be called after shutdown!");
     return;
   }
 
   bool needsCleanup;
   {
--- a/dom/indexedDB/FileInfo.h
+++ b/dom/indexedDB/FileInfo.h
@@ -4,17 +4,16 @@
  * 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 mozilla_dom_indexeddb_fileinfo_h__
 #define mozilla_dom_indexeddb_fileinfo_h__
 
 #include "IndexedDatabase.h"
 
-#include "nsAtomicRefcnt.h"
 #include "nsThreadUtils.h"
 
 #include "FileManager.h"
 #include "IndexedDatabaseManager.h"
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class FileInfo
@@ -30,27 +29,27 @@ public:
   { }
 
   static
   FileInfo* Create(FileManager* aFileManager, int64_t aId);
 
   void AddRef()
   {
     if (IndexedDatabaseManager::IsClosed()) {
-      NS_AtomicIncrementRefcnt(mRefCnt);
+      ++mRefCnt;
     }
     else {
       UpdateReferences(mRefCnt, 1);
     }
   }
 
   void Release()
   {
     if (IndexedDatabaseManager::IsClosed()) {
-      nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
+      nsrefcnt count = --mRefCnt;
       if (count == 0) {
         mRefCnt = 1;
         delete this;
       }
     }
     else {
       UpdateReferences(mRefCnt, -1);
     }
@@ -77,23 +76,23 @@ public:
   FileManager* Manager() const
   {
     return mFileManager;
   }
 
   virtual int64_t Id() const = 0;
 
 private:
-  void UpdateReferences(nsAutoRefCnt& aRefCount, int32_t aDelta,
+  void UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, int32_t aDelta,
                         bool aClear = false);
   void Cleanup();
 
-  nsAutoRefCnt mRefCnt;
-  nsAutoRefCnt mDBRefCnt;
-  nsAutoRefCnt mSliceRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mDBRefCnt;
+  ThreadSafeAutoRefCnt mSliceRefCnt;
 
   nsRefPtr<FileManager> mFileManager;
 };
 
 #define FILEINFO_SUBCLASS(_bits)                                              \
 class FileInfo##_bits : public FileInfo                                       \
 {                                                                             \
 public:                                                                       \
--- a/dom/indexedDB/IDBEvents.h
+++ b/dom/indexedDB/IDBEvents.h
@@ -56,17 +56,17 @@ public:
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE
   {
     return mozilla::dom::IDBVersionChangeEventBinding::Wrap(aCx, aScope, this);
   }
 
   static already_AddRefed<IDBVersionChangeEvent>
   Constructor(const GlobalObject& aGlobal,
-              const NonNull<nsAString>& aType,
+              const nsAString& aType,
               const IDBVersionChangeEventInit& aOptions,
               ErrorResult& aRv)
   {
     uint64_t newVersion = 0;
     if (!aOptions.mNewVersion.IsNull()) {
       newVersion = aOptions.mNewVersion.Value();
     }
     nsCOMPtr<EventTarget> target = do_QueryInterface(aGlobal.Get());
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -642,31 +642,31 @@ IDBFactory::Cmp(JSContext* aCx, JS::Hand
     return 0;
   }
 
   return Key::CompareKeys(first, second);
 }
 
 already_AddRefed<nsIIDBOpenDBRequest>
 IDBFactory::OpenForPrincipal(nsIPrincipal* aPrincipal,
-                             const NonNull<nsAString>& aName,
+                             const nsAString& aName,
                              const Optional<uint64_t>& aVersion,
                              ErrorResult& aRv)
 {
   // Just to be on the extra-safe side
   if (!nsContentUtils::IsCallerChrome()) {
     MOZ_CRASH();
   }
 
   return Open(aPrincipal, aName, aVersion, false, aRv);
 }
 
 already_AddRefed<nsIIDBOpenDBRequest>
 IDBFactory::DeleteForPrincipal(nsIPrincipal* aPrincipal,
-                               const NonNull<nsAString>& aName,
+                               const nsAString& aName,
                                ErrorResult& aRv)
 {
   // Just to be on the extra-safe side
   if (!nsContentUtils::IsCallerChrome()) {
     MOZ_CRASH();
   }
 
   return Open(aPrincipal, aName, Optional<uint64_t>(), true, aRv);
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -136,38 +136,38 @@ public:
     return mWindow;
   }
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   // WebIDL
   already_AddRefed<nsIIDBOpenDBRequest>
-  Open(const NonNull<nsAString>& aName, const Optional<uint64_t>& aVersion,
+  Open(const nsAString& aName, const Optional<uint64_t>& aVersion,
        ErrorResult& aRv)
   {
     return Open(nullptr, aName, aVersion, false, aRv);
   }
 
   already_AddRefed<nsIIDBOpenDBRequest>
-  DeleteDatabase(const NonNull<nsAString>& aName, ErrorResult& aRv)
+  DeleteDatabase(const nsAString& aName, ErrorResult& aRv)
   {
     return Open(nullptr, aName, Optional<uint64_t>(), true, aRv);
   }
 
   int16_t
   Cmp(JSContext* aCx, JS::Handle<JS::Value> aFirst,
       JS::Handle<JS::Value> aSecond, ErrorResult& aRv);
 
   already_AddRefed<nsIIDBOpenDBRequest>
-  OpenForPrincipal(nsIPrincipal* aPrincipal, const NonNull<nsAString>& aName,
+  OpenForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
                    const Optional<uint64_t>& aVersion, ErrorResult& aRv);
 
   already_AddRefed<nsIIDBOpenDBRequest>
-  DeleteForPrincipal(nsIPrincipal* aPrincipal, const NonNull<nsAString>& aName,
+  DeleteForPrincipal(nsIPrincipal* aPrincipal, const nsAString& aName,
                      ErrorResult& aRv);
 
 private:
   IDBFactory();
   ~IDBFactory();
 
   already_AddRefed<nsIIDBOpenDBRequest>
   Open(nsIPrincipal* aPrincipal, const nsAString& aName,
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -815,17 +815,17 @@ CommitHelper::CommitHelper(IDBTransactio
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 }
 
 CommitHelper::~CommitHelper()
 {
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(CommitHelper, nsIRunnable)
+NS_IMPL_ISUPPORTS1(CommitHelper, nsIRunnable)
 
 NS_IMETHODIMP
 CommitHelper::Run()
 {
   if (NS_IsMainThread()) {
     PROFILER_MAIN_THREAD_LABEL("IndexedDB", "CommitHelper::Run");
 
     NS_ASSERTION(mDoomedObjects.IsEmpty(), "Didn't release doomed objects!");
@@ -1016,17 +1016,17 @@ CommitHelper::RevertAutoIncrementCounts(
 nsresult
 UpdateRefcountFunction::Init()
 {
   mFileInfoEntries.Init();
 
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(UpdateRefcountFunction, mozIStorageFunction)
+NS_IMPL_ISUPPORTS1(UpdateRefcountFunction, mozIStorageFunction)
 
 NS_IMETHODIMP
 UpdateRefcountFunction::OnFunctionCall(mozIStorageValueArray* aValues,
                                        nsIVariant** _retval)
 {
   *_retval = nullptr;
 
   uint32_t numEntries;
--- a/dom/indexedDB/IDBTransaction.h
+++ b/dom/indexedDB/IDBTransaction.h
@@ -276,17 +276,17 @@ private:
 #ifdef DEBUG
   bool mFiredCompleteOrAbort;
 #endif
 };
 
 class CommitHelper MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   CommitHelper(IDBTransaction* aTransaction,
                IDBTransactionListener* aListener,
                const nsTArray<nsRefPtr<IDBObjectStore> >& mUpdatedObjectStores);
   CommitHelper(IDBTransaction* aTransaction,
                nsresult aAbortCode);
   ~CommitHelper();
@@ -322,17 +322,17 @@ private:
   nsAutoTArray<nsRefPtr<IDBObjectStore>, 10> mAutoIncrementObjectStores;
 
   nsresult mAbortCode;
 };
 
 class UpdateRefcountFunction MOZ_FINAL : public mozIStorageFunction
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_MOZISTORAGEFUNCTION
 
   UpdateRefcountFunction(FileManager* aFileManager)
   : mFileManager(aFileManager)
   { }
 
   ~UpdateRefcountFunction()
   { }
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/quota/Utilities.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/Services.h"
 #include "mozilla/storage.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsThreadUtils.h"
+#include "pratom.h"
 
 #include "IDBEvents.h"
 #include "IDBFactory.h"
 #include "IDBKeyRange.h"
 #include "IDBRequest.h"
 
 // The two possible values for the data argument when receiving the disk space
 // observer notification.
@@ -46,30 +47,30 @@ namespace {
 mozilla::StaticRefPtr<IndexedDatabaseManager> gInstance;
 
 int32_t gInitialized = 0;
 int32_t gClosed = 0;
 
 class AsyncDeleteFileRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   AsyncDeleteFileRunnable(FileManager* aFileManager, int64_t aFileId);
 
 private:
   nsRefPtr<FileManager> mFileManager;
   int64_t mFileId;
 };
 
 class GetFileReferencesHelper MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   GetFileReferencesHelper(const nsACString& aOrigin,
                           const nsAString& aDatabaseName,
                           int64_t aFileId)
   : mOrigin(aOrigin), mDatabaseName(aDatabaseName), mFileId(aFileId),
     mMutex(IndexedDatabaseManager::FileMutex()),
     mCondVar(mMutex, "GetFileReferencesHelper::mCondVar"),
@@ -606,18 +607,18 @@ IndexedDatabaseManager::Observe(nsISuppo
  }
 
 AsyncDeleteFileRunnable::AsyncDeleteFileRunnable(FileManager* aFileManager,
                                                  int64_t aFileId)
 : mFileManager(aFileManager), mFileId(aFileId)
 {
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(AsyncDeleteFileRunnable,
-                              nsIRunnable)
+NS_IMPL_ISUPPORTS1(AsyncDeleteFileRunnable,
+                   nsIRunnable)
 
 NS_IMETHODIMP
 AsyncDeleteFileRunnable::Run()
 {
   AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory = mFileManager->GetDirectory();
   NS_ENSURE_TRUE(directory, NS_ERROR_FAILURE);
@@ -678,18 +679,18 @@ GetFileReferencesHelper::DispatchAndRetu
   *aMemRefCnt = mMemRefCnt;
   *aDBRefCnt = mDBRefCnt;
   *aSliceRefCnt = mSliceRefCnt;
   *aResult = mResult;
 
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(GetFileReferencesHelper,
-                              nsIRunnable)
+NS_IMPL_ISUPPORTS1(GetFileReferencesHelper,
+                   nsIRunnable)
 
 NS_IMETHODIMP
 GetFileReferencesHelper::Run()
 {
   AssertIsOnIOThread();
 
   IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get();
   NS_ASSERTION(mgr, "This should never fail!");
--- a/dom/indexedDB/OpenDatabaseHelper.cpp
+++ b/dom/indexedDB/OpenDatabaseHelper.cpp
@@ -1675,17 +1675,17 @@ private:
   nsRefPtr<IDBOpenDBRequest> mRequest;
   nsTArray<nsCOMPtr<nsIOfflineStorage> > mWaitingDatabases;
   int64_t mOldVersion;
   int64_t mNewVersion;
 };
 
 } // anonymous namespace
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable)
+NS_IMPL_ISUPPORTS1(OpenDatabaseHelper, nsIRunnable)
 
 nsresult
 OpenDatabaseHelper::Init()
 {
   mDatabaseId = QuotaManager::GetStorageId(mASCIIOrigin, mName);
   NS_ENSURE_TRUE(mDatabaseId, NS_ERROR_FAILURE);
 
   return NS_OK;
--- a/dom/indexedDB/OpenDatabaseHelper.h
+++ b/dom/indexedDB/OpenDatabaseHelper.h
@@ -48,17 +48,17 @@ public:
       mLastIndexId(0), mState(eCreated), mResultCode(NS_OK),
       mLoadDBMetadata(false),
       mTrackingQuota(aPrivilege != mozilla::dom::quota::Chrome)
   {
     NS_ASSERTION(!aForDeletion || !aRequestedVersion,
                  "Can't be for deletion and request a version!");
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   nsresult Init();
 
   nsresult Dispatch(nsIEventTarget* aDatabaseThread);
   nsresult RunImmediately();
 
   void SetError(nsresult rv)
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -29,34 +29,34 @@ const uint32_t kIdleThreadTimeoutMs = 30
 TransactionThreadPool* gInstance = nullptr;
 bool gShutdown = false;
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
 
 class TransactionThreadPoolListener : public nsIThreadPoolListener
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITHREADPOOLLISTENER
 
 private:
   virtual ~TransactionThreadPoolListener()
   { }
 };
 
 #endif // MOZ_ENABLE_PROFILER_SPS
 
 } // anonymous namespace
 
 BEGIN_INDEXEDDB_NAMESPACE
 
 class FinishTransactionRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   inline FinishTransactionRunnable(IDBTransaction* aTransaction,
                                    nsCOMPtr<nsIRunnable>& aFinishRunnable);
 
 private:
   IDBTransaction* mTransaction;
   nsCOMPtr<nsIRunnable> mFinishRunnable;
@@ -561,18 +561,17 @@ TransactionThreadPool::TransactionQueue:
   NS_ASSERTION(!mShouldFinish, "Finish called more than once!");
 
   mShouldFinish = true;
   mFinishRunnable = aFinishRunnable;
 
   mMonitor.Notify();
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(TransactionThreadPool::TransactionQueue,
-                              nsIRunnable)
+NS_IMPL_ISUPPORTS1(TransactionThreadPool::TransactionQueue, nsIRunnable)
 
 NS_IMETHODIMP
 TransactionThreadPool::TransactionQueue::Run()
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
 
   PROFILER_LABEL("IndexedDB", "TransactionQueue::Run");
@@ -634,17 +633,17 @@ FinishTransactionRunnable::FinishTransac
                                          nsCOMPtr<nsIRunnable>& aFinishRunnable)
 : mTransaction(aTransaction)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aTransaction, "Null pointer!");
   mFinishRunnable.swap(aFinishRunnable);
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(FinishTransactionRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(FinishTransactionRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 FinishTransactionRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   PROFILER_MAIN_THREAD_LABEL("IndexedDB", "FinishTransactionRunnable::Run");
 
@@ -660,18 +659,17 @@ FinishTransactionRunnable::Run()
     mFinishRunnable = nullptr;
   }
 
   return NS_OK;
 }
 
 #ifdef MOZ_ENABLE_PROFILER_SPS
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(TransactionThreadPoolListener,
-                              nsIThreadPoolListener)
+NS_IMPL_ISUPPORTS1(TransactionThreadPoolListener, nsIThreadPoolListener)
 
 NS_IMETHODIMP
 TransactionThreadPoolListener::OnThreadCreated()
 {
   MOZ_ASSERT(!NS_IsMainThread());
   char aLocal;
   profiler_register_thread("IndexedDB Transaction", &aLocal);
   return NS_OK;
--- a/dom/indexedDB/TransactionThreadPool.h
+++ b/dom/indexedDB/TransactionThreadPool.h
@@ -54,17 +54,17 @@ public:
 
   // Returns true if there are running or pending transactions for aDatabase.
   bool HasTransactionsForDatabase(IDBDatabase* aDatabase);
 
 protected:
   class TransactionQueue MOZ_FINAL : public nsIRunnable
   {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIRUNNABLE
 
     TransactionQueue(IDBTransaction* aTransaction);
 
     void Unblock();
 
     void Dispatch(nsIRunnable* aRunnable);
 
--- a/dom/ipc/Blob.cpp
+++ b/dom/ipc/Blob.cpp
@@ -55,17 +55,17 @@ class RemoteInputStream : public nsIInpu
 {
   mozilla::Monitor mMonitor;
   nsCOMPtr<nsIDOMBlob> mSourceBlob;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
   ActorFlavorEnum mOrigin;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   RemoteInputStream(nsIDOMBlob* aSourceBlob, ActorFlavorEnum aOrigin)
   : mMonitor("RemoteInputStream.mMonitor"), mSourceBlob(aSourceBlob),
     mOrigin(aOrigin)
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aSourceBlob);
   }
@@ -307,18 +307,18 @@ private:
     else {
       ReallyBlockAndWaitForStream();
     }
 
     return !!mSeekableStream;
   }
 };
 
-NS_IMPL_THREADSAFE_ADDREF(RemoteInputStream)
-NS_IMPL_THREADSAFE_RELEASE(RemoteInputStream)
+NS_IMPL_ADDREF(RemoteInputStream)
+NS_IMPL_RELEASE(RemoteInputStream)
 
 NS_INTERFACE_MAP_BEGIN(RemoteInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableInputStream)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsISeekableStream, IsSeekableStream())
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIInputStream)
   NS_INTERFACE_MAP_ENTRY(IPrivateRemoteInputStream)
 NS_INTERFACE_MAP_END
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1567,20 +1567,20 @@ ContentParent::RecvRecordingDeviceEvents
     if (obs) {
         obs->NotifyObservers(nullptr, "recording-device-events", aRecordingStatus.get());
     } else {
         NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
     }
     return true;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(ContentParent,
-                              nsIObserver,
-                              nsIThreadObserver,
-                              nsIDOMGeoPositionCallback)
+NS_IMPL_ISUPPORTS3(ContentParent,
+                   nsIObserver,
+                   nsIThreadObserver,
+                   nsIDOMGeoPositionCallback)
 
 NS_IMETHODIMP
 ContentParent::Observe(nsISupports* aSubject,
                        const char* aTopic,
                        const PRUnichar* aData)
 {
     if (!strcmp(aTopic, "xpcom-shutdown") && mSubprocess) {
         ShutDownProcess(/* closeWithError */ false);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -103,17 +103,17 @@ public:
      */
     static TabParent*
     CreateBrowserOrApp(const TabContext& aContext,
                        nsIDOMElement* aFrameElement);
 
     static void GetAll(nsTArray<ContentParent*>& aArray);
     static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIDOMGEOPOSITIONCALLBACK
 
     /**
      * MessageManagerCallback methods that we override.
      */
     virtual bool DoSendAsyncMessage(JSContext* aCx,
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -225,17 +225,17 @@ public:
 protected:
   uint64_t mWindowID;
   nsRefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
 };
 
 /**
  * nsIMediaDevice implementation.
  */
-NS_IMPL_THREADSAFE_ISUPPORTS1(MediaDevice, nsIMediaDevice)
+NS_IMPL_ISUPPORTS1(MediaDevice, nsIMediaDevice)
 
 NS_IMETHODIMP
 MediaDevice::GetName(nsAString& aName)
 {
   aName.Assign(mName);
   return NS_OK;
 }
 
@@ -888,17 +888,17 @@ MediaManager::MediaManager()
   }
   LOG(("%s: default prefs: %dx%d @%dfps (min %d)", __FUNCTION__,
        mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS));
 
   mActiveWindows.Init();
   mActiveCallbacks.Init();
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(MediaManager, nsIMediaManagerService, nsIObserver)
+NS_IMPL_ISUPPORTS2(MediaManager, nsIMediaManagerService, nsIObserver)
 
 /* static */ StaticRefPtr<MediaManager> MediaManager::sSingleton;
 
 // NOTE: never Dispatch(....,NS_DISPATCH_SYNC) to the MediaManager
 // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
 // from MediaManager thread.
 /* static */  MediaManager*
 MediaManager::Get() {
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -380,17 +380,17 @@ private:
 };
 
 typedef nsTArray<nsRefPtr<GetUserMediaCallbackMediaStreamListener> > StreamListeners;
 typedef nsClassHashtable<nsUint64HashKey, StreamListeners> WindowTable;
 
 class MediaDevice : public nsIMediaDevice
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIMEDIADEVICE
 
   MediaDevice(MediaEngineVideoSource* aSource) {
     mSource = aSource;
     mType.Assign(NS_LITERAL_STRING("video"));
     mSource->GetName(mName);
     mSource->GetUUID(mID);
   }
@@ -420,17 +420,17 @@ public:
   // thread from the MainThread, as we NS_DISPATCH_SYNC to MainThread
   // from MediaManager thread.
   static MediaManager* Get();
 
   static nsIThread* GetThread() {
     return Get()->mMediaThread;
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIMEDIAMANAGERSERVICE
 
   MediaEngine* GetBackend(uint64_t aWindowId = 0);
   StreamListeners *GetWindowListeners(uint64_t aWindowId) {
     NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
 
     return mActiveWindows.Get(aWindowId);
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -159,19 +159,19 @@ JSClass sNPObjectJSWrapperClass =
     NPObjWrapper_Finalize,
     nullptr,                                                /* checkAccess */
     NPObjWrapper_Call,
     nullptr,                                                /* hasInstance */
     NPObjWrapper_Construct
   };
 
 typedef struct NPObjectMemberPrivate {
-    JSObject *npobjWrapper;
-    JS::Value fieldValue;
-    NPIdentifier methodName;
+    JS::Heap<JSObject *> npobjWrapper;
+    JS::Heap<JS::Value> fieldValue;
+    JS::Heap<jsid> methodName;
     NPP   npp;
 } NPObjectMemberPrivate;
 
 static JSBool
 NPObjectMember_Convert(JSContext *cx, JS::Handle<JSObject*> obj, JSType type, JS::MutableHandle<JS::Value> vp);
 
 static void
 NPObjectMember_Finalize(JSFreeOp *fop, JSObject *obj);
@@ -2012,17 +2012,17 @@ CreateNPObjectMember(NPP npp, JSContext 
   // npobjWrapper is the JSObject through which we make sure we don't
   // outlive the underlying NPObject, so make sure it points to the
   // real JSObject wrapper for the NPObject.
   obj = GetNPObjectWrapper(cx, obj);
 
   memberPrivate->npobjWrapper = obj;
 
   memberPrivate->fieldValue = fieldValue;
-  memberPrivate->methodName = identifier;
+  memberPrivate->methodName = id;
   memberPrivate->npp = npp;
 
   ::JS_RemoveValueRoot(cx, vp);
 
   return JS_TRUE;
 }
 
 static JSBool
@@ -2119,17 +2119,17 @@ NPObjectMember_Call(JSContext *cx, unsig
 
       return JS_FALSE;
     }
   }
 
 
   NPVariant npv;
   JSBool ok;
-  ok = npobj->_class->invoke(npobj, memberPrivate->methodName,
+  ok = npobj->_class->invoke(npobj, JSIdToNPIdentifier(memberPrivate->methodName),
                              npargs, argc, &npv);
 
   // Release arguments.
   for (i = 0; i < argc; ++i) {
     _releasevariantvalue(npargs + i);
   }
 
   if (npargs != npargs_buf) {
@@ -2157,25 +2157,23 @@ static void
 NPObjectMember_Trace(JSTracer *trc, JSObject *obj)
 {
   NPObjectMemberPrivate *memberPrivate =
     (NPObjectMemberPrivate *)::JS_GetPrivate(obj);
   if (!memberPrivate)
     return;
 
   // Our NPIdentifier is not always interned, so we must root it explicitly.
-  jsid id = NPIdentifierToJSId(memberPrivate->methodName);
-  JS_CallIdTracer(trc, &id, "NPObjectMemberPrivate.methodName");
-  memberPrivate->methodName = JSIdToNPIdentifier(id);
+  JS_CallHeapIdTracer(trc, &memberPrivate->methodName, "NPObjectMemberPrivate.methodName");
 
   if (!JSVAL_IS_PRIMITIVE(memberPrivate->fieldValue)) {
-    JS_CallValueTracer(trc, &memberPrivate->fieldValue,
-                       "NPObject Member => fieldValue");
+    JS_CallHeapValueTracer(trc, &memberPrivate->fieldValue,
+                           "NPObject Member => fieldValue");
   }
 
   // There's no strong reference from our private data to the
   // NPObject, so make sure to mark the NPObject wrapper to keep the
   // NPObject alive as long as this NPObjectMember is alive.
   if (memberPrivate->npobjWrapper) {
-    JS_CallObjectTracer(trc, &memberPrivate->npobjWrapper,
-                        "NPObject Member => npobjWrapper");
+    JS_CallHeapObjectTracer(trc, &memberPrivate->npobjWrapper,
+                            "NPObject Member => npobjWrapper");
   }
 }
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -3,16 +3,17 @@
  * 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 "base/basictypes.h"
 
 /* This must occur *after* layers/PLayerTransaction.h to avoid typedefs conflicts. */
 #include "mozilla/Util.h"
 
+#include "pratom.h"
 #include "prmem.h"
 #include "prenv.h"
 #include "prclist.h"
 
 #include "jsfriendapi.h"
 
 #include "nsPluginHost.h"
 #include "nsNPAPIPlugin.h"
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -157,17 +157,17 @@ static std::map<NPP, nsNPAPIPluginInstan
 #endif
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 using namespace mozilla::layers;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 
-NS_IMPL_THREADSAFE_ISUPPORTS0(nsNPAPIPluginInstance)
+NS_IMPL_ISUPPORTS0(nsNPAPIPluginInstance)
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance()
   :
     mDrawingModel(kDefaultDrawingModel),
 #ifdef MOZ_WIDGET_ANDROID
     mANPDrawingModel(0),
     mFullScreenOrientation(dom::eScreenOrientation_LandscapePrimary),
     mWakeLocked(false),
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -76,17 +76,17 @@ public:
 };
 
 class nsNPAPIPluginInstance : public nsISupports
 {
 private:
   typedef mozilla::PluginLibrary PluginLibrary;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   nsresult Initialize(nsNPAPIPlugin *aPlugin, nsPluginInstanceOwner* aOwner, const char* aMIMEType);
   nsresult Start();
   nsresult Stop();
   nsresult SetWindow(NPWindow* window);
   nsresult NewStreamFromPlugin(const char* type, const char* target, nsIOutputStream* *result);
   nsresult Print(NPPrint* platformPrint);
   nsresult HandleEvent(void* event, int16_t* result,
--- a/dom/plugins/base/nsPluginDirServiceProvider.cpp
+++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
@@ -172,18 +172,18 @@ nsPluginDirServiceProvider::nsPluginDirS
 nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
 {
 }
 
 //*****************************************************************************
 // nsPluginDirServiceProvider::nsISupports
 //*****************************************************************************
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsPluginDirServiceProvider,
-                              nsIDirectoryServiceProvider)
+NS_IMPL_ISUPPORTS1(nsPluginDirServiceProvider,
+                   nsIDirectoryServiceProvider)
 
 //*****************************************************************************
 // nsPluginDirServiceProvider::nsIDirectoryServiceProvider
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsPluginDirServiceProvider::GetFile(const char *charProp, bool *persistant,
                                     nsIFile **_retval)
--- a/dom/plugins/base/nsPluginDirServiceProvider.h
+++ b/dom/plugins/base/nsPluginDirServiceProvider.h
@@ -24,17 +24,17 @@ class nsISimpleEnumerator;
 // class nsPluginDirServiceProvider
 //*****************************************************************************   
 
 class nsPluginDirServiceProvider : public nsIDirectoryServiceProvider
 {
 public:
    nsPluginDirServiceProvider();
    
-   NS_DECL_ISUPPORTS
+   NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSIDIRECTORYSERVICEPROVIDER
 
 #ifdef XP_WIN
    static nsresult GetPLIDDirectories(nsISimpleEnumerator **aEnumerator);
 private:
    static nsresult GetPLIDDirectoriesWithRootKey(uint32_t aKey,
      nsCOMArray<nsIFile> &aDirs);
 #endif
--- a/dom/quota/CheckQuotaHelper.cpp
+++ b/dom/quota/CheckQuotaHelper.cpp
@@ -132,19 +132,19 @@ CheckQuotaHelper::GetQuotaPermission(nsI
   nsresult rv = pm->TestPermissionFromPrincipal(aPrincipal,
                                                 PERMISSION_INDEXEDDB_UNLIMITED,
                                                 &permission);
   NS_ENSURE_SUCCESS(rv, nsIPermissionManager::DENY_ACTION);
 
   return permission;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(CheckQuotaHelper, nsIRunnable,
-                                                nsIInterfaceRequestor,
-                                                nsIObserver)
+NS_IMPL_ISUPPORTS3(CheckQuotaHelper, nsIRunnable,
+                   nsIInterfaceRequestor,
+                   nsIObserver)
 
 NS_IMETHODIMP
 CheckQuotaHelper::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsresult rv = NS_OK;
 
--- a/dom/quota/CheckQuotaHelper.h
+++ b/dom/quota/CheckQuotaHelper.h
@@ -21,17 +21,17 @@ class nsPIDOMWindow;
 
 BEGIN_QUOTA_NAMESPACE
 
 class CheckQuotaHelper MOZ_FINAL : public nsIRunnable,
                                    public nsIInterfaceRequestor,
                                    public nsIObserver
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSIOBSERVER
 
   CheckQuotaHelper(nsPIDOMWindow* aWindow,
                    mozilla::Mutex& aMutex);
 
   bool PromptAndReturnQuotaIsDisabled();
--- a/dom/quota/QuotaManager.cpp
+++ b/dom/quota/QuotaManager.cpp
@@ -31,16 +31,17 @@
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsCRTGlue.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsScriptSecurityManager.h"
 #include "nsThreadUtils.h"
 #include "nsXULAppAPI.h"
+#include "pratom.h"
 #include "xpcpublic.h"
 
 #include "AcquireListener.h"
 #include "CheckQuotaHelper.h"
 #include "OriginOrPatternString.h"
 #include "QuotaObject.h"
 #include "StorageMatcher.h"
 #include "UsageRunnable.h"
@@ -119,17 +120,17 @@ class OriginClearRunnable MOZ_FINAL : pu
     // Running on the IO thread.
     IO,
 
     // Running on the main thread after all work is done.
     Complete
   };
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   // AcquireListener override
   virtual nsresult
   OnExclusiveAccessAcquired() MOZ_OVERRIDE;
 
   OriginClearRunnable(const OriginOrPatternString& aOriginOrPattern)
   : mOriginOrPattern(aOriginOrPattern),
@@ -191,17 +192,17 @@ class AsyncUsageRunnable MOZ_FINAL : pub
     // Running on the main thread after all work is done.
     Complete,
 
     // Running on the main thread after skipping the work
     Shortcut
   };
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIQUOTAREQUEST
 
   AsyncUsageRunnable(uint32_t aAppId,
                      bool aInMozBrowserOnly,
                      const OriginOrPatternString& aOrigin,
                      nsIURI* aURI,
                      nsIUsageCallback* aCallback);
@@ -273,17 +274,17 @@ public:
   {
     NS_ASSERTION(mOp, "Why don't we have a runnable?");
     NS_ASSERTION(mOp->mStorages.IsEmpty(), "We're here too early!");
     NS_ASSERTION(mOp->mListener,
                  "What are we supposed to do when we're done?");
     NS_ASSERTION(mCountdown, "Wrong countdown!");
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   void
   AddRun()
   {
     mCountdown++;
   }
 
@@ -295,17 +296,17 @@ private:
 
 class WaitForLockedFilesToFinishRunnable MOZ_FINAL : public nsIRunnable
 {
 public:
   WaitForLockedFilesToFinishRunnable()
   : mBusy(true)
   { }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   bool
   IsBusy() const
   {
     return mBusy;
   }
 
@@ -1894,17 +1895,17 @@ OriginClearRunnable::DeleteFiles(QuotaMa
     }
   }
 
   aQuotaManager->RemoveQuotaForPattern(mOriginOrPattern);
 
   aQuotaManager->OriginClearCompleted(mOriginOrPattern);
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(OriginClearRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(OriginClearRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 OriginClearRunnable::Run()
 {
   PROFILER_LABEL("Quota", "OriginClearRunnable::Run");
 
   QuotaManager* quotaManager = QuotaManager::Get();
   NS_ASSERTION(quotaManager, "This should never fail!");
@@ -2138,19 +2139,19 @@ AsyncUsageRunnable::RunInternal()
       NS_ERROR("Unknown state value!");
       return NS_ERROR_UNEXPECTED;
   }
 
   NS_NOTREACHED("Should never get here!");
   return NS_ERROR_UNEXPECTED;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(AsyncUsageRunnable,
-                              nsIRunnable,
-                              nsIQuotaRequest)
+NS_IMPL_ISUPPORTS2(AsyncUsageRunnable,
+                   nsIRunnable,
+                   nsIQuotaRequest)
 
 NS_IMETHODIMP
 AsyncUsageRunnable::Run()
 {
   PROFILER_LABEL("Quota", "AsyncUsageRunnable::Run");
 
   nsresult rv = RunInternal();
 
@@ -2173,17 +2174,17 @@ AsyncUsageRunnable::Cancel()
   if (PR_ATOMIC_SET(&mCanceled, 1)) {
     NS_WARNING("Canceled more than once?!");
     return NS_ERROR_UNEXPECTED;
   }
 
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(WaitForTransactionsToFinishRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(WaitForTransactionsToFinishRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 WaitForTransactionsToFinishRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mOp, "Null op!");
   NS_ASSERTION(mOp->mListener, "Nothing to run!");
   NS_ASSERTION(mCountdown, "Wrong countdown!");
@@ -2201,17 +2202,17 @@ WaitForTransactionsToFinishRunnable::Run
   nsresult rv = listener->OnExclusiveAccessAcquired();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // The listener is responsible for calling
   // QuotaManager::AllowNextSynchronizedOp.
   return NS_OK;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(WaitForLockedFilesToFinishRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(WaitForLockedFilesToFinishRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 WaitForLockedFilesToFinishRunnable::Run()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   mBusy = false;
 
--- a/dom/quota/QuotaObject.cpp
+++ b/dom/quota/QuotaObject.cpp
@@ -12,34 +12,34 @@ USING_QUOTA_NAMESPACE
 
 void
 QuotaObject::AddRef()
 {
   QuotaManager* quotaManager = QuotaManager::Get();
   if (!quotaManager) {
     NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
 
-    NS_AtomicIncrementRefcnt(mRefCnt);
+    ++mRefCnt;
 
     return;
   }
 
   MutexAutoLock lock(quotaManager->mQuotaMutex);
 
   ++mRefCnt;
 }
 
 void
 QuotaObject::Release()
 {
   QuotaManager* quotaManager = QuotaManager::Get();
   if (!quotaManager) {
     NS_ERROR("Null quota manager, this shouldn't happen, possible leak!");
 
-    nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
+    nsrefcnt count = --mRefCnt;
     if (count == 0) {
       mRefCnt = 1;
       delete this;
     }
 
     return;
   }
 
--- a/dom/quota/QuotaObject.h
+++ b/dom/quota/QuotaObject.h
@@ -37,17 +37,17 @@ public:
 private:
   QuotaObject(OriginInfo* aOriginInfo, const nsAString& aPath, int64_t aSize)
   : mOriginInfo(aOriginInfo), mPath(aPath), mSize(aSize)
   { }
 
   virtual ~QuotaObject()
   { }
 
-  nsAutoRefCnt mRefCnt;
+  mozilla::ThreadSafeAutoRefCnt mRefCnt;
 
   OriginInfo* mOriginInfo;
   nsString mPath;
   int64_t mSize;
 };
 
 class OriginInfo
 {
--- a/dom/src/geolocation/nsGeoPosition.cpp
+++ b/dom/src/geolocation/nsGeoPosition.cpp
@@ -32,18 +32,18 @@ nsGeoPositionCoords::~nsGeoPositionCoord
 {
 }
 
 NS_INTERFACE_MAP_BEGIN(nsGeoPositionCoords)
 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPositionCoords)
 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCoords)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPositionCoords)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPositionCoords)
+NS_IMPL_ADDREF(nsGeoPositionCoords)
+NS_IMPL_RELEASE(nsGeoPositionCoords)
 
 NS_IMETHODIMP
 nsGeoPositionCoords::GetLatitude(double *aLatitude)
 {
   *aLatitude = mLat;
   return NS_OK;
 }
 
@@ -123,18 +123,18 @@ nsGeoPosition::~nsGeoPosition()
 {
 }
 
 NS_INTERFACE_MAP_BEGIN(nsGeoPosition)
 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoPosition)
 NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPosition)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_THREADSAFE_ADDREF(nsGeoPosition)
-NS_IMPL_THREADSAFE_RELEASE(nsGeoPosition)
+NS_IMPL_ADDREF(nsGeoPosition)
+NS_IMPL_RELEASE(nsGeoPosition)
 
 NS_IMETHODIMP
 nsGeoPosition::GetTimestamp(DOMTimeStamp* aTimestamp)
 {
   *aTimestamp = mTimestamp;
   return NS_OK;
 }
 
--- a/dom/src/geolocation/nsGeoPosition.h
+++ b/dom/src/geolocation/nsGeoPosition.h
@@ -22,17 +22,17 @@ struct JSContext;
 ////////////////////////////////////////////////////
 
 /**
  * Simple object that holds a single point in space.
  */
 class nsGeoPositionCoords MOZ_FINAL : public nsIDOMGeoPositionCoords
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIDOMGEOPOSITIONCOORDS
   
   nsGeoPositionCoords(double aLat, double aLong,
                       double aAlt, double aHError,
                       double aVError, double aHeading,
                       double aSpeed);
   ~nsGeoPositionCoords();
 private:
@@ -42,17 +42,17 @@ private:
 
 ////////////////////////////////////////////////////
 // nsGeoPosition
 ////////////////////////////////////////////////////
 
 class nsGeoPosition MOZ_FINAL : public nsIDOMGeoPosition
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIDOMGEOPOSITION
   
   nsGeoPosition(double aLat, double aLong,
                 double aAlt, double aHError,
                 double aVError, double aHeading,
                 double aSpeed, long long aTimestamp);
   
 
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -606,18 +606,18 @@ bool nsGeolocationRequest::Recv__delete_
 // nsGeolocationService
 ////////////////////////////////////////////////////
 NS_INTERFACE_MAP_BEGIN(nsGeolocationService)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIGeolocationUpdate)
   NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_THREADSAFE_ADDREF(nsGeolocationService)
-NS_IMPL_THREADSAFE_RELEASE(nsGeolocationService)
+NS_IMPL_ADDREF(nsGeolocationService)
+NS_IMPL_RELEASE(nsGeolocationService)
 
 
 static bool sGeoEnabled = true;
 static bool sGeoInitPending = true;
 static bool sGeoIgnoreLocationFilter = false;
 static int32_t sProviderTimeout = 6000; // Time, in milliseconds, to wait for the location provider to spin up.
 
 nsresult nsGeolocationService::Init()
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -103,17 +103,17 @@ class nsGeolocationRequest
  */
 class nsGeolocationService MOZ_FINAL : public nsIGeolocationUpdate, public nsIObserver
 {
 public:
 
   static already_AddRefed<nsGeolocationService> GetGeolocationService();
   static mozilla::StaticRefPtr<nsGeolocationService> sService;
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONUPDATE
   NS_DECL_NSIOBSERVER
 
   nsGeolocationService() {
       mHigherAccuracy = false;
   }
 
   nsresult Init();
--- a/dom/src/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/src/jsurl/nsJSProtocolHandler.cpp
@@ -51,17 +51,17 @@ using mozilla::AutoPushJSContext;
 
 static NS_DEFINE_CID(kJSURICID, NS_JSURI_CID);
 
 class nsJSThunk : public nsIInputStream
 {
 public:
     nsJSThunk();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_FORWARD_SAFE_NSIINPUTSTREAM(mInnerStream)
 
     nsresult Init(nsIURI* uri);
     nsresult EvaluateScript(nsIChannel *aChannel,
                             PopupControlState aPopupState,
                             uint32_t aExecutionPolicy,
                             nsPIDOMWindow *aOriginalInnerWindow);
 
@@ -71,17 +71,17 @@ protected:
     nsCOMPtr<nsIInputStream>    mInnerStream;
     nsCString                   mScript;
     nsCString                   mURL;
 };
 
 //
 // nsISupports implementation...
 //
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSThunk, nsIInputStream)
+NS_IMPL_ISUPPORTS1(nsJSThunk, nsIInputStream)
 
 
 nsJSThunk::nsJSThunk()
 {
 }
 
 nsJSThunk::~nsJSThunk()
 {
--- a/dom/src/storage/DOMStorageCache.cpp
+++ b/dom/src/storage/DOMStorageCache.cpp
@@ -48,25 +48,25 @@ GetDataSetIndex(const DOMStorage* aStora
 {
   return GetDataSetIndex(aStorage->IsPrivate(), aStorage->IsSessionOnly());
 }
 
 } // anon
 
 // DOMStorageCacheBridge
 
-NS_IMPL_THREADSAFE_ADDREF(DOMStorageCacheBridge)
+NS_IMPL_ADDREF(DOMStorageCacheBridge)
 
 // Since there is no consumer of return value of Release, we can turn this 
 // method to void to make implementation of asynchronous DOMStorageCache::Release
 // much simpler.
 NS_IMETHODIMP_(void) DOMStorageCacheBridge::Release(void)
 {
   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
-  nsrefcnt count = NS_AtomicDecrementRefcnt(mRefCnt);
+  nsrefcnt count = --mRefCnt;
   NS_LOG_RELEASE(this, count, "DOMStorageCacheBridge");
   if (0 == count) {
     mRefCnt = 1; /* stabilize */
     /* enable this to find non-threadsafe destructors: */
     /* NS_ASSERT_OWNINGTHREAD(_class); */
     delete (this);
   }
 }
--- a/dom/src/storage/DOMStorageCache.h
+++ b/dom/src/storage/DOMStorageCache.h
@@ -50,17 +50,18 @@ public:
   // to this cache
   virtual void LoadDone(nsresult aRv) = 0;
 
   // Use to synchronously wait until the cache gets fully loaded with data,
   // this method exits after LoadDone has been called
   virtual void LoadWait() = 0;
 
 protected:
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
 };
 
 // Implementation of scope cache that is responsible for preloading data
 // for persistent storage (localStorage) and hold data for non-private,
 // private and session-only cookie modes.  It is also responsible for
 // persisting data changes using the database, works as a write-back cache.
 class DOMStorageCache : public DOMStorageCacheBridge
 {
--- a/dom/src/storage/DOMStorageIPC.cpp
+++ b/dom/src/storage/DOMStorageIPC.cpp
@@ -13,17 +13,17 @@
 
 namespace mozilla {
 namespace dom {
 
 // ----------------------------------------------------------------------------
 // Child
 // ----------------------------------------------------------------------------
 
-NS_IMPL_THREADSAFE_ADDREF(DOMStorageDBChild)
+NS_IMPL_ADDREF(DOMStorageDBChild)
 
 NS_IMETHODIMP_(nsrefcnt) DOMStorageDBChild::Release(void)
 {
   NS_PRECONDITION(0 != mRefCnt, "dup release");
   nsrefcnt count = --mRefCnt;
   NS_LOG_RELEASE(this, count, "DOMStorageDBChild");
   if (count == 1 && mIPCOpen) {
     Send__delete__(this);
@@ -269,18 +269,18 @@ DOMStorageDBChild::RecvError(const nsres
   mStatus = aRv;
   return true;
 }
 
 // ----------------------------------------------------------------------------
 // Parent
 // ----------------------------------------------------------------------------
 
-NS_IMPL_THREADSAFE_ADDREF(DOMStorageDBParent)
-NS_IMPL_THREADSAFE_RELEASE(DOMStorageDBParent)
+NS_IMPL_ADDREF(DOMStorageDBParent)
+NS_IMPL_RELEASE(DOMStorageDBParent)
 
 void
 DOMStorageDBParent::AddIPDLReference()
 {
   NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references");
   mIPCOpen = true;
   AddRef();
 }
--- a/dom/src/storage/DOMStorageIPC.h
+++ b/dom/src/storage/DOMStorageIPC.h
@@ -71,17 +71,18 @@ private:
                     const nsresult& aRv);
   bool RecvScopesHavingData(const InfallibleTArray<nsCString>& aScopes);
   bool RecvLoadUsage(const nsCString& aScope,
                      const int64_t& aUsage);
   bool RecvError(const nsresult& aRv);
 
   nsTHashtable<nsCStringHashKey>& ScopesHavingData();
 
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
 
   // Held to get caches to forward answers to.
   nsRefPtr<DOMLocalStorageManager> mManager;
 
   // Scopes having data hash, for optimization purposes only
   nsTHashtable<nsCStringHashKey> mScopesHavingData;
 
   // List of caches waiting for preload.  This ensures the contract that
@@ -174,17 +175,18 @@ private:
   bool RecvAsyncFlush();
 
   // DOMStorageObserverSink
   virtual nsresult Observe(const char* aTopic, const nsACString& aScopePrefix);
 
 private:
   CacheParentBridge* NewCache(const nsACString& aScope);
 
-  nsAutoRefCnt mRefCnt;
+  ThreadSafeAutoRefCnt mRefCnt;
+  NS_DECL_OWNINGTHREAD
 	
 	// True when IPC channel is open and Send*() methods are OK to use.
   bool mIPCOpen;
 };
 
 } // ::dom
 } // ::mozilla
 
--- a/dom/system/gonk/AutoMounterSetting.cpp
+++ b/dom/system/gonk/AutoMounterSetting.cpp
@@ -32,17 +32,17 @@
 #define MOZSETTINGS_CHANGED       "mozsettings-changed"
 
 namespace mozilla {
 namespace system {
 
 class SettingsServiceCallback MOZ_FINAL : public nsISettingsServiceCallback
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   SettingsServiceCallback() {}
 
   NS_IMETHOD Handle(const nsAString& aName, const JS::Value& aResult)
   {
     if (JSVAL_IS_INT(aResult)) {
       int32_t mode = JSVAL_TO_INT(aResult);
       SetAutoMounterMode(mode);
@@ -52,22 +52,22 @@ public:
 
   NS_IMETHOD HandleError(const nsAString& aName)
   {
     ERR("SettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
     return NS_OK;
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(SettingsServiceCallback, nsISettingsServiceCallback)
+NS_IMPL_ISUPPORTS1(SettingsServiceCallback, nsISettingsServiceCallback)
 
 class CheckVolumeSettingsCallback MOZ_FINAL : public nsISettingsServiceCallback
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   CheckVolumeSettingsCallback(const nsACString& aVolumeName)
   : mVolumeName(aVolumeName) {}
 
   NS_IMETHOD Handle(const nsAString& aName, const JS::Value& aResult)
   {
     if (JSVAL_IS_BOOLEAN(aResult)) {
       bool isSharingEnabled = JSVAL_TO_BOOLEAN(aResult);
@@ -80,17 +80,17 @@ public:
   {
     ERR("CheckVolumeSettingsCallback::HandleError: %s\n", NS_LossyConvertUTF16toASCII(aName).get());
     return NS_OK;
   }
 private:
   nsCString mVolumeName;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
+NS_IMPL_ISUPPORTS1(CheckVolumeSettingsCallback, nsISettingsServiceCallback)
 
 AutoMounterSetting::AutoMounterSetting()
 {
   // Setup an observer to watch changes to the setting
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (!observerService) {
     ERR("GetObserverService failed");
--- a/dom/system/gonk/GonkGPSGeolocationProvider.cpp
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.cpp
@@ -39,20 +39,20 @@
 
 using namespace mozilla;
 
 static const int kDefaultPeriod = 1000; // ms
 
 // While most methods of GonkGPSGeolocationProvider should only be
 // called from main thread, we deliberately put the Init and ShutdownGPS
 // methods off main thread to avoid blocking.
-NS_IMPL_THREADSAFE_ISUPPORTS3(GonkGPSGeolocationProvider,
-                              nsIGeolocationProvider,
-                              nsIRILDataCallback,
-                              nsISettingsServiceCallback)
+NS_IMPL_ISUPPORTS3(GonkGPSGeolocationProvider,
+                   nsIGeolocationProvider,
+                   nsIRILDataCallback,
+                   nsISettingsServiceCallback)
 
 /* static */ GonkGPSGeolocationProvider* GonkGPSGeolocationProvider::sSingleton = nullptr;
 GpsCallbacks GonkGPSGeolocationProvider::mCallbacks = {
   sizeof(GpsCallbacks),
   LocationCallback,
   StatusCallback,
   SvStatusCallback,
   NmeaCallback,
--- a/dom/system/gonk/GonkGPSGeolocationProvider.h
+++ b/dom/system/gonk/GonkGPSGeolocationProvider.h
@@ -32,17 +32,17 @@ class nsIThread;
 #define GONK_GPS_GEOLOCATION_PROVIDER_CONTRACTID \
 "@mozilla.org/gonk-gps-geolocation-provider;1"
 
 class GonkGPSGeolocationProvider : public nsIGeolocationProvider
                                  , public nsIRILDataCallback
                                  , public nsISettingsServiceCallback
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIGEOLOCATIONPROVIDER
   NS_DECL_NSIRILDATACALLBACK
   NS_DECL_NSISETTINGSSERVICECALLBACK
 
   static already_AddRefed<GonkGPSGeolocationProvider> GetSingleton();
 
 private:
 
--- a/dom/system/gonk/nsVolume.cpp
+++ b/dom/system/gonk/nsVolume.cpp
@@ -38,17 +38,17 @@ NS_VolumeStateStr(int32_t aState)
   return "???";
 }
 
 // While nsVolumes can only be used on the main thread, in the
 // UpdateVolumeRunnable constructor (which is called from IOThread) we
 // allocate an nsVolume which is then passed to MainThread. Since we
 // have a situation where we allocate on one thread and free on another
 // we use a thread safe AddRef implementation.
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsVolume, nsIVolume)
+NS_IMPL_ISUPPORTS1(nsVolume, nsIVolume)
 
 nsVolume::nsVolume(const Volume* aVolume)
   : mName(NS_ConvertUTF8toUTF16(aVolume->Name())),
     mMountPoint(NS_ConvertUTF8toUTF16(aVolume->MountPoint())),
     mState(aVolume->State()),
     mMountGeneration(aVolume->MountGeneration()),
     mMountLocked(aVolume->IsMountLocked()),
     mIsFake(false)
--- a/dom/system/gonk/nsVolume.h
+++ b/dom/system/gonk/nsVolume.h
@@ -14,17 +14,17 @@ namespace mozilla {
 namespace system {
 
 class Volume;
 class VolumeMountLock;
 
 class nsVolume : public nsIVolume
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIVOLUME
 
   // This constructor is used by the UpdateVolumeRunnable constructor
   nsVolume(const Volume* aVolume);
 
   // This constructor is used by ContentChild::RecvFileSystemUpdate
   nsVolume(const nsAString& aName, const nsAString& aMountPoint,
            const int32_t& aState, const int32_t& aMountGeneration)
--- a/dom/system/gonk/nsVolumeService.cpp
+++ b/dom/system/gonk/nsVolumeService.cpp
@@ -34,19 +34,19 @@
 #include <stdlib.h>
 
 using namespace mozilla::dom;
 using namespace mozilla::services;
 
 namespace mozilla {
 namespace system {
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsVolumeService,
-                              nsIVolumeService,
-                              nsIDOMMozWakeLockListener)
+NS_IMPL_ISUPPORTS2(nsVolumeService,
+                   nsIVolumeService,
+                   nsIDOMMozWakeLockListener)
 
 StaticRefPtr<nsVolumeService> nsVolumeService::sSingleton;
 
 // static
 already_AddRefed<nsVolumeService>
 nsVolumeService::GetSingleton()
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/system/gonk/nsVolumeService.h
+++ b/dom/system/gonk/nsVolumeService.h
@@ -25,17 +25,17 @@ class Volume;
 * on the main thread in order to support the nsIVolume and nsIVolumeService
 * classes.
 */
 
 class nsVolumeService MOZ_FINAL : public nsIVolumeService,
                                   public nsIDOMMozWakeLockListener
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIVOLUMESERVICE
   NS_DECL_NSIDOMMOZWAKELOCKLISTENER
 
   nsVolumeService();
 
   static already_AddRefed<nsVolumeService> GetSingleton();
   //static nsVolumeService* GetSingleton();
   static void Shutdown();
--- a/dom/webidl/ChildNode.webidl
+++ b/dom/webidl/ChildNode.webidl
@@ -4,18 +4,19 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://dom.spec.whatwg.org/#interface-childnode
  */
 
 [NoInterfaceObject]
 interface ChildNode {
-// On Element:
-//  readonly attribute Element? previousElementSibling;
-//  readonly attribute Element? nextElementSibling;
+  [Pure]
+  readonly attribute Element? previousElementSibling;
+  [Pure]
+  readonly attribute Element? nextElementSibling;
 
 // Not implemented yet:
 //  void before((Node or DOMString)... nodes);
 //  void after((Node or DOMString)... nodes);
 //  void replace((Node or DOMString)... nodes);
   void remove();
 };
--- a/dom/webidl/Document.webidl
+++ b/dom/webidl/Document.webidl
@@ -329,8 +329,9 @@ partial interface Document {
 partial interface Document {
   [ChromeOnly] readonly attribute boolean isSrcdocDocument;
 };
 
 Document implements XPathEvaluator;
 Document implements GlobalEventHandlers;
 Document implements NodeEventHandlers;
 Document implements TouchEventHandlers;
+Document implements ParentNode;
--- a/dom/webidl/DocumentFragment.webidl
+++ b/dom/webidl/DocumentFragment.webidl
@@ -24,8 +24,10 @@ interface DocumentFragment : Node {
 
 // http://www.w3.org/TR/2012/WD-selectors-api-20120628/#interface-definitions
 partial interface DocumentFragment {
   [Throws]
   Element?  querySelector(DOMString selectors);
   [Throws]
   NodeList  querySelectorAll(DOMString selectors);
 };
+
+DocumentFragment implements ParentNode;
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -50,29 +50,16 @@ interface Element : Node {
   boolean hasAttribute(DOMString name);
   boolean hasAttributeNS(DOMString? namespace, DOMString localName);
 
   HTMLCollection getElementsByTagName(DOMString localName);
   [Throws]
   HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
   HTMLCollection getElementsByClassName(DOMString classNames);
 
-  [Constant]
-  readonly attribute HTMLCollection children;
-  [Pure]
-  readonly attribute Element? firstElementChild;
-  [Pure]
-  readonly attribute Element? lastElementChild;
-  [Pure]
-  readonly attribute Element? previousElementSibling;
-  [Pure]
-  readonly attribute Element? nextElementSibling;
-  [Pure]
-  readonly attribute unsigned long childElementCount;
-
   /**
    * The ratio of font-size-inflated text font size to computed font
    * size for this element. This will query the element for its primary frame,
    * and then use this to get font size inflation information about the frame.
    * This will be 1.0 if font size inflation is not enabled, and -1.0 if an
    * error occurred during the retrieval of the font size inflation.
    *
    * @note The font size inflation ratio that is returned is actually the
@@ -194,8 +181,9 @@ partial interface Element {
 partial interface Element {
   [Throws]
   Element?  querySelector(DOMString selectors);
   [Throws]
   NodeList  querySelectorAll(DOMString selectors);
 };
 
 Element implements ChildNode;
+Element implements ParentNode;
--- a/dom/webidl/NetDashboard.webidl
+++ b/dom/webidl/NetDashboard.webidl
@@ -15,21 +15,26 @@ dictionary SocketsDict {
 };
 
 dictionary HttpConnInfoDict {
   sequence<unsigned long> rtt;
   sequence<unsigned long> ttl;
   sequence<DOMString> protocolVersion;
 };
 
+dictionary HalfOpenInfoDict {
+  sequence<boolean> speculative;
+};
+
 dictionary HttpConnDict {
   sequence<DOMString> host;
   sequence<unsigned long> port;
   sequence<HttpConnInfoDict> active;
   sequence<HttpConnInfoDict> idle;
+  sequence<HalfOpenInfoDict> halfOpens;
   sequence<boolean> spdy;
   sequence<boolean> ssl;
 };
 
 dictionary WebSocketDict {
   sequence<DOMString> hostport;
   sequence<unsigned long> msgsent;
   sequence<unsigned long> msgreceived;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/ParentNode.webidl
@@ -0,0 +1,24 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ *
+ * The origin of this IDL file is
+ * http://dom.spec.whatwg.org/#interface-parentnode
+ */
+
+[NoInterfaceObject]
+interface ParentNode {
+  [Constant]
+  readonly attribute HTMLCollection children;
+  [Pure]
+  readonly attribute Element? firstElementChild;
+  [Pure]
+  readonly attribute Element? lastElementChild;
+  [Pure]
+  readonly attribute unsigned long childElementCount;
+
+  // Not implemented yet
+  // void prepend((Node or DOMString)... nodes);
+  // void append((Node or DOMString)... nodes);
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -204,16 +204,17 @@ webidl_files = \
   NotifyAudioAvailableEvent.webidl \
   NotifyPaintEvent.webidl \
   OfflineAudioCompletionEvent.webidl \
   OfflineAudioContext.webidl \
   OfflineResourceList.webidl \
   PaintRequest.webidl \
   PaintRequestList.webidl \
   PannerNode.webidl \
+  ParentNode.webidl \
   Performance.webidl \
   PerformanceNavigation.webidl \
   PerformanceTiming.webidl \
   PeriodicWave.webidl \
   Plugin.webidl \
   PluginArray.webidl \
   Position.webidl \
   PositionError.webidl \
--- a/dom/workers/EventListenerManager.cpp
+++ b/dom/workers/EventListenerManager.cpp
@@ -55,17 +55,17 @@ private:
   ListenerCollection(jsid aTypeId)
     : mTypeId(aTypeId)
   {
   }
 };
 
 struct ListenerData : LinkedListElement<ListenerData>
 {
-  JSObject* mListener;
+  JS::Heap<JSObject*> mListener;
   EventListenerManager::Phase mPhase;
   bool mWantsUntrusted;
 
   static ListenerData*
   Add(JSContext* aCx, LinkedList<ListenerData>& aListeners, JSObject* aListener,
       EventListenerManager::Phase aPhase, bool aWantsUntrusted)
   {
     ListenerData* listenerData =
@@ -179,19 +179,19 @@ EventListenerManager::TraceInternal(JSTr
 
   for (const ListenerCollection* collection = mCollections.getFirst();
        collection;
        collection = collection->getNext()) {
 
     for (const ListenerData* listenerElem = collection->mListeners.getFirst();
          listenerElem;
          listenerElem = listenerElem->getNext()) {
-      JS_CallObjectTracer(aTrc,
-                          &const_cast<ListenerData*>(listenerElem)->mListener,
-                          "EventListenerManager listener object");
+      JS_CallHeapObjectTracer(aTrc,
+                              &const_cast<ListenerData*>(listenerElem)->mListener,
+                              "EventListenerManager listener object");
     }
   }
 }
 
 void
 EventListenerManager::FinalizeInternal(JSFreeOp* aFop)
 {
   MOZ_ASSERT(!mCollections.isEmpty());
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -128,17 +128,17 @@ class ScriptLoaderRunnable : public Work
   WorkerPrivate* mWorkerPrivate;
   uint32_t mSyncQueueKey;
   nsTArray<ScriptLoadInfo> mLoadInfos;
   bool mIsWorkerScript;
   bool mCanceled;
   bool mCanceledMainThread;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   ScriptLoaderRunnable(WorkerPrivate* aWorkerPrivate,
                        uint32_t aSyncQueueKey,
                        nsTArray<ScriptLoadInfo>& aLoadInfos,
                        bool aIsWorkerScript)
   : mWorkerPrivate(aWorkerPrivate), mSyncQueueKey(aSyncQueueKey),
     mIsWorkerScript(aIsWorkerScript), mCanceled(false),
     mCanceledMainThread(false)
@@ -515,18 +515,17 @@ public:
         new ScriptExecutorRunnable(*this, mSyncQueueKey, firstIndex, lastIndex);
       if (!runnable->Dispatch(nullptr)) {
         NS_ERROR("This should never fail!");
       }
     }
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(ScriptLoaderRunnable, nsIRunnable,
-                                                    nsIStreamLoaderObserver)
+NS_IMPL_ISUPPORTS2(ScriptLoaderRunnable, nsIRunnable, nsIStreamLoaderObserver)
 
 class StopSyncLoopRunnable MOZ_FINAL : public MainThreadSyncRunnable
 {
 public:
   StopSyncLoopRunnable(WorkerPrivate* aWorkerPrivate,
                        uint32_t aSyncQueueKey)
   : MainThreadSyncRunnable(aWorkerPrivate, SkipWhenClearing, aSyncQueueKey,
                            false)
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1179,17 +1179,17 @@ class WorkerRunnableEventTarget MOZ_FINA
 protected:
   nsRefPtr<WorkerRunnable> mWorkerRunnable;
 
 public:
   WorkerRunnableEventTarget(WorkerRunnable* aWorkerRunnable)
   : mWorkerRunnable(aWorkerRunnable)
   { }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   NS_IMETHOD
   Dispatch(nsIRunnable* aRunnable, uint32_t aFlags)
   {
     NS_ASSERTION(aFlags == nsIEventTarget::DISPATCH_NORMAL, "Don't call me!");
 
     nsRefPtr<WorkerRunnableEventTarget> kungFuDeathGrip = this;
 
@@ -1208,17 +1208,17 @@ public:
   NS_IMETHOD
   IsOnCurrentThread(bool* aIsOnCurrentThread)
   {
     *aIsOnCurrentThread = false;
     return NS_OK;
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerRunnableEventTarget, nsIEventTarget)
+NS_IMPL_ISUPPORTS1(WorkerRunnableEventTarget, nsIEventTarget)
 
 class KillCloseEventRunnable : public WorkerRunnable
 {
   nsCOMPtr<nsITimer> mTimer;
 
   class KillScriptRunnable : public WorkerControlRunnable
   {
   public:
@@ -1534,17 +1534,17 @@ WorkerRunnable::WorkerRunnable(WorkerPri
                                ClearingBehavior aClearingBehavior)
 : mWorkerPrivate(aWorkerPrivate), mTarget(aTarget),
   mBusyBehavior(aBusyBehavior), mClearingBehavior(aClearingBehavior)
 {
   NS_ASSERTION(aWorkerPrivate, "Null worker private!");
 }
 #endif
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(WorkerRunnable, nsIRunnable)
 
 bool
 WorkerRunnable::PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
 {
 #ifdef DEBUG
   if (mBusyBehavior == ModifyBusyCount) {
     NS_ASSERTION(mTarget == WorkerThread,
                  "Don't set this option unless targeting the worker thread!");
@@ -1758,18 +1758,18 @@ struct WorkerPrivate::TimeoutInfo
     return mTargetTime == aOther.mTargetTime;
   }
 
   bool operator<(const TimeoutInfo& aOther)
   {
     return mTargetTime < aOther.mTargetTime;
   }
 
-  JS::Value mTimeoutVal;
-  nsTArray<jsval> mExtraArgVals;
+  JS::Heap<JS::Value> mTimeoutVal;
+  nsTArray<JS::Heap<JS::Value> > mExtraArgVals;
   mozilla::TimeStamp mTargetTime;
   mozilla::TimeDuration mInterval;
   nsCString mFilename;
   uint32_t mLineNumber;
   uint32_t mId;
   bool mIsInterval;
   bool mCanceled;
 };
@@ -1779,17 +1779,17 @@ class WorkerPrivate::MemoryReporter MOZ_
   friend class WorkerPrivate;
 
   SharedMutex mMutex;
   WorkerPrivate* mWorkerPrivate;
   nsCString mRtPath;
   bool mAlreadyMappedToAddon;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   MemoryReporter(WorkerPrivate* aWorkerPrivate)
   : mMutex(aWorkerPrivate->mMutex), mWorkerPrivate(aWorkerPrivate),
     mAlreadyMappedToAddon(false)
   {
     aWorkerPrivate->AssertIsOnWorkerThread();
 
     nsCString escapedDomain(aWorkerPrivate->Domain());
@@ -1886,18 +1886,17 @@ private:
 
     static const size_t explicitLength = strlen("explicit/");
     addonId.Insert(NS_LITERAL_CSTRING("add-ons/"), 0);
     addonId += "/";
     mRtPath.Insert(addonId, explicitLength);
   }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerPrivate::MemoryReporter,
-                              nsIMemoryMultiReporter)
+NS_IMPL_ISUPPORTS1(WorkerPrivate::MemoryReporter, nsIMemoryMultiReporter)
 
 template <class Derived>
 WorkerPrivateParent<Derived>::WorkerPrivateParent(
                                      JSContext* aCx,
                                      JS::Handle<JSObject*> aObject,
                                      WorkerPrivate* aParent,
                                      JSContext* aParentJSContext,
                                      const nsAString& aScriptURL,
@@ -3393,21 +3392,21 @@ WorkerPrivate::ResumeInternal(JSContext*
 
 void
 WorkerPrivate::TraceInternal(JSTracer* aTrc)
 {
   AssertIsOnWorkerThread();
 
   for (uint32_t index = 0; index < mTimeouts.Length(); index++) {
     TimeoutInfo* info = mTimeouts[index];
-    JS_CallValueTracer(aTrc, &info->mTimeoutVal,
-                       "WorkerPrivate timeout value");
+    JS_CallHeapValueTracer(aTrc, &info->mTimeoutVal,
+                           "WorkerPrivate timeout value");
     for (uint32_t index2 = 0; index2 < info->mExtraArgVals.Length(); index2++) {
-      JS_CallValueTracer(aTrc, &info->mExtraArgVals[index2],
-                         "WorkerPrivate timeout extra argument value");
+      JS_CallHeapValueTracer(aTrc, &info->mExtraArgVals[index2],
+                             "WorkerPrivate timeout extra argument value");
     }
   }
 }
 
 bool
 WorkerPrivate::ModifyBusyCountFromWorker(JSContext* aCx, bool aIncrease)
 {
   AssertIsOnWorkerThread();
@@ -3947,17 +3946,17 @@ WorkerPrivate::SetTimeout(JSContext* aCx
   if (aArgc > 1) {
     double intervalMS = 0;
     if (!JS_ValueToNumber(aCx, argv[1], &intervalMS)) {
       return false;
     }
     newInfo->mInterval = TimeDuration::FromMilliseconds(intervalMS);
 
     if (aArgc > 2 && newInfo->mTimeoutVal.isObject()) {
-      nsTArray<jsval> extraArgVals(aArgc - 2);
+      nsTArray<JS::Heap<JS::Value> > extraArgVals(aArgc - 2);
       for (unsigned index = 2; index < aArgc; index++) {
         extraArgVals.AppendElement(argv[index]);
       }
       newInfo->mExtraArgVals.SwapElements(extraArgVals);
     }
   }
 
   newInfo->mTargetTime = TimeStamp::Now() + newInfo->mInterval;
@@ -4099,19 +4098,24 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
       if ((!string || !JS::Evaluate(aCx, global, options, string, stringLength, nullptr)) &&
           !JS_ReportPendingException(aCx)) {
         retval = false;
         break;
       }
     }
     else {
       JS::Rooted<JS::Value> rval(aCx);
+      /*
+       * unsafeGet() is needed below because the argument is a not a const
+       * pointer, even though values are not modified.
+       */
       if (!JS_CallFunctionValue(aCx, global, info->mTimeoutVal,
                                 info->mExtraArgVals.Length(),
-                                info->mExtraArgVals.Elements(), rval.address()) &&
+                                info->mExtraArgVals.Elements()->unsafeGet(),
+                                rval.address()) &&
           !JS_ReportPendingException(aCx)) {
         retval = false;
         break;
       }
     }
 
     NS_ASSERTION(mRunningExpiredTimeouts, "Someone changed this!");
   }
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -60,17 +60,17 @@ public:
 
 protected:
   WorkerPrivate* mWorkerPrivate;
   Target mTarget;
   BusyBehavior mBusyBehavior;
   ClearingBehavior mClearingBehavior;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
   bool
   Dispatch(JSContext* aCx);
 
   static bool
   DispatchToMainThread(nsIRunnable*);
 
   bool
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -72,17 +72,17 @@ class WorkerGlobalScope : public workers
   {
     SLOT_location = 0,
     SLOT_navigator,
 
     SLOT_COUNT
   };
 
   // Must be traced!
-  jsval mSlots[SLOT_COUNT];
+  JS::Heap<JS::Value> mSlots[SLOT_COUNT];
 
   enum
   {
     STRING_onerror = 0,
     STRING_onclose,
 
     STRING_COUNT
   };
@@ -123,17 +123,17 @@ protected:
   {
     MOZ_COUNT_DTOR(mozilla::dom::workers::WorkerGlobalScope);
   }
 
   virtual void
   _trace(JSTracer* aTrc) MOZ_OVERRIDE
   {
     for (int32_t i = 0; i < SLOT_COUNT; i++) {
-      JS_CallValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
+      JS_CallHeapValueTracer(aTrc, &mSlots[i], "WorkerGlobalScope instance slot");
     }
     mWorker->TraceInternal(aTrc);
     EventTarget::_trace(aTrc);
   }
 
   virtual void
   _finalize(JSFreeOp* aFop) MOZ_OVERRIDE
   {
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -120,17 +120,17 @@ public:
   // Only touched on the main thread.
   uint32_t mSyncQueueKey;
   uint32_t mSyncEventResponseSyncQueueKey;
   bool mUploadEventListenersAttached;
   bool mMainThreadSeenLoadStart;
   bool mInOpen;
 
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
 
   Proxy(XMLHttpRequest* aXHRPrivate, bool aMozAnon, bool aMozSystem)
   : mWorkerPrivate(nullptr), mXMLHttpRequestPrivate(aXHRPrivate),
     mMozAnon(aMozAnon), mMozSystem(aMozSystem),
     mInnerEventStreamId(0), mInnerChannelId(0), mOutstandingSendCount(0),
     mOuterEventStreamId(0), mOuterChannelId(0), mLastLoaded(0), mLastTotal(0),
     mLastUploadLoaded(0), mLastUploadTotal(0), mIsSyncXHR(false),
@@ -515,17 +515,17 @@ public:
 NS_IMPL_ISUPPORTS2(LoadStartDetectionRunnable, nsIRunnable, nsIDOMEventListener)
 
 class EventRunnable : public MainThreadProxyRunnable
 {
   nsString mType;
   nsString mResponseType;
   JSAutoStructuredCloneBuffer mResponseBuffer;
   nsTArray<nsCOMPtr<nsISupports> > mClonedObjects;
-  jsval mResponse;
+  JS::Heap<JS::Value> mResponse;
   nsString mResponseText;
   nsCString mStatusText;
   uint64_t mLoaded;
   uint64_t mTotal;
   uint32_t mEventStreamId;
   uint32_t mStatus;
   uint16_t mReadyState;
   bool mUploadEvent;
@@ -602,16 +602,38 @@ public:
 
     xhr->GetStatusText(mStatusText);
 
     mReadyState = xhr->ReadyState();
 
     return true;
   }
 
+  class StateDataAutoRooter : private JS::CustomAutoRooter
+  {
+  public:
+    explicit StateDataAutoRooter(JSContext* aCx, XMLHttpRequest::StateData* aData
+                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+    : CustomAutoRooter(aCx), mStateData(aData), mSkip(aCx, mStateData)
+    {
+      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+    }
+
+  private:
+    virtual void trace(JSTracer* aTrc)
+    {
+      JS_CallHeapValueTracer(aTrc, &mStateData->mResponse,
+                             "XMLHttpRequest::StateData::mResponse");
+    }
+
+    XMLHttpRequest::StateData* mStateData;
+    js::SkipRoot mSkip;
+    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+  };
+
   bool
   WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
   {
     if (mEventStreamId != mProxy->mOuterEventStreamId) {
       // Threads raced, this event is now obsolete.
       return true;
     }
 
@@ -660,18 +682,17 @@ public:
       else {
         mProxy->mLastLengthComputable = mLengthComputable;
         mProxy->mLastLoaded = mLoaded;
         mProxy->mLastTotal = mTotal;
       }
     }
 
     XMLHttpRequest::StateData state;
-    // XXXbz there is no AutoValueRooter anymore?
-    JS::AutoArrayRooter rooter(aCx, 1, &state.mResponse);
+    StateDataAutoRooter rooter(aCx, &state);
 
     state.mResponseTextResult = mResponseTextResult;
     state.mResponseText = mResponseText;
 
     if (NS_SUCCEEDED(mResponseTextResult)) {
       MOZ_ASSERT(JSVAL_IS_VOID(mResponse) || JSVAL_IS_NULL(mResponse));
       state.mResponseResult = mResponseTextResult;
       state.mResponse = mResponse;
@@ -1319,17 +1340,17 @@ Proxy::AddRemoveEventListeners(bool aUpl
 
   if (aUpload) {
     mUploadEventListenersAttached = aAdd;
   }
 
   return true;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(Proxy, nsIDOMEventListener)
+NS_IMPL_ISUPPORTS1(Proxy, nsIDOMEventListener)
 
 NS_IMETHODIMP
 Proxy::HandleEvent(nsIDOMEvent* aEvent)
 {
   AssertIsOnMainThread();
 
   if (!mWorkerPrivate || !mXMLHttpRequestPrivate) {
     NS_ERROR("Shouldn't get here!");
@@ -1418,19 +1439,19 @@ XMLHttpRequest::~XMLHttpRequest()
   mWorkerPrivate->AssertIsOnWorkerThread();
   MOZ_ASSERT(!mJSObjectRooted);
 }
 
 void
 XMLHttpRequest::_trace(JSTracer* aTrc)
 {
   if (mUpload) {
-    mUpload->TraceJSObject(aTrc, "mUpload");
+    mUpload->TraceJSObject(aTrc, "XMLHttpRequest::mUpload");
   }
-  JS_CallValueTracer(aTrc, &mStateData.mResponse, "mResponse");
+  JS_CallHeapValueTracer(aTrc, &mStateData.mResponse, "XMLHttpRequest::mResponse");
   XMLHttpRequestEventTarget::_trace(aTrc);
 }
 
 void
 XMLHttpRequest::_finalize(JSFreeOp* aFop)
 {
   ReleaseProxy(XHRIsGoingAway);
   XMLHttpRequestEventTarget::_finalize(aFop);
@@ -1505,23 +1526,29 @@ XMLHttpRequest::MaybePin(ErrorResult& aR
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mJSObjectRooted) {
     return;
   }
 
   JSContext* cx = GetJSContext();
 
-  if (!JS_AddNamedObjectRoot(cx, &mJSObject, "XMLHttpRequest mJSObject")) {
+  /*
+   * It's safe to use unsafeGet() here: the unsafeness comes from the
+   * possibility of updating the value of mJSObject without triggering the post
+   * barriers.  However if the value will always be marked, post barriers are
+   * unnecessary.
+   */
+  if (!JS_AddNamedObjectRoot(cx, mJSObject.unsafeGet(), "XMLHttpRequest::mJSObjectRooted")) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   if (!mWorkerPrivate->AddFeature(cx, this)) {
-    JS_RemoveObjectRoot(cx, &mJSObject);
+    JS_RemoveObjectRoot(cx, mJSObject.unsafeGet());
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   mJSObjectRooted = true;
 }
 
 void
@@ -1630,17 +1657,18 @@ void
 XMLHttpRequest::Unpin()
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   NS_ASSERTION(mJSObjectRooted, "Mismatched calls to Unpin!");
 
   JSContext* cx = GetJSContext();
 
-  JS_RemoveObjectRoot(cx, &mJSObject);
+  /* See the comment in MaybePin() for why this is safe. */
+  JS_RemoveObjectRoot(cx, mJSObject.unsafeGet());
 
   mWorkerPrivate->RemoveFeature(cx, this);
 
   mJSObjectRooted = false;
 }
 
 void
 XMLHttpRequest::SendInternal(const nsAString& aStringBody,
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -26,30 +26,30 @@ class XMLHttpRequest : public XMLHttpReq
 {
 public:
   struct StateData
   {
     nsString mResponseText;
     uint32_t mStatus;
     nsCString mStatusText;
     uint16_t mReadyState;
-    jsval mResponse;
+    JS::Heap<JS::Value> mResponse;
     nsresult mResponseTextResult;
     nsresult mStatusResult;
     nsresult mResponseResult;
 
     StateData()
     : mStatus(0), mReadyState(0), mResponse(JSVAL_VOID),
       mResponseTextResult(NS_OK), mStatusResult(NS_OK),
       mResponseResult(NS_OK)
     { }
   };
 
 private:
-  JSObject* mJSObject;
+  JS::Heap<JSObject*> mJSObject;
   XMLHttpRequestUpload* mUpload;
   WorkerPrivate* mWorkerPrivate;
   nsRefPtr<Proxy> mProxy;
   XMLHttpRequestResponseType mResponseType;
   StateData mStateData;
 
   uint32_t mTimeout;
 
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -989,26 +989,26 @@ nsDocShellTreeOwner::GetOwnerRequestor()
 ///////////////////////////////////////////////////////////////////////////////
 // DefaultTooltipTextProvider
 
 class DefaultTooltipTextProvider MOZ_FINAL : public nsITooltipTextProvider
 {
 public:
     DefaultTooltipTextProvider();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSITOOLTIPTEXTPROVIDER
     
 protected:
     nsCOMPtr<nsIAtom>   mTag_dialog;
     nsCOMPtr<nsIAtom>   mTag_dialogheader;
     nsCOMPtr<nsIAtom>   mTag_window;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(DefaultTooltipTextProvider, nsITooltipTextProvider)
+NS_IMPL_ISUPPORTS1(DefaultTooltipTextProvider, nsITooltipTextProvider)
 
 DefaultTooltipTextProvider::DefaultTooltipTextProvider()
 {
     // There are certain element types which we don't want to use
     // as tool tip text. 
     mTag_dialog       = do_GetAtom("dialog");
     mTag_dialogheader = do_GetAtom("dialogheader");
     mTag_window       = do_GetAtom("window");   
--- a/embedding/components/printingui/src/mac/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/mac/nsPrintProgress.cpp
@@ -6,18 +6,18 @@
 #include "nsPrintProgress.h"
 
 #include "nsIBaseWindow.h"
 #include "nsISupportsArray.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 
-NS_IMPL_THREADSAFE_ADDREF(nsPrintProgress)
-NS_IMPL_THREADSAFE_RELEASE(nsPrintProgress)
+NS_IMPL_ADDREF(nsPrintProgress)
+NS_IMPL_RELEASE(nsPrintProgress)
 
 NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
    NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
 NS_INTERFACE_MAP_END_THREADSAFE
 
--- a/embedding/components/printingui/src/mac/nsPrintProgress.h
+++ b/embedding/components/printingui/src/mac/nsPrintProgress.h
@@ -13,17 +13,17 @@
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
-	NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPRINTPROGRESS
   NS_DECL_NSIWEBPROGRESSLISTENER
   NS_DECL_NSIPRINTSTATUSFEEDBACK
 
 	nsPrintProgress();
 	virtual ~nsPrintProgress();
 
 private:
--- a/embedding/components/printingui/src/os2/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/os2/nsPrintProgress.cpp
@@ -6,18 +6,18 @@
 #include "nsPrintProgress.h"
 
 #include "nsIBaseWindow.h"
 #include "nsISupportsArray.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 
-NS_IMPL_THREADSAFE_ADDREF(nsPrintProgress)
-NS_IMPL_THREADSAFE_RELEASE(nsPrintProgress)
+NS_IMPL_ADDREF(nsPrintProgress)
+NS_IMPL_RELEASE(nsPrintProgress)
 
 NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
    NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
 NS_INTERFACE_MAP_END_THREADSAFE
 
--- a/embedding/components/printingui/src/os2/nsPrintProgress.h
+++ b/embedding/components/printingui/src/os2/nsPrintProgress.h
@@ -13,17 +13,17 @@
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
-	NS_DECL_ISUPPORTS
+	NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPRINTPROGRESS
   NS_DECL_NSIWEBPROGRESSLISTENER
   NS_DECL_NSIPRINTSTATUSFEEDBACK
 
 	nsPrintProgress();
 	virtual ~nsPrintProgress();
 
 private:
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.cpp
@@ -6,18 +6,18 @@
 #include "nsPrintProgress.h"
 
 #include "nsIBaseWindow.h"
 #include "nsISupportsArray.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 
-NS_IMPL_THREADSAFE_ADDREF(nsPrintProgress)
-NS_IMPL_THREADSAFE_RELEASE(nsPrintProgress)
+NS_IMPL_ADDREF(nsPrintProgress)
+NS_IMPL_RELEASE(nsPrintProgress)
 
 NS_INTERFACE_MAP_BEGIN(nsPrintProgress)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIPrintProgress)
    NS_INTERFACE_MAP_ENTRY(nsIPrintStatusFeedback)
    NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
 NS_INTERFACE_MAP_END_THREADSAFE
 
--- a/embedding/components/printingui/src/unixshared/nsPrintProgress.h
+++ b/embedding/components/printingui/src/unixshared/nsPrintProgress.h
@@ -14,17 +14,17 @@
 #include "nsIDOMWindow.h"
 #include "nsIPrintStatusFeedback.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
-	NS_DECL_ISUPPORTS
+	NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPRINTPROGRESS
   NS_DECL_NSIWEBPROGRESSLISTENER
   NS_DECL_NSIPRINTSTATUSFEEDBACK
 
 	nsPrintProgress(nsIPrintSettings* aPrintSettings);
 	virtual ~nsPrintProgress();
 
 private:
--- a/embedding/components/printingui/src/win/nsPrintProgress.cpp
+++ b/embedding/components/printingui/src/win/nsPrintProgress.cpp
@@ -6,36 +6,35 @@
 #include "nsPrintProgress.h"
 
 #include "nsIBaseWindow.h"
 #include "nsISupportsArray.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
-#include "nsAtomicRefcnt.h"
 
 #if 0
-NS_IMPL_THREADSAFE_ADDREF(nsPrintProgress)
-NS_IMPL_THREADSAFE_RELEASE(nsPrintProgress)
+NS_IMPL_ADDREF(nsPrintProgress)
+NS_IMPL_RELEASE(nsPrintProgress)
 #else
 NS_IMETHODIMP_(nsrefcnt) nsPrintProgress::AddRef(void)
 {
   NS_PRECONDITION(int32_t(mRefCnt) >= 0, "illegal refcnt");
   nsrefcnt count;
-  count = NS_AtomicIncrementRefcnt(mRefCnt);
+  count = ++mRefCnt;
   //NS_LOG_ADDREF(this, count, "nsPrintProgress", sizeof(*this));
   return count;
 }
 
 NS_IMETHODIMP_(nsrefcnt) nsPrintProgress::Release(void)
 {
   nsrefcnt count;
   NS_PRECONDITION(0 != mRefCnt, "dup release");
-  count = NS_AtomicDecrementRefcnt(mRefCnt);
+  count = --mRefCnt;
   //NS_LOG_RELEASE(this, count, "nsPrintProgress");
   if (0 == count) {
     mRefCnt = 1; /* stabilize */
     /* enable this to find non-threadsafe destructors: */
     /* NS_ASSERT_OWNINGTHREAD(nsPrintProgress); */
     delete this;
     return 0;
   }
--- a/embedding/components/printingui/src/win/nsPrintProgress.h
+++ b/embedding/components/printingui/src/win/nsPrintProgress.h
@@ -14,17 +14,17 @@
 #include "nsIPrintStatusFeedback.h"
 #include "nsString.h"
 #include "nsIWindowWatcher.h"
 #include "nsIObserver.h"
 
 class nsPrintProgress : public nsIPrintProgress, public nsIPrintStatusFeedback
 {
 public: 
-	NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPRINTPROGRESS
   NS_DECL_NSIWEBPROGRESSLISTENER
   NS_DECL_NSIPRINTSTATUSFEEDBACK
 
 	nsPrintProgress();
 	virtual ~nsPrintProgress();
 
 private:
--- a/extensions/auth/nsAuthGSSAPI.cpp
+++ b/extensions/auth/nsAuthGSSAPI.cpp
@@ -326,17 +326,17 @@ nsAuthGSSAPI::Shutdown()
 {
     if (gssLibrary) {
         PR_UnloadLibrary(gssLibrary);
         gssLibrary = nullptr;
     }
 }
 
 /* Limitations apply to this class's thread safety. See the header file */
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsAuthGSSAPI, nsIAuthModule)
+NS_IMPL_ISUPPORTS1(nsAuthGSSAPI, nsIAuthModule)
 
 NS_IMETHODIMP
 nsAuthGSSAPI::Init(const char *serviceName,
                    uint32_t    serviceFlags,
                    const PRUnichar *domain,
                    const PRUnichar *username,
                    const PRUnichar *password)
 {
--- a/extensions/auth/nsAuthGSSAPI.h
+++ b/extensions/auth/nsAuthGSSAPI.h
@@ -33,17 +33,17 @@
  * multiple threads. The nature of the GSSAPI protocol is such that a correct 
  * implementation will never call methods in parallel, as the results of the 
  * last call are required as input to the next.
  */
 
 class nsAuthGSSAPI MOZ_FINAL : public nsIAuthModule
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIAUTHMODULE
 
     nsAuthGSSAPI(pType package);
 
     static void Shutdown();
 
 private:
     ~nsAuthGSSAPI() { Reset(); }
--- a/extensions/auth/nsAuthSASL.cpp
+++ b/extensions/auth/nsAuthSASL.cpp
@@ -18,17 +18,17 @@ nsAuthSASL::nsAuthSASL()
 }
 
 void nsAuthSASL::Reset() 
 {
     mSASLReady = false;
 }
 
 /* Limitations apply to this class's thread safety. See the header file */
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsAuthSASL, nsIAuthModule)
+NS_IMPL_ISUPPORTS1(nsAuthSASL, nsIAuthModule)
 
 NS_IMETHODIMP
 nsAuthSASL::Init(const char *serviceName,
                  uint32_t    serviceFlags,
                  const PRUnichar *domain,
                  const PRUnichar *username,
                  const PRUnichar *password)
 {
--- a/extensions/auth/nsAuthSASL.h
+++ b/extensions/auth/nsAuthSASL.h
@@ -14,17 +14,17 @@
 /* This class is implemented using the nsAuthGSSAPI class, and the same
  * thread safety constraints which are documented in nsAuthGSSAPI.h
  * apply to this class
  */
 
 class nsAuthSASL MOZ_FINAL : public nsIAuthModule
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIAUTHMODULE
 
     nsAuthSASL();
 
 private:
     ~nsAuthSASL() { Reset(); }
 
     void Reset();
--- a/extensions/gio/nsGIOProtocolHandler.cpp
+++ b/extensions/gio/nsGIOProtocolHandler.cpp
@@ -133,17 +133,17 @@ static void mount_operation_ask_password
                                           const char        *default_domain,
                                           GAskPasswordFlags flags,
                                           gpointer          user_data);
 //-----------------------------------------------------------------------------
 
 class nsGIOInputStream MOZ_FINAL : public nsIInputStream
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINPUTSTREAM
 
     nsGIOInputStream(const nsCString &uriSpec)
       : mSpec(uriSpec)
       , mChannel(nullptr)
       , mHandle(nullptr)
       , mStream(nullptr)
       , mBytesRemaining(UINT64_MAX)
@@ -575,17 +575,17 @@ nsGIOInputStream::SetContentTypeOfChanne
   }
   else
   {
     rv = NS_DispatchToMainThread(ev);
   }
   return rv;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsGIOInputStream, nsIInputStream)
+NS_IMPL_ISUPPORTS1(nsGIOInputStream, nsIInputStream)
 
 /**
  * Free all used memory and close stream.
  */
 NS_IMETHODIMP
 nsGIOInputStream::Close()
 {
   if (mStream)
--- a/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp
+++ b/extensions/gnomevfs/nsGnomeVFSProtocolHandler.cpp
@@ -309,17 +309,17 @@ FileInfoComparator(gconstpointer a, gcon
   return strcasecmp(ia->name, ib->name);
 }
 
 //-----------------------------------------------------------------------------
 
 class nsGnomeVFSInputStream MOZ_FINAL : public nsIInputStream
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINPUTSTREAM
 
     nsGnomeVFSInputStream(const nsCString &uriSpec)
       : mSpec(uriSpec)
       , mChannel(nullptr)
       , mHandle(nullptr)
       , mBytesRemaining(UINT64_MAX)
       , mStatus(NS_OK)
@@ -626,17 +626,17 @@ nsGnomeVFSInputStream::SetContentTypeOfC
   }
   else
   {
     rv = NS_DispatchToMainThread(ev);
   }
   return rv;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsGnomeVFSInputStream, nsIInputStream)
+NS_IMPL_ISUPPORTS1(nsGnomeVFSInputStream, nsIInputStream)
 
 NS_IMETHODIMP
 nsGnomeVFSInputStream::Close()
 {
   if (mHandle)
   {
     gnome_vfs_close(mHandle);
     mHandle = nullptr;
--- a/extensions/pref/autoconfig/src/nsAutoConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.cpp
@@ -28,17 +28,17 @@ PRLogModuleInfo *MCD;
 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
                                           const char *filename, 
                                           bool bGlobalContext, 
                                           bool bCallbacks, 
                                           bool skipFirstLine);
 
 // nsISupports Implementation
 
-NS_IMPL_THREADSAFE_ISUPPORTS6(nsAutoConfig, nsIAutoConfig, nsITimerCallback, nsIStreamListener, nsIObserver, nsIRequestObserver, nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS6(nsAutoConfig, nsIAutoConfig, nsITimerCallback, nsIStreamListener, nsIObserver, nsIRequestObserver, nsISupportsWeakReference)
 
 nsAutoConfig::nsAutoConfig()
 {
 }
 
 nsresult nsAutoConfig::Init()
 {
     // member initializers and constructor code
--- a/extensions/pref/autoconfig/src/nsAutoConfig.h
+++ b/extensions/pref/autoconfig/src/nsAutoConfig.h
@@ -16,17 +16,17 @@ class nsAutoConfig : public nsIAutoConfi
                      public nsITimerCallback,
                      public nsIStreamListener,
                      public nsIObserver,
                      public nsSupportsWeakReference
 
 {
     public:
 
-        NS_DECL_ISUPPORTS
+        NS_DECL_THREADSAFE_ISUPPORTS
         NS_DECL_NSIAUTOCONFIG
         NS_DECL_NSIREQUESTOBSERVER
         NS_DECL_NSISTREAMLISTENER
         NS_DECL_NSIOBSERVER
         NS_DECL_NSITIMERCALLBACK
 
         nsAutoConfig();
         virtual ~nsAutoConfig();
--- a/extensions/pref/autoconfig/src/nsReadConfig.cpp
+++ b/extensions/pref/autoconfig/src/nsReadConfig.cpp
@@ -68,17 +68,17 @@ static void DisplayError(void)
     if (NS_FAILED(rv))
         return;
 
     promptService->Alert(nullptr, title.get(), err.get());
 }
 
 // nsISupports Implementation
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsReadConfig, nsIReadConfig, nsIObserver)
+NS_IMPL_ISUPPORTS2(nsReadConfig, nsIReadConfig, nsIObserver)
 
 nsReadConfig::nsReadConfig() :
     mRead(false)
 {
     if (!MCD)
       MCD = PR_NewLogModule("MCD");
 }
 
--- a/extensions/pref/autoconfig/src/nsReadConfig.h
+++ b/extensions/pref/autoconfig/src/nsReadConfig.h
@@ -10,17 +10,17 @@
 
 
 class nsReadConfig : public nsIReadConfig,
                      public nsIObserver
 {
 
     public:
 
-        NS_DECL_ISUPPORTS
+        NS_DECL_THREADSAFE_ISUPPORTS
         NS_DECL_NSIREADCONFIG
         NS_DECL_NSIOBSERVER
 
         nsReadConfig();
         virtual ~nsReadConfig();
 
         nsresult Init();
 
--- a/gfx/2d/QuartzSupport.h
+++ b/gfx/2d/QuartzSupport.h
@@ -8,16 +8,17 @@
 #define nsCoreAnimationSupport_h__
 #ifdef XP_MACOSX
 
 #import <OpenGL/OpenGL.h>
 #import "ApplicationServices/ApplicationServices.h"
 #include "gfxTypes.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/gfx/MacIOSurface.h"
+#include "nsError.h"
 
 // Get the system color space.
 CGColorSpaceRef CreateSystemColorSpace();
 
 // Manages a CARenderer
 struct _CGLPBufferObject;
 struct _CGLContextObject;
 
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -8,16 +8,17 @@
 
 #include "mozilla/Mutex.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "gfxASurface.h" // for gfxImageFormat
 #include "mozilla/layers/LayersTypes.h" // for LayersBackend
 #include "mozilla/TimeStamp.h"
 #include "ImageTypes.h"
 #include "nsTArray.h"
+#include "pratom.h"
 
 #ifdef XP_WIN
 struct ID3D10Texture2D;
 struct ID3D10Device;
 struct ID3D10ShaderResourceView;
 #endif
 
 typedef void* HANDLE;
--- a/gfx/layers/d3d10/ReadbackManagerD3D10.cpp
+++ b/gfx/layers/d3d10/ReadbackManagerD3D10.cpp
@@ -33,17 +33,17 @@ struct ReadbackTask {
   // the update is delivered to the readback sink.
   nsIntPoint mBackgroundOffset;
 };
 
 // This class is created and dispatched from the Readback thread but it must be
 // destroyed by the main thread.
 class ReadbackResultWriter MOZ_FINAL : public nsIRunnable
 {
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 public:
   ReadbackResultWriter(ReadbackTask *aTask) : mTask(aTask) {}
 
   NS_IMETHODIMP Run()
   {
     ReadbackProcessor::Update *update = &mTask->mUpdate;
 
     if (!update->mLayer->GetSink()) {
@@ -90,17 +90,17 @@ public:
 
     return NS_OK;
   }
 
 private:
   nsAutoPtr<ReadbackTask> mTask;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(ReadbackResultWriter, nsIRunnable)
+NS_IMPL_ISUPPORTS1(ReadbackResultWriter, nsIRunnable)
 
 DWORD WINAPI StartTaskThread(void *aManager)
 {
   static_cast<ReadbackManagerD3D10*>(aManager)->ProcessTasks();
 
   return 0;
 }
 
--- a/gfx/thebes/gfxTypes.h
+++ b/gfx/thebes/gfxTypes.h
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * 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 GFX_TYPES_H
 #define GFX_TYPES_H
 
-#include "nsAtomicRefcnt.h"
-
 /**
  * Currently needs to be 'double' for Cairo compatibility. Could
  * become 'float', perhaps, in some configurations.
  */
 typedef double gfxFloat;
 
 /**
  * Priority of a line break opportunity.
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -120,17 +120,17 @@ public:
     if (!os) {
       NS_WARNING("Could not get observer service!");
       return;
     }
 
     os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSIOBSERVER
 
   // Run on the main thread, not the vibrator thread.
   void Vibrate(const nsTArray<uint32_t> &pattern);
   void CancelVibrate();
 
   static bool ShuttingDown() { return sShuttingDown; }
@@ -145,17 +145,17 @@ private:
   // mPattern.Length(), then we're not currently playing anything.
   uint32_t mIndex;
 
   // Set to true in our shutdown observer.  When this is true, we kill the
   // vibrator thread.
   static bool sShuttingDown;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
+NS_IMPL_ISUPPORTS2(VibratorRunnable, nsIRunnable, nsIObserver);
 
 bool VibratorRunnable::sShuttingDown = false;
 
 static StaticRefPtr<VibratorRunnable> sVibratorRunnable;
 
 NS_IMETHODIMP
 VibratorRunnable::Run()
 {
--- a/image/decoders/icon/mac/nsIconChannel.h
+++ b/image/decoders/icon/mac/nsIconChannel.h
@@ -19,17 +19,17 @@
 #include "nsIStreamListener.h"
 #include "nsIURI.h"
 
 class nsIFile;
 
 class nsIconChannel MOZ_FINAL : public nsIChannel, public nsIStreamListener
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIREQUEST
   NS_DECL_NSICHANNEL
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
 
   nsIconChannel();
   virtual ~nsIconChannel();
 
--- a/image/decoders/icon/mac/nsIconChannelCocoa.mm
+++ b/image/decoders/icon/mac/nsIconChannelCocoa.mm
@@ -29,17 +29,17 @@
 // nsIconChannel methods
 nsIconChannel::nsIconChannel()
 {
 }
 
 nsIconChannel::~nsIconChannel() 
 {}
 
-NS_IMPL_THREADSAFE_ISUPPORTS4(nsIconChannel, 
+NS_IMPL_ISUPPORTS4(nsIconChannel, 
                               nsIChannel, 
                               nsIRequest,
 			       nsIRequestObserver,
 			       nsIStreamListener)
 
 nsresult nsIconChannel::Init(nsIURI* uri)
 {
   NS_ASSERTION(uri, "no uri");
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -54,17 +54,17 @@ nsMozIconURI::nsMozIconURI()
     mIconState(-1)
 {
 }
  
 nsMozIconURI::~nsMozIconURI()
 {
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsMozIconURI, nsIMozIconURI, nsIURI)
+NS_IMPL_ISUPPORTS2(nsMozIconURI, nsIMozIconURI, nsIURI)
 
 #define MOZICON_SCHEME "moz-icon:"
 #define MOZICON_SCHEME_LEN (sizeof(MOZICON_SCHEME) - 1)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIURI methods:
 
 NS_IMETHODIMP
--- a/image/decoders/icon/nsIconURI.h
+++ b/image/decoders/icon/nsIconURI.h
@@ -17,17 +17,17 @@
     0x2d37,                                          \
     0x11d5,                                          \
     { 0x99, 0x7, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b }   \
 }
 
 class nsMozIconURI : public nsIMozIconURI
 {
 public:    
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
   NS_DECL_NSIMOZICONURI
 
   // nsMozIconURI
   nsMozIconURI();
   virtual ~nsMozIconURI();
 
 protected:
--- a/image/decoders/icon/os2/nsIconChannel.cpp
+++ b/image/decoders/icon/os2/nsIconChannel.cpp
@@ -52,17 +52,17 @@ static bool sUseRws = true;
 
 nsIconChannel::nsIconChannel()
 {
 }
 
 nsIconChannel::~nsIconChannel()
 {}
 
-NS_IMPL_THREADSAFE_ISUPPORTS4(nsIconChannel, 
+NS_IMPL_ISUPPORTS4(nsIconChannel, 
                               nsIChannel,
                               nsIRequest,
                               nsIRequestObserver,
                               nsIStreamListener)
 
 nsresult nsIconChannel::Init(nsIURI* uri)
 {
   NS_ASSERTION(uri, "no uri");
--- a/image/decoders/icon/os2/nsIconChannel.h
+++ b/image/decoders/icon/os2/nsIconChannel.h
@@ -19,17 +19,17 @@
 #include "nsIInputStreamPump.h"
 #include "nsIStreamListener.h"
 
 class nsIFile;
 
 class nsIconChannel MOZ_FINAL : public nsIChannel, public nsIStreamListener
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIREQUEST
   NS_DECL_NSICHANNEL
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
 
   nsIconChannel();
   virtual ~nsIconChannel();
 
--- a/image/decoders/icon/win/nsIconChannel.cpp
+++ b/image/decoders/icon/win/nsIconChannel.cpp
@@ -70,17 +70,17 @@ static SHSTOCKICONID GetStockIconIDForNa
 // nsIconChannel methods
 nsIconChannel::nsIconChannel()
 {
 }
 
 nsIconChannel::~nsIconChannel() 
 {}
 
-NS_IMPL_THREADSAFE_ISUPPORTS4(nsIconChannel, 
+NS_IMPL_ISUPPORTS4(nsIconChannel, 
                               nsIChannel, 
                               nsIRequest,
                               nsIRequestObserver,
                               nsIStreamListener)
 
 nsresult nsIconChannel::Init(nsIURI* uri)
 {
   NS_ASSERTION(uri, "no uri");
--- a/image/decoders/icon/win/nsIconChannel.h
+++ b/image/decoders/icon/win/nsIconChannel.h
@@ -22,17 +22,17 @@
 
 #include <windows.h>
 
 class nsIFile;
 
 class nsIconChannel MOZ_FINAL : public nsIChannel, public nsIStreamListener
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIREQUEST
   NS_DECL_NSICHANNEL
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
 
   nsIconChannel();
   ~nsIconChannel();
 
--- a/image/encoders/bmp/nsBMPEncoder.cpp
+++ b/image/encoders/bmp/nsBMPEncoder.cpp
@@ -8,17 +8,17 @@
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 
 using namespace mozilla;
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsBMPEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+NS_IMPL_ISUPPORTS3(nsBMPEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
 
 nsBMPEncoder::nsBMPEncoder() : mImageBufferStart(nullptr), 
                                mImageBufferCurr(0),
                                mImageBufferSize(0), 
                                mImageBufferReadPoint(0), 
                                mFinished(false),
                                mCallback(nullptr), 
                                mCallbackTarget(nullptr), 
--- a/image/encoders/bmp/nsBMPEncoder.h
+++ b/image/encoders/bmp/nsBMPEncoder.h
@@ -20,17 +20,17 @@
 
 // Provides BMP encoding functionality. Use InitFromData() to do the
 // encoding. See that function definition for encoding options.
 
 class nsBMPEncoder MOZ_FINAL : public imgIEncoder
 {
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsBMPEncoder();
   ~nsBMPEncoder();
 
 protected:
--- a/image/encoders/ico/nsICOEncoder.cpp
+++ b/image/encoders/ico/nsICOEncoder.cpp
@@ -10,17 +10,17 @@
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 #include "nsTArray.h"
 
 using namespace mozilla;
 using namespace mozilla::image;
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+NS_IMPL_ISUPPORTS3(nsICOEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
 
 nsICOEncoder::nsICOEncoder() : mImageBufferStart(nullptr),
                                mImageBufferCurr(0),
                                mImageBufferSize(0), 
                                mImageBufferReadPoint(0), 
                                mFinished(false),
                                mUsePNG(true),
                                mNotifyThreshold(0)
--- a/image/encoders/ico/nsICOEncoder.h
+++ b/image/encoders/ico/nsICOEncoder.h
@@ -24,17 +24,17 @@ class nsPNGEncoder;
 
 // Provides ICO encoding functionality. Use InitFromData() to do the
 // encoding. See that function definition for encoding options.
 
 class nsICOEncoder MOZ_FINAL : public imgIEncoder
 {
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsICOEncoder();
   ~nsICOEncoder();
   
   // Obtains the width of the icon directory entry
--- a/image/encoders/jpeg/nsJPEGEncoder.cpp
+++ b/image/encoders/jpeg/nsJPEGEncoder.cpp
@@ -9,17 +9,17 @@
 #include "nsStreamUtils.h"
 #include "gfxColor.h"
 
 #include <setjmp.h>
 #include "jerror.h"
 
 using namespace mozilla;
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsJPEGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+NS_IMPL_ISUPPORTS3(nsJPEGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
 
 // used to pass error info through the JPEG library
 struct encoder_error_mgr {
   jpeg_error_mgr pub;
   jmp_buf setjmp_buffer;
 };
 
 nsJPEGEncoder::nsJPEGEncoder() : mFinished(false),
--- a/image/encoders/jpeg/nsJPEGEncoder.h
+++ b/image/encoders/jpeg/nsJPEGEncoder.h
@@ -27,17 +27,17 @@ extern "C" {
 
 // Provides JPEG encoding functionality. Use InitFromData() to do the
 // encoding. See that function definition for encoding options.
 
 class nsJPEGEncoder MOZ_FINAL : public imgIEncoder
 {
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsJPEGEncoder();
 
 private:
   ~nsJPEGEncoder();
--- a/image/encoders/png/nsPNGEncoder.cpp
+++ b/image/encoders/png/nsPNGEncoder.cpp
@@ -6,17 +6,17 @@
 #include "nsCRT.h"
 #include "nsPNGEncoder.h"
 #include "prprf.h"
 #include "nsString.h"
 #include "nsStreamUtils.h"
 
 using namespace mozilla;
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsPNGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
+NS_IMPL_ISUPPORTS3(nsPNGEncoder, imgIEncoder, nsIInputStream, nsIAsyncInputStream)
 
 nsPNGEncoder::nsPNGEncoder() : mPNG(nullptr), mPNGinfo(nullptr),
                                mIsAnimation(false),
                                mFinished(false),
                                mImageBuffer(nullptr), mImageBufferSize(0),
                                mImageBufferUsed(0), mImageBufferReadPoint(0),
                                mCallback(nullptr),
                                mCallbackTarget(nullptr), mNotifyThreshold(0),
--- a/image/encoders/png/nsPNGEncoder.h
+++ b/image/encoders/png/nsPNGEncoder.h
@@ -22,17 +22,17 @@
 
 // Provides PNG encoding functionality. Use InitFromData() to do the
 // encoding. See that function definition for encoding options.
 
 class nsPNGEncoder MOZ_FINAL : public imgIEncoder
 {
   typedef mozilla::ReentrantMonitor ReentrantMonitor;
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_IMGIENCODER
   NS_DECL_NSIINPUTSTREAM
   NS_DECL_NSIASYNCINPUTSTREAM
 
   nsPNGEncoder();
   ~nsPNGEncoder();
 
 protected:
--- a/image/src/DiscardTracker.cpp
+++ b/image/src/DiscardTracker.cpp
@@ -3,16 +3,17 @@
  * 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 "nsComponentManagerUtils.h"
 #include "nsITimer.h"
 #include "RasterImage.h"
 #include "DiscardTracker.h"
 #include "mozilla/Preferences.h"
+#include "pratom.h"
 
 namespace mozilla {
 namespace image {
 
 static const char* sDiscardTimeoutPref = "image.mem.min_discard_timeout_ms";
 
 /* static */ LinkedList<DiscardTracker::Node> DiscardTracker::sDiscardableImages;
 /* static */ nsCOMPtr<nsITimer> DiscardTracker::sTimer;
--- a/image/src/DiscardTracker.h
+++ b/image/src/DiscardTracker.h
@@ -3,16 +3,17 @@
  * 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 mozilla_imagelib_DiscardTracker_h_
 #define mozilla_imagelib_DiscardTracker_h_
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/TimeStamp.h"
+#include "prlock.h"
 
 class nsITimer;
 
 namespace mozilla {
 namespace image {
 
 class RasterImage;
 
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -368,19 +368,19 @@ private:
 
 namespace mozilla {
 namespace image {
 
 /* static */ StaticRefPtr<RasterImage::DecodePool> RasterImage::DecodePool::sSingleton;
 static nsCOMPtr<nsIThread> sScaleWorkerThread = nullptr;
 
 #ifndef DEBUG
-NS_IMPL_THREADSAFE_ISUPPORTS2(RasterImage, imgIContainer, nsIProperties)
+NS_IMPL_ISUPPORTS2(RasterImage, imgIContainer, nsIProperties)
 #else
-NS_IMPL_THREADSAFE_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
+NS_IMPL_ISUPPORTS3(RasterImage, imgIContainer, nsIProperties,
                               imgIContainerDebug)
 #endif
 
 //******************************************************************************
 RasterImage::RasterImage(imgStatusTracker* aStatusTracker,
                          nsIURI* aURI /* = nullptr */) :
   ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
   mSize(0,0),
@@ -2982,17 +2982,17 @@ RasterImage::FinishedSomeDecoding(eShutd
       }
     }
 
   }
 
   return rv;
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(RasterImage::DecodePool,
+NS_IMPL_ISUPPORTS1(RasterImage::DecodePool,
                               nsIObserver)
 
 /* static */ RasterImage::DecodePool*
 RasterImage::DecodePool::Singleton()
 {
   if (!sSingleton) {
     MOZ_ASSERT(NS_IsMainThread());
     sSingleton = new DecodePool();
--- a/image/src/RasterImage.h
+++ b/image/src/RasterImage.h
@@ -138,17 +138,17 @@ class FrameAnimator;
 class RasterImage : public ImageResource
                   , public nsIProperties
                   , public SupportsWeakPtr<RasterImage>
 #ifdef DEBUG
                   , public imgIContainerDebug
 #endif
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPROPERTIES
   NS_DECL_IMGICONTAINER
 #ifdef DEBUG
   NS_DECL_IMGICONTAINERDEBUG
 #endif
 
   // (no public constructor - use ImageFactory)
   virtual ~RasterImage();
@@ -379,17 +379,17 @@ private:
    *
    * When the DecodePool is run from the event queue, it decodes the image (and
    * all others it's managing) in chunks, periodically yielding control back to
    * the event loop.
    */
   class DecodePool : public nsIObserver
   {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIOBSERVER
 
     static DecodePool* Singleton();
 
     /**
      * Ask the DecodePool to asynchronously decode this image.
      */
     void RequestDecode(RasterImage* aImg);
--- a/intl/locale/src/mac/nsDateTimeFormatMac.cpp
+++ b/intl/locale/src/mac/nsDateTimeFormatMac.cpp
@@ -11,17 +11,17 @@
 #include "nsLocaleCID.h"
 #include "nsILocaleService.h"
 #include "nsCRT.h"
 #include "plstr.h"
 #include "nsUnicharUtils.h"
 #include "nsTArray.h"
 
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatMac, nsIDateTimeFormat)
+NS_IMPL_ISUPPORTS1(nsDateTimeFormatMac, nsIDateTimeFormat)
 
 nsresult nsDateTimeFormatMac::Initialize(nsILocale* locale)
 {
   nsAutoString localeStr;
   nsAutoString category(NS_LITERAL_STRING("NSILOCALE_TIME"));
   nsresult res;
 
   // use cached info if match with stored locale
--- a/intl/locale/src/mac/nsDateTimeFormatMac.h
+++ b/intl/locale/src/mac/nsDateTimeFormatMac.h
@@ -10,17 +10,17 @@
 
 #include "nsCOMPtr.h"
 #include "nsIDateTimeFormat.h"
 
 
 class nsDateTimeFormatMac : public nsIDateTimeFormat {
 
 public: 
-  NS_DECL_ISUPPORTS 
+  NS_DECL_THREADSAFE_ISUPPORTS 
 
   // performs a locale sensitive date formatting operation on the time_t parameter
   NS_IMETHOD FormatTime(nsILocale* locale, 
                         const nsDateFormatSelector  dateFormatSelector, 
                         const nsTimeFormatSelector timeFormatSelector, 
                         const time_t  timetTime, 
                         nsAString& stringOut); 
 
--- a/intl/locale/src/nsLocale.cpp
+++ b/intl/locale/src/nsLocale.cpp
@@ -13,17 +13,17 @@
 #include "nsVoidArray.h"
 #include "nsMemory.h"
 #include "nsCRT.h"
 
 #define LOCALE_HASH_SIZE  0xFF
 
 
 /* nsILocale */
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsLocale, nsILocale)
+NS_IMPL_ISUPPORTS1(nsLocale, nsILocale)
 
 nsLocale::nsLocale(void)
 :  fHashtable(nullptr), fCategoryCount(0)
 {
   fHashtable = PL_NewHashTable(LOCALE_HASH_SIZE,&nsLocale::Hash_HashFunction,
                                &nsLocale::Hash_CompareNSString,
                                &nsLocale::Hash_CompareNSString,
                                nullptr, nullptr);
--- a/intl/locale/src/nsLocale.h
+++ b/intl/locale/src/nsLocale.h
@@ -22,17 +22,17 @@
 
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsILocale.h"
 #include "plhash.h"
 
 class nsLocale : public nsILocale {
 	friend class nsLocaleService;
-	NS_DECL_ISUPPORTS
+	NS_DECL_THREADSAFE_ISUPPORTS
 
 public:
 	nsLocale(void);
 	virtual ~nsLocale(void);
 	
 	/* Declare methods from nsILocale */
 	NS_DECL_NSILOCALE
 
--- a/intl/locale/src/nsLocaleService.cpp
+++ b/intl/locale/src/nsLocaleService.cpp
@@ -72,17 +72,17 @@ static int posix_locale_category[LocaleL
 //
 class nsLocaleService: public nsILocaleService {
 
 public:
 	
 	//
 	// nsISupports
 	//
-	NS_DECL_ISUPPORTS
+	NS_DECL_THREADSAFE_ISUPPORTS
 
 	//
 	// nsILocaleService
 	//
     NS_DECL_NSILOCALESERVICE
 
 
 	nsLocaleService(void);
@@ -246,17 +246,17 @@ nsLocaleService::nsLocaleService(void)
     NS_ASSERTION(mApplicationLocale, "Failed to create locale objects");
 #endif // XP_MACOSX
 }
 
 nsLocaleService::~nsLocaleService(void)
 {
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsLocaleService, nsILocaleService)
+NS_IMPL_ISUPPORTS1(nsLocaleService, nsILocaleService)
 
 NS_IMETHODIMP
 nsLocaleService::NewLocale(const nsAString &aLocale, nsILocale **_retval)
 {
     nsresult result;
 
     *_retval = nullptr;
 
--- a/intl/locale/src/os2/nsDateTimeFormatOS2.cpp
+++ b/intl/locale/src/os2/nsDateTimeFormatOS2.cpp
@@ -1,16 +1,16 @@
 /* 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 <unidef.h>
 #include "nsDateTimeFormatOS2.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatOS2,nsIDateTimeFormat)
+NS_IMPL_ISUPPORTS1(nsDateTimeFormatOS2,nsIDateTimeFormat)
 
 #define NSDATETIME_FORMAT_BUFFER_LEN  80
 
 #ifndef LOCI_iTime
 #define LOCI_iTime   ((LocaleItem)73)
 #endif
 
 nsresult nsDateTimeFormatOS2::FormatTime(nsILocale* locale, 
--- a/intl/locale/src/os2/nsDateTimeFormatOS2.h
+++ b/intl/locale/src/os2/nsDateTimeFormatOS2.h
@@ -4,17 +4,17 @@
 #ifndef _nsdatetimeformatos2_h_
 #define _nsdatetimeformatos2_h_
 
 #include "nsIDateTimeFormat.h"
 
 class nsDateTimeFormatOS2 : public nsIDateTimeFormat {
 
  public:
-   NS_DECL_ISUPPORTS
+   NS_DECL_THREADSAFE_ISUPPORTS
    
   // performs a locale sensitive date formatting operation on the time_t parameter
   NS_IMETHOD FormatTime(nsILocale* locale, 
                         const nsDateFormatSelector  dateFormatSelector, 
                         const nsTimeFormatSelector timeFormatSelector, 
                         const time_t  timetTime, 
                         nsAString& stringOut);
 
--- a/intl/locale/src/unix/nsAndroidCharset.cpp
+++ b/intl/locale/src/unix/nsAndroidCharset.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "nsIPlatformCharset.h"
 #include "nsPlatformCharset.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsPlatformCharset, nsIPlatformCharset)
+NS_IMPL_ISUPPORTS1(nsPlatformCharset, nsIPlatformCharset)
 
 nsPlatformCharset::nsPlatformCharset()
 {
 }
 
 nsPlatformCharset::~nsPlatformCharset()
 {
 }
--- a/intl/locale/src/unix/nsDateTimeFormatUnix.cpp
+++ b/intl/locale/src/unix/nsDateTimeFormatUnix.cpp
@@ -10,17 +10,17 @@
 #include "nsIComponentManager.h"
 #include "nsILocaleService.h"
 #include "nsIPlatformCharset.h"
 #include "nsPosixLocale.h"
 #include "nsCRT.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatUnix, nsIDateTimeFormat)
+NS_IMPL_ISUPPORTS1(nsDateTimeFormatUnix, nsIDateTimeFormat)
 
 // init this interface to a specified locale
 nsresult nsDateTimeFormatUnix::Initialize(nsILocale* locale)
 {
   nsAutoString localeStr;
   NS_NAMED_LITERAL_STRING(aCategory, "NSILOCALE_TIME##PLATFORM");
   nsresult res = NS_OK;
 
--- a/intl/locale/src/unix/nsDateTimeFormatUnix.h
+++ b/intl/locale/src/unix/nsDateTimeFormatUnix.h
@@ -12,17 +12,17 @@
 #include "nsCOMPtr.h"
 #include "nsIDateTimeFormat.h"
 
 #define kPlatformLocaleLength 64
 
 class nsDateTimeFormatUnix : public nsIDateTimeFormat {
 
 public: 
-  NS_DECL_ISUPPORTS 
+  NS_DECL_THREADSAFE_ISUPPORTS 
 
   // performs a locale sensitive date formatting operation on the time_t parameter
   NS_IMETHOD FormatTime(nsILocale* locale, 
                         const nsDateFormatSelector  dateFormatSelector, 
                         const nsTimeFormatSelector timeFormatSelector, 
                         const time_t  timetTime, 
                         nsAString& stringOut); 
 
--- a/intl/locale/src/unix/nsUNIXCharset.cpp
+++ b/intl/locale/src/unix/nsUNIXCharset.cpp
@@ -31,17 +31,17 @@
 #include "nsUnicharUtils.h"
 
 using namespace mozilla;
 
 static const char* kUnixCharsets[][3] = {
 #include "unixcharset.properties.h"
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsPlatformCharset, nsIPlatformCharset)
+NS_IMPL_ISUPPORTS1(nsPlatformCharset, nsIPlatformCharset)
 
 nsPlatformCharset::nsPlatformCharset()
 {
 }
 
 static nsresult
 ConvertLocaleToCharsetUsingDeprecatedConfig(const nsACString& locale,
                                             nsACString& oResult)
--- a/intl/locale/src/windows/nsDateTimeFormatWin.cpp
+++ b/intl/locale/src/windows/nsDateTimeFormatWin.cpp
@@ -11,17 +11,17 @@
 #include "nsWin32Locale.h"
 #include "nsUnicharUtils.h"
 #include "nsCRT.h"
 #include "nsCOMPtr.h"
 
 
 #define NSDATETIMEFORMAT_BUFFER_LEN  80
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDateTimeFormatWin, nsIDateTimeFormat)
+NS_IMPL_ISUPPORTS1(nsDateTimeFormatWin, nsIDateTimeFormat)
 
 
 // init this interface to a specified locale
 nsresult nsDateTimeFormatWin::Initialize(nsILocale* locale)
 {
   nsAutoString localeStr;
   nsresult res = NS_OK;
 
--- a/intl/locale/src/windows/nsDateTimeFormatWin.h
+++ b/intl/locale/src/windows/nsDateTimeFormatWin.h
@@ -12,17 +12,17 @@
 #include <windows.h>
 
 
 // Locale sensitive date and time format interface
 // 
 class nsDateTimeFormatWin : public nsIDateTimeFormat {
 
 public: 
-  NS_DECL_ISUPPORTS 
+  NS_DECL_THREADSAFE_ISUPPORTS 
 
   // performs a locale sensitive date formatting operation on the time_t parameter
   NS_IMETHOD FormatTime(nsILocale* locale, 
                         const nsDateFormatSelector  dateFormatSelector, 
                         const nsTimeFormatSelector timeFormatSelector, 
                         const time_t  timetTime, 
                         nsAString& stringOut); 
 
--- a/intl/strres/src/nsStringBundle.cpp
+++ b/intl/strres/src/nsStringBundle.cpp
@@ -193,18 +193,17 @@ nsStringBundle::FormatStringFromName(con
   nsAutoString formatStr;
   rv = GetStringFromName(nsDependentString(aName), formatStr);
   if (NS_FAILED(rv)) return rv;
 
   return FormatString(formatStr.get(), aParams, aLength, aResult);
 }
                                      
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsStringBundle,
-                              nsIStringBundle)
+NS_IMPL_ISUPPORTS1(nsStringBundle, nsIStringBundle)
 
 /* void GetStringFromID (in long aID, out wstring aResult); */
 NS_IMETHODIMP
 nsStringBundle::GetStringFromID(int32_t aID, PRUnichar **aResult)
 {
   nsresult rv;
   rv = LoadProperties();
   if (NS_FAILED(rv)) return rv;
@@ -517,20 +516,20 @@ nsStringBundleService::nsStringBundleSer
                    sizeof(bundleCacheEntry_t)*MAX_CACHED_BUNDLES,
                    sizeof(bundleCacheEntry_t));
 
   mErrorService = do_GetService(kErrorServiceCID);
   NS_ASSERTION(mErrorService, "Couldn't get error service");
 
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsStringBundleService,
-                              nsIStringBundleService,
-                              nsIObserver,
-                              nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS3(nsStringBundleService,
+                   nsIStringBundleService,
+                   nsIObserver,
+                   nsISupportsWeakReference)
 
 nsStringBundleService::~nsStringBundleService()
 {
   flushBundleCache();
   PL_FinishArenaPool(&mCacheEntryPool);
 }
 
 nsresult
--- a/intl/strres/src/nsStringBundle.h
+++ b/intl/strres/src/nsStringBundle.h
@@ -17,17 +17,17 @@
 class nsStringBundle : public nsIStringBundle
 {
 public:
     // init version
     nsStringBundle(const char* aURLSpec, nsIStringBundleOverride*);
     nsresult LoadProperties();
     virtual ~nsStringBundle();
   
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSISTRINGBUNDLE
 
     nsCOMPtr<nsIPersistentProperties> mProps;
 
 protected:
     //
     // functional decomposition of the funitions repeatively called 
     //
--- a/intl/strres/src/nsStringBundleService.h
+++ b/intl/strres/src/nsStringBundleService.h
@@ -26,17 +26,17 @@ class nsStringBundleService : public nsI
                               public nsSupportsWeakReference
 {
 public:
   nsStringBundleService();
   virtual ~nsStringBundleService();
 
   nsresult Init();
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISTRINGBUNDLESERVICE
   NS_DECL_NSIOBSERVER
     
 private:
   nsresult getStringBundle(const char *aUrl, nsIStringBundle** aResult);
   nsresult FormatWithBundle(nsIStringBundle* bundle, nsresult aStatus, 
                             uint32_t argCount, PRUnichar** argArray,
                             PRUnichar* *result);
--- a/intl/uconv/src/nsCharsetConverterManager.cpp
+++ b/intl/uconv/src/nsCharsetConverterManager.cpp
@@ -26,18 +26,17 @@
 // just for CONTRACTIDs
 #include "nsCharsetConverterManager.h"
 
 static nsIStringBundle * sDataBundle;
 static nsIStringBundle * sTitleBundle;
 
 // Class nsCharsetConverterManager [implementation]
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsCharsetConverterManager,
-                              nsICharsetConverterManager)
+NS_IMPL_ISUPPORTS1(nsCharsetConverterManager, nsICharsetConverterManager)
 
 nsCharsetConverterManager::nsCharsetConverterManager() 
 {
 }
 
 nsCharsetConverterManager::~nsCharsetConverterManager() 
 {
 }
--- a/intl/uconv/src/nsCharsetConverterManager.h
+++ b/intl/uconv/src/nsCharsetConverterManager.h
@@ -12,17 +12,17 @@
 #include "mozilla/Mutex.h"
 
 class nsCharsetAlias;
 
 class nsCharsetConverterManager : public nsICharsetConverterManager
 {
   friend class nsCharsetAlias;
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSICHARSETCONVERTERMANAGER
 
 public:
   nsCharsetConverterManager();
   virtual ~nsCharsetConverterManager();
 
   static void Shutdown();
 
--- a/intl/uconv/src/nsScriptableUConv.cpp
+++ b/intl/uconv/src/nsScriptableUConv.cpp
@@ -1,24 +1,24 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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 "nsAtomicRefcnt.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIScriptableUConv.h"
 #include "nsScriptableUConv.h"
 #include "nsIStringStream.h"
 #include "nsCRT.h"
 #include "nsComponentManagerUtils.h"
 #include "nsCharsetAlias.h"
+#include "pratom.h"
 
 static int32_t          gInstanceCount = 0;
 
 /* Implementation file */
 NS_IMPL_ISUPPORTS1(nsScriptableUnicodeConverter, nsIScriptableUnicodeConverter)
 
 nsScriptableUnicodeConverter::nsScriptableUnicodeConverter()
 : mIsInternal(false)
--- a/intl/uconv/util/nsUCSupport.cpp
+++ b/intl/uconv/util/nsUCSupport.cpp
@@ -25,21 +25,21 @@ nsBasicDecoderSupport::nsBasicDecoderSup
 nsBasicDecoderSupport::~nsBasicDecoderSupport()
 {
 }
 
 //----------------------------------------------------------------------
 // Interface nsISupports [implementation]
 
 #ifdef DEBUG
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsBasicDecoderSupport,
-                              nsIUnicodeDecoder,
-                              nsIBasicDecoder)
+NS_IMPL_ISUPPORTS2(nsBasicDecoderSupport,
+                   nsIUnicodeDecoder,
+                   nsIBasicDecoder)
 #else
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsBasicDecoderSupport, nsIUnicodeDecoder)
+NS_IMPL_ISUPPORTS1(nsBasicDecoderSupport, nsIUnicodeDecoder)
 #endif
 
 //----------------------------------------------------------------------
 // Interface nsIUnicodeDecoder [implementation]
 
 void
 nsBasicDecoderSupport::SetInputErrorBehavior(int32_t aBehavior)
 {
--- a/intl/uconv/util/nsUCSupport.h
+++ b/intl/uconv/util/nsUCSupport.h
@@ -64,17 +64,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIBasicEn
  * @created         19/Apr/1999
  * @author  Catalin Rotaru [CATA]
  */
 class nsBasicDecoderSupport : public nsIUnicodeDecoder
 #ifdef DEBUG
                               ,public nsIBasicDecoder
 #endif
 {
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
 
 public:
 
   /**
    * Class constructor.
    */
   nsBasicDecoderSupport();
 
--- a/intl/unicharutil/src/nsCaseConversionImp2.cpp
+++ b/intl/unicharutil/src/nsCaseConversionImp2.cpp
@@ -11,17 +11,17 @@ NS_IMETHODIMP_(nsrefcnt) nsCaseConversio
   return (nsrefcnt)1;
 }
 
 NS_IMETHODIMP_(nsrefcnt) nsCaseConversionImp2::Release(void)
 {
   return (nsrefcnt)1;
 }
 
-NS_IMPL_THREADSAFE_QUERY_INTERFACE1(nsCaseConversionImp2, nsICaseConversion)
+NS_IMPL_QUERY_INTERFACE1(nsCaseConversionImp2, nsICaseConversion)
 
 NS_IMETHODIMP nsCaseConversionImp2::ToUpper(PRUnichar aChar, PRUnichar* aReturn)
 {
   *aReturn = ToUpperCase(aChar);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsCaseConversionImp2::ToLower(PRUnichar aChar, PRUnichar* aReturn)
--- a/intl/unicharutil/src/nsCaseConversionImp2.h
+++ b/intl/unicharutil/src/nsCaseConversionImp2.h
@@ -7,17 +7,17 @@
 #define nsCaseConversionImp2_h__
 
 #include "nscore.h"
 #include "nsISupports.h"
 
 #include "nsICaseConversion.h"
 
 class nsCaseConversionImp2 : public nsICaseConversion { 
-  NS_DECL_ISUPPORTS 
+  NS_DECL_THREADSAFE_ISUPPORTS 
 
 public:
   virtual ~nsCaseConversionImp2() { }
 
   static nsCaseConversionImp2* GetInstance();
 
   NS_IMETHOD ToUpper(PRUnichar aChar, PRUnichar* aReturn);
 
--- a/intl/unicharutil/src/nsCategoryImp.cpp
+++ b/intl/unicharutil/src/nsCategoryImp.cpp
@@ -5,17 +5,17 @@
 
 #include "nscore.h"
 #include "nsISupports.h"
 #include "nsCategoryImp.h"
 #include "nsUnicodeProperties.h"
 
 static nsCategoryImp gCategoryImp;
 
-NS_IMPL_THREADSAFE_QUERY_INTERFACE1(nsCategoryImp, nsIUGenCategory)
+NS_IMPL_QUERY_INTERFACE1(nsCategoryImp, nsIUGenCategory)
 
 NS_IMETHODIMP_(nsrefcnt) nsCategoryImp::AddRef(void)
 {
   return nsrefcnt(1);
 }
 
 NS_IMETHODIMP_(nsrefcnt) nsCategoryImp::Release(void)
 {
--- a/intl/unicharutil/src/nsCategoryImp.h
+++ b/intl/unicharutil/src/nsCategoryImp.h
@@ -3,17 +3,17 @@
  * 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 nsCategoryImp_h__
 #define nsCategoryImp_h__
 
 #include "nsIUGenCategory.h"
 
 class nsCategoryImp : public nsIUGenCategory {
-   NS_DECL_ISUPPORTS
+   NS_DECL_THREADSAFE_ISUPPORTS
    
 public:
    static nsCategoryImp* GetInstance();
     
    /**
     * Give a Unichar, return a nsUGenCategory
     */
    virtual nsUGenCategory Get(uint32_t aChar);
--- a/ipc/chromium/src/base/message_loop.cc
+++ b/ipc/chromium/src/base/message_loop.cc
@@ -27,16 +27,17 @@
 #include "base/message_pump_qt.h"
 #endif
 #endif
 #ifdef ANDROID
 #include "base/message_pump_android.h"
 #endif
 
 #include "MessagePump.h"
+#include "pratom.h"
 
 using base::Time;
 using base::TimeDelta;
 using base::TimeTicks;
 
 // A lazily created thread local storage for quick access to a thread's message
 // loop, if one exists.  This should be safe and free of static constructors.
 static base::LazyInstance<base::ThreadLocalPointer<MessageLoop> > lazy_tls_ptr(
--- a/ipc/glue/FileDescriptorUtils.cpp
+++ b/ipc/glue/FileDescriptorUtils.cpp
@@ -31,17 +31,17 @@ CloseFileRunnable::~CloseFileRunnable()
 {
   if (mFileDescriptor.IsValid()) {
     // It's probably safer to take the main thread IO hit here rather than leak
     // the file descriptor.
     CloseFile();
   }
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(CloseFileRunnable, nsIRunnable)
+NS_IMPL_ISUPPORTS1(CloseFileRunnable, nsIRunnable)
 
 void
 CloseFileRunnable::Dispatch()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIEventTarget> eventTarget =
     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
--- a/ipc/glue/FileDescriptorUtils.h
+++ b/ipc/glue/FileDescriptorUtils.h
@@ -26,17 +26,17 @@ public:
   CloseFileRunnable(const FileDescriptor& aFileDescriptor)
 #ifdef DEBUG
   ;
 #else
   : mFileDescriptor(aFileDescriptor)
   { }
 #endif
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
   void Dispatch();
 
 private:
   ~CloseFileRunnable();
 
   void CloseFile();
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -18,17 +18,17 @@
 #include "AndroidBridge.h"
 #endif
 
 using mozilla::ipc::DoWorkRunnable;
 using mozilla::ipc::MessagePump;
 using mozilla::ipc::MessagePumpForChildProcess;
 using base::TimeTicks;
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
+NS_IMPL_ISUPPORTS2(DoWorkRunnable, nsIRunnable, nsITimerCallback)
 
 NS_IMETHODIMP
 DoWorkRunnable::Run()
 {
   MessageLoop* loop = MessageLoop::current();
   NS_ASSERTION(loop, "Shouldn't be null!");
   if (loop) {
     bool nestableTasksAllowed = loop->NestableTasksAllowed();
--- a/ipc/glue/MessagePump.h
+++ b/ipc/glue/MessagePump.h
@@ -24,17 +24,17 @@ class MessagePump;
 
 class DoWorkRunnable MOZ_FINAL : public nsIRunnable,
                                  public nsITimerCallback
 {
 public:
   DoWorkRunnable(MessagePump* aPump)
   : mPump(aPump) { }
 
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
   NS_DECL_NSITIMERCALLBACK
 
 private:
   MessagePump* mPump;
 };
 
 class MessagePump : public base::MessagePumpDefault
--- a/ipc/glue/RPCChannel.h
+++ b/ipc/glue/RPCChannel.h
@@ -10,17 +10,17 @@
 #include <stdio.h>
 
 #include <deque>
 #include <stack>
 #include <vector>
 
 #include "base/basictypes.h"
 
-#include "nsAtomicRefcnt.h"
+#include "nsISupportsImpl.h"
 
 #include "mozilla/ipc/SyncChannel.h"
 #include "nsAutoPtr.h"
 
 namespace mozilla {
 namespace ipc {
 //-----------------------------------------------------------------------------
 
@@ -387,32 +387,25 @@ private:
     //
     // All dequeuing tasks require a single point of cancellation,
     // which is handled via a reference-counted task.
     //
     class RefCountedTask
     {
       public:
         RefCountedTask(CancelableTask* aTask)
-        : mTask(aTask)
-        , mRefCnt(0) {}
+        : mTask(aTask) {}
         ~RefCountedTask() { delete mTask; }
         void Run() { mTask->Run(); }
         void Cancel() { mTask->Cancel(); }
-        void AddRef() {
-            NS_AtomicIncrementRefcnt(mRefCnt);
-        }
-        void Release() {
-            if (NS_AtomicDecrementRefcnt(mRefCnt) == 0)
-                delete this;
-        }
+
+        NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RefCountedTask)
 
       private:
         CancelableTask* mTask;
-        nsrefcnt mRefCnt;
     };
 
     //
     // Wrap an existing task which can be cancelled at any time
     // without the wrapper's knowledge.
     //
     class DequeueTask : public Task
     {
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -733,28 +733,28 @@ jsds_ScriptHookProc (JSDContext* jsdc, J
 }
 
 /*******************************************************************************
  * reflected jsd data structures
  *******************************************************************************/
 
 /* Contexts */
 /*
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral);
+NS_IMPL_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral);
 
 NS_IMETHODIMP
 jsdContext::GetJSDContext(JSDContext **_rval)
 {
     *_rval = mCx;
     return NS_OK;
 }
 */
 
 /* Objects */
-NS_IMPL_THREADSAFE_ISUPPORTS1(jsdObject, jsdIObject)
+NS_IMPL_ISUPPORTS1(jsdObject, jsdIObject)
 
 NS_IMETHODIMP
 jsdObject::GetJSDContext(JSDContext **_rval)
 {
     *_rval = mCx;
     return NS_OK;
 }
 
@@ -798,17 +798,17 @@ jsdObject::GetValue(jsdIValue **_rval)
 {
     JSDValue *jsdv = JSD_GetValueForObject (mCx, mObject);
     
     *_rval = jsdValue::FromPtr (mCx, jsdv);
     return NS_OK;
 }
 
 /* Properties */
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdProperty, jsdIProperty, jsdIEphemeral)
+NS_IMPL_ISUPPORTS2(jsdProperty, jsdIProperty, jsdIEphemeral)
 
 jsdProperty::jsdProperty (JSDContext *aCx, JSDProperty *aProperty) :
     mCx(aCx), mProperty(aProperty)
 {
     DEBUG_CREATE ("jsdProperty", gPropertyCount);
     mValid = (aCx && aProperty);
     mLiveListEntry.value = this;
     jsds_InsertEphemeral (&gLiveProperties, &mLiveListEntry);
@@ -889,17 +889,17 @@ jsdProperty::GetValue(jsdIValue **_rval)
 {
     JSDValue *jsdv = JSD_GetPropertyValue (mCx, mProperty);
     
     *_rval = jsdValue::FromPtr (mCx, jsdv);
     return NS_OK;
 }
 
 /* Scripts */
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
+NS_IMPL_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
 
 static NS_IMETHODIMP
 AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str)
 {
     if (!str) {
         x->SetLength(0);
         return NS_OK;
     }
@@ -1546,17 +1546,17 @@ jsdScript::ClearAllBreakpoints()
     ASSERT_VALID_EPHEMERAL;
     JSD_LockScriptSubsystem(mCx);
     JSD_ClearAllExecutionHooksForScript (mCx, mScript);
     JSD_UnlockScriptSubsystem(mCx);
     return NS_OK;
 }
 
 /* Contexts */
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral)
+NS_IMPL_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral)
 
 jsdIContext *
 jsdContext::FromPtr (JSDContext *aJSDCx, JSContext *aJSCx)
 {
     if (!aJSDCx || !aJSCx)
         return nullptr;
 
     nsCOMPtr<jsdIContext> jsdicx;
@@ -1738,17 +1738,17 @@ jsdContext::SetScriptsEnabled (bool _rva
         return NS_ERROR_NO_INTERFACE;
 
     context->SetScriptsEnabled(_rval, true);
 
     return NS_OK;
 }
 
 /* Stack Frames */
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdStackFrame, jsdIStackFrame, jsdIEphemeral)
+NS_IMPL_ISUPPORTS2(jsdStackFrame, jsdIStackFrame, jsdIEphemeral)
 
 jsdStackFrame::jsdStackFrame (JSDContext *aCx, JSDThreadState *aThreadState,
                               JSDStackFrameInfo *aStackFrameInfo) :
     mCx(aCx), mThreadState(aThreadState), mStackFrameInfo(aStackFrameInfo)
 {
     DEBUG_CREATE ("jsdStackFrame", gFrameCount);
     mValid = (aCx && aThreadState && aStackFrameInfo);
     if (mValid) {
@@ -2010,17 +2010,17 @@ jsdStackFrame::Eval (const nsAString &by
     *result = jsdValue::FromPtr (mCx, jsdv);
     if (!*result)
         return NS_ERROR_FAILURE;
     
     return NS_OK;
 }        
 
 /* Values */
-NS_IMPL_THREADSAFE_ISUPPORTS2(jsdValue, jsdIValue, jsdIEphemeral)
+NS_IMPL_ISUPPORTS2(jsdValue, jsdIValue, jsdIEphemeral)
 jsdIValue *
 jsdValue::FromPtr (JSDContext *aCx, JSDValue *aValue)
 {
     /* value will be dropped by te jsdValue destructor. */
 
     if (!aValue)
         return nullptr;
     
@@ -3262,23 +3262,23 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR
 
 /* app-start observer.  turns on the debugger at app-start.  this is inserted
  * and/or removed from the app-start category by the jsdService::initAtStartup
  * property.
  */
 class jsdASObserver MOZ_FINAL : public nsIObserver
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIOBSERVER
 
     jsdASObserver () {}    
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(jsdASObserver, nsIObserver)
+NS_IMPL_ISUPPORTS1(jsdASObserver, nsIObserver)
 
 NS_IMETHODIMP
 jsdASObserver::Observe (nsISupports *aSubject, const char *aTopic,
                         const PRUnichar *aData)
 {
     nsresult rv;
 
     // Hmm.  Why is the app-startup observer called multiple times?
@@ -3364,17 +3364,17 @@ CreateJSDGlobal(JSContext *aCx, JSClass 
 
 /********************************************************************************
  ********************************************************************************
  * graveyard
  */
 
 #if 0
 /* Thread States */
-NS_IMPL_THREADSAFE_ISUPPORTS1(jsdThreadState, jsdIThreadState); 
+NS_IMPL_ISUPPORTS1(jsdThreadState, jsdIThreadState); 
 
 NS_IMETHODIMP
 jsdThreadState::GetJSDContext(JSDContext **_rval)
 {
     *_rval = mCx;
     return NS_OK;
 }
 
--- a/js/jsd/jsd_xpc.h
+++ b/js/jsd/jsd_xpc.h
@@ -32,17 +32,17 @@ struct PCMapEntry {
     
 /*******************************************************************************
  * reflected jsd data structures
  *******************************************************************************/
 
 class jsdObject MOZ_FINAL : public jsdIObject
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDIOBJECT
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdObject (JSDContext *aCx, JSDObject *aObject) :
         mCx(aCx), mObject(aObject)
     {
     }
 
@@ -64,17 +64,17 @@ class jsdObject MOZ_FINAL : public jsdIO
     JSDContext *mCx;
     JSDObject *mObject;
 };
 
 
 class jsdProperty : public jsdIProperty
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDIPROPERTY
     NS_DECL_JSDIEPHEMERAL
     
     jsdProperty (JSDContext *aCx, JSDProperty *aProperty);
     virtual ~jsdProperty ();
     
     static jsdIProperty *FromPtr (JSDContext *aCx,
                                   JSDProperty *aProperty)
@@ -97,17 +97,17 @@ class jsdProperty : public jsdIProperty
     LiveEphemeral  mLiveListEntry;
     JSDContext    *mCx;
     JSDProperty   *mProperty;
 };
 
 class jsdScript : public jsdIScript
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDISCRIPT
     NS_DECL_JSDIEPHEMERAL
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdScript (JSDContext *aCx, JSDScript *aScript);
     virtual ~jsdScript();
     
     static jsdIScript *FromPtr (JSDContext *aCx, JSDScript *aScript)
@@ -154,17 +154,17 @@ class jsdScript : public jsdIScript
     uintptr_t   mFirstPC;
 };
 
 uint32_t jsdScript::LastTag = 0;
 
 class jsdContext : public jsdIContext
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDICONTEXT
     NS_DECL_JSDIEPHEMERAL
 
     jsdContext (JSDContext *aJSDCx, JSContext *aJSCx, nsISupports *aISCx);
     virtual ~jsdContext();
 
     static void InvalidateAll();
     static jsdIContext *FromPtr (JSDContext *aJSDCx, JSContext *aJSCx);
@@ -182,17 +182,17 @@ class jsdContext : public jsdIContext
     nsCOMPtr<nsISupports>  mISCx;
 };
 
 uint32_t jsdContext::LastTag = 0;
 
 class jsdStackFrame : public jsdIStackFrame
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDISTACKFRAME
     NS_DECL_JSDIEPHEMERAL
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdStackFrame (JSDContext *aCx, JSDThreadState *aThreadState,
                    JSDStackFrameInfo *aStackFrameInfo);
     virtual ~jsdStackFrame();
 
@@ -210,17 +210,17 @@ class jsdStackFrame : public jsdIStackFr
     JSDContext        *mCx;
     JSDThreadState    *mThreadState;
     JSDStackFrameInfo *mStackFrameInfo;
 };
 
 class jsdValue : public jsdIValue
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDIVALUE
     NS_DECL_JSDIEPHEMERAL
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdValue (JSDContext *aCx, JSDValue *aValue);
     virtual ~jsdValue();
 
     static jsdIValue *FromPtr (JSDContext *aCx, JSDValue *aValue);    
@@ -289,17 +289,17 @@ class jsdService : public jsdIDebuggerSe
 
 /* graveyard */
 
 #if 0
 
 class jsdContext : public jsdIContext
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDICONTEXT
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdContext (JSDContext *aCx) : mCx(aCx)
     {
         printf ("++++++ jsdContext\n");
     }
 
@@ -329,17 +329,17 @@ class jsdContext : public jsdIContext
     jsdContext(const jsdContext&); /* no implementation */
     
     JSDContext *mCx;
 };
 
 class jsdThreadState : public jsdIThreadState
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_JSDITHREADSTATE
 
     /* you'll normally use use FromPtr() instead of directly constructing one */
     jsdThreadState (JSDContext *aCx, JSDThreadState *aThreadState) :
         mCx(aCx), mThreadState(aThreadState)
     {
     }
 
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -164,31 +164,29 @@ CheckStackRoots(JSContext *cx);
  * which avoids creating a Rooted<JSObject*> just to pass NULL.
  */
 struct JS_PUBLIC_API(NullPtr)
 {
     static void * const constNullValue;
 };
 
 /*
- * An encapsulated pointer class for heap based GC thing pointers.
- *
- * This implements post-barriers for GC thing pointers stored on the heap. It is
- * designed to be used for all heap-based GC thing pointers outside the JS
- * engine.
+ * The Heap<T> class is a C/C++ heap-stored reference to a JS GC thing.  All
+ * members of heap classes that refer to GC thing should use Heap<T> (or
+ * possibly TenuredHeap<T>, described below).
  *
- * The template parameter T must be a JS GC thing pointer, masked pointer or
- * possible pointer, such as a JS::Value or jsid.
+ * Heap<T> wraps the complex mechanisms required to ensure GC safety for the
+ * contained reference into a C++ class that behaves similarly to a normal
+ * pointer.
  *
- * The class must be used to declare data members of heap classes only.
- * Stack-based GC thing pointers should used Rooted<T>.
+ * GC references stored on the C/C++ stack must use Rooted/Handle/MutableHandle
+ * instead.
  *
- * Write barriers are implemented by overloading the assingment operator.
- * Assiging to a Heap<T> triggers the appropriate calls into the GC to notify it
- * of the change.
+ * Requirements for type T:
+ *  - Must be one of: Value, jsid, JSObject*, JSString*, JSScript*
  */
 template <typename T>
 class Heap : public js::HeapBase<T>
 {
   public:
     Heap() {
         MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap<T>),
                           "Heap<T> must be binary compatible with T.");
@@ -252,16 +250,127 @@ class Heap : public js::HeapBase<T>
 #ifdef JSGC_GENERATIONAL
         js::GCMethods<T>::relocate(&ptr);
 #endif
     }
 
     T ptr;
 };
 
+#ifdef DEBUG
+/*
+ * For generational GC, assert that an object is in the tenured generation as
+ * opposed to being in the nursery.
+ */
+extern JS_FRIEND_API(void)
+AssertGCThingMustBeTenured(JSObject* obj);
+#else
+inline void
+AssertGCThingMustBeTenured(JSObject *obj) {}
+#endif
+
+/*
+ * The TenuredHeap<T> class is similar to the Heap<T> class above in that it
+ * encapsulates the GC concerns of an on-heap reference to a JS object. However,
+ * it has two important differences:
+ *
+ *  1) Pointers which are statically known to only reference "tenured" objects
+ *     can avoid the extra overhead of SpiderMonkey's write barriers.
+ *
+ *  2) Objects in the "tenured" heap have stronger alignment restrictions than
+ *     those in the "nursery", so it is possible to store flags in the lower
+ *     bits of pointers known to be tenured. TenuredHeap wraps a normal tagged
+ *     pointer with a nice API for accessing the flag bits and adds various
+ *     assertions to ensure that it is not mis-used.
+ *
+ * GC things are said to be "tenured" when they are located in the long-lived
+ * heap: e.g. they have gained tenure as an object by surviving past at least
+ * one GC. For performance, SpiderMonkey allocates some things which are known
+ * to normally be long lived directly into the tenured generation; for example,
+ * global objects. Additionally, SpiderMonkey does not visit individual objects
+ * when deleting non-tenured objects, so object with finalizers are also always
+ * tenured; for instance, this includes most DOM objects.
+ *
+ * The considerations to keep in mind when using a TenuredHeap<T> vs a normal
+ * Heap<T> are:
+ *
+ *  - It is invalid for a TenuredHeap<T> to refer to a non-tenured thing.
+ *  - It is however valid for a Heap<T> to refer to a tenured thing.
+ *  - It is not possible to store flag bits in a Heap<T>.
+ */
+template <typename T>
+class TenuredHeap : public js::HeapBase<T>
+{
+  public:
+    TenuredHeap() : bits(0) {
+        MOZ_STATIC_ASSERT(sizeof(T) == sizeof(TenuredHeap<T>),
+                          "TenuredHeap<T> must be binary compatible with T.");
+    }
+    explicit TenuredHeap(T p) : bits(0) { setPtr(p); }
+    explicit TenuredHeap(const TenuredHeap<T> &p) : bits(0) { setPtr(p.ptr); }
+
+    bool operator==(const TenuredHeap<T> &other) { return bits == other.bits; }
+    bool operator!=(const TenuredHeap<T> &other) { return bits != other.bits; }
+
+    void setPtr(T newPtr) {
+        JS_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
+        JS_ASSERT(!js::GCMethods<T>::poisoned(newPtr));
+        if (newPtr)
+            AssertGCThingMustBeTenured(newPtr);
+        bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);
+    }
+
+    void setFlags(uintptr_t flagsToSet) {
+        JS_ASSERT((flagsToSet & ~flagsMask) == 0);
+        bits |= flagsToSet;
+    }
+
+    void unsetFlags(uintptr_t flagsToUnset) {
+        JS_ASSERT((flagsToUnset & ~flagsMask) == 0);
+        bits &= ~flagsToUnset;
+    }
+
+    bool hasFlag(uintptr_t flag) const {
+        JS_ASSERT((flag & ~flagsMask) == 0);
+        return (bits & flag) != 0;
+    }
+
+    T getPtr() const { return reinterpret_cast<T>(bits & ~flagsMask); }
+    uintptr_t getFlags() const { return bits & flagsMask; }
+
+    operator T() const { return getPtr(); }
+    T operator->() const { return getPtr(); }
+
+    TenuredHeap<T> &operator=(T p) {
+        setPtr(p);
+        return *this;
+    }
+
+    /*
+     * Set the pointer to a value which will cause a crash if it is
+     * dereferenced.
+     */
+    void setToCrashOnTouch() {
+        bits = (bits & flagsMask) | crashOnTouchPointer;
+    }
+
+    bool isSetToCrashOnTouch() {
+        return (bits & ~flagsMask) == crashOnTouchPointer;
+    }
+
+  private:
+    enum {
+        maskBits = 3,
+        flagsMask = (1 << maskBits) - 1,
+        crashOnTouchPointer = 1 << maskBits
+    };
+
+    uintptr_t bits;
+};
+
 /*
  * Reference to a T that has been rooted elsewhere. This is most useful
  * as a parameter type, which guarantees that the T lvalue is properly
  * rooted. See "Move GC Stack Rooting" above.
  *
  * If you want to add additional methods to Handle for a specific
  * specialization, define a HandleBase<T> specialization containing them.
  */
@@ -294,26 +403,30 @@ class MOZ_NONHEAP_CLASS Handle : public 
                           "JS::NullPtr overload not valid for non-pointer types");
         ptr = reinterpret_cast<const T *>(&JS::NullPtr::constNullValue);
     }
 
     Handle(MutableHandle<T> handle) {
         ptr = handle.address();
     }
 
-    Handle(const Heap<T> &heapPtr) {
-        ptr = heapPtr.address();
-    }
-
     /*
-     * This may be called only if the location of the T is guaranteed
-     * to be marked (for some reason other than being a Rooted),
-     * e.g., if it is guaranteed to be reachable from an implicit root.
+     * Take care when calling this method!
+     *
+     * This creates a Handle from the raw location of a T.
+     *
+     * It should be called only if the following conditions hold:
      *
-     * Create a Handle from a raw location of a T.
+     *  1) the location of the T is guaranteed to be marked (for some reason
+     *     other than being a Rooted), e.g., if it is guaranteed to be reachable
+     *     from an implicit root.
+     *
+     *  2) the contents of the location are immutable, or at least cannot change
+     *     for the lifetime of the handle, as its users may not expect its value
+     *     to change underneath them.
      */
     static Handle fromMarkedLocation(const T *p) {
         Handle h;
         h.ptr = p;
         return h;
     }
 
     /*
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -235,16 +235,19 @@ endif
 
 ifdef LIBXUL_LIBRARY
 ifdef IS_COMPONENT
 $(error IS_COMPONENT is set, but is not compatible with LIBXUL_LIBRARY)
 endif
 ifdef MODULE_NAME
 $(error MODULE_NAME is $(MODULE_NAME) but MODULE_NAME and LIBXUL_LIBRARY are not compatible)
 endif
+ifdef FORCE_STATIC_LIB
+$(error Makefile sets FORCE_STATIC_LIB which was already implied by LIBXUL_LIBRARY)
+endif
 FORCE_STATIC_LIB=1
 ifneq ($(SHORT_LIBNAME),)
 $(error SHORT_LIBNAME is $(SHORT_LIBNAME) but SHORT_LIBNAME is not compatable with LIBXUL_LIBRARY)
 endif
 endif
 
 # If we are building this component into an extension/xulapp, it cannot be
 # statically linked. In the future we may want to add a xulapp meta-component
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -3320,39 +3320,40 @@ CType::Trace(JSTracer* trc, JSObject* ob
   switch (TypeCode(JSVAL_TO_INT(slot))) {
   case TYPE_struct: {
     slot = obj->getReservedSlot(SLOT_FIELDINFO);
     if (JSVAL_IS_VOID(slot))
       return;
 
     FieldInfoHash* fields =
       static_cast<FieldInfoHash*>(JSVAL_TO_PRIVATE(slot));
-    for (FieldInfoHash::Range r = fields->all(); !r.empty(); r.popFront()) {
-      JSString *key = r.front().key;
+    for (FieldInfoHash::Enum e(*fields); !e.empty(); e.popFront()) {
+      JSString *key = e.front().key;
       JS_CallStringTracer(trc, &key, "fieldName");
-      JS_ASSERT(key == r.front().key);
-      JS_CallObjectTracer(trc, &r.front().value.mType, "fieldType");
+      if (key != e.front().key)
+          e.rekeyFront(JS_ASSERT_STRING_IS_FLAT(key));
+      JS_CallHeapObjectTracer(trc, &e.front().value.mType, "fieldType");
     }
 
     break;
   }
   case TYPE_function: {
     // Check if we have a FunctionInfo.
     slot = obj->getReservedSlot(SLOT_FNINFO);
     if (JSVAL_IS_VOID(slot))
       return;
 
     FunctionInfo* fninfo = static_cast<FunctionInfo*>(JSVAL_TO_PRIVATE(slot));
     JS_ASSERT(fninfo);
 
     // Identify our objects to the tracer.
-    JS_CallObjectTracer(trc, &fninfo->mABI, "abi");
-    JS_CallObjectTracer(trc, &fninfo->mReturnType, "returnType");
+    JS_CallHeapObjectTracer(trc, &fninfo->mABI, "abi");
+    JS_CallHeapObjectTracer(trc, &fninfo->mReturnType, "returnType");
     for (size_t i = 0; i < fninfo->mArgTypes.length(); ++i)
-      JS_CallObjectTracer(trc, &fninfo->mArgTypes[i], "argType");
+      JS_CallHeapObjectTracer(trc, &fninfo->mArgTypes[i], "argType");
 
     break;
   }
   default:
     // Nothing to do here.
     break;
   }
 }
@@ -4728,16 +4729,26 @@ StructType::Create(JSContext* cx, unsign
     if (!DefineInternal(cx, result, arr))
       return JS_FALSE;
   }
 
   args.rval().setObject(*result);
   return JS_TRUE;
 }
 
+static void
+PostBarrierCallback(JSTracer *trc, void *k, void *d)
+{
+    JSString *prior = static_cast<JSString*>(k);
+    FieldInfoHash *table = static_cast<FieldInfoHash*>(d);
+    JSString *key = prior;
+    JS_CallStringTracer(trc, &key, "CType fieldName");
+    table->rekey(JS_ASSERT_STRING_IS_FLAT(prior), JS_ASSERT_STRING_IS_FLAT(key));
+}
+
 JSBool
 StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsObj_)
 {
   RootedObject typeObj(cx, typeObj_);
   RootedObject fieldsObj(cx, fieldsObj_);
 
   uint32_t len;
   ASSERT_OK(JS_GetArrayLength(cx, fieldsObj, &len));
@@ -4818,16 +4829,17 @@ StructType::DefineInternal(JSContext* cx
       }
 
       // Add field name to the hash
       FieldInfo info;
       info.mType = fieldType;
       info.mIndex = i;
       info.mOffset = fieldOffset;
       ASSERT_OK(fields->add(entryPtr, name, info));
+      JS_StoreStringPostBarrierCallback(cx, PostBarrierCallback, name, fields.get());
 
       structSize = fieldOffset + fieldSize;
 
       if (fieldAlign > structAlign)
         structAlign = fieldAlign;
     }
 
     // Pad the struct tail according to struct alignment.
@@ -6077,20 +6089,20 @@ CClosure::Trace(JSTracer* trc, JSObject*
   jsval slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO);
   if (JSVAL_IS_VOID(slot))
     return;
 
   ClosureInfo* cinfo = static_cast<ClosureInfo*>(JSVAL_TO_PRIVATE(slot));
 
   // Identify our objects to the tracer. (There's no need to identify
   // 'closureObj', since that's us.)
-  JS_CallObjectTracer(trc, &cinfo->typeObj, "typeObj");
-  JS_CallObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
+  JS_CallHeapObjectTracer(trc, &cinfo->typeObj, "typeObj");
+  JS_CallHeapObjectTracer(trc, &cinfo->jsfnObj, "jsfnObj");
   if (cinfo->thisObj)
-    JS_CallObjectTracer(trc, &cinfo->thisObj, "thisObj");
+    JS_CallHeapObjectTracer(trc, &cinfo->thisObj, "thisObj");
 }
 
 void
 CClosure::Finalize(JSFreeOp *fop, JSObject* obj)
 {
   // Make sure our ClosureInfo slot is legit. If it's not, bail.
   jsval slot = JS_GetReservedSlot(obj, SLOT_CLOSUREINFO);
   if (JSVAL_IS_VOID(slot))
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -206,19 +206,19 @@ enum TypeCode {
   TYPE_array,
   TYPE_struct
 };
 
 // Descriptor of one field in a StructType. The name of the field is stored
 // as the key to the hash entry.
 struct FieldInfo
 {
-  JSObject* mType;    // CType of the field
-  size_t    mIndex;   // index of the field in the struct (first is 0)
-  size_t    mOffset;  // offset of the field in the struct, in bytes
+  JS::Heap<JSObject*> mType;    // CType of the field
+  size_t              mIndex;   // index of the field in the struct (first is 0)
+  size_t              mOffset;  // offset of the field in the struct, in bytes
 };
 
 // Hash policy for FieldInfos.
 struct FieldHashPolicy
 {
   typedef JSFlatString* Key;
   typedef Key Lookup;
 
@@ -250,47 +250,47 @@ struct FunctionInfo
 {
   // Initialized in NewFunctionInfo when !mIsVariadic, but only later, in
   // FunctionType::Call, when mIsVariadic. Not always consistent with
   // mFFITypes, due to lazy initialization when mIsVariadic.
   ffi_cif mCIF;
 
   // Calling convention of the function. Convert to ffi_abi using GetABI
   // and OBJECT_TO_JSVAL. Stored as a JSObject* for ease of tracing.
-  JSObject* mABI;
+  JS::Heap<JSObject*> mABI;
 
   // The CType of the value returned by the function.
-  JSObject* mReturnType;
+  JS::Heap<JSObject*> mReturnType;
 
   // A fixed array of known parameter types, excluding any variadic
   // parameters (if mIsVariadic).
-  Array<JSObject*> mArgTypes; 
+  Array<JS::Heap<JSObject*> > mArgTypes;
 
   // A variable array of ffi_type*s corresponding to both known parameter
   // types and dynamic (variadic) parameter types. Longer than mArgTypes
   // only if mIsVariadic.
   Array<ffi_type*> mFFITypes;
 
   // Flag indicating whether the function behaves like a C function with
   // ... as the final formal parameter.
   bool mIsVariadic;
 };
 
 // Parameters necessary for invoking a JS function from a C closure.
 struct ClosureInfo
 {
-  JSContext* cx;         // JSContext to use
-  JSRuntime* rt;         // Used in the destructor, where cx might have already
-                         // been GCed.
-  JSObject* closureObj;  // CClosure object
-  JSObject* typeObj;     // FunctionType describing the C function
-  JSObject* thisObj;     // 'this' object to use for the JS function call
-  JSObject* jsfnObj;     // JS function
-  void* errResult;       // Result that will be returned if the closure throws
-  ffi_closure* closure;  // The C closure itself
+  JSContext* cx;                   // JSContext to use
+  JSRuntime* rt;                   // Used in the destructor, where cx might have already
+                                   // been GCed.
+  JS::Heap<JSObject*> closureObj;  // CClosure object
+  JS::Heap<JSObject*> typeObj;     // FunctionType describing the C function
+  JS::Heap<JSObject*> thisObj;     // 'this' object to use for the JS function call
+  JS::Heap<JSObject*> jsfnObj;     // JS function
+  void* errResult;                 // Result that will be returned if the closure throws
+  ffi_closure* closure;            // The C closure itself
 
   // Anything conditionally freed in the destructor should be initialized to
   // NULL here.
   ClosureInfo(JSRuntime* runtime)
     : rt(runtime)
     , errResult(NULL)
     , closure(NULL)
   {}
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -766,17 +766,17 @@ js::gc::MarkRuntime(JSTracer *trc, bool 
     /* The embedding can register additional roots here. */
     for (size_t i = 0; i < rt->gcBlackRootTracers.length(); i++) {
         const JSRuntime::ExtraTracer &e = rt->gcBlackRootTracers[i];
         (*e.op)(trc, e.data);
     }
 
     /* During GC, we don't mark gray roots at this stage. */
     if (JSTraceDataOp op = rt->gcGrayRootTracer.op) {
-        if (!IS_GC_MARKING_TRACER(trc))
+        if (!IS_GC_MARKING_TRACER(trc) && !trc->runtime->isHeapMinorCollecting())
             (*op)(trc, rt->gcGrayRootTracer.data);
     }
 }
 
 void
 js::gc::BufferGrayRoots(GCMarker *gcmarker)
 {
     JSRuntime *rt = gcmarker->runtime;
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -351,27 +351,28 @@ class StoreBuffer
         bool isNullEdge() const { return false; }
 
         void mark(JSTracer *trc);
     };
 
     class CallbackRef : public BufferableRef
     {
       public:
-        typedef void (*MarkCallback)(JSTracer *trc, void *key);
+        typedef void (*MarkCallback)(JSTracer *trc, void *key, void *data);
 
-        CallbackRef(MarkCallback cb, void *k) : callback(cb), key(k) {}
+        CallbackRef(MarkCallback cb, void *k, void *d) : callback(cb), key(k), data(d) {}
 
         virtual void mark(JSTracer *trc) {
-            callback(trc, key);
+            callback(trc, key, data);
         }
 
       private:
         MarkCallback callback;
         void *key;
+        void *data;
     };
 
     MonoTypeBuffer<ValueEdge> bufferVal;
     MonoTypeBuffer<CellPtrEdge> bufferCell;
     MonoTypeBuffer<SlotEdge> bufferSlot;
     MonoTypeBuffer<WholeCellEdges> bufferWholeCell;
     RelocatableMonoTypeBuffer<ValueEdge> bufferRelocVal;
     RelocatableMonoTypeBuffer<CellPtrEdge> bufferRelocCell;
@@ -446,18 +447,19 @@ class StoreBuffer
 
     /* Insert an entry into the generic buffer. */
     template <typename T>
     void putGeneric(const T &t) {
         bufferGeneric.put(t);
     }
 
     /* Insert or update a callback entry. */
-    void putCallback(CallbackRef::MarkCallback callback, void *key) {
-        bufferGeneric.put(CallbackRef(callback, key));
+    void putCallback(CallbackRef::MarkCallback callback, Cell *key, void *data) {
+        if (!key->isTenured())
+            bufferGeneric.put(CallbackRef(callback, key, data));
     }
 
     /* Mark the source of all edges in the store buffer. */
     void mark(JSTracer *trc);
 
     /* We cannot call InParallelSection directly because of a circular dependency. */
     bool inParallelSection() const;
 
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 "ion/MIR.h"
 
-#include "mozilla/Casting.h"
+#include "mozilla/FloatingPoint.h"
 
 #include "ion/BaselineInspector.h"
 #include "ion/IonBuilder.h"
 #include "ion/LICM.h" // For LinearSum
 #include "ion/MIRGraph.h"
 #include "ion/EdgeCaseAnalysis.h"
 #include "ion/RangeAnalysis.h"
 #include "ion/IonSpewer.h"
@@ -21,17 +21,17 @@
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 
 #include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::ion;
 
-using mozilla::BitwiseCast;
+using mozilla::DoublesAreIdentical;
 
 void
 MDefinition::PrintOpcodeName(FILE *fp, MDefinition::Opcode op)
 {
     static const char * const names[] =
     {
 #define NAME(x) #x,
         MIR_OPCODE_LIST(NAME)
@@ -883,20 +883,17 @@ MBitNot::infer()
 }
 
 static inline bool
 IsConstant(MDefinition *def, double v)
 {
     if (!def->isConstant())
         return false;
 
-    // Compare the underlying bits to not equate -0 and +0.
-    uint64_t lhs = BitwiseCast<uint64_t>(def->toConstant()->value().toNumber());
-    uint64_t rhs = BitwiseCast<uint64_t>(v);
-    return lhs == rhs;
+    return DoublesAreIdentical(def->toConstant()->value().toNumber(), v);
 }
 
 MDefinition *
 MBinaryBitwiseInstruction::foldsTo(bool useValueNumbers)
 {
     if (specialization_ != MIRType_Int32)
         return this;
 
deleted file mode 100644
--- a/js/src/jit-test/tests/collections/Array-iterator-surfaces.js
+++ /dev/null
@@ -1,4 +0,0 @@
-// Array.prototype.iterator is the same function object as .values.
-
-assertEq(Array.prototype.values, Array.prototype.iterator);
-assertEq(Array.prototype.iterator.name, "values");
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2357,27 +2357,26 @@ JS_CallIdTracer(JSTracer *trc, jsid *idp
 
 JS_PUBLIC_API(void)
 JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
 {
     MarkObjectUnbarriered(trc, objp, name);
 }
 
 JS_PUBLIC_API(void)
-JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name)
-{
-    uintptr_t flags = *objp & flagMask;
-    JSObject *obj = reinterpret_cast<JSObject *>(*objp & ~flagMask);
+JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name)
+{
+    JSObject *obj = objp->getPtr();
     if (!obj)
         return;
 
     JS_SET_TRACING_LOCATION(trc, (void*)objp);
     MarkObjectUnbarriered(trc, &obj, name);
 
-    *objp = uintptr_t(obj) | flags;
+    objp->setPtr(obj);
 }
 
 JS_PUBLIC_API(void)
 JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name)
 {
     MarkStringUnbarriered(trc, strp, name);
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2581,23 +2581,21 @@ JS_CallHashSetObjectTracer(JSTracer *trc
     JSObject *updated = key;
     JS_SET_TRACING_LOCATION(trc, reinterpret_cast<void *>(&const_cast<JSObject *&>(key)));
     JS_CallObjectTracer(trc, &updated, name);
     if (updated != key)
         e.rekeyFront(key, updated);
 }
 
 /*
- * The JS_CallMaskedObjectTracer variant traces a JSObject* that is stored
- * with flags embedded in the low bits of the word. The flagMask parameter
- * expects |*objp & flagMask| to yield the flags with the pointer value
- * stripped and |*objp & ~flagMask| to yield a valid GC pointer.
+ * Trace an object that is known to always be tenured.  No post barriers are
+ * required in this case.
  */
 extern JS_PUBLIC_API(void)
-JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name);
+JS_CallTenuredObjectTracer(JSTracer *trc, JS::TenuredHeap<JSObject *> *objp, const char *name);
 
 /*
  * API for JSTraceCallback implementations.
  */
 extern JS_PUBLIC_API(void)
 JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback);
 
 extern JS_PUBLIC_API(void)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2815,16 +2815,17 @@ static const JSFunctionSpec array_method
          {"scatterPar",         {NULL, NULL},       5,0, "ArrayScatterPar"},
          {"filterPar",          {NULL, NULL},       2,0, "ArrayFilterPar"},
 #endif
 
     /* ES6 additions */
          {"find",               {NULL, NULL},       1,0, "ArrayFind"},
          {"findIndex",          {NULL, NULL},       1,0, "ArrayFindIndex"},
 
+    JS_FN("iterator",           JS_ArrayIterator,   0,0),
     JS_FS_END
 };
 
 static const JSFunctionSpec array_static_methods[] = {
     JS_FN("isArray",            array_isArray,      1,0),
          {"lastIndexOf",        {NULL, NULL},       2,0, "ArrayStaticLastIndexOf"},
          {"indexOf",            {NULL, NULL},       2,0, "ArrayStaticIndexOf"},
          {"forEach",            {NULL, NULL},       2,0, "ArrayStaticForEach"},
@@ -2945,24 +2946,16 @@ js_InitArrayClass(JSContext *cx, HandleO
         !DefinePropertiesAndBrand(cx, ctor, NULL, array_static_methods))
     {
         return NULL;
     }
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Array, ctor, arrayProto))
         return NULL;
 
-    JSFunction *fun = JS_DefineFunction(cx, arrayProto, "values", JS_ArrayIterator, 0, 0);
-    if (!fun)
-        return NULL;
-
-    RootedValue funval(cx, ObjectValue(*fun));
-    if (!JS_DefineProperty(cx, arrayProto, "iterator", funval, NULL, NULL, 0))
-        return NULL;
-
     return arrayProto;
 }
 
 /*
  * Array allocation functions.
  */
 
 static inline bool
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -1116,13 +1116,23 @@ js::IsInRequest(JSContext *cx)
 #else
     return true;
 #endif
 }
 #endif
 
 #ifdef JSGC_GENERATIONAL
 JS_FRIEND_API(void)
-JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key)
+JS_StoreObjectPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSObject *key, void *data)
 {
-    cx->runtime()->gcStoreBuffer.putCallback(callback, key);
+    cx->runtime()->gcStoreBuffer.putCallback(callback, key, data);
+}
+
+extern JS_FRIEND_API(void)
+JS_StoreStringPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSString *key, void *data)
+{
+    cx->runtime()->gcStoreBuffer.putCallback(callback, key, data);
 }
 #endif /* JSGC_GENERATIONAL */
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1789,15 +1789,29 @@ extern JS_FRIEND_API(JSBool)
 js_DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
                      const js::PropertyDescriptor& descriptor, JSBool *bp);
 
 extern JS_FRIEND_API(JSBool)
 js_ReportIsNotFunction(JSContext *cx, const JS::Value& v);
 
 #ifdef JSGC_GENERATIONAL
 extern JS_FRIEND_API(void)
-JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key);
+JS_StoreObjectPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSObject *key, void *data);
+
+extern JS_FRIEND_API(void)
+JS_StoreStringPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSString *key, void *data);
 #else
 inline void
-JS_StorePostBarrierCallback(JSContext* cx, void (*callback)(JSTracer *trc, void *key), void *key) {}
+JS_StoreObjectPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSObject *key, void *data) {}
+
+inline void
+JS_StoreStringPostBarrierCallback(JSContext* cx,
+                                  void (*callback)(JSTracer *trc, void *key, void *data),
+                                  JSString *key, void *data) {}
 #endif /* JSGC_GENERATIONAL */
 
 #endif /* jsfriendapi_h */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -5102,9 +5102,16 @@ js::UninlinedIsInsideNursery(JSRuntime *
 #ifdef DEBUG
 AutoDisableProxyCheck::AutoDisableProxyCheck(JSRuntime *rt
                                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : count(rt->gcDisableStrictProxyCheckingCount)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     count++;
 }
+
+JS_FRIEND_API(void)
+JS::AssertGCThingMustBeTenured(JSObject *obj)
+{
+    JS_ASSERT((!IsNurseryAllocable(obj->tenuredGetAllocKind()) || obj->getClass()->finalize) &&
+              obj->isTenured());
+}
 #endif
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -146,17 +146,17 @@ template <> struct MapTypeToTraceKind<Un
 template <> struct MapTypeToTraceKind<types::TypeObject>{ const static JSGCTraceKind kind = JSTRACE_TYPE_OBJECT; };
 template <> struct MapTypeToTraceKind<JSAtom>           { const static JSGCTraceKind kind = JSTRACE_STRING; };
 template <> struct MapTypeToTraceKind<JSString>         { const static JSGCTraceKind kind = JSTRACE_STRING; };
 template <> struct MapTypeToTraceKind<JSFlatString>     { const static JSGCTraceKind kind = JSTRACE_STRING; };
 template <> struct MapTypeToTraceKind<JSLinearString>   { const static JSGCTraceKind kind = JSTRACE_STRING; };
 template <> struct MapTypeToTraceKind<PropertyName>     { const static JSGCTraceKind kind = JSTRACE_STRING; };
 template <> struct MapTypeToTraceKind<ion::IonCode>     { const static JSGCTraceKind kind = JSTRACE_IONCODE; };
 
-#ifdef JSGC_GENERATIONAL
+#if defined(JSGC_GENERATIONAL) || defined(DEBUG)
 static inline bool
 IsNurseryAllocable(AllocKind kind)
 {
     JS_ASSERT(kind >= 0 && unsigned(kind) < FINALIZE_LIMIT);
     static const bool map[] = {
         false,     /* FINALIZE_OBJECT0 */
         true,      /* FINALIZE_OBJECT0_BACKGROUND */
         false,     /* FINALIZE_OBJECT2 */
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -618,18 +618,18 @@ num_toString_impl(JSContext *cx, CallArg
     if (!str) {
         JS_ReportOutOfMemory(cx);
         return false;
     }
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
-num_toString(JSContext *cx, unsigned argc, Value *vp)
+JSBool
+js_num_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsNumber, num_toString_impl>(cx, args);
 }
 
 #if !ENABLE_INTL_API
 JS_ALWAYS_INLINE bool
 num_toLocaleString_impl(JSContext *cx, CallArgs args)
@@ -906,17 +906,17 @@ num_toPrecision(JSContext *cx, unsigned 
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsNumber, num_toPrecision_impl>(cx, args);
 }
 
 static const JSFunctionSpec number_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,       num_toSource,          0, 0),
 #endif
-    JS_FN(js_toString_str,       num_toString,          1, 0),
+    JS_FN(js_toString_str,       js_num_toString,       1, 0),
 #if ENABLE_INTL_API
          {js_toLocaleString_str, {NULL, NULL},           0,0, "Number_toLocaleString"},
 #else
     JS_FN(js_toLocaleString_str, num_toLocaleString,     0,0),
 #endif
     JS_FN(js_valueOf_str,        js_num_valueOf,        0, 0),
     JS_FN("toFixed",             num_toFixed,           1, 0),
     JS_FN("toExponential",       num_toExponential,     1, 0),
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -168,16 +168,19 @@ num_parseInt(JSContext *cx, unsigned arg
  * If the string does not contain a number, set *ep to s and return 0.0 in dp.
  * Return false if out of memory.
  */
 extern JSBool
 js_strtod(js::ExclusiveContext *cx, const jschar *s, const jschar *send,
           const jschar **ep, double *dp);
 
 extern JSBool
+js_num_toString(JSContext *cx, unsigned argc, js::Value *vp);
+
+extern JSBool
 js_num_valueOf(JSContext *cx, unsigned argc, js::Value *vp);
 
 namespace js {
 
 static JS_ALWAYS_INLINE bool
 ValueFitsInInt32(const Value &v, int32_t *pi)
 {
     if (v.isInt32()) {
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -259,39 +259,50 @@ GetPropertyOperation(JSContext *cx, Stac
             vp.setInt32(fp->numActualArgs());
             return true;
         }
 
         if (GetLengthProperty(lval, vp))
             return true;
     }
 
-    JSObject *obj = ToObjectFromStack(cx, lval);
-    if (!obj)
-        return false;
+    RootedId id(cx, NameToId(script->getName(pc)));
+    RootedObject obj(cx);
+
+    /* Optimize (.1).toString(). */
+    if (lval.isNumber() && id == NameToId(cx->names().toString)) {
+        JSObject *proto = fp->global().getOrCreateNumberPrototype(cx);
+        if (!proto)
+            return false;
+        if (ClassMethodIsNative(cx, proto, &NumberObject::class_, id, js_num_toString))
+            obj = proto;
+    }
+
+    if (!obj) {
+        obj = ToObjectFromStack(cx, lval);
+        if (!obj)
+            return false;
+    }
 
     bool wasObject = lval.isObject();
 
-    RootedId id(cx, NameToId(script->getName(pc)));
-    RootedObject nobj(cx, obj);
-
     if (obj->getOps()->getProperty) {
-        if (!JSObject::getGeneric(cx, nobj, nobj, id, vp))
+        if (!JSObject::getGeneric(cx, obj, obj, id, vp))
             return false;
     } else {
-        if (!GetPropertyHelper(cx, nobj, id, 0, vp))
+        if (!GetPropertyHelper(cx, obj, id, 0, vp))
             return false;
     }
 
 #if JS_HAS_NO_SUCH_METHOD
     if (op == JSOP_CALLPROP &&
         JS_UNLIKELY(vp.isPrimitive()) &&
         wasObject)
     {
-        if (!OnUnknownMethod(cx, nobj, IdToValue(id), vp))
+        if (!OnUnknownMethod(cx, obj, IdToValue(id), vp))
             return false;
     }
 #endif
 
     return true;
 }
 
 static inline bool
--- a/js/xpconnect/idl/nsIXPConnect.idl
+++ b/js/xpconnect/idl/nsIXPConnect.idl
@@ -286,17 +286,17 @@ interface nsIXPCFunctionThisTranslator :
 %{ C++
 // For use with the service manager
 // {CB6593E0-F9B2-11d2-BDD6-000064657374}
 #define NS_XPCONNECT_CID \
 { 0xcb6593e0, 0xf9b2, 0x11d2, \
     { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
 %}
 
-[uuid(3bc074e6-2102-40a4-8c84-38b002c9e2f1)]
+[uuid(0ebc00f0-f3ad-11e2-b778-0800200c9a66)]
 interface nsIXPConnect : nsISupports
 {
 %{ C++
   NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCONNECT_CID)
 %}
 
     /**
      * Initializes classes on a global object that has already been created.
@@ -626,9 +626,16 @@ interface nsIXPConnect : nsISupports
                                       in JSContextPtr aJSContext);
 
     [noscript] void writeFunction(in nsIObjectOutputStream aStream,
                                   in JSContextPtr aJSContext,
                                   in JSObjectPtr aJSObject);
 
     [noscript] JSObjectPtr readFunction(in nsIObjectInputStream aStream,
                                         in JSContextPtr aJSContext);
+
+    /**
+     * This function should be called in JavaScript error reporters
+     * to signal that they are ignoring the error. In this case,
+     * XPConnect can print a warning to the console.
+     */
+    [noscript] void markErrorUnreported(in JSContextPtr aJSContext);
 };
--- a/js/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -57,17 +57,17 @@ mozJSSubScriptLoader::mozJSSubScriptLoad
         do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
 }
 
 mozJSSubScriptLoader::~mozJSSubScriptLoader()
 {
     /* empty */
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(mozJSSubScriptLoader, mozIJSSubScriptLoader)
+NS_IMPL_ISUPPORTS1(mozJSSubScriptLoader, mozIJSSubScriptLoader)
 
 static nsresult
 ReportError(JSContext *cx, const char *msg)
 {
     JS_SetPendingException(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, msg)));
     return NS_OK;
 }
 
--- a/js/xpconnect/loader/mozJSSubScriptLoader.h
+++ b/js/xpconnect/loader/mozJSSubScriptLoader.h
@@ -21,17 +21,17 @@ class nsIIOService;
 
 class mozJSSubScriptLoader : public mozIJSSubScriptLoader
 {
 public:
     mozJSSubScriptLoader();
     virtual ~mozJSSubScriptLoader();
 
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_MOZIJSSUBSCRIPTLOADER
 
 private:
     nsresult ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
                         const nsAString& charset, const char *uriStr,
                         nsIIOService *serv, nsIPrincipal *principal,
                         bool reuseGlobal, JSScript **scriptp,
                         JSFunction **functionp);
--- a/js/xpconnect/public/SandboxPrivate.h
+++ b/js/xpconnect/public/SandboxPrivate.h
@@ -18,17 +18,17 @@ class SandboxPrivate : public nsIGlobalO
 public:
     SandboxPrivate(nsIPrincipal *principal, JSObject *global)
         : mPrincipal(principal)
         , mGlobalJSObject(global)
     {
     }
     virtual ~SandboxPrivate() { }
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
 
     nsIPrincipal *GetPrincipal()
     {
         return mPrincipal;
     }
 
     JSObject *GetGlobalJSObject()
     {
@@ -39,9 +39,9 @@ public:
     {
         mGlobalJSObject = NULL;
     }
 private:
     nsCOMPtr<nsIPrincipal> mPrincipal;
     JSObject *mGlobalJSObject;
 };
 
-#endif // __SANDBOXPRIVATE_H__
\ No newline at end of file
+#endif // __SANDBOXPRIVATE_H__
--- a/js/xpconnect/src/BackstagePass.h
+++ b/js/xpconnect/src/BackstagePass.h
@@ -11,17 +11,17 @@
 #include "nsIGlobalObject.h"
 
 class BackstagePass : public nsIGlobalObject,
                       public nsIXPCScriptable,
                       public nsIClassInfo,
                       public nsSupportsWeakReference
 {
 public:
-  NS_DECL_ISUPPORTS
+  NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIXPCSCRIPTABLE
   NS_DECL_NSICLASSINFO
 
   virtual nsIPrincipal* GetPrincipal() {
     return mPrincipal;
   }
 
   virtual JSObject* GetGlobalJSObject() {
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -103,17 +103,17 @@ char * xpc_CheckAccessList(const PRUnich
 class nsXPCComponents_Interfaces :
             public nsIXPCComponents_Interfaces,
             public nsIXPCScriptable,
             public nsIClassInfo,
             public nsISecurityCheckedComponent
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_INTERFACES
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
     nsXPCComponents_Interfaces();
     virtual ~nsXPCComponents_Interfaces();
@@ -227,18 +227,18 @@ nsXPCComponents_Interfaces::~nsXPCCompon
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Interfaces)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Interfaces)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Interfaces)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Interfaces)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Interfaces)
+NS_IMPL_ADDREF(nsXPCComponents_Interfaces)
+NS_IMPL_RELEASE(nsXPCComponents_Interfaces)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Interfaces
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Interfaces"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_NEWENUMERATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -389,17 +389,17 @@ nsXPCComponents_Interfaces::CanSetProper
 class nsXPCComponents_InterfacesByID :
             public nsIXPCComponents_InterfacesByID,
             public nsIXPCScriptable,
             public nsIClassInfo,
             public nsISecurityCheckedComponent
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_INTERFACESBYID
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
 
 public:
     nsXPCComponents_InterfacesByID();
     virtual ~nsXPCComponents_InterfacesByID();
@@ -513,18 +513,18 @@ nsXPCComponents_InterfacesByID::~nsXPCCo
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_InterfacesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_InterfacesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_InterfacesByID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_InterfacesByID)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_InterfacesByID)
+NS_IMPL_ADDREF(nsXPCComponents_InterfacesByID)
+NS_IMPL_RELEASE(nsXPCComponents_InterfacesByID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_InterfacesByID
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_InterfacesByID"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_NEWENUMERATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -683,17 +683,17 @@ nsXPCComponents_InterfacesByID::CanSetPr
 
 class nsXPCComponents_Classes :
   public nsIXPCComponents_Classes,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_CLASSES
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 public:
     nsXPCComponents_Classes();
     virtual ~nsXPCComponents_Classes();
 };
@@ -801,18 +801,18 @@ nsXPCComponents_Classes::~nsXPCComponent
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Classes)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Classes)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Classes)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Classes)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Classes)
+NS_IMPL_ADDREF(nsXPCComponents_Classes)
+NS_IMPL_RELEASE(nsXPCComponents_Classes)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Classes
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Classes"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_NEWENUMERATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -924,17 +924,17 @@ nsXPCComponents_Classes::NewResolve(nsIX
 
 class nsXPCComponents_ClassesByID :
   public nsIXPCComponents_ClassesByID,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_CLASSESBYID
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 public:
     nsXPCComponents_ClassesByID();
     virtual ~nsXPCComponents_ClassesByID();
 };
@@ -1042,18 +1042,18 @@ nsXPCComponents_ClassesByID::~nsXPCCompo
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ClassesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ClassesByID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ClassesByID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_ClassesByID)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_ClassesByID)
+NS_IMPL_ADDREF(nsXPCComponents_ClassesByID)
+NS_IMPL_RELEASE(nsXPCComponents_ClassesByID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_ClassesByID
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ClassesByID"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_NEWENUMERATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -1187,17 +1187,17 @@ nsXPCComponents_ClassesByID::NewResolve(
 
 class nsXPCComponents_Results :
   public nsIXPCComponents_Results,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_RESULTS
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 public:
     nsXPCComponents_Results();
     virtual ~nsXPCComponents_Results();
 };
@@ -1305,18 +1305,18 @@ nsXPCComponents_Results::~nsXPCComponent
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Results)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Results)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Results)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Results)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Results)
+NS_IMPL_ADDREF(nsXPCComponents_Results)
+NS_IMPL_RELEASE(nsXPCComponents_Results)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Results
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Results"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_NEWENUMERATE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -1403,17 +1403,17 @@ nsXPCComponents_Results::NewResolve(nsIX
 
 class nsXPCComponents_ID :
   public nsIXPCComponents_ID,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_ID
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 
 public:
     nsXPCComponents_ID();
     virtual ~nsXPCComponents_ID();
@@ -1527,18 +1527,18 @@ nsXPCComponents_ID::~nsXPCComponents_ID(
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_ID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_ID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_ID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_ID)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_ID)
+NS_IMPL_ADDREF(nsXPCComponents_ID)
+NS_IMPL_RELEASE(nsXPCComponents_ID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_ID
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_ID"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define                             XPC_MAP_WANT_HASINSTANCE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -1622,17 +1622,17 @@ nsXPCComponents_ID::HasInstance(nsIXPCon
 
 class nsXPCComponents_Exception :
   public nsIXPCComponents_Exception,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_EXCEPTION
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 
 public:
     nsXPCComponents_Exception();
     virtual ~nsXPCComponents_Exception();
@@ -1746,18 +1746,18 @@ nsXPCComponents_Exception::~nsXPCCompone
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Exception)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Exception)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Exception)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Exception)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Exception)
+NS_IMPL_ADDREF(nsXPCComponents_Exception)
+NS_IMPL_RELEASE(nsXPCComponents_Exception)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Exception
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Exception"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define                             XPC_MAP_WANT_HASINSTANCE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -2002,17 +2002,17 @@ class nsXPCConstructor :
   public nsIXPCConstructor,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     NS_DEFINE_STATIC_CID_ACCESSOR(NS_XPCCONSTRUCTOR_CID)
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCONSTRUCTOR
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 public:
     nsXPCConstructor(); // not implemented
     nsXPCConstructor(nsIJSCID* aClassID,
                      nsIJSIID* aInterfaceID,
@@ -2165,18 +2165,18 @@ nsXPCConstructor::GetInitializer(char * 
 
 NS_INTERFACE_MAP_BEGIN(nsXPCConstructor)
   NS_INTERFACE_MAP_ENTRY(nsIXPCConstructor)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCConstructor)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCConstructor)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCConstructor)
+NS_IMPL_ADDREF(nsXPCConstructor)
+NS_IMPL_RELEASE(nsXPCConstructor)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCConstructor
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCConstructor"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define XPC_MAP_FLAGS               0
 #include "xpc_map_end.h" /* This will #undef the above */
@@ -2264,17 +2264,17 @@ nsXPCConstructor::CallOrConstruct(nsIXPC
 
 class nsXPCComponents_Constructor :
   public nsIXPCComponents_Constructor,
   public nsIXPCScriptable,
   public nsIClassInfo
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_CONSTRUCTOR
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSICLASSINFO
 
 public:
     nsXPCComponents_Constructor();
     virtual ~nsXPCComponents_Constructor();
 
@@ -2387,18 +2387,18 @@ nsXPCComponents_Constructor::~nsXPCCompo
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Constructor)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Constructor)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Constructor)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Constructor)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Constructor)
+NS_IMPL_ADDREF(nsXPCComponents_Constructor)
+NS_IMPL_RELEASE(nsXPCComponents_Constructor)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Constructor
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Constructor"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define                             XPC_MAP_WANT_HASINSTANCE
 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
@@ -2587,17 +2587,17 @@ nsXPCComponents_Constructor::HasInstance
 
 /***************************************************************************/
 // Javascript constructor for the sandbox object
 class nsXPCComponents_utils_Sandbox : public nsIXPCComponents_utils_Sandbox,
                                       public nsIXPCScriptable
 {
 public:
     // Aren't macros nice?
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTS_UTILS_SANDBOX
     NS_DECL_NSIXPCSCRIPTABLE
 
 public:
     nsXPCComponents_utils_Sandbox();
     virtual ~nsXPCComponents_utils_Sandbox();
 
 private:
@@ -2608,17 +2608,17 @@ private:
 
 class nsXPCComponents_Utils :
             public nsIXPCComponents_Utils,
             public nsIXPCScriptable,
             public nsISecurityCheckedComponent
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCSCRIPTABLE
     NS_DECL_NSISECURITYCHECKEDCOMPONENT
     NS_DECL_NSIXPCCOMPONENTS_UTILS
 
 public:
     nsXPCComponents_Utils() { }
     virtual ~nsXPCComponents_Utils() { }
 
@@ -2628,18 +2628,18 @@ private:
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_Utils)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_Utils)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_Utils)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_Utils)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_Utils)
+NS_IMPL_ADDREF(nsXPCComponents_Utils)
+NS_IMPL_RELEASE(nsXPCComponents_Utils)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsXPCComponents_Utils
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_Utils"
 #define XPC_MAP_FLAGS               nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
 #include "xpc_map_end.h" /* This will #undef the above */
 
 NS_IMETHODIMP
@@ -2790,20 +2790,20 @@ nsXPCComponents_Utils::ReportError(const
     return NS_OK;
 }
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 const char kScriptSecurityManagerContractID[] = NS_SCRIPTSECURITYMANAGER_CONTRACTID;
 
-NS_IMPL_THREADSAFE_ISUPPORTS3(SandboxPrivate,
-                              nsIScriptObjectPrincipal,
-                              nsIGlobalObject,
-                              nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS3(SandboxPrivate,
+                   nsIScriptObjectPrincipal,
+                   nsIGlobalObject,
+                   nsISupportsWeakReference)
 
 static JSBool
 SandboxDump(JSContext *cx, unsigned argc, jsval *vp)
 {
     JSString *str;
     if (!argc)
         return true;
 
@@ -2995,18 +2995,18 @@ nsXPCComponents_utils_Sandbox::~nsXPCCom
 }
 
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents_utils_Sandbox)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents_utils_Sandbox)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents_utils_Sandbox)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents_utils_Sandbox)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents_utils_Sandbox)
+NS_IMPL_ADDREF(nsXPCComponents_utils_Sandbox)
+NS_IMPL_RELEASE(nsXPCComponents_utils_Sandbox)
 
 // We use the nsIXPScriptable macros to generate lots of stuff for us.
 #define XPC_MAP_CLASSNAME           nsXPCComponents_utils_Sandbox
 #define XPC_MAP_QUOTED_CLASSNAME   "nsXPCComponents_utils_Sandbox"
 #define                             XPC_MAP_WANT_CALL
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define XPC_MAP_FLAGS               0
 #include "xpc_map_end.h" /* This #undef's the above. */
@@ -4551,18 +4551,18 @@ nsXPCComponents_Utils::GetDOMClassInfo(c
 NS_INTERFACE_MAP_BEGIN(nsXPCComponents)
   NS_INTERFACE_MAP_ENTRY(nsIXPCComponents)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCComponents)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCComponents)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCComponents)
+NS_IMPL_ADDREF(nsXPCComponents)
+NS_IMPL_RELEASE(nsXPCComponents)
 
 /* void getInterfaces (out uint32_t count, [array, size_is (count), retval]
                        out nsIIDPtr array); */
 NS_IMETHODIMP
 nsXPCComponents::GetInterfaces(uint32_t *aCount, nsIID * **aArray)
 {
     const uint32_t count = 3;
     *aCount = count;
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -850,18 +850,19 @@ XPCConvert::NativeInterface2JSObject(jsv
     } else {
         flat = nullptr;
     }
 
     // Don't double wrap CPOWs. This is a temporary measure for compatibility
     // with objects that don't provide necessary QIs (such as objects under
     // the new DOM bindings). We expect the other side of the CPOW to have
     // the appropriate wrappers in place.
-    if (JSObject *cpow = UnwrapNativeCPOW(aHelper.Object())) {
-        if (!JS_WrapObject(cx, &cpow))
+    RootedObject cpow(cx, UnwrapNativeCPOW(aHelper.Object()));
+    if (cpow) {
+        if (!JS_WrapObject(cx, cpow.address()))
             return false;
         *d = OBJECT_TO_JSVAL(cpow);
         return true;
     }
 
     // We can't simply construct a slim wrapper. Go ahead and create an
     // XPCWrappedNative for this object. At this point, |flat| could be
     // non-null, meaning that either we already have a wrapped native from
@@ -1108,23 +1109,22 @@ public:
 
 private:
     JSContext * const mContext;
     RootedValue tvr;
 };
 
 // static
 nsresult
-XPCConvert::JSValToXPCException(jsval sArg,
+XPCConvert::JSValToXPCException(MutableHandleValue s,
                                 const char* ifaceName,
                                 const char* methodName,
                                 nsIException** exceptn)
 {
     AutoJSContext cx;
-    RootedValue s(cx, sArg);
     AutoExceptionRestorer aer(cx, s);
 
     if (!JSVAL_IS_PRIMITIVE(s)) {
         // we have a JSObject
         RootedObject obj(cx, JSVAL_TO_OBJECT(s));
 
         if (!obj) {
             NS_ERROR("when is an object not an object?");
@@ -1570,17 +1570,17 @@ XPCConvert::JSTypedArray2Native(void** d
     if (pErr)
         *pErr = NS_OK;
 
     return true;
 }
 
 // static
 JSBool
-XPCConvert::JSArray2Native(void** d, JS::Value s,
+XPCConvert::JSArray2Native(void** d, HandleValue s,
                            uint32_t count, const nsXPTType& type,
                            const nsID* iid, nsresult* pErr)
 {
     NS_ABORT_IF_FALSE(d, "bad param");
 
     AutoJSContext cx;
 
     // XXX add support for getting chars from strings
@@ -1754,17 +1754,17 @@ XPCConvert::NativeStringWithSize2JS(jsva
             XPC_LOG_ERROR(("XPCConvert::NativeStringWithSize2JS : unsupported type"));
             return false;
     }
     return true;
 }
 
 // static
 JSBool
-XPCConvert::JSStringWithSize2Native(void* d, jsval s,
+XPCConvert::JSStringWithSize2Native(void* d, HandleValue s,
                                     uint32_t count, const nsXPTType& type,
                                     nsresult* pErr)
 {
     NS_PRECONDITION(!JSVAL_IS_NULL(s), "bad param");
     NS_PRECONDITION(d, "bad param");
 
     AutoJSContext cx;
     uint32_t len;
--- a/js/xpconnect/src/XPCException.cpp
+++ b/js/xpconnect/src/XPCException.cpp
@@ -86,18 +86,18 @@ NS_IMPL_CLASSINFO(nsXPCException, NULL, 
                   NS_XPCEXCEPTION_CID)
 NS_INTERFACE_MAP_BEGIN(nsXPCException)
   NS_INTERFACE_MAP_ENTRY(nsIException)
   NS_INTERFACE_MAP_ENTRY(nsIXPCException)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIException)
   NS_IMPL_QUERY_CLASSINFO(nsXPCException)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsXPCException)
-NS_IMPL_THREADSAFE_RELEASE(nsXPCException)
+NS_IMPL_ADDREF(nsXPCException)
+NS_IMPL_RELEASE(nsXPCException)
 
 NS_IMPL_CI_INTERFACE_GETTER1(nsXPCException, nsIXPCException)
 
 nsXPCException::nsXPCException()
     : mMessage(nullptr),
       mResult(NS_OK),
       mName(nullptr),
       mLocation(nullptr),
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -14,17 +14,17 @@
 #include "JavaScriptParent.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 
 /***************************************************************************/
 // nsJSID
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsJSID, nsIJSID)
+NS_IMPL_ISUPPORTS1(nsJSID, nsIJSID)
 
 char nsJSID::gNoString[] = "";
 
 nsJSID::nsJSID()
     : mID(GetInvalidIID()), mNumber(gNoString), mName(gNoString)
 {
 }
 
@@ -207,28 +207,28 @@ nsJSID::NewID(const nsID& id)
 // nsIXPCScriptable::DONT_ENUM_STATIC_PROPS. And having a class to do it is
 // the only means we have. Setting this flag on any given instance scriptable
 // helper is not sufficient to convey the information that we don't want
 // static properties enumerated on the shared proto.
 
 class SharedScriptableHelperForJSIID MOZ_FINAL : public nsIXPCScriptable
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCSCRIPTABLE
     SharedScriptableHelperForJSIID() {}
 };
 
 NS_INTERFACE_MAP_BEGIN(SharedScriptableHelperForJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(SharedScriptableHelperForJSIID)
-NS_IMPL_THREADSAFE_RELEASE(SharedScriptableHelperForJSIID)
+NS_IMPL_ADDREF(SharedScriptableHelperForJSIID)
+NS_IMPL_RELEASE(SharedScriptableHelperForJSIID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           SharedScriptableHelperForJSIID
 #define XPC_MAP_QUOTED_CLASSNAME   "JSIID"
 #define XPC_MAP_FLAGS               nsIXPCScriptable::DONT_ENUM_STATIC_PROPS |\
                                     nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
 #include "xpc_map_end.h" /* This will #undef the above */
 
@@ -287,18 +287,18 @@ NS_INTERFACE_MAP_BEGIN(nsJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIJSID)
   NS_INTERFACE_MAP_ENTRY(nsIJSIID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsISecurityCheckedComponent)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
   NS_IMPL_QUERY_CLASSINFO(nsJSIID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsJSIID)
-NS_IMPL_THREADSAFE_RELEASE(nsJSIID)
+NS_IMPL_ADDREF(nsJSIID)
+NS_IMPL_RELEASE(nsJSIID)
 NS_IMPL_CI_INTERFACE_GETTER2(nsJSIID, nsIJSID, nsIJSIID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsJSIID
 #define XPC_MAP_QUOTED_CLASSNAME   "nsJSIID"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_ENUMERATE
 #define                             XPC_MAP_WANT_HASINSTANCE
@@ -605,18 +605,18 @@ nsJSIID::CanSetProperty(const nsIID * ii
 NS_INTERFACE_MAP_BEGIN(nsJSCID)
   NS_INTERFACE_MAP_ENTRY(nsIJSID)
   NS_INTERFACE_MAP_ENTRY(nsIJSCID)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIJSID)
   NS_IMPL_QUERY_CLASSINFO(nsJSCID)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(nsJSCID)
-NS_IMPL_THREADSAFE_RELEASE(nsJSCID)
+NS_IMPL_ADDREF(nsJSCID)
+NS_IMPL_RELEASE(nsJSCID)
 NS_IMPL_CI_INTERFACE_GETTER2(nsJSCID, nsIJSID, nsIJSCID)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           nsJSCID
 #define XPC_MAP_QUOTED_CLASSNAME   "nsJSCID"
 #define                             XPC_MAP_WANT_CONSTRUCT
 #define                             XPC_MAP_WANT_HASINSTANCE
 #define XPC_MAP_FLAGS               0
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1943,17 +1943,17 @@ ReportJSRuntimeExplicitTreeStats(const J
 }
 
 
 } // namespace xpc
 
 class JSCompartmentsMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter
 {
   public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
 
     NS_IMETHOD GetName(nsACString &name) {
         name.AssignLiteral("compartments");
         return NS_OK;
     }
 
     typedef js::Vector<nsCString, 0, js::SystemAllocPolicy> Paths;
 
@@ -1989,17 +1989,17 @@ class JSCompartmentsMultiReporter MOZ_FI
                    nsIMemoryReporter::KIND_OTHER,
                    nsIMemoryReporter::UNITS_COUNT,
                    1, "");
 
         return NS_OK;
     }
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(JSCompartmentsMultiReporter
+NS_IMPL_ISUPPORTS1(JSCompartmentsMultiReporter
                               , nsIMemoryMultiReporter
                               )
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(OrphanMallocSizeOf)
 
 namespace xpc {
 
 static size_t
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -49,17 +49,17 @@ public:
     inline nsXPCWrappedJS* Add(JSContext* cx, nsXPCWrappedJS* wrapper) {
         NS_PRECONDITION(wrapper,"bad param");
         JSObject* obj = wrapper->GetJSObjectPreserveColor();
         Map::AddPtr p = mTable.lookupForAdd(obj);
         if (p)
             return p->value;
         if (!mTable.add(p, obj, wrapper))
             return nullptr;
-        JS_StorePostBarrierCallback(cx, KeyMarkCallback, obj);
+        JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, obj, this);
         return wrapper;
     }
 
     inline void Remove(nsXPCWrappedJS* wrapper) {
         NS_PRECONDITION(wrapper,"bad param");
         mTable.remove(wrapper->GetJSObjectPreserveColor());
     }
 
@@ -82,22 +82,21 @@ public:
 
 private:
     JSObject2WrappedJSMap() {}
 
     /*
      * This function is called during minor GCs for each key in the HashMap that
      * has been moved.
      */
-    static void KeyMarkCallback(JSTracer *trc, void *k) {
+    static void KeyMarkCallback(JSTracer *trc, void *k, void *d) {
         JSObject *key = static_cast<JSObject*>(k);
+        JSObject2WrappedJSMap* self = static_cast<JSObject2WrappedJSMap*>(d);
         JSObject *prior = key;
         JS_CallObjectTracer(trc, &key, "XPCJSRuntime::mWrappedJSMap key");
-        XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
-        JSObject2WrappedJSMap* self = rt->GetWrappedJSMap();
         self->mTable.rekey(prior, key);
     }
 
     Map mTable;
 };
 
 /*************************/
 
@@ -645,17 +644,17 @@ public:
     inline JSObject* Add(JSContext *cx, JSObject *key, JSObject *value) {
         NS_PRECONDITION(key,"bad param");
         Map::AddPtr p = mTable.lookupForAdd(key);
         if (p)
             return p->value;
         if (!mTable.add(p, key, value))
             return nullptr;
         MOZ_ASSERT(xpc::GetObjectScope(key)->mWaiverWrapperMap == this);
-        JS_StorePostBarrierCallback(cx, KeyMarkCallback, key);
+        JS_StoreObjectPostBarrierCallback(cx, KeyMarkCallback, key, this);
         return value;
     }
 
     inline void Remove(JSObject* key) {
         NS_PRECONDITION(key,"bad param");
         mTable.remove(key);
     }
 
@@ -692,20 +691,20 @@ public:
 
 private:
     JSObject2JSObjectMap() {}
 
     /*
      * This function is called during minor GCs for each key in the HashMap that
      * has been moved.
      */
-    static void KeyMarkCallback(JSTracer *trc, void *k) {
+    static void KeyMarkCallback(JSTracer *trc, void *k, void *d) {
         JSObject *key = static_cast<JSObject*>(k);
+        JSObject2JSObjectMap *self = static_cast<JSObject2JSObjectMap *>(d);
         JSObject *prior = key;
         JS_CallObjectTracer(trc, &key, "XPCWrappedNativeScope::mWaiverWrapperMap key");
-        JSObject2JSObjectMap *self = xpc::GetObjectScope(key)->mWaiverWrapperMap;
         self->mTable.rekey(prior, key);
     }
 
     Map mTable;
 };
 
 #endif /* xpcmaps_h___ */
--- a/js/xpconnect/src/XPCRuntimeService.cpp
+++ b/js/xpconnect/src/XPCRuntimeService.cpp
@@ -16,18 +16,18 @@ NS_INTERFACE_MAP_BEGIN(BackstagePass)
   NS_INTERFACE_MAP_ENTRY(nsIGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
   NS_INTERFACE_MAP_ENTRY(nsIClassInfo)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPCScriptable)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(BackstagePass)
-NS_IMPL_THREADSAFE_RELEASE(BackstagePass)
+NS_IMPL_ADDREF(BackstagePass)
+NS_IMPL_RELEASE(BackstagePass)
 
 // The nsIXPCScriptable map declaration that will generate stubs for us...
 #define XPC_MAP_CLASSNAME           BackstagePass
 #define XPC_MAP_QUOTED_CLASSNAME   "BackstagePass"
 #define                             XPC_MAP_WANT_NEWRESOLVE
 #define                             XPC_MAP_WANT_FINALIZE
 #define                             XPC_MAP_WANT_PRECREATE
 
--- a/js/xpconnect/src/XPCStack.cpp
+++ b/js/xpconnect/src/XPCStack.cpp
@@ -6,17 +6,17 @@
 
 /* Implements nsIStackFrame. */
 
 #include "xpcprivate.h"
 
 class XPCJSStackFrame : public nsIStackFrame
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSISTACKFRAME
 
     static nsresult CreateStack(JSContext* cx, XPCJSStackFrame** stack);
 
     static nsresult CreateStackFrameLocation(uint32_t aLanguage,
                                              const char* aFilename,
                                              const char* aFunctionName,
                                              int32_t aLineNumber,
@@ -82,17 +82,17 @@ XPCJSStackFrame::XPCJSStackFrame()
 XPCJSStackFrame::~XPCJSStackFrame()
 {
     if (mFilename)
         nsMemory::Free(mFilename);
     if (mFunname)
         nsMemory::Free(mFunname);
 }
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(XPCJSStackFrame, nsIStackFrame)
+NS_IMPL_ISUPPORTS1(XPCJSStackFrame, nsIStackFrame)
 
 nsresult
 XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
 {
     static const unsigned MAX_FRAMES = 100;
 
     nsRefPtr<XPCJSStackFrame> first = new XPCJSStackFrame();
     nsRefPtr<XPCJSStackFrame> self = first;
--- a/js/xpconnect/src/XPCVariant.cpp
+++ b/js/xpconnect/src/XPCVariant.cpp
@@ -64,17 +64,17 @@ XPCTraceableVariant::~XPCTraceableVarian
     if (!JSVAL_IS_NULL(val))
         RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
 }
 
 void XPCTraceableVariant::TraceJS(JSTracer* trc)
 {
     MOZ_ASSERT(JSVAL_IS_TRACEABLE(mJSVal));
     JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
-    JS_CallValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
+    JS_CallHeapValueTracer(trc, &mJSVal, "XPCTraceableVariant::mJSVal");
 }
 
 // static
 void
 XPCTraceableVariant::GetTraceName(JSTracer* trc, char *buf, size_t bufsize)
 {
     JS_snprintf(buf, bufsize, "XPCVariant[0x%p].mJSVal", trc->debugPrintArg);
 }
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -3,17 +3,16 @@
  * 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/. */
 
 /* Class that wraps JS objects to appear as XPCOM objects. */
 
 #include "xpcprivate.h"
 #include "nsCxPusher.h"
-#include "nsAtomicRefcnt.h"
 #include "nsContentUtils.h"
 #include "nsProxyRelease.h"
 #include "nsThreadUtils.h"
 #include "nsTextFormatter.h"
 #include "nsCycleCollectorUtils.h"
 
 using namespace mozilla;
 
@@ -152,17 +151,17 @@ nsXPCWrappedJS::QueryInterface(REFNSIID 
 // even after tranistioning to this refcount-of-one state callers might do
 // an addref and cause us to re-root the JSObject and continue on more normally.
 
 nsrefcnt
 nsXPCWrappedJS::AddRef(void)
 {
     if (!MOZ_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
         MOZ_CRASH();
-    nsrefcnt cnt = NS_AtomicIncrementRefcnt(mRefCnt);
+    nsrefcnt cnt = ++mRefCnt;
     NS_LOG_ADDREF(this, cnt, "nsXPCWrappedJS", sizeof(*this));
 
     if (2 == cnt && IsValid()) {
         XPCJSRuntime* rt = mClass->GetRuntime();
         rt->AddWrappedJSRoot(this);
     }
 
     return cnt;
@@ -192,17 +191,17 @@ nsXPCWrappedJS::Release(void)
 
     // need to take the map lock here to prevent GetNewOrUsed from trying
     // to reuse a wrapper on one thread while it's being destroyed on another
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     XPCAutoLock lock(rt->GetMapLock());
 
 do_decrement:
 
-    nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt);
+    nsrefcnt cnt = --mRefCnt;
     NS_LOG_RELEASE(this, cnt, "nsXPCWrappedJS");
 
     if (0 == cnt) {
         delete this;   // also unlinks us from chain
         return 0;
     }
     if (1 == cnt) {
         if (IsValid())
@@ -270,27 +269,26 @@ CheckMainThreadOnly(nsXPCWrappedJS *aWra
 
     aWrapper->SetIsMainThreadOnly();
 
     return true;
 }
 
 // static
 nsresult
-nsXPCWrappedJS::GetNewOrUsed(JSObject* aJSObj,
+nsXPCWrappedJS::GetNewOrUsed(JS::HandleObject jsObj,
                              REFNSIID aIID,
                              nsISupports* aOuter,
                              nsXPCWrappedJS** wrapperResult)
 {
     // Do a release-mode assert against accessing nsXPCWrappedJS off-main-thread.
     if (!MOZ_LIKELY(NS_IsMainThread() || NS_IsCycleCollectorThread()))
         MOZ_CRASH();
 
     AutoJSContext cx;
-    JS::RootedObject jsObj(cx, aJSObj);
     JSObject2WrappedJSMap* map;
     nsXPCWrappedJS* root = nullptr;
     nsXPCWrappedJS* wrapper = nullptr;
     nsXPCWrappedJSClass* clazz = nullptr;
     XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance();
     JSBool release_root = false;
 
     map = rt->GetWrappedJSMap();
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -16,17 +16,17 @@
 #include "mozilla/Attributes.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 using namespace xpc;
 using namespace JS;
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
+NS_IMPL_ISUPPORTS1(nsXPCWrappedJSClass, nsIXPCWrappedJSClass)
 
 // the value of this variable is never used - we use its address as a sentinel
 static uint32_t zero_methods_descriptor;
 
 bool AutoScriptEvaluate::StartEvaluating(HandleObject scope, JSErrorReporter errorReporter)
 {
     NS_PRECONDITION(!mEvaluated, "AutoScriptEvaluate::Evaluate should only be called once");
 
@@ -955,23 +955,23 @@ nsXPCWrappedJSClass::CheckForException(X
     xpcc->GetException(getter_AddRefs(xpc_exception));
     if (xpc_exception)
         xpcc->SetException(nullptr);
 
     // get this right away in case we do something below to cause JS code
     // to run on this JSContext
     nsresult pending_result = xpcc->GetPendingResult();
 
-    jsval js_exception;
-    JSBool is_js_exception = JS_GetPendingException(cx, &js_exception);
+    RootedValue js_exception(cx);
+    JSBool is_js_exception = JS_GetPendingException(cx, js_exception.address());
 
     /* JS might throw an expection whether the reporter was called or not */
     if (is_js_exception) {
         if (!xpc_exception)
-            XPCConvert::JSValToXPCException(js_exception, anInterfaceName,
+            XPCConvert::JSValToXPCException(&js_exception, anInterfaceName,
                                             aPropertyName,
                                             getter_AddRefs(xpc_exception));
 
         /* cleanup and set failed even if we can't build an exception */
         if (!xpc_exception) {
             XPCJSRuntime::Get()->SetPendingException(nullptr); // XXX necessary?
         }
     }
@@ -1016,18 +1016,24 @@ nsXPCWrappedJSClass::CheckForException(X
                 if (e_result == NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED) {
                     reportable = false;
                 }
             }
 
             // Try to use the error reporter set on the context to handle this
             // error if it came from a JS exception.
             if (reportable && is_js_exception &&
-                JS_GetErrorReporter(cx) != xpcWrappedJSErrorReporter) {
+                JS_GetErrorReporter(cx) != xpcWrappedJSErrorReporter)
+            {
+                // If the error reporter ignores the error, it will call
+                // xpc->MarkErrorUnreported().
+                xpcc->ClearUnreportedError();
                 reportable = !JS_ReportPendingException(cx);
+                if (!xpcc->WasErrorReported())
+                    reportable = true;
             }
 
             if (reportable) {
 #ifdef DEBUG
                 static const char line[] =
                     "************************************************************\n";
                 static const char preamble[] =
                     "* Call to xpconnect wrapped JSObject produced this error:  *\n";
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -362,16 +362,17 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
         wrapper->mScriptableInfo = siProto;
         delete si;
     } else {
         wrapper->mScriptableInfo = si;
     }
 
     // Set the JS object to the global we already created.
     wrapper->mFlatJSObject = global;
+    wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     // Set the private to the XPCWrappedNative.
     JS_SetPrivate(global, wrapper);
 
     // There are dire comments elsewhere in the code about how a GC can
     // happen somewhere after wrapper initialization but before the wrapper is
     // added to the hashtable in FinishCreate(). It's not clear if that can
     // happen here, but let's just be safe for now.
@@ -752,56 +753,52 @@ XPCWrappedNative::GetUsedOnly(nsISupport
     return NS_OK;
 }
 
 // This ctor is used if this object will have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeProto* aProto)
     : mMaybeProto(aProto),
       mSet(aProto->GetSet()),
-      mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test
-      mScriptableInfo(nullptr),
-      mWrapperWord(0)
+      mScriptableInfo(nullptr)
 {
     mIdentity = aIdentity.get();
+    mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     NS_ASSERTION(mMaybeProto, "bad ctor param");
     NS_ASSERTION(mSet, "bad ctor param");
 
     DEBUG_TrackNewWrapper(this);
 }
 
 // This ctor is used if this object will NOT have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeScope* aScope,
                                    XPCNativeSet* aSet)
 
     : mMaybeScope(TagScope(aScope)),
       mSet(aSet),
-      mFlatJSObject(INVALID_OBJECT), // non-null to pass IsValid() test
-      mScriptableInfo(nullptr),
-      mWrapperWord(0)
+      mScriptableInfo(nullptr)
 {
     mIdentity = aIdentity.get();
+    mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     NS_ASSERTION(aScope, "bad ctor param");
     NS_ASSERTION(aSet, "bad ctor param");
 
     DEBUG_TrackNewWrapper(this);
 }
 
 XPCWrappedNative::~XPCWrappedNative()
 {
     DEBUG_TrackDeleteWrapper(this);
 
     Destroy();
 }
 
-static const intptr_t WRAPPER_WORD_POISON = 0xa8a8a8a8;
-
 void
 XPCWrappedNative::Destroy()
 {
     XPCWrappedNativeProto* proto = GetProto();
 
     if (mScriptableInfo &&
         (!HasProto() ||
          (proto && proto->GetScriptableInfo() != mScriptableInfo))) {
@@ -830,24 +827,24 @@ XPCWrappedNative::Destroy()
             NS_RELEASE(mIdentity);
         }
     }
 
     /*
      * The only time GetRuntime() will be NULL is if Destroy is called a second
      * time on a wrapped native. Since we already unregistered the pointer the
      * first time, there's no need to unregister again. Unregistration is safe
-     * the first time because mWrapperWord isn't used afterwards.
+     * the first time because mWrapper isn't used afterwards.
      */
     if (XPCJSRuntime *rt = GetRuntime()) {
         if (IsIncrementalBarrierNeeded(rt->Runtime()))
             IncrementalObjectBarrier(GetWrapperPreserveColor());
-        mWrapperWord = WRAPPER_WORD_POISON;
+        mWrapper.setToCrashOnTouch();
     } else {
-        MOZ_ASSERT(mWrapperWord == WRAPPER_WORD_POISON);
+        MOZ_ASSERT(mWrapper.isSetToCrashOnTouch());
     }
 
     mMaybeScope = nullptr;
 }
 
 void
 XPCWrappedNative::UpdateScriptableInfo(XPCNativeScriptableInfo *si)
 {
@@ -1028,19 +1025,22 @@ XPCWrappedNative::Init(HandleObject pare
     JSObject* protoJSObject = HasProto() ?
                                 GetProto()->GetJSProtoObject() :
                                 JS_GetObjectPrototype(cx, parent);
     if (!protoJSObject) {
         return false;
     }
 
     mFlatJSObject = JS_NewObject(cx, jsclazz, protoJSObject, parent);
-    if (!mFlatJSObject)
+    if (!mFlatJSObject) {
+        mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
         return false;
-
+    }
+
+    mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
     JS_SetPrivate(mFlatJSObject, this);
 
     return FinishInit();
 }
 
 JSBool
 XPCWrappedNative::FinishInit()
 {
@@ -1070,18 +1070,18 @@ XPCWrappedNative::FinishInit()
 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCWrappedNative)
   NS_INTERFACE_MAP_ENTRY(nsIXPConnectWrappedNative)
   NS_INTERFACE_MAP_ENTRY(nsIXPConnectJSObjectHolder)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPConnectWrappedNative)
 NS_INTERFACE_MAP_END_THREADSAFE
 
-NS_IMPL_THREADSAFE_ADDREF(XPCWrappedNative)
-NS_IMPL_THREADSAFE_RELEASE(XPCWrappedNative)
+NS_IMPL_ADDREF(XPCWrappedNative)
+NS_IMPL_RELEASE(XPCWrappedNative)
 
 /*
  *  Wrapped Native lifetime management is messy!
  *
  *  - At creation we push the refcount to 2 (only one of which is owned by
  *    the native caller that caused the wrapper creation).
  *  - During the JS GC Mark phase we mark any wrapper with a refcount > 1.
  *  - The *only* thing that can make the wrapper get destroyed is the
@@ -1174,18 +1174,18 @@ XPCWrappedNative::FlatJSObjectFinalized(
         }
     }
 
     nsWrapperCache *cache = nullptr;
     CallQueryInterface(mIdentity, &cache);
     if (cache)
         cache->ClearWrapper();
 
-    // This makes IsValid return false from now on...
     mFlatJSObject = nullptr;
+    mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
 
     NS_ASSERTION(mIdentity, "bad pointer!");
 #ifdef XP_WIN
     // Try to detect free'd pointer
     NS_ASSERTION(*(int*)mIdentity != 0xdddddddd, "bad pointer!");
     NS_ASSERTION(*(int*)mIdentity != 0,          "bad pointer!");
 #endif
 
@@ -1222,17 +1222,18 @@ XPCWrappedNative::SystemIsBeingShutDown(
     // The long standing strategy is to leak some objects still held at shutdown.
     // The general problem is that propagating release out of xpconnect at
     // shutdown time causes a world of problems.
 
     // We leak mIdentity (see above).
 
     // short circuit future finalization
     JS_SetPrivate(mFlatJSObject, nullptr);
-    mFlatJSObject = nullptr; // This makes 'IsValid()' return false.
+    mFlatJSObject = nullptr;
+    mFlatJSObject.unsetFlags(FLAT_JS_OBJECT_VALID);
 
     XPCWrappedNativeProto* proto = GetProto();
 
     if (HasProto())
         proto->SystemIsBeingShutDown();
 
     if (mScriptableInfo &&
         (!HasProto() ||
@@ -1467,17 +1468,20 @@ XPCWrappedNative::ReparentWrapperIfFound
             flat = newobj;
             wrapper->SetWrapper(ww);
         } else {
             flat = xpc::TransplantObject(cx, flat, newobj);
             if (!flat)
                 MOZ_CRASH();
         }
 
+        MOZ_ASSERT(flat);
         wrapper->mFlatJSObject = flat;
+        wrapper->mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
+
         if (cache) {
             bool preserving = cache->PreservingWrapper();
             cache->SetPreservingWrapper(false);
             cache->SetWrapper(flat);
             cache->SetPreservingWrapper(preserving);
         }
         if (!JS_CopyPropertiesFrom(cx, flat, propertyHolder))
             MOZ_CRASH();
@@ -2929,17 +2933,17 @@ NS_IMETHODIMP XPCWrappedNative::DebugDum
         } else
             XPC_LOG_ALWAYS(("Scope @ %x", GetScope()));
 
         if (depth && mSet)
             mSet->DebugDump(depth);
         else
             XPC_LOG_ALWAYS(("mSet @ %x", mSet));
 
-        XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject));
+        XPC_LOG_ALWAYS(("mFlatJSObject of %x", mFlatJSObject.getPtr()));
         XPC_LOG_ALWAYS(("mIdentity of %x", mIdentity));
         XPC_LOG_ALWAYS(("mScriptableInfo @ %x", mScriptableInfo));
 
         if (depth && mScriptableInfo) {
             XPC_LOG_INDENT();
             XPC_LOG_ALWAYS(("mScriptable @ %x", mScriptableInfo->GetCallback()));
             XPC_LOG_ALWAYS(("mFlags of %x", (uint32_t)mScriptableInfo->GetFlags()));
             XPC_LOG_ALWAYS(("mJSClass @ %x", mScriptableInfo->GetJSClass()));
@@ -3370,17 +3374,17 @@ void DEBUG_ReportShadowedMembers(XPCNati
                     }
                 }
             }
         }
     }
 }
 #endif
 
-NS_IMPL_THREADSAFE_ISUPPORTS1(XPCJSObjectHolder, nsIXPConnectJSObjectHolder)
+NS_IMPL_ISUPPORTS1(XPCJSObjectHolder, nsIXPConnectJSObjectHolder)
 
 JSObject*
 XPCJSObjectHolder::GetJSObject()
 {
     NS_PRECONDITION(mJSObj, "bad object state");
     return mJSObj;
 }
 
@@ -3394,17 +3398,17 @@ XPCJSObjectHolder::~XPCJSObjectHolder()
 {
     RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock());
 }
 
 void
 XPCJSObjectHolder::TraceJS(JSTracer *trc)
 {
     JS_SET_TRACING_DETAILS(trc, GetTraceName, this, 0);
-    JS_CallObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
+    JS_CallHeapObjectTracer(trc, &mJSObj, "XPCJSObjectHolder::mJSObj");
 }
 
 // static
 void
 XPCJSObjectHolder::GetTraceName(JSTracer* trc, char *buf, size_t bufsize)
 {
     JS_snprintf(buf, bufsize, "XPCJSObjectHolder[0x%p].mJSObj",
                 trc->debugPrintArg);
--- a/js/xpconnect/src/XPCWrappedNativeProto.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp
@@ -3,16 +3,17 @@
  * 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/. */
 
 /* Shared proto object for XPCWrappedNative. */
 
 #include "xpcprivate.h"
 #include "nsCxPusher.h"
+#include "pratom.h"
 
 using namespace mozilla;
 
 #if defined(DEBUG_xpc_hacker) || defined(DEBUG)
 int32_t XPCWrappedNativeProto::gDEBUG_LiveProtoCount = 0;
 #endif
 
 XPCWrappedNativeProto::XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
--- a/js/xpconnect/src/XPCWrapper.cpp
+++ b/js/xpconnect/src/XPCWrapper.cpp
@@ -60,17 +60,17 @@ XrayWrapperConstructor(JSContext *cx, un
     return true;
   }
 
   *vp = JS::ObjectValue(*js::UncheckedUnwrap(&v.toObject()));
   return JS_WrapValue(cx, vp);
 }
 // static
 bool
-AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject)
+AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject)
 {
   // Pushing a JSContext calls ActivateDebugger which calls this function, so
   // we can't use an AutoJSContext here until JSD is gone.
   JSAutoCompartment ac(aCx, aGlobalObject);
   JSFunction *xpcnativewrapper =
     JS_DefineFunction(aCx, aGlobalObject, "XPCNativeWrapper",
                       XrayWrapperConstructor, 1,
                       JSPROP_READONLY | JSPROP_PERMANENT | JSFUN_STUB_GSOPS | JSFUN_CONSTRUCTOR);
--- a/js/xpconnect/src/XPCWrapper.h
+++ b/js/xpconnect/src/XPCWrapper.h
@@ -18,17 +18,17 @@ namespace XPCNativeWrapper {
 // XPCNativeScriptableFlags corresponding with a flag, returns 'true'
 // if the flag is set.
 // XXX Convert to using GetFlags() and not a macro.
 #define NATIVE_HAS_FLAG(_wn, _flag)                                           \
   ((_wn)->GetScriptableInfo() &&                                              \
    (_wn)->GetScriptableInfo()->GetFlags()._flag())
 
 bool
-AttachNewConstructorObject(JSContext *aCx, JSObject *aGlobalObject);
+AttachNewConstructorObject(JSContext *aCx, JS::HandleObject aGlobalObject);
 
 } // namespace XPCNativeWrapper
 
 // This namespace wraps some common functionality between the three existing
 // wrappers. Its main purpose is to allow XPCCrossOriginWrapper to act both
 // as an XPCSafeJSObjectWrapper and as an XPCNativeWrapper when required to
 // do so (the decision is based on the principals of the wrapper and wrapped
 // objects).
--- a/js/xpconnect/src/nsScriptError.cpp
+++ b/js/xpconnect/src/nsScriptError.cpp
@@ -9,17 +9,17 @@
  */
 
 #include "xpcprivate.h"
 #include "nsGlobalWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsILoadContext.h"
 #include "nsIDocShell.h"
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError)
+NS_IMPL_ISUPPORTS2(nsScriptError, nsIConsoleMessage, nsIScriptError)
 
 nsScriptError::nsScriptError()
     :  mMessage(),
        mSourceName(),
        mLineNumber(0),
        mSourceLine(),
        mColumnNumber(0),
        mFlags(0),
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -49,22 +49,22 @@
 #include "nsThread.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace xpc;
 using namespace JS;
 
-NS_IMPL_THREADSAFE_ISUPPORTS5(nsXPConnect,
-                              nsIXPConnect,
-                              nsISupportsWeakReference,
-                              nsIThreadObserver,
-                              nsIJSRuntimeService,
-                              nsIJSEngineTelemetryStats)
+NS_IMPL_ISUPPORTS5(nsXPConnect,
+                   nsIXPConnect,
+                   nsISupportsWeakReference,
+                   nsIThreadObserver,
+                   nsIJSRuntimeService,
+                   nsIJSEngineTelemetryStats)
 
 nsXPConnect* nsXPConnect::gSelf = nullptr;
 JSBool       nsXPConnect::gOnceAliveNowDead = false;
 uint32_t     nsXPConnect::gReportAllJSExceptions = 0;
 
 JSBool       xpc::gDebugMode = false;
 JSBool       xpc::gDesiredDebugMode = false;
 
@@ -590,19 +590,19 @@ nsXPConnect::WrapNative(JSContext * aJSC
                         nsIXPConnectJSObjectHolder **aHolder)
 {
     NS_ASSERTION(aHolder, "bad param");
     NS_ASSERTION(aJSContext, "bad param");
     NS_ASSERTION(aScopeArg, "bad param");
     NS_ASSERTION(aCOMObj, "bad param");
 
     RootedObject aScope(aJSContext, aScopeArg);
-    jsval v;
+    RootedValue v(aJSContext);
     return NativeInterface2JSObject(aScope, aCOMObj, nullptr, &aIID,
-                                    false, &v, aHolder);
+                                    false, v.address(), aHolder);
 }
 
 /* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out jsval aVal, out nsIXPConnectJSObjectHolder aHolder); */
 NS_IMETHODIMP
 nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext,
                                JSObject * aScopeArg,
                                nsISupports *aCOMObj,
                                nsWrapperCache *aCache,
@@ -1384,18 +1384,18 @@ DeferredRelease(nsISupports *obj)
 }
 
 NS_EXPORT_(bool)
 Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(out);
 
-    JS::Value root = val;
-    xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
+    JS::RootedValue root(cx, val);
+    xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
                                  xpc_qsACString::eStringify);
     if (!encodedString.IsValid())
         return false;
 
     nsAutoCString result;
     if (NS_FAILED(mozilla::Base64Encode(encodedString, result))) {
         JS_ReportError(cx, "Failed to encode base64 data!");
         return false;
@@ -1410,18 +1410,18 @@ Base64Encode(JSContext *cx, JS::Value va
 }
 
 NS_EXPORT_(bool)
 Base64Decode(JSContext *cx, JS::Value val, JS::Value *out)
 {
     MOZ_ASSERT(cx);
     MOZ_ASSERT(out);
 
-    JS::Value root = val;
-    xpc_qsACString encodedString(cx, root, &root, xpc_qsACString::eNull,
+    JS::RootedValue root(cx, val);
+    xpc_qsACString encodedString(cx, root, root.address(), xpc_qsACString::eNull,
                                  xpc_qsACString::eNull);
     if (!encodedString.IsValid())
         return false;
 
     nsAutoCString result;
     if (NS_FAILED(mozilla::Base64Decode(encodedString, result))) {
         JS_ReportError(cx, "Failed to decode base64 string!");
         return false;
@@ -1643,16 +1643,24 @@ nsXPConnect::WriteFunction(nsIObjectOutp
 }
 
 NS_IMETHODIMP
 nsXPConnect::ReadFunction(nsIObjectInputStream *stream, JSContext *cx, JSObject **functionObjp)
 {
     return ReadScriptOrFunction(stream, cx, nullptr, functionObjp);
 }
 
+NS_IMETHODIMP
+nsXPConnect::MarkErrorUnreported(JSContext *cx)
+{
+    XPCContext *xpcc = XPCContext::GetXPCContext(cx);
+    xpcc->MarkErrorUnreported();
+    return NS_OK;
+}
+
 /* These are here to be callable from a debugger */
 extern "C" {
 JS_EXPORT_API(void) DumpJSStack()
 {
     nsresult rv;
     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
     if (NS_SUCCEEDED(rv) && xpc)
         xpc->DebugDumpJSStack(true, true, false);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -434,17 +434,17 @@ AddToCCKind(JSGCTraceKind kind)
 class nsXPConnect : public nsIXPConnect,
                     public nsIThreadObserver,
                     public nsSupportsWeakReference,
                     public nsIJSRuntimeService,
                     public nsIJSEngineTelemetryStats
 {
 public:
     // all the interface method declarations...
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCONNECT
     NS_DECL_NSITHREADOBSERVER
     NS_DECL_NSIJSRUNTIMESERVICE
     NS_DECL_NSIJSENGINETELEMETRYSTATS
 
     // non-interface implementation
 public:
     // These get non-addref'd pointers
@@ -952,31 +952,36 @@ public:
 
     nsresult GetPendingResult() {return mPendingResult;}
     void SetPendingResult(nsresult rc) {mPendingResult = rc;}
 
     void DebugDump(int16_t depth);
     void AddScope(PRCList *scope) { PR_INSERT_AFTER(scope, &mScopes); }
     void RemoveScope(PRCList *scope) { PR_REMOVE_LINK(scope); }
 
+    void MarkErrorUnreported() { mErrorUnreported = true; }
+    void ClearUnreportedError() { mErrorUnreported = false; }
+    bool WasErrorReported() { return !mErrorUnreported; }
+
     ~XPCContext();
 
 private:
     XPCContext();    // no implementation
     XPCContext(XPCJSRuntime* aRuntime, JSContext* aJSContext);
 
     static XPCContext* newXPCContext(XPCJSRuntime* aRuntime,
                                      JSContext* aJSContext);
 private:
     XPCJSRuntime* mRuntime;
     JSContext*  mJSContext;
     nsresult mLastResult;
     nsresult mPendingResult;
     nsIException* mException;
     LangType mCallingLangType;
+    bool mErrorUnreported;
 
     // A linked list of scopes to notify when we are destroyed.
     PRCList mScopes;
 };
 
 /***************************************************************************/
 
 #define NATIVE_CALLER  XPCContext::LANG_NATIVE
@@ -1380,16 +1385,18 @@ public:
     XPCContext *GetContext() { return mContext; }
     void ClearContext() { mContext = nullptr; }
 
     typedef js::HashSet<JSObject *,
                         js::PointerHasher<JSObject *, 3>,
                         js::SystemAllocPolicy> DOMExpandoSet;
 
     bool RegisterDOMExpandoObject(JSObject *expando) {
+        // Expandos are proxy objects, and proxies are always tenured.
+        JS::AssertGCThingMustBeTenured(expando);
         if (!mDOMExpandoSet) {
             mDOMExpandoSet = new DOMExpandoSet();
             mDOMExpandoSet->init(8);
         }
         return mDOMExpandoSet->put(expando);
     }
     void RemoveDOMExpandoObject(JSObject *expando) {
         if (mDOMExpandoSet)
@@ -2221,17 +2228,17 @@ void *xpc_GetJSPrivate(JSObject *obj);
 
 /***************************************************************************/
 // XPCWrappedNative the wrapper around one instance of a native xpcom object
 // to be used from JavaScript.
 
 class XPCWrappedNative : public nsIXPConnectWrappedNative
 {
 public:
-    NS_DECL_ISUPPORTS
+    NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
     NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
     // No need to unlink the JS objects, if the XPCWrappedNative will be cycle
     // collected then its mFlatJSObject will be cycle collected too and
     // finalization of the mFlatJSObject will unlink the js objects (see
     // XPC_WN_NoHelper_Finalize and FlatJSObjectFinalized).
     // We also give XPCWrappedNative empty Root/Unroot methods, to avoid
     // root/unrooting the JS objects from addrefing/releasing the
@@ -2254,17 +2261,17 @@ public:
                                  &participant);
       }
     };
     void DeleteCycleCollectable() {}
 
     nsIPrincipal* GetObjectPrincipal() const;
 
     JSBool
-    IsValid() const {return nullptr != mFlatJSObject;}
+    IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
 
 #define XPC_SCOPE_WORD(s)   (intptr_t(s))
 #define XPC_SCOPE_MASK      (intptr_t(0x3))
 #define XPC_SCOPE_TAG       (intptr_t(0x1))
 #define XPC_WRAPPER_EXPIRED (intptr_t(0x2))
 
     static inline JSBool
     IsTaggedScope(XPCWrappedNativeScope* s)
@@ -2304,18 +2311,17 @@ public:
     GetIdentityObject() const {return mIdentity;}
 
     /**
      * This getter clears the gray bit before handing out the JSObject which
      * means that the object is guaranteed to be kept alive past the next CC.
      */
     JSObject*
     GetFlatJSObject() const
-        {if (mFlatJSObject != INVALID_OBJECT)
-             xpc_UnmarkGrayObject(mFlatJSObject);
+        {xpc_UnmarkGrayObject(mFlatJSObject);
          return mFlatJSObject;}
 
     /**
      * This getter does not change the color of the JSObject meaning that the
      * object returned is not guaranteed to be kept alive past the next CC.
      *
      * This should only be called if you are certain that the return value won't
      * be passed into a JS API function and that it won't be stored without
@@ -2438,36 +2444,35 @@ public:
             if (mScriptableInfo)
                 mScriptableInfo->Mark();
         }
         if (HasProto())
             GetProto()->TraceSelf(trc);
         else
             GetScope()->TraceSelf(trc);
         TraceWrapper(trc);
-        if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT &&
-            JS_IsGlobalObject(mFlatJSObject))
+        if (mFlatJSObject && JS_IsGlobalObject(mFlatJSObject))
         {
             TraceXPCGlobal(trc, mFlatJSObject);
         }
     }
 
     void TraceJS(JSTracer *trc) {
         TraceInside(trc);
     }
 
     void TraceSelf(JSTracer *trc) {
         // If this got called, we're being kept alive by someone who really
         // needs us alive and whole.  Do not let our mFlatJSObject go away.
         // This is the only time we should be tracing our mFlatJSObject,
         // normally somebody else is doing that. Be careful not to trace the
         // bogus INVALID_OBJECT value we can have during init, though.
-        if (mFlatJSObject && mFlatJSObject != INVALID_OBJECT) {
-            JS_CallObjectTracer(trc, &mFlatJSObject,
-                                "XPCWrappedNative::mFlatJSObject");
+        if (mFlatJSObject) {
+            JS_CallTenuredObjectTracer(trc, &mFlatJSObject,
+                                       "XPCWrappedNative::mFlatJSObject");
         }
     }
 
     void AutoTrace(JSTracer *trc) {
         TraceSelf(trc);
     }
 
 #ifdef DEBUG
@@ -2485,51 +2490,48 @@ public:
     // Returns a string that shuld be free'd using JS_smprintf_free (or null).
     char* ToString(XPCWrappedNativeTearOff* to = nullptr) const;
 
     static void GatherProtoScriptableCreateInfo(nsIClassInfo* classInfo,
                                                 XPCNativeScriptableCreateInfo& sciProto);
 
     JSBool HasExternalReference() const {return mRefCnt > 1;}
 
-    JSBool NeedsSOW() { return !!(mWrapperWord & NEEDS_SOW); }
-    void SetNeedsSOW() { mWrapperWord |= NEEDS_SOW; }
-    JSBool NeedsCOW() { return !!(mWrapperWord & NEEDS_COW); }
-    void SetNeedsCOW() { mWrapperWord |= NEEDS_COW; }
-
-    JSObject* GetWrapperPreserveColor() const
-        {return (JSObject*)(mWrapperWord & (size_t)~(size_t)FLAG_MASK);}
+    JSBool NeedsSOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_SOW); }
+    void SetNeedsSOW() { mWrapper.setFlags(WRAPPER_NEEDS_SOW); }
+    JSBool NeedsCOW() { return mWrapper.hasFlag(WRAPPER_NEEDS_COW); }
+    void SetNeedsCOW() { mWrapper.setFlags(WRAPPER_NEEDS_COW); }
+
+    JSObject* GetWrapperPreserveColor() const { return mWrapper.getPtr(); }
 
     JSObject* GetWrapper()
     {
         JSObject* wrapper = GetWrapperPreserveColor();
         if (wrapper) {
             xpc_UnmarkGrayObject(wrapper);
             // Call this to unmark mFlatJSObject.
             GetFlatJSObject();
         }
         return wrapper;
     }
     void SetWrapper(JSObject *obj)
     {
         JS::IncrementalObjectBarrier(GetWrapperPreserveColor());
-        intptr_t newval = intptr_t(obj) | (mWrapperWord & FLAG_MASK);
-        mWrapperWord = newval;
+        mWrapper.setPtr(obj);
     }
 
     void TraceWrapper(JSTracer *trc)
     {
-        JS_CallMaskedObjectTracer(trc, reinterpret_cast<uintptr_t *>(&mWrapperWord),
-                                  (uintptr_t)FLAG_MASK, "XPCWrappedNative::mWrapper");
+        JS_CallTenuredObjectTracer(trc, &mWrapper, "XPCWrappedNative::mWrapper");
     }
 
     // Returns the relevant same-compartment security if applicable, or
     // mFlatJSObject otherwise.
     //
-    // This takes care of checking mWrapperWord to see if we already have such
+    // This takes care of checking mWrapper to see if we already have such
     // a wrapper.
     JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx);
 
     void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
 
     // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
 protected:
     XPCWrappedNative(); // not implemented
@@ -2545,19 +2547,22 @@ protected:
 
     virtual ~XPCWrappedNative();
     void Destroy();
 
     void UpdateScriptableInfo(XPCNativeScriptableInfo *si);