Merge last green changeset from mozilla-inbound to mozilla-central
authorMarco Bonardo <mbonardo@mozilla.com>
Fri, 02 Dec 2011 12:11:31 +0100
changeset 81143 1c13e42d24fa38bf6743d28b7c57528c4fd7df4c
parent 81099 c101c5f8c9280076d5f8c2c43751518347938d8a (current diff)
parent 81142 eeadcd101dcb731df78a923cdc570a9456306f49 (diff)
child 81154 68f5a67587700e5c35517f418e922bbb87efe60e
child 81163 93c850b9f00f1c76cb973050442e87d91c23f558
push id21559
push usermak77@bonardo.net
push dateFri, 02 Dec 2011 11:12:13 +0000
treeherdermozilla-central@1c13e42d24fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone11.0a1
first release with
nightly win64
1c13e42d24fa / 11.0a1 / 20111202031055 / files
nightly linux32
nightly linux64
nightly mac
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win64
Merge last green changeset from mozilla-inbound to mozilla-central
js/src/jit-test/tests/basic/bug685321.js
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -391,30 +391,31 @@ nsRootAccessible::ProcessDOMEvent(nsIDOM
   nsINode* targetNode = accessible->GetNode();
 
 #ifdef MOZ_XUL
   nsRefPtr<nsXULTreeAccessible> treeAcc;
   if (targetNode->IsElement() &&
       targetNode->AsElement()->NodeInfo()->Equals(nsGkAtoms::tree,
                                                   kNameSpaceID_XUL)) {
     treeAcc = do_QueryObject(accessible);
-
-    if (eventType.EqualsLiteral("TreeViewChanged")) {
-      treeAcc->TreeViewChanged();
-      return;
-    }
+    if (treeAcc) {
+      if (eventType.EqualsLiteral("TreeViewChanged")) {
+        treeAcc->TreeViewChanged();
+        return;
+      }
 
-    if (eventType.EqualsLiteral("TreeRowCountChanged")) {
-      HandleTreeRowCountChangedEvent(aDOMEvent, treeAcc);
-      return;
-    }
+      if (eventType.EqualsLiteral("TreeRowCountChanged")) {
+        HandleTreeRowCountChangedEvent(aDOMEvent, treeAcc);
+        return;
+      }
 
-    if (eventType.EqualsLiteral("TreeInvalidated")) {
-      HandleTreeInvalidatedEvent(aDOMEvent, treeAcc);
-      return;
+      if (eventType.EqualsLiteral("TreeInvalidated")) {
+        HandleTreeInvalidatedEvent(aDOMEvent, treeAcc);
+        return;
+      }
     }
   }
 #endif
 
   if (eventType.EqualsLiteral("RadioStateChange")) {
     PRUint64 state = accessible->State();
 
     // radiogroup in prefWindow is exposed as a list,
--- a/browser/components/build/nsBrowserCompsCID.h
+++ b/browser/components/build/nsBrowserCompsCID.h
@@ -46,19 +46,16 @@
 #ifdef XP_MACOSX
 #define NS_SAFARIPROFILEMIGRATOR_CID \
 { 0x29e3b139, 0xad19, 0x44f3, { 0xb2, 0xc2, 0xe9, 0xf1, 0x3b, 0xa2, 0xbb, 0xc6 } }
 #endif
 
 #define NS_OPERAPROFILEMIGRATOR_CID \
 { 0xf34ff792, 0x722e, 0x4490, { 0xb1, 0x95, 0x47, 0xd2, 0x42, 0xed, 0xca, 0x1c } }
 
-#define NS_SEAMONKEYPROFILEMIGRATOR_CID \
-{ 0x9a28ffa7, 0xe6ef, 0x4b52, { 0xa1, 0x27, 0x6a, 0xd9, 0x51, 0xde, 0x8e, 0x9b } }
-
 #define NS_SHELLSERVICE_CID \
 { 0x63c7b9f4, 0xcc8, 0x43f8, { 0xb6, 0x66, 0xa, 0x66, 0x16, 0x55, 0xcb, 0x73 } }
 
 #define NS_SHELLSERVICE_CONTRACTID \
   "@mozilla.org/browser/shell-service;1"
 
 #define NS_RDF_FORWARDPROXY_INFER_DATASOURCE_CID \
 { 0x7a024bcf, 0xedd5, 0x4d9a, { 0x86, 0x14, 0xd4, 0x4b, 0xe1, 0xda, 0xda, 0xd3 } }
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -181,18 +181,18 @@ var MigrationWizard = {
       if (this._autoMigrate)
         this._wiz.currentPage.next = "homePageImport";
       else if (this._bookmarks)
         this._wiz.currentPage.next = "migrating"
       else
         this._wiz.currentPage.next = "importItems";
 
       var sourceProfiles = this._migrator.sourceProfiles;
-      if (sourceProfiles && sourceProfiles.Count() == 1) {
-        var profileName = sourceProfiles.QueryElementAt(0, Components.interfaces.nsISupportsString);
+      if (sourceProfiles && sourceProfiles.length == 1) {
+        var profileName = sourceProfiles.queryElementAt(0, Ci.nsISupportsString);
         this._selectedProfile = profileName.data;
       }
       else
         this._selectedProfile = "";
     }
   },
   
   // 2 - [Profile Selection]
@@ -206,20 +206,19 @@ var MigrationWizard = {
     var profiles = document.getElementById("profiles");
     while (profiles.hasChildNodes()) 
       profiles.removeChild(profiles.firstChild);
     
     // Note that this block is still reached even if the user chose 'From File'
     // and we canceled the dialog.  When that happens, _migrator will be null.
     if (this._migrator) {
       var sourceProfiles = this._migrator.sourceProfiles;
-      var count = sourceProfiles.Count();
-      for (var i = 0; i < count; ++i) {
+      for (var i = 0; i < sourceProfiles.length; ++i) {
         var item = document.createElement("radio");
-        var str = sourceProfiles.QueryElementAt(i, Components.interfaces.nsISupportsString);
+        var str = sourceProfiles.queryElementAt(i, Ci.nsISupportsString);
         item.id = str.data;
         item.setAttribute("label", str.data);
         profiles.appendChild(item);
       }
     }
     
     profiles.selectedItem = this._selectedProfile ? document.getElementById(this._selectedProfile) : profiles.firstChild;
   },
--- a/browser/components/migration/public/nsIBrowserProfileMigrator.idl
+++ b/browser/components/migration/public/nsIBrowserProfileMigrator.idl
@@ -31,20 +31,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
-interface nsISupportsArray;
+interface nsIArray;
 interface nsIProfileStartup;
 
-[scriptable, uuid(f8365b4a-da55-4e47-be7a-230142360f62)]
+[scriptable, uuid(5f445759-86a8-4dd3-ab84-4fc5341d9d9d)]
 interface nsIBrowserProfileMigrator : nsISupports 
 {
   /**
    * profile items to migrate. use with migrate().
    */
   const unsigned short ALL         = 0x0000;
   const unsigned short SETTINGS    = 0x0001;
   const unsigned short COOKIES     = 0x0002;
@@ -63,17 +63,18 @@ interface nsIBrowserProfileMigrator : ns
   void migrate(in unsigned short aItems, in nsIProfileStartup aStartup, in wstring aProfile);
 
   /**
    * A bit field containing profile items that this migrator
    * offers for import. 
    * @param   aProfile the profile that we are looking for available data
    *          to import
    * @param   aDoingStartup "true" if the profile is not currently being used.
-   * @returns bit field containing profile items (see above)
+   * @return  bit field containing profile items (see above)
+   * @note    a return value of 0 represents no items rather than ALL.
    */
   unsigned short getMigrateData(in wstring aProfile, in boolean aDoingStartup);
 
   /** 
    * Whether or not there is any data that can be imported from this 
    * browser (i.e. whether or not it is installed, and there exists
    * a user profile)
    */
@@ -84,15 +85,15 @@ interface nsIBrowserProfileMigrator : ns
    * has multiple user profiles configured.
    */
   readonly attribute boolean          sourceHasMultipleProfiles;
 
   /** 
    * An enumeration of available profiles. If the import source does 
    * not support profiles, this attribute is null.
    */
-  readonly attribute nsISupportsArray sourceProfiles;
-  
+  readonly attribute nsIArray         sourceProfiles;
+
   /**
    * The import source homepage.  Returns null if not present/available
    */
   readonly attribute AUTF8String      sourceHomePageURL;
 };
--- a/browser/components/migration/src/ChromeProfileMigrator.js
+++ b/browser/components/migration/src/ChromeProfileMigrator.js
@@ -34,16 +34,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
+const Cr = Components.results;
 
 const LOCAL_FILE_CID = "@mozilla.org/file/local;1";
 const FILE_INPUT_STREAM_CID = "@mozilla.org/network/file-input-stream;1";
 
 const BUNDLE_MIGRATION = "chrome://browser/locale/migration/migration.properties";
 
 const MIGRATE_ALL = 0x0000;
 const MIGRATE_SETTINGS = 0x0001;
@@ -67,31 +68,31 @@ XPCOMUtils.defineLazyGetter(this, "bookm
   let strbundle =
     Services.strings.createBundle(BUNDLE_MIGRATION);
   let sourceNameChrome = strbundle.GetStringFromName("sourceNameChrome");
   return strbundle.formatStringFromName("importedBookmarksFolder",
                                         [sourceNameChrome],
                                         1);
 });
 
-/*
+/**
  * Convert Chrome time format to Date object
  *
  * @param   aTime
  *          Chrome time 
  * @return  converted Date object
  * @note    Google Chrome uses FILETIME / 10 as time.
  *          FILETIME is based on same structure of Windows.
  */
 function chromeTimeToDate(aTime)
 {
   return new Date((aTime * S100NS_PER_MS - S100NS_FROM1601TO1970 ) / 10000);
 }
 
-/*
+/**
  * Insert bookmark items into specific folder.
  *
  * @param   aFolderId
  *          id of folder where items will be inserted
  * @param   aItems
  *          bookmark items to be inserted
  */
 function insertBookmarkItems(aFolderId, aItems)
@@ -124,51 +125,64 @@ function ChromeProfileMigrator()
 }
 
 ChromeProfileMigrator.prototype = {
   _paths: {
     bookmarks : null,
     cookies : null,
     history : null,
     prefs : null,
+    userData : null,
   },
 
   _homepageURL : null,
   _replaceBookmarks : false,
+  _sourceProfile: null,
+  _profilesCache: null,
 
-  /*
+  /**
    * Notify to observers to start migration
    *
    * @param   aType
    *          notification type such as MIGRATE_BOOKMARKS
    */
-
   _notifyStart : function Chrome_notifyStart(aType)
   {
     Services.obs.notifyObservers(null, "Migration:ItemBeforeMigrate", aType);
     this._pendingCount++;
   },
 
-  /*
+  /**
+   * Notify observers that a migration error occured with an item
+   *
+   * @param   aType
+   *          notification type such as MIGRATE_BOOKMARKS
+   */
+  _notifyError : function Chrome_notifyError(aType)
+  {
+    Services.obs.notifyObservers(null, "Migration:ItemError", aType);
+  },
+
+  /**
    * Notify to observers to finish migration for item
    * If all items are finished, it sends migration end notification.
    *
    * @param   aType
    *          notification type such as MIGRATE_BOOKMARKS
    */
   _notifyCompleted : function Chrome_notifyIfCompleted(aType)
   {
     Services.obs.notifyObservers(null, "Migration:ItemAfterMigrate", aType);
     if (--this._pendingCount == 0) {
       // All items are migrated, so we have to send end notification.
       Services.obs.notifyObservers(null, "Migration:Ended", null);
     }
   },
 
-  /*
+  /**
    * Migrating bookmark items
    */
   _migrateBookmarks : function Chrome_migrateBookmarks()
   {
     this._notifyStart(MIGRATE_BOOKMARKS);
 
     try {
       PlacesUtils.bookmarks.runInBatchMode({
@@ -219,21 +233,22 @@ ChromeProfileMigrator.prototype = {
             }
 
             migrator._notifyCompleted(MIGRATE_BOOKMARKS);
           });
         }
       }, null);
     } catch (e) {
       Cu.reportError(e);
+      this._notifyError(MIGRATE_BOOKMARKS);
       this._notifyCompleted(MIGRATE_BOOKMARKS);
     }
   },
 
-  /*
+  /**
    * Migrating history
    */
   _migrateHistory : function Chrome_migrateHistory()
   {
     this._notifyStart(MIGRATE_HISTORY);
 
     try {
       PlacesUtils.history.runInBatchMode({
@@ -293,21 +308,22 @@ ChromeProfileMigrator.prototype = {
               this._self._notifyCompleted(MIGRATE_HISTORY);
             }
           });
           stmt.finalize();
         }
       }, null);
     } catch (e) {
       Cu.reportError(e);
+      this._notifyError(MIGRATE_HISTORY);
       this._notifyCompleted(MIGRATE_HISTORY);
     }
   },
 
-  /*
+  /**
    * Migrating cookies
    */
   _migrateCookies : function Chrome_migrateCookies()
   {
     this._notifyStart(MIGRATE_COOKIES);
 
     try {
       // Access sqlite3 database of Chrome's cookie
@@ -354,41 +370,44 @@ ChromeProfileMigrator.prototype = {
         handleCompletion : function(aReason) {
           this._db.asyncClose();
           this._self._notifyCompleted(MIGRATE_COOKIES);
         },
       });
       stmt.finalize();
     } catch (e) {
       Cu.reportError(e);
+      this._notifyError(MIGRATE_COOKIES);
       this._notifyCompleted(MIGRATE_COOKIES);
     }
   },
 
-  /*
+  /**
    * nsIBrowserProfileMigrator interface implementation
    */
 
