Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 28 Nov 2012 22:46:45 -0500
changeset 114443 3fec1ffef127bc8885407663211339917808b76d
parent 114442 10b4034b8b16252c1cbcdad27a5c1d04a37db3ac (diff)
parent 114362 c63d5cff18bac0fd5a1749677488b14a143e7005 (current diff)
child 114444 1a19b191539219f5d991ab844c1b52ccbc5a430f
push id23917
push useremorley@mozilla.com
push dateThu, 29 Nov 2012 14:20:29 +0000
treeherdermozilla-central@c72d38e7a212 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.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 inbound.
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -47,26 +47,17 @@ AccEvent::CreateXPCOMObject()
   nsAccEvent* event = new nsAccEvent(this);
   NS_IF_ADDREF(event);
   return event;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccEvent cycle collection
 
-NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AccEvent)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAccessible)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AccEvent)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAccessible");
-  cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mAccessible));
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_NATIVE_1(AccEvent, mAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AccEvent, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AccEvent, Release)
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccStateChangeEvent
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -61,18 +61,17 @@ NS_IMPL_CYCLE_COLLECTING_NATIVE_RELEASE(
 NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NotificationController)
   if (tmp->mDocument)
     tmp->Shutdown();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocument");
-  cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mDocument.get()));
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentInsertions)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvents)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController, Release)
 
--- a/accessible/src/base/nsAccCache.h
+++ b/accessible/src/base/nsAccCache.h
@@ -52,20 +52,30 @@ CycleCollectorTraverseCacheEntry(const v
   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "accessible cache entry");
 
   nsISupports *supports = static_cast<nsIAccessible*>(aAccessible);
   cb->NoteXPCOMChild(supports);
   return PL_DHASH_NEXT;
 }
 
 /**
+ * Unlink the accessible cache for the cycle collector.
+ */
+inline void
+ImplCycleCollectionUnlink(mozilla::a11y::AccessibleHashtable& aCache)
+{
+  ClearCache(aCache);
+}
+
+/**
  * Traverse the accessible cache for cycle collector.
  */
-
-static void
-CycleCollectorTraverseCache(mozilla::a11y::AccessibleHashtable& aCache,
-                            nsCycleCollectionTraversalCallback *aCallback)
+inline void
+ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
+                            mozilla::a11y::AccessibleHashtable& aCache,
+                            const char* aName,
+                            uint32_t aFlags = 0)
 {
   aCache.EnumerateRead(CycleCollectorTraverseCacheEntry<mozilla::a11y::Accessible>,
-                       aCallback);
+                       &aCallback);
 }
 
 #endif
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -79,33 +79,18 @@
 
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Accessible. nsISupports
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(Accessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Accessible, nsAccessNode)
-  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mParent");
-  cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mParent.get()));
-
-  uint32_t i, length = tmp->mChildren.Length();
-  for (i = 0; i < length; ++i) {
-    NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
-    cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mChildren[i].get()));
-  }
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Accessible, nsAccessNode)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_2(Accessible, nsAccessNode,
+                                     mParent, mChildren)
 
 NS_IMPL_ADDREF_INHERITED(Accessible, nsAccessNode)
 NS_IMPL_RELEASE_INHERITED(Accessible, nsAccessNode)
 
 nsresult
 Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
 {
   // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
--- a/accessible/src/generic/DocAccessible.cpp
+++ b/accessible/src/generic/DocAccessible.cpp
@@ -114,37 +114,29 @@ DocAccessible::~DocAccessible()
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(DocAccessible)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocAccessible, Accessible)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationController)
-
-  if (tmp->mVirtualCursor) {
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
-  }
-
-  uint32_t i, length = tmp->mChildDocuments.Length();
-  for (i = 0; i < length; ++i) {
-    NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments[i])
-  }
-
-  CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessibleCache)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DocAccessible, Accessible)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNotificationController)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVirtualCursor)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildDocuments)
   tmp->mDependentIDsHash.Clear();
   tmp->mNodeToAccessibleMap.Clear();
-  ClearCache(tmp->mAccessibleCache);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAccessibleCache)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocAccessible)
   NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument)
   NS_INTERFACE_MAP_ENTRY(nsIDocumentObserver)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
--- a/accessible/src/xul/XULTreeAccessible.cpp
+++ b/accessible/src/xul/XULTreeAccessible.cpp
@@ -57,28 +57,18 @@ XULTreeAccessible::
   }
 
   mAccessibleCache.Init(kDefaultTreeCacheSize);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeAccessible: nsISupports and cycle collection implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(XULTreeAccessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULTreeAccessible,
-                                                  Accessible)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTree)
-  CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULTreeAccessible, Accessible)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTree)
-  ClearCache(tmp->mAccessibleCache);
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_2(XULTreeAccessible, Accessible,
+                                     mTree, mAccessibleCache)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeAccessible)
 NS_INTERFACE_MAP_END_INHERITING(Accessible)
 
 NS_IMPL_ADDREF_INHERITED(XULTreeAccessible, Accessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeAccessible, Accessible)
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -696,27 +686,18 @@ XULTreeItemAccessibleBase::
 {
   mParent = aParent;
   mFlags |= eSharedNode;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessibleBase: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(XULTreeItemAccessibleBase)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULTreeItemAccessibleBase,
-                                                  Accessible)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTree)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULTreeItemAccessibleBase,
-                                                Accessible)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTree)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeItemAccessibleBase, Accessible,
+                                     mTree)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase)
   NS_INTERFACE_TABLE_INHERITED1(XULTreeItemAccessibleBase,
                                 XULTreeItemAccessibleBase)
 NS_INTERFACE_TABLE_TAIL_INHERITING(Accessible)
 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessibleBase, Accessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessibleBase, Accessible)
 
@@ -1101,27 +1082,19 @@ XULTreeItemAccessible::
 {
   mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
   GetCellName(mColumn, mCachedName);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessible: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(XULTreeItemAccessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULTreeItemAccessible,
-                                                  XULTreeItemAccessibleBase)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mColumn)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULTreeItemAccessible,
-                                                XULTreeItemAccessibleBase)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mColumn)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeItemAccessible,
+                                     XULTreeItemAccessibleBase,
+                                     mColumn)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible)
 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeItemAccessible: nsIAccessible implementation
--- a/accessible/src/xul/XULTreeGridAccessible.cpp
+++ b/accessible/src/xul/XULTreeGridAccessible.cpp
@@ -280,27 +280,19 @@ XULTreeGridRowAccessible::
   XULTreeItemAccessibleBase(aContent, aDoc, aTreeAcc, aTree, aTreeView, aRow)
 {
   mAccessibleCache.Init(kDefaultTreeCacheSize);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(XULTreeGridRowAccessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULTreeGridRowAccessible,
-                                                  XULTreeItemAccessibleBase)
-CycleCollectorTraverseCache(tmp->mAccessibleCache, &cb);
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULTreeGridRowAccessible,
-                                                XULTreeItemAccessibleBase)
-ClearCache(tmp->mAccessibleCache);
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(XULTreeGridRowAccessible,
+                                     XULTreeItemAccessibleBase,
+                                     mAccessibleCache)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible)
 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
 
 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
                          XULTreeItemAccessibleBase)
 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
                           XULTreeItemAccessibleBase)
@@ -478,29 +470,18 @@ XULTreeGridCellAccessible::
     mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   else
     mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XULTreeGridCellAccessible: nsISupports implementation
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(XULTreeGridCellAccessible)
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULTreeGridCellAccessible,
-                                                  LeafAccessible)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTree)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mColumn)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULTreeGridCellAccessible,
-                                                LeafAccessible)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mTree)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mColumn)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_INHERITED_2(XULTreeGridCellAccessible, LeafAccessible,
+                                     mTree, mColumn)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
   NS_INTERFACE_TABLE_INHERITED2(XULTreeGridCellAccessible,
                                 nsIAccessibleTableCell,
                                 XULTreeGridCellAccessible)
 NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
 NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
 NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -580,12 +580,18 @@ pref("browser.prompt.allowNative", false
 // they are handled separately. This pref is only read once at startup:
 // a restart is required to enable a new value.
 pref("network.activity.blipIntervalMilliseconds", 250);
 
 pref("jsloader.reuseGlobal", true);
 
 // Enable font inflation for browser tab content.
 pref("font.size.inflation.minTwips", 120);
+// And disable it for lingering master-process UI.
+pref("font.size.inflation.disabledInMasterProcess", true);
 
 // Enable freeing dirty pages when minimizing memory; this reduces memory
 // consumption when applications are sent to the background.
 pref("memory.free_dirty_pages", true);
+
+// UAProfile settings
+pref("wap.UAProf.url", "");
+pref("wap.UAProf.tagname", "x-wap-profile");
--- a/b2g/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -46,17 +46,17 @@ endif
 ifdef ENABLE_MARIONETTE
 DEFINES += -DENABLE_MARIONETTE=1
 endif
 
 ifdef MOZ_PKG_MANIFEST_P
 MOZ_PKG_MANIFEST = package-manifest
 endif
 
-MOZ_POST_STAGING_CMD = find chrome -type f -name *.properties -exec sed -i '/^\#/d' {} \;
+MOZ_POST_STAGING_CMD = find chrome -type f -name *.properties -exec $(PERL) -n -i -e 'print unless /^\#/' {} \;
 
 include $(topsrcdir)/toolkit/mozapps/installer/packager.mk
 
 ifeq (bundle, $(MOZ_FS_LAYOUT))
 BINPATH = $(_BINPATH)
 DEFINES += -DAPPNAME=$(_APPNAME)
 else
 # Every other platform just winds up in dist/bin
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -269,21 +269,21 @@ var FullZoom = {
    * Set the zoom level for the current tab.
    *
    * Per nsPresContext::setFullZoom, we can set the zoom to its current value
    * without significant impact on performance, as the setting is only applied
    * if it differs from the current setting.  In fact getting the zoom and then
    * checking ourselves if it differs costs more.
    * 
    * And perhaps we should always set the zoom even if it was more expensive,
-   * since DocumentViewerImpl::SetTextZoom claims that child documents can have
+   * since nsDocumentViewer::SetTextZoom claims that child documents can have
    * a different text zoom (although it would be unusual), and it implies that
    * those child text zooms should get updated when the parent zoom gets set,
    * and perhaps the same is true for full zoom
-   * (although DocumentViewerImpl::SetFullZoom doesn't mention it).
+   * (although nsDocumentViewer::SetFullZoom doesn't mention it).
    *
    * So when we apply new zoom values to the browser, we simply set the zoom.
    * We don't check first to see if the new value is the same as the current
    * one.
    **/
   _applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
     if ((!this.siteSpecific) || gInPrintPreviewMode)
       return;
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -492,23 +492,23 @@ var gPopupBlockerObserver = {
     var blockedPopupAllowSite = document.getElementById("blockedPopupAllowSite");
     try {
       blockedPopupAllowSite.removeAttribute("hidden");
 
       var pm = Services.perms;
       if (pm.testPermission(uri, "popup") == pm.ALLOW_ACTION) {
         // Offer an item to block popups for this site, if a whitelist entry exists
         // already for it.
-        let blockString = gNavigatorBundle.getFormattedString("popupBlock", [uri.host]);
+        let blockString = gNavigatorBundle.getFormattedString("popupBlock", [uri.host || uri.spec]);
         blockedPopupAllowSite.setAttribute("label", blockString);
         blockedPopupAllowSite.setAttribute("block", "true");
       }
       else {
         // Offer an item to allow popups for this site
-        let allowString = gNavigatorBundle.getFormattedString("popupAllow", [uri.host]);
+        let allowString = gNavigatorBundle.getFormattedString("popupAllow", [uri.host || uri.spec]);
         blockedPopupAllowSite.setAttribute("label", allowString);
         blockedPopupAllowSite.removeAttribute("block");
       }
     }
     catch (e) {
       blockedPopupAllowSite.setAttribute("hidden", "true");
     }
 
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -267,16 +267,17 @@ endif
                  browser_middleMouse_inherit.js \
                  redirect_bug623155.sjs \
                  browser_tabDrop.js \
                  browser_lastAccessedTab.js \
                  browser_bug734076.js \
                  browser_bug812562.js \
                  blockPluginVulnerableUpdatable.xml \
                  blockPluginVulnerableNoUpdate.xml \
+                 browser_utilityOverlay.js \
                  browser_social.js \
                  browser_social_toolbar.js \
                  browser_social_shareButton.js \
                  browser_social_sidebar.js \
                  browser_social_flyout.js \
                  browser_social_mozSocial_API.js \
                  browser_social_isVisible.js \
                  browser_social_chatwindow.js \
--- a/browser/base/content/test/browser_bug321000.js
+++ b/browser/base/content/test/browser_bug321000.js
@@ -66,15 +66,15 @@ function test_paste(aCurrentTest) {
   gBrowser.selectedBrowser.focus();
 
   // Focus the element and wait for focus event.
   info("About to focus " + element.id);
   element.addEventListener("focus", function() {
     element.removeEventListener("focus", arguments.callee, false);
     executeSoon(function() {
       // Pasting is async because the Accel+V codepath ends up going through
-      // DocumentViewerImpl::FireClipboardEvent.
+      // nsDocumentViewer::FireClipboardEvent.
       info("Pasting into " + element.id);
       EventUtils.synthesizeKey("v", { accelKey: true });
     });
   }, false);
   element.focus();
 }
--- a/browser/base/content/test/browser_utilityOverlay.js
+++ b/browser/base/content/test/browser_utilityOverlay.js
@@ -1,35 +1,62 @@
-var gTestTab;
+/* 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/. */
+
+const gTests = [
+  test_getTopWin,
+  test_getBoolPref,
+  test_openNewTabWith,
+  test_openUILink
+];
+
+function test () {
+  waitForExplicitFinish();
+  executeSoon(runNextTest);
+}
 
-function test() {
-  waitForExplicitFinish();
+function runNextTest() {
+  if (gTests.length) {
+    let testFun = gTests.shift();
+    info("Running " + testFun.name);
+    testFun()
+  }
+  else {
+    finish();
+  }
+}
 
+function test_getTopWin() {
   is(getTopWin(), window, "got top window");
+  runNextTest();
+}
+
+
+function test_getBoolPref() {
   is(getBoolPref("browser.search.openintab", false), false, "getBoolPref");
   is(getBoolPref("this.pref.doesnt.exist", true), true, "getBoolPref fallback");
   is(getBoolPref("this.pref.doesnt.exist", false), false, "getBoolPref fallback #2");
-
+  runNextTest();
+}
 
-  gTestTab = openNewTabWith("http://example.com");
-  gBrowser.selectedTab = gTestTab;
-  gTestTab.linkedBrowser.addEventListener("load", function () {
-    gTestTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-
-    is(gTestTab.linkedBrowser.currentURI.spec, "http://example.com/", "example.com loaded");
-
-    test_openUILink();
+function test_openNewTabWith() {
+  openNewTabWith("http://example.com/");
+  let tab = gBrowser.selectedTab = gBrowser.tabs[1];
+  tab.linkedBrowser.addEventListener("load", function onLoad(event) {
+    tab.linkedBrowser.removeEventListener("load", onLoad, true);
+    is(tab.linkedBrowser.currentURI.spec, "http://example.com/", "example.com loaded");
+    gBrowser.removeCurrentTab();
+    runNextTest();
   }, true);
 }
 
 function test_openUILink() {
-  gTestTab.linkedBrowser.addEventListener("load", function () {
-    gTestTab.linkedBrowser.removeEventListener("load", arguments.callee, true);
-
-    is(gTestTab.linkedBrowser.currentURI.spec, "http://example.org/", "example.org loaded");
-
-    gBrowser.removeTab(gTestTab);
-    finish();
+  let tab = gBrowser.selectedTab = gBrowser.addTab("about:blank");
+  tab.linkedBrowser.addEventListener("load", function onLoad(event) {
+    tab.linkedBrowser.removeEventListener("load", onLoad, true);
+    is(tab.linkedBrowser.currentURI.spec, "http://example.org/", "example.org loaded");
+    gBrowser.removeCurrentTab();
+    runNextTest();
   }, true);
 
-  //openUILink(url, e, ignoreButton, ignoreAlt, allowKeywordFixup, postData, referrerUrl);
-  openUILink("http://example.org"); // defaults to "current"
+  openUILink("http://example.org/"); // defaults to "current"
 }
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -324,17 +324,19 @@
             let where = "tab";
             if (isMouseEvent)
               where = whereToOpenLink(aTriggeringEvent, false, false);
 
             if (where == "current") {
               loadCurrent();
             } else {
               this.handleRevert();
-              let params = { allowThirdPartyFixup: true, postData: postData };
+              let params = { allowThirdPartyFixup: true,
+                             postData: postData,
+                             initiatingDoc: document };
               if (!this.valueIsTyped)
                 params.isUTF8 = true;
               openUILinkIn(url, where, params);
             }
           } else {
             loadCurrent();
           }
         ]]></body>
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -101,17 +101,17 @@ function openUILink(url, event, aIgnoreB
     aIgnoreAlt = params.ignoreAlt;
     delete params.ignoreButton;
     delete params.ignoreAlt;
   } else {
     params = {
       allowThirdPartyFixup: aAllowThirdPartyFixup,
       postData: aPostData,
       referrerURI: aReferrerURI,
-      initiatingDoc: event.target.ownerDocument
+      initiatingDoc: event ? event.target.ownerDocument : null
     };
   }
 
   let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
   openUILinkIn(url, where, params);
 }
 
 
@@ -219,16 +219,21 @@ function openLinkIn(url, where, params) 
   var aRelatedToCurrent     = params.relatedToCurrent;
   var aInBackground         = params.inBackground;
   var aDisallowInheritPrincipal = params.disallowInheritPrincipal;
   // Currently, this parameter works only for where=="tab" or "current"
   var aIsUTF8               = params.isUTF8;
   var aInitiatingDoc        = params.initiatingDoc;
 
   if (where == "save") {
+    if (!aInitiatingDoc) {
+      Components.utils.reportError("openUILink/openLinkIn was called with " +
+        "where == 'save' but without initiatingDoc.  See bug 814264.");
+      return;
+    }
     saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc);
     return;
   }
   const Cc = Components.classes;
   const Ci = Components.interfaces;
 
   var w = getTopWin();
   if ((where == "tab" || where == "tabshifted") &&
--- a/browser/components/downloads/content/downloads.css
+++ b/browser/components/downloads/content/downloads.css
@@ -1,12 +1,18 @@
 /* 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/. */
 
+/*** Download panel ***/
+
+#downloadsPanel {
+  -moz-user-focus: normal;
+}
+
 /*** Download items ***/
 
 richlistitem[type="download"] {
   -moz-binding: url('chrome://browser/content/downloads/download.xml#download');
 }
 
 richlistitem[type="download"]:not([selected]) button {
   /* Only focus buttons in the selected item. */
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -351,17 +351,17 @@ const DownloadsPanel = {
     let element = document.commandDispatcher.focusedElement;
     while (element && element != this.panel) {
       element = element.parentNode;
     }
     if (!element) {
       if (DownloadsView.richListBox.itemCount > 0) {
         DownloadsView.richListBox.focus();
       } else {
-        DownloadsView.downloadsHistory.focus();
+        this.panel.focus();
       }
     }
   },
 
   /**
    * Opens the downloads panel when data is ready to be displayed.
    */
   _openPopupIfDataReady: function DP_openPopupIfDataReady()
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -72,18 +72,22 @@ class RemoteAutomation(Automation):
             or for maxTime elapse, in which case kill the process regardless.
         """
         # maxTime is used to override the default timeout, we should honor that
         status = proc.wait(timeout = maxTime)
         self.lastTestSeen = proc.getLastTestSeen
 
         if (status == 1 and self._devicemanager.processExist(proc.procName)):
             # Then we timed out, make sure Fennec is dead
-            print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
-                  "allowed maximum time of %d seconds" % (self.lastTestSeen, int(maxTime))
+            if maxTime:
+                print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
+                      "allowed maximum time of %s seconds" % (self.lastTestSeen, maxTime)
+            else:
+                print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
+                      "allowed maximum time" % (self.lastTestSeen)
             proc.kill()
 
         return status
 
     def checkForCrashes(self, directory, symbolsPath):
         remoteCrashDir = self._remoteProfile + '/minidumps/'
         if not self._devicemanager.dirExists(remoteCrashDir):
             # As of this writing, the minidumps directory is automatically
--- a/config/nspr/Makefile.in
+++ b/config/nspr/Makefile.in
@@ -18,17 +18,17 @@ endif
 ifdef MOZ_NATIVE_NSPR
 $(error config/nspr/Makefile.in is not compatible with MOZ_NATIVE_NSPR)
 endif
 
 # Copy NSPR to the SDK
 ABS_DIST = $(call core_abspath,$(DIST))
 
 libs::
-	$(MAKE) -C $(DEPTH)/nsprpub install prefix=$(ABS_DIST)/sdk exec_prefix=$(ABS_DIST)/sdk bindir=$(ABS_DIST)/sdk/dummy includedir=$(ABS_DIST)/include libdir=$(ABS_DIST)/sdk/lib datadir=$(ABS_DIST)/sdk/dummy DESTDIR=
+	$(MAKE) -C $(DEPTH)/nsprpub install prefix=$(ABS_DIST)/sdk exec_prefix=$(ABS_DIST)/sdk bindir=$(ABS_DIST)/sdk/dummy includedir=$(ABS_DIST)/include/nspr libdir=$(ABS_DIST)/sdk/lib datadir=$(ABS_DIST)/sdk/dummy DESTDIR=
 	$(INSTALL) $(DEPTH)/nsprpub/config/nspr-config $(DIST)/sdk/bin
 	$(RM) -rf $(DIST)/sdk/dummy
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH))) # {
 	$(RM) -f $(DIST)/sdk/lib/$(DLL_PREFIX)nspr4$(DLL_SUFFIX) $(DIST)/sdk/lib/$(DLL_PREFIX)plc4$(DLL_SUFFIX) $(DIST)/sdk/lib/$(DLL_PREFIX)plds4$(DLL_SUFFIX)
 	$(RM) -f $(DIST)/sdk/lib/$(LIB_PREFIX)nspr4_s.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plc4_s.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plds4_s.$(LIB_SUFFIX)
 else # } {
 	$(RM) -f $(DIST)/sdk/lib/$(LIB_PREFIX)nspr4.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plc4.$(LIB_SUFFIX) $(DIST)/sdk/lib/$(LIB_PREFIX)plds4.$(LIB_SUFFIX)
 endif # }
--- a/config/system-headers
+++ b/config/system-headers
@@ -1,8 +1,151 @@
+nspr.h
+plarena.h
+plarenas.h
+plbase64.h
+plerror.h
+plgetopt.h
+plhash.h
+plstr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcpucfg.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+private
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+prwin16.h
+base64.h
+blapit.h
+cert.h
+certdb.h
+certt.h
+ciferfam.h
+cmmf.h
+cmmft.h
+cms.h
+cmsreclist.h
+cmst.h
+crmf.h
+crmft.h
+cryptohi.h
+cryptoht.h
+ecl-exp.h
+hasht.h
+jar-ds.h
+jar.h
+jarfile.h
+key.h
+keyhi.h
+keyt.h
+keythi.h
+nss.h
+nssb64.h
+nssb64t.h
+nssbase.h
+nssbaset.h
+nssck.api
+nssckbi.h
+nssckepv.h
+nssckft.h
+nssckfw.h
+nssckfwc.h
+nssckfwt.h
+nssckg.h
+nssckmdt.h
+nssckt.h
+nssilckt.h
+nssilock.h
+nsslocks.h
+nssrwlk.h
+nssrwlkt.h
+nssutil.h
+ocsp.h
+ocspt.h
+p12.h
+p12plcy.h
+p12t.h
+pk11func.h
+pk11pqg.h
+pk11priv.h
+pk11pub.h
+pk11sdr.h
+pkcs11.h
+pkcs11f.h
+pkcs11n.h
+pkcs11p.h
+pkcs11t.h
+pkcs11u.h
+pkcs12.h
+pkcs12t.h
+pkcs7t.h
+portreg.h
+preenc.h
+secasn1.h
+secasn1t.h
+seccomon.h
+secder.h
+secdert.h
+secdig.h
+secdigt.h
+secerr.h
+sechash.h
+secitem.h
+secmime.h
+secmod.h
+secmodt.h
+secoid.h
+secoidt.h
+secpkcs5.h
+secpkcs7.h
+secport.h
+shsign.h
+smime.h
+ssl.h
+sslerr.h
+sslproto.h
+sslt.h
+utilmodt.h
+utilpars.h
+utilparst.h
+utilrename.h
 A4Stuff.h
 activscp.h
 AEDataModel.h
 AEObjects.h
 AEPackObject.h
 AERegistry.h
 AEUtils.h
 afxcmn.h
@@ -143,17 +286,16 @@ callconv.h
 Carbon/Carbon.h
 CarbonEvents.h
 Carbon.h
 cassert
 c_asm.h
 cctype
 cderr.h
 cerrno
-cert.h
 CFBase.h
 CFBundle.h
 CFData.h
 CFDictionary.h
 cf.h
 CFNumber.h
 CFPlugIn.h
 CFPreferences.h
@@ -323,34 +465,30 @@ iodef.h
 io.h
 IOKit/IOKitLib.h
 IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
 iterator
-jar.h
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
 jemalloc.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
 jpeglib.h
 #endif
 JVMManagerTests.h
 Kerberos/Kerberos.h
 kernel/image.h
 kernel/OS.h
-key.h
-keyt.h
-keythi.h
 LAction.h
 langinfo.h
 LApplication.h
 LArray.h
 LArrayIterator.h
 LAttachable.h
 LAttachment.h
 LaunchServices.h
@@ -522,18 +660,16 @@ net/if.h
 netinet/in.h
 netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
-nss.h
-nssilock.h
 nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
@@ -558,19 +694,16 @@ pango/pangoxft.h
 pango/pango-utils.h
 pascal.h
 Patches.h
 Path.h
 pcfs/pc_dir.h
 Pgenerr.h
 PGenErr.h
 Ph.h
-pk11func.h
-pk11pub.h
-pkcs11t.h
 PLStringFuncs.h
 PMApplication.h
 pmddim.h
 poll.h
 Polygon.h
 portable.h
 Power.h
 PP_ClassHeaders.cp
@@ -620,20 +753,17 @@ rpcproxy.h
 rpc/types.h
 sane/sane.h
 sane/sanei.h
 sane/saneopts.h
 Scrap.h
 Screen.h
 Script.h
 ScrollBar.h
-seccomon.h
 sec.h
-secmod.h
-secmodt.h
 secrng.h
 security.h
 secutil.h
 semaphore.h
 servprov.h
 set
 setjmp.h
 SFNTLayoutTypes.h
@@ -648,19 +778,16 @@ SimpleGameSound.h
 SIOUX.h
 size_t.h
 sndio.h
 someincludefile.h
 Sound.h
 soundcard.h
 sqlite3.h
 ssdef.h
-sslerr.h
-ssl.h
-sslproto.h
 sstream
 stack
 StandardFile.h
 starlet.h
 stat.h
 statreg.cpp
 statreg.h
 stdarg.h
@@ -903,89 +1030,16 @@ X11/XKBlib.h
 X11/Xlib.h
 X11/Xlibint.h
 X11/Xlocale.h
 X11/Xos.h
 X11/Xutil.h
 xpt_struct.h
 xpt_xdr.h
 zmouse.h
-sslt.h
-smime.h
-cms.h
-sechash.h
-secoidt.h
-certdb.h
-secerr.h
-nssutil.h
-nssb64.h
-secasn1.h
-secder.h
-certt.h
-ocsp.h
-keyhi.h
-cryptohi.h
-crmf.h
-pk11pqg.h
-cmmf.h
-base64.h
-secdert.h
-secitem.h
-secmime.h
-nssckbi.h
-pkcs12.h
-p12plcy.h
-pk11sdr.h
-nspr.h
-pratom.h
-prbit.h
-prclist.h
-prcmon.h
-prcountr.h
-prcvar.h
-prdtoa.h
-prenv.h
-prerr.h
-prerror.h
-prinet.h
-prinit.h
-prinrval.h
-prio.h
-pripcsem.h
-prlink.h
-prlock.h
-prlog.h
-prlong.h
-prmem.h
-prmon.h
-prmwait.h
-prnetdb.h
-prolock.h
-prpdce.h
-prprf.h
-prproces.h
-prrng.h
-prrwlock.h
-prshm.h
-prshma.h
-prsystem.h
-prthread.h
-prtime.h
-prtpool.h
-prtrace.h
-prtypes.h
-prvrsion.h
-plbase64.h
-plerror.h
-plgetopt.h
-plresolv.h
-plstr.h
-plarenas.h
-plarena.h
-plhash.h
 speex/speex_resampler.h
 soundtouch/SoundTouch.h
 #if MOZ_NATIVE_PNG==1
 png.h
 #endif
 #if MOZ_NATIVE_ZLIB==1
 zlib.h
 #endif
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -525,17 +525,17 @@ public:
   {
     GetAttr(kNameSpaceID_None, nsGkAtoms::id, aId);
   }
   void SetId(const nsAString& aId)
   {
     SetAttr(kNameSpaceID_None, nsGkAtoms::id, aId, true);
   }
 
-  nsDOMTokenList* ClassList();
+  nsDOMTokenList* GetClassList();
   nsDOMAttributeMap* GetAttributes()
   {
     nsDOMSlots *slots = DOMSlots();
     if (!slots->mAttributeMap) {
       slots->mAttributeMap = new nsDOMAttributeMap(this);
     }
 
     return slots->mAttributeMap;
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -442,34 +442,34 @@ Element::GetLastElementChild() const
       return child->AsElement();
     }
   }
   
   return nullptr;
 }
 
 nsDOMTokenList*
-Element::ClassList()
+Element::GetClassList()
 {
   Element::nsDOMSlots *slots = DOMSlots();
 
   if (!slots->mClassList) {
-    nsCOMPtr<nsIAtom> classAttr = GetClassAttributeName();
+    nsIAtom* classAttr = GetClassAttributeName();
     if (classAttr) {
       slots->mClassList = new nsDOMTokenList(this, classAttr);
     }
   }
 
   return slots->mClassList;
 }
 
 void
 Element::GetClassList(nsIDOMDOMTokenList** aClassList)
 {
-  NS_IF_ADDREF(*aClassList = ClassList());
+  NS_IF_ADDREF(*aClassList = GetClassList());
 }
 
 already_AddRefed<nsIHTMLCollection>
 Element::GetElementsByTagName(const nsAString& aLocalName)
 {
   return NS_GetContentList(this, kNameSpaceID_Unknown, aLocalName);
 }
 
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -255,17 +255,17 @@ public:
                 void* aData,
                 bool aDeep = true,
                 nsIAtom* aMatchAtom = nullptr,
                 int32_t aMatchNameSpaceId = kNameSpaceID_None,
                 bool aFuncMayDependOnAttr = true);
   virtual ~nsContentList();
 
   // nsWrapperCache
-  using nsWrapperCache::GetWrapper;
+  using nsWrapperCache::GetWrapperPreserveColor;
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
   // nsIDOMHTMLCollection
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsBaseContentList overrides
   virtual int32_t IndexOf(nsIContent *aContent, bool aDoFlush);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -6769,17 +6769,17 @@ nsDocument::Destroy()
   for (i = 0; i < count; ++i) {
     mChildren.ChildAt(i)->DestroyContent();
   }
   mInUnlinkOrDeletion = oldVal;
 
   mLayoutHistoryState = nullptr;
 
   // Shut down our external resource map.  We might not need this for
-  // leak-fixing if we fix DocumentViewerImpl to do cycle-collection, but
+  // leak-fixing if we fix nsDocumentViewer to do cycle-collection, but
   // tearing down all those frame trees right now is the right thing to do.
   mExternalResourceMap.Shutdown();
 
   // XXX We really should let cycle collection do this, but that currently still
   //     leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
   nsContentUtils::ReleaseWrapper(static_cast<nsINode*>(this), this);
 }
 
--- a/content/html/content/public/nsIHTMLCollection.h
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -65,21 +65,21 @@ public:
   {
     JSObject* namedItem = NamedItem(cx, name, error);
     found = !!namedItem;
     return namedItem;
   }
 
   virtual void GetSupportedNames(nsTArray<nsString>& aNames) = 0;
 
-  JSObject* GetWrapper()
+  JSObject* GetWrapperPreserveColor()
   {
     nsWrapperCache* cache;
     CallQueryInterface(this, &cache);
-    return cache->GetWrapper();
+    return cache->GetWrapperPreserveColor();
   }
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLCollection, NS_IHTMLCOLLECTION_IID)
 
 #endif /* nsIHTMLCollection_h___ */
--- a/content/html/content/src/HTMLPropertiesCollection.h
+++ b/content/html/content/src/HTMLPropertiesCollection.h
@@ -53,17 +53,17 @@ class HTMLPropertiesCollection : public 
                                  public nsWrapperCache
 {
   friend class PropertyNodeList;
   friend class PropertyStringList;
 public:
   HTMLPropertiesCollection(nsGenericHTMLElement* aRoot);
   virtual ~HTMLPropertiesCollection();
 
-  using nsWrapperCache::GetWrapper;
+  using nsWrapperCache::GetWrapperPreserveColor;
   virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
                                bool *triedToWrap);
 
   virtual Element* GetElementAt(uint32_t aIndex);
 
   NS_IMETHOD NamedItem(const nsAString& aName, nsIDOMNode** aResult);
   void SetDocument(nsIDocument* aDocument);
   nsINode* GetParentObject();
--- a/content/html/content/test/reflect.js
+++ b/content/html/content/test/reflect.js
@@ -43,19 +43,19 @@ function reflectString(aParameters)
   is(element[idlAttr], "",
      "When not set, the IDL attribute should return the empty string");
 
   /**
    * TODO: as long as null stringification doesn't follow the WebIDL
    * specifications, don't add it to the loop below and keep it here.
    */
   element.setAttribute(contentAttr, null);
-  todo_is(element.getAttribute(contentAttr), "null",
+  is(element.getAttribute(contentAttr), "null",
      "null should have been stringified to 'null'");
-  todo_is(element[idlAttr], "null",
+  is(element[idlAttr], "null",
      "null should have been stringified to 'null'");
   element.removeAttribute(contentAttr);
 
   element[idlAttr] = null;
   // TODO: remove this ugly hack when null stringification will work as expected.
   if (element.localName == "textarea" && idlAttr == "wrap") {
     is(element.getAttribute(contentAttr), "null",
        "null should have been stringified to 'null'");
@@ -418,24 +418,18 @@ function reflectBoolean(aParameters)
       result: true },
     { value: { }, stringified: "[object Object]", result: true },
   ];
 
   valuesToTest.forEach(function(v) {
     element.setAttribute(contentAttr, v.value);
     is(element[idlAttr], true,
        "IDL attribute should return always return 'true' if the content attribute has been set");
-    if (v.value === null) {
-      // bug 667856
-      todo(element.getAttribute(contentAttr), v.stringified,
-           "Content attribute should return the stringified value it has been set to.");
-    } else {
-      is(element.getAttribute(contentAttr), v.stringified,
-         "Content attribute should return the stringified value it has been set to.");
-    }
+    is(element.getAttribute(contentAttr), v.stringified,
+       "Content attribute should return the stringified value it has been set to.");
     element.removeAttribute(contentAttr);
 
     element[idlAttr] = v.value;
     is(element[idlAttr], v.result, "IDL attribute should return " + v.result);
     is(element.getAttribute(contentAttr), v.result ? "" : null,
        v.result ? "Content attribute should return the empty string."
                 : "Content attribute should return null.");
     is(element.hasAttribute(contentAttr), v.result,
@@ -460,17 +454,17 @@ function reflectBoolean(aParameters)
  *  - attribute         String    name of the attribute
  *  - nonNegative       Boolean   true if the attribute is limited to 'non-negative numbers', false otherwise
  *  - defaultValue      Integer   [optional] default value, if one exists
  */
 function reflectInt(aParameters)
 {
   // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute().
   function expectedGetAttributeResult(value) {
-    return (value !== null) ? String(value) : "";
+    return String(value);
   }
 
   function stringToInteger(value, nonNegative, defaultValue) {
     // Parse: Ignore leading whitespace, find [+/-][numbers]
     var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value);
     if (result) {
       if ((nonNegative ? 0:-0x80000000) <= result[1] && result[1] <= 0x7FFFFFFF) {
         // If the value is within allowed value range for signed/unsigned integer, return value
--- a/content/media/AudioSampleFormat.h
+++ b/content/media/AudioSampleFormat.h
@@ -1,154 +1,154 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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 MOZILLA_AUDIOSAMPLEFORMAT_H_
-#define MOZILLA_AUDIOSAMPLEFORMAT_H_
-
-#include "nsAlgorithm.h"
-
-namespace mozilla {
-
-/**
- * Audio formats supported in MediaStreams and media elements.
- *
- * Only one of these is supported by AudioStream, and that is determined
- * at compile time (roughly, FLOAT32 on desktops, S16 on mobile). Media decoders
- * produce that format only; queued AudioData always uses that format.
- */
-enum AudioSampleFormat
-{
-  // Native-endian signed 16-bit audio samples
-  AUDIO_FORMAT_S16,
-  // Signed 32-bit float samples
-  AUDIO_FORMAT_FLOAT32,
-  // The format used for output by AudioStream.
-#ifdef MOZ_SAMPLE_TYPE_S16
-  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_S16
-#else
-  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_FLOAT32
-#endif
-};
-
-template <AudioSampleFormat Format> class AudioSampleTraits;
-
-template <> class AudioSampleTraits<AUDIO_FORMAT_FLOAT32> {
-public:
-  typedef float Type;
-};
-template <> class AudioSampleTraits<AUDIO_FORMAT_S16> {
-public:
-  typedef int16_t Type;
-};
-
-typedef AudioSampleTraits<AUDIO_OUTPUT_FORMAT>::Type AudioDataValue;
-
-// Single-sample conversion
-
-/*
- * Use "2^N" conversion since it's simple, fast, "bit transparent", used by
- * many other libraries and apparently behaves reasonably.
- * http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html
- * http://blog.bjornroche.com/2009/12/linearity-and-dynamic-range-in-int.html
- */
-inline float
-AudioSampleToFloat(float aValue)
-{
-  return aValue;
-}
-inline float
-AudioSampleToFloat(int16_t aValue)
-{
-  return aValue/32768.0f;
-}
-
-template <typename T> T FloatToAudioSample(float aValue);
-
-template <> inline float
-FloatToAudioSample<float>(float aValue)
-{
-  return aValue;
-}
-template <> inline int16_t
-FloatToAudioSample<int16_t>(float aValue)
-{
-  float v = aValue*32768.0f;
-  float clamped = NS_MAX(-32768.0f, NS_MIN(32767.0f, v));
-  return int16_t(clamped);
-}
-
-// Sample buffer conversion
-
-template <typename From, typename To> inline void
-ConvertAudioSamples(const From* aFrom, To* aTo, int aCount)
-{
-  for (int i = 0; i < aCount; ++i) {
-    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i]));
-  }
-}
-inline void
-ConvertAudioSamples(const int16_t* aFrom, int16_t* aTo, int aCount)
-{
-  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
-}
-inline void
-ConvertAudioSamples(const float* aFrom, float* aTo, int aCount)
-{
-  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
-}
-
-// Sample buffer conversion with scale
-
-template <typename From, typename To> inline void
-ConvertAudioSamplesWithScale(const From* aFrom, To* aTo, int aCount, float aScale)
-{
-  if (aScale == 1.0f) {
-    ConvertAudioSamples(aFrom, aTo, aCount);
-    return;
-  }
-  for (int i = 0; i < aCount; ++i) {
-    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i])*aScale);
-  }
-}
-inline void
-ConvertAudioSamplesWithScale(const int16_t* aFrom, int16_t* aTo, int aCount, float aScale)
-{
-  if (aScale == 1.0f) {
-    ConvertAudioSamples(aFrom, aTo, aCount);
-    return;
-  }
-  if (0.0f <= aScale && aScale < 1.0f) {
-    int32_t scale = int32_t((1 << 16) * aScale);
-    for (int i = 0; i < aCount; ++i) {
-      aTo[i] = int16_t((int32_t(aFrom[i]) * scale) >> 16);
-    }
-    return;
-  }
-  for (int i = 0; i < aCount; ++i) {
-    aTo[i] = FloatToAudioSample<int16_t>(AudioSampleToFloat(aFrom[i])*aScale);
-  }
-}
-
-// In place audio sample scaling.
-inline void
-ScaleAudioSamples(float* aBuffer, int aCount, float aScale)
-{
-  for (int32_t i = 0; i < aCount; ++i) {
-    aBuffer[i] *= aScale;
-  }
-}
-
-
-inline void
-ScaleAudioSamples(short* aBuffer, int aCount, float aScale)
-{
-  int32_t volume = int32_t(1 << 16) * aScale;
-  for (int32_t i = 0; i < aCount; ++i) {
-    aBuffer[i] = short((int32_t(aBuffer[i]) * volume) >> 16);
-  }
-}
-
-} // namespace mozilla
-
-#endif /* MOZILLA_AUDIOSAMPLEFORMAT_H_ */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 MOZILLA_AUDIOSAMPLEFORMAT_H_
+#define MOZILLA_AUDIOSAMPLEFORMAT_H_
+
+#include "nsAlgorithm.h"
+
+namespace mozilla {
+
+/**
+ * Audio formats supported in MediaStreams and media elements.
+ *
+ * Only one of these is supported by AudioStream, and that is determined
+ * at compile time (roughly, FLOAT32 on desktops, S16 on mobile). Media decoders
+ * produce that format only; queued AudioData always uses that format.
+ */
+enum AudioSampleFormat
+{
+  // Native-endian signed 16-bit audio samples
+  AUDIO_FORMAT_S16,
+  // Signed 32-bit float samples
+  AUDIO_FORMAT_FLOAT32,
+  // The format used for output by AudioStream.
+#ifdef MOZ_SAMPLE_TYPE_S16
+  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_S16
+#else
+  AUDIO_OUTPUT_FORMAT = AUDIO_FORMAT_FLOAT32
+#endif
+};
+
+template <AudioSampleFormat Format> class AudioSampleTraits;
+
+template <> class AudioSampleTraits<AUDIO_FORMAT_FLOAT32> {
+public:
+  typedef float Type;
+};
+template <> class AudioSampleTraits<AUDIO_FORMAT_S16> {
+public:
+  typedef int16_t Type;
+};
+
+typedef AudioSampleTraits<AUDIO_OUTPUT_FORMAT>::Type AudioDataValue;
+
+// Single-sample conversion
+
+/*
+ * Use "2^N" conversion since it's simple, fast, "bit transparent", used by
+ * many other libraries and apparently behaves reasonably.
+ * http://blog.bjornroche.com/2009/12/int-float-int-its-jungle-out-there.html
+ * http://blog.bjornroche.com/2009/12/linearity-and-dynamic-range-in-int.html
+ */
+inline float
+AudioSampleToFloat(float aValue)
+{
+  return aValue;
+}
+inline float
+AudioSampleToFloat(int16_t aValue)
+{
+  return aValue/32768.0f;
+}
+
+template <typename T> T FloatToAudioSample(float aValue);
+
+template <> inline float
+FloatToAudioSample<float>(float aValue)
+{
+  return aValue;
+}
+template <> inline int16_t
+FloatToAudioSample<int16_t>(float aValue)
+{
+  float v = aValue*32768.0f;
+  float clamped = NS_MAX(-32768.0f, NS_MIN(32767.0f, v));
+  return int16_t(clamped);
+}
+
+// Sample buffer conversion
+
+template <typename From, typename To> inline void
+ConvertAudioSamples(const From* aFrom, To* aTo, int aCount)
+{
+  for (int i = 0; i < aCount; ++i) {
+    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i]));
+  }
+}
+inline void
+ConvertAudioSamples(const int16_t* aFrom, int16_t* aTo, int aCount)
+{
+  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
+}
+inline void
+ConvertAudioSamples(const float* aFrom, float* aTo, int aCount)
+{
+  memcpy(aTo, aFrom, sizeof(*aTo)*aCount);
+}
+
+// Sample buffer conversion with scale
+
+template <typename From, typename To> inline void
+ConvertAudioSamplesWithScale(const From* aFrom, To* aTo, int aCount, float aScale)
+{
+  if (aScale == 1.0f) {
+    ConvertAudioSamples(aFrom, aTo, aCount);
+    return;
+  }
+  for (int i = 0; i < aCount; ++i) {
+    aTo[i] = FloatToAudioSample<To>(AudioSampleToFloat(aFrom[i])*aScale);
+  }
+}
+inline void
+ConvertAudioSamplesWithScale(const int16_t* aFrom, int16_t* aTo, int aCount, float aScale)
+{
+  if (aScale == 1.0f) {
+    ConvertAudioSamples(aFrom, aTo, aCount);
+    return;
+  }
+  if (0.0f <= aScale && aScale < 1.0f) {
+    int32_t scale = int32_t((1 << 16) * aScale);
+    for (int i = 0; i < aCount; ++i) {
+      aTo[i] = int16_t((int32_t(aFrom[i]) * scale) >> 16);
+    }
+    return;
+  }
+  for (int i = 0; i < aCount; ++i) {
+    aTo[i] = FloatToAudioSample<int16_t>(AudioSampleToFloat(aFrom[i])*aScale);
+  }
+}
+
+// In place audio sample scaling.
+inline void
+ScaleAudioSamples(float* aBuffer, int aCount, float aScale)
+{
+  for (int32_t i = 0; i < aCount; ++i) {
+    aBuffer[i] *= aScale;
+  }
+}
+
+
+inline void
+ScaleAudioSamples(short* aBuffer, int aCount, float aScale)
+{
+  int32_t volume = int32_t(1 << 16) * aScale;
+  for (int32_t i = 0; i < aCount; ++i) {
+    aBuffer[i] = short((int32_t(aBuffer[i]) * volume) >> 16);
+  }
+}
+
+} // namespace mozilla
+
+#endif /* MOZILLA_AUDIOSAMPLEFORMAT_H_ */
--- a/content/media/AudioSegment.cpp
+++ b/content/media/AudioSegment.cpp
@@ -1,123 +1,123 @@
-/* -*- 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 "AudioSegment.h"
-
-#include "AudioStream.h"
-
-namespace mozilla {
-
-template <class SrcT, class DestT>
-static void
-InterleaveAndConvertBuffer(const SrcT* aSource, int32_t aSourceLength,
-                           int32_t aLength,
-                           float aVolume,
-                           int32_t aChannels,
-                           DestT* aOutput)
-{
-  DestT* output = aOutput;
-  for (int32_t i = 0; i < aLength; ++i) {
-    for (int32_t channel = 0; channel < aChannels; ++channel) {
-      float v = AudioSampleToFloat(aSource[channel*aSourceLength + i])*aVolume;
-      *output = FloatToAudioSample<DestT>(v);
-      ++output;
-    }
-  }
-}
-
-static inline void
-InterleaveAndConvertBuffer(const int16_t* aSource, int32_t aSourceLength,
-                           int32_t aLength,
-                           float aVolume,
-                           int32_t aChannels,
-                           int16_t* aOutput)
-{
-  int16_t* output = aOutput;
-  if (0.0f <= aVolume && aVolume <= 1.0f) {
-    int32_t scale = int32_t((1 << 16) * aVolume);
-    for (int32_t i = 0; i < aLength; ++i) {
-      for (int32_t channel = 0; channel < aChannels; ++channel) {
-        int16_t s = aSource[channel*aSourceLength + i];
-        *output = int16_t((int32_t(s) * scale) >> 16);
-        ++output;
-      }
-    }
-    return;
-  }
-
-  for (int32_t i = 0; i < aLength; ++i) {
-    for (int32_t channel = 0; channel < aChannels; ++channel) {
-      float v = AudioSampleToFloat(aSource[channel*aSourceLength + i])*aVolume;
-      *output = FloatToAudioSample<int16_t>(v);
-      ++output;
-    }
-  }
-}
-
-static void
-InterleaveAndConvertBuffer(const void* aSource, AudioSampleFormat aSourceFormat,
-                           int32_t aSourceLength,
-                           int32_t aOffset, int32_t aLength,
-                           float aVolume,
-                           int32_t aChannels,
-                           AudioDataValue* aOutput)
-{
-  switch (aSourceFormat) {
-  case AUDIO_FORMAT_FLOAT32:
-    InterleaveAndConvertBuffer(static_cast<const float*>(aSource) + aOffset,
-                               aSourceLength,
-                               aLength,
-                               aVolume,
-                               aChannels,
-                               aOutput);
-    break;
-  case AUDIO_FORMAT_S16:
-    InterleaveAndConvertBuffer(static_cast<const int16_t*>(aSource) + aOffset,
-                               aSourceLength,
-                               aLength,
-                               aVolume,
-                               aChannels,
-                               aOutput);
-    break;
-  }
-}
-
-void
-AudioSegment::ApplyVolume(float aVolume)
-{
-  for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
-    ci->mVolume *= aVolume;
-  }
-}
-
-static const int STATIC_AUDIO_SAMPLES = 10000;
-
-void
-AudioSegment::WriteTo(AudioStream* aOutput)
-{
-  NS_ASSERTION(mChannels == aOutput->GetChannels(), "Wrong number of channels");
-  nsAutoTArray<AudioDataValue,STATIC_AUDIO_SAMPLES> buf;
-  for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
-    AudioChunk& c = *ci;
-    if (uint64_t(mChannels)*c.mDuration > INT32_MAX) {
-      NS_ERROR("Buffer overflow");
-      return;
-    }
-    buf.SetLength(int32_t(mChannels*c.mDuration));
-    if (c.mBuffer) {
-      InterleaveAndConvertBuffer(c.mBuffer->Data(), c.mBufferFormat, c.mBufferLength,
-                                 c.mOffset, int32_t(c.mDuration),
-                                 c.mVolume,
-                                 aOutput->GetChannels(),
-                                 buf.Elements());
-    } else {
-      // Assumes that a bit pattern of zeroes == 0.0f
-      memset(buf.Elements(), 0, buf.Length()*sizeof(AudioDataValue));
-    }
-    aOutput->Write(buf.Elements(), int32_t(c.mDuration));
-  }
-}
-
-}
+/* -*- 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 "AudioSegment.h"
+
+#include "AudioStream.h"
+
+namespace mozilla {
+
+template <class SrcT, class DestT>
+static void
+InterleaveAndConvertBuffer(const SrcT* aSource, int32_t aSourceLength,
+                           int32_t aLength,
+                           float aVolume,
+                           int32_t aChannels,
+                           DestT* aOutput)
+{
+  DestT* output = aOutput;
+  for (int32_t i = 0; i < aLength; ++i) {
+    for (int32_t channel = 0; channel < aChannels; ++channel) {
+      float v = AudioSampleToFloat(aSource[channel*aSourceLength + i])*aVolume;
+      *output = FloatToAudioSample<DestT>(v);
+      ++output;
+    }
+  }
+}
+
+static inline void
+InterleaveAndConvertBuffer(const int16_t* aSource, int32_t aSourceLength,
+                           int32_t aLength,
+                           float aVolume,
+                           int32_t aChannels,
+                           int16_t* aOutput)
+{
+  int16_t* output = aOutput;
+  if (0.0f <= aVolume && aVolume <= 1.0f) {
+    int32_t scale = int32_t((1 << 16) * aVolume);
+    for (int32_t i = 0; i < aLength; ++i) {
+      for (int32_t channel = 0; channel < aChannels; ++channel) {
+        int16_t s = aSource[channel*aSourceLength + i];
+        *output = int16_t((int32_t(s) * scale) >> 16);
+        ++output;
+      }
+    }
+    return;
+  }
+
+  for (int32_t i = 0; i < aLength; ++i) {
+    for (int32_t channel = 0; channel < aChannels; ++channel) {
+      float v = AudioSampleToFloat(aSource[channel*aSourceLength + i])*aVolume;
+      *output = FloatToAudioSample<int16_t>(v);
+      ++output;
+    }
+  }
+}
+
+static void
+InterleaveAndConvertBuffer(const void* aSource, AudioSampleFormat aSourceFormat,
+                           int32_t aSourceLength,
+                           int32_t aOffset, int32_t aLength,
+                           float aVolume,
+                           int32_t aChannels,
+                           AudioDataValue* aOutput)
+{
+  switch (aSourceFormat) {
+  case AUDIO_FORMAT_FLOAT32:
+    InterleaveAndConvertBuffer(static_cast<const float*>(aSource) + aOffset,
+                               aSourceLength,
+                               aLength,
+                               aVolume,
+                               aChannels,
+                               aOutput);
+    break;
+  case AUDIO_FORMAT_S16:
+    InterleaveAndConvertBuffer(static_cast<const int16_t*>(aSource) + aOffset,
+                               aSourceLength,
+                               aLength,
+                               aVolume,
+                               aChannels,
+                               aOutput);
+    break;
+  }
+}
+
+void
+AudioSegment::ApplyVolume(float aVolume)
+{
+  for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
+    ci->mVolume *= aVolume;
+  }
+}
+
+static const int STATIC_AUDIO_SAMPLES = 10000;
+
+void
+AudioSegment::WriteTo(AudioStream* aOutput)
+{
+  NS_ASSERTION(mChannels == aOutput->GetChannels(), "Wrong number of channels");
+  nsAutoTArray<AudioDataValue,STATIC_AUDIO_SAMPLES> buf;
+  for (ChunkIterator ci(*this); !ci.IsEnded(); ci.Next()) {
+    AudioChunk& c = *ci;
+    if (uint64_t(mChannels)*c.mDuration > INT32_MAX) {
+      NS_ERROR("Buffer overflow");
+      return;
+    }
+    buf.SetLength(int32_t(mChannels*c.mDuration));
+    if (c.mBuffer) {
+      InterleaveAndConvertBuffer(c.mBuffer->Data(), c.mBufferFormat, c.mBufferLength,
+                                 c.mOffset, int32_t(c.mDuration),
+                                 c.mVolume,
+                                 aOutput->GetChannels(),
+                                 buf.Elements());
+    } else {
+      // Assumes that a bit pattern of zeroes == 0.0f
+      memset(buf.Elements(), 0, buf.Length()*sizeof(AudioDataValue));
+    }
+    aOutput->Write(buf.Elements(), int32_t(c.mDuration));
+  }
+}
+
+}
--- a/content/media/AudioStream.cpp
+++ b/content/media/AudioStream.cpp
@@ -41,21 +41,21 @@ namespace mozilla {
 PRLogModuleInfo* gAudioStreamLog = nullptr;
 #endif
 
 static const uint32_t FAKE_BUFFER_SIZE = 176400;
 
 // Number of milliseconds per second.
 static const int64_t MS_PER_S = 1000;
 
-class nsNativeAudioStream : public AudioStream
+class NativeAudioStream : public AudioStream
 {
  public:
-  ~nsNativeAudioStream();
-  nsNativeAudioStream();
+  ~NativeAudioStream();
+  NativeAudioStream();
 
   nsresult Init(int32_t aNumChannels, int32_t aRate,
                 const dom::AudioChannelType aAudioChannelType);
   void Shutdown();
   nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames);
   uint32_t Available();
   void SetVolume(double aVolume);
   void Drain();
@@ -218,21 +218,20 @@ void AudioStream::ShutdownLibrary()
 AudioStream::~AudioStream()
 {
 }
 
 bool AudioStream::EnsureTimeStretcherInitialized()
 {
   if (mTimeStretcher)
     return true;
-  soundtouch::SoundTouch* state = new soundtouch::SoundTouch();
-  if (!state) {
+  mTimeStretcher = new soundtouch::SoundTouch();
+  if (!mTimeStretcher) {
     return false;
   }
-  mTimeStretcher.own(state);
   mTimeStretcher->setSampleRate(mInRate);
   mTimeStretcher->setChannels(mChannels);
   mTimeStretcher->setPitch(1.0);
   return true;
 }
 
 nsresult AudioStream::SetPlaybackRate(double aPlaybackRate)
 {
@@ -274,97 +273,97 @@ nsresult AudioStream::SetPreservesPitch(
     mTimeStretcher->setRate(mAudioClock.GetPlaybackRate());
   }
 
   mAudioClock.SetPreservesPitch(aPreservesPitch);
 
   return NS_OK;
 }
 
-nsNativeAudioStream::nsNativeAudioStream() :
+NativeAudioStream::NativeAudioStream() :
   mVolume(1.0),
   mAudioHandle(0),
   mPaused(false),
   mInError(false)
 {
 }
 
-nsNativeAudioStream::~nsNativeAudioStream()
+NativeAudioStream::~NativeAudioStream()
 {
   Shutdown();
 }
 
-nsresult nsNativeAudioStream::Init(int32_t aNumChannels, int32_t aRate,
+nsresult NativeAudioStream::Init(int32_t aNumChannels, int32_t aRate,
                                    const dom::AudioChannelType aAudioChannelType)
 {
   mInRate = mOutRate = aRate;
   mChannels = aNumChannels;
 
   if (sa_stream_create_pcm(reinterpret_cast<sa_stream_t**>(&mAudioHandle),
                            NULL,
                            SA_MODE_WRONLY,
                            SA_PCM_FORMAT_S16_NE,
                            aRate,
                            aNumChannels) != SA_SUCCESS) {
     mAudioHandle = nullptr;
     mInError = true;
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_create_pcm error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_create_pcm error"));
     return NS_ERROR_FAILURE;
   }
 
   int saError = sa_stream_set_stream_type(static_cast<sa_stream_t*>(mAudioHandle),
                        ConvertChannelToSAType(aAudioChannelType));
   if (saError != SA_SUCCESS && saError != SA_ERROR_NOT_SUPPORTED) {
     mAudioHandle = nullptr;
     mInError = true;
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_set_stream_type error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_set_stream_type error"));
     return NS_ERROR_FAILURE;
   }
 
   if (sa_stream_open(static_cast<sa_stream_t*>(mAudioHandle)) != SA_SUCCESS) {
     sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
     mAudioHandle = nullptr;
     mInError = true;
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_open error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_open error"));
     return NS_ERROR_FAILURE;
   }
   mInError = false;
 
   mAudioClock.Init();
 
   return NS_OK;
 }
 
-void nsNativeAudioStream::Shutdown()
+void NativeAudioStream::Shutdown()
 {
   if (!mAudioHandle)
     return;
 
   sa_stream_destroy(static_cast<sa_stream_t*>(mAudioHandle));
   mAudioHandle = nullptr;
   mInError = true;
 }
 
-int32_t nsNativeAudioStream::WriteToBackend(const AudioDataValue* aBuffer, uint32_t aSamples)
+int32_t NativeAudioStream::WriteToBackend(const AudioDataValue* aBuffer, uint32_t aSamples)
 {
   double scaledVolume = GetVolumeScale() * mVolume;
 
   nsAutoArrayPtr<short> outputBuffer(new short[aSamples]);
   ConvertAudioSamplesWithScale(aBuffer, outputBuffer.get(), aSamples, scaledVolume);
 
   if (sa_stream_write(static_cast<sa_stream_t*>(mAudioHandle),
                       outputBuffer,
                       aSamples * sizeof(short)) != SA_SUCCESS) {
     return -1;
   }
   mAudioClock.UpdateWritePosition(aSamples / mChannels);
   return aSamples;
 }
 
-nsresult nsNativeAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames)
+nsresult NativeAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames)
 {
   NS_ASSERTION(!mPaused, "Don't write audio when paused, you'll block");
 
   if (mInError)
     return NS_ERROR_FAILURE;
 
   uint32_t samples = aFrames * mChannels;
   int32_t written = -1;
@@ -387,111 +386,111 @@ nsresult nsNativeAudioStream::Write(cons
     } else {
       written = 0;
     }
   } else {
     written = WriteToBackend(aBuf, samples);
   }
 
   if (written == -1) {
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_write error"));
     mInError = true;
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
-uint32_t nsNativeAudioStream::Available()
+uint32_t NativeAudioStream::Available()
 {
   // If the audio backend failed to open, lie and say we'll accept some
   // data.
   if (mInError)
     return FAKE_BUFFER_SIZE;
 
   size_t s = 0;
   if (sa_stream_get_write_size(static_cast<sa_stream_t*>(mAudioHandle), &s) != SA_SUCCESS)
     return 0;
 
   return s / mChannels / sizeof(short);
 }
 
-void nsNativeAudioStream::SetVolume(double aVolume)
+void NativeAudioStream::SetVolume(double aVolume)
 {
   NS_ASSERTION(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
 #if defined(SA_PER_STREAM_VOLUME)
   if (sa_stream_set_volume_abs(static_cast<sa_stream_t*>(mAudioHandle), aVolume) != SA_SUCCESS) {
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_set_volume_abs error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_set_volume_abs error"));
     mInError = true;
   }
 #else
   mVolume = aVolume;
 #endif
 }
 
-void nsNativeAudioStream::Drain()
+void NativeAudioStream::Drain()
 {
   NS_ASSERTION(!mPaused, "Don't drain audio when paused, it won't finish!");
 
   // Write all the frames still in the time stretcher pipeline.
   if (mTimeStretcher) {
     uint32_t numFrames = mTimeStretcher->numSamples();
     uint32_t arraySize = numFrames * mChannels * sizeof(AudioDataValue);
     nsAutoArrayPtr<AudioDataValue> data(new AudioDataValue[arraySize]);
     uint32_t framesAvailable = mTimeStretcher->receiveSamples(data, numFrames);
     int32_t written = 0;
     if (framesAvailable) {
       written = WriteToBackend(data, framesAvailable * mChannels);
     }
 
     if (written == -1) {
-      PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_write error"));
+      PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_write error"));
       mInError = true;
     }
 
     NS_ASSERTION(mTimeStretcher->numSamples() == 0,
                  "We did not get all the data from the SoundTouch pipeline.");
   }
 
   if (mInError)
     return;
 
   int r = sa_stream_drain(static_cast<sa_stream_t*>(mAudioHandle));
   if (r != SA_SUCCESS && r != SA_ERROR_INVALID) {
-    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("nsNativeAudioStream: sa_stream_drain error"));
+    PR_LOG(gAudioStreamLog, PR_LOG_ERROR, ("NativeAudioStream: sa_stream_drain error"));
     mInError = true;
   }
 }
 
-void nsNativeAudioStream::Pause()
+void NativeAudioStream::Pause()
 {
   if (mInError)
     return;
   mPaused = true;
   sa_stream_pause(static_cast<sa_stream_t*>(mAudioHandle));
 }
 
-void nsNativeAudioStream::Resume()
+void NativeAudioStream::Resume()
 {
   if (mInError)
     return;
   mPaused = false;
   sa_stream_resume(static_cast<sa_stream_t*>(mAudioHandle));
 }
 
-int64_t nsNativeAudioStream::GetPosition()
+int64_t NativeAudioStream::GetPosition()
 {
   return mAudioClock.GetPosition();
 }
 
-int64_t nsNativeAudioStream::GetPositionInFrames()
+int64_t NativeAudioStream::GetPositionInFrames()
 {
   return mAudioClock.GetPositionInFrames();
 }
 
-int64_t nsNativeAudioStream::GetPositionInFramesInternal()
+int64_t NativeAudioStream::GetPositionInFramesInternal()
 {
   if (mInError) {
     return -1;
   }
 
   sa_position_t positionType = SA_POSITION_WRITE_SOFTWARE;
 #if defined(XP_WIN)
   positionType = SA_POSITION_WRITE_HARDWARE;
@@ -500,22 +499,22 @@ int64_t nsNativeAudioStream::GetPosition
   if (sa_stream_get_position(static_cast<sa_stream_t*>(mAudioHandle),
                              positionType, &position) == SA_SUCCESS) {
     return position / mChannels / sizeof(short);
   }
 
   return -1;
 }
 
-bool nsNativeAudioStream::IsPaused()
+bool NativeAudioStream::IsPaused()
 {
   return mPaused;
 }
 
-int32_t nsNativeAudioStream::GetMinWriteSize()
+int32_t NativeAudioStream::GetMinWriteSize()
 {
   size_t size;
   int r = sa_stream_get_min_write(static_cast<sa_stream_t*>(mAudioHandle),
                                   &size);
   if (r == SA_ERROR_NOT_SUPPORTED)
     return 1;
   else if (r != SA_SUCCESS || size > INT32_MAX)
     return -1;
@@ -584,21 +583,21 @@ public:
 
 private:
   nsAutoArrayPtr<uint8_t> mBuffer;
   uint32_t mCapacity;
   uint32_t mStart;
   uint32_t mCount;
 };
 
-class nsBufferedAudioStream : public AudioStream
+class BufferedAudioStream : public AudioStream
 {
  public:
-  nsBufferedAudioStream();
-  ~nsBufferedAudioStream();
+  BufferedAudioStream();
+  ~BufferedAudioStream();
 
   nsresult Init(int32_t aNumChannels, int32_t aRate,
                 const dom::AudioChannelType aAudioChannelType);
   void Shutdown();
   nsresult Write(const AudioDataValue* aBuf, uint32_t aFrames);
   uint32_t Available();
   void SetVolume(double aVolume);
   void Drain();
@@ -608,22 +607,22 @@ class nsBufferedAudioStream : public Aud
   int64_t GetPositionInFrames();
   int64_t GetPositionInFramesInternal();
   bool IsPaused();
   int32_t GetMinWriteSize();
 
 private:
   static long DataCallback_S(cubeb_stream*, void* aThis, void* aBuffer, long aFrames)
   {
-    return static_cast<nsBufferedAudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
+    return static_cast<BufferedAudioStream*>(aThis)->DataCallback(aBuffer, aFrames);
   }
 
   static void StateCallback_S(cubeb_stream*, void* aThis, cubeb_state aState)
   {
-    static_cast<nsBufferedAudioStream*>(aThis)->StateCallback(aState);
+    static_cast<BufferedAudioStream*>(aThis)->StateCallback(aState);
   }
 
   long DataCallback(void* aBuffer, long aFrames);
   void StateCallback(cubeb_state aState);
 
   long GetUnprocessed(void* aBuffer, long aFrames);
 
   long GetTimeStretched(void* aBuffer, long aFrames);
@@ -684,36 +683,36 @@ private:
   StreamState mState;
 };
 #endif
 
 AudioStream* AudioStream::AllocateStream()
 {
 #if defined(MOZ_CUBEB)
   if (GetUseCubeb()) {
-    return new nsBufferedAudioStream();
+    return new BufferedAudioStream();
   }
 #endif
-  return new nsNativeAudioStream();
+  return new NativeAudioStream();
 }
 
 #if defined(MOZ_CUBEB)
-nsBufferedAudioStream::nsBufferedAudioStream()
-  : mMonitor("nsBufferedAudioStream"), mLostFrames(0), mVolume(1.0),
+BufferedAudioStream::BufferedAudioStream()
+  : mMonitor("BufferedAudioStream"), mLostFrames(0), mVolume(1.0),
     mBytesPerFrame(0), mState(INITIALIZED)
 {
 }
 
-nsBufferedAudioStream::~nsBufferedAudioStream()
+BufferedAudioStream::~BufferedAudioStream()
 {
   Shutdown();
 }
 
 nsresult
-nsBufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
+BufferedAudioStream::Init(int32_t aNumChannels, int32_t aRate,
                             const dom::AudioChannelType aAudioChannelType)
 {
   cubeb* cubebContext = GetCubebContext();
 
   if (!cubebContext || aNumChannels < 0 || aRate < 0) {
     return NS_ERROR_FAILURE;
   }
 
@@ -729,17 +728,17 @@ nsBufferedAudioStream::Init(int32_t aNum
     params.format = CUBEB_SAMPLE_FLOAT32NE;
   }
   mBytesPerFrame = sizeof(AudioDataValue) * aNumChannels;
 
   mAudioClock.Init();
 
   {
     cubeb_stream* stream;
-    if (cubeb_stream_init(cubebContext, &stream, "nsBufferedAudioStream", params,
+    if (cubeb_stream_init(cubebContext, &stream, "BufferedAudioStream", params,
                           GetCubebLatency(), DataCallback_S, StateCallback_S, this) == CUBEB_OK) {
       mCubebStream.own(stream);
     }
   }
 
   if (!mCubebStream) {
     return NS_ERROR_FAILURE;
   }
@@ -750,28 +749,28 @@ nsBufferedAudioStream::Init(int32_t aNum
   uint32_t bufferLimit = FramesToBytes(aRate);
   NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
   mBuffer.SetCapacity(bufferLimit);
 
   return NS_OK;
 }
 
 void
-nsBufferedAudioStream::Shutdown()
+BufferedAudioStream::Shutdown()
 {
   if (mState == STARTED) {
     Pause();
   }
   if (mCubebStream) {
     mCubebStream.reset();
   }
 }
 
 nsresult
-nsBufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames)
+BufferedAudioStream::Write(const AudioDataValue* aBuf, uint32_t aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState == ERRORED) {
     return NS_ERROR_FAILURE;
   }
   NS_ASSERTION(mState == INITIALIZED || mState == STARTED,
     "Stream write in unexpected state.");
 
@@ -804,52 +803,52 @@ nsBufferedAudioStream::Write(const Audio
       mon.Wait();
     }
   }
 
   return NS_OK;
 }
 
 uint32_t
-nsBufferedAudioStream::Available()
+BufferedAudioStream::Available()
 {
   MonitorAutoLock mon(mMonitor);
   NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
   return BytesToFrames(mBuffer.Available());
 }
 
 int32_t
-nsBufferedAudioStream::GetMinWriteSize()
+BufferedAudioStream::GetMinWriteSize()
 {
   return 1;
 }
 
 void
-nsBufferedAudioStream::SetVolume(double aVolume)
+BufferedAudioStream::SetVolume(double aVolume)
 {
   MonitorAutoLock mon(mMonitor);
   NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
   mVolume = aVolume;
 }
 
 void
-nsBufferedAudioStream::Drain()
+BufferedAudioStream::Drain()
 {
   MonitorAutoLock mon(mMonitor);
   if (mState != STARTED) {
     return;
   }
   mState = DRAINING;
   while (mState == DRAINING) {
     mon.Wait();
   }
 }
 
 void
-nsBufferedAudioStream::Pause()
+BufferedAudioStream::Pause()
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState != STARTED) {
     return;
   }
 
   int r;
   {
@@ -857,17 +856,17 @@ nsBufferedAudioStream::Pause()
     r = cubeb_stream_stop(mCubebStream);
   }
   if (mState != ERRORED && r == CUBEB_OK) {
     mState = STOPPED;
   }
 }
 
 void
-nsBufferedAudioStream::Resume()
+BufferedAudioStream::Resume()
 {
   MonitorAutoLock mon(mMonitor);
   if (!mCubebStream || mState != STOPPED) {
     return;
   }
 
   int r;
   {
@@ -875,43 +874,43 @@ nsBufferedAudioStream::Resume()
     r = cubeb_stream_start(mCubebStream);
   }
   if (mState != ERRORED && r == CUBEB_OK) {
     mState = STARTED;
   }
 }
 
 int64_t
-nsBufferedAudioStream::GetPosition()
+BufferedAudioStream::GetPosition()
 {
   return mAudioClock.GetPosition();
 }
 
 // This function is miscompiled by PGO with MSVC 2010.  See bug 768333.
 #ifdef _MSC_VER
 #pragma optimize("", off)
 #endif
 int64_t
-nsBufferedAudioStream::GetPositionInFrames()
+BufferedAudioStream::GetPositionInFrames()
 {
   return mAudioClock.GetPositionInFrames();
 }
 #ifdef _MSC_VER
 #pragma optimize("", on)
 #endif
 
 int64_t
-nsBufferedAudioStream::GetPositionInFramesInternal()
+BufferedAudioStream::GetPositionInFramesInternal()
 {
   MonitorAutoLock mon(mMonitor);
   return GetPositionInFramesUnlocked();
 }
 
 int64_t
-nsBufferedAudioStream::GetPositionInFramesUnlocked()
+BufferedAudioStream::GetPositionInFramesUnlocked()
 {
   mMonitor.AssertCurrentThreadOwns();
 
   if (!mCubebStream || mState == ERRORED) {
     return -1;
   }
 
   uint64_t position = 0;
@@ -927,24 +926,24 @@ nsBufferedAudioStream::GetPositionInFram
   uint64_t adjustedPosition = 0;
   if (position >= mLostFrames) {
     adjustedPosition = position - mLostFrames;
   }
   return NS_MIN<uint64_t>(adjustedPosition, INT64_MAX);
 }
 
 bool
-nsBufferedAudioStream::IsPaused()
+BufferedAudioStream::IsPaused()
 {
   MonitorAutoLock mon(mMonitor);
   return mState == STOPPED;
 }
 
 long
-nsBufferedAudioStream::GetUnprocessed(void* aBuffer, long aFrames)
+BufferedAudioStream::GetUnprocessed(void* aBuffer, long aFrames)
 {
   uint8_t* wpos = reinterpret_cast<uint8_t*>(aBuffer);
 
   // Flush the timestretcher pipeline, if we were playing using a playback rate
   // other than 1.0.
   uint32_t flushedFrames = 0;
   if (mTimeStretcher && mTimeStretcher->numSamples()) {
     flushedFrames = mTimeStretcher->receiveSamples(reinterpret_cast<AudioDataValue*>(wpos), aFrames);
@@ -958,17 +957,17 @@ nsBufferedAudioStream::GetUnprocessed(vo
   mBuffer.PopElements(available, &input[0], &input_size[0], &input[1], &input_size[1]);
   memcpy(wpos, input[0], input_size[0]);
   wpos += input_size[0];
   memcpy(wpos, input[1], input_size[1]);
   return BytesToFrames(available) + flushedFrames;
 }
 
 long
-nsBufferedAudioStream::GetTimeStretched(void* aBuffer, long aFrames)
+BufferedAudioStream::GetTimeStretched(void* aBuffer, long aFrames)
 {
   long processedFrames = 0;
   if (!EnsureTimeStretcherInitialized()) {
     return -1;
   }
   uint8_t* wpos = reinterpret_cast<uint8_t*>(aBuffer);
   double playbackRate = static_cast<double>(mInRate) / mOutRate;
   uint32_t toPopBytes = FramesToBytes(ceil(aFrames / playbackRate));
@@ -993,17 +992,17 @@ nsBufferedAudioStream::GetTimeStretched(
     wpos += FramesToBytes(receivedFrames);
     processedFrames += receivedFrames;
   } while (processedFrames < aFrames && !lowOnBufferedData);
 
   return processedFrames;
 }
 
 long
-nsBufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
+BufferedAudioStream::DataCallback(void* aBuffer, long aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   uint32_t available = NS_MIN(static_cast<uint32_t>(FramesToBytes(aFrames)), mBuffer.Length());
   NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames");
   uint32_t underrunFrames = 0;
   uint32_t servicedFrames = 0;
 
   if (available) {
@@ -1032,17 +1031,17 @@ nsBufferedAudioStream::DataCallback(void
     servicedFrames += underrunFrames;
   }
 
   mAudioClock.UpdateWritePosition(servicedFrames);
   return servicedFrames;
 }
 
 void
-nsBufferedAudioStream::StateCallback(cubeb_state aState)
+BufferedAudioStream::StateCallback(cubeb_state aState)
 {
   MonitorAutoLock mon(mMonitor);
   if (aState == CUBEB_STATE_DRAINED) {
     mState = DRAINED;
   } else if (aState == CUBEB_STATE_ERROR) {
     mState = ERRORED;
   }
   mon.NotifyAll();
--- a/content/media/AudioStream.h
+++ b/content/media/AudioStream.h
@@ -5,28 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #if !defined(AudioStream_h_)
 #define AudioStream_h_
 
 #include "nscore.h"
 #include "AudioSampleFormat.h"
 #include "AudioChannelCommon.h"
 #include "soundtouch/SoundTouch.h"
-#include "nsAutoRef.h"
-
-
-template <>
-class nsAutoRefTraits<soundtouch::SoundTouch> : public nsPointerRefTraits<soundtouch::SoundTouch>
-{
-public:
-  static void Release(soundtouch::SoundTouch* resamplerState) {
-    delete resamplerState;
-    resamplerState = nullptr;
-  }
-};
+#include "nsAutoPtr.h"
 
 namespace mozilla {
 
 class AudioStream;
 
 class AudioClock
 {
   public:
@@ -181,14 +170,14 @@ public:
 
 protected:
   // Input rate in Hz (characteristic of the media being played)
   int mInRate;
   // Output rate in Hz (characteristic of the playback rate)
   int mOutRate;
   int mChannels;
   AudioClock mAudioClock;
-  nsAutoRef<soundtouch::SoundTouch> mTimeStretcher;
+  nsAutoPtr<soundtouch::SoundTouch> mTimeStretcher;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/MediaDecoderReader.cpp
+++ b/content/media/MediaDecoderReader.cpp
@@ -75,17 +75,17 @@ IsYV12Format(const VideoData::YCbCrBuffe
     aYPlane.mHeight % 2 == 0 &&
     aYPlane.mWidth / 2 == aCbPlane.mWidth &&
     aYPlane.mHeight / 2 == aCbPlane.mHeight &&
     aCbPlane.mWidth == aCrPlane.mWidth &&
     aCbPlane.mHeight == aCrPlane.mHeight;
 }
 
 bool
-nsVideoInfo::ValidateVideoRegion(const nsIntSize& aFrame,
+VideoInfo::ValidateVideoRegion(const nsIntSize& aFrame,
                                  const nsIntRect& aPicture,
                                  const nsIntSize& aDisplay)
 {
   return
     aFrame.width <= PlanarYCbCrImage::MAX_DIMENSION &&
     aFrame.height <= PlanarYCbCrImage::MAX_DIMENSION &&
     aFrame.width * aFrame.height <= MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
     aFrame.width * aFrame.height != 0 &&
@@ -134,17 +134,17 @@ VideoData::VideoData(int64_t aOffset,
 }
 
 VideoData::~VideoData()
 {
   MOZ_COUNT_DTOR(VideoData);
 }
 
 
-VideoData* VideoData::Create(nsVideoInfo& aInfo,
+VideoData* VideoData::Create(VideoInfo& aInfo,
                              ImageContainer* aContainer,
                              int64_t aOffset,
                              int64_t aTime,
                              int64_t aEndTime,
                              const YCbCrBuffer& aBuffer,
                              bool aKeyframe,
                              int64_t aTimecode,
                              nsIntRect aPicture)
@@ -236,17 +236,17 @@ VideoData* VideoData::Create(nsVideoInfo
   data.mStereoMode = aInfo.mStereoMode;
 
   videoImage->SetDelayedConversion(true);
   videoImage->SetData(data);
   return v.forget();
 }
 
 #ifdef MOZ_WIDGET_GONK
-VideoData* VideoData::Create(nsVideoInfo& aInfo,
+VideoData* VideoData::Create(VideoInfo& aInfo,
                              ImageContainer* aContainer,
                              int64_t aOffset,
                              int64_t aTime,
                              int64_t aEndTime,
                              mozilla::layers::GraphicBufferLocked *aBuffer,
                              bool aKeyframe,
                              int64_t aTimecode,
                              nsIntRect aPicture)
--- a/content/media/MediaDecoderReader.h
+++ b/content/media/MediaDecoderReader.h
@@ -16,19 +16,19 @@
 #include "MediaResource.h"
 #include "nsHTMLMediaElement.h"
 
 namespace mozilla {
 
 class AbstractMediaDecoder;
 
 // Stores info relevant to presenting media frames.
-class nsVideoInfo {
+class VideoInfo {
 public:
-  nsVideoInfo()
+  VideoInfo()
     : mAudioRate(44100),
       mAudioChannels(2),
       mDisplay(0,0),
       mStereoMode(STEREO_MODE_MONO),
       mHasAudio(false),
       mHasVideo(false)
   {}
 
@@ -133,27 +133,27 @@ public:
   };
 
   // Constructs a VideoData object. Makes a copy of YCbCr data in aBuffer.
   // aTimecode is a codec specific number representing the timestamp of
   // the frame of video data. Returns nullptr if an error occurs. This may
   // indicate that memory couldn't be allocated to create the VideoData
   // object, or it may indicate some problem with the input data (e.g.
   // negative stride).
-  static VideoData* Create(nsVideoInfo& aInfo,
+  static VideoData* Create(VideoInfo& aInfo,
                            ImageContainer* aContainer,
                            int64_t aOffset,
                            int64_t aTime,
                            int64_t aEndTime,
                            const YCbCrBuffer &aBuffer,
                            bool aKeyframe,
                            int64_t aTimecode,
                            nsIntRect aPicture);
 
-  static VideoData* Create(nsVideoInfo& aInfo,
+  static VideoData* Create(VideoInfo& aInfo,
                            ImageContainer* aContainer,
                            int64_t aOffset,
                            int64_t aTime,
                            int64_t aEndTime,
                            layers::GraphicBufferLocked *aBuffer,
                            bool aKeyframe,
                            int64_t aTimecode,
                            nsIntRect aPicture);
@@ -381,17 +381,17 @@ public:
 
   virtual bool HasAudio() = 0;
   virtual bool HasVideo() = 0;
 
   // Read header data for all bitstreams in the file. Fills aInfo with
   // the data required to present the media, and optionally fills *aTags
   // with tag metadata from the file.
   // Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags) = 0;
 
   // Stores the presentation time of the first frame we'd be able to play if
   // we started playback at the current position. Returns the first video
   // frame, if we have video.
   virtual VideoData* FindStartTime(int64_t& aOutStartTime);
 
   // Moves the decode head to aTime microseconds. aStartTime and aEndTime
@@ -486,14 +486,14 @@ protected:
   // Pumps the decode until we reach frames required to play at time aTarget
   // (usecs).
   nsresult DecodeToTarget(int64_t aTarget);
 
   // Reference to the owning decoder object.
   AbstractMediaDecoder* mDecoder;
 
   // Stores presentation info required for playback.
-  nsVideoInfo mInfo;
+  VideoInfo mInfo;
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/media/MediaDecoderStateMachine.cpp
+++ b/content/media/MediaDecoderStateMachine.cpp
@@ -1732,17 +1732,17 @@ nsresult MediaDecoderStateMachine::Decod
 {
   NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   NS_ASSERTION(mState == DECODER_STATE_DECODING_METADATA,
                "Only call when in metadata decoding state");
 
   LOG(PR_LOG_DEBUG, ("%p Decoding Media Headers", mDecoder.get()));
   nsresult res;
-  nsVideoInfo info;
+  VideoInfo info;
   MetadataTags* tags;
   {
     ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
     res = mReader->ReadMetadata(&info, &tags);
   }
   mInfo = info;
 
   if (NS_FAILED(res) || (!info.mHasVideo && !info.mHasAudio)) {
--- a/content/media/MediaDecoderStateMachine.h
+++ b/content/media/MediaDecoderStateMachine.h
@@ -779,13 +779,13 @@ private:
 
   // Manager for queuing and dispatching MozAudioAvailable events.  The
   // event manager is accessed from the state machine and audio threads,
   // and takes care of synchronizing access to its internal queue.
   AudioAvailableEventManager mEventManager;
 
   // Stores presentation info required for playback. The decoder monitor
   // must be held when accessing this.
-  nsVideoInfo mInfo;
+  VideoInfo mInfo;
 };
 
 } // namespace mozilla;
 #endif
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -721,17 +721,17 @@ void ChannelMediaResource::CloseChannel(
 
   if (mChannel) {
     if (mSuspendCount > 0) {
       // Resume the channel before we cancel it
       PossiblyResume();
     }
     // The status we use here won't be passed to the decoder, since
     // we've already revoked the listener. It can however be passed
-    // to DocumentViewerImpl::LoadComplete if our channel is the one
+    // to nsDocumentViewer::LoadComplete if our channel is the one
     // that kicked off creation of a video document. We don't want that
     // document load to think there was an error.
     // NS_ERROR_PARSED_DATA_CACHED is the best thing we have for that
     // at the moment.
     mChannel->Cancel(NS_ERROR_PARSED_DATA_CACHED);
     mChannel = nullptr;
   }
 }
--- a/content/media/VideoUtils.h
+++ b/content/media/VideoUtils.h
@@ -121,17 +121,17 @@ static const int64_t USECS_PER_MS = 1000
 // The maximum height and width of the video. Used for
 // sanitizing the memory allocation of the RGB buffer.
 // The maximum resolution we anticipate encountering in the
 // wild is 2160p - 3840x2160 pixels.
 static const int32_t MAX_VIDEO_WIDTH = 4000;
 static const int32_t MAX_VIDEO_HEIGHT = 3000;
 
 // Scales the display rect aDisplay by aspect ratio aAspectRatio.
-// Note that aDisplay must be validated by nsVideoInfo::ValidateVideoRegion()
+// Note that aDisplay must be validated by VideoInfo::ValidateVideoRegion()
 // before being used!
 void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
 
 // The amount of virtual memory reserved for thread stacks.
 #if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \
     !defined(MOZ_ASAN)
 #define MEDIA_THREAD_STACK_SIZE (128 * 1024)
 #else
--- a/content/media/VorbisUtils.h
+++ b/content/media/VorbisUtils.h
@@ -1,27 +1,27 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* 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 VORBISUTILS_H_
-#define VORBISUTILS_H_
-
-#ifdef MOZ_SAMPLE_TYPE_S16
-#include <ogg/os_types.h>
-typedef ogg_int32_t VorbisPCMValue;
-
-#define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767)
-// Convert the output of vorbis_synthesis_pcmout to a AudioDataValue
-#define MOZ_CONVERT_VORBIS_SAMPLE(x) \
- (static_cast<AudioDataValue>(MOZ_CLIP_TO_15((x)>>9)))
-
-#else /* MOZ_SAMPLE_TYPE_FLOAT32 */
-
-typedef float VorbisPCMValue;
-
-#define MOZ_CONVERT_VORBIS_SAMPLE(x) (x)
-
-#endif
-
-#endif /* VORBISUTILS_H_ */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 VORBISUTILS_H_
+#define VORBISUTILS_H_
+
+#ifdef MOZ_SAMPLE_TYPE_S16
+#include <ogg/os_types.h>
+typedef ogg_int32_t VorbisPCMValue;
+
+#define MOZ_CLIP_TO_15(x) ((x)<-32768?-32768:(x)<=32767?(x):32767)
+// Convert the output of vorbis_synthesis_pcmout to a AudioDataValue
+#define MOZ_CONVERT_VORBIS_SAMPLE(x) \
+ (static_cast<AudioDataValue>(MOZ_CLIP_TO_15((x)>>9)))
+
+#else /* MOZ_SAMPLE_TYPE_FLOAT32 */
+
+typedef float VorbisPCMValue;
+
+#define MOZ_CONVERT_VORBIS_SAMPLE(x) (x)
+
+#endif
+
+#endif /* VORBISUTILS_H_ */
--- a/content/media/dash/DASHReader.cpp
+++ b/content/media/dash/DASHReader.cpp
@@ -110,33 +110,33 @@ DASHReader::DecodeVideoFrame(bool &aKeyf
 bool
 DASHReader::DecodeAudioData()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   return (mAudioReader ? mAudioReader->DecodeAudioData() : false);
 }
 
 nsresult
-DASHReader::ReadMetadata(nsVideoInfo* aInfo,
+DASHReader::ReadMetadata(VideoInfo* aInfo,
                            MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   // Wait for MPD to be parsed and child readers created.
   LOG1("Waiting for metadata download.");
   nsresult rv = WaitForMetadata();
   // If we get an abort, return silently; the decoder is shutting down.
   if (NS_ERROR_ABORT == rv) {
     return NS_OK;
   }
   // Verify no other errors before continuing.
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get metadata from child readers.
-  nsVideoInfo audioInfo, videoInfo;
+  VideoInfo audioInfo, videoInfo;
 
   if (mVideoReader) {
     rv = mVideoReader->ReadMetadata(&videoInfo, aTags);
     NS_ENSURE_SUCCESS(rv, rv);
     mInfo.mHasVideo      = videoInfo.mHasVideo;
     mInfo.mDisplay       = videoInfo.mDisplay;
   }
   if (mAudioReader) {
--- a/content/media/dash/DASHReader.h
+++ b/content/media/dash/DASHReader.h
@@ -42,17 +42,17 @@ public:
 
   // Adds a pointer to a audio/video reader for a media |Representation|.
   // Called on the main thread only.
   void AddAudioReader(MediaDecoderReader* aAudioReader);
   void AddVideoReader(MediaDecoderReader* aVideoReader);
 
   // Waits for metadata bytes to be downloaded, then reads and parses them.
   // Called on the decode thread only.
-  nsresult ReadMetadata(nsVideoInfo* aInfo,
+  nsresult ReadMetadata(VideoInfo* aInfo,
                         MetadataTags** aTags);
 
   // Waits for |ReadyToReadMetadata| or |NotifyDecoderShuttingDown|
   // notification, whichever comes first. Ensures no attempt to read metadata
   // during |DASHDecoder|::|Shutdown|. Called on decode thread only.
   nsresult WaitForMetadata() {
     NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
     ReentrantMonitorAutoEnter mon(mReadMetadataMonitor);
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -190,17 +190,17 @@ void GStreamerReader::PlayBinSourceSetup
     gst_app_src_set_stream_type(mSource, GST_APP_STREAM_TYPE_RANDOM_ACCESS);
   } else {
     /* make the demuxer work in push mode so that seeking is kept to a minimum
      */
     gst_app_src_set_stream_type(mSource, GST_APP_STREAM_TYPE_SEEKABLE);
   }
 }
 
-nsresult GStreamerReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult GStreamerReader::ReadMetadata(VideoInfo* aInfo,
                                          MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
   nsresult ret = NS_OK;
 
   /* We do 3 attempts here: decoding audio and video, decoding video only,
    * decoding audio only. This allows us to play streams that have one broken
    * stream but that are otherwise decodeable.
--- a/content/media/gstreamer/GStreamerReader.h
+++ b/content/media/gstreamer/GStreamerReader.h
@@ -23,17 +23,17 @@ public:
   GStreamerReader(AbstractMediaDecoder* aDecoder);
   virtual ~GStreamerReader();
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor);
   virtual nsresult ResetDecode();
   virtual bool DecodeAudioData();
   virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
                                 int64_t aTimeThreshold);
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime,
                         int64_t aStartTime,
                         int64_t aEndTime,
                         int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
 
   virtual bool IsSeekableInBufferedRanges() {
--- a/content/media/ogg/OggCodecState.cpp
+++ b/content/media/ogg/OggCodecState.cpp
@@ -284,17 +284,17 @@ bool TheoraState::Init() {
 
   mPixelAspectRatio = (n == 0 || d == 0) ?
     1.0f : static_cast<float>(n) / static_cast<float>(d);
 
   // Ensure the frame and picture regions aren't larger than our prescribed
   // maximum, or zero sized.
   nsIntSize frame(mInfo.frame_width, mInfo.frame_height);
   nsIntRect picture(mInfo.pic_x, mInfo.pic_y, mInfo.pic_width, mInfo.pic_height);
-  if (!nsVideoInfo::ValidateVideoRegion(frame, picture, frame)) {
+  if (!VideoInfo::ValidateVideoRegion(frame, picture, frame)) {
     return mActive = false;
   }
 
   mCtx = th_decode_alloc(&mInfo, mSetup);
   if (mCtx == NULL) {
     return mActive = false;
   }
 
--- a/content/media/ogg/OggReader.cpp
+++ b/content/media/ogg/OggReader.cpp
@@ -156,17 +156,17 @@ void OggReader::BuildSerialList(nsTArray
     if (mVorbisState) {
       aTracks.AppendElement(mVorbisState->mSerial);
     } else if(mOpusState) {
       aTracks.AppendElement(mOpusState->mSerial);
     }
   }
 }
 
-nsresult OggReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult OggReader::ReadMetadata(VideoInfo* aInfo,
                                    MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   // We read packets until all bitstreams have read all their header packets.
   // We record the offset of the first non-header page so that we know
   // what page to seek to when seeking to the media start.
 
@@ -265,17 +265,17 @@ nsresult OggReader::ReadMetadata(nsVideo
                                       mTheoraState->mInfo.pic_height);
 
     // Apply the aspect ratio to produce the intrinsic display size we report
     // to the element.
     ScaleDisplayByAspectRatio(displaySize, mTheoraState->mPixelAspectRatio);
 
     nsIntSize frameSize(mTheoraState->mInfo.frame_width,
                         mTheoraState->mInfo.frame_height);
-    if (nsVideoInfo::ValidateVideoRegion(frameSize, picture, displaySize)) {
+    if (VideoInfo::ValidateVideoRegion(frameSize, picture, displaySize)) {
       // Video track's frame sizes will not overflow. Activate the video track.
       mInfo.mHasVideo = true;
       mInfo.mDisplay = displaySize;
       mPicture = picture;
 
       VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
       if (container) {
         container->SetCurrentFrame(gfxIntSize(displaySize.width, displaySize.height),
--- a/content/media/ogg/OggReader.h
+++ b/content/media/ogg/OggReader.h
@@ -41,17 +41,17 @@ public:
     return (mVorbisState != 0 && mVorbisState->mActive) ||
            (mOpusState != 0 && mOpusState->mActive);
   }
 
   virtual bool HasVideo() {
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
 
   // We use bisection to seek in buffered range.
   virtual bool IsSeekableInBufferedRanges() {
     return true;
   }
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -37,17 +37,17 @@ MediaOmxReader::~MediaOmxReader()
   ResetDecode();
 }
 
 nsresult MediaOmxReader::Init(MediaDecoderReader* aCloneDonor)
 {
   return NS_OK;
 }
 
-nsresult MediaOmxReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult MediaOmxReader::ReadMetadata(VideoInfo* aInfo,
                                         MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   *aTags = nullptr;
 
   if (!mOmxDecoder) {
     mOmxDecoder = new OmxDecoder(mDecoder->GetResource(), mDecoder);
@@ -66,17 +66,17 @@ nsresult MediaOmxReader::ReadMetadata(ns
     int32_t width, height;
     mOmxDecoder->GetVideoParameters(&width, &height);
     nsIntRect pictureRect(0, 0, width, height);
 
     // Validate the container-reported frame and pictureRect sizes. This ensures
     // that our video frame creation code doesn't overflow.
     nsIntSize displaySize(width, height);
     nsIntSize frameSize(width, height);
-    if (!nsVideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
+    if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
       return NS_ERROR_FAILURE;
     }
 
     // Video track's frame sizes will not overflow. Activate the video track.
     mHasVideo = mInfo.mHasVideo = true;
     mInfo.mDisplay = displaySize;
     mPicture = pictureRect;
     mInitialFrame = frameSize;
--- a/content/media/omx/MediaOmxReader.h
+++ b/content/media/omx/MediaOmxReader.h
@@ -45,17 +45,17 @@ public:
     return mHasAudio;
   }
 
   virtual bool HasVideo()
   {
     return mHasVideo;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
   virtual bool IsSeekableInBufferedRanges() {
     return true;
   }
 
 };
--- a/content/media/plugins/MediaPluginReader.cpp
+++ b/content/media/plugins/MediaPluginReader.cpp
@@ -33,17 +33,17 @@ MediaPluginReader::~MediaPluginReader()
   ResetDecode();
 }
 
 nsresult MediaPluginReader::Init(MediaDecoderReader* aCloneDonor)
 {
   return NS_OK;
 }
 
-nsresult MediaPluginReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult MediaPluginReader::ReadMetadata(VideoInfo* aInfo,
                                            MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   if (!mPlugin) {
     mPlugin = GetMediaPluginHost()->CreateDecoder(mDecoder->GetResource(), mType);
     if (!mPlugin) {
       return NS_ERROR_FAILURE;
@@ -62,17 +62,17 @@ nsresult MediaPluginReader::ReadMetadata
     int32_t width, height;
     mPlugin->GetVideoParameters(mPlugin, &width, &height);
     nsIntRect pictureRect(0, 0, width, height);
 
     // Validate the container-reported frame and pictureRect sizes. This ensures
     // that our video frame creation code doesn't overflow.
     nsIntSize displaySize(width, height);
     nsIntSize frameSize(width, height);
-    if (!nsVideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
+    if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
       return NS_ERROR_FAILURE;
     }
 
     // Video track's frame sizes will not overflow. Activate the video track.
     mHasVideo = mInfo.mHasVideo = true;
     mInfo.mDisplay = displaySize;
     mPicture = pictureRect;
     mInitialFrame = frameSize;
--- a/content/media/plugins/MediaPluginReader.h
+++ b/content/media/plugins/MediaPluginReader.h
@@ -45,17 +45,17 @@ public:
     return mHasAudio;
   }
 
   virtual bool HasVideo()
   {
     return mHasVideo;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
   virtual bool IsSeekableInBufferedRanges() {
     return true;
   }
 
 };
--- a/content/media/raw/RawReader.cpp
+++ b/content/media/raw/RawReader.cpp
@@ -29,17 +29,17 @@ nsresult RawReader::Init(MediaDecoderRea
 }
 
 nsresult RawReader::ResetDecode()
 {
   mCurrentFrame = 0;
   return MediaDecoderReader::ResetDecode();
 }
 
-nsresult RawReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult RawReader::ReadMetadata(VideoInfo* aInfo,
                                    MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(),
                "Should be on decode thread.");
 
   MediaResource* resource = mDecoder->GetResource();
   NS_ASSERTION(resource, "Decoder has no media resource");
 
@@ -64,17 +64,17 @@ nsresult RawReader::ReadMetadata(nsVideo
 
   // Determine and verify frame display size.
   float pixelAspectRatio = static_cast<float>(mMetadata.aspectNumerator) / 
                             mMetadata.aspectDenominator;
   nsIntSize display(mMetadata.frameWidth, mMetadata.frameHeight);
   ScaleDisplayByAspectRatio(display, pixelAspectRatio);
   mPicture = nsIntRect(0, 0, mMetadata.frameWidth, mMetadata.frameHeight);
   nsIntSize frameSize(mMetadata.frameWidth, mMetadata.frameHeight);
-  if (!nsVideoInfo::ValidateVideoRegion(frameSize, mPicture, display)) {
+  if (!VideoInfo::ValidateVideoRegion(frameSize, mPicture, display)) {
     // Video track's frame sizes will overflow. Fail.
     return NS_ERROR_FAILURE;
   }
 
   mInfo.mHasVideo = true;
   mInfo.mHasAudio = false;
   mInfo.mDisplay = display;
 
--- a/content/media/raw/RawReader.h
+++ b/content/media/raw/RawReader.h
@@ -29,17 +29,17 @@ public:
     return false;
   }
 
   virtual bool HasVideo()
   {
     return true;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
 
   // By seeking in the media resource, it is possible to seek.
   bool IsSeekableInBufferedRanges() {
     return true;
   }
--- a/content/media/test/test_defaultMuted.html
+++ b/content/media/test/test_defaultMuted.html
@@ -1,54 +1,54 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Media test: defaultMuted</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-  <script type="text/javascript" src="manifest.js"></script>
-  <script type="text/javascript" src="../../html/content/test/reflect.js"></script>
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=706731">Mozilla Bug 706731</a>
-  <p id="display"></p>
-  <div id="content" style="display: none"></div>
-  <video id='v1'></video><audio id='a1'></audio>
-  <video id='v2' muted></video><audio id='a2' muted></audio>
-<pre id="test">
-<script class="testbody" type="text/javascript">
-    reflectBoolean({
-      element: document.createElement("video"),
-      attribute: { content: "muted", idl: "defaultMuted" },
-    });
-
-    reflectBoolean({
-      element: document.createElement("audio"),
-      attribute: { content: "muted", idl: "defaultMuted" },
-    });
-
-    var v1 = document.getElementById('v1');
-    var a1 = document.getElementById('a1');
-    var v2 = document.getElementById('v2');
-    var a2 = document.getElementById('a2');
-
-    // Check that muted state correspond to the default value.
-    is(v1.muted, false, "v1.muted should be false by default");
-    is(a1.muted, false, "a1.muted should be false by default");
-    is(v2.muted, true, "v2.muted should be true by default");
-    is(a2.muted, true, "a2.muted should be true by default");
-
-    // Changing defaultMuted value should not change current muted state.
-    v1.defaultMuted = true;
-    a1.defaultMuted = true;
-    v2.defaultMuted = false;
-    a2.defaultMuted = false;
-
-    is(v1.muted, false, "v1.muted should not have changed");
-    is(a1.muted, false, "a1.muted should not have changed");
-    is(v2.muted, true, "v2.muted should not have changed");
-    is(a2.muted, true, "a2.muted should not have changed");
-
-    mediaTestCleanup();
-</script>
-</pre>
-</body>
-</html>
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Media test: defaultMuted</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+  <script type="text/javascript" src="manifest.js"></script>
+  <script type="text/javascript" src="../../html/content/test/reflect.js"></script>
+</head>
+<body>
+  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=706731">Mozilla Bug 706731</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <video id='v1'></video><audio id='a1'></audio>
+  <video id='v2' muted></video><audio id='a2' muted></audio>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+    reflectBoolean({
+      element: document.createElement("video"),
+      attribute: { content: "muted", idl: "defaultMuted" },
+    });
+
+    reflectBoolean({
+      element: document.createElement("audio"),
+      attribute: { content: "muted", idl: "defaultMuted" },
+    });
+
+    var v1 = document.getElementById('v1');
+    var a1 = document.getElementById('a1');
+    var v2 = document.getElementById('v2');
+    var a2 = document.getElementById('a2');
+
+    // Check that muted state correspond to the default value.
+    is(v1.muted, false, "v1.muted should be false by default");
+    is(a1.muted, false, "a1.muted should be false by default");
+    is(v2.muted, true, "v2.muted should be true by default");
+    is(a2.muted, true, "a2.muted should be true by default");
+
+    // Changing defaultMuted value should not change current muted state.
+    v1.defaultMuted = true;
+    a1.defaultMuted = true;
+    v2.defaultMuted = false;
+    a2.defaultMuted = false;
+
+    is(v1.muted, false, "v1.muted should not have changed");
+    is(a1.muted, false, "a1.muted should not have changed");
+    is(v2.muted, true, "v2.muted should not have changed");
+    is(a2.muted, true, "a2.muted should not have changed");
+
+    mediaTestCleanup();
+</script>
+</pre>
+</body>
+</html>
--- a/content/media/wave/WaveReader.cpp
+++ b/content/media/wave/WaveReader.cpp
@@ -115,17 +115,17 @@ WaveReader::~WaveReader()
   MOZ_COUNT_DTOR(WaveReader);
 }
 
 nsresult WaveReader::Init(MediaDecoderReader* aCloneDonor)
 {
   return NS_OK;
 }
 
-nsresult WaveReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult WaveReader::ReadMetadata(VideoInfo* aInfo,
                                     MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   bool loaded = LoadRIFFChunk() && LoadFormatChunk() && FindDataOffset();
   if (!loaded) {
     return NS_ERROR_FAILURE;
   }
--- a/content/media/wave/WaveReader.h
+++ b/content/media/wave/WaveReader.h
@@ -28,17 +28,17 @@ public:
     return true;
   }
 
   virtual bool HasVideo()
   {
     return false;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
 
   // To seek in a buffered range, we just have to seek the stream.
   virtual bool IsSeekableInBufferedRanges() {
     return true;
   }
--- a/content/media/webm/WebMReader.cpp
+++ b/content/media/webm/WebMReader.cpp
@@ -177,17 +177,17 @@ nsresult WebMReader::ResetDecode()
 void WebMReader::Cleanup()
 {
   if (mContext) {
     nestegg_destroy(mContext);
     mContext = nullptr;
   }
 }
 
-nsresult WebMReader::ReadMetadata(nsVideoInfo* aInfo,
+nsresult WebMReader::ReadMetadata(VideoInfo* aInfo,
                                     MetadataTags** aTags)
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
 
   LOG(PR_LOG_DEBUG, ("Reader [%p] for Decoder [%p]: Reading WebM Metadata: "
                      "init bytes [%d - %d] cues bytes [%d - %d]",
                      this, mDecoder,
                      mInitByteRange.mStart, mInitByteRange.mEnd,
@@ -252,17 +252,17 @@ nsresult WebMReader::ReadMetadata(nsVide
         pictureRect.width = params.width;
         pictureRect.height = params.height;
       }
 
       // Validate the container-reported frame and pictureRect sizes. This ensures
       // that our video frame creation code doesn't overflow.
       nsIntSize displaySize(params.display_width, params.display_height);
       nsIntSize frameSize(params.width, params.height);
-      if (!nsVideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
+      if (!VideoInfo::ValidateVideoRegion(frameSize, pictureRect, displaySize)) {
         // Video track's frame sizes will overflow. Ignore the video track.
         continue;
       }
 
       mVideoTrack = track;
       mHasVideo = true;
       mInfo.mHasVideo = true;
 
--- a/content/media/webm/WebMReader.h
+++ b/content/media/webm/WebMReader.h
@@ -125,17 +125,17 @@ public:
     return mHasVideo;
   }
 
   // Bug 575140, cannot seek in webm if no cue is present.
   bool IsSeekableInBufferedRanges() {
     return false;
   }
 
-  virtual nsresult ReadMetadata(nsVideoInfo* aInfo,
+  virtual nsresult ReadMetadata(VideoInfo* aInfo,
                                 MetadataTags** aTags);
   virtual nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime, int64_t aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, int64_t aStartTime);
   virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset);
 
   // Sets byte range for initialization (EBML); used by DASH.
   void SetInitByteRange(MediaByteRange &aByteRange) {
     mInitByteRange = aByteRange;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -109,17 +109,16 @@
 #include "nsIFileURL.h"
 #include "nsIHistoryEntry.h"
 #include "nsISHistoryListener.h"
 #include "nsIWindowWatcher.h"
 #include "nsIPromptFactory.h"
 #include "nsIObserver.h"
 #include "nsINestedURI.h"
 #include "nsITransportSecurityInfo.h"
-#include "nsISSLSocketControl.h"
 #include "nsINSSErrorsService.h"
 #include "nsIApplicationCache.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
 #include "nsIPermissionManager.h"
 #include "nsStreamUtils.h"
 #include "nsIController.h"
 #include "nsPICommandUpdater.h"
@@ -4170,21 +4169,18 @@ nsDocShell::DisplayLoadError(nsresult aE
             if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
                 error.AssignLiteral("nssBadCert");
 
                 // if this is a Strict-Transport-Security host and the cert
                 // is bad, don't allow overrides (STS Spec section 7.3).
                 nsCOMPtr<nsIStrictTransportSecurityService> stss =
                           do_GetService(NS_STSSERVICE_CONTRACTID, &rv);
                 NS_ENSURE_SUCCESS(rv, rv);
-                uint32_t flags = 0;
-                nsCOMPtr<nsISSLSocketControl> socketControl = do_QueryInterface(tsi);
-                if (socketControl) {
-                    socketControl->GetProviderFlags(&flags);
-                }
+                uint32_t flags =
+                  mInPrivateBrowsing ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
                 
                 bool isStsHost = false;
                 rv = stss->IsStsURI(aURI, flags, &isStsHost);
                 NS_ENSURE_SUCCESS(rv, rv);
 
                 uint32_t bucketId;
                 if (isStsHost) {
                   cssClass.AssignLiteral("badStsCert");
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -189,16 +189,30 @@ DOMInterfaces = {
 {
     'resultNotAddRefed': [ 'threshold', 'knee', 'ratio',
                            'reduction', 'attack', 'release' ],
     'binaryNames': {
         'release': 'getRelease'
     }
 }],
 
+'Element': {
+    # 'prefable' is True because some nodes are not on new bindings yet, so the
+    # wrapping code for Element return values needs to fall back to XPConnect as
+    # needed.
+    'prefable': True,
+    'hasXPConnectImpls': True,
+    'hasInstanceInterface': 'nsIDOMElement',
+    'resultNotAddRefed': [
+        'classList', 'attributes', 'children', 'firstElementChild',
+        'lastElementChild', 'previousElementSibling', 'nextElementSibling',
+        'getAttributeNode', 'getAttributeNodeNS'
+    ]
+},
+
 'Event': [
 {
     'workers': True,
 }],
 
 'EventListener': [
 {
     'workers': True,
@@ -719,17 +733,16 @@ addExternalIface('Attr')
 addExternalIface('CanvasGradient', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('CanvasPattern', headerFile='nsIDOMCanvasRenderingContext2D.h')
 addExternalIface('ClientRect')
 addExternalIface('CSSRule')
 addExternalIface('CSSValue')
 addExternalIface('DocumentType', nativeType='nsIDOMDocumentType')
 addExternalIface('DOMStringList', nativeType='nsDOMStringList',
                  headerFile='nsDOMLists.h')
-addExternalIface('Element', nativeType='mozilla::dom::Element')
 addExternalIface('File')
 addExternalIface('HitRegionOptions', nativeType='nsISupports')
 addExternalIface('HTMLElement')
 addExternalIface('MediaStream')
 addExternalIface('NamedNodeMap')
 addExternalIface('PaintRequest')
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4389,41 +4389,43 @@ class CGMemberJITInfo(CGThing):
     """
     def __init__(self, descriptor, member):
         self.member = member
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
-    def defineJitInfo(self, infoName, opName, infallible):
+    def defineJitInfo(self, infoName, opName, infallible, constant):
         protoID = "prototypes::id::%s" % self.descriptor.name
         depth = "PrototypeTraits<%s>::Depth" % protoID
-        failstr = "true" if infallible else "false"
+        failstr = toStringBool(infallible)
+        conststr = toStringBool(constant)
         return ("\n"
                 "const JSJitInfo %s = {\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  %s,\n"
                 "  %s,  /* isInfallible. False in setters. */\n"
-                "  false  /* isConstant. Only relevant for getters. */\n"
-                "};\n" % (infoName, opName, protoID, depth, failstr))
+                "  %s  /* isConstant. Only relevant for getters. */\n"
+                "};\n" % (infoName, opName, protoID, depth, failstr, conststr))
 
     def define(self):
         if self.member.isAttr():
             getterinfo = ("%s_getterinfo" % self.member.identifier.name)
             getter = ("(JSJitPropertyOp)get_%s" % self.member.identifier.name)
             getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
             getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
-            result = self.defineJitInfo(getterinfo, getter, getterinfal)
+            getterconst = self.member.getExtendedAttribute("Constant")
+            result = self.defineJitInfo(getterinfo, getter, getterinfal, getterconst)
             if not self.member.readonly or self.member.getExtendedAttribute("PutForwards") is not None:
                 setterinfo = ("%s_setterinfo" % self.member.identifier.name)
                 setter = ("(JSJitPropertyOp)set_%s" % self.member.identifier.name)
                 # Setters are always fallible, since they have to do a typed unwrap.
-                result += self.defineJitInfo(setterinfo, setter, False)
+                result += self.defineJitInfo(setterinfo, setter, False, False)
             return result
         if self.member.isMethod():
             methodinfo = ("%s_methodinfo" % self.member.identifier.name)
             name = CppKeywords.checkMethodName(self.member.identifier.name)
             # Actually a JSJitMethodOp, but JSJitPropertyOp by struct definition.
             method = ("(JSJitPropertyOp)%s" % name)
 
             # Methods are infallible if they are infallible, have no arguments
@@ -4434,17 +4436,17 @@ class CGMemberJITInfo(CGThing):
             if len(sigs) == 1:
                 # Don't handle overloading. If there's more than one signature,
                 # one of them must take arguments.
                 sig = sigs[0]
                 if len(sig[1]) == 0 and infallibleForMember(self.member, sig[0], self.descriptor):
                     # No arguments and infallible return boxing
                     methodInfal = True
 
-            result = self.defineJitInfo(methodinfo, method, methodInfal)
+            result = self.defineJitInfo(methodinfo, method, methodInfal, False)
             return result
         raise TypeError("Illegal member type to CGPropertyJITInfo")
 
 def getEnumValueName(value):
     # Some enum values can be empty strings.  Others might have weird
     # characters in them.  Deal with the former by returning "_empty",
     # deal with possible name collisions from that by throwing if the
     # enum value is actually "_empty", and throw on any value
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2138,16 +2138,19 @@ class IDLAttribute(IDLInterfaceMember):
                 raise WebIDLError("[LenientThis] is only allowed on non-static "
                                   "attributes", [attr.location, self.location])
             self.lenientThis = True
         elif identifier == "Unforgeable":
             if not self.readonly:
                 raise WebIDLError("[Unforgeable] is only allowed on readonly "
                                   "attributes", [attr.location, self.location])
             self._unforgeable = True
+        elif identifier == "Constant" and not self.readonly:
+            raise WebIDLError("[Constant] only allowed on readonly attributes",
+                              [attr.location, self.location])
         elif identifier == "PutForwards":
             if not self.readonly:
                 raise WebIDLError("[PutForwards] is only allowed on readonly "
                                   "attributes", [attr.location, self.location])
             if self.isStatic():
                 raise WebIDLError("[PutForwards] is only allowed on non-static "
                                   "attributes", [attr.location, self.location])
             if self.getExtendedAttribute("Replaceable") is not None:
@@ -2636,16 +2639,20 @@ class IDLMethod(IDLInterfaceMember, IDLS
         elif identifier == "SetterThrows":
             raise WebIDLError("Methods must not be flagged as "
                               "[SetterThrows]",
                               [attr.location, self.location])
         elif identifier == "Unforgeable":
             raise WebIDLError("Methods must not be flagged as "
                               "[Unforgeable]",
                               [attr.location, self.location])
+        elif identifier == "Constant":
+            raise WebIDLError("Methods must not be flagged as "
+                              "[Constant]",
+                              [attr.location, self.location]);
         elif identifier == "PutForwards":
             raise WebIDLError("Only attributes support [PutForwards]",
                               [attr.location, self.location])
         elif identifier == "LenientFloat":
             # This is called before we've done overload resolution
             assert len(self.signatures()) == 1
             sig = self.signatures()[0]
             if not sig[0].isVoid():
--- a/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
+++ b/dom/imptests/failures/webapps/DOMCore/tests/approved/test_interfaces.html.json
@@ -149,44 +149,25 @@
   "DocumentType interface: attribute publicId": true,
   "DocumentType interface: attribute systemId": true,
   "DocumentType interface: operation remove()": true,
   "Stringification of document.doctype": "debug",
   "DocumentType interface: document.doctype must inherit property \"remove\" with the proper type (3)": true,
   "EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError": true,
   "EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on document.doctype with too few arguments must throw TypeError": true,
   "EventTarget interface: calling dispatchEvent(Event) on document.doctype with too few arguments must throw TypeError": true,
-  "Element interface: existence and properties of interface object": true,
-  "Element interface: existence and properties of interface prototype object": true,
-  "Element interface: existence and properties of interface prototype object's \"constructor\" property": true,
-  "Element interface: attribute tagName": true,
-  "Element interface: attribute id": true,
+  "Element interface: attribute namespaceURI": true,
+  "Element interface: attribute prefix": true,
+  "Element interface: attribute localName": true,
   "Element interface: attribute className": true,
-  "Element interface: attribute classList": true,
-  "Element interface: attribute children": true,
-  "Element interface: attribute firstElementChild": true,
-  "Element interface: attribute lastElementChild": true,
-  "Element interface: attribute previousElementSibling": true,
-  "Element interface: attribute nextElementSibling": true,
-  "Element interface: attribute childElementCount": true,
+  "Element interface: attribute attributes": true,
   "Element interface: operation remove()": true,
+  "Element must be primary interface of element": true,
   "Stringification of element": "debug",
-  "Element interface: element must inherit property \"id\" with the proper type (4)": true,
   "Element interface: element must inherit property \"className\" with the proper type (5)": true,
-  "Element interface: calling getAttribute(DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling getAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling setAttribute(DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling setAttributeNS(DOMString,DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling removeAttribute(DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling removeAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling hasAttribute(DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling hasAttributeNS(DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling getElementsByTagName(DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling getElementsByTagNameNS(DOMString,DOMString) on element with too few arguments must throw TypeError": true,
-  "Element interface: calling getElementsByClassName(DOMString) on element with too few arguments must throw TypeError": true,
   "Element interface: element must inherit property \"remove\" with the proper type (25)": true,
   "EventTarget interface: calling addEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError": true,
   "EventTarget interface: calling removeEventListener(DOMString,EventListener,boolean) on element with too few arguments must throw TypeError": true,
   "EventTarget interface: calling dispatchEvent(Event) on element with too few arguments must throw TypeError": true,
   "Attr interface: existence and properties of interface object": true,
   "Attr interface: existence and properties of interface prototype object": true,
   "Attr interface: existence and properties of interface prototype object's \"constructor\" property": true,
   "Attr interface: attribute name": true,
--- a/dom/mms/interfaces/nsIWapPushApplication.idl
+++ b/dom/mms/interfaces/nsIWapPushApplication.idl
@@ -17,15 +17,14 @@ interface nsIWapPushApplication : nsISup
    *        An array containing raw PDU data.
    * @param aLength
    *        Length of aData.
    * @param aOffset
    *        Start offset of aData containing message body of the Push PDU.
    * @param options
    *        An object containing various attributes from lower transport layer.
    */
-  [implicit_jscontext]
   void receiveWapPush([array, size_is(aLength)] in octet aData,
                       in unsigned long                   aLength,
                       in unsigned long                   aOffset,
                       in jsval                           aOptions);
 };
 
--- a/dom/mms/src/ril/MmsService.js
+++ b/dom/mms/src/ril/MmsService.js
@@ -52,16 +52,26 @@ XPCOMUtils.defineLazyGetter(this, "MMS",
 });
 
 /**
  * MmsService
  */
 function MmsService() {
   Services.obs.addObserver(this, kXpcomShutdownObserverTopic, false);
   Services.obs.addObserver(this, kNetworkInterfaceStateChangedTopic, false);
+  try {
+    this.urlUAProf = Services.prefs.getCharPref('wap.UAProf.url');
+  } catch (e) {
+    this.urlUAProf = "";
+  }
+  try {
+    this.tagnameUAProf = Services.prefs.getCharPref('wap.UAProf.tagname');
+  } catch (e) {
+    this.tagnameUAProf = "x-wap-profile";
+  }
 }
 MmsService.prototype = {
 
   classID:   RIL_MMSSERVICE_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMmsService,
                                          Ci.nsIWapPushApplication,
                                          Ci.nsIObserver,
                                          Ci.nsIProtocolProxyFilter]),
@@ -73,16 +83,20 @@ MmsService.prototype = {
   confSendDeliveryReport: CONFIG_SEND_REPORT_DEFAULT_YES,
 
   proxyInfo: null,
   MMSC: null,
 
   /** MMS proxy filter reference count. */
   proxyFilterRefCount: 0,
 
+  // WebMMS
+  urlUAProf: null,
+  tagnameUAProf: null,
+
   /**
    * Calculate Whether or not should we enable X-Mms-Report-Allowed.
    *
    * @param config
    *        Current config value.
    * @param wish
    *        Sender wish. Could be undefined, false, or true.
    */
@@ -154,16 +168,20 @@ MmsService.prototype = {
       xhr.responseType = "arraybuffer";
       if (istream) {
         xhr.setRequestHeader("Content-Type", "application/vnd.wap.mms-message");
         xhr.setRequestHeader("Content-Length", istream.available());
       } else {
         xhr.setRequestHeader("Content-Length", 0);
       }
 
+      if(this.urlUAProf !== "") {
+        xhr.setRequestHeader(this.tagnameUAProf, this.urlUAProf);
+      }
+
       // Setup event listeners
       xhr.onerror = function () {
         debug("xhr error, response headers: " + xhr.getAllResponseHeaders());
         releaseProxyFilterAndCallback(xhr.status, null);
       };
       xhr.onreadystatechange = function () {
         if (xhr.readyState != Ci.nsIXMLHttpRequest.DONE) {
           return;
--- a/dom/sms/tests/marionette/manifest.ini
+++ b/dom/sms/tests/marionette/manifest.ini
@@ -6,16 +6,17 @@ qemu = true
 ;[test_between_emulators.py]
 [test_incoming.js]
 [test_outgoing.js]
 [test_message_classes.js]
 [test_incoming_delete.js]
 [test_outgoing_delete.js]
 [test_getmessage.js]
 [test_getmessage_notfound.js]
+[test_incoming_multipart.js]
 [test_getmessages.js]
 [test_filter_date.js]
 [test_filter_date_notfound.js]
 [test_filter_number_single.js]
 [test_filter_number_multiple.js]
 [test_filter_received.js]
 [test_filter_sent.js]
 [test_filter_read.js]
new file mode 100644
--- /dev/null
+++ b/dom/sms/tests/marionette/test_incoming_multipart.js
@@ -0,0 +1,106 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 10000;
+
+SpecialPowers.setBoolPref("dom.sms.enabled", true);
+SpecialPowers.addPermission("sms", true, document);
+
+let sms = window.navigator.mozSms;
+
+function verifyInitialState() {
+  log("Verifying initial state.");
+  ok(sms, "mozSms");
+  simulateIncomingSms();  
+}
+
+function simulateIncomingSms() {
+  let fromNumber = "5551234567";
+  let msgText = "";
+
+  log("Simulating incoming SMS.");
+
+  // Have message text > max SMS size (160 char) so will be a multi-part SMS
+  for (var x = 1; x <= 24; x++) {
+    msgText += 'FirefoxOS ';
+  }
+
+  sms.onreceived = function onreceived(event) {
+    log("Received 'onreceived' smsmanager event.");
+    let incomingSms = event.message;
+    ok(incomingSms, "incoming sms");
+    ok(incomingSms.id, "sms id");
+    log("Received SMS (id: " + incomingSms.id + ").");
+    is(incomingSms.body, msgText, "msg body");
+    is(incomingSms.delivery, "received", "delivery");
+    is(incomingSms.read, false, "read");
+    is(incomingSms.receiver, null, "receiver");
+    is(incomingSms.sender, fromNumber, "sender");
+    ok(incomingSms.timestamp instanceof Date, "timestamp is istanceof date");
+
+    verifySmsExists(incomingSms);
+  };
+  runEmulatorCmd("sms send " + fromNumber + " " + msgText, function(result) {
+    is(result[0], "OK", "emulator output");
+  });
+}
+
+function verifySmsExists(incomingSms) {
+  log("Getting SMS (id: " + incomingSms.id + ").");
+  let requestRet = sms.getMessage(incomingSms.id);
+  ok(requestRet, "smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    ok(event.target.result, "smsrequest event.target.result");
+    let foundSms = event.target.result;
+    is(foundSms.id, incomingSms.id, "found SMS id matches");
+    is(foundSms.body, incomingSms.body, "found SMS msg text matches");
+    log("Got SMS (id: " + foundSms.id + ") as expected.");
+    deleteSms(incomingSms);
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    is(event.target.error.name, "NotFoundError", "error returned");
+    log("Could not get SMS (id: " + incomingSms.id + ") but should have.");
+    ok(false,"SMS was not found");
+    cleanUp();
+  };
+}
+
+function deleteSms(smsMsgObj){
+  log("Deleting SMS (id: " + smsMsgObj.id + ") using smsmsg obj parameter.");
+  let requestRet = sms.delete(smsMsgObj);
+  ok(requestRet,"smsrequest obj returned");
+
+  requestRet.onsuccess = function(event) {
+    log("Received 'onsuccess' smsrequest event.");
+    if(event.target.result){
+      cleanUp();
+    } else {
+      log("smsrequest returned false for sms.delete");
+      ok(false,"SMS delete failed");
+      cleanUp();
+    }
+  };
+
+  requestRet.onerror = function(event) {
+    log("Received 'onerror' smsrequest event.");
+    ok(event.target.error, "domerror obj");
+    ok(false, "sms.delete request returned unexpected error: "
+        + event.target.error.name );
+    cleanUp();
+  };
+}
+
+function cleanUp() {
+  sms.onreceived = null;
+  SpecialPowers.removePermission("sms", document);
+  SpecialPowers.clearUserPref("dom.sms.enabled");
+  finish();
+}
+
+// Start the test
+verifyInitialState();
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -27,17 +27,17 @@ interface Element : Node {
 */
   readonly attribute DOMString tagName;
 
            attribute DOMString id;
 /*
   FIXME Bug 810677 Move className from HTMLElement to Element
            attribute DOMString className;
 */
-  readonly attribute DOMTokenList classList;
+  readonly attribute DOMTokenList? classList;
 
   //readonly attribute Attr[] attributes;
   DOMString? getAttribute(DOMString name);
   DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
   [Throws]
   void setAttribute(DOMString name, DOMString value);
   [Throws]
   void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
@@ -69,16 +69,23 @@ interface Element : Node {
   void before((Node or DOMString)... nodes);
   void after((Node or DOMString)... nodes);
   void replace((Node or DOMString)... nodes);
   void remove();
 */
 
   // Mozilla specific stuff
 
+  [SetterThrows,LenientThis]
+           attribute EventHandler onmouseenter;
+  [SetterThrows,LenientThis]
+           attribute EventHandler onmouseleave;
+  [SetterThrows]
+           attribute EventHandler onwheel;
+
   // Selectors API
   /**
    * Returns whether this element would be selected by the given selector
    * string.
    *
    * See <http://dev.w3.org/2006/webapi/selectors-api2/#matchesselector>
    */
   [Throws]
@@ -120,17 +127,17 @@ interface Element : Node {
 
   // Obsolete methods.
   Attr getAttributeNode(DOMString name);
   [Throws]
   Attr setAttributeNode(Attr newAttr);
   [Throws]
   Attr removeAttributeNode(Attr oldAttr);
   [Throws]
-  Attr getAttributeNodeNS(DOMString namespaceURI, DOMString localName);
+  Attr getAttributeNodeNS(DOMString? namespaceURI, DOMString localName);
   [Throws]
   Attr setAttributeNodeNS(Attr newAttr);
 /*
 };
 
 // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface
 partial interface Element {
 */
--- a/dom/webidl/HTMLElement.webidl
+++ b/dom/webidl/HTMLElement.webidl
@@ -196,23 +196,16 @@ interface HTMLElement : Element {
            attribute EventHandler onmozpointerlockchange;
   [SetterThrows]
            attribute EventHandler onmozpointerlockerror;
 
   // Mozilla specific stuff
   // FIXME Bug 810677 Move className from HTMLElement to Element
            attribute DOMString className;
 
-  [SetterThrows,LenientThis]
-           attribute EventHandler onmouseenter;
-  [SetterThrows,LenientThis]
-           attribute EventHandler onmouseleave;
-  [SetterThrows]
-           attribute EventHandler onwheel;
-
   [SetterThrows,Pref="dom.w3c_touch_events.expose"]
            attribute EventHandler ontouchstart;
   [SetterThrows,Pref="dom.w3c_touch_events.expose"]
            attribute EventHandler ontouchend;
   [SetterThrows,Pref="dom.w3c_touch_events.expose"]
            attribute EventHandler ontouchmove;
   [SetterThrows,Pref="dom.w3c_touch_events.expose"]
            attribute EventHandler ontouchenter;
--- a/dom/webidl/ImageData.webidl
+++ b/dom/webidl/ImageData.webidl
@@ -8,10 +8,10 @@
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera Software ASA.
  * You are granted a license to use, reproduce and create derivative works of this document.
  */
 
 interface ImageData {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;
- readonly attribute Uint8ClampedArray data;
+ [Constant] readonly attribute Uint8ClampedArray data;
 };
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -23,16 +23,17 @@ webidl_files = \
   ClientRectList.webidl \
   CSSStyleDeclaration.webidl \
   DelayNode.webidl \
   DOMImplementation.webidl \
   DOMTokenList.webidl \
   DOMSettableTokenList.webidl \
   DOMStringMap.webidl \
   DynamicsCompressorNode.webidl \
+  Element.webidl \
   EventHandler.webidl \
   EventListener.webidl \
   EventTarget.webidl \
   FileList.webidl \
   FileReaderSync.webidl \
   Function.webidl \
   GainNode.webidl \
   HTMLCollection.webidl \
--- a/gfx/2d/Blur.cpp
+++ b/gfx/2d/Blur.cpp
@@ -492,39 +492,41 @@ AlphaBoxBlur::Blur()
 #endif
 
     if (cIsBigEndian || (integralImageSize.width * integralImageSize.height) > (1 << 24)) {
       // Fallback to old blurring code when the surface is so large it may
       // overflow our integral image!
 
       // No need to use CheckedInt here - we have validated it in the constructor.
       size_t szB = stride * size.height;
-      unsigned char* tmpData = new uint8_t[szB];
-
+      uint8_t* tmpData = new uint8_t[szB];
       memset(tmpData, 0, szB);
 
+      uint8_t* a = mData;
+      uint8_t* b = tmpData;
       if (mBlurRadius.width > 0) {
-        BoxBlurHorizontal(mData, tmpData, horizontalLobes[0][0], horizontalLobes[0][1], stride, GetSize().height, mSkipRect);
-        BoxBlurHorizontal(tmpData, mData, horizontalLobes[1][0], horizontalLobes[1][1], stride, GetSize().height, mSkipRect);
-        BoxBlurHorizontal(mData, tmpData, horizontalLobes[2][0], horizontalLobes[2][1], stride, GetSize().height, mSkipRect);
+        BoxBlurHorizontal(a, b, horizontalLobes[0][0], horizontalLobes[0][1], stride, GetSize().height, mSkipRect);
+        BoxBlurHorizontal(b, a, horizontalLobes[1][0], horizontalLobes[1][1], stride, GetSize().height, mSkipRect);
+        BoxBlurHorizontal(a, b, horizontalLobes[2][0], horizontalLobes[2][1], stride, GetSize().height, mSkipRect);
       } else {
-        uint8_t *tmp = mData;
-        mData = tmpData;
-        tmpData = tmp;
+        a = tmpData;
+        b = mData;
       }
+      // The result is in 'b' here.
       if (mBlurRadius.height > 0) {
-        BoxBlurVertical(tmpData, mData, verticalLobes[0][0], verticalLobes[0][1], stride, GetSize().height, mSkipRect);
-        BoxBlurVertical(mData, tmpData, verticalLobes[1][0], verticalLobes[1][1], stride, GetSize().height, mSkipRect);
-        BoxBlurVertical(tmpData, mData, verticalLobes[2][0], verticalLobes[2][1], stride, GetSize().height, mSkipRect);
+        BoxBlurVertical(b, a, verticalLobes[0][0], verticalLobes[0][1], stride, GetSize().height, mSkipRect);
+        BoxBlurVertical(a, b, verticalLobes[1][0], verticalLobes[1][1], stride, GetSize().height, mSkipRect);
+        BoxBlurVertical(b, a, verticalLobes[2][0], verticalLobes[2][1], stride, GetSize().height, mSkipRect);
       } else {
-        uint8_t *tmp = mData;
-        mData = tmpData;
-        tmpData = tmp;
+        a = b;
       }
-
+      // The result is in 'a' here.
+      if (a == tmpData) {
+        memcpy(mData, tmpData, szB);
+      }
       delete [] tmpData;
     } else {
       size_t integralImageStride = GetAlignedStride<16>(integralImageSize.width * 4);
 
       // We need to leave room for an additional 12 bytes for a maximum overrun
       // of 3 pixels in the blurring code.
       AlignedArray<uint32_t> integralImage((integralImageStride / 4) * integralImageSize.height + 12);
 
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -333,26 +333,18 @@ uint32_t nsGIFDecoder2::OutputRow()
     // Row to process
     const uint32_t bpr = sizeof(uint32_t) * mGIFStruct.width; 
     uint8_t *rowp = mImageData + (mGIFStruct.irow * bpr);
 
     // Convert color indices to Cairo pixels
     uint8_t *from = rowp + mGIFStruct.width;
     uint32_t *to = ((uint32_t*)rowp) + mGIFStruct.width;
     uint32_t *cmap = mColormap;
-    if (mColorMask == 0xFF) {
-      for (uint32_t c = mGIFStruct.width; c > 0; c--) {
-        *--to = cmap[*--from];
-      }
-    } else {
-      // Make sure that pixels within range of colormap.
-      uint8_t mask = mColorMask;
-      for (uint32_t c = mGIFStruct.width; c > 0; c--) {
-        *--to = cmap[(*--from) & mask];
-      }
+    for (uint32_t c = mGIFStruct.width; c > 0; c--) {
+      *--to = cmap[*--from];
     }
   
     // check for alpha (only for first frame)
     if (mGIFStruct.is_transparent && !mSawTransparency) {
       const uint32_t *rgb = (uint32_t*)rowp;
       for (uint32_t i = mGIFStruct.width; i > 0; i--) {
         if (*rgb++ == 0) {
           mSawTransparency = true;
@@ -462,17 +454,17 @@ nsGIFDecoder2::DoLzw(const uint8_t *q)
       if (code == (clear_code + 1)) {
         /* end-of-stream should only appear after all image data */
         return (mGIFStruct.rows_remaining == 0);
       }
 
       if (oldcode == -1) {
         if (code >= MAX_BITS)
           return false;
-        *rowp++ = suffix[code];
+        *rowp++ = suffix[code] & mColorMask; // ensure index is within colormap
         if (rowp == rowend)
           OUTPUT_ROW();
 
         firstchar = oldcode = code;
         continue;
       }
 
       int incode = code;
@@ -512,17 +504,17 @@ nsGIFDecoder2::DoLzw(const uint8_t *q)
           codesize++;
           codemask += avail;
         }
       }
       oldcode = incode;
 
       /* Copy the decoded data out to the scanline buffer. */
       do {
-        *rowp++ = *--stackp;
+        *rowp++ = *--stackp & mColorMask; // ensure index is within colormap
         if (rowp == rowend)
           OUTPUT_ROW();
       } while (stackp > stack);
     }
   }
 
   END:
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -137,21 +137,24 @@ CPPSRCS		= \
 		TestingFunctions.cpp \
 		Profilers.cpp \
 		LifoAlloc.cpp \
 		Eval.cpp \
 		MapObject.cpp \
 		RegExpObject.cpp \
 		RegExpStatics.cpp \
 		RegExp.cpp \
+		RootMarking.cpp \
 		Marking.cpp \
 		Memory.cpp \
 		Statistics.cpp \
 		StoreBuffer.cpp \
 		FindSCCs.cpp \
+		Iteration.cpp \
+		Verifier.cpp \
 		StringBuffer.cpp \
 		Unicode.cpp \
 		Xdr.cpp \
 		$(NULL)
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -1,8 +1,151 @@
+nspr.h
+plarena.h
+plarenas.h
+plbase64.h
+plerror.h
+plgetopt.h
+plhash.h
+plstr.h
+pratom.h
+prbit.h
+prclist.h
+prcmon.h
+prcountr.h
+prcpucfg.h
+prcvar.h
+prdtoa.h
+prenv.h
+prerr.h
+prerror.h
+prinet.h
+prinit.h
+prinrval.h
+prio.h
+pripcsem.h
+private
+prlink.h
+prlock.h
+prlog.h
+prlong.h
+prmem.h
+prmon.h
+prmwait.h
+prnetdb.h
+prolock.h
+prpdce.h
+prprf.h
+prproces.h
+prrng.h
+prrwlock.h
+prshm.h
+prshma.h
+prsystem.h
+prthread.h
+prtime.h
+prtpool.h
+prtrace.h
+prtypes.h
+prvrsion.h
+prwin16.h
+base64.h
+blapit.h
+cert.h
+certdb.h
+certt.h
+ciferfam.h
+cmmf.h
+cmmft.h
+cms.h
+cmsreclist.h
+cmst.h
+crmf.h
+crmft.h
+cryptohi.h
+cryptoht.h
+ecl-exp.h
+hasht.h
+jar-ds.h
+jar.h
+jarfile.h
+key.h
+keyhi.h
+keyt.h
+keythi.h
+nss.h
+nssb64.h
+nssb64t.h
+nssbase.h
+nssbaset.h
+nssck.api
+nssckbi.h
+nssckepv.h
+nssckft.h
+nssckfw.h
+nssckfwc.h
+nssckfwt.h
+nssckg.h
+nssckmdt.h
+nssckt.h
+nssilckt.h
+nssilock.h
+nsslocks.h
+nssrwlk.h
+nssrwlkt.h
+nssutil.h
+ocsp.h
+ocspt.h
+p12.h
+p12plcy.h
+p12t.h
+pk11func.h
+pk11pqg.h
+pk11priv.h
+pk11pub.h
+pk11sdr.h
+pkcs11.h
+pkcs11f.h
+pkcs11n.h
+pkcs11p.h
+pkcs11t.h
+pkcs11u.h
+pkcs12.h
+pkcs12t.h
+pkcs7t.h
+portreg.h
+preenc.h
+secasn1.h
+secasn1t.h
+seccomon.h
+secder.h
+secdert.h
+secdig.h
+secdigt.h
+secerr.h
+sechash.h
+secitem.h
+secmime.h
+secmod.h
+secmodt.h
+secoid.h
+secoidt.h
+secpkcs5.h
+secpkcs7.h
+secport.h
+shsign.h
+smime.h
+ssl.h
+sslerr.h
+sslproto.h
+sslt.h
+utilmodt.h
+utilpars.h
+utilparst.h
+utilrename.h
 A4Stuff.h
 activscp.h
 AEDataModel.h
 AEObjects.h
 AEPackObject.h
 AERegistry.h
 AEUtils.h
 afxcmn.h
@@ -143,17 +286,16 @@ callconv.h
 Carbon/Carbon.h
 CarbonEvents.h
 Carbon.h
 cassert
 c_asm.h
 cctype
 cderr.h
 cerrno
-cert.h
 CFBase.h
 CFBundle.h
 CFData.h
 CFDictionary.h
 cf.h
 CFNumber.h
 CFPlugIn.h
 CFPreferences.h
@@ -323,34 +465,30 @@ iodef.h
 io.h
 IOKit/IOKitLib.h
 IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
 iterator
-jar.h
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
 jemalloc.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
 jpeglib.h
 #endif
 JVMManagerTests.h
 Kerberos/Kerberos.h
 kernel/image.h
 kernel/OS.h
-key.h
-keyt.h
-keythi.h
 LAction.h
 langinfo.h
 LApplication.h
 LArray.h
 LArrayIterator.h
 LAttachable.h
 LAttachment.h
 LaunchServices.h
@@ -522,18 +660,16 @@ net/if.h
 netinet/in.h
 netinet/in_systm.h
 netinet/tcp.h
 new
 newexe.h
 new.h
 nl_types.h
 NodeInfo.h
-nss.h
-nssilock.h
 nsswitch.h
 objbase.h
 objidl.h
 Objsafe.h
 ojiapitests.h
 ole2.h
 oleidl.h
 OpenGL/OpenGL.h
@@ -558,19 +694,16 @@ pango/pangoxft.h
 pango/pango-utils.h
 pascal.h
 Patches.h
 Path.h
 pcfs/pc_dir.h
 Pgenerr.h
 PGenErr.h
 Ph.h
-pk11func.h
-pk11pub.h
-pkcs11t.h
 PLStringFuncs.h
 PMApplication.h
 pmddim.h
 poll.h
 Polygon.h
 portable.h
 Power.h
 PP_ClassHeaders.cp
@@ -620,20 +753,17 @@ rpcproxy.h
 rpc/types.h
 sane/sane.h
 sane/sanei.h
 sane/saneopts.h
 Scrap.h
 Screen.h
 Script.h
 ScrollBar.h
-seccomon.h
 sec.h
-secmod.h
-secmodt.h
 secrng.h
 security.h
 secutil.h
 semaphore.h
 servprov.h
 set
 setjmp.h
 SFNTLayoutTypes.h
@@ -648,19 +778,16 @@ SimpleGameSound.h
 SIOUX.h
 size_t.h
 sndio.h
 someincludefile.h
 Sound.h
 soundcard.h
 sqlite3.h
 ssdef.h
-sslerr.h
-ssl.h
-sslproto.h
 sstream
 stack
 StandardFile.h
 starlet.h
 stat.h
 statreg.cpp
 statreg.h
 stdarg.h
@@ -903,89 +1030,16 @@ X11/XKBlib.h
 X11/Xlib.h
 X11/Xlibint.h
 X11/Xlocale.h
 X11/Xos.h
 X11/Xutil.h
 xpt_struct.h
 xpt_xdr.h
 zmouse.h
-sslt.h
-smime.h
-cms.h
-sechash.h
-secoidt.h
-certdb.h
-secerr.h
-nssutil.h
-nssb64.h
-secasn1.h
-secder.h
-certt.h
-ocsp.h
-keyhi.h
-cryptohi.h
-crmf.h
-pk11pqg.h
-cmmf.h
-base64.h
-secdert.h
-secitem.h
-secmime.h
-nssckbi.h
-pkcs12.h
-p12plcy.h
-pk11sdr.h
-nspr.h
-pratom.h
-prbit.h
-prclist.h
-prcmon.h
-prcountr.h
-prcvar.h
-prdtoa.h
-prenv.h
-prerr.h
-prerror.h
-prinet.h
-prinit.h
-prinrval.h
-prio.h
-pripcsem.h
-prlink.h
-prlock.h
-prlog.h
-prlong.h
-prmem.h
-prmon.h
-prmwait.h
-prnetdb.h
-prolock.h
-prpdce.h
-prprf.h
-prproces.h
-prrng.h
-prrwlock.h
-prshm.h
-prshma.h
-prsystem.h
-prthread.h
-prtime.h
-prtpool.h
-prtrace.h
-prtypes.h
-prvrsion.h
-plbase64.h
-plerror.h
-plgetopt.h
-plresolv.h
-plstr.h
-plarenas.h
-plarena.h
-plhash.h
 speex/speex_resampler.h
 soundtouch/SoundTouch.h
 #if MOZ_NATIVE_PNG==1
 png.h
 #endif
 #if MOZ_NATIVE_ZLIB==1
 zlib.h
 #endif
new file mode 100644
--- /dev/null
+++ b/js/src/gc/GCInternals.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 jsgc_internal_h___
+#define jsgc_internal_h___
+
+#include "jsapi.h"
+
+namespace js {
+namespace gc {
+
+void
+MarkRuntime(JSTracer *trc, bool useSavedRoots = false);
+
+class AutoCopyFreeListToArenas {
+    JSRuntime *runtime;
+
+  public:
+    AutoCopyFreeListToArenas(JSRuntime *rt);
+    ~AutoCopyFreeListToArenas();
+};
+
+struct AutoFinishGC
+{
+    AutoFinishGC(JSRuntime *rt);
+};
+
+/*
+ * This class should be used by any code that needs to exclusive access to the
+ * heap in order to trace through it...
+ */
+class AutoTraceSession {
+  public:
+    AutoTraceSession(JSRuntime *rt, HeapState state = Tracing);
+    ~AutoTraceSession();
+
+  protected:
+    JSRuntime *runtime;
+
+  private:
+    AutoTraceSession(const AutoTraceSession&) MOZ_DELETE;
+    void operator=(const AutoTraceSession&) MOZ_DELETE;
+
+    js::HeapState prevState;
+};
+
+struct AutoPrepareForTracing
+{
+    AutoFinishGC finish;
+    AutoTraceSession session;
+    AutoCopyFreeListToArenas copy;
+
+    AutoPrepareForTracing(JSRuntime *rt);
+};
+
+class IncrementalSafety
+{
+    const char *reason_;
+
+    IncrementalSafety(const char *reason) : reason_(reason) {}
+
+  public:
+    static IncrementalSafety Safe() { return IncrementalSafety(NULL); }
+    static IncrementalSafety Unsafe(const char *reason) { return IncrementalSafety(reason); }
+
+    typedef void (IncrementalSafety::* ConvertibleToBool)();
+    void nonNull() {}
+
+    operator ConvertibleToBool() const {
+        return reason_ == NULL ? &IncrementalSafety::nonNull : 0;
+    }
+
+    const char *reason() {
+        JS_ASSERT(reason_);
+        return reason_;
+    }
+};
+
+IncrementalSafety
+IsIncrementalGCSafe(JSRuntime *rt);
+
+#ifdef JS_GC_ZEAL
+void
+StartVerifyPreBarriers(JSRuntime *rt);
+
+void
+EndVerifyPreBarriers(JSRuntime *rt);
+
+void
+StartVerifyPostBarriers(JSRuntime *rt);
+
+void
+EndVerifyPostBarriers(JSRuntime *rt);
+
+void
+FinishVerifier(JSRuntime *rt);
+#endif /* JS_GC_ZEAL */
+
+} /* namespace gc */
+} /* namespace js */
+
+#endif /* jsgc_internal_h___ */
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Iteration.cpp
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 "jsapi.h"
+#include "jscntxt.h"
+#include "jsgc.h"
+#include "jsprf.h"
+
+#include "js/HashTable.h"
+#include "gc/GCInternals.h"
+
+#include "jsgcinlines.h"
+
+using namespace js;
+using namespace js::gc;
+
+void
+js::TraceRuntime(JSTracer *trc)
+{
+    JS_ASSERT(!IS_GC_MARKING_TRACER(trc));
+
+    AutoPrepareForTracing prep(trc->runtime);
+    MarkRuntime(trc);
+}
+
+struct IterateArenaCallbackOp
+{
+    JSRuntime *rt;
+    void *data;
+    IterateArenaCallback callback;
+    JSGCTraceKind traceKind;
+    size_t thingSize;
+    IterateArenaCallbackOp(JSRuntime *rt, void *data, IterateArenaCallback callback,
+                           JSGCTraceKind traceKind, size_t thingSize)
+        : rt(rt), data(data), callback(callback), traceKind(traceKind), thingSize(thingSize)
+    {}
+    void operator()(Arena *arena) { (*callback)(rt, data, arena, traceKind, thingSize); }
+};
+
+struct IterateCellCallbackOp
+{
+    JSRuntime *rt;
+    void *data;
+    IterateCellCallback callback;
+    JSGCTraceKind traceKind;
+    size_t thingSize;
+    IterateCellCallbackOp(JSRuntime *rt, void *data, IterateCellCallback callback,
+                          JSGCTraceKind traceKind, size_t thingSize)
+        : rt(rt), data(data), callback(callback), traceKind(traceKind), thingSize(thingSize)
+    {}
+    void operator()(Cell *cell) { (*callback)(rt, data, cell, traceKind, thingSize); }
+};
+
+void
+js::IterateCompartmentsArenasCells(JSRuntime *rt, void *data,
+                                   JSIterateCompartmentCallback compartmentCallback,
+                                   IterateArenaCallback arenaCallback,
+                                   IterateCellCallback cellCallback)
+{
+    AutoPrepareForTracing prop(rt);
+
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        (*compartmentCallback)(rt, data, c);
+
+        for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) {
+            JSGCTraceKind traceKind = MapAllocToTraceKind(AllocKind(thingKind));
+            size_t thingSize = Arena::thingSize(AllocKind(thingKind));
+            IterateArenaCallbackOp arenaOp(rt, data, arenaCallback, traceKind, thingSize);
+            IterateCellCallbackOp cellOp(rt, data, cellCallback, traceKind, thingSize);
+            ForEachArenaAndCell(c, AllocKind(thingKind), arenaOp, cellOp);
+        }
+    }
+}
+
+void
+js::IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
+{
+    AutoPrepareForTracing prep(rt);
+
+    for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
+        chunkCallback(rt, data, r.front());
+}
+
+void
+js::IterateCells(JSRuntime *rt, JSCompartment *compartment, AllocKind thingKind,
+                 void *data, IterateCellCallback cellCallback)
+{
+    AutoPrepareForTracing prep(rt);
+
+    JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind);
+    size_t thingSize = Arena::thingSize(thingKind);
+
+    if (compartment) {
+        for (CellIterUnderGC i(compartment, thingKind); !i.done(); i.next())
+            cellCallback(rt, data, i.getCell(), traceKind, thingSize);
+    } else {
+        for (CompartmentsIter c(rt); !c.done(); c.next()) {
+            for (CellIterUnderGC i(c, thingKind); !i.done(); i.next())
+                cellCallback(rt, data, i.getCell(), traceKind, thingSize);
+        }
+    }
+}
+
+void
+js::IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, void *data)
+{
+    JS_ASSERT(compartment);
+    AutoPrepareForTracing prep(compartment->rt);
+
+    for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) {
+        for (CellIterUnderGC i(compartment, AllocKind(finalizeKind)); !i.done(); i.next()) {
+            Cell *cell = i.getCell();
+            if (cell->isMarked(GRAY))
+                cellCallback(data, cell);
+        }
+    }
+}
+
+JS_PUBLIC_API(void)
+JS_IterateCompartments(JSRuntime *rt, void *data,
+                       JSIterateCompartmentCallback compartmentCallback)
+{
+    JS_ASSERT(!rt->isHeapBusy());
+
+    AutoTraceSession session(rt);
+    rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
+
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        (*compartmentCallback)(rt, data, c);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/gc/RootMarking.cpp
@@ -0,0 +1,788 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 "mozilla/Attributes.h"
+#include "mozilla/Util.h"
+
+#include "jsapi.h"
+#include "jscntxt.h"
+#include "jsgc.h"
+#include "jsprf.h"
+#include "jswatchpoint.h"
+
+#include "frontend/Parser.h"
+#include "gc/GCInternals.h"
+#include "gc/Marking.h"
+#ifdef JS_ION
+# include "ion/IonMacroAssembler.h"
+# include "ion/IonFrameIterator.h"
+#endif
+#include "js/HashTable.h"
+#include "vm/Debugger.h"
+
+#include "jsgcinlines.h"
+#include "jsobjinlines.h"
+
+using namespace js;
+using namespace js::gc;
+
+using mozilla::ArrayEnd;
+
+typedef RootedValueMap::Range RootRange;
+typedef RootedValueMap::Entry RootEntry;
+typedef RootedValueMap::Enum RootEnum;
+
+#ifdef JSGC_USE_EXACT_ROOTING
+static inline void
+MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
+{
+    void **addr = (void **)rooter->address();
+    if (!*addr)
+        return;
+
+    switch (kind) {
+      case THING_ROOT_OBJECT:      MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break;
+      case THING_ROOT_STRING:      MarkStringRoot(trc, (JSSTring **)addr, "exact-string"); break;
+      case THING_ROOT_SCRIPT:      MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break;
+      case THING_ROOT_SHAPE:       MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break;
+      case THING_ROOT_BASE_SHAPE:  MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break;
+      case THING_ROOT_TYPE:        MarkTypeRoot(trc, (types::Type *)addr, "exact-type"); break;
+      case THING_ROOT_TYPE_OBJECT: MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact-typeobject"); break;
+      case THING_ROOT_VALUE:       MarkValueRoot(trc, (Value *)addr, "exact-value"); break;
+      case THING_ROOT_ID:          MarkIdRoot(trc, (jsid *)addr, "exact-id"); break;
+      case THING_ROOT_PROPERTY_ID: MarkIdRoot(trc, &((js::PropertyId *)addr)->asId(), "exact-propertyid"); break;
+      case THING_ROOT_BINDINGS:    ((Bindings *)addr)->trace(trc); break;
+      default: JS_NOT_REACHED("Invalid THING_ROOT kind"); break;
+    }
+}
+
+static inline void
+MarkExactStackRooters(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
+{
+    Rooted<void*> *rooter = cx->thingGCRooters[i];
+    while (rooter) {
+        MarkExactStackRoot(trc, rooter, ThingRootKind(i));
+        rooter = rooter->previous();
+    }
+}
+
+static void
+MarkExactStackRoots(JSTracer *trc)
+{
+    for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
+        for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
+            MarkExactStackRooters(trc, cx->thingGCRooters[i], ThingRootKind(i));
+        }
+        MarkExactStackRooters(trc, rt->mainThread.thingGCRooters[i], ThingRootKind(i));
+    }
+}
+#endif /* JSGC_USE_EXACT_ROOTING */
+
+static inline bool
+InFreeList(ArenaHeader *aheader, uintptr_t addr)
+{
+    if (!aheader->hasFreeThings())
+        return false;
+
+    FreeSpan firstSpan(aheader->getFirstFreeSpan());
+
+    for (const FreeSpan *span = &firstSpan;;) {
+        /* If the thing comes fore the current span, it's not free. */
+        if (addr < span->first)
+            return false;
+
+        /*
+         * If we find it inside the span, it's dead. We use here "<=" and not
+         * "<" even for the last span as we know that thing is inside the
+         * arena. Thus for the last span thing < span->end.
+         */
+        if (addr <= span->last)
+            return true;
+
+        /*
+         * The last possible empty span is an the end of the arena. Here
+         * span->end < thing < thingsEnd and so we must have more spans.
+         */
+        span = span->nextSpan();
+    }
+}
+
+enum ConservativeGCTest
+{
+    CGCT_VALID,
+    CGCT_LOWBITSET, /* excluded because one of the low bits was set */
+    CGCT_NOTARENA,  /* not within arena range in a chunk */
+    CGCT_OTHERCOMPARTMENT,  /* in another compartment */
+    CGCT_NOTCHUNK,  /* not within a valid chunk */
+    CGCT_FREEARENA, /* within arena containing only free things */
+    CGCT_NOTLIVE,   /* gcthing is not allocated */
+    CGCT_END
+};
+
+/*
+ * Tests whether w is a (possibly dead) GC thing. Returns CGCT_VALID and
+ * details about the thing if so. On failure, returns the reason for rejection.
+ */
+static inline ConservativeGCTest
+IsAddressableGCThing(JSRuntime *rt, uintptr_t w,
+                     bool skipUncollectedCompartments,
+                     gc::AllocKind *thingKindPtr,
+                     ArenaHeader **arenaHeader,
+                     void **thing)
+{
+    /*
+     * We assume that the compiler never uses sub-word alignment to store
+     * pointers and does not tag pointers on its own. Additionally, the value
+     * representation for all values and the jsid representation for GC-things
+     * do not touch the low two bits. Thus any word with the low two bits set
+     * is not a valid GC-thing.
+     */
+    JS_STATIC_ASSERT(JSID_TYPE_STRING == 0 && JSID_TYPE_OBJECT == 4);
+    if (w & 0x3)
+        return CGCT_LOWBITSET;
+
+    /*
+     * An object jsid has its low bits tagged. In the value representation on
+     * 64-bit, the high bits are tagged.
+     */
+    const uintptr_t JSID_PAYLOAD_MASK = ~uintptr_t(JSID_TYPE_MASK);
+#if JS_BITS_PER_WORD == 32
+    uintptr_t addr = w & JSID_PAYLOAD_MASK;
+#elif JS_BITS_PER_WORD == 64
+    uintptr_t addr = w & JSID_PAYLOAD_MASK & JSVAL_PAYLOAD_MASK;
+#endif
+
+    Chunk *chunk = Chunk::fromAddress(addr);
+
+    if (!rt->gcChunkSet.has(chunk))
+        return CGCT_NOTCHUNK;
+
+    /*
+     * We query for pointers outside the arena array after checking for an
+     * allocated chunk. Such pointers are rare and we want to reject them
+     * after doing more likely rejections.
+     */
+    if (!Chunk::withinArenasRange(addr))
+        return CGCT_NOTARENA;
+
+    /* If the arena is not currently allocated, don't access the header. */
+    size_t arenaOffset = Chunk::arenaIndex(addr);
+    if (chunk->decommittedArenas.get(arenaOffset))
+        return CGCT_FREEARENA;
+
+    ArenaHeader *aheader = &chunk->arenas[arenaOffset].aheader;
+
+    if (!aheader->allocated())
+        return CGCT_FREEARENA;
+
+    if (skipUncollectedCompartments && !aheader->compartment->isCollecting())
+        return CGCT_OTHERCOMPARTMENT;
+
+    AllocKind thingKind = aheader->getAllocKind();
+    uintptr_t offset = addr & ArenaMask;
+    uintptr_t minOffset = Arena::firstThingOffset(thingKind);
+    if (offset < minOffset)
+        return CGCT_NOTARENA;
+
+    /* addr can point inside the thing so we must align the address. */
+    uintptr_t shift = (offset - minOffset) % Arena::thingSize(thingKind);
+    addr -= shift;
+
+    if (thing)
+        *thing = reinterpret_cast<void *>(addr);
+    if (arenaHeader)
+        *arenaHeader = aheader;
+    if (thingKindPtr)
+        *thingKindPtr = thingKind;
+    return CGCT_VALID;
+}
+
+/*
+ * Returns CGCT_VALID and mark it if the w can be a  live GC thing and sets
+ * thingKind accordingly. Otherwise returns the reason for rejection.
+ */
+static inline ConservativeGCTest
+MarkIfGCThingWord(JSTracer *trc, uintptr_t w)
+{
+    void *thing;
+    ArenaHeader *aheader;
+    AllocKind thingKind;
+    ConservativeGCTest status =
+        IsAddressableGCThing(trc->runtime, w, IS_GC_MARKING_TRACER(trc),
+                             &thingKind, &aheader, &thing);
+    if (status != CGCT_VALID)
+        return status;
+
+    /*
+     * Check if the thing is free. We must use the list of free spans as at
+     * this point we no longer have the mark bits from the previous GC run and
+     * we must account for newly allocated things.
+     */
+    if (InFreeList(aheader, uintptr_t(thing)))
+        return CGCT_NOTLIVE;
+
+    JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind);
+#ifdef DEBUG
+    const char pattern[] = "machine_stack %p";
+    char nameBuf[sizeof(pattern) - 2 + sizeof(thing) * 2];
+    JS_snprintf(nameBuf, sizeof(nameBuf), pattern, thing);
+    JS_SET_TRACING_NAME(trc, nameBuf);
+#endif
+    JS_SET_TRACING_LOCATION(trc, (void *)w);
+    void *tmp = thing;
+    MarkKind(trc, &tmp, traceKind);
+    JS_ASSERT(tmp == thing);
+
+#ifdef DEBUG
+    if (trc->runtime->gcIncrementalState == MARK_ROOTS)
+        trc->runtime->mainThread.gcSavedRoots.append(
+            PerThreadData::SavedGCRoot(thing, traceKind));
+#endif
+
+    return CGCT_VALID;
+}
+
+static void
+MarkWordConservatively(JSTracer *trc, uintptr_t w)
+{
+    /*
+     * The conservative scanner may access words that valgrind considers as
+     * undefined. To avoid false positives and not to alter valgrind view of
+     * the memory we make as memcheck-defined the argument, a copy of the
+     * original word. See bug 572678.
+     */
+#ifdef JS_VALGRIND
+    JS_SILENCE_UNUSED_VALUE_IN_EXPR(VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w)));
+#endif
+
+    MarkIfGCThingWord(trc, w);
+}
+
+MOZ_ASAN_BLACKLIST
+static void
+MarkRangeConservatively(JSTracer *trc, const uintptr_t *begin, const uintptr_t *end)
+{
+    JS_ASSERT(begin <= end);
+    for (const uintptr_t *i = begin; i < end; ++i)
+        MarkWordConservatively(trc, *i);
+}
+
+#ifndef JSGC_USE_EXACT_ROOTING
+static void
+MarkRangeConservativelyAndSkipIon(JSTracer *trc, JSRuntime *rt, const uintptr_t *begin, const uintptr_t *end)
+{
+    const uintptr_t *i = begin;
+
+#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
+    // Walk only regions in between Ion activations. Note that non-volatile
+    // registers are spilled to the stack before the entry Ion frame, ensuring
+    // that the conservative scanner will still see them.
+    for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
+        uintptr_t *ionMin, *ionEnd;
+        ion.ionStackRange(ionMin, ionEnd);
+
+        MarkRangeConservatively(trc, i, ionMin);
+        i = ionEnd;
+    }
+#endif
+
+    // Mark everything after the most recent Ion activation.
+    MarkRangeConservatively(trc, i, end);
+}
+
+static JS_NEVER_INLINE void
+MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
+{
+    JSRuntime *rt = trc->runtime;
+
+#ifdef DEBUG
+    if (useSavedRoots) {
+        for (PerThreadData::SavedGCRoot *root = rt->mainThread.gcSavedRoots.begin();
+             root != rt->mainThread.gcSavedRoots.end();
+             root++)
+        {
+            JS_SET_TRACING_NAME(trc, "cstack");
+            MarkKind(trc, &root->thing, root->kind);
+        }
+        return;
+    }
+
+    if (rt->gcIncrementalState == MARK_ROOTS)
+        rt->mainThread.gcSavedRoots.clearAndFree();
+#endif
+
+    ConservativeGCData *cgcd = &rt->conservativeGC;
+    if (!cgcd->hasStackToScan()) {
+#ifdef JS_THREADSAFE
+        JS_ASSERT(!rt->requestDepth);
+#endif
+        return;
+    }
+
+    uintptr_t *stackMin, *stackEnd;
+#if JS_STACK_GROWTH_DIRECTION > 0
+    stackMin = rt->nativeStackBase;
+    stackEnd = cgcd->nativeStackTop;
+#else
+    stackMin = cgcd->nativeStackTop + 1;
+    stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
+#endif
+
+    JS_ASSERT(stackMin <= stackEnd);
+    MarkRangeConservativelyAndSkipIon(trc, rt, stackMin, stackEnd);
+    MarkRangeConservatively(trc, cgcd->registerSnapshot.words,
+                            ArrayEnd(cgcd->registerSnapshot.words));
+}
+
+#endif /* JSGC_USE_EXACT_ROOTING */
+
+void
+js::MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv)
+{
+    const uintptr_t *begin = beginv->payloadUIntPtr();
+    const uintptr_t *end = endv->payloadUIntPtr();
+#ifdef JS_NUNBOX32
+    /*
+     * With 64-bit jsvals on 32-bit systems, we can optimize a bit by
+     * scanning only the payloads.
+     */
+    JS_ASSERT(begin <= end);
+    for (const uintptr_t *i = begin; i < end; i += sizeof(Value) / sizeof(uintptr_t))
+        MarkWordConservatively(trc, *i);
+#else
+    MarkRangeConservatively(trc, begin, end);
+#endif
+}
+
+JS_NEVER_INLINE void
+ConservativeGCData::recordStackTop()
+{
+    /* Update the native stack pointer if it points to a bigger stack. */
+    uintptr_t dummy;
+    nativeStackTop = &dummy;
+
+    /*
+     * To record and update the register snapshot for the conservative scanning
+     * with the latest values we use setjmp.
+     */
+#if defined(_MSC_VER)
+# pragma warning(push)
+# pragma warning(disable: 4611)
+#endif
+    (void) setjmp(registerSnapshot.jmpbuf);
+#if defined(_MSC_VER)
+# pragma warning(pop)
+#endif
+}
+
+void
+AutoIdArray::trace(JSTracer *trc)
+{
+    JS_ASSERT(tag == IDARRAY);
+    gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
+}
+
+inline void
+AutoGCRooter::trace(JSTracer *trc)
+{
+    switch (tag) {
+      case JSVAL:
+        MarkValueRoot(trc, &static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
+        return;
+
+      case PARSER:
+        static_cast<frontend::Parser *>(this)->trace(trc);
+        return;
+
+      case IDARRAY: {
+        JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
+        MarkIdRange(trc, ida->length, ida->vector, "JS::AutoIdArray.idArray");
+        return;
+      }
+
+      case DESCRIPTORS: {
+        PropDescArray &descriptors =
+            static_cast<AutoPropDescArrayRooter *>(this)->descriptors;
+        for (size_t i = 0, len = descriptors.length(); i < len; i++) {
+            PropDesc &desc = descriptors[i];
+            MarkValueRoot(trc, &desc.pd_, "PropDesc::pd_");
+            MarkValueRoot(trc, &desc.value_, "PropDesc::value_");
+            MarkValueRoot(trc, &desc.get_, "PropDesc::get_");
+            MarkValueRoot(trc, &desc.set_, "PropDesc::set_");
+        }
+        return;
+      }
+
+      case DESCRIPTOR : {
+        PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
+        if (desc.obj)
+            MarkObjectRoot(trc, &desc.obj, "Descriptor::obj");
+        MarkValueRoot(trc, &desc.value, "Descriptor::value");
+        if ((desc.attrs & JSPROP_GETTER) && desc.getter) {
+            JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter);
+            MarkObjectRoot(trc, &tmp, "Descriptor::get");
+            desc.getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, tmp);
+        }
+        if (desc.attrs & JSPROP_SETTER && desc.setter) {
+            JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter);
+            MarkObjectRoot(trc, &tmp, "Descriptor::set");
+            desc.setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
+        }
+        return;
+      }
+
+#if JS_HAS_XML_SUPPORT
+      case NAMESPACES: {
+        JSXMLArray<JSObject> &array = static_cast<AutoNamespaceArray *>(this)->array;
+        MarkObjectRange(trc, array.length, array.vector, "JSXMLArray.vector");
+        js_XMLArrayCursorTrace(trc, array.cursors);
+        return;
+      }
+
+      case XML:
+        js_TraceXML(trc, static_cast<AutoXMLRooter *>(this)->xml);
+        return;
+#endif
+
+      case OBJECT:
+        if (static_cast<AutoObjectRooter *>(this)->obj)
+            MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj,
+                           "JS::AutoObjectRooter.obj");
+        return;
+
+      case ID:
+        MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
+        return;
+
+      case VALVECTOR: {
+        AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
+        MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
+        return;
+      }
+
+      case STRING:
+        if (static_cast<AutoStringRooter *>(this)->str)
+            MarkStringRoot(trc, &static_cast<AutoStringRooter *>(this)->str,
+                           "JS::AutoStringRooter.str");
+        return;
+
+      case IDVECTOR: {
+        AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
+        MarkIdRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
+        return;
+      }
+
+      case SHAPEVECTOR: {
+        AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
+        MarkShapeRootRange(trc, vector.length(), const_cast<Shape **>(vector.begin()),
+                           "js::AutoShapeVector.vector");
+        return;
+      }
+
+      case OBJVECTOR: {
+        AutoObjectVector::VectorImpl &vector = static_cast<AutoObjectVector *>(this)->vector;
+        MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
+        return;
+      }
+
+      case STRINGVECTOR: {
+        AutoStringVector::VectorImpl &vector = static_cast<AutoStringVector *>(this)->vector;
+        MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector");
+        return;
+      }
+
+      case NAMEVECTOR: {
+        AutoNameVector::VectorImpl &vector = static_cast<AutoNameVector *>(this)->vector;
+        MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoNameVector.vector");
+        return;
+      }
+
+      case VALARRAY: {
+        AutoValueArray *array = static_cast<AutoValueArray *>(this);
+        MarkValueRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
+        return;
+      }
+
+      case SCRIPTVECTOR: {
+        AutoScriptVector::VectorImpl &vector = static_cast<AutoScriptVector *>(this)->vector;
+        for (size_t i = 0; i < vector.length(); i++)
+            MarkScriptRoot(trc, &vector[i], "AutoScriptVector element");
+        return;
+      }
+
+      case PROPDESC: {
+        PropDesc::AutoRooter *rooter = static_cast<PropDesc::AutoRooter *>(this);
+        MarkValueRoot(trc, &rooter->pd->pd_, "PropDesc::AutoRooter pd");
+        MarkValueRoot(trc, &rooter->pd->value_, "PropDesc::AutoRooter value");
+        MarkValueRoot(trc, &rooter->pd->get_, "PropDesc::AutoRooter get");
+        MarkValueRoot(trc, &rooter->pd->set_, "PropDesc::AutoRooter set");
+        return;
+      }
+
+      case SHAPERANGE: {
+        Shape::Range::AutoRooter *rooter = static_cast<Shape::Range::AutoRooter *>(this);
+        rooter->trace(trc);
+        return;
+      }
+
+      case STACKSHAPE: {
+        StackShape::AutoRooter *rooter = static_cast<StackShape::AutoRooter *>(this);
+        if (rooter->shape->base)
+            MarkBaseShapeRoot(trc, (BaseShape**) &rooter->shape->base, "StackShape::AutoRooter base");
+        MarkIdRoot(trc, (jsid*) &rooter->shape->propid, "StackShape::AutoRooter id");
+        return;
+      }
+
+      case STACKBASESHAPE: {
+        StackBaseShape::AutoRooter *rooter = static_cast<StackBaseShape::AutoRooter *>(this);
+        if (rooter->base->parent)
+            MarkObjectRoot(trc, (JSObject**) &rooter->base->parent, "StackBaseShape::AutoRooter parent");
+        if ((rooter->base->flags & BaseShape::HAS_GETTER_OBJECT) && rooter->base->rawGetter) {
+            MarkObjectRoot(trc, (JSObject**) &rooter->base->rawGetter,
+                           "StackBaseShape::AutoRooter getter");
+        }
+        if ((rooter->base->flags & BaseShape::HAS_SETTER_OBJECT) && rooter->base->rawSetter) {
+            MarkObjectRoot(trc, (JSObject**) &rooter->base->rawSetter,
+                           "StackBaseShape::AutoRooter setter");
+        }
+        return;
+      }
+
+      case GETTERSETTER: {
+        AutoRooterGetterSetter::Inner *rooter = static_cast<AutoRooterGetterSetter::Inner *>(this);
+        if ((rooter->attrs & JSPROP_GETTER) && *rooter->pgetter)
+            MarkObjectRoot(trc, (JSObject**) rooter->pgetter, "AutoRooterGetterSetter getter");
+        if ((rooter->attrs & JSPROP_SETTER) && *rooter->psetter)
+            MarkObjectRoot(trc, (JSObject**) rooter->psetter, "AutoRooterGetterSetter setter");
+        return;
+      }
+
+      case REGEXPSTATICS: {
+          /*
+        RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
+        rooter->trace(trc);
+          */
+        return;
+      }
+
+      case HASHABLEVALUE: {
+          /*
+        HashableValue::AutoRooter *rooter = static_cast<HashableValue::AutoRooter *>(this);
+        rooter->trace(trc);
+          */
+        return;
+      }
+
+      case IONMASM: {
+#ifdef JS_ION
+        static_cast<js::ion::MacroAssembler::AutoRooter *>(this)->masm()->trace(trc);
+#endif
+        return;
+      }
+
+      case IONALLOC: {
+#ifdef JS_ION
+        static_cast<js::ion::AutoTempAllocatorRooter *>(this)->trace(trc);
+#endif
+        return;
+      }
+
+      case WRAPPER: {
+        /*
+         * We need to use MarkValueUnbarriered here because we mark wrapper
+         * roots in every slice. This is because of some rule-breaking in
+         * RemapAllWrappersForObject; see comment there.
+         */
+          MarkValueUnbarriered(trc, &static_cast<AutoWrapperRooter *>(this)->value.get(),
+                               "JS::AutoWrapperRooter.value");
+        return;
+      }
+
+      case WRAPVECTOR: {
+        AutoWrapperVector::VectorImpl &vector = static_cast<AutoWrapperVector *>(this)->vector;
+        /*
+         * We need to use MarkValueUnbarriered here because we mark wrapper
+         * roots in every slice. This is because of some rule-breaking in
+         * RemapAllWrappersForObject; see comment there.
+         */
+        for (WrapperValue *p = vector.begin(); p < vector.end(); p++)
+            MarkValueUnbarriered(trc, &p->get(), "js::AutoWrapperVector.vector");
+        return;
+      }
+    }
+
+    JS_ASSERT(tag >= 0);
+    MarkValueRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
+                       "JS::AutoArrayRooter.array");
+}
+
+/* static */ void
+AutoGCRooter::traceAll(JSTracer *trc)
+{
+    for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down)
+        gcr->trace(trc);
+}
+
+/* static */ void
+AutoGCRooter::traceAllWrappers(JSTracer *trc)
+{
+    for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down) {
+        if (gcr->tag == WRAPVECTOR || gcr->tag == WRAPPER)
+            gcr->trace(trc);
+    }
+}
+
+void
+Shape::Range::AutoRooter::trace(JSTracer *trc)
+{
+    if (r->cursor)
+        MarkShapeRoot(trc, const_cast<Shape**>(&r->cursor), "Shape::Range::AutoRooter");
+}
+
+void
+RegExpStatics::AutoRooter::trace(JSTracer *trc)
+{
+    if (statics->matchPairsInput)
+        MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchPairsInput),
+                       "RegExpStatics::AutoRooter matchPairsInput");
+    if (statics->pendingInput)
+        MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
+                       "RegExpStatics::AutoRooter pendingInput");
+}
+
+void
+HashableValue::AutoRooter::trace(JSTracer *trc)
+{
+    MarkValueRoot(trc, reinterpret_cast<Value*>(&v->value), "HashableValue::AutoRooter");
+}
+
+void
+js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
+{
+    JSRuntime *rt = trc->runtime;
+    JS_ASSERT(trc->callback != GCMarker::GrayCallback);
+
+    if (IS_GC_MARKING_TRACER(trc)) {
+        for (CompartmentsIter c(rt); !c.done(); c.next()) {
+            if (!c->isCollecting())
+                c->markCrossCompartmentWrappers(trc);
+        }
+        Debugger::markCrossCompartmentDebuggerObjectReferents(trc);
+    }
+
+    AutoGCRooter::traceAll(trc);
+
+    if (rt->hasContexts()) {
+#ifdef JSGC_USE_EXACT_ROOTING
+        MarkExactStackRoots(trc);
+#else
+        MarkConservativeStackRoots(trc, useSavedRoots);
+#endif
+        rt->markSelfHostedGlobal(trc);
+    }
+
+    for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
+        const RootEntry &entry = r.front();
+        const char *name = entry.value.name ? entry.value.name : "root";
+        if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
+            MarkGCThingRoot(trc, reinterpret_cast<void **>(entry.key), name);
+        else
+            MarkValueRoot(trc, reinterpret_cast<Value *>(entry.key), name);
+    }
+
+    for (GCLocks::Range r = rt->gcLocksHash.all(); !r.empty(); r.popFront()) {
+        const GCLocks::Entry &entry = r.front();
+        JS_ASSERT(entry.value >= 1);
+        JS_SET_TRACING_LOCATION(trc, (void *)&entry.key);
+        void *tmp = entry.key;
+        MarkGCThingRoot(trc, &tmp, "locked object");
+        JS_ASSERT(tmp == entry.key);
+    }
+
+    if (rt->scriptAndCountsVector) {
+        ScriptAndCountsVector &vec = *rt->scriptAndCountsVector;
+        for (size_t i = 0; i < vec.length(); i++)
+            MarkScriptRoot(trc, &vec[i].script, "scriptAndCountsVector");
+    }
+
+    if (!IS_GC_MARKING_TRACER(trc) || rt->atomsCompartment->isCollecting()) {
+        MarkAtoms(trc);
+#ifdef JS_ION
+        /* Any Ion wrappers survive until the runtime is being torn down. */
+        if (rt->hasContexts())
+            ion::IonRuntime::Mark(trc);
+#endif
+    }
+
+    rt->staticStrings.trace(trc);
+
+    for (ContextIter acx(rt); !acx.done(); acx.next())
+        acx->mark(trc);
+
+    /* We can't use GCCompartmentsIter if we're called from TraceRuntime. */
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        if (IS_GC_MARKING_TRACER(trc) && !c->isCollecting())
+            continue;
+
+        if ((c->activeAnalysis || c->isPreservingCode()) && IS_GC_MARKING_TRACER(trc)) {
+            gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_TYPES);
+            c->markTypes(trc);
+        }
+
+        /* During a GC, these are treated as weak pointers. */
+        if (!IS_GC_MARKING_TRACER(trc)) {
+            if (c->watchpointMap)
+                c->watchpointMap->markAll(trc);
+        }
+
+        /* Do not discard scripts with counts while profiling. */
+        if (rt->profilingScripts) {
+            for (CellIterUnderGC i(c, FINALIZE_SCRIPT); !i.done(); i.next()) {
+                JSScript *script = i.get<JSScript>();
+                if (script->hasScriptCounts) {
+                    MarkScriptRoot(trc, &script, "profilingScripts");
+                    JS_ASSERT(script == i.get<JSScript>());
+                }
+            }
+        }
+
+        /* Mark debug scopes, if present */
+        if (c->debugScopes)
+            c->debugScopes->mark(trc);
+    }
+
+#ifdef JS_METHODJIT
+    /* We need to expand inline frames before stack scanning. */
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        mjit::ExpandInlineFrames(c);
+#endif
+
+    rt->stackSpace.mark(trc);
+
+#ifdef JS_ION
+    ion::MarkIonActivations(rt, trc);
+#endif
+
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        c->mark(trc);
+
+    /* The embedding can register additional roots here. */
+    if (JSTraceDataOp op = rt->gcBlackRootsTraceOp)
+        (*op)(trc, rt->gcBlackRootsData);
+
+    /* During GC, this buffers up the gray roots and doesn't mark them. */
+    if (JSTraceDataOp op = rt->gcGrayRootsTraceOp) {
+        if (IS_GC_MARKING_TRACER(trc)) {
+            GCMarker *gcmarker = static_cast<GCMarker *>(trc);
+            gcmarker->startBufferingGrayRoots();
+            (*op)(trc, rt->gcGrayRootsData);
+            gcmarker->endBufferingGrayRoots();
+        } else {
+            (*op)(trc, rt->gcGrayRootsData);
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Verifier.cpp
@@ -0,0 +1,759 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * 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 "jsapi.h"
+#include "jscntxt.h"
+#include "jsgc.h"
+#include "jsprf.h"
+
+#include "js/HashTable.h"
+#include "gc/GCInternals.h"
+
+#include "jsgcinlines.h"
+
+using namespace js;
+using namespace js::gc;
+
+#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
+
+JS_ALWAYS_INLINE bool
+CheckStackRootThing(uintptr_t *w, void *address, ThingRootKind kind)
+{
+    if (kind != THING_ROOT_BINDINGS)
+        return address == static_cast<void*>(w);
+
+    Bindings *bp = static_cast<Bindings*>(address);
+    return w >= (uintptr_t*)bp && w < (uintptr_t*)(bp + 1);
+}
+
+JS_ALWAYS_INLINE void
+CheckStackRootThings(uintptr_t *w, Rooted<void*> *rooter, ThingRootKind kind, bool *matched)
+{
+    while (rooter) {
+        if (CheckStackRootThing(w, rooter->address(), kind))
+            *matched = true;
+        rooter = rooter->previous();
+    }
+}
+
+static void
+CheckStackRoot(JSTracer *trc, uintptr_t *w)
+{
+    /* Mark memory as defined for valgrind, as in MarkWordConservatively. */
+#ifdef JS_VALGRIND
+    VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
+#endif
+
+    ConservativeGCTest test = MarkIfGCThingWord(trc, *w);
+
+    if (test == CGCT_VALID) {
+        bool matched = false;
+        JSRuntime *rt = trc->runtime;
+        for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
+            CheckStackRootThings(w, rt->mainThread.thingGCRooters[i],
+                                 ThingRootKind(i), &matched);
+            for (ContextIter cx(rt); !cx.done(); cx.next()) {
+                CheckStackRootThings(w, cx->thingGCRooters[i], ThingRootKind(i), &matched);
+                SkipRoot *skip = cx->skipGCRooters;
+                while (skip) {
+                    if (skip->contains(reinterpret_cast<uint8_t*>(w), sizeof(w)))
+                        matched = true;
+                    skip = skip->previous();
+                }
+            }
+        }
+        if (!matched) {
+            /*
+             * Only poison the last byte in the word. It is easy to get
+             * accidental collisions when a value that does not occupy a full
+             * word is used to overwrite a now-dead GC thing pointer. In this
+             * case we want to avoid damaging the smaller value.
+             */
+            PoisonPtr(w);
+        }
+    }
+}
+
+static void
+CheckStackRootsRange(JSTracer *trc, uintptr_t *begin, uintptr_t *end)
+{
+    JS_ASSERT(begin <= end);
+    for (uintptr_t *i = begin; i != end; ++i)
+        CheckStackRoot(trc, i);
+}
+
+static void
+CheckStackRootsRangeAndSkipIon(JSRuntime *rt, JSTracer *trc, uintptr_t *begin, uintptr_t *end)
+{
+    /*
+     * Regions of the stack between Ion activiations are marked exactly through
+     * a different mechanism. We need to skip these regions when checking the
+     * stack so that we do not poison IonMonkey's things.
+     */
+    uintptr_t *i = begin;
+
+#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
+    for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
+        uintptr_t *ionMin, *ionEnd;
+        ion.ionStackRange(ionMin, ionEnd);
+
+        CheckStackRootsRange(trc, i, ionMin);
+        i = ionEnd;
+    }
+#endif
+
+    /* The topmost Ion activiation may be beyond our prior top. */
+    if (i <= end)
+        CheckStackRootsRange(trc, i, end);
+}
+
+static void
+EmptyMarkCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
+{}
+
+void
+JS::CheckStackRoots(JSContext *cx)
+{
+    JSRuntime *rt = cx->runtime;
+
+    if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue)
+        return;
+    if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled)
+        return;
+
+    // If this assertion fails, it means that an AutoAssertNoGC was placed
+    // around code that could trigger GC, and is therefore wrong. The
+    // AutoAssertNoGC should be removed and the code it was guarding should be
+    // modified to properly root any gcthings, and very possibly any code
+    // calling that function should also be modified if it was improperly
+    // assuming that GC could not happen at all within the called function.
+    // (The latter may not apply if the AutoAssertNoGC only protected a portion
+    // of a function, so the callers were already assuming that GC could
+    // happen.)
+    JS_ASSERT(!InNoGCScope());
+
+    // GCs can't happen when analysis/inference/compilation are active.
+    if (cx->compartment->activeAnalysis)
+        return;
+
+    // Can switch to the atoms compartment during analysis.
+    if (IsAtomsCompartment(cx->compartment)) {
+        for (CompartmentsIter c(rt); !c.done(); c.next()) {
+            if (c.get()->activeAnalysis)
+                return;
+        }
+    }
+
+    AutoCopyFreeListToArenas copy(rt);
+
+    JSTracer checker;
+    JS_TracerInit(&checker, rt, EmptyMarkCallback);
+
+    ConservativeGCData *cgcd = &rt->conservativeGC;
+    cgcd->recordStackTop();
+
+    JS_ASSERT(cgcd->hasStackToScan());
+    uintptr_t *stackMin, *stackEnd;
+#if JS_STACK_GROWTH_DIRECTION > 0
+    stackMin = rt->nativeStackBase;
+    stackEnd = cgcd->nativeStackTop;
+#else
+    stackMin = cgcd->nativeStackTop + 1;
+    stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
+
+    uintptr_t *&oldStackMin = cgcd->oldStackMin, *&oldStackEnd = cgcd->oldStackEnd;
+    uintptr_t *&oldStackData = cgcd->oldStackData;
+    uintptr_t &oldStackCapacity = cgcd->oldStackCapacity;
+
+    /*
+     * Adjust the stack to remove regions which have not changed since the
+     * stack was last scanned, and update the last scanned state.
+     */
+    if (stackEnd != oldStackEnd) {
+        js_free(oldStackData);
+        oldStackCapacity = rt->nativeStackQuota / sizeof(uintptr_t);
+        oldStackData = (uintptr_t *) rt->malloc_(oldStackCapacity * sizeof(uintptr_t));
+        if (!oldStackData) {
+            oldStackCapacity = 0;
+        } else {
+            uintptr_t *existing = stackEnd - 1, *copy = oldStackData;
+            while (existing >= stackMin && size_t(copy - oldStackData) < oldStackCapacity)
+                *copy++ = *existing--;
+            oldStackEnd = stackEnd;
+            oldStackMin = existing + 1;
+        }
+    } else {
+        uintptr_t *existing = stackEnd - 1, *copy = oldStackData;
+        while (existing >= stackMin && existing >= oldStackMin && *existing == *copy) {
+            copy++;
+            existing--;
+        }
+        stackEnd = existing + 1;
+        while (existing >= stackMin && size_t(copy - oldStackData) < oldStackCapacity)
+            *copy++ = *existing--;
+        oldStackMin = existing + 1;
+    }
+#endif
+
+    JS_ASSERT(stackMin <= stackEnd);
+    CheckStackRootsRangeAndSkipIon(rt, &checker, stackMin, stackEnd);
+    CheckStackRootsRange(&checker, cgcd->registerSnapshot.words,
+                         ArrayEnd(cgcd->registerSnapshot.words));
+}
+
+#endif /* DEBUG && JS_GC_ZEAL && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */
+
+#ifdef JS_GC_ZEAL
+
+/*
+ * Write barrier verification
+ *
+ * The next few functions are for write barrier verification.
+ *
+ * The VerifyBarriers function is a shorthand. It checks if a verification phase
+ * is currently running. If not, it starts one. Otherwise, it ends the current
+ * phase and starts a new one.
+ *
+ * The user can adjust the frequency of verifications, which causes
+ * VerifyBarriers to be a no-op all but one out of N calls. However, if the
+ * |always| parameter is true, it starts a new phase no matter what.
+ *
+ * Pre-Barrier Verifier:
+ *   When StartVerifyBarriers is called, a snapshot is taken of all objects in
+ *   the GC heap and saved in an explicit graph data structure. Later,
+ *   EndVerifyBarriers traverses the heap again. Any pointer values that were in
+ *   the snapshot and are no longer found must be marked; otherwise an assertion
+ *   triggers. Note that we must not GC in between starting and finishing a
+ *   verification phase.
+ *
+ * Post-Barrier Verifier:
+ *   When StartVerifyBarriers is called, we create a virtual "Nursery Set" which
+ *   future allocations are recorded in and turn on the StoreBuffer. Later,
+ *   EndVerifyBarriers traverses the heap and ensures that the set of cross-
+ *   generational pointers we find is a subset of the pointers recorded in our
+ *   StoreBuffer.
+ */
+
+struct EdgeValue
+{
+    void *thing;
+    JSGCTraceKind kind;
+    char *label;
+};
+
+struct VerifyNode
+{
+    void *thing;
+    JSGCTraceKind kind;
+    uint32_t count;
+    EdgeValue edges[1];
+};
+
+typedef HashMap<void *, VerifyNode *, DefaultHasher<void *>, SystemAllocPolicy> NodeMap;
+
+/*
+ * The verifier data structures are simple. The entire graph is stored in a
+ * single block of memory. At the beginning is a VerifyNode for the root
+ * node. It is followed by a sequence of EdgeValues--the exact number is given
+ * in the node. After the edges come more nodes and their edges.
+ *
+ * The edgeptr and term fields are used to allocate out of the block of memory
+ * for the graph. If we run out of memory (i.e., if edgeptr goes beyond term),
+ * we just abandon the verification.
+ *
+ * The nodemap field is a hashtable that maps from the address of the GC thing
+ * to the VerifyNode that represents it.
+ */
+struct VerifyPreTracer : JSTracer {
+    /* The gcNumber when the verification began. */
+    uint64_t number;
+
+    /* This counts up to gcZealFrequency to decide whether to verify. */
+    int count;
+
+    /* This graph represents the initial GC "snapshot". */
+    VerifyNode *curnode;
+    VerifyNode *root;
+    char *edgeptr;
+    char *term;
+    NodeMap nodemap;
+
+    VerifyPreTracer() : root(NULL) {}
+    ~VerifyPreTracer() { js_free(root); }
+};
+
+/*
+ * This function builds up the heap snapshot by adding edges to the current
+ * node.
+ */
+static void
+AccumulateEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
+{
+    VerifyPreTracer *trc = (VerifyPreTracer *)jstrc;
+
+    trc->edgeptr += sizeof(EdgeValue);
+    if (trc->edgeptr >= trc->term) {
+        trc->edgeptr = trc->term;
+        return;
+    }
+
+    VerifyNode *node = trc->curnode;
+    uint32_t i = node->count;
+
+    node->edges[i].thing = *thingp;
+    node->edges[i].kind = kind;
+    node->edges[i].label = trc->debugPrinter ? NULL : (char *)trc->debugPrintArg;
+    node->count++;
+}
+
+static VerifyNode *
+MakeNode(VerifyPreTracer *trc, void *thing, JSGCTraceKind kind)
+{
+    NodeMap::AddPtr p = trc->nodemap.lookupForAdd(thing);
+    if (!p) {
+        VerifyNode *node = (VerifyNode *)trc->edgeptr;
+        trc->edgeptr += sizeof(VerifyNode) - sizeof(EdgeValue);
+        if (trc->edgeptr >= trc->term) {
+            trc->edgeptr = trc->term;
+            return NULL;
+        }
+
+        node->thing = thing;
+        node->count = 0;
+        node->kind = kind;
+        trc->nodemap.add(p, thing, node);
+        return node;
+    }
+    return NULL;
+}
+
+static VerifyNode *
+NextNode(VerifyNode *node)
+{
+    if (node->count == 0)
+        return (VerifyNode *)((char *)node + sizeof(VerifyNode) - sizeof(EdgeValue));
+    else
+        return (VerifyNode *)((char *)node + sizeof(VerifyNode) +
+                             sizeof(EdgeValue)*(node->count - 1));
+}
+
+void
+gc::StartVerifyPreBarriers(JSRuntime *rt)
+{
+    if (rt->gcVerifyPreData ||
+        rt->gcIncrementalState != NO_INCREMENTAL ||
+        !IsIncrementalGCSafe(rt))
+    {
+        return;
+    }
+
+    AutoPrepareForTracing prep(rt);
+
+    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
+        r.front()->bitmap.clear();
+
+    VerifyPreTracer *trc = js_new<VerifyPreTracer>();
+
+    rt->gcNumber++;
+    trc->number = rt->gcNumber;
+    trc->count = 0;
+
+    JS_TracerInit(trc, rt, AccumulateEdge);
+
+    const size_t size = 64 * 1024 * 1024;
+    trc->root = (VerifyNode *)js_malloc(size);
+    JS_ASSERT(trc->root);
+    trc->edgeptr = (char *)trc->root;
+    trc->term = trc->edgeptr + size;
+
+    if (!trc->nodemap.init())
+        return;
+
+    /* Create the root node. */
+    trc->curnode = MakeNode(trc, NULL, JSGCTraceKind(0));
+
+    /* We want MarkRuntime to save the roots to gcSavedRoots. */
+    rt->gcIncrementalState = MARK_ROOTS;
+
+    /* Make all the roots be edges emanating from the root node. */
+    MarkRuntime(trc);
+
+    VerifyNode *node = trc->curnode;
+    if (trc->edgeptr == trc->term)
+        goto oom;
+
+    /* For each edge, make a node for it if one doesn't already exist. */
+    while ((char *)node < trc->edgeptr) {
+        for (uint32_t i = 0; i < node->count; i++) {
+            EdgeValue &e = node->edges[i];
+            VerifyNode *child = MakeNode(trc, e.thing, e.kind);
+            if (child) {
+                trc->curnode = child;
+                JS_TraceChildren(trc, e.thing, e.kind);
+            }
+            if (trc->edgeptr == trc->term)
+                goto oom;
+        }
+
+        node = NextNode(node);
+    }
+
+    rt->gcVerifyPreData = trc;
+    rt->gcIncrementalState = MARK;
+    rt->gcMarker.start(rt);
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        PurgeJITCaches(c);
+        c->setNeedsBarrier(true, JSCompartment::UpdateIon);
+        c->arenas.purge();
+    }
+
+    return;
+
+oom:
+    rt->gcIncrementalState = NO_INCREMENTAL;
+    trc->~VerifyPreTracer();
+    js_free(trc);
+}
+
+static bool
+IsMarkedOrAllocated(Cell *cell)
+{
+    return cell->isMarked() || cell->arenaHeader()->allocatedDuringIncremental;
+}
+
+const static uint32_t MAX_VERIFIER_EDGES = 1000;
+
+/*
+ * This function is called by EndVerifyBarriers for every heap edge. If the edge
+ * already existed in the original snapshot, we "cancel it out" by overwriting
+ * it with NULL. EndVerifyBarriers later asserts that the remaining non-NULL
+ * edges (i.e., the ones from the original snapshot that must have been
+ * modified) must point to marked objects.
+ */
+static void
+CheckEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
+{
+    VerifyPreTracer *trc = (VerifyPreTracer *)jstrc;
+    VerifyNode *node = trc->curnode;
+
+    /* Avoid n^2 behavior. */
+    if (node->count > MAX_VERIFIER_EDGES)
+        return;
+
+    for (uint32_t i = 0; i < node->count; i++) {
+        if (node->edges[i].thing == *thingp) {
+            JS_ASSERT(node->edges[i].kind == kind);
+            node->edges[i].thing = NULL;
+            return;
+        }
+    }
+}
+
+static void
+AssertMarkedOrAllocated(const EdgeValue &edge)
+{
+    if (!edge.thing || IsMarkedOrAllocated(static_cast<Cell *>(edge.thing)))
+        return;
+
+    char msgbuf[1024];
+    const char *label = edge.label ? edge.label : "<unknown>";
+
+    JS_snprintf(msgbuf, sizeof(msgbuf), "[barrier verifier] Unmarked edge: %s", label);
+    MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
+    MOZ_CRASH();
+}
+
+void
+gc::EndVerifyPreBarriers(JSRuntime *rt)
+{
+    AutoPrepareForTracing prep(rt);
+
+    VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData;
+
+    if (!trc)
+        return;
+
+    bool compartmentCreated = false;
+
+    /* We need to disable barriers before tracing, which may invoke barriers. */
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        if (!c->needsBarrier())
+            compartmentCreated = true;
+
+        PurgeJITCaches(c);
+        c->setNeedsBarrier(false, JSCompartment::UpdateIon);
+    }
+
+    /*
+     * We need to bump gcNumber so that the methodjit knows that jitcode has
+     * been discarded.
+     */
+    JS_ASSERT(trc->number == rt->gcNumber);
+    rt->gcNumber++;
+
+    rt->gcVerifyPreData = NULL;
+    rt->gcIncrementalState = NO_INCREMENTAL;
+
+    if (!compartmentCreated && IsIncrementalGCSafe(rt)) {
+        JS_TracerInit(trc, rt, CheckEdge);
+
+        /* Start after the roots. */
+        VerifyNode *node = NextNode(trc->root);
+        while ((char *)node < trc->edgeptr) {
+            trc->curnode = node;
+            JS_TraceChildren(trc, node->thing, node->kind);
+
+            if (node->count <= MAX_VERIFIER_EDGES) {
+                for (uint32_t i = 0; i < node->count; i++)
+                    AssertMarkedOrAllocated(node->edges[i]);
+            }
+
+            node = NextNode(node);
+        }
+    }
+
+    rt->gcMarker.reset();
+    rt->gcMarker.stop();
+
+    trc->~VerifyPreTracer();
+    js_free(trc);
+}
+
+/*** Post-Barrier Verifyier ***/
+
+struct VerifyPostTracer : JSTracer {
+    /* The gcNumber when the verification began. */
+    uint64_t number;
+
+    /* This counts up to gcZealFrequency to decide whether to verify. */
+    int count;
+};
+
+/*
+ * The post-barrier verifier runs the full store buffer and a fake nursery when
+ * running and when it stops, walks the full heap to ensure that all the
+ * important edges were inserted into the storebuffer.
+ */
+void
+gc::StartVerifyPostBarriers(JSRuntime *rt)
+{
+#ifdef JSGC_GENERATIONAL
+    if (!rt->gcExactScanningEnabled ||
+        rt->gcVerifyPostData ||
+        rt->gcIncrementalState != NO_INCREMENTAL)
+    {
+        return;
+    }
+    VerifyPostTracer *trc = js_new<VerifyPostTracer>();
+    rt->gcVerifyPostData = trc;
+    rt->gcNumber++;
+    trc->number = rt->gcNumber;
+    trc->count = 0;
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        if (IsAtomsCompartment(c))
+            continue;
+
+        if (!c->gcNursery.enable())
+            goto oom;
+
+        if (!c->gcStoreBuffer.enable())
+            goto oom;
+    }
+    return;
+oom:
+    trc->~VerifyPostTracer();
+    js_free(trc);
+    rt->gcVerifyPostData = NULL;
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        c->gcNursery.disable();
+        c->gcStoreBuffer.disable();
+    }
+#endif
+}
+
+#ifdef JSGC_GENERATIONAL
+static void
+AssertStoreBufferContainsEdge(StoreBuffer *storebuf, void *loc, void *dst)
+{
+    if (storebuf->containsEdgeAt(loc))
+        return;
+
+    char msgbuf[1024];
+    JS_snprintf(msgbuf, sizeof(msgbuf), "[post-barrier verifier] Missing edge @ %p to %p",
+                loc, dst);
+    MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
+    MOZ_CRASH();
+}
+
+void
+gc::PostVerifierVisitEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
+{
+    VerifyPostTracer *trc = (VerifyPostTracer *)jstrc;
+    Cell *dst = (Cell *)*thingp;
+    JSCompartment *comp = dst->compartment();
+
+    /*
+     * Note: watchpoint markAll will give us cross-compartment pointers into the
+     * atoms compartment.
+     */
+    if (IsAtomsCompartment(comp))
+        return;
+
+    /* Filter out non cross-generational edges. */
+    if (!comp->gcNursery.isInside(dst))
+        return;
+
+    /*
+     * Note: since Value travels through the stack to get Cell**, we need to use
+     * the annotated location in the tracer instead of the indirect location for
+     * these edges.
+     */
+    Cell *loc = (Cell *)(trc->realLocation != NULL ? trc->realLocation : thingp);
+
+    AssertStoreBufferContainsEdge(&comp->gcStoreBuffer, loc, dst);
+}
+#endif
+
+void
+js::gc::EndVerifyPostBarriers(JSRuntime *rt)
+{
+#ifdef JSGC_GENERATIONAL
+    AutoPrepareForTracing prep(rt);
+
+    VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData;
+    JS_TracerInit(trc, rt, PostVerifierVisitEdge);
+    trc->count = 0;
+
+    if (!rt->gcExactScanningEnabled)
+        goto oom;
+
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        if (c->gcStoreBuffer.hasOverflowed())
+            continue;
+        if (!c->gcStoreBuffer.coalesceForVerification())
+            goto oom;
+    }
+
+    /* Walk the heap. */
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        if (!c->gcStoreBuffer.isEnabled() ||
+             c->gcStoreBuffer.hasOverflowed() ||
+             IsAtomsCompartment(c))
+        {
+            continue;
+        }
+
+        if (c->watchpointMap)
+            c->watchpointMap->markAll(trc);
+
+        for (size_t kind = 0; kind < FINALIZE_LIMIT; ++kind) {
+            for (CellIterUnderGC cells(c, AllocKind(kind)); !cells.done(); cells.next()) {
+                Cell *src = cells.getCell();
+                if (!c->gcNursery.isInside(src))
+                    JS_TraceChildren(trc, src, MapAllocToTraceKind(AllocKind(kind)));
+            }
+        }
+    }
+
+oom:
+    trc->~VerifyPostTracer();
+    js_free(trc);
+    rt->gcVerifyPostData = NULL;
+    for (CompartmentsIter c(rt); !c.done(); c.next()) {
+        c->gcNursery.disable();
+        c->gcStoreBuffer.disable();
+        c->gcStoreBuffer.releaseVerificationData();
+    }
+#endif
+}
+
+/*** Barrier Verifier Scheduling ***/
+
+static void
+VerifyPreBarriers(JSRuntime *rt)
+{
+    if (rt->gcVerifyPreData)
+        EndVerifyPreBarriers(rt);
+    else
+        StartVerifyPreBarriers(rt);
+}
+
+static void
+VerifyPostBarriers(JSRuntime *rt)
+{
+    if (rt->gcVerifyPostData)
+        EndVerifyPostBarriers(rt);
+    else
+        StartVerifyPostBarriers(rt);
+}
+
+void
+gc::VerifyBarriers(JSRuntime *rt, VerifierType type)
+{
+    if (type == PreBarrierVerifier)
+        VerifyPreBarriers(rt);
+    else
+        VerifyPostBarriers(rt);
+}
+
+static void
+MaybeVerifyPreBarriers(JSRuntime *rt, bool always)
+{
+    if (rt->gcZeal() != ZealVerifierPreValue)
+        return;
+
+    if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
+        if (++trc->count < rt->gcZealFrequency && !always)
+            return;
+
+        EndVerifyPreBarriers(rt);
+    }
+    StartVerifyPreBarriers(rt);
+}
+
+static void
+MaybeVerifyPostBarriers(JSRuntime *rt, bool always)
+{
+    if (rt->gcZeal() != ZealVerifierPostValue)
+        return;
+
+    if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
+        if (++trc->count < rt->gcZealFrequency && !always)
+            return;
+
+        EndVerifyPostBarriers(rt);
+    }
+    StartVerifyPostBarriers(rt);
+}
+
+void
+js::gc::MaybeVerifyBarriers(JSContext *cx, bool always)
+{
+    MaybeVerifyPreBarriers(cx->runtime, always);
+    MaybeVerifyPostBarriers(cx->runtime, always);
+}
+
+void
+js::gc::FinishVerifier(JSRuntime *rt)
+{
+    if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
+        trc->~VerifyPreTracer();
+        js_free(trc);
+    }
+#ifdef JSGC_GENERATIONAL
+    if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
+        trc->~VerifyPostTracer();
+        js_free(trc);
+        for (CompartmentsIter c(rt); !c.done(); c.next()) {
+            c->gcNursery.disable();
+            c->gcStoreBuffer.disable();
+        }
+    }
+#endif
+}
+
+#endif /* JS_GC_ZEAL */
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -24,18 +24,18 @@
 using namespace js;
 using namespace js::ion;
 
 using mozilla::DebugOnly;
 
 IonBuilder::IonBuilder(JSContext *cx, TempAllocator *temp, MIRGraph *graph,
                        TypeOracle *oracle, CompileInfo *info, size_t inliningDepth, uint32 loopDepth)
   : MIRGenerator(cx->compartment, temp, graph, info),
+    backgroundCodegen_(NULL),
     recompileInfo(cx->compartment->types.compiledInfo),
-    backgroundCodegen_(NULL),
     cx(cx),
     loopDepth_(loopDepth),
     callerResumePoint_(NULL),
     callerBuilder_(NULL),
     oracle(oracle),
     inliningDepth(inliningDepth),
     failedBoundsCheck_(info->script()->failedBoundsCheck),
     failedShapeGuard_(info->script()->failedShapeGuard),
@@ -5346,17 +5346,18 @@ IonBuilder::jsop_not()
     current->add(ins);
     current->push(ins);
     return true;
 }
 
 
 inline bool
 IonBuilder::TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types, HandleId id,
-                               JSFunction **funcp, bool isGetter, bool *isDOM)
+                               JSFunction **funcp, bool isGetter, bool *isDOM,
+                               MDefinition **guardOut)
 {
     JSObject *found = NULL;
     JSObject *foundProto = NULL;
 
     *funcp = NULL;
     *isDOM = false;
 
     bool thinkDOM = true;
@@ -5490,16 +5491,22 @@ IonBuilder::TestCommonPropFunc(JSContext
     // Add a shape guard on the prototype we found the property on. The rest of
     // the prototype chain is guarded by TI freezes. Note that a shape guard is
     // good enough here, even in the proxy case, because we have ensured there
     // are no lookup hooks for this property.
     MInstruction *wrapper = MConstant::New(ObjectValue(*foundProto));
     current->add(wrapper);
     wrapper = addShapeGuard(wrapper, foundProto->lastProperty(), Bailout_ShapeGuard);
 
+    // Pass the guard back so it can be an operand.
+    if (isGetter) {
+        JS_ASSERT(wrapper->isGuardShape());
+        *guardOut = wrapper;
+    }
+
     // Now we have to freeze all the property typesets to ensure there isn't a
     // lower shadowing getter or setter installed in the future.
     types::TypeObject *curType;
     for (unsigned i = 0; i < types->getObjectCount(); i++) {
         curType = types->getTypeObject(i);
         JSObject *obj = NULL;
         if (!curType) {
             obj = types->getSingleObject(i);
@@ -5952,32 +5959,36 @@ IonBuilder::getPropTryDefiniteSlot(bool 
 
 bool
 IonBuilder::getPropTryCommonGetter(bool *emitted, HandleId id, types::StackTypeSet *barrier,
                                    types::StackTypeSet *types, TypeOracle::UnaryTypes unaryTypes)
 {
     JS_ASSERT(*emitted == false);
     JSFunction *commonGetter;
     bool isDOM;
-
-    if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true, &isDOM))
+    MDefinition *guard;
+
+    if (!TestCommonPropFunc(cx, unaryTypes.inTypes, id, &commonGetter, true,
+                            &isDOM, &guard))
+    {
         return false;
+    }
     if (!commonGetter)
         return true;
 
     MDefinition *obj = current->pop();
     RootedFunction getter(cx, commonGetter);
 
     if (isDOM && TestShouldDOMCall(cx, unaryTypes.inTypes, getter)) {
         const JSJitInfo *jitinfo = getter->jitInfo();
-        MGetDOMProperty *get = MGetDOMProperty::New(jitinfo->op, obj, jitinfo->isInfallible);
+        MGetDOMProperty *get = MGetDOMProperty::New(jitinfo, obj, guard);
         current->add(get);
         current->push(get);
 
-        if (!resumeAfter(get))
+        if (get->isEffectful() && !resumeAfter(get))
             return false;
         if (!pushTypeBarrier(get, types, barrier))
             return false;
 
         *emitted = true;
         return true;
     }
 
@@ -6112,17 +6123,17 @@ IonBuilder::jsop_setprop(HandlePropertyN
         }
     }
 
     RootedId id(cx, NameToId(name));
     types::StackTypeSet *types = binaryTypes.lhsTypes;
 
     JSFunction *commonSetter;
     bool isDOM;
-    if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM))
+    if (!TestCommonPropFunc(cx, types, id, &commonSetter, false, &isDOM, NULL))
         return false;
     if (!monitored && commonSetter) {
         RootedFunction setter(cx, commonSetter);
         if (isDOM && TestShouldDOMCall(cx, types, setter)) {
             MSetDOMProperty *set = MSetDOMProperty::New(setter->jitInfo()->op, obj, value);
             if (!set)
                 return false;
 
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -418,17 +418,18 @@ class IonBuilder : public MIRGenerator
     bool makeInliningDecision(AutoObjectVector &targets, uint32 argc);
 
     MCall *makeCallHelper(HandleFunction target, uint32 argc, bool constructing);
     bool makeCallBarrier(HandleFunction target, uint32 argc, bool constructing,
                          types::StackTypeSet *types, types::StackTypeSet *barrier);
 
     inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types,
                                    HandleId id, JSFunction **funcp,
-                                   bool isGetter, bool *isDOM);
+                                   bool isGetter, bool *isDOM,
+                                   MDefinition **guardOut);
 
     bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
                                   types::StackTypeSet *objTypes, types::StackTypeSet *pushedTypes);
 
     MGetPropertyCache *checkInlineableGetPropertyCache(uint32_t argc);
 
     MPolyInlineDispatch *
     makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -4950,51 +4950,90 @@ class MSetDOMProperty
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
 };
 
 class MGetDOMProperty
-  : public MAryInstruction<1>,
+  : public MAryInstruction<2>,
     public ObjectPolicy<0>
 {
-    const JSJitPropertyOp func_;
-    bool isInfallible_;
-
-    MGetDOMProperty(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible)
-      : func_(func), isInfallible_(isInfallible)
+    const JSJitInfo *info_;
+
+    MGetDOMProperty(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard)
+      : info_(jitinfo)
     {
+        JS_ASSERT(jitinfo);
+
         initOperand(0, obj);
 
+        // Pin the guard as an operand if we want to hoist later
+        initOperand(1, guard);
+
+        // We are movable iff the jitinfo says we can be.
+        if (jitinfo->isConstant)
+            setMovable();
+
         setResultType(MIRType_Value);
     }
 
+  protected:
+    const JSJitInfo *info() const {
+        return info_;
+    }
+
   public:
     INSTRUCTION_HEADER(GetDOMProperty);
 
-    static MGetDOMProperty *New(const JSJitPropertyOp func, MDefinition *obj, bool isInfallible)
+    static MGetDOMProperty *New(const JSJitInfo *info, MDefinition *obj, MDefinition *guard)
     {
-        return new MGetDOMProperty(func, obj, isInfallible);
+        return new MGetDOMProperty(info, obj, guard);
     }
 
     const JSJitPropertyOp fun() {
-        return func_;
-    }
-    bool isInfallible() {
-        return isInfallible_;
+        return info_->op;
+    }
+    bool isInfallible() const {
+        return info_->isInfallible;
+    }
+    bool isDomConstant() const {
+        return info_->isConstant;
     }
     MDefinition *object() {
         return getOperand(0);
     }
 
     TypePolicy *typePolicy() {
         return this;
     }
+
+    bool congruentTo(MDefinition *const &ins) const {
+        if (!isDomConstant())
+            return false;
+
+        if (!ins->isGetDOMProperty())
+            return false;
+
+        // Checking the jitinfo is the same as checking the constant function
+        if (!(info() == ins->toGetDOMProperty()->info()))
+            return false;
+
+        return congruentIfOperandsEqual(ins);
+    }
+
+    AliasSet getAliasSet() const {
+        // The whole point of constancy is that it's non-effectful and doesn't
+        // conflict with anything
+        if (isDomConstant())
+            return AliasSet::None();
+        return AliasSet::Store(AliasSet::Any);
+    }
+
 };
 
 class MStringLength
   : public MUnaryInstruction,
     public StringPolicy
 {
     MStringLength(MDefinition *string)
       : MUnaryInstruction(string)
--- a/js/src/jsapi-tests/Makefile.in
+++ b/js/src/jsapi-tests/Makefile.in
@@ -27,52 +27,52 @@ CPPSRCS = \
   testCloneScript.cpp \
   testConservativeGC.cpp \
   testContexts.cpp \
   testCustomIterator.cpp \
   testDebugger.cpp \
   testDeepFreeze.cpp \
   testDefineGetterSetterNonEnumerable.cpp \
   testDefineProperty.cpp \
+  testEnclosingFunction.cpp \
+  testErrorCopying.cpp \
   testExtendedEq.cpp \
   testExternalStrings.cpp \
+  testFindSCCs.cpp \
   testFuncCallback.cpp \
   testFunctionProperties.cpp \
   testGCOutOfMemory.cpp \
   testOOM.cpp \
   testGetPropertyDefault.cpp \
   testHashTable.cpp \
   testIndexToString.cpp \
   testIntString.cpp \
   testIntTypesABI.cpp \
   testIntern.cpp \
+  testJSEvaluateScript.cpp \
   testLookup.cpp \
   testLooselyEqual.cpp \
   testNewObject.cpp \
   testOps.cpp \
   testOriginPrincipals.cpp \
   testParseJSON.cpp \
+  testProfileStrings.cpp \
   testPropCache.cpp \
   testRegExp.cpp \
   testResolveRecursion.cpp \
   testSameValue.cpp \
   testScriptInfo.cpp \
   testScriptObject.cpp \
   testSetProperty.cpp \
   testSourcePolicy.cpp \
   testStringBuffer.cpp \
   testTrap.cpp \
   testTypedArrays.cpp \
   testVersion.cpp \
   testXDR.cpp \
-  testProfileStrings.cpp \
-  testJSEvaluateScript.cpp \
-  testErrorCopying.cpp \
-  testEnclosingFunction.cpp \
-  testFindSCCs.cpp \
   $(NULL)
 
 # Disabled: an entirely unrelated test seems to cause this to fail.  Moreover,
 # given the test's dependence on interactions between the compiler, the GC, and
 # conservative stack scanning, the fix isn't obvious: more investigation
 # needed.
 #CPPSRCS += \
 #  testRegExpInstanceProperties.cpp \
--- a/js/src/jsapi-tests/testFindSCCs.cpp
+++ b/js/src/jsapi-tests/testFindSCCs.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=8 sw=4 et 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 "tests.h"
+
 #include <string.h>
 #include <stdarg.h>
 
 #include "../gc/FindSCCs.h"
 #include "jscntxt.h"
 #include "jsgc.h"
 
 static const unsigned MaxVertices = 10;
@@ -160,17 +161,17 @@ void run()
 bool group(int vertex, ...)
 {
     TestNode *v = (TestNode *)ComponentFinder::getNextGroup(resultsList);
 
     va_list ap;
     va_start(ap, vertex);
     while (vertex != -1) {
         CHECK(v != NULL);
-        CHECK(v->index == vertex);
+        CHECK(v->index == unsigned(vertex));
         v = (TestNode *)v->gcNextGraphNode;
         vertex = va_arg(ap, int);
     }
     va_end(ap);
 
     CHECK(v == NULL);
     return true;
 }
@@ -178,17 +179,17 @@ bool group(int vertex, ...)
 bool remaining(int vertex, ...)
 {
     TestNode *v = (TestNode *)ComponentFinder::getAllRemaining(resultsList);
 
     va_list ap;
     va_start(ap, vertex);
     while (vertex != -1) {
         CHECK(v != NULL);
-        CHECK(v->index == vertex);
+        CHECK(v->index == unsigned(vertex));
         v = (TestNode *)v->gcNextGraphNode;
         vertex = va_arg(ap, int);
     }
     va_end(ap);
 
     CHECK(v == NULL);
     return true;
 }
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -228,29 +228,29 @@ JS_GetEmptyString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
     return rt->emptyString;
 }
 
 static void
 AssertHeapIsIdle(JSRuntime *rt)
 {
-    JS_ASSERT(rt->heapState == JSRuntime::Idle);
+    JS_ASSERT(rt->heapState == js::Idle);
 }
 
 static void
 AssertHeapIsIdle(JSContext *cx)
 {
     AssertHeapIsIdle(cx->runtime);
 }
 
 static void
 AssertHeapIsIdleOrIterating(JSRuntime *rt)
 {
-    JS_ASSERT(rt->heapState != JSRuntime::Collecting);
+    JS_ASSERT(rt->heapState != js::Collecting);
 }
 
 static void
 AssertHeapIsIdleOrIterating(JSContext *cx)
 {
     AssertHeapIsIdleOrIterating(cx->runtime);
 }
 
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -760,27 +760,21 @@ struct JSRuntime : js::RuntimeFriendFiel
      * stuff. At various times we check this counter and, if it has changed, we
      * run an immediate, non-incremental GC to clean up the dead
      * compartments. This should happen very rarely.
      */
     unsigned            gcObjectsMarkedInDeadCompartments;
 
     bool                gcPoke;
 
-    enum HeapState {
-        Idle,       // doing nothing with the GC heap
-        Tracing,    // tracing the GC heap without collecting, e.g. IterateCompartments()
-        Collecting  // doing a GC of the heap
-    };
+    js::HeapState       heapState;
 
-    HeapState           heapState;
+    bool isHeapBusy() { return heapState != js::Idle; }
 
-    bool isHeapBusy() { return heapState != Idle; }
-
-    bool isHeapCollecting() { return heapState == Collecting; }
+    bool isHeapCollecting() { return heapState == js::Collecting; }
 
     /*
      * These options control the zealousness of the GC. The fundamental values
      * are gcNextScheduled and gcDebugCompartmentGC. At every allocation,
      * gcNextScheduled is decremented. When it reaches zero, we do either a
      * full or a compartmental GC, based on gcDebugCompartmentGC.
      *
      * At this point, if gcZeal_ is one of the types that trigger periodic
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -69,16 +69,17 @@
 #include "jswatchpoint.h"
 #include "jsweakmap.h"
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #include "builtin/MapObject.h"
 #include "frontend/Parser.h"
+#include "gc/GCInternals.h"
 #include "gc/Marking.h"
 #include "gc/Memory.h"
 #include "methodjit/MethodJIT.h"
 #include "vm/Debugger.h"
 #include "vm/String.h"
 #include "ion/IonCode.h"
 #ifdef JS_ION
 # include "ion/IonMacroAssembler.h"
@@ -119,33 +120,16 @@ using mozilla::DebugOnly;
 using mozilla::Maybe;
 
 /* Perform a Full GC every 20 seconds if MaybeGC is called */
 static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
 
 /* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
 static const int IGC_MARK_SLICE_MULTIPLIER = 2;
 
-#ifdef JS_GC_ZEAL
-static void
-StartVerifyPreBarriers(JSRuntime *rt);
-
-static void
-EndVerifyPreBarriers(JSRuntime *rt);
-
-static void
-StartVerifyPostBarriers(JSRuntime *rt);
-
-static void
-EndVerifyPostBarriers(JSRuntime *rt);
-
-static void
-FinishVerifier(JSRuntime *rt);
-#endif
-
 /* This array should be const, but that doesn't link right under GCC. */
 AllocKind gc::slotsToThingKind[] = {
     /* 0 */  FINALIZE_OBJECT0,  FINALIZE_OBJECT2,  FINALIZE_OBJECT2,  FINALIZE_OBJECT4,
     /* 4 */  FINALIZE_OBJECT4,  FINALIZE_OBJECT8,  FINALIZE_OBJECT8,  FINALIZE_OBJECT8,
     /* 8 */  FINALIZE_OBJECT8,  FINALIZE_OBJECT12, FINALIZE_OBJECT12, FINALIZE_OBJECT12,
     /* 12 */ FINALIZE_OBJECT12, FINALIZE_OBJECT16, FINALIZE_OBJECT16, FINALIZE_OBJECT16,
     /* 16 */ FINALIZE_OBJECT16
 };
@@ -928,359 +912,16 @@ js_InitGC(JSRuntime *rt, uint32_t maxbyt
     rt->setGCMaxMallocBytes(maxbytes);
 
 #ifndef JS_MORE_DETERMINISTIC
     rt->gcJitReleaseTime = PRMJ_Now() + JIT_SCRIPT_RELEASE_TYPES_INTERVAL;
 #endif
     return true;
 }
 
-static inline bool
-InFreeList(ArenaHeader *aheader, uintptr_t addr)
-{
-    if (!aheader->hasFreeThings())
-        return false;
-
-    FreeSpan firstSpan(aheader->getFirstFreeSpan());
-
-    for (const FreeSpan *span = &firstSpan;;) {
-        /* If the thing comes fore the current span, it's not free. */
-        if (addr < span->first)
-            return false;
-
-        /*
-         * If we find it inside the span, it's dead. We use here "<=" and not
-         * "<" even for the last span as we know that thing is inside the
-         * arena. Thus for the last span thing < span->end.
-         */
-        if (addr <= span->last)
-            return true;
-
-        /*
-         * The last possible empty span is an the end of the arena. Here
-         * span->end < thing < thingsEnd and so we must have more spans.
-         */
-        span = span->nextSpan();
-    }
-}
-
-#ifdef JSGC_USE_EXACT_ROOTING
-static inline void
-MarkExactStackRooter(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
-{
-    void **addr = (void **)rooter->address();
-    if (!*addr)
-        return;
-
-    switch (kind) {
-      case THING_ROOT_OBJECT:      MarkObjectRoot(trc, (JSObject **)addr, "exact-object"); break;
-      case THING_ROOT_STRING:      MarkStringRoot(trc, (JSSTring **)addr, "exact-string"); break;
-      case THING_ROOT_SCRIPT:      MarkScriptRoot(trc, (JSScript **)addr, "exact-script"); break;
-      case THING_ROOT_SHAPE:       MarkShapeRoot(trc, (Shape **)addr, "exact-shape"); break;
-      case THING_ROOT_BASE_SHAPE:  MarkBaseShapeRoot(trc, (BaseShape **)addr, "exact-baseshape"); break;
-      case THING_ROOT_TYPE:        MarkTypeRoot(trc, (types::Type *)addr, "exact-type"); break;
-      case THING_ROOT_TYPE_OBJECT: MarkTypeObjectRoot(trc, (types::TypeObject **)addr, "exact-typeobject"); break;
-      case THING_ROOT_VALUE:       MarkValueRoot(trc, (Value *)addr, "exact-value"); break;
-      case THING_ROOT_ID:          MarkIdRoot(trc, (jsid *)addr, "exact-id"); break;
-      case THING_ROOT_PROPERTY_ID: MarkIdRoot(trc, &((js::PropertyId *)addr)->asId(), "exact-propertyid"); break;
-      case THING_ROOT_BINDINGS:    ((Bindings *)addr)->trace(trc); break;
-      default: JS_NOT_REACHED("Invalid THING_ROOT kind"); break;
-    }
-}
-
-static inline void
-MarkExactStackRooters(JSTracer *trc, Rooted<void*> rooter, ThingRootKind kind)
-{
-    Rooted<void*> *rooter = cx->thingGCRooters[i];
-    while (rooter) {
-        MarkExactStackRoot(trc, rooter, ThingRootKind(i));
-        rooter = rooter->previous();
-    }
-}
-
-static void
-MarkExactStackRoots(JSTracer *trc)
-{
-    for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
-        for (ContextIter cx(trc->runtime); !cx.done(); cx.next()) {
-            MarkExactStackRooters(trc, cx->thingGCRooters[i], ThingRootKind(i));
-        }
-        MarkExactStackRooters(trc, rt->mainThread.thingGCRooters[i], ThingRootKind(i));
-    }
-}
-#endif /* JSGC_USE_EXACT_ROOTING */
-
-enum ConservativeGCTest
-{
-    CGCT_VALID,
-    CGCT_LOWBITSET, /* excluded because one of the low bits was set */
-    CGCT_NOTARENA,  /* not within arena range in a chunk */
-    CGCT_OTHERCOMPARTMENT,  /* in another compartment */
-    CGCT_NOTCHUNK,  /* not within a valid chunk */
-    CGCT_FREEARENA, /* within arena containing only free things */
-    CGCT_NOTLIVE,   /* gcthing is not allocated */
-    CGCT_END
-};
-
-/*
- * Tests whether w is a (possibly dead) GC thing. Returns CGCT_VALID and
- * details about the thing if so. On failure, returns the reason for rejection.
- */
-static inline ConservativeGCTest
-IsAddressableGCThing(JSRuntime *rt, uintptr_t w,
-                     bool skipUncollectedCompartments,
-                     gc::AllocKind *thingKindPtr,
-                     ArenaHeader **arenaHeader,
-                     void **thing)
-{
-    /*
-     * We assume that the compiler never uses sub-word alignment to store
-     * pointers and does not tag pointers on its own. Additionally, the value
-     * representation for all values and the jsid representation for GC-things
-     * do not touch the low two bits. Thus any word with the low two bits set
-     * is not a valid GC-thing.
-     */
-    JS_STATIC_ASSERT(JSID_TYPE_STRING == 0 && JSID_TYPE_OBJECT == 4);
-    if (w & 0x3)
-        return CGCT_LOWBITSET;
-
-    /*
-     * An object jsid has its low bits tagged. In the value representation on
-     * 64-bit, the high bits are tagged.
-     */
-    const uintptr_t JSID_PAYLOAD_MASK = ~uintptr_t(JSID_TYPE_MASK);
-#if JS_BITS_PER_WORD == 32
-    uintptr_t addr = w & JSID_PAYLOAD_MASK;
-#elif JS_BITS_PER_WORD == 64
-    uintptr_t addr = w & JSID_PAYLOAD_MASK & JSVAL_PAYLOAD_MASK;
-#endif
-
-    Chunk *chunk = Chunk::fromAddress(addr);
-
-    if (!rt->gcChunkSet.has(chunk))
-        return CGCT_NOTCHUNK;
-
-    /*
-     * We query for pointers outside the arena array after checking for an
-     * allocated chunk. Such pointers are rare and we want to reject them
-     * after doing more likely rejections.
-     */
-    if (!Chunk::withinArenasRange(addr))
-        return CGCT_NOTARENA;
-
-    /* If the arena is not currently allocated, don't access the header. */
-    size_t arenaOffset = Chunk::arenaIndex(addr);
-    if (chunk->decommittedArenas.get(arenaOffset))
-        return CGCT_FREEARENA;
-
-    ArenaHeader *aheader = &chunk->arenas[arenaOffset].aheader;
-
-    if (!aheader->allocated())
-        return CGCT_FREEARENA;
-
-    if (skipUncollectedCompartments && !aheader->compartment->isCollecting())
-        return CGCT_OTHERCOMPARTMENT;
-
-    AllocKind thingKind = aheader->getAllocKind();
-    uintptr_t offset = addr & ArenaMask;
-    uintptr_t minOffset = Arena::firstThingOffset(thingKind);
-    if (offset < minOffset)
-        return CGCT_NOTARENA;
-
-    /* addr can point inside the thing so we must align the address. */
-    uintptr_t shift = (offset - minOffset) % Arena::thingSize(thingKind);
-    addr -= shift;
-
-    if (thing)
-        *thing = reinterpret_cast<void *>(addr);
-    if (arenaHeader)
-        *arenaHeader = aheader;
-    if (thingKindPtr)
-        *thingKindPtr = thingKind;
-    return CGCT_VALID;
-}
-
-/*
- * Returns CGCT_VALID and mark it if the w can be a  live GC thing and sets
- * thingKind accordingly. Otherwise returns the reason for rejection.
- */
-static inline ConservativeGCTest
-MarkIfGCThingWord(JSTracer *trc, uintptr_t w)
-{
-    void *thing;
-    ArenaHeader *aheader;
-    AllocKind thingKind;
-    ConservativeGCTest status =
-        IsAddressableGCThing(trc->runtime, w, IS_GC_MARKING_TRACER(trc),
-                             &thingKind, &aheader, &thing);
-    if (status != CGCT_VALID)
-        return status;
-
-    /*
-     * Check if the thing is free. We must use the list of free spans as at
-     * this point we no longer have the mark bits from the previous GC run and
-     * we must account for newly allocated things.
-     */
-    if (InFreeList(aheader, uintptr_t(thing)))
-        return CGCT_NOTLIVE;
-
-    JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind);
-#ifdef DEBUG
-    const char pattern[] = "machine_stack %p";
-    char nameBuf[sizeof(pattern) - 2 + sizeof(thing) * 2];
-    JS_snprintf(nameBuf, sizeof(nameBuf), pattern, thing);
-    JS_SET_TRACING_NAME(trc, nameBuf);
-#endif
-    JS_SET_TRACING_LOCATION(trc, (void *)w);
-    void *tmp = thing;
-    MarkKind(trc, &tmp, traceKind);
-    JS_ASSERT(tmp == thing);
-
-#ifdef DEBUG
-    if (trc->runtime->gcIncrementalState == MARK_ROOTS)
-        trc->runtime->mainThread.gcSavedRoots.append(
-            PerThreadData::SavedGCRoot(thing, traceKind));
-#endif
-
-    return CGCT_VALID;
-}
-
-static void
-MarkWordConservatively(JSTracer *trc, uintptr_t w)
-{
-    /*
-     * The conservative scanner may access words that valgrind considers as
-     * undefined. To avoid false positives and not to alter valgrind view of
-     * the memory we make as memcheck-defined the argument, a copy of the
-     * original word. See bug 572678.
-     */
-#ifdef JS_VALGRIND
-    JS_SILENCE_UNUSED_VALUE_IN_EXPR(VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w)));
-#endif
-
-    MarkIfGCThingWord(trc, w);
-}
-
-MOZ_ASAN_BLACKLIST
-static void
-MarkRangeConservatively(JSTracer *trc, const uintptr_t *begin, const uintptr_t *end)
-{
-    JS_ASSERT(begin <= end);
-    for (const uintptr_t *i = begin; i < end; ++i)
-        MarkWordConservatively(trc, *i);
-}
-
-#ifndef JSGC_USE_EXACT_ROOTING
-static void
-MarkRangeConservativelyAndSkipIon(JSTracer *trc, JSRuntime *rt, const uintptr_t *begin, const uintptr_t *end)
-{
-    const uintptr_t *i = begin;
-
-#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
-    // Walk only regions in between Ion activations. Note that non-volatile
-    // registers are spilled to the stack before the entry Ion frame, ensuring
-    // that the conservative scanner will still see them.
-    for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
-        uintptr_t *ionMin, *ionEnd;
-        ion.ionStackRange(ionMin, ionEnd);
-
-        MarkRangeConservatively(trc, i, ionMin);
-        i = ionEnd;
-    }
-#endif
-
-    // Mark everything after the most recent Ion activation.
-    MarkRangeConservatively(trc, i, end);
-}
-
-static JS_NEVER_INLINE void
-MarkConservativeStackRoots(JSTracer *trc, bool useSavedRoots)
-{
-    JSRuntime *rt = trc->runtime;
-
-#ifdef DEBUG
-    if (useSavedRoots) {
-        for (PerThreadData::SavedGCRoot *root = rt->mainThread.gcSavedRoots.begin();
-             root != rt->mainThread.gcSavedRoots.end();
-             root++)
-        {
-            JS_SET_TRACING_NAME(trc, "cstack");
-            MarkKind(trc, &root->thing, root->kind);
-        }
-        return;
-    }
-
-    if (rt->gcIncrementalState == MARK_ROOTS)
-        rt->mainThread.gcSavedRoots.clearAndFree();
-#endif
-
-    ConservativeGCData *cgcd = &rt->conservativeGC;
-    if (!cgcd->hasStackToScan()) {
-#ifdef JS_THREADSAFE
-        JS_ASSERT(!rt->requestDepth);
-#endif
-        return;
-    }
-
-    uintptr_t *stackMin, *stackEnd;
-#if JS_STACK_GROWTH_DIRECTION > 0
-    stackMin = rt->nativeStackBase;
-    stackEnd = cgcd->nativeStackTop;
-#else
-    stackMin = cgcd->nativeStackTop + 1;
-    stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
-#endif
-
-    JS_ASSERT(stackMin <= stackEnd);
-    MarkRangeConservativelyAndSkipIon(trc, rt, stackMin, stackEnd);
-    MarkRangeConservatively(trc, cgcd->registerSnapshot.words,
-                            ArrayEnd(cgcd->registerSnapshot.words));
-}
-
-#endif /* JSGC_USE_EXACT_ROOTING */
-
-void
-js::MarkStackRangeConservatively(JSTracer *trc, Value *beginv, Value *endv)
-{
-    const uintptr_t *begin = beginv->payloadUIntPtr();
-    const uintptr_t *end = endv->payloadUIntPtr();
-#ifdef JS_NUNBOX32
-    /*
-     * With 64-bit jsvals on 32-bit systems, we can optimize a bit by
-     * scanning only the payloads.
-     */
-    JS_ASSERT(begin <= end);
-    for (const uintptr_t *i = begin; i < end; i += sizeof(Value) / sizeof(uintptr_t))
-        MarkWordConservatively(trc, *i);
-#else
-    MarkRangeConservatively(trc, begin, end);
-#endif
-}
-
-JS_NEVER_INLINE void
-ConservativeGCData::recordStackTop()
-{
-    /* Update the native stack pointer if it points to a bigger stack. */
-    uintptr_t dummy;
-    nativeStackTop = &dummy;
-
-    /*
-     * To record and update the register snapshot for the conservative scanning
-     * with the latest values we use setjmp.
-     */
-#if defined(_MSC_VER)
-# pragma warning(push)
-# pragma warning(disable: 4611)
-#endif
-    (void) setjmp(registerSnapshot.jmpbuf);
-#if defined(_MSC_VER)
-# pragma warning(pop)
-#endif
-}
-
 static void
 RecordNativeStackTopForGC(JSRuntime *rt)
 {
     ConservativeGCData *cgcd = &rt->conservativeGC;
 
 #ifdef JS_THREADSAFE
     /* Record the stack top here only if we are called from a request. */
     if (!rt->requestDepth)
@@ -2179,424 +1820,16 @@ js::SetMarkStackLimit(JSRuntime *rt, siz
 }
 
 void
 js::MarkCompartmentActive(StackFrame *fp)
 {
     fp->script()->compartment()->active = true;
 }
 
-void
-AutoIdArray::trace(JSTracer *trc)
-{
-    JS_ASSERT(tag == IDARRAY);
-    gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
-}
-
-inline void
-AutoGCRooter::trace(JSTracer *trc)
-{
-    switch (tag) {
-      case JSVAL:
-        MarkValueRoot(trc, &static_cast<AutoValueRooter *>(this)->val, "JS::AutoValueRooter.val");
-        return;
-
-      case PARSER:
-        static_cast<frontend::Parser *>(this)->trace(trc);
-        return;
-
-      case IDARRAY: {
-        JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
-        MarkIdRange(trc, ida->length, ida->vector, "JS::AutoIdArray.idArray");
-        return;
-      }
-
-      case DESCRIPTORS: {
-        PropDescArray &descriptors =
-            static_cast<AutoPropDescArrayRooter *>(this)->descriptors;
-        for (size_t i = 0, len = descriptors.length(); i < len; i++) {
-            PropDesc &desc = descriptors[i];
-            MarkValueRoot(trc, &desc.pd_, "PropDesc::pd_");
-            MarkValueRoot(trc, &desc.value_, "PropDesc::value_");
-            MarkValueRoot(trc, &desc.get_, "PropDesc::get_");
-            MarkValueRoot(trc, &desc.set_, "PropDesc::set_");
-        }
-        return;
-      }
-
-      case DESCRIPTOR : {
-        PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
-        if (desc.obj)
-            MarkObjectRoot(trc, &desc.obj, "Descriptor::obj");
-        MarkValueRoot(trc, &desc.value, "Descriptor::value");
-        if ((desc.attrs & JSPROP_GETTER) && desc.getter) {
-            JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter);
-            MarkObjectRoot(trc, &tmp, "Descriptor::get");
-            desc.getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, tmp);
-        }
-        if (desc.attrs & JSPROP_SETTER && desc.setter) {
-            JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter);
-            MarkObjectRoot(trc, &tmp, "Descriptor::set");
-            desc.setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
-        }
-        return;
-      }
-
-#if JS_HAS_XML_SUPPORT
-      case NAMESPACES: {
-        JSXMLArray<JSObject> &array = static_cast<AutoNamespaceArray *>(this)->array;
-        MarkObjectRange(trc, array.length, array.vector, "JSXMLArray.vector");
-        js_XMLArrayCursorTrace(trc, array.cursors);
-        return;
-      }
-
-      case XML:
-        js_TraceXML(trc, static_cast<AutoXMLRooter *>(this)->xml);
-        return;
-#endif
-
-      case OBJECT:
-        if (static_cast<AutoObjectRooter *>(this)->obj)
-            MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj,
-                           "JS::AutoObjectRooter.obj");
-        return;
-
-      case ID:
-        MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
-        return;
-
-      case VALVECTOR: {
-        AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
-        MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
-        return;
-      }
-
-      case STRING:
-        if (static_cast<AutoStringRooter *>(this)->str)
-            MarkStringRoot(trc, &static_cast<AutoStringRooter *>(this)->str,
-                           "JS::AutoStringRooter.str");
-        return;
-
-      case IDVECTOR: {
-        AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
-        MarkIdRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
-        return;
-      }
-
-      case SHAPEVECTOR: {
-        AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
-        MarkShapeRootRange(trc, vector.length(), const_cast<Shape **>(vector.begin()),
-                           "js::AutoShapeVector.vector");
-        return;
-      }
-
-      case OBJVECTOR: {
-        AutoObjectVector::VectorImpl &vector = static_cast<AutoObjectVector *>(this)->vector;
-        MarkObjectRootRange(trc, vector.length(), vector.begin(), "js::AutoObjectVector.vector");
-        return;
-      }
-
-      case STRINGVECTOR: {
-        AutoStringVector::VectorImpl &vector = static_cast<AutoStringVector *>(this)->vector;
-        MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoStringVector.vector");
-        return;
-      }
-
-      case NAMEVECTOR: {
-        AutoNameVector::VectorImpl &vector = static_cast<AutoNameVector *>(this)->vector;
-        MarkStringRootRange(trc, vector.length(), vector.begin(), "js::AutoNameVector.vector");
-        return;
-      }
-
-      case VALARRAY: {
-        AutoValueArray *array = static_cast<AutoValueArray *>(this);
-        MarkValueRootRange(trc, array->length(), array->start(), "js::AutoValueArray");
-        return;
-      }
-
-      case SCRIPTVECTOR: {
-        AutoScriptVector::VectorImpl &vector = static_cast<AutoScriptVector *>(this)->vector;
-        for (size_t i = 0; i < vector.length(); i++)
-            MarkScriptRoot(trc, &vector[i], "AutoScriptVector element");
-        return;
-      }
-
-      case PROPDESC: {
-        PropDesc::AutoRooter *rooter = static_cast<PropDesc::AutoRooter *>(this);
-        MarkValueRoot(trc, &rooter->pd->pd_, "PropDesc::AutoRooter pd");
-        MarkValueRoot(trc, &rooter->pd->value_, "PropDesc::AutoRooter value");
-        MarkValueRoot(trc, &rooter->pd->get_, "PropDesc::AutoRooter get");
-        MarkValueRoot(trc, &rooter->pd->set_, "PropDesc::AutoRooter set");
-        return;
-      }
-
-      case SHAPERANGE: {
-        Shape::Range::AutoRooter *rooter = static_cast<Shape::Range::AutoRooter *>(this);
-        rooter->trace(trc);
-        return;
-      }
-
-      case STACKSHAPE: {
-        StackShape::AutoRooter *rooter = static_cast<StackShape::AutoRooter *>(this);
-        if (rooter->shape->base)
-            MarkBaseShapeRoot(trc, (BaseShape**) &rooter->shape->base, "StackShape::AutoRooter base");
-        MarkIdRoot(trc, (jsid*) &rooter->shape->propid, "StackShape::AutoRooter id");
-        return;
-      }
-
-      case STACKBASESHAPE: {
-        StackBaseShape::AutoRooter *rooter = static_cast<StackBaseShape::AutoRooter *>(this);
-        if (rooter->base->parent)
-            MarkObjectRoot(trc, (JSObject**) &rooter->base->parent, "StackBaseShape::AutoRooter parent");
-        if ((rooter->base->flags & BaseShape::HAS_GETTER_OBJECT) && rooter->base->rawGetter) {
-            MarkObjectRoot(trc, (JSObject**) &rooter->base->rawGetter,
-                           "StackBaseShape::AutoRooter getter");
-        }
-        if ((rooter->base->flags & BaseShape::HAS_SETTER_OBJECT) && rooter->base->rawSetter) {
-            MarkObjectRoot(trc, (JSObject**) &rooter->base->rawSetter,
-                           "StackBaseShape::AutoRooter setter");
-        }
-        return;
-      }
-
-      case GETTERSETTER: {
-        AutoRooterGetterSetter::Inner *rooter = static_cast<AutoRooterGetterSetter::Inner *>(this);
-        if ((rooter->attrs & JSPROP_GETTER) && *rooter->pgetter)
-            MarkObjectRoot(trc, (JSObject**) rooter->pgetter, "AutoRooterGetterSetter getter");
-        if ((rooter->attrs & JSPROP_SETTER) && *rooter->psetter)
-            MarkObjectRoot(trc, (JSObject**) rooter->psetter, "AutoRooterGetterSetter setter");
-        return;
-      }
-
-      case REGEXPSTATICS: {
-          /*
-        RegExpStatics::AutoRooter *rooter = static_cast<RegExpStatics::AutoRooter *>(this);
-        rooter->trace(trc);
-          */
-        return;
-      }
-
-      case HASHABLEVALUE: {
-          /*
-        HashableValue::AutoRooter *rooter = static_cast<HashableValue::AutoRooter *>(this);
-        rooter->trace(trc);
-          */
-        return;
-      }
-
-      case IONMASM: {
-#ifdef JS_ION
-        static_cast<js::ion::MacroAssembler::AutoRooter *>(this)->masm()->trace(trc);
-#endif
-        return;
-      }
-
-      case IONALLOC: {
-#ifdef JS_ION
-        static_cast<js::ion::AutoTempAllocatorRooter *>(this)->trace(trc);
-#endif
-        return;
-      }
-
-      case WRAPPER: {
-        /*
-         * We need to use MarkValueUnbarriered here because we mark wrapper
-         * roots in every slice. This is because of some rule-breaking in
-         * RemapAllWrappersForObject; see comment there.
-         */
-          MarkValueUnbarriered(trc, &static_cast<AutoWrapperRooter *>(this)->value.get(),
-                               "JS::AutoWrapperRooter.value");
-        return;
-      }
-
-      case WRAPVECTOR: {
-        AutoWrapperVector::VectorImpl &vector = static_cast<AutoWrapperVector *>(this)->vector;
-        /*
-         * We need to use MarkValueUnbarriered here because we mark wrapper
-         * roots in every slice. This is because of some rule-breaking in
-         * RemapAllWrappersForObject; see comment there.
-         */
-        for (WrapperValue *p = vector.begin(); p < vector.end(); p++)
-            MarkValueUnbarriered(trc, &p->get(), "js::AutoWrapperVector.vector");
-        return;
-      }
-    }
-
-    JS_ASSERT(tag >= 0);
-    MarkValueRootRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array,
-                       "JS::AutoArrayRooter.array");
-}
-
-/* static */ void
-AutoGCRooter::traceAll(JSTracer *trc)
-{
-    for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down)
-        gcr->trace(trc);
-}
-
-/* static */ void
-AutoGCRooter::traceAllWrappers(JSTracer *trc)
-{
-    for (js::AutoGCRooter *gcr = trc->runtime->autoGCRooters; gcr; gcr = gcr->down) {
-        if (gcr->tag == WRAPVECTOR || gcr->tag == WRAPPER)
-            gcr->trace(trc);
-    }
-}
-
-void
-Shape::Range::AutoRooter::trace(JSTracer *trc)
-{
-    if (r->cursor)
-        MarkShapeRoot(trc, const_cast<Shape**>(&r->cursor), "Shape::Range::AutoRooter");
-}
-
-void
-RegExpStatics::AutoRooter::trace(JSTracer *trc)
-{
-    if (statics->matchPairsInput)
-        MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->matchPairsInput),
-                       "RegExpStatics::AutoRooter matchPairsInput");
-    if (statics->pendingInput)
-        MarkStringRoot(trc, reinterpret_cast<JSString**>(&statics->pendingInput),
-                       "RegExpStatics::AutoRooter pendingInput");
-}
-
-void
-HashableValue::AutoRooter::trace(JSTracer *trc)
-{
-    MarkValueRoot(trc, reinterpret_cast<Value*>(&v->value), "HashableValue::AutoRooter");
-}
-
-static void
-MarkRuntime(JSTracer *trc, bool useSavedRoots = false)
-{
-    JSRuntime *rt = trc->runtime;
-    JS_ASSERT(trc->callback != GCMarker::GrayCallback);
-
-    if (IS_GC_MARKING_TRACER(trc)) {
-        for (CompartmentsIter c(rt); !c.done(); c.next()) {
-            if (!c->isCollecting())
-                c->markCrossCompartmentWrappers(trc);
-        }
-        Debugger::markCrossCompartmentDebuggerObjectReferents(trc);
-    }
-
-    AutoGCRooter::traceAll(trc);
-
-    if (rt->hasContexts()) {
-#ifdef JSGC_USE_EXACT_ROOTING
-        MarkExactStackRoots(trc);
-#else
-        MarkConservativeStackRoots(trc, useSavedRoots);
-#endif
-        rt->markSelfHostedGlobal(trc);
-    }
-
-    for (RootRange r = rt->gcRootsHash.all(); !r.empty(); r.popFront()) {
-        const RootEntry &entry = r.front();
-        const char *name = entry.value.name ? entry.value.name : "root";
-        if (entry.value.type == JS_GC_ROOT_GCTHING_PTR)
-            MarkGCThingRoot(trc, reinterpret_cast<void **>(entry.key), name);
-        else
-            MarkValueRoot(trc, reinterpret_cast<Value *>(entry.key), name);
-    }
-
-    for (GCLocks::Range r = rt->gcLocksHash.all(); !r.empty(); r.popFront()) {
-        const GCLocks::Entry &entry = r.front();
-        JS_ASSERT(entry.value >= 1);
-        JS_SET_TRACING_LOCATION(trc, (void *)&entry.key);
-        void *tmp = entry.key;
-        MarkGCThingRoot(trc, &tmp, "locked object");
-        JS_ASSERT(tmp == entry.key);
-    }
-
-    if (rt->scriptAndCountsVector) {
-        ScriptAndCountsVector &vec = *rt->scriptAndCountsVector;
-        for (size_t i = 0; i < vec.length(); i++)
-            MarkScriptRoot(trc, &vec[i].script, "scriptAndCountsVector");
-    }
-
-    if (!IS_GC_MARKING_TRACER(trc) || rt->atomsCompartment->isCollecting()) {
-        MarkAtoms(trc);
-#ifdef JS_ION
-        /* Any Ion wrappers survive until the runtime is being torn down. */
-        if (rt->hasContexts())
-            ion::IonRuntime::Mark(trc);
-#endif
-    }
-
-    rt->staticStrings.trace(trc);
-
-    for (ContextIter acx(rt); !acx.done(); acx.next())
-        acx->mark(trc);
-
-    /* We can't use GCCompartmentsIter if we're called from TraceRuntime. */
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (IS_GC_MARKING_TRACER(trc) && !c->isCollecting())
-            continue;
-
-        if ((c->activeAnalysis || c->isPreservingCode()) && IS_GC_MARKING_TRACER(trc)) {
-            gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_TYPES);
-            c->markTypes(trc);
-        }
-
-        /* During a GC, these are treated as weak pointers. */
-        if (!IS_GC_MARKING_TRACER(trc)) {
-            if (c->watchpointMap)
-                c->watchpointMap->markAll(trc);
-        }
-
-        /* Do not discard scripts with counts while profiling. */
-        if (rt->profilingScripts) {
-            for (CellIterUnderGC i(c, FINALIZE_SCRIPT); !i.done(); i.next()) {
-                JSScript *script = i.get<JSScript>();
-                if (script->hasScriptCounts) {
-                    MarkScriptRoot(trc, &script, "profilingScripts");
-                    JS_ASSERT(script == i.get<JSScript>());
-                }
-            }
-        }
-
-        /* Mark debug scopes, if present */
-        if (c->debugScopes)
-            c->debugScopes->mark(trc);
-    }
-
-#ifdef JS_METHODJIT
-    /* We need to expand inline frames before stack scanning. */
-    for (CompartmentsIter c(rt); !c.done(); c.next())
-        mjit::ExpandInlineFrames(c);
-#endif
-
-    rt->stackSpace.mark(trc);
-
-#ifdef JS_ION
-    ion::MarkIonActivations(rt, trc);
-#endif
-
-    for (CompartmentsIter c(rt); !c.done(); c.next())
-        c->mark(trc);
-
-    /* The embedding can register additional roots here. */
-    if (JSTraceDataOp op = rt->gcBlackRootsTraceOp)
-        (*op)(trc, rt->gcBlackRootsData);
-
-    /* During GC, this buffers up the gray roots and doesn't mark them. */
-    if (JSTraceDataOp op = rt->gcGrayRootsTraceOp) {
-        if (IS_GC_MARKING_TRACER(trc)) {
-            GCMarker *gcmarker = static_cast<GCMarker *>(trc);
-            gcmarker->startBufferingGrayRoots();
-            (*op)(trc, rt->gcGrayRootsData);
-            gcmarker->endBufferingGrayRoots();
-        } else {
-            (*op)(trc, rt->gcGrayRootsData);
-        }
-    }
-}
-
 static void
 TriggerOperationCallback(JSRuntime *rt, gcreason::Reason reason)
 {
     if (rt->gcIsNeeded)
         return;
 
     rt->gcIsNeeded = true;
     rt->gcTriggerReason = reason;
@@ -3884,32 +3117,34 @@ RemoveFromGrayList(RawObject wrapper)
     unsigned slot = GrayLinkSlot(wrapper);
     if (wrapper->getReservedSlot(slot).isUndefined())
         return false;  /* Not on our list. */
 
     RawObject tail = wrapper->getReservedSlot(slot).toObjectOrNull();
     wrapper->setReservedSlot(slot, UndefinedValue());
 
     JSCompartment *c = CrossCompartmentPointerReferent(wrapper)->compartment();
-    RawObject o = c->gcIncomingGrayPointers;
-    if (o == wrapper) {
+    RawObject obj = c->gcIncomingGrayPointers;
+    if (obj == wrapper) {
         c->gcIncomingGrayPointers = tail;
         return true;
     }
 
-    while (o) {
-        unsigned slot = GrayLinkSlot(o);
-        RawObject next = o->getReservedSlot(slot).toObjectOrNull();
+    while (obj) {
+        unsigned slot = GrayLinkSlot(obj);
+        RawObject next = obj->getReservedSlot(slot).toObjectOrNull();
         if (next == wrapper) {
-            o->setCrossCompartmentSlot(slot, ObjectOrNullValue(tail));
+            obj->setCrossCompartmentSlot(slot, ObjectOrNullValue(tail));
             return true;
         }
-        o = next;
+        obj = next;
     }
-    JS_NOT_REACHED();
+
+    JS_NOT_REACHED("object not found in gray link list");
+    return false;
 }
 
 void
 js::NotifyGCNukeWrapper(RawObject o)
 {
     /*
      * References to target of wrapper are being removed, we no longer have to
      * remember to mark it.
@@ -4327,61 +3562,42 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
                          !c->arenas.arenaListsToSweep[i]);
         }
 #endif
     }
 
     rt->gcLastGCTime = PRMJ_Now();
 }
 
-/*
- * This class should be used by any code that needs to exclusive access to the
- * heap in order to trace through it...
- */
-class AutoTraceSession {
-  public:
-    AutoTraceSession(JSRuntime *rt, JSRuntime::HeapState state = JSRuntime::Tracing);
-    ~AutoTraceSession();
-
-  protected:
-    JSRuntime *runtime;
-
-  private:
-    AutoTraceSession(const AutoTraceSession&) MOZ_DELETE;
-    void operator=(const AutoTraceSession&) MOZ_DELETE;
-
-    JSRuntime::HeapState prevState;
-};
-
 /* ...while this class is to be used only for garbage collection. */
 class AutoGCSession : AutoTraceSession {
   public:
     explicit AutoGCSession(JSRuntime *rt);
     ~AutoGCSession();
 };
 
 /* Start a new heap session. */
-AutoTraceSession::AutoTraceSession(JSRuntime *rt, JSRuntime::HeapState heapState)
+AutoTraceSession::AutoTraceSession(JSRuntime *rt, js::HeapState heapState)
   : runtime(rt),
     prevState(rt->heapState)
 {
     JS_ASSERT(!rt->noGCOrAllocationCheck);
     JS_ASSERT(!rt->isHeapBusy());
-    JS_ASSERT(heapState == JSRuntime::Collecting || heapState == JSRuntime::Tracing);
+    JS_ASSERT(heapState == Collecting || heapState == Tracing);
     rt->heapState = heapState;
 }
 
 AutoTraceSession::~AutoTraceSession()
 {
     JS_ASSERT(runtime->isHeapBusy());
     runtime->heapState = prevState;
 }
 
 AutoGCSession::AutoGCSession(JSRuntime *rt)
-  : AutoTraceSession(rt, JSRuntime::Collecting)
+  : AutoTraceSession(rt, Collecting)
 {
     runtime->gcIsNeeded = false;
     runtime->gcInterFrameGC = true;
 
     runtime->gcNumber++;
 }
 
 AutoGCSession::~AutoGCSession()
@@ -4401,31 +3617,28 @@ AutoGCSession::~AutoGCSession()
     for (CompartmentsIter c(runtime); !c.done(); c.next()) {
         c->resetGCMallocBytes();
         c->unscheduleGC();
     }
 
     runtime->resetGCMallocBytes();
 }
 
-class AutoCopyFreeListToArenas {
-    JSRuntime *rt;
-
-  public:
-    AutoCopyFreeListToArenas(JSRuntime *rt)
-      : rt(rt) {
-        for (CompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.copyFreeListsToArenas();
-    }
-
-    ~AutoCopyFreeListToArenas() {
-        for (CompartmentsIter c(rt); !c.done(); c.next())
-            c->arenas.clearFreeListsInArenas();
-    }
-};
+AutoCopyFreeListToArenas::AutoCopyFreeListToArenas(JSRuntime *rt)
+  : runtime(rt)
+{
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        c->arenas.copyFreeListsToArenas();
+}
+
+AutoCopyFreeListToArenas::~AutoCopyFreeListToArenas()
+{
+    for (CompartmentsIter c(runtime); !c.done(); c.next())
+        c->arenas.clearFreeListsInArenas();
+}
 
 static void
 IncrementalCollectSlice(JSRuntime *rt,
                         int64_t budget,
                         gcreason::Reason gcReason,
                         JSGCInvocationKind gcKind);
 
 static void
@@ -4676,41 +3889,18 @@ IncrementalCollectSlice(JSRuntime *rt,
         break;
       }
 
       default:
         JS_ASSERT(false);
     }
 }
 
-class IncrementalSafety
-{
-    const char *reason_;
-
-    IncrementalSafety(const char *reason) : reason_(reason) {}
-
-  public:
-    static IncrementalSafety Safe() { return IncrementalSafety(NULL); }
-    static IncrementalSafety Unsafe(const char *reason) { return IncrementalSafety(reason); }
-
-    typedef void (IncrementalSafety::* ConvertibleToBool)();
-    void nonNull() {}
-
-    operator ConvertibleToBool() const {
-        return reason_ == NULL ? &IncrementalSafety::nonNull : 0;
-    }
-
-    const char *reason() {
-        JS_ASSERT(reason_);
-        return reason_;
-    }
-};
-
-static IncrementalSafety
-IsIncrementalGCSafe(JSRuntime *rt)
+IncrementalSafety
+gc::IsIncrementalGCSafe(JSRuntime *rt)
 {
     if (rt->gcKeepAtoms)
         return IncrementalSafety::Unsafe("gcKeepAtoms set");
 
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
         if (c->activeAnalysis)
             return IncrementalSafety::Unsafe("activeAnalysis set");
     }
@@ -5004,142 +4194,32 @@ js::ShrinkGCBuffers(JSRuntime *rt)
     JS_ASSERT(!rt->isHeapBusy());
 
     if (!rt->useHelperThreads())
         ExpireChunksAndArenas(rt, true);
     else
         rt->gcHelperThread.startBackgroundShrink();
 }
 
-struct AutoFinishGC
-{
-    AutoFinishGC(JSRuntime *rt) {
-        if (IsIncrementalGCInProgress(rt)) {
-            PrepareForIncrementalGC(rt);
-            FinishIncrementalGC(rt, gcreason::API);
-        }
-
-        rt->gcHelperThread.waitBackgroundSweepEnd();
-    }
-};
-
-struct AutoPrepareForTracing
-{
-    AutoFinishGC finish;
-    AutoTraceSession session;
-    AutoCopyFreeListToArenas copy;
-
-    AutoPrepareForTracing(JSRuntime *rt)
-      : finish(rt),
-        session(rt),
-        copy(rt)
-    {}
-};
-
-void
-js::TraceRuntime(JSTracer *trc)
-{
-    JS_ASSERT(!IS_GC_MARKING_TRACER(trc));
-
-    AutoPrepareForTracing prep(trc->runtime);
-    RecordNativeStackTopForGC(trc->runtime);
-    MarkRuntime(trc);
-}
-
-struct IterateArenaCallbackOp
-{
-    JSRuntime *rt;
-    void *data;
-    IterateArenaCallback callback;
-    JSGCTraceKind traceKind;
-    size_t thingSize;
-    IterateArenaCallbackOp(JSRuntime *rt, void *data, IterateArenaCallback callback,
-                           JSGCTraceKind traceKind, size_t thingSize)
-        : rt(rt), data(data), callback(callback), traceKind(traceKind), thingSize(thingSize)
-    {}
-    void operator()(Arena *arena) { (*callback)(rt, data, arena, traceKind, thingSize); }
-};
-
-struct IterateCellCallbackOp
+AutoFinishGC::AutoFinishGC(JSRuntime *rt)
 {
-    JSRuntime *rt;
-    void *data;
-    IterateCellCallback callback;
-    JSGCTraceKind traceKind;
-    size_t thingSize;
-    IterateCellCallbackOp(JSRuntime *rt, void *data, IterateCellCallback callback,
-                          JSGCTraceKind traceKind, size_t thingSize)
-        : rt(rt), data(data), callback(callback), traceKind(traceKind), thingSize(thingSize)
-    {}
-    void operator()(Cell *cell) { (*callback)(rt, data, cell, traceKind, thingSize); }
-};
-
-void
-js::IterateCompartmentsArenasCells(JSRuntime *rt, void *data,
-                                   JSIterateCompartmentCallback compartmentCallback,
-                                   IterateArenaCallback arenaCallback,
-                                   IterateCellCallback cellCallback)
-{
-    AutoPrepareForTracing prop(rt);
-
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        (*compartmentCallback)(rt, data, c);
-
-        for (size_t thingKind = 0; thingKind != FINALIZE_LIMIT; thingKind++) {
-            JSGCTraceKind traceKind = MapAllocToTraceKind(AllocKind(thingKind));
-            size_t thingSize = Arena::thingSize(AllocKind(thingKind));
-            IterateArenaCallbackOp arenaOp(rt, data, arenaCallback, traceKind, thingSize);
-            IterateCellCallbackOp cellOp(rt, data, cellCallback, traceKind, thingSize);
-            ForEachArenaAndCell(c, AllocKind(thingKind), arenaOp, cellOp);
-        }
+    if (IsIncrementalGCInProgress(rt)) {
+        PrepareForIncrementalGC(rt);
+        FinishIncrementalGC(rt, gcreason::API);
     }
+
+    rt->gcHelperThread.waitBackgroundSweepEnd();
 }
 
-void
-js::IterateChunks(JSRuntime *rt, void *data, IterateChunkCallback chunkCallback)
+AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt)
+  : finish(rt),
+    session(rt),
+    copy(rt)
 {
-    AutoPrepareForTracing prep(rt);
-
-    for (js::GCChunkSet::Range r = rt->gcChunkSet.all(); !r.empty(); r.popFront())
-        chunkCallback(rt, data, r.front());
-}
-
-void
-js::IterateCells(JSRuntime *rt, JSCompartment *compartment, AllocKind thingKind,
-                 void *data, IterateCellCallback cellCallback)
-{
-    AutoPrepareForTracing prep(rt);
-
-    JSGCTraceKind traceKind = MapAllocToTraceKind(thingKind);
-    size_t thingSize = Arena::thingSize(thingKind);
-
-    if (compartment) {
-        for (CellIterUnderGC i(compartment, thingKind); !i.done(); i.next())
-            cellCallback(rt, data, i.getCell(), traceKind, thingSize);
-    } else {
-        for (CompartmentsIter c(rt); !c.done(); c.next()) {
-            for (CellIterUnderGC i(c, thingKind); !i.done(); i.next())
-                cellCallback(rt, data, i.getCell(), traceKind, thingSize);
-        }
-    }
-}
-
-void
-js::IterateGrayObjects(JSCompartment *compartment, GCThingCallback *cellCallback, void *data)
-{
-    JS_ASSERT(compartment);
-    AutoPrepareForTracing prep(compartment->rt);
-
-    for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) {
-        for (CellIterUnderGC i(compartment, AllocKind(finalizeKind)); !i.done(); i.next()) {
-            Cell *cell = i.getCell();
-            if (cell->isMarked(GRAY))
-                cellCallback(data, cell);
-        }
-    }
+    RecordNativeStackTopForGC(rt);
 }
 
 JSCompartment *
 gc::NewCompartment(JSContext *cx, JSPrincipals *principals)
 {
     JSRuntime *rt = cx->runtime;
     JS_AbortIfWrongThread(rt);
 
@@ -5229,770 +4309,16 @@ gc::SetDeterministicGC(JSContext *cx, bo
 
 void
 gc::SetValidateGC(JSContext *cx, bool enabled)
 {
     JSRuntime *rt = cx->runtime;
     rt->gcValidate = enabled;
 }
 
-#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
-
-JS_ALWAYS_INLINE bool
-CheckStackRootThing(uintptr_t *w, void *address, ThingRootKind kind)
-{
-    if (kind != THING_ROOT_BINDINGS)
-        return address == static_cast<void*>(w);
-
-    Bindings *bp = static_cast<Bindings*>(address);
-    return w >= (uintptr_t*)bp && w < (uintptr_t*)(bp + 1);
-}
-
-JS_ALWAYS_INLINE void
-CheckStackRootThings(uintptr_t *w, Rooted<void*> *rooter, ThingRootKind kind, bool *matched)
-{
-    while (rooter) {
-        if (CheckStackRootThing(w, rooter->address(), kind))
-            *matched = true;
-        rooter = rooter->previous();
-    }
-}
-
-static void
-CheckStackRoot(JSTracer *trc, uintptr_t *w)
-{
-    /* Mark memory as defined for valgrind, as in MarkWordConservatively. */
-#ifdef JS_VALGRIND
-    VALGRIND_MAKE_MEM_DEFINED(&w, sizeof(w));
-#endif
-
-    ConservativeGCTest test = MarkIfGCThingWord(trc, *w);
-
-    if (test == CGCT_VALID) {
-        bool matched = false;
-        JSRuntime *rt = trc->runtime;
-        for (unsigned i = 0; i < THING_ROOT_LIMIT; i++) {
-            CheckStackRootThings(w, rt->mainThread.thingGCRooters[i],
-                                 ThingRootKind(i), &matched);
-            for (ContextIter cx(rt); !cx.done(); cx.next()) {
-                CheckStackRootThings(w, cx->thingGCRooters[i], ThingRootKind(i), &matched);
-                SkipRoot *skip = cx->skipGCRooters;
-                while (skip) {
-                    if (skip->contains(reinterpret_cast<uint8_t*>(w), sizeof(w)))
-                        matched = true;
-                    skip = skip->previous();
-                }
-            }
-        }
-        if (!matched) {
-            /*
-             * Only poison the last byte in the word. It is easy to get
-             * accidental collisions when a value that does not occupy a full
-             * word is used to overwrite a now-dead GC thing pointer. In this
-             * case we want to avoid damaging the smaller value.
-             */
-            PoisonPtr(w);
-        }
-    }
-}
-
-static void
-CheckStackRootsRange(JSTracer *trc, uintptr_t *begin, uintptr_t *end)
-{
-    JS_ASSERT(begin <= end);
-    for (uintptr_t *i = begin; i != end; ++i)
-        CheckStackRoot(trc, i);
-}
-
-static void
-CheckStackRootsRangeAndSkipIon(JSRuntime *rt, JSTracer *trc, uintptr_t *begin, uintptr_t *end)
-{
-    /*
-     * Regions of the stack between Ion activiations are marked exactly through
-     * a different mechanism. We need to skip these regions when checking the
-     * stack so that we do not poison IonMonkey's things.
-     */
-    uintptr_t *i = begin;
-
-#if JS_STACK_GROWTH_DIRECTION < 0 && defined(JS_ION)
-    for (ion::IonActivationIterator ion(rt); ion.more(); ++ion) {
-        uintptr_t *ionMin, *ionEnd;
-        ion.ionStackRange(ionMin, ionEnd);
-
-        CheckStackRootsRange(trc, i, ionMin);
-        i = ionEnd;
-    }
-#endif
-
-    /* The topmost Ion activiation may be beyond our prior top. */
-    if (i <= end)
-        CheckStackRootsRange(trc, i, end);
-}
-
-static void
-EmptyMarkCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
-{}
-
-void
-JS::CheckStackRoots(JSContext *cx)
-{
-    JSRuntime *rt = cx->runtime;
-
-    if (rt->gcZeal_ != ZealStackRootingSafeValue && rt->gcZeal_ != ZealStackRootingValue)
-        return;
-    if (rt->gcZeal_ == ZealStackRootingSafeValue && !rt->gcExactScanningEnabled)
-        return;
-
-    // If this assertion fails, it means that an AutoAssertNoGC was placed
-    // around code that could trigger GC, and is therefore wrong. The
-    // AutoAssertNoGC should be removed and the code it was guarding should be
-    // modified to properly root any gcthings, and very possibly any code
-    // calling that function should also be modified if it was improperly
-    // assuming that GC could not happen at all within the called function.
-    // (The latter may not apply if the AutoAssertNoGC only protected a portion
-    // of a function, so the callers were already assuming that GC could
-    // happen.)
-    JS_ASSERT(!InNoGCScope());
-
-    // GCs can't happen when analysis/inference/compilation are active.
-    if (cx->compartment->activeAnalysis)
-        return;
-
-    // Can switch to the atoms compartment during analysis.
-    if (IsAtomsCompartment(cx->compartment)) {
-        for (CompartmentsIter c(rt); !c.done(); c.next()) {
-            if (c.get()->activeAnalysis)
-                return;
-        }
-    }
-
-    AutoCopyFreeListToArenas copy(rt);
-
-    JSTracer checker;
-    JS_TracerInit(&checker, rt, EmptyMarkCallback);
-
-    ConservativeGCData *cgcd = &rt->conservativeGC;
-    cgcd->recordStackTop();
-
-    JS_ASSERT(cgcd->hasStackToScan());
-    uintptr_t *stackMin, *stackEnd;
-#if JS_STACK_GROWTH_DIRECTION > 0
-    stackMin = rt->nativeStackBase;
-    stackEnd = cgcd->nativeStackTop;
-#else
-    stackMin = cgcd->nativeStackTop + 1;
-    stackEnd = reinterpret_cast<uintptr_t *>(rt->nativeStackBase);
-
-    uintptr_t *&oldStackMin = cgcd->oldStackMin, *&oldStackEnd = cgcd->oldStackEnd;
-    uintptr_t *&oldStackData = cgcd->oldStackData;
-    uintptr_t &oldStackCapacity = cgcd->oldStackCapacity;
-
-    /*
-     * Adjust the stack to remove regions which have not changed since the
-     * stack was last scanned, and update the last scanned state.
-     */
-    if (stackEnd != oldStackEnd) {
-        js_free(oldStackData);
-        oldStackCapacity = rt->nativeStackQuota / sizeof(uintptr_t);
-        oldStackData = (uintptr_t *) rt->malloc_(oldStackCapacity * sizeof(uintptr_t));
-        if (!oldStackData) {
-            oldStackCapacity = 0;
-        } else {
-            uintptr_t *existing = stackEnd - 1, *copy = oldStackData;
-            while (existing >= stackMin && size_t(copy - oldStackData) < oldStackCapacity)
-                *copy++ = *existing--;
-            oldStackEnd = stackEnd;
-            oldStackMin = existing + 1;
-        }
-    } else {
-        uintptr_t *existing = stackEnd - 1, *copy = oldStackData;
-        while (existing >= stackMin && existing >= oldStackMin && *existing == *copy) {
-            copy++;
-            existing--;
-        }
-        stackEnd = existing + 1;
-        while (existing >= stackMin && size_t(copy - oldStackData) < oldStackCapacity)
-            *copy++ = *existing--;
-        oldStackMin = existing + 1;
-    }
-#endif
-
-    JS_ASSERT(stackMin <= stackEnd);
-    CheckStackRootsRangeAndSkipIon(rt, &checker, stackMin, stackEnd);
-    CheckStackRootsRange(&checker, cgcd->registerSnapshot.words,
-                         ArrayEnd(cgcd->registerSnapshot.words));
-}
-
-#endif /* DEBUG && JS_GC_ZEAL && JSGC_ROOT_ANALYSIS && !JS_THREADSAFE */
-
-#ifdef JS_GC_ZEAL
-
-/*
- * Write barrier verification
- *
- * The next few functions are for write barrier verification.
- *
- * The VerifyBarriers function is a shorthand. It checks if a verification phase
- * is currently running. If not, it starts one. Otherwise, it ends the current
- * phase and starts a new one.
- *
- * The user can adjust the frequency of verifications, which causes
- * VerifyBarriers to be a no-op all but one out of N calls. However, if the
- * |always| parameter is true, it starts a new phase no matter what.
- *
- * Pre-Barrier Verifier:
- *   When StartVerifyBarriers is called, a snapshot is taken of all objects in
- *   the GC heap and saved in an explicit graph data structure. Later,
- *   EndVerifyBarriers traverses the heap again. Any pointer values that were in
- *   the snapshot and are no longer found must be marked; otherwise an assertion
- *   triggers. Note that we must not GC in between starting and finishing a
- *   verification phase.
- *
- * Post-Barrier Verifier:
- *   When StartVerifyBarriers is called, we create a virtual "Nursery Set" which
- *   future allocations are recorded in and turn on the StoreBuffer. Later,
- *   EndVerifyBarriers traverses the heap and ensures that the set of cross-
- *   generational pointers we find is a subset of the pointers recorded in our
- *   StoreBuffer.
- */
-
-struct EdgeValue
-{
-    void *thing;
-    JSGCTraceKind kind;
-    char *label;
-};
-
-struct VerifyNode
-{
-    void *thing;
-    JSGCTraceKind kind;
-    uint32_t count;
-    EdgeValue edges[1];
-};
-
-typedef HashMap<void *, VerifyNode *, DefaultHasher<void *>, SystemAllocPolicy> NodeMap;
-
-/*
- * The verifier data structures are simple. The entire graph is stored in a
- * single block of memory. At the beginning is a VerifyNode for the root
- * node. It is followed by a sequence of EdgeValues--the exact number is given
- * in the node. After the edges come more nodes and their edges.
- *
- * The edgeptr and term fields are used to allocate out of the block of memory
- * for the graph. If we run out of memory (i.e., if edgeptr goes beyond term),
- * we just abandon the verification.
- *
- * The nodemap field is a hashtable that maps from the address of the GC thing
- * to the VerifyNode that represents it.
- */
-struct VerifyPreTracer : JSTracer {
-    /* The gcNumber when the verification began. */
-    uint64_t number;
-
-    /* This counts up to gcZealFrequency to decide whether to verify. */
-    int count;
-
-    /* This graph represents the initial GC "snapshot". */
-    VerifyNode *curnode;
-    VerifyNode *root;
-    char *edgeptr;
-    char *term;
-    NodeMap nodemap;
-
-    VerifyPreTracer() : root(NULL) {}
-    ~VerifyPreTracer() { js_free(root); }
-};
-
-/*
- * This function builds up the heap snapshot by adding edges to the current
- * node.
- */
-static void
-AccumulateEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
-{
-    VerifyPreTracer *trc = (VerifyPreTracer *)jstrc;
-
-    trc->edgeptr += sizeof(EdgeValue);
-    if (trc->edgeptr >= trc->term) {
-        trc->edgeptr = trc->term;
-        return;
-    }
-
-    VerifyNode *node = trc->curnode;
-    uint32_t i = node->count;
-
-    node->edges[i].thing = *thingp;
-    node->edges[i].kind = kind;
-    node->edges[i].label = trc->debugPrinter ? NULL : (char *)trc->debugPrintArg;
-    node->count++;
-}
-
-static VerifyNode *
-MakeNode(VerifyPreTracer *trc, void *thing, JSGCTraceKind kind)
-{
-    NodeMap::AddPtr p = trc->nodemap.lookupForAdd(thing);
-    if (!p) {
-        VerifyNode *node = (VerifyNode *)trc->edgeptr;
-        trc->edgeptr += sizeof(VerifyNode) - sizeof(EdgeValue);
-        if (trc->edgeptr >= trc->term) {
-            trc->edgeptr = trc->term;
-            return NULL;
-        }
-
-        node->thing = thing;
-        node->count = 0;
-        node->kind = kind;
-        trc->nodemap.add(p, thing, node);
-        return node;
-    }
-    return NULL;
-}
-
-static VerifyNode *
-NextNode(VerifyNode *node)
-{
-    if (node->count == 0)
-        return (VerifyNode *)((char *)node + sizeof(VerifyNode) - sizeof(EdgeValue));
-    else
-        return (VerifyNode *)((char *)node + sizeof(VerifyNode) +
-                             sizeof(EdgeValue)*(node->count - 1));
-}
-
-static void
-StartVerifyPreBarriers(JSRuntime *rt)
-{
-    if (rt->gcVerifyPreData || rt->gcIncrementalState != NO_INCREMENTAL)
-        return;
-
-    AutoTraceSession session(rt);
-
-    if (!IsIncrementalGCSafe(rt))
-        return;
-
-    rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
-
-    AutoCopyFreeListToArenas copy(rt);
-    RecordNativeStackTopForGC(rt);
-
-    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
-        r.front()->bitmap.clear();
-
-    VerifyPreTracer *trc = js_new<VerifyPreTracer>();
-
-    rt->gcNumber++;
-    trc->number = rt->gcNumber;
-    trc->count = 0;
-
-    JS_TracerInit(trc, rt, AccumulateEdge);
-
-    const size_t size = 64 * 1024 * 1024;
-    trc->root = (VerifyNode *)js_malloc(size);
-    JS_ASSERT(trc->root);
-    trc->edgeptr = (char *)trc->root;
-    trc->term = trc->edgeptr + size;
-
-    if (!trc->nodemap.init())
-        return;
-
-    /* Create the root node. */
-    trc->curnode = MakeNode(trc, NULL, JSGCTraceKind(0));
-
-    /* We want MarkRuntime to save the roots to gcSavedRoots. */
-    rt->gcIncrementalState = MARK_ROOTS;
-
-    /* Make all the roots be edges emanating from the root node. */
-    MarkRuntime(trc);
-
-    VerifyNode *node = trc->curnode;
-    if (trc->edgeptr == trc->term)
-        goto oom;
-
-    /* For each edge, make a node for it if one doesn't already exist. */
-    while ((char *)node < trc->edgeptr) {
-        for (uint32_t i = 0; i < node->count; i++) {
-            EdgeValue &e = node->edges[i];
-            VerifyNode *child = MakeNode(trc, e.thing, e.kind);
-            if (child) {
-                trc->curnode = child;
-                JS_TraceChildren(trc, e.thing, e.kind);
-            }
-            if (trc->edgeptr == trc->term)
-                goto oom;
-        }
-
-        node = NextNode(node);
-    }
-
-    rt->gcVerifyPreData = trc;
-    rt->gcIncrementalState = MARK;
-    rt->gcMarker.start(rt);
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        PurgeJITCaches(c);
-        c->setNeedsBarrier(true, JSCompartment::UpdateIon);
-        c->arenas.purge();
-    }
-
-    return;
-
-oom:
-    rt->gcIncrementalState = NO_INCREMENTAL;
-    trc->~VerifyPreTracer();
-    js_free(trc);
-}
-
-static bool
-IsMarkedOrAllocated(Cell *cell)
-{
-    return cell->isMarked() || cell->arenaHeader()->allocatedDuringIncremental;
-}
-
-const static uint32_t MAX_VERIFIER_EDGES = 1000;
-
-/*
- * This function is called by EndVerifyBarriers for every heap edge. If the edge
- * already existed in the original snapshot, we "cancel it out" by overwriting
- * it with NULL. EndVerifyBarriers later asserts that the remaining non-NULL
- * edges (i.e., the ones from the original snapshot that must have been
- * modified) must point to marked objects.
- */
-static void
-CheckEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
-{
-    VerifyPreTracer *trc = (VerifyPreTracer *)jstrc;
-    VerifyNode *node = trc->curnode;
-
-    /* Avoid n^2 behavior. */
-    if (node->count > MAX_VERIFIER_EDGES)
-        return;
-
-    for (uint32_t i = 0; i < node->count; i++) {
-        if (node->edges[i].thing == *thingp) {
-            JS_ASSERT(node->edges[i].kind == kind);
-            node->edges[i].thing = NULL;
-            return;
-        }
-    }
-}
-
-static void
-AssertMarkedOrAllocated(const EdgeValue &edge)
-{
-    if (!edge.thing || IsMarkedOrAllocated(static_cast<Cell *>(edge.thing)))
-        return;
-
-    char msgbuf[1024];
-    const char *label = edge.label ? edge.label : "<unknown>";
-
-    JS_snprintf(msgbuf, sizeof(msgbuf), "[barrier verifier] Unmarked edge: %s", label);
-    MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
-    MOZ_CRASH();
-}
-
-static void
-EndVerifyPreBarriers(JSRuntime *rt)
-{
-    AutoTraceSession session(rt);
-
-    rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
-
-    AutoCopyFreeListToArenas copy(rt);
-    RecordNativeStackTopForGC(rt);
-
-    VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData;
-
-    if (!trc)
-        return;
-
-    bool compartmentCreated = false;
-
-    /* We need to disable barriers before tracing, which may invoke barriers. */
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (!c->needsBarrier())
-            compartmentCreated = true;
-
-        PurgeJITCaches(c);
-        c->setNeedsBarrier(false, JSCompartment::UpdateIon);
-    }
-
-    /*
-     * We need to bump gcNumber so that the methodjit knows that jitcode has
-     * been discarded.
-     */
-    JS_ASSERT(trc->number == rt->gcNumber);
-    rt->gcNumber++;
-
-    rt->gcVerifyPreData = NULL;
-    rt->gcIncrementalState = NO_INCREMENTAL;
-
-    if (!compartmentCreated && IsIncrementalGCSafe(rt)) {
-        JS_TracerInit(trc, rt, CheckEdge);
-
-        /* Start after the roots. */
-        VerifyNode *node = NextNode(trc->root);
-        while ((char *)node < trc->edgeptr) {
-            trc->curnode = node;
-            JS_TraceChildren(trc, node->thing, node->kind);
-
-            if (node->count <= MAX_VERIFIER_EDGES) {
-                for (uint32_t i = 0; i < node->count; i++)
-                    AssertMarkedOrAllocated(node->edges[i]);
-            }
-
-            node = NextNode(node);
-        }
-    }
-
-    rt->gcMarker.reset();
-    rt->gcMarker.stop();
-
-    trc->~VerifyPreTracer();
-    js_free(trc);
-}
-
-/*** Post-Barrier Verifyier ***/
-
-struct VerifyPostTracer : JSTracer {
-    /* The gcNumber when the verification began. */
-    uint64_t number;
-
-    /* This counts up to gcZealFrequency to decide whether to verify. */
-    int count;
-};
-
-/*
- * The post-barrier verifier runs the full store buffer and a fake nursery when
- * running and when it stops, walks the full heap to ensure that all the
- * important edges were inserted into the storebuffer.
- */
-static void
-StartVerifyPostBarriers(JSRuntime *rt)
-{
-#ifdef JSGC_GENERATIONAL
-    if (!rt->gcExactScanningEnabled ||
-        rt->gcVerifyPostData ||
-        rt->gcIncrementalState != NO_INCREMENTAL)
-    {
-        return;
-    }
-    VerifyPostTracer *trc = js_new<VerifyPostTracer>();
-    rt->gcVerifyPostData = trc;
-    rt->gcNumber++;
-    trc->number = rt->gcNumber;
-    trc->count = 0;
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (IsAtomsCompartment(c))
-            continue;
-
-        if (!c->gcNursery.enable())
-            goto oom;
-
-        if (!c->gcStoreBuffer.enable())
-            goto oom;
-    }
-    return;
-oom:
-    trc->~VerifyPostTracer();
-    js_free(trc);
-    rt->gcVerifyPostData = NULL;
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        c->gcNursery.disable();
-        c->gcStoreBuffer.disable();
-    }
-#endif
-}
-
-#ifdef JSGC_GENERATIONAL
-static void
-AssertStoreBufferContainsEdge(StoreBuffer *storebuf, void *loc, void *dst)
-{
-    if (storebuf->containsEdgeAt(loc))
-        return;
-
-    char msgbuf[1024];
-    JS_snprintf(msgbuf, sizeof(msgbuf), "[post-barrier verifier] Missing edge @ %p to %p",
-                loc, dst);
-    MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
-    MOZ_CRASH();
-}
-
-static void
-PostVerifierVisitEdge(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
-{
-    VerifyPostTracer *trc = (VerifyPostTracer *)jstrc;
-    Cell *dst = (Cell *)*thingp;
-    JSCompartment *comp = dst->compartment();
-
-    /*
-     * Note: watchpoint markAll will give us cross-compartment pointers into the
-     * atoms compartment.
-     */
-    if (IsAtomsCompartment(comp))
-        return;
-
-    /* Filter out non cross-generational edges. */
-    if (!comp->gcNursery.isInside(dst))
-        return;
-
-    /*
-     * Note: since Value travels through the stack to get Cell**, we need to use
-     * the annotated location in the tracer instead of the indirect location for
-     * these edges.
-     */
-    Cell *loc = (Cell *)(trc->realLocation != NULL ? trc->realLocation : thingp);
-
-    AssertStoreBufferContainsEdge(&comp->gcStoreBuffer, loc, dst);
-}
-#endif
-
-static void
-EndVerifyPostBarriers(JSRuntime *rt)
-{
-#ifdef JSGC_GENERATIONAL
-    AutoTraceSession session(rt);
-
-    rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
-
-    AutoCopyFreeListToArenas copy(rt);
-    RecordNativeStackTopForGC(rt);
-
-    VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData;
-    JS_TracerInit(trc, rt, PostVerifierVisitEdge);
-    trc->count = 0;
-
-    if (!rt->gcExactScanningEnabled)
-        goto oom;
-
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (c->gcStoreBuffer.hasOverflowed())
-            continue;
-        if (!c->gcStoreBuffer.coalesceForVerification())
-            goto oom;
-    }
-
-    /* Walk the heap. */
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        if (!c->gcStoreBuffer.isEnabled() ||
-             c->gcStoreBuffer.hasOverflowed() ||
-             IsAtomsCompartment(c))
-        {
-            continue;
-        }
-
-        if (c->watchpointMap)
-            c->watchpointMap->markAll(trc);
-
-        for (size_t kind = 0; kind < FINALIZE_LIMIT; ++kind) {
-            for (CellIterUnderGC cells(c, AllocKind(kind)); !cells.done(); cells.next()) {
-                Cell *src = cells.getCell();
-                if (!c->gcNursery.isInside(src))
-                    JS_TraceChildren(trc, src, MapAllocToTraceKind(AllocKind(kind)));
-            }
-        }
-    }
-
-oom:
-    trc->~VerifyPostTracer();
-    js_free(trc);
-    rt->gcVerifyPostData = NULL;
-    for (CompartmentsIter c(rt); !c.done(); c.next()) {
-        c->gcNursery.disable();
-        c->gcStoreBuffer.disable();
-        c->gcStoreBuffer.releaseVerificationData();
-    }
-#endif
-}
-
-/*** Barrier Verifier Scheduling ***/
-
-static void
-VerifyPreBarriers(JSRuntime *rt)
-{
-    if (rt->gcVerifyPreData)
-        EndVerifyPreBarriers(rt);
-    else
-        StartVerifyPreBarriers(rt);
-}
-
-static void
-VerifyPostBarriers(JSRuntime *rt)
-{
-    if (rt->gcVerifyPostData)
-        EndVerifyPostBarriers(rt);
-    else
-        StartVerifyPostBarriers(rt);
-}
-
-void
-gc::VerifyBarriers(JSRuntime *rt, VerifierType type)
-{
-    if (type == PreBarrierVerifier)
-        VerifyPreBarriers(rt);
-    else
-        VerifyPostBarriers(rt);
-}
-
-static void
-MaybeVerifyPreBarriers(JSRuntime *rt, bool always)
-{
-    if (rt->gcZeal() != ZealVerifierPreValue)
-        return;
-
-    if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
-        if (++trc->count < rt->gcZealFrequency && !always)
-            return;
-
-        EndVerifyPreBarriers(rt);
-    }
-    StartVerifyPreBarriers(rt);
-}
-
-static void
-MaybeVerifyPostBarriers(JSRuntime *rt, bool always)
-{
-    if (rt->gcZeal() != ZealVerifierPostValue)
-        return;
-
-    if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
-        if (++trc->count < rt->gcZealFrequency && !always)
-            return;
-
-        EndVerifyPostBarriers(rt);
-    }
-    StartVerifyPostBarriers(rt);
-}
-
-void
-gc::MaybeVerifyBarriers(JSContext *cx, bool always)
-{
-    MaybeVerifyPreBarriers(cx->runtime, always);
-    MaybeVerifyPostBarriers(cx->runtime, always);
-}
-
-void
-FinishVerifier(JSRuntime *rt)
-{
-    if (VerifyPreTracer *trc = (VerifyPreTracer *)rt->gcVerifyPreData) {
-        trc->~VerifyPreTracer();
-        js_free(trc);
-    }
-#ifdef JSGC_GENERATIONAL
-    if (VerifyPostTracer *trc = (VerifyPostTracer *)rt->gcVerifyPostData) {
-        trc->~VerifyPostTracer();
-        js_free(trc);
-        for (CompartmentsIter c(rt); !c.done(); c.next()) {
-            c->gcNursery.disable();
-            c->gcStoreBuffer.disable();
-        }
-    }
-#endif
-}
-
-#endif /* JS_GC_ZEAL */
-
 #ifdef DEBUG
 
 /* Should only be called manually under gdb */
 void PreventGCDuringInteractiveDebug()
 {
     TlsPerThreadData.get()->suppressGC++;
 }
 
@@ -6174,29 +4500,16 @@ AutoMaybeTouchDeadCompartments::~AutoMay
     if (inIncremental && runtime->gcObjectsMarkedInDeadCompartments != markCount) {
         PrepareForFullGC(runtime);
         js::GC(runtime, GC_NORMAL, gcreason::TRANSPLANT);
     }
 
     runtime->gcManipulatingDeadCompartments = manipulatingDeadCompartments;
 }
 
-JS_PUBLIC_API(void)
-JS_IterateCompartments(JSRuntime *rt, void *data,
-                       JSIterateCompartmentCallback compartmentCallback)
-{
-    JS_ASSERT(!rt->isHeapBusy());
-
-    AutoTraceSession session(rt);
-    rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
-
-    for (CompartmentsIter c(rt); !c.done(); c.next())
-        (*compartmentCallback)(rt, data, c);
-}
-
 #if JS_HAS_XML_SUPPORT
 extern size_t sE4XObjectsCreated;
 
 JSXML *
 js_NewGCXML(JSContext *cx)
 {
     if (!cx->runningWithTrustedPrincipals())
         ++sE4XObjectsCreated;
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -32,16 +32,22 @@
 struct JSCompartment;
 
 namespace js {
 
 class GCHelperThread;
 struct Shape;
 struct SliceBudget;
 
+enum HeapState {
+    Idle,       // doing nothing with the GC heap
+    Tracing,    // tracing the GC heap without collecting, e.g. IterateCompartments()
+    Collecting  // doing a GC of the heap
+};
+
 namespace ion {
     class IonCode;
 }
 
 namespace gc {
 
 enum State {
     NO_INCREMENTAL,
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -6357,17 +6357,18 @@ DecompileArgumentFromStack(JSContext *cx
 
     if (current < script->main())
         return true;
 
     PCStack pcStack;
     if (!pcStack.init(cx, script, current))
         return false;
 
-    uint32_t formalStackIndex = pcStack.depth() - GET_ARGC(current) + formalIndex;
+    int formalStackIndex = pcStack.depth() - GET_ARGC(current) + formalIndex;
+    JS_ASSERT(formalStackIndex >= 0);
     if (formalStackIndex >= pcStack.depth())
         return true;
 
     ExpressionDecompiler ed(cx, script, fun);
     if (!ed.init())
         return false;
     if (!ed.decompilePC(pcStack[formalStackIndex]))
         return false;
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -90,50 +90,16 @@ members = [
     # case for security.
     #'nsIDOMDocument.location',
     'nsIDOMDocument.elementFromPoint',
     'nsIDOMDocument.activeElement',
     'nsIDOMDocument.onreadystatechange',
     'nsIDOMDocument.onmouseenter',
     'nsIDOMDocument.onmouseleave',
     'nsIDOMDocument.URL',
-    'nsIDOMElement.removeAttributeNS',
-    'nsIDOMElement.removeAttribute',
-    'nsIDOMElement.getAttribute',
-    'nsIDOMElement.getElementsByTagName',
-    'nsIDOMElement.setAttribute',
-    'nsIDOMElement.getElementsByTagNameNS',
-    'nsIDOMElement.hasAttributeNS',
-    'nsIDOMElement.tagName',
-    'nsIDOMElement.setAttributeNS',
-    'nsIDOMElement.hasAttribute',
-    'nsIDOMElement.getAttributeNS',
-    'nsIDOMElement.onmouseenter',
-    'nsIDOMElement.onmouseleave',
-    'nsIDOMElement.getElementsByClassName',
-    'nsIDOMElement.getClientRects',
-    'nsIDOMElement.getBoundingClientRect',
-    'nsIDOMElement.scrollTop',
-    'nsIDOMElement.scrollLeft',
-    'nsIDOMElement.scrollHeight',
-    'nsIDOMElement.scrollWidth',
-    'nsIDOMElement.clientTop',
-    'nsIDOMElement.clientLeft',
-    'nsIDOMElement.clientHeight',
-    'nsIDOMElement.clientWidth',
-    'nsIDOMElement.firstElementChild',
-    'nsIDOMElement.lastElementChild',
-    'nsIDOMElement.previousElementSibling',
-    'nsIDOMElement.nextElementSibling',
-    'nsIDOMElement.childElementCount',
-    'nsIDOMElement.children',
-    'nsIDOMElement.classList',
-    'nsIDOMElement.setCapture',
-    'nsIDOMElement.releaseCapture',
-    'nsIDOMElement.mozMatchesSelector',
     'nsIDOMNamedNodeMap.item',
     'nsIDOMNamedNodeMap.length',
     'nsIDOMNodeSelector.querySelector',
     'nsIDOMNodeSelector.querySelectorAll',
     'nsIDOMText.splitText',
     'nsIDOMDOMStringList.*',
     'nsIDOMXULDocument.getBoxObjectFor',
     'nsIDOMMutationRecord.*',
@@ -478,17 +444,18 @@ customIncludes = [
     'nsGenericHTMLElement.h',
     'nsSVGStylableElement.h',
     'nsHTMLDocument.h',
     'nsDOMQS.h',
     'nsDOMStringMap.h',
     'HTMLPropertiesCollection.h',
     'nsHTMLMenuElement.h',
     'nsICSSDeclaration.h',
-    'mozilla/dom/NodeBinding.h'
+    'mozilla/dom/NodeBinding.h',
+    'mozilla/dom/ElementBinding.h'
     ]
 
 customReturnInterfaces = [
     'nsIDOMCanvasPattern',
     'nsIDOMCanvasGradient',
     ]
 
 nsIDOMHTMLDocument_Write_customMethodCallCode = """
@@ -538,111 +505,16 @@ customMethodCalls = {
         'thisType': 'nsHTMLDocument',
         'code': '    nsRefPtr<nsContentList> result = '
                 'self->GetElementsByName(arg0);',
         'canFail': False
         },
     'nsIDOMStorage_Clear': {
         'code': nsIDOMStorage_Clear_customMethodCallCode
         },
-    'nsIDOMElement_GetScrollTop': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ScrollTop();',
-        'canFail': False
-        },
-    'nsIDOMElement_SetScrollTop': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_GetScrollLeft': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ScrollLeft();',
-        'canFail': False
-        },
-    'nsIDOMElement_SetScrollLeft': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_GetScrollHeight': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ScrollHeight();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetScrollWidth': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ScrollWidth();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClientTop': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ClientTop();',
-        'canFail': False
-        },
-    'nsIDOMElement_SetClientTop': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClientLeft': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ClientLeft();',
-        'canFail': False
-        },
-    'nsIDOMElement_SetClientLeft': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClientHeight': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ClientHeight();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClientWidth': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    int32_t result = self->ClientWidth();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetFirstElementChild': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    nsIContent *result = self->GetFirstElementChild();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetLastElementChild': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    nsIContent *result = self->GetLastElementChild();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetPreviousElementSibling': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    nsIContent *result = self->GetPreviousElementSibling();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetNextElementSibling': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    nsIContent *result = self->GetNextElementSibling();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClassList': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    nsDOMTokenList *result = self->ClassList();',
-        'canFail': False
-        },
-    'nsIDOMElement_SetCapture': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_ReleaseCapture': {
-        'thisType': 'mozilla::dom::Element',
-        'canFail': False
-        },
-    'nsIDOMElement_MozMatchesSelector': {
-        'thisType': 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    bool result = self->MozMatchesSelector(arg0, error);\n'
-                '    rv = error.ErrorCode();'
-        },
     'nsIDOMNodeSelector_QuerySelector': {
         'thisType': 'nsINode',
         'code': '    mozilla::ErrorResult error;\n'
                 '    nsIContent* result = '
                 'self->QuerySelector(arg0, error);\n'
                 '    rv = error.ErrorCode();'
         },
     'nsIDOMNodeSelector_QuerySelectorAll': {
@@ -734,24 +606,16 @@ customMethodCalls = {
         'canFail': False
         },
     'nsIDOMDocument_GetElementsByTagNameNS': {
         'thisType': 'nsDocument',
         'code': '    nsRefPtr<nsContentList> result ='
                 'self->GetElementsByTagNameNS(arg0, arg1);',
         'canFail': False
         },
-    'nsIDOMElement_': {
-        'thisType': 'mozilla::dom::Element'
-        },
-    'nsIDOMElement_GetTagName': {
-        'thisType': 'mozilla::dom::Element',
-        'code': 'nsString result = self->NodeName();',
-        'canFail': False
-        },
     'nsIDOMDocument_CreateElement': {
         'thisType': 'nsDocument',
         'code': '    nsCOMPtr<nsIContent> result;\n'
                 '    rv = self->CreateElement(arg0, getter_AddRefs(result));'
     },
     'nsIDOMDocument_CreateElementNS': {
         'thisType': 'nsDocument',
         'code': '    nsCOMPtr<nsIContent> result;\n'
@@ -781,104 +645,16 @@ customMethodCalls = {
     'nsIDOMDocument_GetOnmouseleave' : {
         'thisType' : 'nsDocument',
         'unwrapThisFailureFatal' : False
         },
     'nsIDOMDocument_SetOnmouseleave' : {
         'thisType' : 'nsDocument',
         'unwrapThisFailureFatal' : False
         },
-    'nsIDOMElement_GetOnmouseenter' : {
-        'thisType' : 'mozilla::dom::Element',
-        'unwrapThisFailureFatal' : False
-        },
-    'nsIDOMElement_SetOnmouseenter' : {
-        'thisType' : 'mozilla::dom::Element',
-        'unwrapThisFailureFatal' : False
-        },
-    'nsIDOMElement_GetOnmouseleave' : {
-        'thisType' : 'mozilla::dom::Element',
-        'unwrapThisFailureFatal' : False
-        },
-    'nsIDOMElement_SetOnmouseleave' : {
-        'thisType' : 'mozilla::dom::Element',
-        'unwrapThisFailureFatal' : False
-        },
-    'nsIDOMElement_RemoveAttributeNS' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    self->RemoveAttributeNS(arg0, arg1, error);\n'
-                '    rv = error.ErrorCode();'
-        },
-    'nsIDOMElement_RemoveAttribute' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    self->RemoveAttribute(arg0, error);\n'
-                '    rv = error.ErrorCode();'
-        },
-    'nsIDOMElement_GetAttribute' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    nsString result;\n'
-                '    self->GetAttribute(arg0, result);',
-        'canFail': False
-        },
-    'nsIDOMElement_GetAttributeNS' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    nsString result;\n'
-                '    self->GetAttributeNS(arg0, arg1, result);',
-        'canFail': False
-        },
-    'nsIDOMElement_SetAttribute' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    self->SetAttribute(arg0, arg1, error);\n'
-                '    rv = error.ErrorCode();'
-        },
-    'nsIDOMElement_SetAttributeNS' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    self->SetAttributeNS(arg0, arg1, arg2, error);\n'
-                '    rv = error.ErrorCode();'
-        },
-    'nsIDOMElement_HasAttribute' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    bool result = self->HasAttribute(arg0);',
-        'canFail': False
-        },
-    'nsIDOMElement_HasAttributeNS' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    bool result = self->HasAttributeNS(arg0, arg1);',
-        'canFail': False
-        },
-    'nsIDOMElement_GetElementsByTagName' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    nsCOMPtr<nsIHTMLCollection> result = self->GetElementsByTagName(arg0);',
-        'canFail': False
-        },
-    'nsIDOMElement_GetClientRects' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    mozilla::ErrorResult error;\n'
-                '    nsRefPtr<nsClientRectList> result = self->GetClientRects(error);\n'
-                '    rv = error.ErrorCode();'
-        },
-    'nsIDOMElement_GetBoundingClientRect' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    nsRefPtr<nsClientRect> result = self->GetBoundingClientRect();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetChildElementCount' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    uint32_t result = self->ChildElementCount();',
-        'canFail': False
-        },
-    'nsIDOMElement_GetChildElements' : {
-        'thisType' : 'mozilla::dom::Element',
-        'code': '    nsIHTMLCollection* result = self->Children();',
-        'canFail': False
-        },
     'nsIDOMHTMLElement_GetTitle': {
         'thisType' : 'nsGenericHTMLElement',
         'canFail': False
         },
     'nsIDOMHTMLElement_SetTitle': {
         'thisType' : 'nsGenericHTMLElement',
         'canFail': False
         },
@@ -1050,10 +826,11 @@ customMethodCalls = {
         },
     'nsIDOMWindow_SetOnmouseleave' : {
         'thisType' : 'nsIDOMWindow',
         'unwrapThisFailureFatal' : False
         }
     }
 
 newBindingProperties = {
-    'nsIDOMNode': 'mozilla::dom::NodeBinding::sNativePropertyHooks.mNativeProperties.regular'
+    'nsIDOMNode': 'mozilla::dom::NodeBinding::sNativePropertyHooks.mNativeProperties.regular',
+    'nsIDOMElement': 'mozilla::dom::ElementBinding::sNativePropertyHooks.mNativeProperties.regular'
     }
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -190,17 +190,17 @@ GetPrintingLog()
 
 #define PRT_YESNO(_p) ((_p)?"YES":"NO")
 #else
 #define PRT_YESNO(_p)
 #define PR_PL(_p1)
 #endif
 //-----------------------------------------------------
 
-class DocumentViewerImpl;
+class nsDocumentViewer;
 class nsPrintEventDispatcher;
 
 // a small delegate class used to avoid circular references
 
 class nsDocViewerSelectionListener : public nsISelectionListener
 {
 public:
 
@@ -214,21 +214,21 @@ public:
                        : mDocViewer(NULL)
                        , mGotSelectionState(false)
                        , mSelectionWasCollapsed(false)
                        {
                        }
 
   virtual              ~nsDocViewerSelectionListener() {}
 
-  nsresult             Init(DocumentViewerImpl *aDocViewer);
+  nsresult             Init(nsDocumentViewer *aDocViewer);
 
 protected:
 
-  DocumentViewerImpl*  mDocViewer;
+  nsDocumentViewer*  mDocViewer;
   bool                 mGotSelectionState;
   bool                 mSelectionWasCollapsed;
 
 };
 
 
 /** editor Implementation of the FocusListener interface
  */
@@ -240,41 +240,41 @@ public:
   nsDocViewerFocusListener();
   /** default destructor
    */
   virtual ~nsDocViewerFocusListener();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMEVENTLISTENER
 
-  nsresult             Init(DocumentViewerImpl *aDocViewer);
+  nsresult             Init(nsDocumentViewer *aDocViewer);
 
 private:
-    DocumentViewerImpl*  mDocViewer;
+    nsDocumentViewer*  mDocViewer;
 };
 
 
 //-------------------------------------------------------------
-class DocumentViewerImpl : public nsIContentViewer,
+class nsDocumentViewer : public nsIContentViewer,
                            public nsIContentViewerEdit,
                            public nsIContentViewerFile,
                            public nsIMarkupDocumentViewer,
                            public nsIDocumentViewerPrint
 
 #ifdef NS_PRINTING
                            , public nsIWebBrowserPrint
 #endif
 
 {
   friend class nsDocViewerSelectionListener;
   friend class nsPagePrintTimer;
   friend class nsPrintEngine;
 
 public:
-  DocumentViewerImpl();
+  nsDocumentViewer();
 
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
 
   // nsISupports interface...
   NS_DECL_ISUPPORTS
 
   // nsIContentViewer interface...
   NS_DECL_NSICONTENTVIEWER
@@ -308,17 +308,17 @@ public:
   static void DispatchAfterPrint(nsIDocument* aTop)
   {
     DispatchEventToWindowTree(aTop, NS_LITERAL_STRING("afterprint"));
   }
   static void DispatchEventToWindowTree(nsIDocument* aTop,
                                         const nsAString& aEvent);
 
 protected:
-  virtual ~DocumentViewerImpl();
+  virtual ~nsDocumentViewer();
 
 private:
   /**
    * Creates a view manager, root view, and widget for the root view, setting
    * mViewManager and mWindow.
    * @param aSize the initial size in appunits
    * @param aContainerView the container view to hook our root view up
    * to as a child, or null if this will be the root view manager
@@ -466,21 +466,21 @@ protected:
   bool mHidden;
 };
 
 class nsPrintEventDispatcher
 {
 public:
   nsPrintEventDispatcher(nsIDocument* aTop) : mTop(aTop)
   {
-    DocumentViewerImpl::DispatchBeforePrint(mTop);
+    nsDocumentViewer::DispatchBeforePrint(mTop);
   }
   ~nsPrintEventDispatcher()
   {
-    DocumentViewerImpl::DispatchAfterPrint(mTop);
+    nsDocumentViewer::DispatchAfterPrint(mTop);
   }
 
   nsCOMPtr<nsIDocument> mTop;
 };
 
 class nsDocumentShownDispatcher : public nsRunnable
 {
 public:
@@ -490,33 +490,33 @@ public:
   NS_IMETHOD Run();
 
 private:
   nsCOMPtr<nsIDocument> mDocument;
 };
 
 
 //------------------------------------------------------------------
-// DocumentViewerImpl
+// nsDocumentViewer
 //------------------------------------------------------------------
 // Class IDs
 static NS_DEFINE_CID(kViewManagerCID,       NS_VIEW_MANAGER_CID);
 
 //------------------------------------------------------------------
 nsresult
 NS_NewContentViewer(nsIContentViewer** aResult)
 {
-  *aResult = new DocumentViewerImpl();
+  *aResult = new nsDocumentViewer();
 
   NS_ADDREF(*aResult);
 
   return NS_OK;
 }
 
-void DocumentViewerImpl::PrepareToStartLoad()
+void nsDocumentViewer::PrepareToStartLoad()
 {
   mStopped          = false;
   mLoaded           = false;
   mAttachedToParent = false;
   mDeferredWindowClose = false;
   mCallerIsClosingWindow = false;
 
 #ifdef NS_PRINTING
@@ -536,45 +536,45 @@ void DocumentViewerImpl::PrepareToStartL
 #ifdef DEBUG
   mDebugFile = nullptr;
 #endif
 
 #endif // NS_PRINTING
 }
 
 // Note: operator new zeros our memory, so no need to init things to null.
-DocumentViewerImpl::DocumentViewerImpl()
+nsDocumentViewer::nsDocumentViewer()
   : mTextZoom(1.0), mPageZoom(1.0), mMinFontSize(0),
     mIsSticky(true),
 #ifdef NS_PRINT_PREVIEW
     mPrintPreviewZoom(1.0),
 #endif
     mHintCharsetSource(kCharsetUninitialized),
     mInitializedForPrintPreview(false),
     mHidden(false)
 {
   PrepareToStartLoad();
 }
 
-NS_IMPL_ADDREF(DocumentViewerImpl)
-NS_IMPL_RELEASE(DocumentViewerImpl)
-
-NS_INTERFACE_MAP_BEGIN(DocumentViewerImpl)
+NS_IMPL_ADDREF(nsDocumentViewer)
+NS_IMPL_RELEASE(nsDocumentViewer)
+
+NS_INTERFACE_MAP_BEGIN(nsDocumentViewer)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewer)
     NS_INTERFACE_MAP_ENTRY(nsIMarkupDocumentViewer)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewerFile)
     NS_INTERFACE_MAP_ENTRY(nsIContentViewerEdit)
     NS_INTERFACE_MAP_ENTRY(nsIDocumentViewerPrint)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentViewer)
 #ifdef NS_PRINTING
     NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPrint)
 #endif
 NS_INTERFACE_MAP_END
 
-DocumentViewerImpl::~DocumentViewerImpl()
+nsDocumentViewer::~nsDocumentViewer()
 {
   if (mDocument) {
     Close(nullptr);
     mDocument->Destroy();
   }
 
   NS_ASSERTION(!mPresShell && !mPresContext,
                "User did not call nsIContentViewer::Destroy");
@@ -593,37 +593,37 @@ DocumentViewerImpl::~DocumentViewerImpl(
  * This method is called by the Document Loader once a document has
  * been created for a particular data stream...  The content viewer
  * must cache this document for later use when Init(...) is called.
  *
  * This method is also called when an out of band document.write() happens.
  * In that case, the document passed in is the same as the previous document.
  */
 NS_IMETHODIMP
-DocumentViewerImpl::LoadStart(nsISupports *aDoc)
+nsDocumentViewer::LoadStart(nsISupports *aDoc)
 {
 #ifdef NOISY_VIEWER
-  printf("DocumentViewerImpl::LoadStart\n");
+  printf("nsDocumentViewer::LoadStart\n");
 #endif
 
   nsresult rv = NS_OK;
   if (!mDocument) {
     mDocument = do_QueryInterface(aDoc, &rv);
   }
   else if (mDocument == aDoc) {
     // Reset the document viewer's state back to what it was
     // when the document load started.
     PrepareToStartLoad();
   }
 
   return rv;
 }
 
 nsresult
-DocumentViewerImpl::SyncParentSubDocMap()
+nsDocumentViewer::SyncParentSubDocMap()
 {
   nsCOMPtr<nsIDocShellTreeItem> item(do_QueryReferent(mContainer));
   nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(item));
   nsCOMPtr<nsIContent> content;
 
   if (mDocument && pwin) {
     content = do_QueryInterface(pwin->GetFrameElementInternal());
   }
@@ -649,50 +649,50 @@ DocumentViewerImpl::SyncParentSubDocMap(
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetContainer(nsISupports* aContainer)
+nsDocumentViewer::SetContainer(nsISupports* aContainer)
 {
   mContainer = do_GetWeakReference(aContainer);
   if (mPresContext) {
     mPresContext->SetContainer(aContainer);
   }
 
   // We're loading a new document into the window where this document
   // viewer lives, sync the parent document's frame element -> sub
   // document map
 
   return SyncParentSubDocMap();
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetContainer(nsISupports** aResult)
+nsDocumentViewer::GetContainer(nsISupports** aResult)
 {
    NS_ENSURE_ARG_POINTER(aResult);
 
    *aResult = nullptr;
    nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
    container.swap(*aResult);
    return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Init(nsIWidget* aParentWidget,
+nsDocumentViewer::Init(nsIWidget* aParentWidget,
                          const nsIntRect& aBounds)
 {
   return InitInternal(aParentWidget, nullptr, aBounds, true);
 }
 
 nsresult
-DocumentViewerImpl::InitPresentationStuff(bool aDoInitialReflow)
+nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow)
 {
   if (GetIsPrintPreview())
     return NS_OK;
 
   NS_ASSERTION(!mPresShell,
                "Someone should have destroyed the presshell!");
 
   // Create the style set...
@@ -813,17 +813,17 @@ CreatePresContext(nsIDocument* aDocument
   return new nsRootPresContext(aDocument, aType);
 }
 
 //-----------------------------------------------
 // This method can be used to initial the "presentation"
 // The aDoCreation indicates whether it should create
 // all the new objects or just initialize the existing ones
 nsresult
-DocumentViewerImpl::InitInternal(nsIWidget* aParentWidget,
+nsDocumentViewer::InitInternal(nsIWidget* aParentWidget,
                                  nsISupports *aState,
                                  const nsIntRect& aBounds,
                                  bool aDoCreation,
                                  bool aNeedMakeCX /*= true*/,
                                  bool aForceSetNewDocument /* = true*/)
 {
   if (mIsPageMode) {
     // XXXbz should the InitInternal in SetPageMode just pass false
@@ -950,41 +950,41 @@ DocumentViewerImpl::InitInternal(nsIWidg
     // MakeWindow())...
 
     rv = InitPresentationStuff(!makeCX);
   }
 
   return rv;
 }
 
-void DocumentViewerImpl::SetNavigationTiming(nsDOMNavigationTiming* timing)
+void nsDocumentViewer::SetNavigationTiming(nsDOMNavigationTiming* timing)
 {
   NS_ASSERTION(mDocument, "Must have a document to set navigation timing.");
   if (mDocument) {
     mDocument->SetNavigationTiming(timing);
   }
 }
 
 //
 // LoadComplete(aStatus)
 //
 //   aStatus - The status returned from loading the document.
 //
 // This method is called by the container when the document has been
 // completely loaded.
 //
 NS_IMETHODIMP
-DocumentViewerImpl::LoadComplete(nsresult aStatus)
+nsDocumentViewer::LoadComplete(nsresult aStatus)
 {
   /* We need to protect ourself against auto-destruction in case the
      window is closed while processing the OnLoad event.  See bug
      http://bugzilla.mozilla.org/show_bug.cgi?id=78445 for more
      explanation.
   */
-  nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
+  nsRefPtr<nsDocumentViewer> kungFuDeathGrip(this);
 
   // Flush out layout so it's up-to-date by the time onload is called.
   // Note that this could destroy the window, so do this before
   // checking for our mDocument and its window.
   if (mPresShell && !mStopped) {
     // Hold strong ref because this could conceivably run script
     nsCOMPtr<nsIPresShell> shell = mPresShell;
     shell->FlushPendingNotifications(Flush_Layout);
@@ -1085,17 +1085,17 @@ DocumentViewerImpl::LoadComplete(nsresul
     mCachedPrintWebProgressListner = nullptr;
   }
 #endif
 
   return rv;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::PermitUnload(bool aCallerClosesWindow, bool *aPermitUnload)
+nsDocumentViewer::PermitUnload(bool aCallerClosesWindow, bool *aPermitUnload)
 {
   *aPermitUnload = true;
 
   if (!mDocument || mInPermitUnload || mCallerIsClosingWindow) {
     return NS_OK;
   }
 
   // First, get the script global object from the document...
@@ -1122,17 +1122,17 @@ DocumentViewerImpl::PermitUnload(bool aC
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Dispatching to |window|, but using |document| as the target.
   event->SetTarget(mDocument);
   event->SetTrusted(true);
 
   // In evil cases we might be destroyed while handling the
   // onbeforeunload event, don't let that happen. (see also bug#331040)
-  nsRefPtr<DocumentViewerImpl> kungFuDeathGrip(this);
+  nsRefPtr<nsDocumentViewer> kungFuDeathGrip(this);
 
   {
     // Never permit popups from the beforeunload handler, no matter
     // how we get here.
     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
     mInPermitUnload = true;
     nsEventDispatcher::DispatchDOMEvent(window, nullptr, event, mPresContext,
@@ -1220,17 +1220,17 @@ DocumentViewerImpl::PermitUnload(bool aC
 
   if (aCallerClosesWindow && *aPermitUnload)
     mCallerIsClosingWindow = true;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::ResetCloseWindow()
+nsDocumentViewer::ResetCloseWindow()
 {
   mCallerIsClosingWindow = false;
 
   nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
   if (docShellNode) {
     int32_t childCount;
     docShellNode->GetChildCount(&childCount);
 
@@ -1249,17 +1249,17 @@ DocumentViewerImpl::ResetCloseWindow()
         }
       }
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::PageHide(bool aIsUnload)
+nsDocumentViewer::PageHide(bool aIsUnload)
 {
   mHidden = true;
 
   if (!mDocument) {
     return NS_ERROR_NULL_POINTER;
   }
 
   mDocument->OnPageHide(!aIsUnload, nullptr);
@@ -1341,17 +1341,17 @@ AttachContainerRecurse(nsIDocShell* aShe
   for (int32_t i = 0; i < childCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> childItem;
     node->GetChildAt(i, getter_AddRefs(childItem));
     AttachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem)));
   }
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Open(nsISupports *aState, nsISHEntry *aSHEntry)
+nsDocumentViewer::Open(nsISupports *aState, nsISHEntry *aSHEntry)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
 
   if (mDocument)
     mDocument->SetContainer(nsCOMPtr<nsISupports>(do_QueryReferent(mContainer)));
 
   nsresult rv = InitInternal(mParentWidget, aState, mBounds, false);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1408,17 +1408,17 @@ DocumentViewerImpl::Open(nsISupports *aS
 
     mAttachedToParent = true;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Close(nsISHEntry *aSHEntry)
+nsDocumentViewer::Close(nsISHEntry *aSHEntry)
 {
   // All callers are supposed to call close to break circular
   // references.  If we do this stuff in the destructor, the
   // destructor might never be called (especially if we're being
   // used from JS.
 
   mSHEntry = aSHEntry;
 
@@ -1498,17 +1498,17 @@ DetachContainerRecurse(nsIDocShell *aShe
   for (int32_t i = 0; i < childCount; ++i) {
     nsCOMPtr<nsIDocShellTreeItem> childItem;
     node->GetChildAt(i, getter_AddRefs(childItem));
     DetachContainerRecurse(nsCOMPtr<nsIDocShell>(do_QueryInterface(childItem)));
   }
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Destroy()
+nsDocumentViewer::Destroy()
 {
   NS_ASSERTION(mDocument, "No document in Destroy()!");
 
 #ifdef NS_PRINTING
   // Here is where we check to see if the document was still being prepared 
   // for printing when it was asked to be destroy from someone externally
   // This usually happens if the document is unloaded while the user is in the
   // Print Dialog
@@ -1671,17 +1671,17 @@ DocumentViewerImpl::Destroy()
   mWindow = nullptr;
   mViewManager = nullptr;
   mContainer = nullptr;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Stop(void)
+nsDocumentViewer::Stop(void)
 {
   NS_ASSERTION(mDocument, "Stop called too early or too late");
   if (mDocument) {
     mDocument->StopDocumentLoad();
   }
 
   if (!mHidden && (mLoaded || mStopped) && mPresContext && !mSHEntry)
     mPresContext->SetImageAnimationMode(imgIContainer::kDontAnimMode);
@@ -1693,30 +1693,30 @@ DocumentViewerImpl::Stop(void)
     nsCOMPtr<nsIPresShell> shellDeathGrip(mPresShell); // bug 378682
     mPresShell->UnsuppressPainting();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetDOMDocument(nsIDOMDocument **aResult)
+nsDocumentViewer::GetDOMDocument(nsIDOMDocument **aResult)
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
   return CallQueryInterface(mDocument, aResult);
 }
 
 NS_IMETHODIMP_(nsIDocument *)
-DocumentViewerImpl::GetDocument()
+nsDocumentViewer::GetDocument()
 {
   return mDocument;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetDOMDocument(nsIDOMDocument *aDocument)
+nsDocumentViewer::SetDOMDocument(nsIDOMDocument *aDocument)
 {
   // Assumptions:
   //
   // 1) this document viewer has been initialized with a call to Init().
   // 2) the stylesheets associated with the document have been added
   // to the document.
 
   // XXX Right now, this method assumes that the layout of the current
@@ -1730,17 +1730,17 @@ DocumentViewerImpl::SetDOMDocument(nsIDO
 
   nsCOMPtr<nsIDocument> newDoc = do_QueryInterface(aDocument);
   NS_ENSURE_TRUE(newDoc, NS_ERROR_UNEXPECTED);
 
   return SetDocumentInternal(newDoc, false);
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetDocumentInternal(nsIDocument* aDocument,
+nsDocumentViewer::SetDocumentInternal(nsIDocument* aDocument,
                                         bool aForceReuseInnerWindow)
 {
   MOZ_ASSERT(aDocument);
 
   // Set new container
   nsCOMPtr<nsISupports> container = do_QueryReferent(mContainer);
   aDocument->SetContainer(container);
 
@@ -1790,67 +1790,67 @@ DocumentViewerImpl::SetDocumentInternal(
     mWindow = nullptr;
     InitInternal(mParentWidget, nullptr, mBounds, true, true, false);
   }
 
   return rv;
 }
 
 nsIPresShell*
-DocumentViewerImpl::GetPresShell()
+nsDocumentViewer::GetPresShell()
 {
   return mPresShell;
 }
 
 nsPresContext*
-DocumentViewerImpl::GetPresContext()
+nsDocumentViewer::GetPresContext()
 {
   return mPresContext;
 }
 
 nsIViewManager*
-DocumentViewerImpl::GetViewManager()
+nsDocumentViewer::GetViewManager()
 {
   return mViewManager;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetPresShell(nsIPresShell** aResult)
+nsDocumentViewer::GetPresShell(nsIPresShell** aResult)
 {
   nsIPresShell* shell = GetPresShell();
   NS_IF_ADDREF(*aResult = shell);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetPresContext(nsPresContext** aResult)
+nsDocumentViewer::GetPresContext(nsPresContext** aResult)
 {
   nsPresContext* pc = GetPresContext();
   NS_IF_ADDREF(*aResult = pc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetBounds(nsIntRect& aResult)
+nsDocumentViewer::GetBounds(nsIntRect& aResult)
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
   aResult = mBounds;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetPreviousViewer(nsIContentViewer** aViewer)
+nsDocumentViewer::GetPreviousViewer(nsIContentViewer** aViewer)
 {
   *aViewer = mPreviousViewer;
   NS_IF_ADDREF(*aViewer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetPreviousViewer(nsIContentViewer* aViewer)
+nsDocumentViewer::SetPreviousViewer(nsIContentViewer* aViewer)
 {
   // NOTE:  |Show| sets |mPreviousViewer| to null without calling this
   // function.
 
   if (aViewer) {
     NS_ASSERTION(!mPreviousViewer,
                  "can't set previous viewer when there already is one");
 
@@ -1873,17 +1873,17 @@ DocumentViewerImpl::SetPreviousViewer(ns
     }
   }
 
   mPreviousViewer = aViewer;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetBounds(const nsIntRect& aBounds)
+nsDocumentViewer::SetBounds(const nsIntRect& aBounds)
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
   mBounds = aBounds;
   if (mWindow) {
     if (!mAttachedToParent) {
       // Don't have the widget repaint. Layout will generate repaint requests
       // during reflow.
@@ -1908,28 +1908,28 @@ DocumentViewerImpl::SetBounds(const nsIn
     nsCOMPtr<nsIContentViewer> previousViewer = mPreviousViewer;
     previousViewer->SetBounds(aBounds);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Move(int32_t aX, int32_t aY)
+nsDocumentViewer::Move(int32_t aX, int32_t aY)
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
   mBounds.MoveTo(aX, aY);
   if (mWindow) {
     mWindow->Move(aX, aY);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Show(void)
+nsDocumentViewer::Show(void)
 {
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
   // We don't need the previous viewer anymore since we're not
   // displaying it.
   if (mPreviousViewer) {
     // This little dance *may* only be to keep
     // PresShell::EndObservingDocument happy, but I'm not sure.
@@ -2034,17 +2034,17 @@ DocumentViewerImpl::Show(void)
   // Notify observers that a new page has been shown. This will get run
   // from the event loop after we actually draw the page.
   NS_DispatchToMainThread(new nsDocumentShownDispatcher(mDocument));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::Hide(void)
+nsDocumentViewer::Hide(void)
 {
   if (!mAttachedToParent && mWindow) {
     mWindow->Show(false);
   }
 
   if (!mPresShell)
     return NS_OK;
 
@@ -2084,33 +2084,33 @@ DocumentViewerImpl::Hide(void)
   if (base_win && !mAttachedToParent) {
     base_win->SetParentWidget(nullptr);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetSticky(bool *aSticky)
+nsDocumentViewer::GetSticky(bool *aSticky)
 {
   *aSticky = mIsSticky;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetSticky(bool aSticky)
+nsDocumentViewer::SetSticky(bool aSticky)
 {
   mIsSticky = aSticky;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::RequestWindowClose(bool* aCanClose)
+nsDocumentViewer::RequestWindowClose(bool* aCanClose)
 {
 #ifdef NS_PRINTING
   if (mPrintIsPending || (mPrintEngine && mPrintEngine->GetIsPrinting())) {
     *aCanClose = false;
     mDeferredWindowClose = true;
   } else
 #endif
     *aCanClose = true;
@@ -2130,17 +2130,17 @@ static bool
 PrependUserSheet(nsIStyleSheet *aSheet, void *aData)
 {
   nsStyleSet *styleSet = static_cast<nsStyleSet*>(aData);
   styleSet->PrependStyleSheet(nsStyleSet::eUserSheet, aSheet);
   return true;
 }
 
 nsresult
-DocumentViewerImpl::CreateStyleSet(nsIDocument* aDocument,
+nsDocumentViewer::CreateStyleSet(nsIDocument* aDocument,
                                    nsStyleSet** aStyleSet)
 {
   // Make sure this does the same thing as PresShell::AddSheet wrt ordering.
 
   // this should eventually get expanded to allow for creating
   // different sets for different media
   nsStyleSet *styleSet = new nsStyleSet();
 
@@ -2246,26 +2246,26 @@ DocumentViewerImpl::CreateStyleSet(nsIDo
   }
 
   // Caller will handle calling EndUpdate, per contract.
   *aStyleSet = styleSet;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::ClearHistoryEntry()
+nsDocumentViewer::ClearHistoryEntry()
 {
   mSHEntry = nullptr;
   return NS_OK;
 }
 
 //-------------------------------------------------------
 
 nsresult
-DocumentViewerImpl::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
+nsDocumentViewer::MakeWindow(const nsSize& aSize, nsIView* aContainerView)
 {
   if (GetIsPrintPreview())
     return NS_OK;
 
   bool shouldAttach = ShouldAttachToTopLevel();
 
   if (shouldAttach) {
     // If the old view is already attached to our parent, detach
@@ -2334,29 +2334,29 @@ DocumentViewerImpl::MakeWindow(const nsS
   // go to the scrolled view as soon as the Window is created instead of going to
   // the browser window (this enables keyboard scrolling of the document)
   // mWindow->SetFocus();
 
   return rv;
 }
 
 void
-DocumentViewerImpl::DetachFromTopLevelWidget()
+nsDocumentViewer::DetachFromTopLevelWidget()
 {
   if (mViewManager) {
     nsIView* oldView = mViewManager->GetRootView();
     if (oldView && oldView->IsAttachedToTopLevel()) {
       oldView->DetachFromTopLevelWidget();
     }
   }
   mAttachedToParent = false;
 }
 
 nsIView*
-DocumentViewerImpl::FindContainerView()
+nsDocumentViewer::FindContainerView()
 {
   nsIView* containerView = nullptr;
 
   if (mContainer) {
     nsCOMPtr<nsIDocShellTreeItem> docShellItem = do_QueryReferent(mContainer);
     nsCOMPtr<nsPIDOMWindow> pwin(do_GetInterface(docShellItem));
     if (pwin) {
       nsCOMPtr<nsIContent> containerElement = do_QueryInterface(pwin->GetFrameElementInternal());
@@ -2402,17 +2402,17 @@ DocumentViewerImpl::FindContainerView()
       }
     }
   }
 
   return containerView;
 }
 
 nsresult
-DocumentViewerImpl::CreateDeviceContext(nsIView* aContainerView)
+nsDocumentViewer::CreateDeviceContext(nsIView* aContainerView)
 {
   NS_PRECONDITION(!mPresShell && !mWindow,
                   "This will screw up our existing presentation");
   NS_PRECONDITION(mDocument, "Gotta have a document here");
   
   nsIDocument* doc = mDocument->GetDisplayDocument();
   if (doc) {
     NS_ASSERTION(!aContainerView, "External resource document embedded somewhere?");
@@ -2442,17 +2442,17 @@ DocumentViewerImpl::CreateDeviceContext(
 
   mDeviceContext = new nsDeviceContext();
   mDeviceContext->Init(widget);
   return NS_OK;
 }
 
 // Return the selection for the document. Note that text fields have their
 // own selection, which cannot be accessed with this method.
-nsresult DocumentViewerImpl::GetDocumentSelection(nsISelection **aSelection)
+nsresult nsDocumentViewer::GetDocumentSelection(nsISelection **aSelection)
 {
   NS_ENSURE_ARG_POINTER(aSelection);
   if (!mPresShell) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   nsCOMPtr<nsISelectionController> selcon;
   selcon = do_QueryInterface(mPresShell);
@@ -2461,29 +2461,29 @@ nsresult DocumentViewerImpl::GetDocument
                                 aSelection);
   return NS_ERROR_FAILURE;
 }
 
 /* ========================================================================================
  * nsIContentViewerEdit
  * ======================================================================================== */
 
-NS_IMETHODIMP DocumentViewerImpl::ClearSelection()
+NS_IMETHODIMP nsDocumentViewer::ClearSelection()
 {
   nsresult rv;
   nsCOMPtr<nsISelection> selection;
 
   // use nsCopySupport::GetSelectionForCopy() ?
   rv = GetDocumentSelection(getter_AddRefs(selection));
   if (NS_FAILED(rv)) return rv;
 
   return selection->CollapseToStart();
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SelectAll()
+NS_IMETHODIMP nsDocumentViewer::SelectAll()
 {
   // XXX this is a temporary implementation copied from nsWebShell
   // for now. I think nsDocument and friends should have some helper
   // functions to make this easier.
   nsCOMPtr<nsISelection> selection;
   nsresult rv;
 
   // use nsCopySupport::GetSelectionForCopy() ?
@@ -2509,23 +2509,23 @@ NS_IMETHODIMP DocumentViewerImpl::Select
 
   rv = selection->RemoveAllRanges();
   if (NS_FAILED(rv)) return rv;
 
   rv = selection->SelectAllChildren(bodyNode);
   return rv;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::CopySelection()
+NS_IMETHODIMP nsDocumentViewer::CopySelection()
 {
   nsCopySupport::FireClipboardEvent(NS_COPY, mPresShell, nullptr);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::CopyLinkLocation()
+NS_IMETHODIMP nsDocumentViewer::CopyLinkLocation()
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
   nsCOMPtr<nsIDOMNode> node;
   GetPopupLinkNode(getter_AddRefs(node));
   // make noise if we're not in a link
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   nsCOMPtr<dom::Element> elm(do_QueryInterface(node));
@@ -2540,38 +2540,38 @@ NS_IMETHODIMP DocumentViewerImpl::CopyLi
   nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // copy the href onto the clipboard
   nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(mDocument);
   return clipboard->CopyString(locationText, doc);
 }
 
-NS_IMETHODIMP DocumentViewerImpl::CopyImage(int32_t aCopyFlags)
+NS_IMETHODIMP nsDocumentViewer::CopyImage(int32_t aCopyFlags)
 {
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
   nsCOMPtr<nsIImageLoadingContent> node;
   GetPopupImageNode(getter_AddRefs(node));
   // make noise if we're not in an image
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsILoadContext> loadContext(do_QueryReferent(mContainer));
   return nsCopySupport::ImageCopy(node, loadContext, aCopyFlags);
 }
 
 
-NS_IMETHODIMP DocumentViewerImpl::GetCopyable(bool *aCopyable)
+NS_IMETHODIMP nsDocumentViewer::GetCopyable(bool *aCopyable)
 {
   NS_ENSURE_ARG_POINTER(aCopyable);
   *aCopyable = nsCopySupport::CanCopy(mDocument);
   return NS_OK;
 }
 
 /* AString getContents (in string mimeType, in boolean selectionOnly); */
-NS_IMETHODIMP DocumentViewerImpl::GetContents(const char *mimeType, bool selectionOnly, nsAString& aOutValue)
+NS_IMETHODIMP nsDocumentViewer::GetContents(const char *mimeType, bool selectionOnly, nsAString& aOutValue)
 {
   aOutValue.Truncate();
 
   NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
 
   // Now we have the selection.  Make sure it's nonzero:
   nsCOMPtr<nsISelection> sel;
@@ -2586,17 +2586,17 @@ NS_IMETHODIMP DocumentViewerImpl::GetCon
   }
 
   // call the copy code
   return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
                                     mDocument, aOutValue);
 }
 
 /* readonly attribute boolean canGetContents; */
-NS_IMETHODIMP DocumentViewerImpl::GetCanGetContents(bool *aCanGetContents)
+NS_IMETHODIMP nsDocumentViewer::GetCanGetContents(bool *aCanGetContents)
 {
   NS_ENSURE_ARG_POINTER(aCanGetContents);
   *aCanGetContents = false;
   NS_ENSURE_STATE(mDocument);
   *aCanGetContents = nsCopySupport::CanCopy(mDocument);
   return NS_OK;
 }
 
@@ -2604,17 +2604,17 @@ NS_IMETHODIMP DocumentViewerImpl::GetCan
 /* ========================================================================================
  * nsIContentViewerFile
  * ======================================================================================== */
 /** ---------------------------------------------------
  *  See documentation above in the nsIContentViewerfile class definition
  *	@update 01/24/00 dwc
  */
 NS_IMETHODIMP
-DocumentViewerImpl::Print(bool              aSilent,
+nsDocumentViewer::Print(bool              aSilent,
                           FILE *            aDebugFile,
                           nsIPrintSettings* aPrintSettings)
 {
 #ifdef NS_PRINTING
   nsCOMPtr<nsIPrintSettings> printSettings;
 
 #ifdef DEBUG
   nsresult rv = NS_ERROR_FAILURE;
@@ -2639,41 +2639,41 @@ DocumentViewerImpl::Print(bool          
   return Print(printSettings, nullptr);
 #else
   return NS_ERROR_FAILURE;
 #endif
 }
 
 /* [noscript] void printWithParent (in nsIDOMWindow aParentWin, in nsIPrintSettings aThePrintSettings, in nsIWebProgressListener aWPListener); */
 NS_IMETHODIMP 
-DocumentViewerImpl::PrintWithParent(nsIDOMWindow*, nsIPrintSettings *aThePrintSettings, nsIWebProgressListener *aWPListener)
+nsDocumentViewer::PrintWithParent(nsIDOMWindow*, nsIPrintSettings *aThePrintSettings, nsIWebProgressListener *aWPListener)
 {
 #ifdef NS_PRINTING
   return Print(aThePrintSettings, aWPListener);
 #else
   return NS_ERROR_FAILURE;
 #endif
 }
 
 // nsIContentViewerFile interface
 NS_IMETHODIMP
-DocumentViewerImpl::GetPrintable(bool *aPrintable)
+nsDocumentViewer::GetPrintable(bool *aPrintable)
 {
   NS_ENSURE_ARG_POINTER(aPrintable);
 
   *aPrintable = !GetIsPrinting();
 
   return NS_OK;
 }
 
 //*****************************************************************************
 // nsIMarkupDocumentViewer
 //*****************************************************************************
 
-NS_IMETHODIMP DocumentViewerImpl::ScrollToNode(nsIDOMNode* aNode)
+NS_IMETHODIMP nsDocumentViewer::ScrollToNode(nsIDOMNode* aNode)
 {
   NS_ENSURE_ARG(aNode);
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
   nsCOMPtr<nsIPresShell> presShell;
   NS_ENSURE_SUCCESS(GetPresShell(getter_AddRefs(presShell)), NS_ERROR_FAILURE);
 
   // Get the nsIContent interface, because that's what we need to
   // get the primary frame
@@ -2689,17 +2689,17 @@ NS_IMETHODIMP DocumentViewerImpl::Scroll
                                        nsIPresShell::SCROLL_ALWAYS),
                                      nsIPresShell::ScrollAxis(),
                                      nsIPresShell::SCROLL_OVERFLOW_HIDDEN),
     NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 void
-DocumentViewerImpl::CallChildren(CallChildFunc aFunc, void* aClosure)
+nsDocumentViewer::CallChildren(CallChildFunc aFunc, void* aClosure)
 {
   nsCOMPtr<nsIDocShellTreeNode> docShellNode(do_QueryReferent(mContainer));
   if (docShellNode)
   {
     int32_t i;
     int32_t n;
     docShellNode->GetChildCount(&n);
     for (i=0; i < n; i++)
@@ -2805,17 +2805,17 @@ SetExtResourceFullZoom(nsIDocument* aDoc
       ctxt->SetFullZoom(ZoomInfo->mZoom);
     }
   }
 
   return true;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetTextZoom(float aTextZoom)
+nsDocumentViewer::SetTextZoom(float aTextZoom)
 {
   if (GetIsPrintPreview()) {
     return NS_OK;
   }
 
   mTextZoom = aTextZoom;
 
   // Set the text zoom on all children of mContainer (even if our zoom didn't
@@ -2833,26 +2833,26 @@ DocumentViewerImpl::SetTextZoom(float aT
 
   // And do the external resources
   mDocument->EnumerateExternalResources(SetExtResourceTextZoom, &ZoomInfo);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetTextZoom(float* aTextZoom)
+nsDocumentViewer::GetTextZoom(float* aTextZoom)
 {
   NS_ENSURE_ARG_POINTER(aTextZoom);
   nsPresContext* pc = GetPresContext();
   *aTextZoom = pc ? pc->TextZoom() : 1.0f;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetMinFontSize(int32_t aMinFontSize)
+nsDocumentViewer::SetMinFontSize(int32_t aMinFontSize)
 {
   if (GetIsPrintPreview()) {
     return NS_OK;
   }
 
   mMinFontSize = aMinFontSize;
 
   // Set the min font on all children of mContainer (even if our min font didn't
@@ -2870,26 +2870,26 @@ DocumentViewerImpl::SetMinFontSize(int32
   // And do the external resources
   mDocument->EnumerateExternalResources(SetExtResourceMinFontSize,
                                         NS_INT32_TO_PTR(aMinFontSize));
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetMinFontSize(int32_t* aMinFontSize)
+nsDocumentViewer::GetMinFontSize(int32_t* aMinFontSize)
 {
   NS_ENSURE_ARG_POINTER(aMinFontSize);
   nsPresContext* pc = GetPresContext();
   *aMinFontSize = pc ? pc->MinFontSize(nullptr) : 0;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetFullZoom(float aFullZoom)
+nsDocumentViewer::SetFullZoom(float aFullZoom)
 {
 #ifdef NS_PRINT_PREVIEW
   if (GetIsPrintPreview()) {
     nsPresContext* pc = GetPresContext();
     NS_ENSURE_TRUE(pc, NS_OK);
     nsCOMPtr<nsIPresShell> shell = pc->GetPresShell();
     NS_ENSURE_TRUE(shell, NS_OK);
 
@@ -2926,17 +2926,17 @@ DocumentViewerImpl::SetFullZoom(float aF
 
   // And do the external resources
   mDocument->EnumerateExternalResources(SetExtResourceFullZoom, &ZoomInfo);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetFullZoom(float* aFullZoom)
+nsDocumentViewer::GetFullZoom(float* aFullZoom)
 {
   NS_ENSURE_ARG_POINTER(aFullZoom);
 #ifdef NS_PRINT_PREVIEW
   if (GetIsPrintPreview()) {
     *aFullZoom = mPrintPreviewZoom;
     return NS_OK;
   }
 #endif
@@ -2951,38 +2951,38 @@ static void
 SetChildAuthorStyleDisabled(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   bool styleDisabled  = *static_cast<bool*>(aClosure);
   aChild->SetAuthorStyleDisabled(styleDisabled);
 }
 
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetAuthorStyleDisabled(bool aStyleDisabled)
+nsDocumentViewer::SetAuthorStyleDisabled(bool aStyleDisabled)
 {
   if (mPresShell) {
     mPresShell->SetAuthorStyleDisabled(aStyleDisabled);
   }
   CallChildren(SetChildAuthorStyleDisabled, &aStyleDisabled);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetAuthorStyleDisabled(bool* aStyleDisabled)
+nsDocumentViewer::GetAuthorStyleDisabled(bool* aStyleDisabled)
 {
   if (mPresShell) {
     *aStyleDisabled = mPresShell->GetAuthorStyleDisabled();
   } else {
     *aStyleDisabled = false;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
+nsDocumentViewer::GetDefaultCharacterSet(nsACString& aDefaultCharacterSet)
 {
   if (mDefaultCharacterSet.IsEmpty())
   {
     const nsAdoptingCString& defCharset =
       Preferences::GetLocalizedCString("intl.charset.default");
 
     if (!defCharset.IsEmpty()) {
       mDefaultCharacterSet = defCharset;
@@ -2997,231 +2997,231 @@ DocumentViewerImpl::GetDefaultCharacterS
 static void
 SetChildDefaultCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   const nsACString* charset = static_cast<nsACString*>(aClosure);
   aChild->SetDefaultCharacterSet(*charset);
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetDefaultCharacterSet(const nsACString& aDefaultCharacterSet)
+nsDocumentViewer::SetDefaultCharacterSet(const nsACString& aDefaultCharacterSet)
 {
   mDefaultCharacterSet = aDefaultCharacterSet;  // this does a copy of aDefaultCharacterSet
   // now set the default char set on all children of mContainer
   CallChildren(SetChildDefaultCharacterSet, (void*) &aDefaultCharacterSet);
   return NS_OK;
 }
 
 // XXX: SEMANTIC CHANGE!
 //      returns a copy of the string.  Caller is responsible for freeing result
 //      using Recycle(aForceCharacterSet)
-NS_IMETHODIMP DocumentViewerImpl::GetForceCharacterSet(nsACString& aForceCharacterSet)
+NS_IMETHODIMP nsDocumentViewer::GetForceCharacterSet(nsACString& aForceCharacterSet)
 {
   aForceCharacterSet = mForceCharacterSet;
   return NS_OK;
 }
 
 static void
 SetChildForceCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   const nsACString* charset = static_cast<nsACString*>(aClosure);
   aChild->SetForceCharacterSet(*charset);
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetForceCharacterSet(const nsACString& aForceCharacterSet)
+nsDocumentViewer::SetForceCharacterSet(const nsACString& aForceCharacterSet)
 {
   mForceCharacterSet = aForceCharacterSet;
   // now set the force char set on all children of mContainer
   CallChildren(SetChildForceCharacterSet, (void*) &aForceCharacterSet);
   return NS_OK;
 }
 
 // XXX: SEMANTIC CHANGE!
 //      returns a copy of the string.  Caller is responsible for freeing result
 //      using Recycle(aHintCharacterSet)
-NS_IMETHODIMP DocumentViewerImpl::GetHintCharacterSet(nsACString& aHintCharacterSet)
+NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSet(nsACString& aHintCharacterSet)
 {
 
   if(kCharsetUninitialized == mHintCharsetSource) {
     aHintCharacterSet.Truncate();
   } else {
     aHintCharacterSet = mHintCharset;
     // this can't possibly be right.  we can't set a value just because somebody got a related value!
     //mHintCharsetSource = kCharsetUninitialized;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetHintCharacterSetSource(int32_t *aHintCharacterSetSource)
+NS_IMETHODIMP nsDocumentViewer::GetHintCharacterSetSource(int32_t *aHintCharacterSetSource)
 {
   NS_ENSURE_ARG_POINTER(aHintCharacterSetSource);
 
   *aHintCharacterSetSource = mHintCharsetSource;
   return NS_OK;
 }
 
 
-NS_IMETHODIMP DocumentViewerImpl::GetPrevDocCharacterSet(nsACString& aPrevDocCharacterSet)
+NS_IMETHODIMP nsDocumentViewer::GetPrevDocCharacterSet(nsACString& aPrevDocCharacterSet)
 {
   aPrevDocCharacterSet = mPrevDocCharacterSet;
 
   return NS_OK;
 }
 
 static void
 SetChildPrevDocCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   const nsACString* charset = static_cast<nsACString*>(aClosure);
   aChild->SetPrevDocCharacterSet(*charset);
 }
 
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetPrevDocCharacterSet(const nsACString& aPrevDocCharacterSet)
+nsDocumentViewer::SetPrevDocCharacterSet(const nsACString& aPrevDocCharacterSet)
 {
   mPrevDocCharacterSet = aPrevDocCharacterSet;  
   CallChildren(SetChildPrevDocCharacterSet, (void*) &aPrevDocCharacterSet);
   return NS_OK;
 }
 
 
 static void
 SetChildHintCharacterSetSource(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   aChild->SetHintCharacterSetSource(NS_PTR_TO_INT32(aClosure));
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetHintCharacterSetSource(int32_t aHintCharacterSetSource)
+nsDocumentViewer::SetHintCharacterSetSource(int32_t aHintCharacterSetSource)
 {
   mHintCharsetSource = aHintCharacterSetSource;
   // now set the hint char set source on all children of mContainer
   CallChildren(SetChildHintCharacterSetSource,
                       NS_INT32_TO_PTR(aHintCharacterSetSource));
   return NS_OK;
 }
 
 static void
 SetChildHintCharacterSet(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   const nsACString* charset = static_cast<nsACString*>(aClosure);
   aChild->SetHintCharacterSet(*charset);
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::SetHintCharacterSet(const nsACString& aHintCharacterSet)
+nsDocumentViewer::SetHintCharacterSet(const nsACString& aHintCharacterSet)
 {
   mHintCharset = aHintCharacterSet;
   // now set the hint char set on all children of mContainer
   CallChildren(SetChildHintCharacterSet, (void*) &aHintCharacterSet);
   return NS_OK;
 }
 
 static void
 SetChildBidiOptions(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   aChild->SetBidiOptions(NS_PTR_TO_INT32(aClosure));
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SetBidiTextDirection(uint8_t aTextDirection)
+NS_IMETHODIMP nsDocumentViewer::SetBidiTextDirection(uint8_t aTextDirection)
 {
   uint32_t bidiOptions;
 
   GetBidiOptions(&bidiOptions);
   SET_BIDI_OPTION_DIRECTION(bidiOptions, aTextDirection);
   SetBidiOptions(bidiOptions);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetBidiTextDirection(uint8_t* aTextDirection)
+NS_IMETHODIMP nsDocumentViewer::GetBidiTextDirection(uint8_t* aTextDirection)
 {
   uint32_t bidiOptions;
 
   if (aTextDirection) {
     GetBidiOptions(&bidiOptions);
     *aTextDirection = GET_BIDI_OPTION_DIRECTION(bidiOptions);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SetBidiTextType(uint8_t aTextType)
+NS_IMETHODIMP nsDocumentViewer::SetBidiTextType(uint8_t aTextType)
 {
   uint32_t bidiOptions;
 
   GetBidiOptions(&bidiOptions);
   SET_BIDI_OPTION_TEXTTYPE(bidiOptions, aTextType);
   SetBidiOptions(bidiOptions);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetBidiTextType(uint8_t* aTextType)
+NS_IMETHODIMP nsDocumentViewer::GetBidiTextType(uint8_t* aTextType)
 {
   uint32_t bidiOptions;
 
   if (aTextType) {
     GetBidiOptions(&bidiOptions);
     *aTextType = GET_BIDI_OPTION_TEXTTYPE(bidiOptions);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SetBidiNumeral(uint8_t aNumeral)
+NS_IMETHODIMP nsDocumentViewer::SetBidiNumeral(uint8_t aNumeral)
 {
   uint32_t bidiOptions;
 
   GetBidiOptions(&bidiOptions);
   SET_BIDI_OPTION_NUMERAL(bidiOptions, aNumeral);
   SetBidiOptions(bidiOptions);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetBidiNumeral(uint8_t* aNumeral)
+NS_IMETHODIMP nsDocumentViewer::GetBidiNumeral(uint8_t* aNumeral)
 {
   uint32_t bidiOptions;
 
   if (aNumeral) {
     GetBidiOptions(&bidiOptions);
     *aNumeral = GET_BIDI_OPTION_NUMERAL(bidiOptions);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SetBidiSupport(uint8_t aSupport)
+NS_IMETHODIMP nsDocumentViewer::SetBidiSupport(uint8_t aSupport)
 {
   uint32_t bidiOptions;
 
   GetBidiOptions(&bidiOptions);
   SET_BIDI_OPTION_SUPPORT(bidiOptions, aSupport);
   SetBidiOptions(bidiOptions);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetBidiSupport(uint8_t* aSupport)
+NS_IMETHODIMP nsDocumentViewer::GetBidiSupport(uint8_t* aSupport)
 {
   uint32_t bidiOptions;
 
   if (aSupport) {
     GetBidiOptions(&bidiOptions);
     *aSupport = GET_BIDI_OPTION_SUPPORT(bidiOptions);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::SetBidiOptions(uint32_t aBidiOptions)
+NS_IMETHODIMP nsDocumentViewer::SetBidiOptions(uint32_t aBidiOptions)
 {
   if (mPresContext) {
     mPresContext->SetBidi(aBidiOptions, true); // could cause reflow
   }
   // now set bidi on all children of mContainer
   CallChildren(SetChildBidiOptions, NS_INT32_TO_PTR(aBidiOptions));
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetBidiOptions(uint32_t* aBidiOptions)
+NS_IMETHODIMP nsDocumentViewer::GetBidiOptions(uint32_t* aBidiOptions)
 {
   if (aBidiOptions) {
     if (mPresContext) {
       *aBidiOptions = mPresContext->GetBidi();
     }
     else
       *aBidiOptions = IBMBIDI_DEFAULT_BIDI_OPTIONS;
   }
@@ -3231,24 +3231,24 @@ NS_IMETHODIMP DocumentViewerImpl::GetBid
 static void
 AppendChildSubtree(nsIMarkupDocumentViewer* aChild, void* aClosure)
 {
   nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >& array =
     *static_cast<nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >*>(aClosure);
   aChild->AppendSubtree(array);
 }
 
-NS_IMETHODIMP DocumentViewerImpl::AppendSubtree(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >& aArray)
+NS_IMETHODIMP nsDocumentViewer::AppendSubtree(nsTArray<nsCOMPtr<nsIMarkupDocumentViewer> >& aArray)
 {
   aArray.AppendElement(this);
   CallChildren(AppendChildSubtree, &aArray);
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::ChangeMaxLineBoxWidth(int32_t aMaxLineBoxWidth)
+NS_IMETHODIMP nsDocumentViewer::ChangeMaxLineBoxWidth(int32_t aMaxLineBoxWidth)
 {
   // Change the max line box width for all children.
   struct LineBoxInfo lbi = { aMaxLineBoxWidth };
   CallChildren(ChangeChildMaxLineBoxWidth, &lbi);
 
   // Now, change our max line box width.
   // Convert to app units, since our input is in CSS pixels.
   nscoord mlbw = nsPresContext::CSSPixelsToAppUnits(aMaxLineBoxWidth);
@@ -3256,17 +3256,17 @@ NS_IMETHODIMP DocumentViewerImpl::Change
   if (presShell) {
     presShell->SetMaxLineBoxWidth(mlbw);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::GetContentSize(int32_t* aWidth, int32_t* aHeight)
+nsDocumentViewer::GetContentSize(int32_t* aWidth, int32_t* aHeight)
 {
    NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
    // Skip doing this on docshell-less documents for now
    nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryReferent(mContainer));
    NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_NOT_AVAILABLE);
    
    nsCOMPtr<nsIDocShellTreeItem> docShellParent;
@@ -3313,33 +3313,33 @@ DocumentViewerImpl::GetContentSize(int32
    *aHeight = presContext->AppUnitsToDevPixels(shellArea.height);
 
    return NS_OK;
 }
 
 
 NS_IMPL_ISUPPORTS1(nsDocViewerSelectionListener, nsISelectionListener)
 
-nsresult nsDocViewerSelectionListener::Init(DocumentViewerImpl *aDocViewer)
+nsresult nsDocViewerSelectionListener::Init(nsDocumentViewer *aDocViewer)
 {
   mDocViewer = aDocViewer;
   return NS_OK;
 }
 
 /*
  * GetPopupNode, GetPopupLinkNode and GetPopupImageNode are helpers
  * for the cmd_copyLink / cmd_copyImageLocation / cmd_copyImageContents family
  * of commands. The focus controller stores the popup node, these retrieve
  * them and munge appropriately. Note that we have to store the popup node
  * rather than retrieving it from EventStateManager::GetFocusedContent because
  * not all content (images included) can receive focus.
  */
 
 nsresult
-DocumentViewerImpl::GetPopupNode(nsIDOMNode** aNode)
+nsDocumentViewer::GetPopupNode(nsIDOMNode** aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   *aNode = nullptr;
 
   // get the document
   nsIDocument* document = GetDocument();
   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
@@ -3370,17 +3370,17 @@ DocumentViewerImpl::GetPopupNode(nsIDOMN
     node.swap(*aNode);
   }
 
   return NS_OK;
 }
 
 // GetPopupLinkNode: return popup link node or fail
 nsresult
-DocumentViewerImpl::GetPopupLinkNode(nsIDOMNode** aNode)
+nsDocumentViewer::GetPopupLinkNode(nsIDOMNode** aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   // you get null unless i say so
   *aNode = nullptr;
 
   // find popup node
   nsCOMPtr<nsIDOMNode> node;
@@ -3407,17 +3407,17 @@ DocumentViewerImpl::GetPopupLinkNode(nsI
   }
 
   // if we have no node, fail
   return NS_ERROR_FAILURE;
 }
 
 // GetPopupLinkNode: return popup image node or fail
 nsresult
-DocumentViewerImpl::GetPopupImageNode(nsIImageLoadingContent** aNode)
+nsDocumentViewer::GetPopupImageNode(nsIImageLoadingContent** aNode)
 {
   NS_ENSURE_ARG_POINTER(aNode);
 
   // you get null unless i say so
   *aNode = nullptr;
 
   // find popup node
   nsCOMPtr<nsIDOMNode> node;
@@ -3436,20 +3436,20 @@ DocumentViewerImpl::GetPopupImageNode(ns
  * These two functions -- GetInLink and GetInImage -- are kind of annoying
  * in that they only get called from the controller (in
  * nsDOMWindowController::IsCommandEnabled). The actual construction of the
  * context menus in communicator (nsContextMenu.js) has its own, redundant
  * tests. No big deal, but good to keep in mind if we ever clean context
  * menus.
  */
 
-NS_IMETHODIMP DocumentViewerImpl::GetInLink(bool* aInLink)
+NS_IMETHODIMP nsDocumentViewer::GetInLink(bool* aInLink)
 {
 #ifdef DEBUG_dr
-  printf("dr :: DocumentViewerImpl::GetInLink\n");
+  printf("dr :: nsDocumentViewer::GetInLink\n");
 #endif
 
   NS_ENSURE_ARG_POINTER(aInLink);
 
   // we're not in a link unless i say so
   *aInLink = false;
 
   // get the popup link
@@ -3458,20 +3458,20 @@ NS_IMETHODIMP DocumentViewerImpl::GetInL
   if (NS_FAILED(rv)) return rv;
   NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
 
   // if we made it here, we're in a link
   *aInLink = true;
   return NS_OK;
 }
 
-NS_IMETHODIMP DocumentViewerImpl::GetInImage(bool* aInImage)
+NS_IMETHODIMP nsDocumentViewer::GetInImage(bool* aInImage)
 {
 #ifdef DEBUG_dr
-  printf("dr :: DocumentViewerImpl::GetInImage\n");
+  printf("dr :: nsDocumentViewer::GetInImage\n");
 #endif
 
   NS_ENSURE_ARG_POINTER(aInImage);
 
   // we're not in an image unless i say so
   *aInImage = false;
 
   // get the popup image
@@ -3558,30 +3558,30 @@ nsDocViewerFocusListener::HandleEvent(ns
       selCon->RepaintSelection(nsISelectionController::SELECTION_NORMAL);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
-nsDocViewerFocusListener::Init(DocumentViewerImpl *aDocViewer)
+nsDocViewerFocusListener::Init(nsDocumentViewer *aDocViewer)
 {
   mDocViewer = aDocViewer;
   return NS_OK;
 }
 
 /** ---------------------------------------------------
  *  From nsIWebBrowserPrint
  */
 
 #ifdef NS_PRINTING
 
 NS_IMETHODIMP
-DocumentViewerImpl::Print(nsIPrintSettings*       aPrintSettings,
+nsDocumentViewer::Print(nsIPrintSettings*       aPrintSettings,
                           nsIWebProgressListener* aWebProgressListener)
 {
 
 #ifdef MOZ_XUL
   // Temporary code for Bug 136185 / Bug 240490
   nsCOMPtr<nsIXULDocument> xulDoc(do_QueryInterface(mDocument));
   if (xulDoc) {
     nsPrintEngine::ShowPrintErrorDialog(NS_ERROR_GFX_PRINTER_NO_XUL);
@@ -3666,17 +3666,17 @@ DocumentViewerImpl::Print(nsIPrintSettin
   rv = mPrintEngine->Print(aPrintSettings, aWebProgressListener);
   if (NS_FAILED(rv)) {
     OnDonePrinting();
   }
   return rv;
 }
 
 NS_IMETHODIMP
-DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, 
+nsDocumentViewer::PrintPreview(nsIPrintSettings* aPrintSettings, 
                                  nsIDOMWindow *aChildDOMWin, 
                                  nsIWebProgressListener* aWebProgressListener)
 {
 #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW)
   NS_WARN_IF_FALSE(IsInitializedForPrintPreview(),
                    "Using docshell.printPreview is the preferred way for print previewing!");
 
   NS_ENSURE_ARG_POINTER(aChildDOMWin);
@@ -3741,17 +3741,17 @@ DocumentViewerImpl::PrintPreview(nsIPrin
   return rv;
 #else