-  /*
+  /**
    * Let's migrate all items
    *
    * @param   aItems
-   *          list of data items to migrate.  but this is unused.
+   *          list of data items to migrate.
    * @param   aStartup
    *          non-null if called during startup.
    * @param   aProfile
-   *          this is unused due to single profile support only
+   *          profile directory name to migrate
    */
   migrate : function Chrome_migrate(aItems, aStartup, aProfile)
   {
     if (aStartup) {
       aStartup.doStartup();
       this._replaceBookmarks = true;
     }
 
+    this._sourceProfile = aProfile;
+
     Services.obs.notifyObservers(null, "Migration:Started", null);
 
     // Reset panding count.  If this count becomes 0, "Migration:Ended"
     // notification is sent
     this._pendingCount = 1;
 
     if (aItems & MIGRATE_HISTORY)
       this._migrateHistory();
@@ -402,112 +421,174 @@ ChromeProfileMigrator.prototype = {
     if (--this._pendingCount == 0) {
       // When async imports are immeditelly completed unfortunately,
       // this will be called.
       // Usually, this notification is sent by _notifyCompleted()
       Services.obs.notifyObservers(null, "Migration:Ended", null);
     }
   },
 
-  /*
+  /**
    * return supported migration types
    *
    * @param   aProfile
-   *          this is unused due to single profile support only
+   *          directory name of the profile
    * @param   aDoingStartup
    *          non-null if called during startup.
    * @return  supported migration types
    */
   getMigrateData: function Chrome_getMigrateData(aProfile, aDoingStartup)
   {
-#ifdef XP_WIN
-    let chromepath = Services.dirsvc.get("LocalAppData", Ci.nsIFile).path +
-                     "\\Google\\Chrome\\User Data\\Default\\";
-#elifdef XP_MACOSX
-    let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
-                     "/Library/Application Support/Google/Chrome/Default/";
-#else
-    let chromepath = Services.dirsvc.get("Home", Ci.nsIFile).path +
-                     "/.config/google-chrome/Default/";
-#endif
+    this._sourceProfile = aProfile;
+    let chromeProfileDir = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+    chromeProfileDir.initWithPath(this._paths.userData + aProfile);
 
     let result = 0;
+    if (!chromeProfileDir.exists() || !chromeProfileDir.isReadable())
+      return result;
 
     // bookmark and preference are JSON format
 
     try {
-      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
-      file.initWithPath(chromepath + "Bookmarks");
+      let file = chromeProfileDir.clone();
+      file.append("Bookmarks");
       if (file.exists()) {
-        this._paths.bookmarks = file.path
+        this._paths.bookmarks = file.path;
         result += MIGRATE_BOOKMARKS;
       }
     } catch (e) {
       Cu.reportError(e);
     }
 
-    if (!this._paths.prefs)
-      this._paths.prefs = chromepath + "Preferences";
+    if (!this._paths.prefs) {
+      let file = chromeProfileDir.clone();
+      file.append("Preferences");
+      this._paths.prefs = file.path;
+    }
 
     // history and cookies are SQLite database
 
     try {
-      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
-      file.initWithPath(chromepath + "History");
+      let file = chromeProfileDir.clone();
+      file.append("History");
       if (file.exists()) {
-        this._paths.history = file.path
+        this._paths.history = file.path;
         result += MIGRATE_HISTORY;
       }
     } catch (e) {
       Cu.reportError(e);
     }
 
     try {
-      let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
-      file.initWithPath(chromepath + "Cookies");
+      let file = chromeProfileDir.clone();
+      file.append("Cookies");
       if (file.exists()) {
-        this._paths.cookies = file.path
+        this._paths.cookies = file.path;
         result += MIGRATE_COOKIES;
       }
     } catch (e) {
       Cu.reportError(e);
     }
 
     return result;
   },
 
-  /*
+  /**
    * Whether we support migration of Chrome
    *
    * @return true if supported
    */
   get sourceExists()
   {
-    let result = this.getMigrateData(null, false);
-    return result != 0;
+#ifdef XP_WIN
+    this._paths.userData = Services.dirsvc.get("LocalAppData", Ci.nsIFile).path +
+                            "\\Google\\Chrome\\User Data\\";
+#elifdef XP_MACOSX
+    this._paths.userData = Services.dirsvc.get("Home", Ci.nsIFile).path +
+                            "/Library/Application Support/Google/Chrome/";
+#else
+    this._paths.userData = Services.dirsvc.get("Home", Ci.nsIFile).path +
+                            "/.config/google-chrome/";
+#endif
+    let result = 0;
+    try {
+      let userDataDir = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+      userDataDir.initWithPath(this._paths.userData);
+      if (!userDataDir.exists() || !userDataDir.isReadable())
+        return false;
+
+      let profiles = this.sourceProfiles;
+      if (profiles.length < 1)
+        return false;
+
+      // check that we can actually get data from the first profile
+      result = this.getMigrateData(profiles.queryElementAt(0, Ci.nsISupportsString), false);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+    return result > 0;
+  },
+
+  get sourceHasMultipleProfiles()
+  {
+    return this.sourceProfiles.length > 1;
   },
 
-  // Although Chrome supports multi-profiles, there is no way
-  // to get profile lists.
-  sourceHasMultipleProfiles: false,
-  sourceProfiles: null,
+  get sourceProfiles()
+  {
+    let profiles = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+    try {
+      if (!this._profilesCache) {
+        let localState = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
+        // Local State is a JSON file that contains profile info.
+        localState.initWithPath(this._paths.userData + "Local State");
+        if (!localState.exists())
+          throw new Components.Exception("Chrome's 'Local State' file does not exist.",
+                                         Cr.NS_ERROR_FILE_NOT_FOUND);
+        if (!localState.isReadable())
+          throw new Components.Exception("Chrome's 'Local State' file could not be read.",
+                                         Cr.NS_ERROR_FILE_ACCESS_DENIED);
+        let fstream = Cc[FILE_INPUT_STREAM_CID].createInstance(Ci.nsIFileInputStream);
+        fstream.init(localState, -1, 0, 0);
+        let inputStream = NetUtil.readInputStreamToString(fstream, fstream.available(),
+                                                          { charset: "UTF-8" });
+        this._profilesCache = JSON.parse(inputStream).profile.info_cache;
+      }
 
-  /*
+      for (let index in this._profilesCache) {
+        let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+        str.data = index;
+        profiles.appendElement(str, false);
+      }
+    } catch (e) {
+      Cu.reportError("Error detecting Chrome profiles: " + e);
+      // if we weren't able to detect any profiles above, fallback to the Default profile.
+      if (profiles.length < 1) {
+        let str = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+        // the default profile name is "Default"
+        str.data = "Default";
+        profiles.appendElement(str, false);
+      }
+    }
+    return profiles;
+  },
+
+  /**
    * Return home page URL
    *
    * @return  home page URL
    */
   get sourceHomePageURL()
   {
     try  {
       if (this._homepageURL)
         return this._homepageURL;
 
       if (!this._paths.prefs)
-        this.getMigrateData(null, false);
+        this.getMigrateData(this._sourceProfile, false);
 
       // XXX reading and parsing JSON is synchronous.
       let file = Cc[LOCAL_FILE_CID].createInstance(Ci.nsILocalFile);
       file.initWithPath(this._paths.prefs);
       let fstream = Cc[FILE_INPUT_STREAM_CID].
                     createInstance(Ci.nsIFileInputStream);
       fstream.init(file, -1, 0, 0); 
       this._homepageURL = JSON.parse(
--- a/browser/components/migration/src/nsBrowserProfileMigratorUtils.cpp
+++ b/browser/components/migration/src/nsBrowserProfileMigratorUtils.cpp
@@ -49,17 +49,16 @@
 
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsISupportsPrimitives.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIRDFService.h"
 #include "nsIStringBundle.h"
-#include "nsISupportsArray.h"
 #include "nsXPCOMCID.h"
 
 #define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
 
 #define BOOKMARKS_FILE_NAME NS_LITERAL_STRING("bookmarks.html")
 
 void SetUnicharPref(const char* aPref, const nsAString& aValue,
                     nsIPrefBranch* aPrefs)
--- a/browser/components/migration/src/nsIEProfileMigrator.cpp
+++ b/browser/components/migration/src/nsIEProfileMigrator.cpp
@@ -60,17 +60,16 @@
 #include "prlong.h"
 #include "nsICookieManager2.h"
 #include "nsIEProfileMigrator.h"
 #include "nsIFile.h"
 #include "nsILocalFile.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsISimpleEnumerator.h"
-#include "nsISupportsArray.h"
 #include "nsIProfileMigrator.h"
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIObserverService.h"
 #include "nsILocalFileWin.h"
 #include "nsAutoPtr.h"
 
 #include "prnetdb.h"
 
@@ -481,17 +480,17 @@ nsIEProfileMigrator::GetSourceExists(boo
 NS_IMETHODIMP
 nsIEProfileMigrator::GetSourceHasMultipleProfiles(bool* aResult)
 {
   *aResult = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsIEProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
+nsIEProfileMigrator::GetSourceProfiles(nsIArray** aResult)
 {
   *aResult = nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIEProfileMigrator::GetSourceHomePageURL(nsACString& aResult)
 {
--- a/browser/components/migration/src/nsOperaProfileMigrator.cpp
+++ b/browser/components/migration/src/nsOperaProfileMigrator.cpp
@@ -165,56 +165,56 @@ nsOperaProfileMigrator::GetMigrateData(c
                           aReplace, mOperaProfile, aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOperaProfileMigrator::GetSourceExists(bool* aResult)
 {
-  nsCOMPtr<nsISupportsArray> profiles;
+  nsCOMPtr<nsIArray> profiles;
   GetSourceProfiles(getter_AddRefs(profiles));
 
   if (profiles) { 
     PRUint32 count;
-    profiles->Count(&count);
+    profiles->GetLength(&count);
     *aResult = count > 0;
   }
   else
     *aResult = false;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOperaProfileMigrator::GetSourceHasMultipleProfiles(bool* aResult)
 {
-  nsCOMPtr<nsISupportsArray> profiles;
+  nsCOMPtr<nsIArray> profiles;
   GetSourceProfiles(getter_AddRefs(profiles));
 
 #ifdef XP_WIN
   if (profiles) {
     PRUint32 count;
-    profiles->Count(&count);
+    profiles->GetLength(&count);
     *aResult = count > 1;
   }
   else
 #endif
     *aResult = false;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsOperaProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
+nsOperaProfileMigrator::GetSourceProfiles(nsIArray** aResult)
 {
   if (!mProfiles) {
     nsresult rv;
 
-    mProfiles = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
+    mProfiles = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     if (NS_FAILED(rv)) return rv;
 
     nsCOMPtr<nsIProperties> fileLocator(do_GetService("@mozilla.org/file/directory_service;1"));
     nsCOMPtr<nsILocalFile> file;
 #ifdef XP_WIN
     fileLocator->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
 
     // Opera profile lives under %APP_DATA%\Opera\<operaver>\profile 
@@ -233,47 +233,47 @@ nsOperaProfileMigrator::GetSourceProfile
 
       bool isDirectory = false;
       curr->IsDirectory(&isDirectory);
       if (isDirectory) {
         nsCOMPtr<nsISupportsString> string(do_CreateInstance("@mozilla.org/supports-string;1"));
         nsAutoString leafName;
         curr->GetLeafName(leafName);
         string->SetData(leafName);
-        mProfiles->AppendElement(string);
+        mProfiles->AppendElement(string, false);
       }
 
       e->HasMoreElements(&hasMore);
     }
 #elif defined (XP_MACOSX)
     fileLocator->Get(NS_MAC_USER_LIB_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
     
     file->Append(NS_LITERAL_STRING("Preferences"));
     file->Append(OPERA_PREFERENCES_FOLDER_NAME);
     
     bool exists;
     file->Exists(&exists);
     
     if (exists) {
       nsCOMPtr<nsISupportsString> string(do_CreateInstance("@mozilla.org/supports-string;1"));
       string->SetData(OPERA_PREFERENCES_FOLDER_NAME);
-      mProfiles->AppendElement(string);
+      mProfiles->AppendElement(string, false);
     }
 #elif defined (XP_UNIX)
     fileLocator->Get(NS_UNIX_HOME_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(file));
     
     file->Append(OPERA_PREFERENCES_FOLDER_NAME);
     
     bool exists;
     file->Exists(&exists);
     
     if (exists) {
       nsCOMPtr<nsISupportsString> string(do_CreateInstance("@mozilla.org/supports-string;1"));
       string->SetData(OPERA_PREFERENCES_FOLDER_NAME);
-      mProfiles->AppendElement(string);
+      mProfiles->AppendElement(string, false);
     }
 #endif
   }
 
   *aResult = mProfiles;
   NS_IF_ADDREF(*aResult);
   return NS_OK;
 }
--- a/browser/components/migration/src/nsOperaProfileMigrator.h
+++ b/browser/components/migration/src/nsOperaProfileMigrator.h
@@ -37,19 +37,19 @@
  
 #ifndef operaprofilemigrator___h___
 #define operaprofilemigrator___h___
 
 #include "nsCOMPtr.h"
 #include "nsIBinaryInputStream.h"
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIObserverService.h"
-#include "nsISupportsArray.h"
 #include "nsStringAPI.h"
 #include "nsTArray.h"
+#include "nsIMutableArray.h"
 #include "nsINavHistoryService.h"
 #include "nsIStringBundle.h"
 
 class nsICookieManager2;
 class nsILineInputStream;
 class nsILocalFile;
 class nsINIParser;
 class nsIPermissionManager;
@@ -139,17 +139,17 @@ protected:
                              nsIStringBundle* aBundle, 
                              PRInt64 aParentFolder);
 #endif // defined(XP_WIN) || (defined(XP_UNIX) && !defined(XP_MACOSX))
 
   void     GetOperaProfile(const PRUnichar* aProfile, nsILocalFile** aFile);
 
 private:
   nsCOMPtr<nsILocalFile> mOperaProfile;
-  nsCOMPtr<nsISupportsArray> mProfiles;
+  nsCOMPtr<nsIMutableArray> mProfiles;
   nsCOMPtr<nsIObserverService> mObserverService;
 };
 
 class nsOperaCookieMigrator
 {
 public:
   nsOperaCookieMigrator(nsIInputStream* aSourceStream);
   virtual ~nsOperaCookieMigrator();
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -40,17 +40,17 @@
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIComponentManager.h"
 #include "nsIDOMWindow.h"
 #include "nsILocalFile.h"
 #include "nsIObserverService.h"
 #include "nsIProperties.h"
 #include "nsIServiceManager.h"
 #include "nsISupportsPrimitives.h"
-#include "nsISupportsArray.h"
+#include "nsIMutableArray.h"
 #include "nsIToolkitProfile.h"
 #include "nsIToolkitProfileService.h"
 #include "nsIWindowWatcher.h"
 
 #include "nsCOMPtr.h"
 #include "nsBrowserCompsCID.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDirectoryServiceDefs.h"
@@ -122,23 +122,22 @@ nsProfileMigrator::Migrate(nsIProfileSta
   nsCOMPtr<nsISupportsCString> cstr
     (do_CreateInstance("@mozilla.org/supports-cstring;1"));
   if (!cstr) return NS_ERROR_OUT_OF_MEMORY;
   cstr->SetData(key);
 
   // By opening the Migration FE with a supplied bpm, it will automatically
   // migrate from it. 
   nsCOMPtr<nsIWindowWatcher> ww(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
-  nsCOMPtr<nsISupportsArray> params = 
-    do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID);
+  nsCOMPtr<nsIMutableArray> params = do_CreateInstance(NS_ARRAY_CONTRACTID);
   if (!ww || !params) return NS_ERROR_FAILURE;
 
-  params->AppendElement(cstr);
-  params->AppendElement(bpm);
-  params->AppendElement(aStartup);
+  params->AppendElement(cstr, false);
+  params->AppendElement(bpm, false);
+  params->AppendElement(aStartup, false);
 
   nsCOMPtr<nsIDOMWindow> migrateWizard;
   return ww->OpenWindow(nsnull, 
                         MIGRATION_WIZARD_FE_URL,
                         "_blank",
                         MIGRATION_WIZARD_FE_FEATURES,
                         params,
                         getter_AddRefs(migrateWizard));
--- a/browser/components/migration/src/nsSafariProfileMigrator.cpp
+++ b/browser/components/migration/src/nsSafariProfileMigrator.cpp
@@ -54,17 +54,16 @@
 #include "nsIProfileMigrator.h"
 #include "nsIProtocolHandler.h"
 #include "nsIRDFContainer.h"
 #include "nsIRDFDataSource.h"
 #include "nsIRDFRemoteDataSource.h"
 #include "nsIRDFService.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
-#include "nsISupportsArray.h"
 #include "nsISupportsPrimitives.h"
 #include "nsSafariProfileMigrator.h"
 #include "nsToolkitCompsCID.h"
 #include "nsNetUtil.h"
 #include "nsTArray.h"
 
 #include <Carbon/Carbon.h>
 
@@ -197,17 +196,17 @@ NS_IMETHODIMP
 nsSafariProfileMigrator::GetSourceHasMultipleProfiles(bool* aResult)
 {
   // Safari only has one profile per-user.
   *aResult = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSafariProfileMigrator::GetSourceProfiles(nsISupportsArray** aResult)
+nsSafariProfileMigrator::GetSourceProfiles(nsIArray** aResult)
 {
   *aResult = nsnull;
   return NS_OK;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // nsSafariProfileMigrator
 
--- a/browser/components/migration/src/nsSafariProfileMigrator.h
+++ b/browser/components/migration/src/nsSafariProfileMigrator.h
@@ -36,17 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef safariprofilemigrator___h___
 #define safariprofilemigrator___h___
 
 #include "nsIBrowserProfileMigrator.h"
 #include "nsIObserverService.h"
-#include "nsISupportsArray.h"
 #include "nsStringAPI.h"
 #include "nsINavHistoryService.h"
 
 #include <CoreFoundation/CoreFoundation.h>
 
 class nsIRDFDataSource;
 
 class nsSafariProfileMigrator : public nsIBrowserProfileMigrator,
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -2215,17 +2215,19 @@ InspectorProgressListener.prototype = {
           GetStringFromName("confirmNavigationAway.buttonLeave"),
         accessKey: this.IUI.strings.
           GetStringFromName("confirmNavigationAway.buttonLeaveAccesskey"),
         callback: function onButtonLeave() {
           if (aRequest) {
             aRequest.resume();
             aRequest = null;
             this.IUI.closeInspectorUI();
+            return true;
           }
+          return false;
         }.bind(this),
       },
       {
         id: "inspector.confirmNavigationAway.buttonStay",
         label: this.IUI.strings.
           GetStringFromName("confirmNavigationAway.buttonStay"),
         accessKey: this.IUI.strings.
           GetStringFromName("confirmNavigationAway.buttonStayAccesskey"),
--- a/browser/locales/en-US/chrome/browser/migration/migration.dtd
+++ b/browser/locales/en-US/chrome/browser/migration/migration.dtd
@@ -4,18 +4,16 @@
 <!ENTITY importFrom.label               "Import Options, Bookmarks, History, Passwords and other data from:">
 <!ENTITY importFromUnix.label           "Import Preferences, Bookmarks, History, Passwords and other data from:">
 <!ENTITY importFromBookmarks.label      "Import Bookmarks from:">
 
 <!ENTITY importFromIE.label             "Microsoft Internet Explorer">
 <!ENTITY importFromIE.accesskey         "M">
 <!ENTITY importFromNothing.label        "Don't import anything">
 <!ENTITY importFromNothing.accesskey    "D">
-<!ENTITY importFromSeamonkey.label      "Netscape 6, 7 or Mozilla 1.x">
-<!ENTITY importFromSeamonkey.accesskey  "N">
 <!ENTITY importFromOpera.label          "Opera">
 <!ENTITY importFromOpera.accesskey      "O">
 <!ENTITY importFromSafari.label         "Safari">
 <!ENTITY importFromSafari.accesskey     "S">
 <!ENTITY importFromChrome.label         "Chrome">
 <!ENTITY importFromChrome.accesskey     "C">
 <!ENTITY importFromHTMLFile.label       "From an HTML File">
 <!ENTITY importFromHTMLFile.accesskey   "F">
--- a/browser/locales/en-US/chrome/browser/migration/migration.properties
+++ b/browser/locales/en-US/chrome/browser/migration/migration.properties
@@ -1,62 +1,53 @@
 profileName_format=%S %S
 
 # Browser Specific
 sourceNameIE=Internet Explorer
-sourceNameSeamonkey=Netscape 6/7/Mozilla
 sourceNameOpera=Opera
 sourceNameSafari=Safari
 sourceNameChrome=Google Chrome
 
 importedBookmarksFolder=From %S
 importedSearchURLsFolder=Keyword Searches (From %S)
 importedSearchURLsTitle=Search on %S
 importedSearchUrlDesc=Type "%S <search query>" in the Location Bar to perform a search on %S.
 
-importedSeamonkeyBookmarksTitle=From Netscape 6/7/Mozilla
 importedSafariBookmarks=From Safari
 importedOperaHotlistTitle=From Opera
 importedOperaSearchUrls=Keyword Searches (From Opera)
 
 # Import Sources
 1_ie=Internet Options
 1_opera=Preferences
-1_seamonkey=Preferences
 1_safari=Preferences
 1_chrome=Preferences
 
 2_ie=Cookies
 2_opera=Cookies
-2_seamonkey=Cookies
 2_safari=Cookies
 2_chrome=Cookies
 
 4_ie=Browsing History
 4_opera=Browsing History
-4_seamonkey=Browsing History
 4_safari=Browsing History
 4_chrome=Browsing History
 
 8_ie=Saved Form History
 8_opera=Saved Form History
-8_seamonkey=Saved Form History
 8_safari=Saved Form History
 8_chrome=Saved Form History
 
 16_ie=Saved Passwords
 16_opera=Saved Passwords
-16_seamonkey=Saved Passwords
 16_safari=Saved Passwords
 16_chrome=Saved Passwords
 
 32_ie=Favorites
 32_opera=Bookmarks
-32_seamonkey=Bookmarks
 32_safari=Bookmarks
 32_chrome=Bookmarks
 
 64_ie=Other Data
 64_opera=Other Data
-64_seamonkey=Other Data
 64_safari=Other Data
 64_chrome=Other Data
 
--- a/content/html/document/src/VideoDocument.cpp
+++ b/content/html/document/src/VideoDocument.cpp
@@ -79,18 +79,16 @@ VideoDocument::StartDocumentLoad(const c
                                  nsIContentSink*     aSink)
 {
   nsresult rv =
     MediaDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer,
                                      aDocListener, aReset, aSink);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mStreamListener = new MediaDocumentStreamListener(this);
-  if (!mStreamListener)
-    return NS_ERROR_OUT_OF_MEMORY;
 
   // Create synthetic document
   rv = CreateSyntheticVideoDocument(aChannel,
       getter_AddRefs(mStreamListener->mNextStream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*aDocListener = mStreamListener);
   return rv;
@@ -153,17 +151,16 @@ VideoDocument::UpdateTitle(nsIChannel* a
 
 } // namespace dom
 } // namespace mozilla
 
 nsresult
 NS_NewVideoDocument(nsIDocument** aResult)
 {
   mozilla::dom::VideoDocument* doc = new mozilla::dom::VideoDocument();
-  NS_ENSURE_TRUE(doc, NS_ERROR_OUT_OF_MEMORY);
 
   NS_ADDREF(doc);
   nsresult rv = doc->Init();
 
   if (NS_FAILED(rv)) {
     NS_RELEASE(doc);
   }
 
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -1072,17 +1072,17 @@ nsMediaCache::PredictNextUseForIncomingD
   }
   if (bytesAhead <= 0)
     return TimeDuration(0);
   PRInt64 millisecondsAhead = bytesAhead*1000/aStream->mPlaybackBytesPerSecond;
   return TimeDuration::FromMilliseconds(
       NS_MIN<PRInt64>(millisecondsAhead, PR_INT32_MAX));
 }
 
-enum StreamAction { NONE, SEEK, RESUME, SUSPEND };
+enum StreamAction { NONE, SEEK, SEEK_AND_RESUME, RESUME, SUSPEND };
 
 void
 nsMediaCache::Update()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   // The action to use for each stream. We store these so we can make
   // decisions while holding the cache lock but implement those decisions
@@ -1317,66 +1317,83 @@ nsMediaCache::Update()
       if (stream->mChannelOffset != desiredOffset && enableReading) {
         // We need to seek now.
         NS_ASSERTION(stream->mIsSeekable || desiredOffset == 0,
                      "Trying to seek in a non-seekable stream!");
         // Round seek offset down to the start of the block. This is essential
         // because we don't want to think we have part of a block already
         // in mPartialBlockBuffer.
         stream->mChannelOffset = (desiredOffset/BLOCK_SIZE)*BLOCK_SIZE;
-        actions[i] = SEEK;
+        actions[i] = stream->mCacheSuspended ? SEEK_AND_RESUME : SEEK;
       } else if (enableReading && stream->mCacheSuspended) {
         actions[i] = RESUME;
       } else if (!enableReading && !stream->mCacheSuspended) {
         actions[i] = SUSPEND;
       }
     }
 #ifdef DEBUG
     mInUpdate = false;
 #endif
   }
 
   // Update the channel state without holding our cache lock. While we're
   // doing this, decoder threads may be running and seeking, reading or changing
   // other cache state. That's OK, they'll trigger new Update events and we'll
   // get back here and revise our decisions. The important thing here is that
   // performing these actions only depends on mChannelOffset and
-  // mCacheSuspended, which can only be written by the main thread (i.e., this
+  // the action, which can only be written by the main thread (i.e., this
   // thread), so we don't have races here.
+
+  // First, update the mCacheSuspended/mCacheEnded flags so that they're all correct
+  // when we fire our CacheClient commands below. Those commands can rely on these flags
+  // being set correctly for all streams.
   for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
     nsMediaCacheStream* stream = mStreams[i];
-    nsresult rv = NS_OK;
     switch (actions[i]) {
     case SEEK:
-      LOG(PR_LOG_DEBUG, ("Stream %p CacheSeek to %lld (resume=%d)", stream,
-           (long long)stream->mChannelOffset, stream->mCacheSuspended));
-      rv = stream->mClient->CacheClientSeek(stream->mChannelOffset,
-                                            stream->mCacheSuspended);
+	case SEEK_AND_RESUME:
       stream->mCacheSuspended = false;
       stream->mChannelEnded = false;
       break;
+    case RESUME:
+      stream->mCacheSuspended = false;
+      break;
+    case SUSPEND:
+      stream->mCacheSuspended = true;
+      break;
+    default:
+      break;
+    }
+    stream->mHasHadUpdate = true;
+  }
 
+  for (PRUint32 i = 0; i < mStreams.Length(); ++i) {
+    nsMediaCacheStream* stream = mStreams[i];
+    nsresult rv;
+    switch (actions[i]) {
+    case SEEK:
+	case SEEK_AND_RESUME:
+      LOG(PR_LOG_DEBUG, ("Stream %p CacheSeek to %lld (resume=%d)", stream,
+           (long long)stream->mChannelOffset, actions[i] == SEEK_AND_RESUME));
+      rv = stream->mClient->CacheClientSeek(stream->mChannelOffset,
+                                            actions[i] == SEEK_AND_RESUME);
+      break;
     case RESUME:
       LOG(PR_LOG_DEBUG, ("Stream %p Resumed", stream));
       rv = stream->mClient->CacheClientResume();
-      stream->mCacheSuspended = false;
       break;
-
     case SUSPEND:
       LOG(PR_LOG_DEBUG, ("Stream %p Suspended", stream));
       rv = stream->mClient->CacheClientSuspend();
-      stream->mCacheSuspended = true;
       break;
-
     default:
+      rv = NS_OK;
       break;
     }
 
-    stream->mHasHadUpdate = true;
-
     if (NS_FAILED(rv)) {
       // Close the streams that failed due to error. This will cause all
       // client Read and Seek operations on those streams to fail. Blocked
       // Reads will also be woken up.
       ReentrantMonitorAutoEnter mon(mReentrantMonitor);
       stream->CloseInternal(mon);
     }
   }
--- a/content/media/nsMediaStream.cpp
+++ b/content/media/nsMediaStream.cpp
@@ -761,17 +761,17 @@ nsMediaChannelStream::CacheClientNotifyD
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 nsMediaChannelStream::CacheClientSeek(PRInt64 aOffset, bool aResume)
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
-  printf("*** nsMediaChannelStream::CacheClientSeek() mDecoder=%p\n", mDecoder);
+  printf("*** nsMediaChannelStream::CacheClientSeek() mDecoder=%p aOffset=%lld aResume = %d\n", mDecoder, (long long)aOffset, aResume);
 
   CloseChannel();
 
   if (aResume) {
     NS_ASSERTION(mSuspendCount > 0, "Too many resumes!");
     // No need to mess with the channel, since we're making a new one
     --mSuspendCount;
   }
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/706283-1.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script>
+
+window.mozRequestAnimationFrame(null);
+
+</script>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -27,8 +27,9 @@ load 601247.html
 load 609560-1.xhtml
 load 612018-1.html
 load 637116.html
 load 666869.html
 load 675621-1.html
 load 693894.html
 load 695867.html
 load 697643.html
+load 706283-1.html
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1322,16 +1322,17 @@ nsDOMWindowUtils::SendQueryContentEvent(
     nsQueryContentEvent dummyEvent(true, NS_QUERY_CONTENT_STATE, widget);
     InitEvent(dummyEvent, &pt);
     nsIFrame* popupFrame =
       nsLayoutUtils::GetPopupFrameForEventCoordinates(presContext->GetRootPresContext(), &dummyEvent);
 
     nsIntRect widgetBounds;
     nsresult rv = widget->GetClientBounds(widgetBounds);
     NS_ENSURE_SUCCESS(rv, rv);
+    widgetBounds.MoveTo(0, 0);
 
     // There is no popup frame at the point and the point isn't in our widget,
     // we cannot process this request.
     NS_ENSURE_TRUE(popupFrame || widgetBounds.Contains(pt),
                    NS_ERROR_FAILURE);
 
     // Fire the event on the widget at the point
     if (popupFrame) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -3878,16 +3878,20 @@ nsGlobalWindow::MozRequestAnimationFrame
 {
   FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback),
                    NS_ERROR_NOT_INITIALIZED);
 
   if (!mDoc) {
     return NS_OK;
   }
 
+  if (!aCallback) {
+    return NS_ERROR_XPC_BAD_CONVERT_JS;
+  }
+
   mDoc->ScheduleFrameRequestCallback(aCallback);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetMozAnimationStartTime(PRInt64 *aTime)
 {
   FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
@@ -10315,17 +10319,17 @@ nsGlobalChromeWindow::BeginWindowMove(ns
 #ifdef MOZ_XUL
   if (aPanel) {
     nsCOMPtr<nsIContent> panel = do_QueryInterface(aPanel);
     NS_ENSURE_TRUE(panel, NS_ERROR_FAILURE);
 
     nsIFrame* frame = panel->GetPrimaryFrame();
     NS_ENSURE_TRUE(frame && frame->GetType() == nsGkAtoms::menuPopupFrame, NS_OK);
 
-    (static_cast<nsMenuPopupFrame*>(frame))->GetWidget(getter_AddRefs(widget));
+    widget = (static_cast<nsMenuPopupFrame*>(frame))->GetWidget();
   }
   else {
 #endif
     widget = GetMainWidget();
 #ifdef MOZ_XUL
   }
 #endif
 
--- a/dom/workers/EventTarget.cpp
+++ b/dom/workers/EventTarget.cpp
@@ -134,16 +134,19 @@ EventTarget::FromJSObject(JSContext* aCx
   return GetPrivate(aCx, aObj);
 }
 
 // static
 JSBool
 EventTarget::AddEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+  if (!obj) {
+    return true;
+  }
 
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSString* type;
   JSObject* listener;
@@ -162,16 +165,19 @@ EventTarget::AddEventListener(JSContext*
                                                  capturing, wantsUntrusted);
 }
 
 // static
 JSBool
 EventTarget::RemoveEventListener(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+  if (!obj) {
+    return true;
+  }
 
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSString* type;
   JSObject* listener;
@@ -190,16 +196,19 @@ EventTarget::RemoveEventListener(JSConte
                                                     capturing);
 }
 
 // static
 JSBool
 EventTarget::DispatchEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
 {
   JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+  if (!obj) {
+    return true;
+  }
 
   EventTarget* self = GetPrivate(aCx, obj);
   if (!self) {
     return true;
   }
 
   JSObject* event;
   if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "o", &event)) {
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -312,46 +312,55 @@ private:
     *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
     return true;
   }
 
   static JSBool
   StopPropagation(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     Event* event = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!event) {
       return false;
     }
 
     event->mStopPropagationCalled = true;
 
     return true;
   }
 
   static JSBool
   StopImmediatePropagation(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     Event* event = GetInstancePrivate(aCx, obj, sFunctions[3].name);
     if (!event) {
       return false;
     }
 
     event->mStopImmediatePropagationCalled = true;
 
     return true;
   }
   
   static JSBool
   PreventDefault(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     Event* event = GetInstancePrivate(aCx, obj, sFunctions[1].name);
     if (!event) {
       return false;
     }
 
     jsval cancelableVal;
     if (!GetPropertyCommon(aCx, obj, SLOT_cancelable, &cancelableVal)) {
@@ -362,16 +371,19 @@ private:
            JS_SetReservedSlot(aCx, obj, SLOT_defaultPrevented, cancelableVal) :
            true;
   }
 
   static JSBool
   InitEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     Event* event = GetInstancePrivate(aCx, obj, sFunctions[2].name);
     if (!event) {
       return false;
     }
 
     JSString* type;
     JSBool bubbles, cancelable;
@@ -622,16 +634,19 @@ private:
 
     return JS_GetReservedSlot(aCx, aObj, slot, aVp);
   }
 
   static JSBool
   InitMessageEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     MessageEvent* event = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!event) {
       return false;
     }
 
     JSString* type, *data, *origin;
     JSBool bubbles, cancelable;
@@ -818,16 +833,19 @@ private:
 
     return JS_GetReservedSlot(aCx, aObj, slot, aVp);
   }
 
   static JSBool
   InitErrorEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     ErrorEvent* event = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!event) {
       return false;
     }
 
     JSString* type, *message, *filename;
     JSBool bubbles, cancelable;
@@ -1005,16 +1023,19 @@ private:
 
     return JS_GetReservedSlot(aCx, aObj, slot, aVp);
   }
 
   static JSBool
   InitProgressEvent(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     ProgressEvent* event = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!event) {
       return false;
     }
 
     JSString* type;
     JSBool bubbles, cancelable, lengthComputable;
--- a/dom/workers/Exceptions.cpp
+++ b/dom/workers/Exceptions.cpp
@@ -117,16 +117,19 @@ private:
     JS_ASSERT(JS_GET_CLASS(aCx, aObj) == &sClass);
     delete GetJSPrivateSafeish<DOMException>(aCx, aObj);
   }
 
   static JSBool
   ToString(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     JSClass* classPtr;
     if (!obj || ((classPtr = JS_GET_CLASS(aCx, obj)) != &sClass)) {
       JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
                            JSMSG_INCOMPATIBLE_PROTO, sClass.name, "toString",
                            classPtr ? classPtr->name : "object");
       return false;
     }
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -180,16 +180,19 @@ private:
 
     return true;
   }
 
   static JSBool
   MozSlice(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "mozSlice");
     if (!blob) {
       return false;
     }
 
     jsdouble start = 0, end = 0;
     JSString* jsContentType = JS_GetEmptyString(JS_GetRuntime(aCx));
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -175,16 +175,19 @@ private:
       GetJSPrivateSafeish<FileReaderSyncPrivate>(aCx, aObj);
     NS_IF_RELEASE(fileReader);
   }
 
   static JSBool
   ReadAsArrayBuffer(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     FileReaderSyncPrivate* fileReader =
       GetInstancePrivate(aCx, obj, "readAsArrayBuffer");
     if (!fileReader) {
       return false;
     }
 
     JSObject* jsBlob;
@@ -219,16 +222,19 @@ private:
     JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(jsArrayBuffer));
     return true;
   }
 
   static JSBool
   ReadAsDataURL(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     FileReaderSyncPrivate* fileReader =
       GetInstancePrivate(aCx, obj, "readAsDataURL");
     if (!fileReader) {
       return false;
     }
 
     JSObject* jsBlob;
@@ -256,16 +262,19 @@ private:
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(jsBlobText));
     return true;
   }
 
   static JSBool
   ReadAsBinaryString(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     FileReaderSyncPrivate* fileReader =
       GetInstancePrivate(aCx, obj, "readAsBinaryString");
     if (!fileReader) {
       return false;
     }
 
     JSObject* jsBlob;
@@ -293,16 +302,19 @@ private:
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(jsBlobText));
     return true;
   }
 
   static JSBool
   ReadAsText(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     FileReaderSyncPrivate* fileReader =
       GetInstancePrivate(aCx, obj, "readAsText");
     if (!fileReader) {
       return false;
     }
 
     JSObject* jsBlob;
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -262,30 +262,36 @@ private:
       worker->TraceInstance(aTrc);
     }
   }
 
   static JSBool
   Terminate(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     const char*& name = sFunctions[0].name;
     WorkerPrivate* worker = GetInstancePrivate(aCx, obj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
     }
 
     return worker->Terminate(aCx);
   }
 
   static JSBool
   PostMessage(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     const char*& name = sFunctions[1].name;
     WorkerPrivate* worker = GetInstancePrivate(aCx, obj, name);
     if (!worker) {
       return !JS_IsExceptionPending(aCx);
     }
 
     jsval message;
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -381,29 +381,35 @@ private:
     *aVp = scope->mSlots[SLOT_navigator];
     return true;
   }
 
   static JSBool
   Close(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!scope) {
       return false;
     }
 
     return scope->mWorker->CloseInternal(aCx);
   }
 
   static JSBool
   ImportScripts(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[1].name);
     if (!scope) {
       return false;
     }
 
     if (aArgc && !scriptloader::Load(aCx, aArgc, JS_ARGV(aCx, aVp))) {
       return false;
@@ -411,16 +417,19 @@ private:
 
     return true;
   }
 
   static JSBool
   SetTimeout(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[2].name);
     if (!scope) {
       return false;
     }
 
     jsval dummy;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
@@ -429,16 +438,19 @@ private:
 
     return scope->mWorker->SetTimeout(aCx, aArgc, aVp, false);
   }
 
   static JSBool
   ClearTimeout(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[3].name);
     if (!scope) {
       return false;
     }
 
     uint32 id;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "u", &id)) {
@@ -447,16 +459,19 @@ private:
 
     return scope->mWorker->ClearTimeout(aCx, id);
   }
 
   static JSBool
   SetInterval(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[4].name);
     if (!scope) {
       return false;
     }
 
     jsval dummy;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
@@ -465,16 +480,19 @@ private:
 
     return scope->mWorker->SetTimeout(aCx, aArgc, aVp, true);
   }
 
   static JSBool
   ClearInterval(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     WorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, sFunctions[5].name);
     if (!scope) {
       return false;
     }
 
     uint32 id;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "u", &id)) {
@@ -482,18 +500,22 @@ private:
     }
 
     return scope->mWorker->ClearTimeout(aCx, id);
   }
 
   static JSBool
   Dump(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
-    if (!GetInstancePrivate(aCx, JS_THIS_OBJECT(aCx, aVp),
-                            sFunctions[6].name)) {
+    JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
+
+    if (!GetInstancePrivate(aCx, obj, sFunctions[6].name)) {
       return false;
     }
 
     if (aArgc) {
       JSString* str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0]);
       if (!str) {
         return false;
       }
@@ -508,18 +530,22 @@ private:
     }
 
     return true;
   }
 
   static JSBool
   AtoB(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
-    if (!GetInstancePrivate(aCx, JS_THIS_OBJECT(aCx, aVp),
-                            sFunctions[7].name)) {
+    JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
+
+    if (!GetInstancePrivate(aCx, obj, sFunctions[7].name)) {
       return false;
     }
 
     jsval string;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &string)) {
       return false;
     }
 
@@ -530,18 +556,22 @@ private:
 
     JS_SET_RVAL(aCx, aVp, result);
     return true;
   }
 
   static JSBool
   BtoA(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
-    if (!GetInstancePrivate(aCx, JS_THIS_OBJECT(aCx, aVp),
-                            sFunctions[8].name)) {
+    JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
+
+    if (!GetInstancePrivate(aCx, obj, sFunctions[8].name)) {
       return false;
     }
 
     jsval binary;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &binary)) {
       return false;
     }
 
@@ -749,16 +779,19 @@ private:
       scope->TraceInstance(aTrc);
     }
   }
 
   static JSBool
   PostMessage(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     const char*& name = sFunctions[0].name;
     DedicatedWorkerGlobalScope* scope = GetInstancePrivate(aCx, obj, name);
     if (!scope) {
       return false;
     }
 
     jsval message;
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -600,30 +600,36 @@ private:
 
     return priv->SetEventListenerOnEventTarget(aCx, name + 2, aVp);
   }
 
   static JSBool
   Abort(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!priv) {
       return false;
     }
 
     return priv->Abort(aCx);
   }
 
   static JSBool
   GetAllResponseHeaders(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[1].name);
     if (!priv) {
       return false;
     }
 
     JSString* responseHeaders = priv->GetAllResponseHeaders(aCx);
@@ -634,16 +640,19 @@ private:
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(responseHeaders));
     return true;
   }
 
   static JSBool
   GetResponseHeader(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[2].name);
     if (!priv) {
       return false;
     }
 
     jsval headerVal;
@@ -670,16 +679,19 @@ private:
     JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(value));
     return true;
   }
 
   static JSBool
   Open(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[3].name);
     if (!priv) {
       return false;
     }
 
     JSString* method, *url;
@@ -693,32 +705,38 @@ private:
 
     return priv->Open(aCx, method, url, async, user, password);
   }
 
   static JSBool
   Send(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[4].name);
     if (!priv) {
       return false;
     }
 
     jsval body = aArgc ? JS_ARGV(aCx, aVp)[0] : JSVAL_VOID;
 
     return priv->Send(aCx, !!aArgc, body);
   }
 
   static JSBool
   SendAsBinary(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[5].name);
     if (!priv) {
       return false;
     }
 
     jsval bodyVal;
@@ -739,16 +757,19 @@ private:
 
     return priv->SendAsBinary(aCx, body);
   }
 
   static JSBool
   SetRequestHeader(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[6].name);
     if (!priv) {
       return false;
     }
 
     JSString* header, *value;
@@ -759,16 +780,19 @@ private:
 
     return priv->SetRequestHeader(aCx, header, value);
   }
 
   static JSBool
   OverrideMimeType(JSContext* aCx, uintN aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
+    if (!obj) {
+      return false;
+    }
 
     XMLHttpRequestPrivate* priv =
       GetInstancePrivate(aCx, obj, sFunctions[7].name);
     if (!priv) {
       return false;
     }
 
     JSString* mimeType;
--- a/js/src/assembler/jit/ExecutableAllocator.cpp
+++ b/js/src/assembler/jit/ExecutableAllocator.cpp
@@ -33,25 +33,25 @@ size_t ExecutableAllocator::pageSize = 0
 size_t ExecutableAllocator::largeAllocSize = 0;
 
 ExecutablePool::~ExecutablePool()
 {
     m_allocator->releasePoolPages(this);
 }
 
 void
-ExecutableAllocator::getCodeStats(size_t& method, size_t& regexp, size_t& unused) const
+ExecutableAllocator::sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const
 {
-    method = 0;
-    regexp = 0;
-    unused = 0;
+    *method = 0;
+    *regexp = 0;
+    *unused = 0;
 
     for (ExecPoolHashSet::Range r = m_pools.all(); !r.empty(); r.popFront()) {
         ExecutablePool* pool = r.front();
-        method += pool->m_mjitCodeMethod;
-        regexp += pool->m_mjitCodeRegexp;
-        unused += pool->m_allocation.size - pool->m_mjitCodeMethod - pool->m_mjitCodeRegexp;
+        *method += pool->m_mjitCodeMethod;
+        *regexp += pool->m_mjitCodeRegexp;
+        *unused += pool->m_allocation.size - pool->m_mjitCodeMethod - pool->m_mjitCodeRegexp;
     }
 }
 
 }
 
 #endif // HAVE(ASSEMBLER)
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -225,17 +225,17 @@ public:
     void releasePoolPages(ExecutablePool *pool) {
         JS_ASSERT(pool->m_allocation.pages);
         if (destroyCallback)
             destroyCallback(pool->m_allocation.pages, pool->m_allocation.size);
         systemRelease(pool->m_allocation);
         m_pools.remove(m_pools.lookup(pool));   // this asserts if |pool| is not in m_pools
     }
 
-    void getCodeStats(size_t& method, size_t& regexp, size_t& unused) const;
+    void sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const;
 
     void setDestroyCallback(DestroyCallback destroyCallback) {
         this->destroyCallback = destroyCallback;
     }
 
 private:
     static size_t pageSize;
     static size_t largeAllocSize;
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4559,16 +4559,28 @@ MOZ_ARG_ENABLE_BOOL(js-diagnostics,
 [  --enable-js-diagnostics
                           Enable JS diagnostic assertions and breakpad data],
     JS_CRASH_DIAGNOSTICS=1,
     JS_CRASH_DIAGNOSTICS= )
 if test -n "$JS_CRASH_DIAGNOSTICS"; then
     AC_DEFINE(JS_CRASH_DIAGNOSTICS)
 fi
 
+dnl ========================================================
+dnl Enable changes that make the shell more deterministic
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(more-deterministic,
+[  --enable-more-deterministic
+                          Enable changes that make the shell more deterministic],
+    JS_MORE_DETERMINISTIC=1,
+    JS_MORE_DETERMINISTIC= )
+if test -n "$JS_MORE_DETERMINISTIC"; then
+    AC_DEFINE(JS_MORE_DETERMINISTIC)
+fi
+
 dnl ======================================================
 dnl = Enable compiling with ccache
 dnl ======================================================
 MOZ_ARG_WITH_STRING(ccache,
 [  --with-ccache[=path/to/ccache]
                           Enable compiling with ccache],
     CCACHE=$withval, CCACHE="no")
 
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -135,21 +135,20 @@ LifoAlloc::freeUnused()
         if (!lastUsed) {
             freeAll();
             return;
         }
         latest = lastUsed;
     }
 
     /* Free all chunks after |latest|. */
-    size_t freed = 0;
-    for (BumpChunk *victim = latest->next(); victim; victim = victim->next()) {
+    for (BumpChunk *victim = latest->next(); victim; victim = victim->next())
         BumpChunk::delete_(victim);
-        freed++;
-    }
+
+    latest->setNext(NULL);
 }
 
 LifoAlloc::BumpChunk *
 LifoAlloc::getOrCreateChunk(size_t n)
 {
     if (first) {
         /* Look for existing, unused BumpChunks to satisfy the request. */
         while (latest->next()) {
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -320,17 +320,18 @@ class LifoAlloc
     JS_DECLARE_NEW_METHODS(alloc, JS_ALWAYS_INLINE)
 
     /* Some legacy clients (ab)use LifoAlloc to act like a vector, see bug 688891. */
 
     void *allocUnaligned(size_t n);
     void *reallocUnaligned(void *origPtr, size_t origSize, size_t incr);
 };
 
-class LifoAllocScope {
+class LifoAllocScope
+{
     LifoAlloc   *lifoAlloc;
     void        *mark;
     bool        shouldRelease;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   public:
     explicit LifoAllocScope(LifoAlloc *lifoAlloc
                             JS_GUARD_OBJECT_NOTIFIER_PARAM)
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -121,17 +121,16 @@ BytecodeEmitter::BytecodeEmitter(Parser 
     constList(parser->context),
     upvarIndices(parser->context),
     upvarMap(parser->context),
     globalScope(NULL),
     globalUses(parser->context),
     globalMap(parser->context),
     closedArgs(parser->context),
     closedVars(parser->context),
-    traceIndex(0),
     typesetCount(0)
 {
     flags = TCF_COMPILING;
     memset(&prolog, 0, sizeof prolog);
     memset(&main, 0, sizeof main);
     current = &main;
     firstLine = prolog.currentLine = main.currentLine = lineno;
 }
@@ -1445,31 +1444,28 @@ UpdateLineNumberNotes(JSContext *cx, Byt
     return JS_TRUE;
 }
 
 static ptrdiff_t
 EmitTraceOp(JSContext *cx, BytecodeEmitter *bce, ParseNode *nextpn)
 {
     if (nextpn) {
         /*
-         * Try to give the JSOP_TRACE the same line number as the next
+         * Try to give the JSOP_LOOPHEAD the same line number as the next
          * instruction. nextpn is often a block, in which case the next
          * instruction typically comes from the first statement inside.
          */
         JS_ASSERT_IF(nextpn->isKind(PNK_STATEMENTLIST), nextpn->isArity(PN_LIST));
         if (nextpn->isKind(PNK_STATEMENTLIST) && nextpn->pn_head)
             nextpn = nextpn->pn_head;
         if (!UpdateLineNumberNotes(cx, bce, nextpn->pn_pos.begin.lineno))
             return -1;
     }
 
-    uint32 index = bce->traceIndex;
-    if (index < UINT16_MAX)
-        bce->traceIndex++;
-    return Emit3(cx, bce, JSOP_TRACE, UINT16_HI(index), UINT16_LO(index));
+    return Emit1(cx, bce, JSOP_LOOPHEAD);
 }
 
 /*
  * If op is JOF_TYPESET (see the type barriers comment in jsinfer.h), reserve
  * a type set to store its result.
  */
 static inline void
 CheckTypeSet(JSContext *cx, BytecodeEmitter *bce, JSOp op)
@@ -5505,17 +5501,17 @@ EmitForIn(JSContext *cx, BytecodeEmitter
     /*
      * Jump down to the loop condition to minimize overhead assuming at
      * least one iteration, as the other loop forms do.
      */
     ptrdiff_t jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
     if (jmp < 0)
         return false;
 
-    intN noteIndex2 = NewSrcNote(cx, bce, SRC_TRACE);
+    intN noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
     if (noteIndex2 < 0)
         return false;
 
     top = bce->offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
     if (EmitTraceOp(cx, bce, NULL) < 0)
         return false;
 
@@ -5646,17 +5642,17 @@ EmitNormalFor(JSContext *cx, BytecodeEmi
         jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
         if (jmp < 0)
             return false;
     }
 
     top = bce->offset();
     SET_STATEMENT_TOP(&stmtInfo, top);
 
-    intN noteIndex2 = NewSrcNote(cx, bce, SRC_TRACE);
+    intN noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
     if (noteIndex2 < 0)
         return false;
 
     /* Emit code for the loop body. */
     if (EmitTraceOp(cx, bce, forBody) < 0)
         return false;
     if (!EmitTree(cx, bce, forBody))
         return false;
@@ -5970,17 +5966,17 @@ frontend::EmitTree(JSContext *cx, Byteco
          */
         PushStatement(bce, &stmtInfo, STMT_WHILE_LOOP, top);
         noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
         if (noteIndex < 0)
             return JS_FALSE;
         jmp = EmitJump(cx, bce, JSOP_GOTO, 0);
         if (jmp < 0)
             return JS_FALSE;
-        noteIndex2 = NewSrcNote(cx, bce, SRC_TRACE);
+        noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
         if (noteIndex2 < 0)
             return JS_FALSE;
         top = EmitTraceOp(cx, bce, pn->pn_right);
         if (top < 0)
             return JS_FALSE;
         if (!EmitTree(cx, bce, pn->pn_right))
             return JS_FALSE;
         CHECK_AND_SET_JUMP_OFFSET_AT(cx, bce, jmp);
@@ -6001,17 +5997,17 @@ frontend::EmitTree(JSContext *cx, Byteco
         break;
 
       case PNK_DOWHILE:
         /* Emit an annotated nop so we know to decompile a 'do' keyword. */
         noteIndex = NewSrcNote(cx, bce, SRC_WHILE);
         if (noteIndex < 0 || Emit1(cx, bce, JSOP_NOP) < 0)
             return JS_FALSE;
 
-        noteIndex2 = NewSrcNote(cx, bce, SRC_TRACE);
+        noteIndex2 = NewSrcNote(cx, bce, SRC_LOOPHEAD);
         if (noteIndex2 < 0)
             return JS_FALSE;
 
         /* Compile the loop body. */
         top = EmitTraceOp(cx, bce, pn->pn_left);
         if (top < 0)
             return JS_FALSE;
         PushStatement(bce, &stmtInfo, STMT_DO_LOOP, top);
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -669,17 +669,16 @@ struct BytecodeEmitter : public TreeCont
     GlobalUseVector globalUses;     /* per-script global uses */
     OwnedAtomIndexMapPtr globalMap; /* per-script map of global name to globalUses vector */
 
     /* Vectors of pn_cookie slot values. */
     typedef Vector<uint32, 8> SlotVector;
     SlotVector      closedArgs;
     SlotVector      closedVars;
 
-    uint16          traceIndex;     /* index for the next JSOP_TRACE instruction */
     uint16          typesetCount;   /* Number of JOF_TYPESET opcodes generated */
 
     BytecodeEmitter(Parser *parser, uintN lineno);
     bool init(JSContext *cx, TreeContext::InitBehavior ib = USED_AS_CODE_GENERATOR);
 
     JSContext *context() {
         return parser->context;
     }
@@ -952,17 +951,17 @@ enum SrcNoteType {
     SRC_GENEXP      = 1,        /* JSOP_LAMBDA from generator expression */
     SRC_IF_ELSE     = 2,        /* JSOP_IFEQ bytecode is from an if-then-else */
     SRC_FOR_IN      = 2,        /* JSOP_GOTO to for-in loop condition from
                                    before loop (same arity as SRC_IF_ELSE) */
     SRC_FOR         = 3,        /* JSOP_NOP or JSOP_POP in for(;;) loop head */
     SRC_WHILE       = 4,        /* JSOP_GOTO to for or while loop condition
                                    from before loop, else JSOP_NOP at top of
                                    do-while loop */
-    SRC_TRACE       = 4,        /* For JSOP_TRACE; includes distance to loop end */
+    SRC_LOOPHEAD    = 4,        /* For JSOP_LOOPHEAD; includes distance to loop end */
     SRC_CONTINUE    = 5,        /* JSOP_GOTO is a continue, not a break;
                                    also used on JSOP_ENDINIT if extra comma
                                    at end of array literal: [1,2,,];
                                    JSOP_DUP continuing destructuring pattern */
     SRC_DECL        = 6,        /* type of a declaration (var, const, let*) */
     SRC_DESTRUCT    = 6,        /* JSOP_DUP starting a destructuring assignment
                                    operation, with SRC_DECL_* offset operand */
     SRC_PCDELTA     = 7,        /* distance forward from comma-operator to
--- a/js/src/jit-test/tests/basic/bug657975.js
+++ b/js/src/jit-test/tests/basic/bug657975.js
@@ -15,24 +15,24 @@ x = 0;
 
 // bug 657984 #1
 function f3(){ for(y in x); }
 trap(f3, 5, '')
 f3()
 
 // bug 657984 #2
 function f4(){ for(y in x); }
-trap(f4, 10, '')
+trap(f4, 8, '')
 f4()
 
 // bug 658464
 function f5() {
   for ([, x] in 0) {}
 }
-trap(f5, 9, '')
+trap(f5, 7, '')
 f5()
 
 // bug 658465
 function f6() {
   "use strict";
   print(Math.min(0, 1));
 }
 trap(f6, 10, '')
@@ -55,25 +55,25 @@ for (a in f8())
   (function() {})()
 
 // bug 659043
 f9 = (function() {
   for (let a = 0; a < 0; ++a) {
     for each(let w in []) {}
   }
 })
-trap(f9, 27, undefined);
+trap(f9, 22, undefined);
 for (b in f9())
   (function() {})()
 
 // bug 659233
 f10 = (function() {
     while (h) {
         continue
     }
 })
 trap(f10, 0, '');
 try { f10() } catch (e) {}
 
 // bug 659337
 f11 = Function("for (x = 0; x < 6; x++) { gc() }");
-trap(f11, 25, '');
+trap(f11, 23, '');
 f11()
rename from js/src/jit-test/tests/basic/bug685321.js
rename to js/src/jit-test/tests/basic/bug685321-1.js
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug685321-2.js
@@ -0,0 +1,13 @@
+var o = {};
+function f() {
+    function g() {
+        x = 80;
+        return x;
+    };
+    Object.defineProperty(o, "f", {get:g});
+    var [x] = 0;
+    x = {};
+    2 + o.f;
+    print(x);
+}
+f();
--- a/js/src/jit-test/tests/basic/testBug683470.js
+++ b/js/src/jit-test/tests/basic/testBug683470.js
@@ -6,10 +6,10 @@ f = (function() {
     Object.defineProperty(this, "x", ({}));
   }
   for each(let d in [0, 0]) {
     try {
       b(d);
     } catch (e) {}
   }
 })
-trap(f, 54, undefined);
+trap(f, 52, undefined);
 f()
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -88,19 +88,16 @@ ScriptAnalysis::addJump(JSContext *cx, u
     JS_ASSERT(code->stackDepth == stackDepth);
 
     code->jumpTarget = true;
 
     if (offset < *currentOffset) {
         jsbytecode *pc = script->code + offset;
         UntrapOpcode untrap(cx, script, pc);
 
-        if (JSOp(*pc) == JSOP_TRACE || JSOp(*pc) == JSOP_NOTRACE)
-            code->loopHead = true;
-
         /* Scripts containing loops are never inlined. */
         isInlineable = false;
 
         /* Don't follow back edges to bytecode which has already been analyzed. */
         if (!code->analyzed) {
             if (*forwardJump == 0)
                 *forwardJump = *currentOffset;
             *currentOffset = offset;
@@ -664,17 +661,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
         if (loop && code->safePoint)
             loop->hasSafePoints = true;
 
         jsbytecode *pc = script->code + offset;
         UntrapOpcode untrap(cx, script, pc);
 
         JSOp op = (JSOp) *pc;
 
-        if ((op == JSOP_TRACE || op == JSOP_NOTRACE) && code->loop) {
+        if (op == JSOP_LOOPHEAD && code->loop) {
             /*
              * This is the head of a loop, we need to go and make sure that any
              * variables live at the head are live at the backedge and points prior.
              * For each such variable, look for the last lifetime segment in the body
              * and extend it to the end of the loop.
              */
             JS_ASSERT(loop == code->loop);
             unsigned backedge = code->loop->backedge;
@@ -811,17 +808,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
             if (loop && loop->entry == targetOffset && loop->entry > loop->lastBlock)
                 loop->lastBlock = loop->entry;
 
             if (targetOffset < offset) {
                 /* This is a loop back edge, no lifetime to pull in yet. */
 
 #ifdef DEBUG
                 JSOp nop = JSOp(script->code[targetOffset]);
-                JS_ASSERT(nop == JSOP_TRACE || nop == JSOP_NOTRACE || nop == JSOP_TRAP);
+                JS_ASSERT(nop == JSOP_LOOPHEAD || nop == JSOP_TRAP);
 #endif
 
                 /*
                  * If we already have a loop, it is an outer loop and we
                  * need to prune the last block in the loop --- we do not
                  * track 'continue' statements for outer loops.
                  */
                 if (loop && loop->entry > loop->lastBlock)
@@ -1168,17 +1165,17 @@ ScriptAnalysis::analyzeSSA(JSContext *cx
             offset = successorOffset;
             continue;
         }
 
         if (code->stackDepth > stackDepth)
             PodZero(stack + stackDepth, code->stackDepth - stackDepth);
         stackDepth = code->stackDepth;
 
-        if ((op == JSOP_TRACE || op == JSOP_NOTRACE) && code->loop) {
+        if (op == JSOP_LOOPHEAD && code->loop) {
             /*
              * Make sure there is a pending value array for phi nodes at the
              * loop head. We won't be able to clear these until we reach the
              * loop's back edge.
              *
              * We need phi nodes for all variables which might be modified
              * during the loop. This ensures that in the loop body we have
              * already updated state to reflect possible changes that happen
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -93,19 +93,16 @@ class Bytecode
   public:
     Bytecode() { PodZero(this); }
 
     /* --------- Bytecode analysis --------- */
 
     /* Whether there are any incoming jumps to this instruction. */
     bool jumpTarget : 1;
 
-    /* There is a backwards jump to this instruction. */
-    bool loopHead : 1;
-
     /* Whether there is fallthrough to this instruction from a non-branching instruction. */
     bool fallthrough : 1;
 
     /* Whether this instruction is the fall through point of a conditional jump. */
     bool jumpFallthrough : 1;
 
     /* Whether this instruction can be branched to from a switch statement. Implies jumpTarget. */
     bool switchTarget : 1;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1139,16 +1139,22 @@ JS_GetRuntime(JSContext *cx)
 }
 
 JS_PUBLIC_API(JSContext *)
 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
 {
     return js_ContextIterator(rt, JS_TRUE, iterp);
 }
 
+JS_PUBLIC_API(JSContext *)
+JS_ContextIteratorUnlocked(JSRuntime *rt, JSContext **iterp)
+{
+    return js_ContextIterator(rt, JS_FALSE, iterp);
+}
+
 JS_PUBLIC_API(JSVersion)
 JS_GetVersion(JSContext *cx)
 {
     return VersionNumber(cx->findVersion());
 }
 
 JS_PUBLIC_API(JSVersion)
 JS_SetVersion(JSContext *cx, JSVersion newVersion)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2096,16 +2096,19 @@ extern JS_PUBLIC_API(void)
 JS_SetContextPrivate(JSContext *cx, void *data);
 
 extern JS_PUBLIC_API(JSRuntime *)
 JS_GetRuntime(JSContext *cx);
 
 extern JS_PUBLIC_API(JSContext *)
 JS_ContextIterator(JSRuntime *rt, JSContext **iterp);
 
+extern JS_PUBLIC_API(JSContext *)
+JS_ContextIteratorUnlocked(JSRuntime *rt, JSContext **iterp);
+
 extern JS_PUBLIC_API(JSVersion)
 JS_GetVersion(JSContext *cx);
 
 extern JS_PUBLIC_API(JSVersion)
 JS_SetVersion(JSContext *cx, JSVersion version);
 
 extern JS_PUBLIC_API(const char *)
 JS_VersionToString(JSVersion version);
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -132,16 +132,45 @@ ThreadData::~ThreadData()
 
 bool
 ThreadData::init()
 {
     JS_ASSERT(!repCache);
     return stackSpace.init() && !!(dtoaState = js_NewDtoaState());
 }
 
+#ifdef JS_THREADSAFE
+void
+ThreadData::sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
+                                size_t *regexpCode, size_t *stackCommitted)
+{
+    /*
+     * There are other ThreadData members that could be measured; the ones
+     * below have been seen by DMD to be worth measuring.  More stuff may be
+     * added later.
+     */
+
+    /*
+     * The computedSize is 0 because sizeof(DtoaState) isn't available here and
+     * it's not worth making it available.
+     */
+    *normal = mallocSizeOf(dtoaState, /* sizeof(DtoaState) */0);
+
+    *temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
+
+    size_t method = 0, regexp = 0, unused = 0;
+    if (execAlloc)
+        execAlloc->sizeOfCode(&method, &regexp, &unused);
+    JS_ASSERT(method == 0);     /* this execAlloc is only used for regexp code */
+    *regexpCode = regexp + unused;
+
+    *stackCommitted = stackSpace.sizeOfCommitted();
+}
+#endif
+
 void
 ThreadData::triggerOperationCallback(JSRuntime *rt)
 {
     JS_ASSERT(rt == this->rt);
 
     /*
      * Use JS_ATOMIC_SET and JS_ATOMIC_INCREMENT in the hope that it ensures
      * the write will become immediately visible to other processors polling
@@ -214,16 +243,24 @@ JSScript *
 js_GetCurrentScript(JSContext *cx)
 {
     return cx->hasfp() ? cx->fp()->maybeScript() : NULL;
 }
 
 
 #ifdef JS_THREADSAFE
 
+void
+JSThread::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
+                              size_t *regexpCode, size_t *stackCommitted)
+{
+    data.sizeOfExcludingThis(mallocSizeOf, normal, temporary, regexpCode, stackCommitted);
+    *normal += mallocSizeOf(this, sizeof(JSThread));
+}
+
 JSThread *
 js_CurrentThreadAndLockGC(JSRuntime *rt)
 {
     void *id = js_CurrentThreadId();
     JS_LOCK_GC(rt);
 
     /*
      * We must not race with a GC that accesses cx->thread for JSContext
@@ -770,16 +807,27 @@ js_ReportOutOfMemory(JSContext *cx)
         AutoAtomicIncrement incr(&cx->runtime->inOOMReport);
         onError(cx, msg, &report);
     }
 }
 
 JS_FRIEND_API(void)
 js_ReportOverRecursed(JSContext *maybecx)
 {
+#ifdef JS_MORE_DETERMINISTIC
+    /*
+     * We cannot make stack depth deterministic across different
+     * implementations (e.g. JIT vs. interpreter will differ in
+     * their maximum stack depth).
+     * However, we can detect externally when we hit the maximum
+     * stack depth which is useful for external testing programs
+     * like fuzzers.
+     */
+    fprintf(stderr, "js_ReportOverRecursed called\n");
+#endif
     if (maybecx)
         JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
 }
 
 void
 js_ReportAllocationOverflow(JSContext *maybecx)
 {
     if (maybecx)
@@ -1650,16 +1698,28 @@ JSContext::updateJITEnabled()
 # if defined JS_CPU_X86 || defined JS_CPU_X64
                        && JSC::MacroAssemblerX86Common::getSSEState() >=
                           JSC::MacroAssemblerX86Common::HasSSE2
 # endif
                         ;
 #endif
 }
 
+size_t
+JSContext::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const
+{
+    /*
+     * There are other JSContext members that could be measured; the following
+     * ones have been found by DMD to be worth measuring.  More stuff may be
+     * added later.
+     */
+    return mallocSizeOf(this, sizeof(JSContext)) +
+           busyArrays.sizeOfExcludingThis(mallocSizeOf);
+}
+
 namespace js {
 
 AutoEnumStateRooter::~AutoEnumStateRooter()
 {
     if (!stateValue.isNull()) {
         DebugOnly<JSBool> ok =
             obj->enumerate(context, JSENUMERATE_DESTROY, &stateValue, 0);
         JS_ASSERT(ok);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -222,16 +222,21 @@ struct ThreadData {
     void purge(JSContext *cx) {
         tempLifoAlloc.freeUnused();
         gsnCache.purge();
 
         /* FIXME: bug 506341. */
         propertyCache.purge(cx);
     }
 
+#ifdef JS_THREADSAFE
+    void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal, size_t *temporary,
+                             size_t *regexpCode, size_t *stackCommitted);
+#endif
+
     /* This must be called with the GC lock held. */
     void triggerOperationCallback(JSRuntime *rt);
 
     /*
      * Frames currently running in js::Interpret. See InterpreterFrames for
      * details.
      */
     InterpreterFrames *interpreterFrames;
@@ -252,17 +257,17 @@ struct JSThread {
                         js::SystemAllocPolicy> Map;
 
     /* Linked list of all contexts in use on this thread. */
     JSCList             contextList;
 
     /* Opaque thread-id, from NSPR's PR_GetCurrentThread(). */
     void                *id;
 
-    /* Number of JS_SuspendRequest calls withot JS_ResumeRequest. */
+    /* Number of JS_SuspendRequest calls without JS_ResumeRequest. */
     unsigned            suspendCount;
 
 # ifdef DEBUG
     unsigned            checkRequestDepth;
 # endif
 
     /* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
     js::ThreadData      data;
@@ -281,16 +286,20 @@ struct JSThread {
     ~JSThread() {
         /* The thread must have zero contexts. */
         JS_ASSERT(JS_CLIST_IS_EMPTY(&contextList));
     }
 
     bool init() {
         return data.init();
     }
+
+    JS_FRIEND_API(void) sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf, size_t *normal,
+                                            size_t *temporary, size_t *regexpCode,
+                                            size_t *stackCommitted);
 };
 
 #define JS_THREAD_DATA(cx)      (&(cx)->thread()->data)
 
 extern JSThread *
 js_CurrentThreadAndLockGC(JSRuntime *rt);
 
 /*
@@ -1264,16 +1273,18 @@ struct JSContext
 #endif
 
     /*
      * See JS_SetTrustedPrincipals in jsapi.h.
      * Note: !cx->compartment is treated as trusted.
      */
     bool runningWithTrustedPrincipals() const;
 
+    JS_FRIEND_API(size_t) sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
+
     static inline JSContext *fromLinkField(JSCList *link) {
         JS_ASSERT(link);
         return reinterpret_cast<JSContext *>(uintptr_t(link) - offsetof(JSContext, link));
     }
 
 #ifdef JS_THREADSAFE
     static inline JSContext *fromThreadLinks(JSCList *link) {
         JS_ASSERT(link);
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -145,24 +145,24 @@ JSCompartment::ensureJaegerCompartmentEx
         cx->delete_(jc);
         return false;
     }
     jaegerCompartment_ = jc;
     return true;
 }
 
 void
-JSCompartment::getMjitCodeStats(size_t& method, size_t& regexp, size_t& unused) const
+JSCompartment::sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const
 {
     if (jaegerCompartment_) {
-        jaegerCompartment_->execAlloc()->getCodeStats(method, regexp, unused);
+        jaegerCompartment_->execAlloc()->sizeOfCode(method, regexp, unused);
     } else {
-        method = 0;
-        regexp = 0;
-        unused = 0;
+        *method = 0;
+        *regexp = 0;
+        *unused = 0;
     }
 }
 #endif
 
 bool
 JSCompartment::wrap(JSContext *cx, Value *vp)
 {
     JS_ASSERT(cx->compartment == this);
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -227,17 +227,17 @@ struct JS_FRIEND_API(JSCompartment) {
 
     js::mjit::JaegerCompartment *jaegerCompartment() const {
         JS_ASSERT(jaegerCompartment_);
         return jaegerCompartment_;
     }
 
     bool ensureJaegerCompartmentExists(JSContext *cx);
 
-    void getMjitCodeStats(size_t& method, size_t& regexp, size_t& unused) const;
+    void sizeOfCode(size_t *method, size_t *regexp, size_t *unused) const;
 #endif
 
     /*
      * Shared scope property tree, and arena-pool for allocating its nodes.
      */
     js::PropertyTree             propertyTree;
 
 #ifdef DEBUG
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3381,18 +3381,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
     }
 
     /* Add type constraints for the various opcodes. */
     switch (op) {
 
         /* Nop bytecodes. */
       case JSOP_POP:
       case JSOP_NOP:
-      case JSOP_TRACE:
-      case JSOP_NOTRACE:
+      case JSOP_LOOPHEAD:
       case JSOP_GOTO:
       case JSOP_GOTOX:
       case JSOP_IFEQ:
       case JSOP_IFEQX:
       case JSOP_IFNE:
       case JSOP_IFNEX:
       case JSOP_LINENO:
       case JSOP_DEFCONST:
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1925,33 +1925,29 @@ ADD_EMPTY_CASE(JSOP_NOP)
 ADD_EMPTY_CASE(JSOP_UNUSED0)
 ADD_EMPTY_CASE(JSOP_CONDSWITCH)
 ADD_EMPTY_CASE(JSOP_TRY)
 #if JS_HAS_XML_SUPPORT
 ADD_EMPTY_CASE(JSOP_STARTXML)
 ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
 #endif
 ADD_EMPTY_CASE(JSOP_NULLBLOCKCHAIN)
+ADD_EMPTY_CASE(JSOP_LOOPHEAD)
 END_EMPTY_CASES
 
-BEGIN_CASE(JSOP_TRACE)
-BEGIN_CASE(JSOP_NOTRACE)
-    /* No-op */
-END_CASE(JSOP_TRACE)
-
 BEGIN_CASE(JSOP_LABEL)
 END_CASE(JSOP_LABEL)
 
 BEGIN_CASE(JSOP_LABELX)
 END_CASE(JSOP_LABELX)
 
 check_backedge:
 {
     CHECK_BRANCH();
-    if (op != JSOP_NOTRACE && op != JSOP_TRACE)
+    if (op != JSOP_LOOPHEAD)
         DO_OP();
 
 #ifdef JS_METHODJIT
     if (!useMethodJIT)
         DO_OP();
     mjit::CompileStatus status =
         mjit::CanMethodJITAtBranch(cx, script, regs.fp(), regs.pc);
     if (status == mjit::Compile_Error)
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -4232,17 +4232,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * DecompileExpression or recursively from case
                      * JSOP_{NOP,AND,OR}.)
                      *
                      * There's no special case for |if (genexp)| because the
                      * compiler optimizes that to |if (true)|.
                      */
                     pc2 = pc + len;
                     op = JSOp(*pc2);
-                    if (op == JSOP_TRACE || op == JSOP_NOP)
+                    if (op == JSOP_LOOPHEAD || op == JSOP_NOP)
                         pc2 += JSOP_NOP_LENGTH;
                     LOCAL_ASSERT(pc2 < endpc ||
                                  endpc < outer->code + outer->length);
                     LOCAL_ASSERT(ss2.top == 1);
                     ss2.opcodes[0] = JSOP_POP;
                     if (pc2 == endpc) {
                         op = JSOP_SETNAME;
                     } else {
@@ -5477,33 +5477,27 @@ ReconstructPCStack(JSContext *cx, JSScri
 namespace js {
 
 bool
 CallResultEscapes(jsbytecode *pc)
 {
     /*
      * If we see any of these sequences, the result is unused:
      * - call / pop
-     * - call / trace / pop
      *
      * If we see any of these sequences, the result is only tested for nullness:
      * - call / ifeq
-     * - call / trace / ifeq
      * - call / not / ifeq
-     * - call / trace / not / ifeq
      */
 
     if (*pc != JSOP_CALL)
         return true;
 
     pc += JSOP_CALL_LENGTH;
 
-    if (*pc == JSOP_TRACE)
-        pc += JSOP_TRACE_LENGTH;
-
     if (*pc == JSOP_POP)
         return false;
 
     if (*pc == JSOP_NOT)
         pc += JSOP_NOT_LENGTH;
 
     return (*pc != JSOP_IFEQ);
 }
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -276,18 +276,18 @@ OPDEF(JSOP_UNUSED0,   105,"unused0",    
 
 /* The argument is the offset to the next statement and is used by IonMonkey. */
 OPDEF(JSOP_LABEL,     106,"label",     NULL,          3,  0,  0,  0,  JOF_JUMP)
 OPDEF(JSOP_LABELX,    107,"labelx",    NULL,          5,  0,  0,  0,  JOF_JUMPX)
 
 /* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */
 OPDEF(JSOP_FUNCALL,   108,"funcall",    NULL,         3, -1,  1, 18,  JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
 
-/* This opcode stores an index that is unique to the given loop. */
-OPDEF(JSOP_TRACE,     109,"trace",      NULL,         3,  0,  0,  0,  JOF_UINT16)
+/* This opcode is the target of the backwards jump for some loop. */
+OPDEF(JSOP_LOOPHEAD,  109,"loophead",   NULL,         1,  0,  0,  0,  JOF_BYTE)
 
 /* ECMA-compliant assignment ops. */
 OPDEF(JSOP_BINDNAME,  110,"bindname",   NULL,         3,  0,  1,  0,  JOF_ATOM|JOF_NAME|JOF_SET)
 OPDEF(JSOP_SETNAME,   111,"setname",    NULL,         3,  2,  1,  3,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_DETECTING)
 
 /* Exception handling ops. */
 OPDEF(JSOP_THROW,     112,js_throw_str, NULL,         1,  1,  0,  0,  JOF_BYTE)
 
@@ -429,160 +429,159 @@ OPDEF(JSOP_SETXMLNAME,    171,"setxmlnam
 OPDEF(JSOP_XMLNAME,       172,"xmlname",    NULL,     1,  1,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_DESCENDANTS,   173,"descendants",NULL,     1,  2,  1, 18,  JOF_BYTE)
 OPDEF(JSOP_FILTER,        174,"filter",     NULL,     3,  1,  1,  0,  JOF_JUMP)
 OPDEF(JSOP_ENDFILTER,     175,"endfilter",  NULL,     3,  2,  1, 18,  JOF_JUMP)
 OPDEF(JSOP_TOXML,         176,"toxml",      NULL,     1,  1,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_TOXMLLIST,     177,"toxmllist",  NULL,     1,  1,  1, 19,  JOF_BYTE)
 OPDEF(JSOP_XMLTAGEXPR,    178,"xmltagexpr", NULL,     1,  1,  1,  0,  JOF_BYTE)
 OPDEF(JSOP_XMLELTEXPR,    179,"xmleltexpr", NULL,     1,  1,  1,  0,  JOF_BYTE)
-OPDEF(JSOP_NOTRACE,       180,"notrace",    NULL,     3,  0,  0,  0,  JOF_UINT16)
-OPDEF(JSOP_XMLCDATA,      181,"xmlcdata",   NULL,     3,  0,  1, 19,  JOF_ATOM)
-OPDEF(JSOP_XMLCOMMENT,    182,"xmlcomment", NULL,     3,  0,  1, 19,  JOF_ATOM)
-OPDEF(JSOP_XMLPI,         183,"xmlpi",      NULL,     3,  1,  1, 19,  JOF_ATOM)
-OPDEF(JSOP_DELDESC,       184,"deldesc",    NULL,     1,  2,  1, 15,  JOF_BYTE|JOF_ELEM|JOF_DEL)
+OPDEF(JSOP_XMLCDATA,      180,"xmlcdata",   NULL,     3,  0,  1, 19,  JOF_ATOM)
+OPDEF(JSOP_XMLCOMMENT,    181,"xmlcomment", NULL,     3,  0,  1, 19,  JOF_ATOM)
+OPDEF(JSOP_XMLPI,         182,"xmlpi",      NULL,     3,  1,  1, 19,  JOF_ATOM)
+OPDEF(JSOP_DELDESC,       183,"deldesc",    NULL,     1,  2,  1, 15,  JOF_BYTE|JOF_ELEM|JOF_DEL)
 
-OPDEF(JSOP_CALLPROP,      185,"callprop",   NULL,     3,  1,  2, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_CALLOP|JOF_TMPSLOT3)
+OPDEF(JSOP_CALLPROP,      184,"callprop",   NULL,     3,  1,  2, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET|JOF_CALLOP|JOF_TMPSLOT3)
 
 /*
  * These opcodes contain a reference to the current blockChain object.
  * They are emitted directly after instructions, such as DEFFUN, that need fast access to
  * the blockChain. The special NULLBLOCKCHAIN is needed because the JOF_OBJECT
  * does not permit NULL object references, since it stores an index into a table of
  * objects.
  */
-OPDEF(JSOP_BLOCKCHAIN,    186,"blockchain",    NULL,  3,  0,  0,  0, JOF_OBJECT)
-OPDEF(JSOP_NULLBLOCKCHAIN,187,"nullblockchain",NULL,  1,  0,  0,  0, JOF_BYTE)
+OPDEF(JSOP_BLOCKCHAIN,    185,"blockchain",    NULL,  3,  0,  0,  0, JOF_OBJECT)
+OPDEF(JSOP_NULLBLOCKCHAIN,186,"nullblockchain",NULL,  1,  0,  0,  0, JOF_BYTE)
 
 /*
  * Opcode to hold 24-bit immediate integer operands.
  */
-OPDEF(JSOP_UINT24,        188,"uint24",     NULL,     4,  0,  1, 16,  JOF_UINT24)
+OPDEF(JSOP_UINT24,        187,"uint24",     NULL,     4,  0,  1, 16,  JOF_UINT24)
 
 /*
  * Opcodes to allow 24-bit atom or object indexes. Whenever an index exceeds
  * the 16-bit limit, the index-accessing bytecode must be bracketed by
  * JSOP_INDEXBASE and JSOP_RESETBASE to provide the upper bits of the index.
  * See jsemit.c, EmitIndexOp.
  */
-OPDEF(JSOP_INDEXBASE,     189,"indexbase",  NULL,     2,  0,  0,  0,  JOF_UINT8|JOF_INDEXBASE)
-OPDEF(JSOP_RESETBASE,     190,"resetbase",  NULL,     1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_RESETBASE0,    191,"resetbase0", NULL,     1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_INDEXBASE,     188,"indexbase",  NULL,     2,  0,  0,  0,  JOF_UINT8|JOF_INDEXBASE)
+OPDEF(JSOP_RESETBASE,     189,"resetbase",  NULL,     1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_RESETBASE0,    190,"resetbase0", NULL,     1,  0,  0,  0,  JOF_BYTE)
 
 /*
  * Opcodes to help the decompiler deal with XML.
  */
-OPDEF(JSOP_STARTXML,      192,"startxml",    NULL,    1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_STARTXMLEXPR,  193,"startxmlexpr",NULL,    1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_STARTXML,      191,"startxml",    NULL,    1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_STARTXMLEXPR,  192,"startxmlexpr",NULL,    1,  0,  0,  0,  JOF_BYTE)
 
-OPDEF(JSOP_CALLELEM,      194, "callelem",   NULL,    1,  2,  2, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC|JOF_CALLOP)
+OPDEF(JSOP_CALLELEM,      193, "callelem",   NULL,    1,  2,  2, 18,  JOF_BYTE |JOF_ELEM|JOF_TYPESET|JOF_LEFTASSOC|JOF_CALLOP)
 
 /*
  * Stop interpretation, emitted at end of script to save the threaded bytecode
  * interpreter an extra branch test on every DO_NEXT_OP (see jsinterp.c).
  */
-OPDEF(JSOP_STOP,          195,"stop",        NULL,    1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_STOP,          194,"stop",        NULL,    1,  0,  0,  0,  JOF_BYTE)
 
 /*
  * Get an extant property value, throwing ReferenceError if the identified
  * property does not exist.
  */
-OPDEF(JSOP_GETXPROP,      196,"getxprop",    NULL,    3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
+OPDEF(JSOP_GETXPROP,      195,"getxprop",    NULL,    3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
 
-OPDEF(JSOP_CALLXMLNAME,   197, "callxmlname",  NULL,  1,  1,  2, 19,  JOF_BYTE|JOF_CALLOP)
+OPDEF(JSOP_CALLXMLNAME,   196, "callxmlname",  NULL,  1,  1,  2, 19,  JOF_BYTE|JOF_CALLOP)
 
 /*
  * Specialized JSOP_TYPEOF to avoid reporting undefined for typeof(0, undef).
  */
-OPDEF(JSOP_TYPEOFEXPR,    198,"typeofexpr",  NULL,    1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
+OPDEF(JSOP_TYPEOFEXPR,    197,"typeofexpr",  NULL,    1,  1,  1, 15,  JOF_BYTE|JOF_DETECTING)
 
 /*
  * Block-local scope support.
  */
-OPDEF(JSOP_ENTERBLOCK,    199,"enterblock",  NULL,    3,  0, -1,  0,  JOF_OBJECT)
-OPDEF(JSOP_LEAVEBLOCK,    200,"leaveblock",  NULL,    5, -1,  0,  0,  JOF_UINT16)
+OPDEF(JSOP_ENTERBLOCK,    198,"enterblock",  NULL,    3,  0, -1,  0,  JOF_OBJECT)
+OPDEF(JSOP_LEAVEBLOCK,    199,"leaveblock",  NULL,    5, -1,  0,  0,  JOF_UINT16)
 
 /* Jump to target if top of stack value isn't callable. */
-OPDEF(JSOP_IFCANTCALLTOP, 201,"ifcantcalltop",NULL,   3,  1,  1,  0,  JOF_JUMP|JOF_DETECTING)
+OPDEF(JSOP_IFCANTCALLTOP, 200,"ifcantcalltop",NULL,   3,  1,  1,  0,  JOF_JUMP|JOF_DETECTING)
 
 /* Throws a TypeError if the value at the top of the stack is not primitive. */
-OPDEF(JSOP_PRIMTOP,       202,"primtop",     NULL,    2,  1,  1,  0,  JOF_INT8)
+OPDEF(JSOP_PRIMTOP,       201,"primtop",     NULL,    2,  1,  1,  0,  JOF_INT8)
 
 /*
  * Generator and array comprehension support.
  */
-OPDEF(JSOP_GENERATOR,     203,"generator",   NULL,    1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_YIELD,         204,"yield",       NULL,    1,  1,  1,  1,  JOF_BYTE)
-OPDEF(JSOP_ARRAYPUSH,     205,"arraypush",   NULL,    3,  1,  0,  3,  JOF_LOCAL)
+OPDEF(JSOP_GENERATOR,     202,"generator",   NULL,    1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_YIELD,         203,"yield",       NULL,    1,  1,  1,  1,  JOF_BYTE)
+OPDEF(JSOP_ARRAYPUSH,     204,"arraypush",   NULL,    3,  1,  0,  3,  JOF_LOCAL)
 
 /*
  * Get the built-in function::foo namespace and push it.
  */
-OPDEF(JSOP_GETFUNNS,      206,"getfunns",   NULL,     1,  0,  1, 19,  JOF_BYTE)
+OPDEF(JSOP_GETFUNNS,      205,"getfunns",   NULL,     1,  0,  1, 19,  JOF_BYTE)
 
 /*
  * Variant of JSOP_ENUMELEM for destructuring const (const [a, b] = ...).
  */
-OPDEF(JSOP_ENUMCONSTELEM, 207,"enumconstelem",NULL,   1,  3,  0,  3,  JOF_BYTE|JOF_SET)
+OPDEF(JSOP_ENUMCONSTELEM, 206,"enumconstelem",NULL,   1,  3,  0,  3,  JOF_BYTE|JOF_SET)
 
 /*
  * Variant of JSOP_LEAVEBLOCK has a result on the stack above the locals,
  * which must be moved down when the block pops.
  */
-OPDEF(JSOP_LEAVEBLOCKEXPR,208,"leaveblockexpr",NULL,  5, -1,  1,  3,  JOF_UINT16)
+OPDEF(JSOP_LEAVEBLOCKEXPR,207,"leaveblockexpr",NULL,  5, -1,  1,  3,  JOF_UINT16)
 \
 /*
  * Optimize atom segments 1-3.  These must be followed by JSOP_RESETBASE0 after
  * the opcode that they prefix.
  */
-OPDEF(JSOP_INDEXBASE1,    209,"indexbase1",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
-OPDEF(JSOP_INDEXBASE2,    210,"indexbase2",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
-OPDEF(JSOP_INDEXBASE3,    211,"indexbase3",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE1,    208,"indexbase1",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE2,    209,"indexbase2",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
+OPDEF(JSOP_INDEXBASE3,    210,"indexbase3",    NULL,  1,  0,  0,  0,  JOF_BYTE |JOF_INDEXBASE)
 
-OPDEF(JSOP_CALLGNAME,     212, "callgname",    NULL,  3,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP|JOF_GNAME)
-OPDEF(JSOP_CALLLOCAL,     213, "calllocal",    NULL,  3,  0,  2, 19,  JOF_LOCAL|JOF_NAME|JOF_CALLOP)
-OPDEF(JSOP_CALLARG,       214, "callarg",      NULL,  3,  0,  2, 19,  JOF_QARG |JOF_NAME|JOF_CALLOP)
-OPDEF(JSOP_BINDGNAME,     215, "bindgname",    NULL,  3,  0,  1,  0,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME)
+OPDEF(JSOP_CALLGNAME,     211, "callgname",    NULL,  3,  0,  2, 19,  JOF_ATOM|JOF_NAME|JOF_TYPESET|JOF_CALLOP|JOF_GNAME)
+OPDEF(JSOP_CALLLOCAL,     212, "calllocal",    NULL,  3,  0,  2, 19,  JOF_LOCAL|JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_CALLARG,       213, "callarg",      NULL,  3,  0,  2, 19,  JOF_QARG |JOF_NAME|JOF_CALLOP)
+OPDEF(JSOP_BINDGNAME,     214, "bindgname",    NULL,  3,  0,  1,  0,  JOF_ATOM|JOF_NAME|JOF_SET|JOF_GNAME)
 
 /*
  * Opcodes to hold 8-bit and 32-bit immediate integer operands.
  */
-OPDEF(JSOP_INT8,          216, "int8",         NULL,  2,  0,  1, 16,  JOF_INT8)
-OPDEF(JSOP_INT32,         217, "int32",        NULL,  5,  0,  1, 16,  JOF_INT32)
+OPDEF(JSOP_INT8,          215, "int8",         NULL,  2,  0,  1, 16,  JOF_INT8)
+OPDEF(JSOP_INT32,         216, "int32",        NULL,  5,  0,  1, 16,  JOF_INT32)
 
 /*
  * Get the value of the 'length' property from a stacked object.
  */
-OPDEF(JSOP_LENGTH,        218, "length",       NULL,  3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
+OPDEF(JSOP_LENGTH,        217, "length",       NULL,  3,  1,  1, 18,  JOF_ATOM|JOF_PROP|JOF_TYPESET)
 
 /*
  * Push a JSVAL_HOLE value onto the stack, representing an omitted property in
  * an array literal (e.g. property 0 in the array [, 1]).  This opcode is used
  * with the JSOP_NEWARRAY opcode.
  */
-OPDEF(JSOP_HOLE,          219, "hole",         NULL,  1,  0,  1,  0,  JOF_BYTE)
+OPDEF(JSOP_HOLE,          218, "hole",         NULL,  1,  0,  1,  0,  JOF_BYTE)
 
 /*
  * Variants of JSOP_{DEF{,LOCAL}FUN,LAMBDA} optimized for the flat closure case.
  */
-OPDEF(JSOP_DEFFUN_FC,     220,"deffun_fc",     NULL,  3,  0,  0,  0,  JOF_OBJECT|JOF_DECLARING)
-OPDEF(JSOP_DEFLOCALFUN_FC,221,"deflocalfun_fc",NULL,  5,  0,  0,  0,  JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
-OPDEF(JSOP_LAMBDA_FC,     222,"lambda_fc",     NULL,  3,  0,  1, 19,  JOF_OBJECT)
+OPDEF(JSOP_DEFFUN_FC,     219,"deffun_fc",     NULL,  3,  0,  0,  0,  JOF_OBJECT|JOF_DECLARING)
+OPDEF(JSOP_DEFLOCALFUN_FC,220,"deflocalfun_fc",NULL,  5,  0,  0,  0,  JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
+OPDEF(JSOP_LAMBDA_FC,     221,"lambda_fc",     NULL,  3,  0,  1, 19,  JOF_OBJECT)
 
 /*
  * Ensure that the value on the top of the stack is an object. The one
  * argument is an error message, defined in js.msg, that takes one parameter
  * (the decompilation of the primitive value).
  */
-OPDEF(JSOP_OBJTOP,        223,"objtop",        NULL,  3,  0,  0,  0,  JOF_UINT16)
+OPDEF(JSOP_OBJTOP,        222,"objtop",        NULL,  3,  0,  0,  0,  JOF_UINT16)
 
 /*
  * Joined function object as method optimization support.
  */
-OPDEF(JSOP_SETMETHOD,     224,"setmethod",     NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
-OPDEF(JSOP_INITMETHOD,    225,"initmethod",    NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
-OPDEF(JSOP_UNBRAND,       226,"unbrand",       NULL,  1,  1,  1,  0,  JOF_BYTE)
-OPDEF(JSOP_UNBRANDTHIS,   227,"unbrandthis",   NULL,  1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_SETMETHOD,     223,"setmethod",     NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_INITMETHOD,    224,"initmethod",    NULL,  3,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
+OPDEF(JSOP_UNBRAND,       225,"unbrand",       NULL,  1,  1,  1,  0,  JOF_BYTE)
+OPDEF(JSOP_UNBRANDTHIS,   226,"unbrandthis",   NULL,  1,  0,  0,  0,  JOF_BYTE)
 
-OPDEF(JSOP_SHARPINIT,     228,"sharpinit",     NULL,  3,  0,  0,  0,  JOF_UINT16|JOF_SHARPSLOT)
+OPDEF(JSOP_SHARPINIT,     227,"sharpinit",     NULL,  3,  0,  0,  0,  JOF_UINT16|JOF_SHARPSLOT)
 
 /* Pop the stack, convert to a jsid (int or string), and push back. */
-OPDEF(JSOP_TOID,          229, "toid",         NULL,  1,  1,  1,  0,  JOF_BYTE)
+OPDEF(JSOP_TOID,          228, "toid",         NULL,  1,  1,  1,  0,  JOF_BYTE)
--- a/js/src/jsxdrapi.h
+++ b/js/src/jsxdrapi.h
@@ -221,17 +221,17 @@ JS_XDRFindClassById(JSXDRState *xdr, uin
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 98)
+#define JSXDR_BYTECODE_VERSION      (0xb973c0de - 99)
 
 /*
  * Library-private functions.
  */
 extern JSBool
 js_XDRAtom(JSXDRState *xdr, JSAtom **atomp);
 
 JS_END_EXTERN_C
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -953,17 +953,18 @@ mjit::Compiler::finishThisUp(JITScript *
     JSC::LinkBuffer fullCode(result, codeSize, JSC::METHOD_CODE);
     JSC::LinkBuffer stubCode(result + masm.size(), stubcc.size(), JSC::METHOD_CODE);
 
     size_t nNmapLive = loopEntries.length();
     for (size_t i = 0; i < script->length; i++) {
         Bytecode *opinfo = analysis->maybeCode(i);
         if (opinfo && opinfo->safePoint) {
             /* loopEntries cover any safe points which are at loop heads. */
-            if (!cx->typeInferenceEnabled() || !opinfo->loopHead)
+            JSOp op = js_GetOpcode(cx, script, script->code + i);
+            if (!cx->typeInferenceEnabled() || op != JSOP_LOOPHEAD)
                 nNmapLive++;
         }
     }
 
     /* Please keep in sync with JITScript::scriptDataSize! */
     size_t dataSize = sizeof(JITScript) +
                       sizeof(NativeMapEntry) * nNmapLive +
                       sizeof(InlineFrame) * inlineFrames.length() +
@@ -1016,17 +1017,18 @@ mjit::Compiler::finishThisUp(JITScript *
     NativeMapEntry *jitNmap = (NativeMapEntry *)cursor;
     jit->nNmapPairs = nNmapLive;
     cursor += sizeof(NativeMapEntry) * jit->nNmapPairs;
     size_t ix = 0;
     if (jit->nNmapPairs > 0) {
         for (size_t i = 0; i < script->length; i++) {
             Bytecode *opinfo = analysis->maybeCode(i);
             if (opinfo && opinfo->safePoint) {
-                if (cx->typeInferenceEnabled() && opinfo->loopHead)
+                JSOp op = js_GetOpcode(cx, script, script->code + i);
+                if (cx->typeInferenceEnabled() && op == JSOP_LOOPHEAD)
                     continue;
                 Label L = jumpMap[i];
                 JS_ASSERT(L.isSet());
                 jitNmap[ix].bcOff = i;
                 jitNmap[ix].ncode = (uint8 *)(result + masm.distanceOf(L));
                 ix++;
             }
         }
@@ -1576,17 +1578,17 @@ mjit::Compiler::generateMethod()
                 fixedDoubleToAnyEntries.clear();
 
                 /*
                  * Watch for fallthrough to the head of a 'do while' loop.
                  * We don't know what register state we will be using at the head
                  * of the loop so sync, branch, and fix it up after the loop
                  * has been processed.
                  */
-                if (cx->typeInferenceEnabled() && analysis->getCode(PC).loopHead) {
+                if (cx->typeInferenceEnabled() && op == JSOP_LOOPHEAD) {
                     frame.syncAndForgetEverything();
                     Jump j = masm.jump();
                     if (!startLoop(PC, j, PC))
                         return Compile_Error;
                 } else {
                     Label start = masm.label();
                     if (!frame.syncForBranch(PC, Uses(0)))
                         return Compile_Error;
@@ -1729,17 +1731,17 @@ mjit::Compiler::generateMethod()
 
             /*
              * Watch for gotos which are entering a 'for' or 'while' loop.
              * These jump to the loop condition test and are immediately
              * followed by the head of the loop.
              */
             jsbytecode *next = PC + js_CodeSpec[op].length;
             if (cx->typeInferenceEnabled() && analysis->maybeCode(next) &&
-                analysis->getCode(next).loopHead) {
+                js_GetOpcode(cx, script, next) == JSOP_LOOPHEAD) {
                 frame.syncAndForgetEverything();
                 Jump j = masm.jump();
                 if (!startLoop(next, j, target))
                     return Compile_Error;
             } else {
                 if (!frame.syncForBranch(target, Uses(0)))
                     return Compile_Error;
                 Jump j = masm.jump();
@@ -2806,25 +2808,24 @@ mjit::Compiler::generateMethod()
             prepareStubCall(Uses(frame.frameSlots()));
             masm.move(ImmPtr(fun), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::FlatLambda, REJOIN_PUSH_OBJECT);
             frame.takeReg(Registers::ReturnReg);
             frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
           }
           END_CASE(JSOP_LAMBDA_FC)
 
-          BEGIN_CASE(JSOP_TRACE)
-          BEGIN_CASE(JSOP_NOTRACE)
+          BEGIN_CASE(JSOP_LOOPHEAD)
           {
             if (analysis->jumpTarget(PC)) {
                 interruptCheckHelper();
                 recompileCheckHelper();
             }
           }
-          END_CASE(JSOP_TRACE)
+          END_CASE(JSOP_LOOPHEAD)
 
           BEGIN_CASE(JSOP_DEBUGGER)
           {
             prepareStubCall(Uses(0));
             masm.move(ImmPtr(PC), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::DebuggerStatement, REJOIN_FALLTHROUGH);
           }
           END_CASE(JSOP_DEBUGGER)
--- a/js/src/methodjit/LoopState.cpp
+++ b/js/src/methodjit/LoopState.cpp
@@ -1777,35 +1777,36 @@ LoopState::analyzeLoopBody(unsigned fram
     temporariesStart =
         Max<uint32>(temporariesStart,
                     ssa->getFrame(frame).depth + VALUES_PER_STACK_FRAME * 2 + script->nslots);
 
     if (script->failedBoundsCheck || analysis->localsAliasStack())
         skipAnalysis = true;
 
     /* Analyze the entire script for frames inlined in the loop body. */
-    unsigned start = (frame == CrossScriptSSA::OUTER_FRAME) ? lifetime->head + JSOP_TRACE_LENGTH : 0;
+    unsigned start = (frame == CrossScriptSSA::OUTER_FRAME) ? lifetime->head + JSOP_LOOPHEAD_LENGTH : 0;
     unsigned end = (frame == CrossScriptSSA::OUTER_FRAME) ? lifetime->backedge : script->length;
 
     unsigned offset = start;
     while (offset < end) {
         jsbytecode *pc = script->code + offset;
         uint32 successorOffset = offset + analyze::GetBytecodeLength(pc);
 
         analyze::Bytecode *opinfo = analysis->maybeCode(offset);
         if (!opinfo) {
             offset = successorOffset;
             continue;
         }
 
+        JSOp op = JSOp(*pc);
+
         /* Don't do any hoisting for outer loops in case of nesting. */
-        if (opinfo->loopHead)
+        if (op == JSOP_LOOPHEAD)
             skipAnalysis = true;
 
-        JSOp op = JSOp(*pc);
         switch (op) {
 
           case JSOP_CALL: {
             /*
              * Don't hoist within this loop unless calls at this site are inlined.
              * :XXX: also recognize native calls which will be inlined.
              */
             bool foundInline = false;
@@ -1890,18 +1891,17 @@ LoopState::analyzeLoopBody(unsigned fram
             break;
           }
 
           case JSOP_ENUMELEM:
           case JSOP_ENUMCONSTELEM:
             unknownModset = true;
             break;
 
-          case JSOP_TRACE:
-          case JSOP_NOTRACE:
+          case JSOP_LOOPHEAD:
           case JSOP_POP:
           case JSOP_ZERO:
           case JSOP_ONE:
           case JSOP_INT8:
           case JSOP_INT32:
           case JSOP_UINT16:
           case JSOP_UINT24:
           case JSOP_FALSE:
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1200,28 +1200,34 @@ GC(JSContext *cx, uintN argc, jsval *vp)
 {
     JSCompartment *comp = NULL;
     if (argc == 1) {
         Value arg = vp[2];
         if (arg.isObject())
             comp = UnwrapObject(&arg.toObject())->compartment();
     }
 
+#ifndef JS_MORE_DETERMINISTIC
     size_t preBytes = cx->runtime->gcBytes;
+#endif
     JS_CompartmentGC(cx, comp);
 
     char buf[256];
+#ifdef JS_MORE_DETERMINISTIC
+    buf[0] = '\0';
+#else
     JS_snprintf(buf, sizeof(buf), "before %lu, after %lu, break %08lx\n",
                 (unsigned long)preBytes, (unsigned long)cx->runtime->gcBytes,
 #ifdef HAVE_SBRK
                 (unsigned long)sbrk(0)
 #else
                 0
 #endif
                 );
+#endif
     *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf));
     return true;
 }
 
 static const struct ParamPair {
     const char      *name;
     JSGCParamKey    param;
 } paramMap[] = {
@@ -3820,17 +3826,17 @@ JSBool
 MJitCodeStats(JSContext *cx, uintN argc, jsval *vp)
 {
 #ifdef JS_METHODJIT
     JSRuntime *rt = cx->runtime;
     AutoLockGC lock(rt);
     size_t n = 0, method, regexp, unused;
     for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
     {
-        (*c)->getMjitCodeStats(method, regexp, unused);
+        (*c)->sizeOfCode(&method, &regexp, &unused);
         n += method + regexp + unused;
     }
     JS_SET_RVAL(cx, vp, INT_TO_JSVAL(n));
 #else
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
 #endif
     return true;
 }
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -493,17 +493,17 @@ StackSpace::tryBumpLimit(JSContext *cx, 
 {
     if (!ensureSpace(cx, REPORT_ERROR, from, nvals))
         return false;
     *limit = conservativeEnd_;
     return true;
 }
 
 size_t
-StackSpace::committedSize()
+StackSpace::sizeOfCommitted()
 {
 #ifdef XP_WIN
     return (commitEnd_ - base_) * sizeof(Value);
 #else
     return (trustedEnd_ - base_) * sizeof(Value);
 #endif
 }
 
--- a/js/src/vm/StackSpace.h
+++ b/js/src/vm/StackSpace.h
@@ -176,17 +176,17 @@ class StackSpace
      */
     inline Value *getStackLimit(JSContext *cx, MaybeReportError report);
     bool tryBumpLimit(JSContext *cx, Value *from, uintN nvals, Value **limit);
 
     /* Called during GC: mark segments, frames, and slots under firstUnused. */
     void mark(JSTracer *trc);
 
     /* We only report the committed size;  uncommitted size is uninteresting. */
-    JS_FRIEND_API(size_t) committedSize();
+    JS_FRIEND_API(size_t) sizeOfCommitted();
 };
 
 /*****************************************************************************/
 
 class ContextStack
 {
     StackSegment *seg_;
     StackSpace *space_;
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/crashtests/705875.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<script>
+
+window.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
+window.getInterface(null);
+
+</script>
--- a/js/xpconnect/crashtests/crashtests.list
+++ b/js/xpconnect/crashtests/crashtests.list
@@ -29,8 +29,9 @@ load 558979.html
 load 582649.html
 load 601284-1.html
 load 603146-1.html
 load 603858-1.html
 load 608963.html
 load 616930-1.html
 load 639737-1.html
 load 648206-1.html
+load 705875.html
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -3899,18 +3899,21 @@ nsXPCComponents_Utils::CreateObjectIn(co
 JSBool
 FunctionWrapper(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval v;
     if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)), 0, &v))
         return false;
     NS_ASSERTION(JSVAL_IS_OBJECT(v), "weird function");
 
-    return JS_CallFunctionValue(cx, JS_THIS_OBJECT(cx, vp), v,
-                                argc, JS_ARGV(cx, vp), vp);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj) {
+        return JS_FALSE;
+    }
+    return JS_CallFunctionValue(cx, obj, v, argc, JS_ARGV(cx, vp), vp);
 }
 
 JSBool
 WrapCallable(JSContext *cx, JSObject *obj, jsid id, JSObject *propobj, jsval *vp)
 {
     JSFunction *fun = JS_NewFunctionById(cx, FunctionWrapper, 0, 0,
                                          JS_GetGlobalForObject(cx, obj), id);
     if (!fun)
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -596,19 +596,21 @@ XPCConvert::JSData2Native(XPCCallContext
             XPC_LOG_ERROR(("XPCConvert::JSData2Native : void* params not supported"));
             NS_ERROR("void* params not supported");
             return false;
         case nsXPTType::T_IID:
         {
             JSObject* obj;
             const nsID* pid=nsnull;
 
+            // There's no good reason to pass a null IID.
             if (JSVAL_IS_VOID(s) || JSVAL_IS_NULL(s)) {
-                *((const nsID**)d) = nsnull;
-                return true;
+                if (pErr)
+                  *pErr = NS_ERROR_XPC_BAD_CONVERT_JS;
+                return false;
             }
 
             if (!JSVAL_IS_OBJECT(s) ||
                 (!(obj = JSVAL_TO_OBJECT(s))) ||
                 (!(pid = xpc_JSObjectToID(cx, obj))) ||
                 (!(pid = (const nsID*) nsMemory::Clone(pid, sizeof(nsID))))) {
                 return false;
             }
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1222,20 +1222,19 @@ CompartmentCallback(JSContext *cx, void 
     CompartmentStats compartmentStats(cx, compartment);
     CompartmentStats *curr =
         data->compartmentStatsVector.AppendElement(compartmentStats);
     data->currCompartmentStats = curr;
 
     // Get the compartment-level numbers.
 #ifdef JS_METHODJIT
     size_t method, regexp, unused;
-    compartment->getMjitCodeStats(method, regexp, unused);
-    curr->mjitCodeMethod = method;
-    curr->mjitCodeRegexp = regexp;
-    curr->mjitCodeUnused = unused;
+    compartment->sizeOfCode(&method, &regexp, &unused);
+    JS_ASSERT(regexp == 0);     /* this execAlloc is only used for method code */
+    curr->mjitCode = method + unused;
 #endif
     JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
                                    MemoryReporterMallocSizeOf);
 }
 
 void
 ChunkCallback(JSContext *cx, void *vdata, js::gc::Chunk *chunk)
 {
@@ -1526,25 +1525,53 @@ CollectCompartmentStatsForRuntime(JSRunt
         data->gcHeapChunkTotal =
             PRInt64(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) *
             js::gc::ChunkSize;
 
         js::IterateCompartmentsArenasCells(cx, data, CompartmentCallback,
                                            ArenaCallback, CellCallback);
         js::IterateChunks(cx, data, ChunkCallback);
 
-        for (js::ThreadDataIter i(rt); !i.empty(); i.popFront())
-            data->stackSize += i.threadData()->stackSpace.committedSize();
-
-        data->runtimeObjectSize = MemoryReporterMallocSizeOf(rt, sizeof(JSRuntime));
+        data->runtimeObject = MemoryReporterMallocSizeOf(rt, sizeof(JSRuntime));
 
         // Nb: we use sizeOfExcludingThis() because atomState.atoms is within
         // JSRuntime, and so counted when JSRuntime is counted.
-        data->atomsTableSize =
+        data->runtimeAtomsTable =
             rt->atomState.atoms.sizeOfExcludingThis(MemoryReporterMallocSizeOf);
+
+        {
+            #ifndef JS_THREADSAFE
+            #error "This code assumes JS_THREADSAFE is defined"
+            #endif
+
+            // Need the GC lock to call JS_ContextIteratorUnlocked() and to
+            // access rt->threads.
+            js::AutoLockGC lock(rt);
+
+            JSContext *acx, *iter = NULL;
+            while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL) {
+                data->runtimeContexts +=
+                    acx->sizeOfIncludingThis(MemoryReporterMallocSizeOf);
+            }
+
+            for (JSThread::Map::Range r = rt->threads.all(); !r.empty(); r.popFront()) {
+                JSThread *thread = r.front().value;
+                size_t normal, temporary, regexpCode, stackCommitted;
+                thread->sizeOfIncludingThis(MemoryReporterMallocSizeOf,
+                                            &normal,
+                                            &temporary,
+                                            &regexpCode,
+                                            &stackCommitted);
+
+                data->runtimeThreadsNormal         += normal;
+                data->runtimeThreadsTemporary      += temporary;
+                data->runtimeThreadsRegexpCode     += regexpCode;
+                data->runtimeThreadsStackCommitted += stackCommitted;
+            }
+        }
     }
 
     JS_DestroyContextNoGC(cx);
 
     // This is initialized to all bytes stored in used chunks, and then we
     // subtract used space from it each time around the loop.
     data->gcHeapChunkDirtyUnused = data->gcHeapChunkTotal -
                                    data->gcHeapChunkCleanUnused -
@@ -1578,19 +1605,17 @@ CollectCompartmentStatsForRuntime(JSRunt
                               stats.shapesExtraTreeTables +
                               stats.shapesExtraDictTables +
                               stats.typeInferenceMemory.emptyShapes;
         data->totalScripts += stats.gcHeapScripts + 
                               stats.scriptData;
         data->totalStrings += stats.gcHeapStrings + 
                               stats.stringChars;
 #ifdef JS_METHODJIT
-        data->totalMjit    += stats.mjitCodeMethod + 
-                              stats.mjitCodeRegexp +
-                              stats.mjitCodeUnused +
+        data->totalMjit    += stats.mjitCode + 
                               stats.mjitData;
 #endif
         data->totalTypeInference += stats.gcHeapTypeObjects +
                                     stats.typeInferenceMemory.objects +
                                     stats.typeInferenceMemory.scripts + 
                                     stats.typeInferenceMemory.tables;
         data->totalAnalysisTemp  += stats.typeInferenceMemory.temporary;
     }
@@ -1760,35 +1785,22 @@ ReportCompartmentStats(const Compartment
                                               "script-data"),
                        nsIMemoryReporter::KIND_HEAP, stats.scriptData,
                        "Memory allocated for JSScript bytecode and various variable-length "
                        "tables." SLOP_BYTES_STRING,
                        callback, closure);
 
 #ifdef JS_METHODJIT
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
-                                              "mjit-code/method"),
-                       nsIMemoryReporter::KIND_NONHEAP, stats.mjitCodeMethod,
+                                              "mjit-code"),
+                       nsIMemoryReporter::KIND_NONHEAP, stats.mjitCode,
                        "Memory used by the method JIT to hold the compartment's generated code.",
                        callback, closure);
 
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
-                                              "mjit-code/regexp"),
-                       nsIMemoryReporter::KIND_NONHEAP, stats.mjitCodeRegexp,
-                       "Memory used by the regexp JIT to hold the compartment's generated code.",
-                       callback, closure);
-
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
-                                              "mjit-code/unused"),
-                       nsIMemoryReporter::KIND_NONHEAP, stats.mjitCodeUnused,
-                       "Memory allocated by the method and/or regexp JIT to hold the "
-                       "compartment's code, but which is currently unused.",
-                       callback, closure);
-
-    ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
                                               "mjit-data"),
                        nsIMemoryReporter::KIND_HEAP, stats.mjitData,
                        "Memory used by the method JIT for the compartment's compilation data: "
                        "JITScripts, native maps, and inline cache structs." SLOP_BYTES_STRING,
                        callback, closure);
 #endif
 
     ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
@@ -1831,30 +1843,55 @@ ReportJSRuntimeStats(const IterateData &
     for (PRUint32 index = 0;
          index < data.compartmentStatsVector.Length();
          index++) {
         ReportCompartmentStats(data.compartmentStatsVector[index], pathPrefix,
                                callback, closure);
     }
 
     ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"),
-                      nsIMemoryReporter::KIND_NONHEAP, data.runtimeObjectSize,
+                      nsIMemoryReporter::KIND_HEAP, data.runtimeObject,
                       "Memory used by the JSRuntime object." SLOP_BYTES_STRING,
                       callback, closure);
 
     ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"),
-                      nsIMemoryReporter::KIND_NONHEAP, data.atomsTableSize,
-                      "Memory used by the atoms table.",
+                      nsIMemoryReporter::KIND_HEAP, data.runtimeAtomsTable,
+                      "Memory used by the atoms table." SLOP_BYTES_STRING,
+                      callback, closure);
+
+    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"),
+                      nsIMemoryReporter::KIND_HEAP, data.runtimeContexts,
+                      "Memory used by JSContext objects and certain structures "
+                      "hanging off them."  SLOP_BYTES_STRING,
+                      callback, closure);
+
+    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/threads/normal"),
+                      nsIMemoryReporter::KIND_HEAP, data.runtimeThreadsNormal,
+                      "Memory used by JSThread objects and their data, "
+                      "excluding memory that is reported by "
+                      "other reporters under 'explicit/js/runtime/'." SLOP_BYTES_STRING,
                       callback, closure);
 
-    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("stack"),
-                      nsIMemoryReporter::KIND_NONHEAP, data.stackSize,
-                      "Memory used for the JavaScript stack.  This is the committed portion "
-                      "of the stack; any uncommitted portion is not measured because it "
-                      "hardly costs anything.",
+    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/threads/temporary"),
+                      nsIMemoryReporter::KIND_HEAP, data.runtimeThreadsTemporary,
+                      "Memory held transiently in JSThreads and used during "
+                      "compilation.  It mostly holds parse nodes."
+                      SLOP_BYTES_STRING,
+                      callback, closure);
+
+    ReportMemoryBytes0(pathPrefix + NS_LITERAL_CSTRING("runtime/threads/regexp-code"),
+                       nsIMemoryReporter::KIND_NONHEAP, data.runtimeThreadsRegexpCode,
+                       "Memory used by the regexp JIT to hold generated code.",
+                       callback, closure);
+
+    ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/threads/stack-committed"),
+                      nsIMemoryReporter::KIND_NONHEAP, data.runtimeThreadsStackCommitted,
+                      "Memory used for the thread stacks.  This is the committed portions "
+                      "of the stacks; any uncommitted portions are not measured because they "
+                      "hardly cost anything.",
                       callback, closure);
 
     ReportMemoryBytes(pathPrefix +
                       NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"),
                       JS_GC_HEAP_KIND, data.gcHeapChunkDirtyUnused,
                       "Memory on the garbage-collected JavaScript heap, within chunks with at "
                       "least one allocated GC thing, that could be holding useful data but "
                       "currently isn't.  Memory here is mutually exclusive with memory reported"
@@ -1978,30 +2015,29 @@ public:
                           nsIMemoryReporter::KIND_OTHER, data.totalStrings,
                           "Memory used for all string-related data.  This is the sum of all "
                           "compartments' 'gc-heap/strings' and 'string-chars' numbers.",
                           callback, closure);
 #ifdef JS_METHODJIT
         ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-mjit"),
                           nsIMemoryReporter::KIND_OTHER, data.totalMjit,
                           "Memory used by the method JIT.  This is the sum of all compartments' "
-                          "'mjit-code-method', 'mjit-code-regexp', 'mjit-code-unused' and '"
-                          "'mjit-data' numbers.",
+                          "'mjit-code', and 'mjit-data' numbers.",
                           callback, closure);
 #endif
         ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-type-inference"),
                           nsIMemoryReporter::KIND_OTHER, data.totalTypeInference,
                           "Non-transient memory used by type inference.  This is the sum of all "
                           "compartments' 'gc-heap/type-objects', 'type-inference/script-main', "
                           "'type-inference/object-main' and 'type-inference/tables' numbers.",
                           callback, closure);
 
         ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-analysis-temporary"),
                           nsIMemoryReporter::KIND_OTHER, data.totalAnalysisTemp,
-                          "Transient memory used during type inference and compilation. "
+                          "Memory used transiently during type inference and compilation. "
                           "This is the sum of all compartments' 'analysis-temporary' numbers.",
                           callback, closure);
 
         return NS_OK;
     }
 };
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(XPConnectJSCompartmentsMultiReporter
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -214,30 +214,32 @@ struct CompartmentStats
     PRInt64 objectSlots;
     PRInt64 stringChars;
     PRInt64 shapesExtraTreeTables;
     PRInt64 shapesExtraDictTables;
     PRInt64 shapesExtraTreeShapeKids;
     PRInt64 scriptData;
 
 #ifdef JS_METHODJIT
-    PRInt64 mjitCodeMethod;
-    PRInt64 mjitCodeRegexp;
-    PRInt64 mjitCodeUnused;
+    PRInt64 mjitCode;
     PRInt64 mjitData;
 #endif
     TypeInferenceMemoryStats typeInferenceMemory;
 };
 
 struct IterateData
 {
     IterateData()
-      : runtimeObjectSize(0),
-        atomsTableSize(0),
-        stackSize(0),
+      : runtimeObject(0),
+        runtimeAtomsTable(0),
+        runtimeContexts(0),
+        runtimeThreadsNormal(0),
+        runtimeThreadsTemporary(0),
+        runtimeThreadsRegexpCode(0),
+        runtimeThreadsStackCommitted(0),
         gcHeapChunkTotal(0),
         gcHeapChunkCleanUnused(0),
         gcHeapChunkDirtyUnused(0),
         gcHeapChunkCleanDecommitted(0),
         gcHeapChunkDirtyDecommitted(0),
         gcHeapArenaUnused(0),
         gcHeapChunkAdmin(0),
         gcHeapUnusedPercentage(0),
@@ -248,19 +250,23 @@ struct IterateData
 #ifdef JS_METHODJIT
         totalMjit(0),
 #endif
         totalTypeInference(0),
         totalAnalysisTemp(0),
         compartmentStatsVector(),
         currCompartmentStats(NULL) { }
 
-    PRInt64 runtimeObjectSize;
-    PRInt64 atomsTableSize;
-    PRInt64 stackSize;
+    PRInt64 runtimeObject;
+    PRInt64 runtimeAtomsTable;
+    PRInt64 runtimeContexts;
+    PRInt64 runtimeThreadsNormal;
+    PRInt64 runtimeThreadsTemporary;
+    PRInt64 runtimeThreadsRegexpCode;
+    PRInt64 runtimeThreadsStackCommitted;
     PRInt64 gcHeapChunkTotal;
     PRInt64 gcHeapChunkCleanUnused;
     PRInt64 gcHeapChunkDirtyUnused;
     PRInt64 gcHeapChunkCleanDecommitted;
     PRInt64 gcHeapChunkDirtyDecommitted;
     PRInt64 gcHeapArenaUnused;
     PRInt64 gcHeapChunkAdmin;
     PRInt64 gcHeapUnusedPercentage;
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -445,17 +445,17 @@ nodePrincipal_getter(JSContext *cx, JSOb
     }
     return true;
 }
 
 static JSBool
 XrayToString(JSContext *cx, uintN argc, jsval *vp)
 {
     JSObject *wrapper = JS_THIS_OBJECT(cx, vp);
-    if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
+    if (!wrapper || !IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "XrayToString called on an incompatible object");
         return false;
     }
 
     nsAutoString result(NS_LITERAL_STRING("[object XrayWrapper "));
     if (mozilla::dom::binding::instanceIsProxy(&js::GetProxyPrivate(wrapper).toObject())) {
         JSString *wrapperStr = js::GetProxyHandler(wrapper)->obj_toString(cx, wrapper);
         size_t length;
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -1883,24 +1883,29 @@ DocumentViewerImpl::SetBounds(const nsIn
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
 
   mBounds = aBounds;
   if (mWindow) {
     // When attached to a top level window, change the client area, not the
     // window frame.
     // Don't have the widget repaint. Layout will generate repaint requests
     // during reflow.
-    if (mAttachedToParent)
-      mWindow->ResizeClient(aBounds.x, aBounds.y,
-                            aBounds.width, aBounds.height,
-                            false);
-    else
+    if (mAttachedToParent) {
+      if (aBounds.x != 0 || aBounds.y != 0) {
+        mWindow->ResizeClient(aBounds.x, aBounds.y,
+                              aBounds.width, aBounds.height,
+                              false);
+      } else {
+        mWindow->ResizeClient(aBounds.width, aBounds.height, false);
+      }
+    } else {
       mWindow->Resize(aBounds.x, aBounds.y,
                       aBounds.width, aBounds.height,
                       false);
+    }
   } else if (mPresContext && mViewManager) {
     PRInt32 p2a = mPresContext->AppUnitsPerDevPixel();
     mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(mBounds.width, p2a),
                                       NSIntPixelsToAppUnits(mBounds.height, p2a));
   }
 
   // If there's a previous viewer, it's the one that's actually showing,
   // so be sure to resize it as well so it paints over the right area.
--- a/layout/build/nsLayoutCID.h
+++ b/layout/build/nsLayoutCID.h
@@ -86,23 +86,19 @@
 // {3B581FD4-3497-426c-8F61-3658B971CB80}
 #define NS_TREEBOXOBJECT_CID \
 { 0x3b581fd4, 0x3497, 0x426c, { 0x8f, 0x61, 0x36, 0x58, 0xb9, 0x71, 0xcb, 0x80 } }
 
 // {a35d1cd4-c505-4d2d-a0f9-aef00b7ce5a5}
 #define NS_CANVASRENDERINGCONTEXT2D_CID \
 { 0xa35d1cd4, 0xc505, 0x4d2d, { 0xa0, 0xf9, 0xae, 0xf0, 0x0b, 0x7c, 0xe5, 0xa5 } }
 
-// {BCD923C0-9788-4350-AC48-365F473161EB}
-#define NS_CANVASRENDERINGCONTEXT2DTHEBES_CID \
-{ 0xbcd923c0, 0x9788, 0x4350, { 0xac, 0x48, 0x36, 0x5f, 0x47, 0x31, 0x61, 0xeb } }
-
-// {9052bb12-79b0-4bdd-8e60-7bf078026b6d}
-#define NS_CANVASRENDERINGCONTEXT2DAZURE_CID \
-{0x9052bb12, 0x79b0, 0x4bdd, {0x8e, 0x60, 0x7b, 0xf0, 0x78, 0x02, 0x6b, 0x6d}}
+// {BCD923C0-9788-4350-AC48-365F473161EB}
+#define NS_CANVASRENDERINGCONTEXT2DTHEBES_CID \
+{ 0xbcd923c0, 0x9788, 0x4350, { 0xac, 0x48, 0x36, 0x5f, 0x47, 0x31, 0x61, 0xeb } }
 
 // {2fe88332-31c6-4829-b247-a07d8a73e80f}
 #define NS_CANVASRENDERINGCONTEXTWEBGL_CID \
 { 0x2fe88332, 0x31c6, 0x4829, { 0xb2, 0x47, 0xa0, 0x7d, 0x8a, 0x7e, 0xe8, 0x0fe } }
 
 // {8b449142-1eab-4bfa-9830-fab6ebb09774}
 #define NS_DOMSTORAGE_CID \
 { 0x8b449142, 0x1eab, 0x4bfa, { 0x98, 0x30, 0xfa, 0xb6, 0xeb, 0xb0, 0x97, 0x74 } }
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -760,17 +760,16 @@ NS_DEFINE_NAMED_CID(NS_PRECONTENTITERATO
 NS_DEFINE_NAMED_CID(NS_SUBTREEITERATOR_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLIMAGEELEMENT_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLOPTIONELEMENT_CID);
 #ifdef MOZ_MEDIA
 NS_DEFINE_NAMED_CID(NS_HTMLAUDIOELEMENT_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2D_CID);
 NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DTHEBES_CID);
-NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXT2DAZURE_CID);
 NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCONTEXTWEBGL_CID);
 NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCOPY_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_XMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_XHTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(MOZ_SANITIZINGHTMLSERIALIZER_CID);
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -110,16 +110,17 @@ NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame
 
 //
 // nsMenuPopupFrame ctor
 //
 nsMenuPopupFrame::nsMenuPopupFrame(nsIPresShell* aShell, nsStyleContext* aContext)
   :nsBoxFrame(aShell, aContext),
   mCurrentMenu(nsnull),
   mPrefSize(-1, -1),
+  mLastClientOffset(0, 0),
   mPopupType(ePopupTypePanel),
   mPopupState(ePopupClosed),
   mPopupAlignment(POPUPALIGNMENT_NONE),
   mPopupAnchor(POPUPALIGNMENT_NONE),
   mConsumeRollupEvent(nsIPopupBoxObject::ROLLUP_DEFAULT),
   mFlipBoth(false),
   mIsOpenChanged(false),
   mIsContextMenu(false),
@@ -481,31 +482,16 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayou
 
   nsPresContext* pc = PresContext();
   if (isOpen) {
     nsIView* view = GetView();
     nsIViewManager* viewManager = view->GetViewManager();
     nsRect rect = GetRect();
     rect.x = rect.y = 0;
 
-    // Increase the popup's view size to account for any titlebar or borders.
-    // XXXndeakin this should really be accounted for earlier in
-    // SetPopupPosition so that this extra size is accounted for when flipping
-    // or resizing the popup due to it being too large, but that can be a
-    // followup bug.
-    if (mPopupType == ePopupTypePanel && view) {
-      nsIWidget* widget = view->GetWidget();
-      if (widget) {
-        nsIntSize popupSize = nsIntSize(pc->AppUnitsToDevPixels(rect.width),
-                                        pc->AppUnitsToDevPixels(rect.height));
-        popupSize = widget->ClientToWindowSize(popupSize);
-        rect.width = pc->DevPixelsToAppUnits(popupSize.width);
-        rect.height = pc->DevPixelsToAppUnits(popupSize.height);
-      }
-    }
     viewManager->ResizeView(view, rect);
 
     viewManager->SetViewVisibility(view, nsViewVisibility_kShow);
     mPopupState = ePopupOpenAndVisible;
     nsContainerFrame::SyncFrameViewProperties(pc, this, nsnull, view, 0);
   }
 
   // finally, if the popup just opened, send a popupshown event
@@ -1313,30 +1299,31 @@ nsMenuPopupFrame::SetPopupPosition(nsIFr
   nsPoint viewPoint = screenPoint - rootScreenRect.TopLeft();
 
   // snap the view's position to device pixels, see bug 622507
   viewPoint.x = presContext->RoundAppUnitsToNearestDevPixels(viewPoint.x);
   viewPoint.y = presContext->RoundAppUnitsToNearestDevPixels(viewPoint.y);
 
   nsIView* view = GetView();
   NS_ASSERTION(view, "popup with no view");
-  presContext->GetPresShell()->GetViewManager()->
-    MoveViewTo(view, viewPoint.x, viewPoint.y);
 
   // Offset the position by the width and height of the borders and titlebar.
   // Even though GetClientOffset should return (0, 0) when there is no
   // titlebar or borders, we skip these calculations anyway for non-panels
   // to save time since they will never have a titlebar.
   nsIWidget* widget = view->GetWidget();
   if (mPopupType == ePopupTypePanel && widget) {
-    nsIntPoint offset = widget->GetClientOffset();
-    viewPoint.x += presContext->DevPixelsToAppUnits(offset.x);
-    viewPoint.y += presContext->DevPixelsToAppUnits(offset.y);
+    mLastClientOffset = widget->GetClientOffset();
+    viewPoint.x += presContext->DevPixelsToAppUnits(mLastClientOffset.x);
+    viewPoint.y += presContext->DevPixelsToAppUnits(mLastClientOffset.y);
   }
 
+  presContext->GetPresShell()->GetViewManager()->
+    MoveViewTo(view, viewPoint.x, viewPoint.y);
+
   // Now that we've positioned the view, sync up the frame's origin.
   nsBoxFrame::SetPosition(viewPoint - GetParent()->GetOffsetTo(rootFrame));
 
   if (sizedToPopup) {
     nsBoxLayoutState state(PresContext());
     // XXXndeakin can parentSize.width still extend outside?
     SetBounds(state, nsRect(mRect.x, mRect.y, parentRect.width, mRect.height));
   }
@@ -1758,26 +1745,24 @@ nsMenuPopupFrame::LockMenuUntilClosed(bo
   if (parent && parent->GetType() == nsGkAtoms::menuFrame) {
     nsMenuParent* parentParent = static_cast<nsMenuFrame*>(parent)->GetMenuParent();
     if (parentParent) {
       parentParent->LockMenuUntilClosed(aLock);
     }
   }
 }
 
-NS_IMETHODIMP
-nsMenuPopupFrame::GetWidget(nsIWidget **aWidget)
+nsIWidget*
+nsMenuPopupFrame::GetWidget()
 {
   nsIView * view = GetRootViewForPopup(this);
   if (!view)
-    return NS_OK;
+    return nsnull;
 
-  *aWidget = view->GetWidget();
-  NS_IF_ADDREF(*aWidget);
-  return NS_OK;
+  return view->GetWidget();
 }
 
 void
 nsMenuPopupFrame::AttachedDismissalListener()
 {
   mConsumeRollupEvent = nsIPopupBoxObject::ROLLUP_DEFAULT;
 }
 
@@ -1866,18 +1851,21 @@ nsMenuPopupFrame::DestroyFrom(nsIFrame* 
 
   nsBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
 void
 nsMenuPopupFrame::MoveTo(PRInt32 aLeft, PRInt32 aTop, bool aUpdateAttrs)
 {
-  if (mScreenXPos == aLeft && mScreenYPos == aTop)
+  nsIWidget* widget = GetWidget();
+  if ((mScreenXPos == aLeft && mScreenYPos == aTop) &&
+      (!widget || widget->GetClientOffset() == mLastClientOffset)) {
     return;
+  }
 
   // reposition the popup at the specified coordinates. Don't clear the anchor
   // and position, because the popup can be reset to its anchor position by
   // using (-1, -1) as coordinates. Subtract off the margin as it will be
   // added to the position when SetPopupPosition is called.
   nsMargin margin(0, 0, 0, 0);
   GetStyleMargin()->GetMargin(margin);
   nsPresContext* presContext = PresContext();
--- a/layout/xul/base/src/nsMenuPopupFrame.h
+++ b/layout/xul/base/src/nsMenuPopupFrame.h
@@ -171,17 +171,17 @@ public:
 
   virtual bool IsContextMenu() { return mIsContextMenu; }
 
   virtual bool MenuClosed() { return true; }
 
   virtual void LockMenuUntilClosed(bool aLock);
   virtual bool IsMenuLocked() { return mIsMenuLocked; }
 
-  NS_IMETHOD GetWidget(nsIWidget **aWidget);
+  nsIWidget* GetWidget();
 
   // The dismissal listener gets created and attached to the window.
   void AttachedDismissalListener();
 
   // Overridden methods
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
@@ -347,16 +347,19 @@ public:
   nsIContent* GetAnchor() const { return mAnchorContent; }
 
   // Return the screen coordinates of the popup, or (-1, -1) if anchored.
   nsIntPoint ScreenPosition() const { return nsIntPoint(mScreenXPos, mScreenYPos); }
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
+
+  nsIntPoint GetLastClientOffset() const { return mLastClientOffset; }
+
 protected:
 
   // returns the popup's level.
   nsPopupLevel PopupLevel(bool aIsNoAutoHide) const;
 
   // redefine to tell the box system not to move the views.
   virtual void GetLayoutFlags(PRUint32& aFlags);
 
@@ -430,16 +433,20 @@ protected:
   nsSize mPrefSize;
 
   // the position of the popup. The screen coordinates, if set to values other
   // than -1, override mXPos and mYPos.
   PRInt32 mXPos;
   PRInt32 mYPos;
   PRInt32 mScreenXPos;
   PRInt32 mScreenYPos;
+  // The value of the client offset of our widget the last time we positioned
+  // ourselves. We store this so that we can detect when it changes but the
+  // position of our widget didn't change.
+  nsIntPoint mLastClientOffset;
 
   nsPopupType mPopupType; // type of popup
   nsPopupState mPopupState; // open state of the popup
 
   // popup alignment relative to the anchor node
   PRInt8 mPopupAlignment;
   PRInt8 mPopupAnchor;
   // One of nsIPopupBoxObject::ROLLUP_DEFAULT/ROLLUP_CONSUME/ROLLUP_NO_CONSUME
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -254,18 +254,17 @@ nsResizerFrame::HandleEvent(nsPresContex
           appUnitsRect.width = mRect.width;
         if (appUnitsRect.height < mRect.height && mouseMove.y)
           appUnitsRect.height = mRect.height;
         nsIntRect cssRect = appUnitsRect.ToInsidePixels(nsPresContext::AppUnitsPerCSSPixel());
 
         nsIntRect oldRect;
         nsWeakFrame weakFrame(menuPopupFrame);
         if (menuPopupFrame) {
-          nsCOMPtr<nsIWidget> widget;
-          menuPopupFrame->GetWidget(getter_AddRefs(widget));
+          nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
           if (widget)
             widget->GetScreenBounds(oldRect);
 
           // convert the new rectangle into outer window coordinates
           nsIntPoint clientOffset = widget->GetClientOffset();
           rect.x -= clientOffset.x; 
           rect.y -= clientOffset.y; 
         }
--- a/layout/xul/base/src/nsTitleBarFrame.cpp
+++ b/layout/xul/base/src/nsTitleBarFrame.cpp
@@ -156,18 +156,17 @@ nsTitleBarFrame::HandleEvent(nsPresConte
          nsIFrame* parent = GetParent();
          while (parent && parent->GetType() != nsGkAtoms::menuPopupFrame)
            parent = parent->GetParent();
 
          // if the titlebar is in a popup, move the popup frame, otherwise
          // move the widget associated with the window
          if (parent) {
            nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
-           nsCOMPtr<nsIWidget> widget;
-           menuPopupFrame->GetWidget(getter_AddRefs(widget));
+           nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
            nsIntRect bounds;
            widget->GetScreenBounds(bounds);
            menuPopupFrame->MoveTo(bounds.x + nsMoveBy.x, bounds.y + nsMoveBy.y, false);
          }
          else {
            nsIPresShell* presShell = aPresContext->PresShell();
            nsPIDOMWindow *window = presShell->GetDocument()->GetWindow();
            if (window) {
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -278,18 +278,17 @@ nsXULPopupManager::GetSubmenuWidgetChain
   // this method is used by the widget code to determine the list of popups
   // that are open. If a mouse click occurs outside one of these popups, the
   // panels will roll up. If the click is inside a popup, they will not roll up
   PRUint32 count = 0, sameTypeCount = 0;
 
   NS_ASSERTION(aWidgetChain, "null parameter");
   nsMenuChainItem* item = GetTopVisibleMenu();
   while (item) {
-    nsCOMPtr<nsIWidget> widget;
-    item->Frame()->GetWidget(getter_AddRefs(widget));
+    nsCOMPtr<nsIWidget> widget = item->Frame()->GetWidget();
     NS_ASSERTION(widget, "open popup has no widget");
     aWidgetChain->AppendElement(widget.get());
     // In the case when a menulist inside a panel is open, clicking in the
     // panel should still roll up the menu, so if a different type is found,
     // stop scanning.
     nsMenuChainItem* parent = item->GetParent();
     if (!sameTypeCount) {
       count++;
@@ -354,17 +353,19 @@ nsXULPopupManager::PopupMoved(nsIFrame* 
 {
   nsMenuPopupFrame* menuPopupFrame = GetPopupToMoveOrResize(aFrame);
   if (!menuPopupFrame)
     return;
 
   // Don't do anything if the popup is already at the specified location. This
   // prevents recursive calls when a popup is positioned.
   nsIntPoint currentPnt = menuPopupFrame->ScreenPosition();
-  if (aPnt.x != currentPnt.x || aPnt.y != currentPnt.y) {
+  nsIWidget* widget = menuPopupFrame->GetWidget();
+  if ((aPnt.x != currentPnt.x || aPnt.y != currentPnt.y) || (widget &&
+      widget->GetClientOffset() != menuPopupFrame->GetLastClientOffset())) {
     // Update the popup's position using SetPopupPosition if the popup is
     // anchored and at the parent level as these maintain their position
     // relative to the parent window. Otherwise, just update the popup to
     // the specified screen coordinates.
     if (menuPopupFrame->IsAnchored() &&
         menuPopupFrame->PopupLevel() == ePopupLevelParent) {
       menuPopupFrame->SetPopupPosition(nsnull, true);
     }
@@ -1459,18 +1460,17 @@ nsXULPopupManager::MayShowPopup(nsMenuPo
 
   // Don't show popups that we already have in our popup chain
   if (IsPopupOpen(aPopup->GetContent())) {
     NS_WARNING("Refusing to show duplicate popup");
     return false;
   }
 
   // if the popup was just rolled up, don't reopen it
-  nsCOMPtr<nsIWidget> widget;
-  aPopup->GetWidget(getter_AddRefs(widget));
+  nsCOMPtr<nsIWidget> widget = aPopup->GetWidget();
   if (widget && widget->GetLastRollup() == aPopup->GetContent())
       return false;
 
   nsCOMPtr<nsISupports> cont = aPopup->PresContext()->GetContainer();
   nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(dsti);
   if (!baseWin)
     return false;
@@ -1613,18 +1613,17 @@ nsXULPopupManager::SetCaptureState(nsICo
 
   if (mWidget) {
     mWidget->CaptureRollupEvents(this, false, false);
     mWidget = nsnull;
   }
 
   if (item) {
     nsMenuPopupFrame* popup = item->Frame();
-    nsCOMPtr<nsIWidget> widget;
-    popup->GetWidget(getter_AddRefs(widget));
+    nsCOMPtr<nsIWidget> widget = popup->GetWidget();
     if (widget) {
       widget->CaptureRollupEvents(this, true, popup->ConsumeOutsideClicks());
       mWidget = widget;
       popup->AttachedDismissalListener();
     }
   }
 
   UpdateKeyboardListeners();
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -70,20 +70,21 @@
 #      define MOZ_HAVE_CXX11_DELETE
 #    endif
 #  endif
 #elif defined(__GNUC__)
 #  if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
 #    if __GNUC__ > 4
 #      define MOZ_HAVE_CXX11_DELETE
 #      define MOZ_HAVE_CXX11_OVERRIDE
-#      define MOZ_HAVE CXX11_FINAL       final
+#      define MOZ_HAVE_CXX11_FINAL       final
 #    elif __GNUC__ == 4
 #      if __GNUC_MINOR__ >= 7
 #        define MOZ_HAVE_CXX11_OVERRIDE
+#        define MOZ_HAVE_CXX11_FINAL     final
 #      endif
 #      if __GNUC_MINOR__ >= 4
 #        define MOZ_HAVE_CXX11_DELETE
 #      endif
 #    endif
 #  else
      /* __final is a non-C++11 GCC synonym for 'final', per GCC r176655. */
 #    if __GNUC__ > 4
--- a/storage/src/mozStorageStatementJSHelper.cpp
+++ b/storage/src/mozStorageStatementJSHelper.cpp
@@ -61,19 +61,23 @@ namespace storage {
 static
 JSBool
 stepFunc(JSContext *aCtx,
          PRUint32,
          jsval *_vp)
 {
   nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
-  nsresult rv = xpc->GetWrappedNativeOfJSObject(
-    aCtx, JS_THIS_OBJECT(aCtx, _vp), getter_AddRefs(wrapper)
-  );
+  JSObject *obj = JS_THIS_OBJECT(aCtx, _vp);
+  if (!obj) {
+    return JS_FALSE;
+  }
+
+  nsresult rv =
+    xpc->GetWrappedNativeOfJSObject(aCtx, obj, getter_AddRefs(wrapper));
   if (NS_FAILED(rv)) {
     ::JS_ReportError(aCtx, "mozIStorageStatement::step() could not obtain native statement");
     return JS_FALSE;
   }
 
 #ifdef DEBUG
   {
     nsCOMPtr<mozIStorageStatement> isStatement(
--- a/toolkit/components/places/AsyncFaviconHelpers.cpp
+++ b/toolkit/components/places/AsyncFaviconHelpers.cpp
@@ -16,16 +16,17 @@
  * The Original Code is Places.
  *
  * The Initial Developer of the Original Code is the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Marco Bonardo <mak77@bonardo.net> (original author)
+ *   Richard Newman <rnewman@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -719,33 +720,50 @@ AsyncAssociateIconToPage::Run()
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mozStorageTransaction transaction(mDB->MainConn(), false,
                                     mozIStorageConnection::TRANSACTION_IMMEDIATE);
 
   // If there is no entry for this icon, or the entry is obsolete, replace it.
   if (mIcon.id == 0 || (mIcon.status & ICON_STATUS_CHANGED)) {
+    // The 'multi-coalesce' here ensures that replacing a favicon without
+    // specifying a :guid parameter doesn't cause it to be allocated a new
+    // GUID.
     nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
       "INSERT OR REPLACE INTO moz_favicons "
-        "(id, url, data, mime_type, expiration) "
+        "(id, url, data, mime_type, expiration, guid) "
       "VALUES ((SELECT id FROM moz_favicons WHERE url = :icon_url), "
-              ":icon_url, :data, :mime_type, :expiration) "
+              ":icon_url, :data, :mime_type, :expiration, "
+              "COALESCE(:guid, "
+                       "(SELECT guid FROM moz_favicons "
+                        "WHERE url = :icon_url), "
+                       "GENERATE_GUID()))"
     );
     NS_ENSURE_STATE(stmt);
     mozStorageStatementScoper scoper(stmt);
     rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), mIcon.spec);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindBlobByName(NS_LITERAL_CSTRING("data"),
                               TO_INTBUFFER(mIcon.data), mIcon.data.Length());
     NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("mime_type"), mIcon.mimeType);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("expiration"), mIcon.expiration);
     NS_ENSURE_SUCCESS(rv, rv);
+
+    // Binding a GUID allows us to override the current (or generated) GUID.
+    if (mIcon.guid.IsEmpty()) {
+      rv = stmt->BindNullByName(NS_LITERAL_CSTRING("guid"));
+    }
+    else {
+      rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("guid"), mIcon.guid);
+    }
+    NS_ENSURE_SUCCESS(rv, rv);
+
     rv = stmt->Execute();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Get the new icon id.  Do this regardless mIcon.id, since other code
     // could have added a entry before us.  Indeed we interrupted the thread
     // after the previous call to FetchIconInfo.
     rv = FetchIconInfo(mDB, mIcon);
     NS_ENSURE_SUCCESS(rv, rv);
--- a/toolkit/components/places/AsyncFaviconHelpers.h
+++ b/toolkit/components/places/AsyncFaviconHelpers.h
@@ -70,25 +70,27 @@ enum AsyncFaviconFetchMode {
 struct IconData
 {
   IconData()
   : id(0)
   , expiration(0)
   , fetchMode(FETCH_NEVER)
   , status(ICON_STATUS_UNKNOWN)
   {
+    guid.SetIsVoid(PR_TRUE);
   }
 
   PRInt64 id;
   nsCString spec;
   nsCString data;
   nsCString mimeType;
   PRTime expiration;
   enum AsyncFaviconFetchMode fetchMode;
   PRUint16 status; // This is a bitset, see ICON_STATUS_* defines above.
+  nsCString guid;
 };
 
 /**
  * Data cache for a page entry.
  */
 struct PageData
 {
   PageData()
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -28,16 +28,17 @@
  *   Asaf Romano <mano@mozilla.com>
  *   Marco Bonardo <mak77@bonardo.net>
  *   Edward Lee <edward.lee@engineering.uiuc.edu>
  *   Michael Ventnor <m.ventnor@gmail.com>
  *   Ehsan Akhgari <ehsan.akhgari@gmail.com>
  *   Drew Willcoxon <adw@mozilla.com>
  *   Philipp von Weitershausen <philipp@weitershausen.de>
  *   Paolo Amadini <http://www.amadzone.org/>
+ *   Richard Newman <rnewman@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -637,17 +638,23 @@ Database::InitSchema(bool* aDatabaseMigr
       // Firefox 4 uses schema version 11.
 
       // Firefox 8 uses schema version 12.
 
       if (currentSchemaVersion < 13) {
         rv = MigrateV13Up();
         NS_ENSURE_SUCCESS(rv, rv);
       }
-      // Firefox 11 uses schema version 13.
+
+      if (currentSchemaVersion < 14) {
+        rv = MigrateV14Up();
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+
+      // Firefox 11 uses schema version 14.
 
       // Schema Upgrades must add migration code here.
     }
   }
   else {
     // This is a new database, so we have to create all the tables and indices.
 
     // moz_places.
@@ -945,17 +952,17 @@ Database::MigrateV7Up()
   NS_ENSURE_SUCCESS(rv, rv);
   if (!URLUniqueIndexExists) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
   mozStorageTransaction transaction(mMainConn, false);
 
   // We need an index on lastModified to catch quickly last modified bookmark
-  // title for tag container's children. This will be useful for sync too.
+  // title for tag container's children. This will be useful for Sync, too.
   bool lastModIndexExists = false;
   rv = mMainConn->IndexExists(
     NS_LITERAL_CSTRING("moz_bookmarks_itemlastmodifiedindex"),
     &lastModIndexExists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!lastModIndexExists) {
     rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_PLACELASTMODIFIED);
@@ -1277,18 +1284,18 @@ Database::MigrateV11Up()
       "ALTER TABLE moz_bookmarks "
       "ADD COLUMN guid TEXT"
     ));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_BOOKMARKS_GUID);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    // moz_placess grew a guid column.  Add the column, but do not populate it
-    // with anything just yet.  We will do that soon.
+    // moz_places grew a guid column. Add the column, but do not populate it
+    // with anything just yet. We will do that soon.
     rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
       "ALTER TABLE moz_places "
       "ADD COLUMN guid TEXT"
     ));
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_GUID);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -1301,35 +1308,65 @@ Database::MigrateV11Up()
   return NS_OK;
 }
 
 nsresult
 Database::MigrateV13Up()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  // Dynamic containers are no more supported.
-
-  // For existing profiles, we may not have a moz_bookmarks.guid column
+  // Dynamic containers are no longer supported.
   nsCOMPtr<mozIStorageAsyncStatement> deleteDynContainersStmt;
   nsresult rv = mMainConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
       "DELETE FROM moz_bookmarks WHERE type = :item_type"),
     getter_AddRefs(deleteDynContainersStmt));
   rv = deleteDynContainersStmt->BindInt32ByName(
     NS_LITERAL_CSTRING("item_type"),
     nsINavBookmarksService::TYPE_DYNAMIC_CONTAINER
   );
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<mozIStoragePendingStatement> ps;
   rv = deleteDynContainersStmt->ExecuteAsync(nsnull, getter_AddRefs(ps));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
+nsresult
+Database::MigrateV14Up()
+{
+  // For existing profiles, we may not have a moz_favicons.guid column.
+  // Add it here. We want it to be unique, but ALTER TABLE doesn't allow
+  // a uniqueness constraint, so the index must be created separately.
+  nsCOMPtr<mozIStorageStatement> hasGuidStatement;
+  nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
+      "SELECT guid FROM moz_favicons"),
+    getter_AddRefs(hasGuidStatement));
+
+  if (NS_FAILED(rv)) {
+    rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+      "ALTER TABLE moz_favicons "
+      "ADD COLUMN guid TEXT"
+    ));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Generate GUIDs for our existing favicons.
+    rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+      "UPDATE moz_favicons "
+      "SET guid = GENERATE_GUID()"
+    ));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // And now we can make the column unique.
+    rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_FAVICONS_GUID);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  return NS_OK;
+}
+
 void
 Database::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mShuttingDown);
 
   mMainThreadStatements.FinalizeStatements();
   mMainThreadAsyncStatements.FinalizeStatements();
@@ -1407,16 +1444,20 @@ Database::Observe(nsISupports *aSubject,
       nsresult rv = mMainConn->CreateStatement(NS_LITERAL_CSTRING(
         "SELECT 1 "
         "FROM moz_places "
         "WHERE guid IS NULL "
         "UNION ALL "
         "SELECT 1 "
         "FROM moz_bookmarks "
         "WHERE guid IS NULL "
+        "UNION ALL "
+        "SELECT 1 "
+        "FROM moz_favicons "
+        "WHERE guid IS NULL "
       ), getter_AddRefs(stmt));
       NS_ENSURE_SUCCESS(rv, rv);
 
       bool haveNullGuids;
       rv = stmt->ExecuteStep(&haveNullGuids);
       NS_ENSURE_SUCCESS(rv, rv);
       NS_ASSERTION(!haveNullGuids,
                    "Someone added an entry without adding a GUID!");
--- a/toolkit/components/places/Database.h
+++ b/toolkit/components/places/Database.h
@@ -40,19 +40,19 @@
 
 #include "nsThreadUtils.h"
 #include "nsWeakReference.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIObserver.h"
 #include "mozilla/storage.h"
 #include "mozilla/storage/StatementCache.h"
 
-// This is the schema version, update it at any schema change and add a
+// This is the schema version. Update it at any schema change and add a
 // corresponding migrateVxx method below.
-#define DATABASE_SCHEMA_VERSION 13
+#define DATABASE_SCHEMA_VERSION 14
 
 // Fired after Places inited.
 #define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
 // Fired when initialization fails due to a locked database.
 #define TOPIC_DATABASE_LOCKED "places-database-locked"
 // This topic is received when the profile is about to be lost.  Places does
 // initial shutdown work and notifies TOPIC_PLACES_SHUTDOWN to all listeners.
 // Any shutdown work that requires the Places APIs should happen here.
@@ -283,18 +283,20 @@ protected:
   /**
    * Helpers used by schema upgrades.
    */
   nsresult MigrateV7Up();
   nsresult MigrateV8Up();
   nsresult MigrateV9Up();
   nsresult MigrateV10Up();
   nsresult MigrateV11Up();
+  nsresult MigrateV13Up();
+  nsresult MigrateV14Up();
+
   nsresult CheckAndUpdateGUIDs();
-  nsresult MigrateV13Up();
 
 private:
   ~Database();
 
   /**
    * Singleton getter, invoked by class instantiation.
    *
    * Note: does AddRef.
--- a/toolkit/components/places/nsFaviconService.cpp
+++ b/toolkit/components/places/nsFaviconService.cpp
@@ -233,22 +233,25 @@ nsFaviconService::SetFaviconUrlForPage(n
     }
   }
 
   mozStorageTransaction transaction(mDB->MainConn(), false);
 
   if (iconId == -1) {
     // We did not find any entry for this icon, so create a new one.
     nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
-      "INSERT INTO moz_favicons (id, url, data, mime_type, expiration) "
-      "VALUES (:icon_id, :icon_url, :data, :mime_type, :expiration)"
+      "INSERT INTO moz_favicons (id, url, data, mime_type, expiration, guid) "
+      "VALUES (:icon_id, :icon_url, :data, :mime_type, :expiration, "
+              "COALESCE(:guid, GENERATE_GUID()))"
     );
     NS_ENSURE_STATE(stmt);
     mozStorageStatementScoper scoper(stmt);
 
+    rv = stmt->BindNullByName(NS_LITERAL_CSTRING("guid"));
+    NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindNullByName(NS_LITERAL_CSTRING("icon_id"));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindNullByName(NS_LITERAL_CSTRING("data"));
     NS_ENSURE_SUCCESS(rv, rv);
     rv = stmt->BindNullByName(NS_LITERAL_CSTRING("mime_type"));
     NS_ENSURE_SUCCESS(rv, rv);
@@ -438,49 +441,56 @@ nsFaviconService::SetFaviconData(nsIURI*
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (hasResult) {
       // Get id of the old entry and update it.
       PRInt64 id;
       rv = stmt->GetInt64(0, &id);
       NS_ENSURE_SUCCESS(rv, rv);
       statement = mDB->GetStatement(
-        "UPDATE moz_favicons SET data = :data, mime_type = :mime_type, "
-                                "expiration = :expiration "
+        "UPDATE moz_favicons SET "
+               "guid       = COALESCE(:guid, guid), "
+               "data       = :data, "
+               "mime_type  = :mime_type, "
+               "expiration = :expiration "
         "WHERE id = :icon_id"
       );
       NS_ENSURE_STATE(statement);
 
+      rv = statement->BindNullByName(NS_LITERAL_CSTRING("guid"));
+      NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("icon_id"), id);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindBlobByName(NS_LITERAL_CSTRING("data"), data, dataLen);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindUTF8StringByName(NS_LITERAL_CSTRING("mime_type"), *mimeType);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("expiration"), aExpiration);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else {
       // Insert a new entry.
       statement = mDB->GetStatement(
-        "INSERT INTO moz_favicons (id, url, data, mime_type, expiration) "
-        "VALUES (:icon_id, :icon_url, :data, :mime_type, :expiration)"
-      );
+       "INSERT INTO moz_favicons (id, url, data, mime_type, expiration, guid) "
+       "VALUES (:icon_id, :icon_url, :data, :mime_type, :expiration, "
+               "COALESCE(:guid, GENERATE_GUID()))");
       NS_ENSURE_STATE(statement);
 
       rv = statement->BindNullByName(NS_LITERAL_CSTRING("icon_id"));
       NS_ENSURE_SUCCESS(rv, rv);
       rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("icon_url"), aFaviconURI);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindBlobByName(NS_LITERAL_CSTRING("data"), data, dataLen);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindUTF8StringByName(NS_LITERAL_CSTRING("mime_type"), *mimeType);
       NS_ENSURE_SUCCESS(rv, rv);
       rv = statement->BindInt64ByName(NS_LITERAL_CSTRING("expiration"), aExpiration);
       NS_ENSURE_SUCCESS(rv, rv);
+      rv = statement->BindNullByName(NS_LITERAL_CSTRING("guid"));
+      NS_ENSURE_SUCCESS(rv, rv);
     }
   }
   mozStorageStatementScoper statementScoper(statement);
 
   rv = statement->Execute();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -25,16 +25,17 @@
  *   Asaf Romano <mano@mozilla.com>
  *   Marco Bonardo <mak77@bonardo.net>
  *   Edward Lee <edward.lee@engineering.uiuc.edu>
  *   Michael Ventnor <m.ventnor@gmail.com>
  *   Ehsan Akhgari <ehsan.akhgari@gmail.com>
  *   Drew Willcoxon <adw@mozilla.com>
  *   Philipp von Weitershausen <philipp@weitershausen.de>
  *   Paolo Amadini <http://www.amadzone.org/>
+ *   Richard Newman <rnewman@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
--- a/toolkit/components/places/nsPlacesIndexes.h
+++ b/toolkit/components/places/nsPlacesIndexes.h
@@ -140,10 +140,18 @@
  * moz_items_annos
  */
 
 #define CREATE_IDX_MOZ_ITEMSANNOS_PLACEATTRIBUTE \
   CREATE_PLACES_IDX( \
     "itemattributeindex", "moz_items_annos", "item_id, anno_attribute_id", "UNIQUE" \
   )
 
+/**
+ * moz_favicons
+ */
+
+#define CREATE_IDX_MOZ_FAVICONS_GUID \
+  CREATE_PLACES_IDX( \
+    "guid_uniqueindex", "moz_favicons", "guid", "UNIQUE" \
+  )
 
 #endif // nsPlacesIndexes_h__
--- a/toolkit/components/places/nsPlacesTables.h
+++ b/toolkit/components/places/nsPlacesTables.h
@@ -17,16 +17,17 @@
  *
  * The Initial Developer of the Original Code is
  * Mozilla Corporation.
  * Portions created by the Initial Developer are Copyright (C) 2008
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Richard Newman <rnewman@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -122,16 +123,17 @@
 
 #define CREATE_MOZ_FAVICONS NS_LITERAL_CSTRING( \
   "CREATE TABLE moz_favicons (" \
     "  id INTEGER PRIMARY KEY" \
     ", url LONGVARCHAR UNIQUE" \
     ", data BLOB" \
     ", mime_type VARCHAR(32)" \
     ", expiration LONG" \
+    ", guid TEXT" \
   ")" \
 )
 
 #define CREATE_MOZ_BOOKMARKS NS_LITERAL_CSTRING( \
   "CREATE TABLE moz_bookmarks (" \
     "  id INTEGER PRIMARY KEY" \
     ", type INTEGER" \
     ", fk INTEGER DEFAULT NULL" /* place_id */ \
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -30,17 +30,17 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-const CURRENT_SCHEMA_VERSION = 13;
+const CURRENT_SCHEMA_VERSION = 14;
 
 const NS_APP_USER_PROFILE_50_DIR = "ProfD";
 const NS_APP_PROFILE_DIR_STARTUP = "ProfDS";
 const NS_APP_BOOKMARKS_50_FILE = "BMarks";
 
 // Shortcuts to transitions type.
 const TRANSITION_LINK = Ci.nsINavHistoryService.TRANSITION_LINK;
 const TRANSITION_TYPED = Ci.nsINavHistoryService.TRANSITION_TYPED;
--- a/toolkit/components/places/tests/migration/test_current_from_v10.js
+++ b/toolkit/components/places/tests/migration/test_current_from_v10.js
@@ -290,16 +290,17 @@ function test_final_state()
     do_check_true(stmt.executeStep());
     // WAL journal mode should be set on this database.
     do_check_eq(stmt.getString(0).toLowerCase(), "wal");
     stmt.finalize();
   }
 
   do_check_true(db.indexExists("moz_bookmarks_guid_uniqueindex"));
   do_check_true(db.indexExists("moz_places_guid_uniqueindex"));
+  do_check_true(db.indexExists("moz_favicons_guid_uniqueindex"));
 
   do_check_eq(db.schemaVersion, CURRENT_SCHEMA_VERSION);
 
   db.close();
   run_next_test();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/toolkit/components/places/tests/unit/test_favicons.js
+++ b/toolkit/components/places/tests/unit/test_favicons.js
@@ -83,16 +83,27 @@ function check_oversized_icon_data(iconN
 
   // Compare thet expected data to the actual data.
   do_check_eq("image/png", outMimeType);
   if (!skipContent) {
     do_check_true(compareArrays(expectedData, outData));
   }
 }
 
+function check_page_has_no_favicon(pageURI) {
+  try {
+    PlacesUtils.favicons.getFaviconForPage(pageURI);
+    do_throw("Page has a favicon!");
+  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) {
+    // Page should have no favicon.
+  } catch (ex) {
+    do_throw("Unexpected exception " + ex);
+  }
+}
+
 /*
  * Done with utilities! On to the tests.
  */
 function run_test() {
   run_next_test();
 }
 
 add_test(function test_storing_a_normal_16x16_icon() {
@@ -343,8 +354,150 @@ add_test(function test_getFaviconData_on
   do_check_eq(outMimeType.value, "image/png");
 
   // Read in the icon and compare it to what the API returned above.
   let istream = NetUtil.newChannel(PlacesUtils.favicons.defaultFavicon).open();
   let expectedData = readInputStreamData(istream);
   do_check_true(compareArrays(outData, expectedData));
   run_next_test();
 });
+
+/*
+ * Retrieve the GUID for a favicon URI. For now we'll do this through SQL.
+ * Provide a mozIStorageStatementCallback, such as a SingleGUIDCallback.
+ */
+function guidForFaviconURI(iconURIString, cb) {
+  let query = "SELECT guid FROM moz_favicons WHERE url = :url";
+  let stmt = cb.statement = DBConn().createAsyncStatement(query);
+  stmt.params.url = iconURIString;
+  stmt.executeAsync(cb);
+  stmt.finalize();
+}
+
+/*
+ * A mozIStorageStatementCallback for single GUID results.
+ * Pass in a callback function, which will be invoked on completion.
+ * Ensures that only a single GUID is returned.
+ */
+function SingleGUIDCallback(cb) {
+  this.called = 0;
+  this.cb     = cb;
+}
+SingleGUIDCallback.prototype = {
+  _guid: null,
+  handleCompletion: function handleCompletion(reason) {
+    do_log_info("Completed single GUID callback.");
+    do_check_eq(this.called, 1);
+    this.cb(this._guid);
+  },
+  handleError: function handleError(err) {
+    do_throw(err);
+  },
+  handleResult: function handleResult(resultSet) {
+    this.called++;
+    this._guid = resultSet.getNextRow().getResultByName("guid");
+    do_log_info("Retrieved GUID is " + this._guid);
+    do_check_true(!!this._guid);
+    do_check_valid_places_guid(this._guid);
+    do_check_eq(null, resultSet.getNextRow());  // No more rows.
+  }
+};
+
+function insertToolbarBookmark(uri, title) {
+  PlacesUtils.bookmarks.insertBookmark(
+    PlacesUtils.toolbarFolderId,
+    uri,
+    PlacesUtils.bookmarks.DEFAULT_INDEX,
+    title
+  );
+}
+
+add_test(function test_insert_synchronous_mints_guid() {
+  do_log_info("Test that synchronously inserting a favicon results in a " +
+              "record with a new GUID.");
+
+  let testURI     = "http://test.com/sync/";
+  let testIconURI = "http://test.com/favicon.ico";
+  let pageURI     = NetUtil.newURI(testURI);
+
+  // No icon to start with.
+  check_page_has_no_favicon(pageURI);
+
+  // Add a page with a bookmark.
+  insertToolbarBookmark(pageURI, "Test page");
+
+  // Set a favicon for the page.
+  PlacesUtils.favicons.setFaviconUrlForPage(
+    pageURI, NetUtil.newURI(testIconURI)
+  );
+
+  // Check that the URI has been set correctly.
+  do_check_eq(PlacesUtils.favicons.getFaviconForPage(pageURI).spec,
+              testIconURI);
+
+  guidForFaviconURI(testIconURI, new SingleGUIDCallback(run_next_test));
+});
+
+add_test(function test_insert_asynchronous_mints_guid() {
+  do_log_info("Test that asynchronously inserting a favicon results in a " +
+              "record with a new GUID.");
+
+  let testURI = "http://test.com/async/";
+  let iconURI = NetUtil.newURI(do_get_file("favicon-normal32.png"));
+  let pageURI = NetUtil.newURI(testURI);
+
+  // No icon to start with.
+  check_page_has_no_favicon(pageURI);
+
+  // Add a page with a bookmark.
+  insertToolbarBookmark(pageURI, "Other test page");
+
+  // Set a favicon for the page.
+  let faviconDataCallback = {
+    onFaviconDataAvailable: function (uri, len, data, mimeType) {
+      do_check_true(iconURI.equals(uri));
+
+      // Make sure there's a valid GUID.
+      guidForFaviconURI(iconURI.spec, new SingleGUIDCallback(run_next_test));
+    }
+  };
+
+  let forceReload = false;
+  do_log_info("Asynchronously setting page favicon.");
+  PlacesUtils.favicons.setAndFetchFaviconForPage(
+    pageURI, iconURI, forceReload, faviconDataCallback
+  );
+});
+
+add_test(function test_insert_asynchronous_update_preserves_guid() {
+  do_log_info("Test that asynchronously inserting an existing favicon leaves " +
+              "the GUID unchanged.");
+
+  let testURI = "http://test.com/async/";
+  let iconURI = NetUtil.newURI(do_get_file("favicon-normal32.png"));
+  let pageURI = NetUtil.newURI(testURI);
+
+  guidForFaviconURI(iconURI.spec, new SingleGUIDCallback(function (guid) {
+    // Set a favicon for the page... again.
+    let faviconDataCallback = {
+      onFaviconDataAvailable: function (uri, len, data, mimeType) {
+        do_check_true(iconURI.equals(uri));
+
+        // Make sure there's a valid GUID.
+        guidForFaviconURI(iconURI.spec, new SingleGUIDCallback(function (again) {
+          do_check_eq(guid, again);
+          run_next_test();
+        }));
+      }
+    };
+
+    let forceReload = true;
+    do_log_info("Asynchronously re-setting page favicon.");
+    PlacesUtils.favicons.setAndFetchFaviconForPage(
+      pageURI, iconURI, forceReload, faviconDataCallback
+    );
+  }));
+});
+
+/*
+ * TODO: need a test for async write that modifies a GUID for a favicon.
+ * This will come later, when there's an API that actually does that!
+ */
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -212,29 +212,37 @@ JSHistogram_Add(JSContext *cx, uintN arg
   }
 
   if (!JS_ValueToECMAInt32(cx, v, &value)) {
     return JS_FALSE;
   }
 
   if (TelemetryImpl::CanRecord()) {
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj) {
+      return JS_FALSE;
+    }
+
     Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj));
     if (h->histogram_type() == Histogram::BOOLEAN_HISTOGRAM)
       h->Add(!!value);
     else
       h->Add(value);
   }
   return JS_TRUE;
 }
 
 JSBool
 JSHistogram_Snapshot(JSContext *cx, uintN argc, jsval *vp)
 {
   JSObject *obj = JS_THIS_OBJECT(cx, vp);
+  if (!obj) {
+    return JS_FALSE;
+  }
+
   Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj));
   JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL);
   if (!snapshot)
     return JS_FALSE;
   JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot));
   return ReflectHistogramSnapshot(cx, snapshot, h);
 }
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -2811,16 +2811,19 @@ XRE_main(int argc, char* argv[], const n
 
     // pass some basic info from the app data
     if (appData.vendor)
       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Vendor"),
                                          nsDependentCString(appData.vendor));
     if (appData.name)
       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductName"),
                                          nsDependentCString(appData.name));
+    if (appData.ID)
+      CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("ProductID"),
+                                         nsDependentCString(appData.ID));
     if (appData.version)
       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("Version"),
                                          nsDependentCString(appData.version));
     if (appData.buildID)
       CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("BuildID"),
                                          nsDependentCString(appData.buildID));
 
     nsDependentCString releaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));
--- a/tools/profiler/sps/TableTicker.cpp
+++ b/tools/profiler/sps/TableTicker.cpp
@@ -287,32 +287,32 @@ void ProfileEntry::WriteTag(Profile *pro
     }
   }
 #endif
 }
 
 #define PROFILE_DEFAULT_ENTRY 100000
 void mozilla_sampler_init()
 {
-  const char *val = PR_GetEnv("MOZ_PROFILER_SPS");
-  if (!val || !*val) {
-    return;
-  }
-
   // TODO linux port: Use TLS with ifdefs
   // TODO window port: See bug 683229 comment 15
   // profiler uses getspecific because TLS is not supported on android.
   // getspecific was picked over nspr because it had less overhead required
   // to make the checkpoint function fast.
   if (pthread_key_create(&pkey_stack, NULL) ||
         pthread_key_create(&pkey_ticker, NULL)) {
     LOG("Failed to init.");
     return;
   }
 
+  const char *val = PR_GetEnv("MOZ_PROFILER_SPS");
+  if (!val || !*val) {
+    return;
+  }
+
   TableTicker *t = new TableTicker(PROFILE_DEFAULT_ENTRY, 10);
   pthread_setspecific(pkey_ticker, t);
   pthread_setspecific(pkey_stack, t->GetStack());
 
   t->Start();
 }
 
 void mozilla_sampler_deinit()
--- a/tools/profiler/sps/sps_sampler.h
+++ b/tools/profiler/sps/sps_sampler.h
@@ -38,17 +38,16 @@
 
 #include <pthread.h>
 #include "base/atomicops.h"
 #include "nscore.h"
 
 // TODO Merge into Sampler.h
 
 extern pthread_key_t pkey_stack;
-extern pthread_key_t pkey_ticker;
 
 #define SAMPLER_INIT() mozilla_sampler_init();
 #define SAMPLER_DEINIT() mozilla_sampler_deinit();
 #define SAMPLE_CHECKPOINT(name_space, info) mozilla::SamplerStackFrameRAII only_one_sampleraii_per_scope(FULLFUNCTION, name_space "::" info);
 #define SAMPLE_MARKER(info) mozilla_sampler_add_marker(info);
 
 // STORE_SEQUENCER: Because signals can interrupt our profile modification
 //                  we need to make stores are not re-ordered by the compiler
--- a/tools/trace-malloc/lib/nsTraceMalloc.c
+++ b/tools/trace-malloc/lib/nsTraceMalloc.c
@@ -952,17 +952,17 @@ backtrace(tm_thread *t, int skip, int *i
     stack_buffer_info *info = &t->backtrace_buf;
     void ** new_stack_buffer;
     size_t new_stack_buffer_size;
     nsresult rv;
 
     t->suppress_tracing++;
 
     if (!stacks_enabled) {
-#if defined(XP_MACOSX) && defined(__i386)
+#if defined(XP_MACOSX)
         /* Walk the stack, even if stacks_enabled is false. We do this to
            check if we must set immediate_abort. */
         info->entries = 0;
         rv = NS_StackWalk(stack_callback, skip, info);
         *immediate_abort = rv == NS_ERROR_UNEXPECTED;
         if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) {
             t->suppress_tracing--;
             return NULL;
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -433,17 +433,17 @@ void nsView::DoResetWidgetBounds(bool aM
                                  bool aInvalidateChangedSize) {
   // The geometry of a root view's widget is controlled externally,
   // NOT by sizing or positioning the view
   if (mViewManager->GetRootViewImpl() == this) {
     return;
   }
   
   nsIntRect curBounds;
-  mWindow->GetBounds(curBounds);
+  mWindow->GetClientBounds(curBounds);
 
   nsWindowType type;
   mWindow->GetWindowType(type);
 
   if (curBounds.IsEmpty() && mDimBounds.IsEmpty() && type == eWindowType_popup) {
     // Don't manipulate empty popup widgets. For example there's no point
     // moving hidden comboboxes around, or doing X server roundtrips
     // to compute their true screen position. This could mean that WidgetToScreen
@@ -457,24 +457,26 @@ void nsView::DoResetWidgetBounds(bool aM
   nsIntRect newBounds = CalcWidgetBounds(type);
 
   bool changedPos = curBounds.TopLeft() != newBounds.TopLeft();
   bool changedSize = curBounds.Size() != newBounds.Size();
 
   // Child views are never attached to top level widgets, this is safe.
   if (changedPos) {
     if (changedSize && !aMoveOnly) {
-      mWindow->Resize(newBounds.x, newBounds.y, newBounds.width, newBounds.height,
-                      aInvalidateChangedSize);
+      mWindow->ResizeClient(newBounds.x, newBounds.y,
+                            newBounds.width, newBounds.height,
+                            aInvalidateChangedSize);
     } else {
-      mWindow->Move(newBounds.x, newBounds.y);
+      mWindow->MoveClient(newBounds.x, newBounds.y);
     }
   } else {
     if (changedSize && !aMoveOnly) {
-      mWindow->Resize(newBounds.width, newBounds.height, aInvalidateChangedSize);
+      mWindow->ResizeClient(newBounds.width, newBounds.height,
+                            aInvalidateChangedSize);
     } // else do nothing!
   }
 }
 
 void nsView::SetDimensions(const nsRect& aRect, bool aPaint, bool aResizeWidget)
 {
   nsRect dims = aRect;
   dims.MoveBy(mPosX, mPosY);
--- a/widget/public/nsIWidget.h
+++ b/widget/public/nsIWidget.h
@@ -113,18 +113,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #endif
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #endif
 
 #define NS_IWIDGET_IID \
-  { 0x34460b01, 0x3dc2, 0x4b58, \
-    { 0x8e, 0xd3, 0x7e, 0x7c, 0x33, 0xb5, 0x78, 0x8b } }
+  { 0x41fc0f2c, 0x65c2, 0x418e, \
+    { 0x89, 0x91, 0x5f, 0x0c, 0xa7, 0x01, 0x05, 0x34 } }
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
 #define NS_STYLE_WINDOW_SHADOW_MENU             2
@@ -668,16 +668,31 @@ class nsIWidget : public nsISupports {
      *
      * @param aX the new x position expressed in the parent's coordinate system
      * @param aY the new y position expressed in the parent's coordinate system
      *
      **/
     NS_IMETHOD Move(PRInt32 aX, PRInt32 aY) = 0;
 
     /**
+     * Reposition this widget so that the client area has the given offset.
+     *
+     * @param aX       the new x offset of the client area expressed as an
+     *                 offset from the origin of the client area of the parent
+     *                 widget (for root widgets and popup widgets it is in
+     *                 screen coordinates)
+     * @param aY       the new y offset of the client area expressed as an
+     *                 offset from the origin of the client area of the parent
+     *                 widget (for root widgets and popup widgets it is in
+     *                 screen coordinates)
+     *
+     **/
+    NS_IMETHOD MoveClient(PRInt32 aX, PRInt32 aY) = 0;
+
+    /**
      * Resize this widget. 
      *
      * @param aWidth  the new width expressed in the parent's coordinate system
      * @param aHeight the new height expressed in the parent's coordinate system
      * @param aRepaint whether the widget should be repainted
      *
      */
     NS_IMETHOD Resize(PRInt32 aWidth,
@@ -696,20 +711,39 @@ class nsIWidget : public nsISupports {
      */
     NS_IMETHOD Resize(PRInt32 aX,
                       PRInt32 aY,
                       PRInt32 aWidth,
                       PRInt32 aHeight,
                       bool     aRepaint) = 0;
 
     /**
-     * Resize and reposition the inner client area of the widget.
+     * Resize the widget so that the inner client area has the given size.
+     *
+     * @param aWidth   the new width of the client area.
+     * @param aHeight  the new height of the client area.
+     * @param aRepaint whether the widget should be repainted
      *
-     * @param aX       the new x offset expressed in the parent's coordinate system
-     * @param aY       the new y offset expressed in the parent's coordinate system
+     */
+    NS_IMETHOD ResizeClient(PRInt32 aWidth,
+                            PRInt32 aHeight,
+                            bool  aRepaint) = 0;
+
+    /**
+     * Resize and reposition the widget so tht inner client area has the given
+     * offset and size.
+     *
+     * @param aX       the new x offset of the client area expressed as an
+     *                 offset from the origin of the client area of the parent
+     *                 widget (for root widgets and popup widgets it is in
+     *                 screen coordinates)
+     * @param aY       the new y offset of the client area expressed as an
+     *                 offset from the origin of the client area of the parent
+     *                 widget (for root widgets and popup widgets it is in
+     *                 screen coordinates)
      * @param aWidth   the new width of the client area.
      * @param aHeight  the new height of the client area.
      * @param aRepaint whether the widget should be repainted
      *
      */
     NS_IMETHOD ResizeClient(PRInt32 aX,
                             PRInt32 aY,
                             PRInt32 aWidth,
@@ -794,19 +828,20 @@ class nsIWidget : public nsISupports {
      * includes any title bar on the window.
      *
      * @param aRect   On return it holds the  x, y, width and height of
      *                this widget.
      */
     NS_IMETHOD GetScreenBounds(nsIntRect &aRect) = 0;
 
     /**
-     * Get this widget's client area dimensions, if the window has a 3D
-     * border appearance this returns the area inside the border. Origin
-     * is always zero.
+     * Get this widget's client area bounds, if the window has a 3D border
+     * appearance this returns the area inside the border. The position is the
+     * position of the client area relative to the client area of the parent
+     * widget (for root widgets and popup widgets it is in screen coordinates).
      *
      * @param aRect   On return it holds the  x. y, width and height of
      *                the client area of this widget.
      */
     NS_IMETHOD GetClientBounds(nsIntRect &aRect) = 0;
 
     /**
      * Get the non-client area dimensions of the window.
--- a/widget/src/gtk2/nsWindow.cpp
+++ b/widget/src/gtk2/nsWindow.cpp
@@ -1575,16 +1575,67 @@ nsWindow::GetScreenBounds(nsIntRect &aRe
     // with Resize.
     aRect.SizeTo(mBounds.Size());
     LOG(("GetScreenBounds %d,%d | %dx%d\n",
          aRect.x, aRect.y, aRect.width, aRect.height));
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsWindow::GetClientBounds(nsIntRect &aRect)
+{
+    // GetBounds returns a rect whose top left represents the top left of the
+    // outer bounds, but whose width/height represent the size of the inner
+    // bounds (which is messed up).
+    GetBounds(aRect);
+    aRect.MoveBy(GetClientOffset());
+
+    return NS_OK;
+}
+
+nsIntPoint
+nsWindow::GetClientOffset()
+{
+    if (!mIsTopLevel) {
+        return nsIntPoint(0, 0);
+    }
+
+    GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
+
+    GdkAtom type_returned;
+    int format_returned;
+    int length_returned;
+    long *frame_extents;
+
+    if (!mShell || !mShell->window ||
+        !gdk_property_get(mShell->window,
+                          gdk_atom_intern ("_NET_FRAME_EXTENTS", FALSE),
+                          cardinal_atom,
+                          0, // offset
+                          4*4, // length
+                          FALSE, // delete
+                          &type_returned,
+                          &format_returned,
+                          &length_returned,
+                          (guchar **) &frame_extents) ||
+        length_returned/sizeof(glong) != 4) {
+
+        return nsIntPoint(0, 0);
+    }
+
+    // data returned is in the order left, right, top, bottom
+    PRInt32 left = PRInt32(frame_extents[0]);
+    PRInt32 top = PRInt32(frame_extents[2]);
+
+    g_free(frame_extents);
+
+    return nsIntPoint(left, top);
+}
+
+NS_IMETHODIMP
 nsWindow::SetForegroundColor(const nscolor &aColor)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsWindow::SetBackgroundColor(const nscolor &aColor)
 {
@@ -2334,27 +2385,26 @@ nsWindow::OnConfigureEvent(GtkWidget *aW
     //   the client window.
     //
     //   Override-redirect windows are children of the root window so parent
     //   coordinates are root coordinates.
 
     LOG(("configure event [%p] %d %d %d %d\n", (void *)this,
          aEvent->x, aEvent->y, aEvent->width, aEvent->height));
 
-    // mBounds.x/y are set to the window manager frame top-left when Move() or
-    // Resize()d from within Gecko, so comparing with the client window
-    // top-left is weird.  However, mBounds.x/y are set to client window
-    // position below, so this check avoids unwanted rollup on spurious
-    // configure events from Cygwin/X (bug 672103).
-    if (mBounds.x == aEvent->x &&
-        mBounds.y == aEvent->y)
-        return FALSE;
+    nsIntRect screenBounds;
+    GetScreenBounds(screenBounds);
 
     if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) {
-        check_for_rollup(aEvent->window, 0, 0, false, true);
+        // This check avoids unwanted rollup on spurious configure events from
+        // Cygwin/X (bug 672103).
+        if (mBounds.x != screenBounds.x ||
+            mBounds.y != screenBounds.y) {
+            check_for_rollup(aEvent->window, 0, 0, false, true);
+        }
     }
 
     // This event indicates that the window position may have changed.
     // mBounds.Size() is updated in OnSizeAllocate().
 
     // (The gtk_window_get_window_type() function is only available from
     // version 2.20.)
     NS_ASSERTION(GTK_IS_WINDOW(aWidget),
@@ -2372,21 +2422,17 @@ nsWindow::OnConfigureEvent(GtkWidget *aW
         //
         // Skipping the NS_MOVE dispatch saves context menus from an infinite
         // loop when nsXULPopupManager::PopupMoved moves the window to the new
         // position and nsMenuPopupFrame::SetPopupPosition adds
         // offsetForContextMenu on each iteration.
         return FALSE;
     }
 
-    // This is wrong, but noautohide titlebar panels currently depend on it
-    // (bug 601545#c13).  mBounds.TopLeft() should refer to the
-    // window-manager frame top-left, but WidgetToScreenOffset() gives the
-    // client window origin.
-    mBounds.MoveTo(WidgetToScreenOffset());
+    mBounds.MoveTo(screenBounds.TopLeft());
 
     nsGUIEvent event(true, NS_MOVE, this);
 
     event.refPoint = mBounds.TopLeft();
 
     // XXX mozilla will invalidate the entire window after this move
     // complete.  wtf?
     nsEventStatus status;
--- a/widget/src/gtk2/nsWindow.h
+++ b/widget/src/gtk2/nsWindow.h
@@ -165,16 +165,18 @@ public:
     NS_IMETHOD         PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
                                    nsIWidget                  *aWidget,
                                    bool                        aActivate);
     NS_IMETHOD         SetZIndex(PRInt32 aZIndex);
     NS_IMETHOD         SetSizeMode(PRInt32 aMode);
     NS_IMETHOD         Enable(bool aState);
     NS_IMETHOD         SetFocus(bool aRaise = false);
     NS_IMETHOD         GetScreenBounds(nsIntRect &aRect);
+    NS_IMETHOD         GetClientBounds(nsIntRect &aRect);
+    virtual nsIntPoint GetClientOffset();
     NS_IMETHOD         SetForegroundColor(const nscolor &aColor);
     NS_IMETHOD         SetBackgroundColor(const nscolor &aColor);
     NS_IMETHOD         SetCursor(nsCursor aCursor);
     NS_IMETHOD         SetCursor(imgIContainer* aCursor,
                                  PRUint32 aHotspotX, PRUint32 aHotspotY);
     NS_IMETHOD         Invalidate(const nsIntRect &aRect,
                                   bool             aIsSynchronous);
     NS_IMETHOD         Update();
--- a/widget/src/os2/nsWindow.cpp
+++ b/widget/src/os2/nsWindow.cpp
@@ -764,20 +764,17 @@ NS_METHOD nsWindow::GetBounds(nsIntRect&
 }
 
 //-----------------------------------------------------------------------------
 // Since mBounds contains the dimensions of the client, os2FrameWindow
 // doesn't have to provide any special handling for this method.
 
 NS_METHOD nsWindow::GetClientBounds(nsIntRect& aRect)
 {
-  aRect.x = 0;
-  aRect.y = 0;
-  aRect.width = mBounds.width;
-  aRect.height = mBounds.height;
+  aRect = mBounds;
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
 nsIntPoint nsWindow::WidgetToScreenOffset()
 {
   POINTL point = { 0, 0 };
--- a/widget/src/windows/nsTextStore.cpp
+++ b/widget/src/windows/nsTextStore.cpp
@@ -1180,16 +1180,18 @@ nsTextStore::GetScreenExt(TsViewCookie v
   // Result rect is in top level widget coordinates
   refWindow = refWindow->GetTopLevelWindow(false);
   NS_ENSURE_TRUE(refWindow, E_FAIL);
 
   nsIntRect boundRect;
   nsresult rv = refWindow->GetClientBounds(boundRect);
   NS_ENSURE_SUCCESS(rv, E_FAIL);
 
+  boundRect.MoveTo(0, 0);
+
   // Clip frame rect to window rect
   boundRect.IntersectRect(event.mReply.mRect, boundRect);
   if (!boundRect.IsEmpty()) {
     boundRect.MoveBy(refWindow->WidgetToScreenOffset());
     ::SetRect(prc, boundRect.x, boundRect.y,
               boundRect.XMost(), boundRect.YMost());
   } else {
     ::SetRectEmpty(prc);
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -1518,40 +1518,16 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, P
   }
 
   if (aRepaint)
     Invalidate(false);
 
   return NS_OK;
 }
 
-// Resize the client area and position the widget within it's parent
-NS_METHOD nsWindow::ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint)
-{
-  NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
-  NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
-
-  // Adjust our existing window bounds, based on the new client dims.
-  RECT client;
-  GetClientRect(mWnd, &client);
-  nsIntPoint dims(client.right - client.left, client.bottom - client.top);
-  aWidth = mBounds.width + (aWidth - dims.x);
-  aHeight = mBounds.height + (aHeight - dims.y);
-  
-  if (aX || aY) {
-    // offsets
-    nsIntRect bounds;
-    GetScreenBounds(bounds);
-    aX += bounds.x;
-    aY += bounds.y;
-    return Resize(aX, aY, aWidth, aHeight, aRepaint);
-  }
-  return Resize(aWidth, aHeight, aRepaint);
-}
-
 NS_IMETHODIMP
 nsWindow::BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical)
 {
   NS_ENSURE_ARG_POINTER(aEvent);
 
   if (aEvent->eventStructType != NS_MOUSE_EVENT) {
     // you can only begin a resize drag with a mouse event
     return NS_ERROR_INVALID_ARG;
@@ -1925,19 +1901,19 @@ NS_METHOD nsWindow::GetBounds(nsIntRect 
 
 // Get this component dimension
 NS_METHOD nsWindow::GetClientBounds(nsIntRect &aRect)
 {
   if (mWnd) {
     RECT r;
     VERIFY(::GetClientRect(mWnd, &r));
 
-    // assign size
-    aRect.x = 0;
-    aRect.y = 0;
+    nsIntRect bounds;
+    GetBounds(bounds);
+    aRect.MoveTo(bounds.TopLeft() + GetClientOffset());
     aRect.width  = r.right - r.left;
     aRect.height = r.bottom - r.top;
 
   } else {
     aRect.SetRect(0,0,0,0);
   }
   return NS_OK;
 }
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -120,17 +120,16 @@ public:
   virtual nsIWidget*      GetParent(void);
   virtual float           GetDPI();
   NS_IMETHOD              Show(bool bState);
   NS_IMETHOD              IsVisible(bool & aState);
   NS_IMETHOD              ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY);
   NS_IMETHOD              Move(PRInt32 aX, PRInt32 aY);
   NS_IMETHOD              Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
   NS_IMETHOD              Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
-  NS_IMETHOD              ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
   NS_IMETHOD              BeginResizeDrag(nsGUIEvent* aEvent, PRInt32 aHorizontal, PRInt32 aVertical);
   NS_IMETHOD              PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget *aWidget, bool aActivate);
   NS_IMETHOD              SetSizeMode(PRInt32 aMode);
   NS_IMETHOD              Enable(bool aState);
   NS_IMETHOD              IsEnabled(bool *aState);
   NS_IMETHOD              SetFocus(bool aRaise);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
--- a/widget/src/xpwidgets/nsBaseWidget.cpp
+++ b/widget/src/xpwidgets/nsBaseWidget.cpp
@@ -295,25 +295,16 @@ ViewWrapper* nsBaseWidget::GetAttachedVi
  }
  
 NS_IMETHODIMP nsBaseWidget::SetAttachedViewPtr(ViewWrapper* aViewWrapper)
  {
    mViewWrapperPtr = aViewWrapper;
    return NS_OK;
  }
 
-NS_METHOD nsBaseWidget::ResizeClient(PRInt32 aX,
-                                     PRInt32 aY,
-                                     PRInt32 aWidth,
-                                     PRInt32 aHeight,
-                                     bool aRepaint)
-{
-  return Resize(aX, aY, aWidth, aHeight, aRepaint);
-}
-
 //-------------------------------------------------------------------------
 //
 // Close this nsBaseWidget
 //
 //-------------------------------------------------------------------------
 NS_METHOD nsBaseWidget::Destroy()
 {
   // Just in case our parent is the only ref to us
@@ -914,16 +905,60 @@ void nsBaseWidget::OnDestroy()
   NS_IF_RELEASE(mContext);
 }
 
 NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
+NS_METHOD nsBaseWidget::MoveClient(PRInt32 aX, PRInt32 aY)
+{
+  nsIntPoint clientOffset(GetClientOffset());
+  aX -= clientOffset.x;
+  aY -= clientOffset.y;
+  return Move(aX, aY);
+}
+
+NS_METHOD nsBaseWidget::ResizeClient(PRInt32 aWidth,
+                                     PRInt32 aHeight,
+                                     bool aRepaint)
+{
+  NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
+  NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
+
+  nsIntRect clientBounds;
+  GetClientBounds(clientBounds);
+  aWidth = mBounds.width + (aWidth - clientBounds.width);
+  aHeight = mBounds.height + (aHeight - clientBounds.height);
+
+  return Resize(aWidth, aHeight, aRepaint);
+}
+
+NS_METHOD nsBaseWidget::ResizeClient(PRInt32 aX,
+                                     PRInt32 aY,
+                                     PRInt32 aWidth,
+                                     PRInt32 aHeight,
+                                     bool aRepaint)
+{
+  NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
+  NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
+
+  nsIntRect clientBounds;
+  GetClientBounds(clientBounds);
+  aWidth = mBounds.width + (aWidth - clientBounds.width);
+  aHeight = mBounds.height + (aHeight - clientBounds.height);
+
+  nsIntPoint clientOffset(GetClientOffset());
+  aX -= clientOffset.x;
+  aY -= clientOffset.y;
+
+  return Resize(aX, aY, aWidth, aHeight, aRepaint);
+}
+
 //-------------------------------------------------------------------------
 //
 // Bounds
 //
 //-------------------------------------------------------------------------
 
 /**
 * If the implementation of nsWindow supports borders this method MUST be overridden
--- a/widget/src/xpwidgets/nsBaseWidget.h
+++ b/widget/src/xpwidgets/nsBaseWidget.h
@@ -117,20 +117,25 @@ public:
                                           LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nsnull);
 
   virtual void            DrawOver(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(bool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
+  NS_IMETHOD              MoveClient(PRInt32 aX, PRInt32 aY);
+  NS_IMETHOD              ResizeClient(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
+  NS_IMETHOD              ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
   NS_IMETHOD              SetBounds(const nsIntRect &aRect);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetClientBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
+  NS_IMETHOD              GetNonClientMargins(nsIntMargin &margins);
+  NS_IMETHOD              SetNonClientMargins(nsIntMargin &margins);
   virtual nsIntPoint      GetClientOffset();
   NS_IMETHOD              EnableDragDrop(bool aEnable);
   NS_IMETHOD              GetAttention(PRInt32 aCycleCount);
   virtual bool            HasPendingInputEvent();
   NS_IMETHOD              SetIcon(const nsAString &anIconSpec);
   NS_IMETHOD              BeginSecureKeyboardInput();
   NS_IMETHOD              EndSecureKeyboardInput();
   NS_IMETHOD              SetWindowTitlebarColor(nscolor aColor, bool aActive);
@@ -158,19 +163,16 @@ public:
               EVENT_CALLBACK   aHandleEventFunction,
               nsDeviceContext *aContext,
               nsWidgetInitData *aInitData = nsnull,
               bool             aForceUseIWidgetParent = false);
   NS_IMETHOD              SetEventCallback(EVENT_CALLBACK aEventFunction, nsDeviceContext *aContext);
   NS_IMETHOD              AttachViewToTopLevel(EVENT_CALLBACK aViewEventFunction, nsDeviceContext *aContext);
   virtual ViewWrapper*    GetAttachedViewPtr();
   NS_IMETHOD              SetAttachedViewPtr(ViewWrapper* aViewWrapper);
-  NS_IMETHOD              ResizeClient(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint);
-  NS_IMETHOD              GetNonClientMargins(nsIntMargin &margins);
-  NS_IMETHOD              SetNonClientMargins(nsIntMargin &margins);
   NS_IMETHOD              RegisterTouchWindow();
   NS_IMETHOD              UnregisterTouchWindow();
 
   nsPopupLevel PopupLevel() { return mPopupLevel; }
 
   virtual nsIntSize       ClientToWindowSize(const nsIntSize& aClientSize)
   {
     return aClientSize;
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -36,19 +36,157 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* API for getting a stack trace of the C/C++ stack on the current thread */
 
 #include "mozilla/Util.h"
+#include "nsDebug.h"
+#include "nsStackWalkPrivate.h"
 
 #include "nsStackWalk.h"
 
+// The presence of this address is the stack must stop the stack walk. If
+// there is no such address, the structure will be {NULL, true}.
+struct CriticalAddress {
+  void* mAddr;
+  bool mInit;
+};
+static CriticalAddress gCriticalAddress;
+
+#if defined(HAVE_DLOPEN) || defined(XP_MACOSX)
+#include <dlfcn.h>
+#endif
+
+#ifdef XP_MACOSX
+#include <pthread.h>
+#include <errno.h>
+#include <CoreServices/CoreServices.h>
+
+typedef void
+malloc_logger_t(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
+                uintptr_t result, uint32_t num_hot_frames_to_skip);
+extern malloc_logger_t *malloc_logger;
+
+static void
+stack_callback(void *pc, void *closure)
+{
+  const char *name = reinterpret_cast<char *>(closure);
+  Dl_info info;
+
+  // On Leopard dladdr returns the wrong value for "new_sem_from_pool". The
+  // stack shows up as having two pthread_cond_wait$UNIX2003 frames. The
+  // correct one is the first that we find on our way up, so the
+  // following check for gCriticalAddress.mAddr is critical.
+  if(gCriticalAddress.mAddr || dladdr(pc, &info) == 0  ||
+     info.dli_sname == NULL || strcmp(info.dli_sname, name) != 0)
+    return;
+  gCriticalAddress.mAddr = pc;
+}
+
+#define MAC_OS_X_VERSION_10_7_HEX 0x00001070
+#define MAC_OS_X_VERSION_10_6_HEX 0x00001060
+
+static PRInt32 OSXVersion()
+{
+  static PRInt32 gOSXVersion = 0x0;
+  if (gOSXVersion == 0x0) {
+    OSErr err = ::Gestalt(gestaltSystemVersion, (SInt32*)&gOSXVersion);
+    MOZ_ASSERT(err == noErr);
+  }
+  return gOSXVersion;
+}
+
+static bool OnLionOrLater()
+{
+  return (OSXVersion() >= MAC_OS_X_VERSION_10_7_HEX);
+}
+
+static bool OnSnowLeopardOrLater()
+{
+  return (OSXVersion() >= MAC_OS_X_VERSION_10_6_HEX);
+}
+
+static void
+my_malloc_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3,
+                 uintptr_t result, uint32_t num_hot_frames_to_skip)
+{
+  static bool once = false;
+  if (once)
+    return;
+  once = true;
+
+  // On Leopard dladdr returns the wrong value for "new_sem_from_pool". The
+  // stack shows up as having two pthread_cond_wait$UNIX2003 frames.
+  const char *name = OnSnowLeopardOrLater() ? "new_sem_from_pool" :
+    "pthread_cond_wait$UNIX2003";
+  NS_StackWalk(stack_callback, 0, const_cast<char*>(name));
+}
+
+void
+StackWalkInitCriticalAddress()
+{
+  if(gCriticalAddress.mInit)
+    return;
+  gCriticalAddress.mInit = true;
+  // We must not do work when 'new_sem_from_pool' calls realloc, since
+  // it holds a non-reentrant spin-lock and we will quickly deadlock.
+  // new_sem_from_pool is not directly accessible using dlsym, so
+  // we force a situation where new_sem_from_pool is on the stack and
+  // use dladdr to check the addresses.
+
+  MOZ_ASSERT(malloc_logger == NULL);
+  malloc_logger = my_malloc_logger;
+
+  pthread_cond_t cond;
+  int r = pthread_cond_init(&cond, 0);
+  MOZ_ASSERT(r == 0);
+  pthread_mutex_t mutex;
+  r = pthread_mutex_init(&mutex,0);
+  MOZ_ASSERT(r == 0);
+  r = pthread_mutex_lock(&mutex);
+  MOZ_ASSERT(r == 0);
+  struct timespec abstime = {0, 1};
+  r = pthread_cond_timedwait_relative_np(&cond, &mutex, &abstime);
+  malloc_logger = NULL;
+
+  // On Lion, malloc is no longer called from pthread_cond_*wait*. This prevents
+  // us from finding the address, but that is fine, since with no call to malloc
+  // there is no critical address.
+  MOZ_ASSERT(OnLionOrLater() || gCriticalAddress.mAddr != NULL);
+  MOZ_ASSERT(r == ETIMEDOUT);
+  r = pthread_mutex_unlock(&mutex);
+  MOZ_ASSERT(r == 0);
+  r = pthread_mutex_destroy(&mutex);
+  MOZ_ASSERT(r == 0);
+  r = pthread_cond_destroy(&cond);
+  MOZ_ASSERT(r == 0);
+}
+
+static bool IsCriticalAddress(void* aPC)
+{
+  return gCriticalAddress.mAddr == aPC;
+}
+#else
+static bool IsCriticalAddress(void* aPC)
+{
+  return false;
+}
+// We still initialize gCriticalAddress.mInit so that this code behaves
+// the same on all platforms. Otherwise a failure to init would be visible
+// only on OS X.
+void
+StackWalkInitCriticalAddress()
+{
+  gCriticalAddress.mInit = true;
+}
+#endif
+
 #if defined(_WIN32) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64)) // WIN32 x86 stack walking code
 
 #include "nscore.h"
 #include <windows.h>
 #include <process.h>
 #include <stdio.h>
 #include "plstr.h"
 #include "mozilla/FunctionTimer.h"
@@ -650,16 +788,17 @@ WalkStackThread(void* aData)
  * Otherwise StackWalk will return FALSE when it hits a frame in a DLL
  * whose in memory address doesn't match its in-file address.
  */
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure)
 {
+    MOZ_ASSERT(gCriticalAddress.mInit);
     HANDLE myProcess, myThread;
     DWORD walkerReturn;
     struct WalkStackData data;
 
     if (!EnsureImageHlpInitialized())
         return false;
 
     // Have to duplicate handle to get a real handle.
@@ -1135,22 +1274,16 @@ NS_FormatCodeAddressDetails(void *aPC, c
 // On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
 // if __USE_GNU is defined.  I suppose its some kind of standards
 // adherence thing.
 //
 #if (__GLIBC_MINOR__ >= 1) && !defined(__USE_GNU)
 #define __USE_GNU
 #endif
 
-#if defined(HAVE_DLOPEN) || defined(XP_MACOSX)
-#include <dlfcn.h>
-#endif
-
-
-
 // This thing is exported by libstdc++
 // Yes, this is a gcc only hack
 #if defined(MOZ_DEMANGLE_SYMBOLS)
 #include <cxxabi.h>
 #include <stdlib.h> // for free()
 #endif // MOZ_DEMANGLE_SYMBOLS
 
 void DemangleSymbol(const char * aSymbol, 
@@ -1343,16 +1476,17 @@ cs_operate(int (*operate_func)(void *, v
 {
     cswalkstack(csgetframeptr(), operate_func, usrarg);
 }
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure)
 {
+    MOZ_ASSERT(gCriticalAddress.mInit);
     struct my_user_args args;
 
     if (!initialized)
         myinit();
 
     args.callback = aCallback;
     args.skipFrames = aSkipFrames; /* XXX Not handled! */
     args.closure = aClosure;
@@ -1417,68 +1551,22 @@ NS_FormatCodeAddressDetails(void *aPC, c
 #else
 #define HAVE___LIBC_STACK_END 0
 #endif
 
 #if HAVE___LIBC_STACK_END
 extern void *__libc_stack_end; // from ld-linux.so
 #endif
 
-#ifdef XP_MACOSX
-struct AddressRange {
-  void* mStart;
-  void* mEnd;
-};
-// Addresses in this range must stop the stack walk
-static AddressRange gCriticalRange;
-
-static void FindFunctionAddresses(const char* aName, AddressRange* aRange)
-{
-  aRange->mStart = dlsym(RTLD_DEFAULT, aName);
-  if (!aRange->mStart)
-    return;
-  aRange->mEnd = aRange->mStart;
-  while (true) {
-    Dl_info info;
-    if (!dladdr(aRange->mEnd, &info))
-      break;
-    if (strcmp(info.dli_sname, aName))
-      break;
-    aRange->mEnd = (char*)aRange->mEnd + 1;
-  }
-}
-
-static void InitCriticalRanges()
-{
-  if (gCriticalRange.mStart)
-    return;
-  // We must not do work when 'new_sem_from_pool' calls realloc, since
-  // it holds a non-reentrant spin-lock and we will quickly deadlock.
-  // new_sem_from_pool is not directly accessible using dladdr but its
-  // code is bundled with pthread_cond_wait$UNIX2003 (on
-  // Leopard anyway).
-  FindFunctionAddresses("pthread_cond_wait$UNIX2003", &gCriticalRange);
-}
-
-static bool InCriticalRange(void* aPC)
-{
-  return gCriticalRange.mStart &&
-    gCriticalRange.mStart <= aPC && aPC < gCriticalRange.mEnd;
-}
-#else
-static void InitCriticalRanges() {}
-static bool InCriticalRange(void* aPC) { return false; }
-#endif
-
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure)
 {
+  MOZ_ASSERT(gCriticalAddress.mInit);
   // Stack walking code courtesy Kipp's "leaky".
-  InitCriticalRanges();
 
   // Get the frame pointer
   void **bp;
 #if defined(__i386) 
   __asm__( "movl %%ebp, %0" : "=g"(bp));
 #else
   // It would be nice if this worked uniformly, but at least on i386 and
   // x86_64, it stopped working with gcc 4.1, because it points to the
@@ -1501,18 +1589,18 @@ NS_StackWalk(NS_WalkStackCallback aCallb
       break;
     }
 #if (defined(__ppc__) && defined(XP_MACOSX)) || defined(__powerpc64__)
     // ppc mac or powerpc64 linux
     void *pc = *(bp+2);
 #else // i386 or powerpc32 linux
     void *pc = *(bp+1);
 #endif
-    if (InCriticalRange(pc)) {
-      printf("Aborting stack trace, PC in critical range\n");
+    if (IsCriticalAddress(pc)) {
+      printf("Aborting stack trace, PC is critical\n");
       return NS_ERROR_UNEXPECTED;
     }
     if (--skip < 0) {
       (*aCallback)(pc, aClosure);
     }
     bp = next;
   }
   return NS_OK;
@@ -1528,34 +1616,39 @@ struct unwind_info {
     int skip;
     void *closure;
 };
 
 static _Unwind_Reason_Code
 unwind_callback (struct _Unwind_Context *context, void *closure)
 {
     unwind_info *info = static_cast<unwind_info *>(closure);
-    if (--info->skip < 0) {
-        void *pc = reinterpret_cast<void *>(_Unwind_GetIP(context));
+    void *pc = reinterpret_cast<void *>(_Unwind_GetIP(context));
+    if (IsCriticalAddress(pc)) {
+        printf("Aborting stack trace, PC is critical\n");
+        return _URC_NORMAL_STOP;
+    }
+    if (--info->skip < 0)
         (*info->callback)(pc, info->closure);
-    }
     return _URC_NO_REASON;
 }
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure)
 {
+    MOZ_ASSERT(gCriticalAddress.mInit);
     unwind_info info;
     info.callback = aCallback;
     info.skip = aSkipFrames + 1;
     info.closure = aClosure;
 
-    _Unwind_Backtrace(unwind_callback, &info);
-
+    _Unwind_Reason_Code t = _Unwind_Backtrace(unwind_callback, &info);
+    if (t != _URC_END_OF_STACK)
+        return NS_ERROR_UNEXPECTED;
     return NS_OK;
 }
 
 #endif
 
 EXPORT_XPCOM_API(nsresult)
 NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
 {
@@ -1615,16 +1708,17 @@ NS_FormatCodeAddressDetails(void *aPC, c
 #endif
 
 #else // unsupported platform.
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, PRUint32 aSkipFrames,
              void *aClosure)
 {
+    MOZ_ASSERT(gCriticalAddress.mInit);
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 EXPORT_XPCOM_API(nsresult)
 NS_DescribeCodeAddress(void *aPC, nsCodeAddressDetails *aDetails)
 {
     aDetails->library[0] = '\0';
     aDetails->loffset = 0;
new file mode 100644
--- /dev/null
+++ b/xpcom/base/nsStackWalkPrivate.h
@@ -0,0 +1,43 @@
+/* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is NS_WalkTheStack.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Mozilla Corporation (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Initialize the critical sections for this platform so that we can
+ * abort stack walks when needed.
+ */
+void
+StackWalkInitCriticalAddress(void);
--- a/xpcom/base/nsTraceRefcntImpl.cpp
+++ b/xpcom/base/nsTraceRefcntImpl.cpp
@@ -45,16 +45,17 @@
 #include "prprf.h"
 #include "prlog.h"
 #include "plstr.h"
 #include "prlink.h"
 #include <stdlib.h>
 #include "nsCOMPtr.h"
 #include "nsCRT.h"
 #include <math.h>
+#include "nsStackWalkPrivate.h"
 #include "nsStackWalk.h"
 #include "nsString.h"
 
 #include "nsXULAppAPI.h"
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
@@ -918,16 +919,18 @@ nsTraceRefcntImpl::DemangleSymbol(const 
 }
 
 
 //----------------------------------------------------------------------
 
 EXPORT_XPCOM_API(void)
 NS_LogInit()
 {
+  // FIXME: This is called multiple times, we should probably not allow that.
+  StackWalkInitCriticalAddress();
 #ifdef NS_IMPL_REFCNT_LOGGING
   if (++gInitCount)
     nsTraceRefcntImpl::SetActivityIsLegal(true);
 #endif
 
 #ifdef NS_TRACE_MALLOC
   // XXX we don't have to worry about shutting down trace-malloc; it
   // handles this itself, through an atexit() callback.